package keeper import ( "errors" "fmt" "net/url" "cosmossdk.io/collections" errorsmod "cosmossdk.io/errors" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" auctiontypes "git.vdb.to/cerc-io/laconic2d/x/auction" registrytypes "git.vdb.to/cerc-io/laconic2d/x/registry" "git.vdb.to/cerc-io/laconic2d/x/registry/helpers" ) // HasNameAuthority - checks if a name/authority exists. func (k Keeper) HasNameAuthority(ctx sdk.Context, name string) (bool, error) { has, err := k.Authorities.Has(ctx, name) if err != nil { return false, err } return has, nil } // GetNameAuthority - gets a name authority from the store. func (k Keeper) GetNameAuthority(ctx sdk.Context, name string) (registrytypes.NameAuthority, error) { authority, err := k.Authorities.Get(ctx, name) if err != nil { if errors.Is(err, collections.ErrNotFound) { return registrytypes.NameAuthority{}, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Name authority not found.") } return registrytypes.NameAuthority{}, err } return authority, nil } // HasNameRecord - checks if a name record exists. func (k Keeper) HasNameRecord(ctx sdk.Context, crn string) bool { panic("unimplemented") } // GetNameRecord - gets a name record from the store. func (k Keeper) GetNameRecord(ctx sdk.Context, crn string) *registrytypes.NameRecord { panic("unimplemented") } // ListNameRecords - get all name records. func (k Keeper) ListNameRecords(ctx sdk.Context) []registrytypes.NameEntry { panic("unimplemented") } // ProcessSetName creates a CRN -> Record ID mapping. func (k Keeper) ProcessSetName(ctx sdk.Context, msg registrytypes.MsgSetName) error { panic("unimplemented") } // SaveNameAuthority creates the NameAuthority record. func (k Keeper) SaveNameAuthority(ctx sdk.Context, name string, authority *registrytypes.NameAuthority) error { return k.Authorities.Set(ctx, name, *authority) // TODO // updateBlockChangeSetForNameAuthority(ctx, codec, store, name) } // ProcessReserveAuthority reserves a name authority. func (k Keeper) ReserveAuthority(ctx sdk.Context, msg registrytypes.MsgReserveAuthority) error { crn := fmt.Sprintf("crn://%s", msg.GetName()) parsedCrn, err := url.Parse(crn) if err != nil { return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Invalid name") } name := parsedCrn.Host if fmt.Sprintf("crn://%s", name) != crn { return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Invalid name") } // TODO // if strings.Contains(name, ".") { // return k.ProcessReserveSubAuthority(ctx, name, msg) // } err = k.createAuthority(ctx, name, msg.GetSigner(), true) if err != nil { return err } return nil } func (k Keeper) createAuthority(ctx sdk.Context, name string, owner string, isRoot bool) error { moduleParams, err := k.GetParams(ctx) if err != nil { return err } has, err := k.HasNameAuthority(ctx, name) if err != nil { return err } if has { authority, err := k.GetNameAuthority(ctx, name) if err != nil { return err } if authority.Status != registrytypes.AuthorityExpired { return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Name already reserved.") } } ownerAddress, err := sdk.AccAddressFromBech32(owner) if err != nil { return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Invalid owner address.") } ownerAccount := k.accountKeeper.GetAccount(ctx, ownerAddress) if ownerAccount == nil { return errorsmod.Wrap(sdkerrors.ErrUnknownAddress, "Owner account not found.") } authority := registrytypes.NameAuthority{ OwnerPublicKey: getAuthorityPubKey(ownerAccount.GetPubKey()), OwnerAddress: owner, Height: uint64(ctx.BlockHeight()), Status: registrytypes.AuthorityActive, AuctionId: "", BondId: "", ExpiryTime: ctx.BlockTime().Add(moduleParams.AuthorityGracePeriod), } if isRoot && moduleParams.AuthorityAuctionEnabled { // If auctions are enabled, clear out owner fields. They will be set after a winner is picked. authority.OwnerAddress = "" authority.OwnerPublicKey = "" // Reset bond ID if required. if authority.BondId != "" || len(authority.BondId) != 0 { // TODO // k.RemoveBondToAuthorityIndexEntry(ctx, authority.BondId, name) authority.BondId = "" } params := auctiontypes.Params{ CommitsDuration: moduleParams.AuthorityAuctionCommitsDuration, RevealsDuration: moduleParams.AuthorityAuctionRevealsDuration, CommitFee: moduleParams.AuthorityAuctionCommitFee, RevealFee: moduleParams.AuthorityAuctionRevealFee, MinimumBid: moduleParams.AuthorityAuctionMinimumBid, } // Create an auction. msg := auctiontypes.NewMsgCreateAuction(params, ownerAddress) auction, sdkErr := k.auctionKeeper.CreateAuction(ctx, msg) if sdkErr != nil { return sdkErr } // TODO // Create auction ID -> authority name index. // k.AddAuctionToAuthorityMapping(ctx, auction.Id, name) authority.Status = registrytypes.AuthorityUnderAuction authority.AuctionId = auction.Id authority.ExpiryTime = auction.RevealsEndTime.Add(moduleParams.AuthorityGracePeriod) } // Save name authority in store. if err = k.SaveNameAuthority(ctx, name, &authority); err != nil { return err } // TODO // k.InsertAuthorityExpiryQueue(ctx, name, authority.ExpiryTime) return nil } func (k Keeper) ProcessSetAuthorityBond(ctx sdk.Context, msg registrytypes.MsgSetAuthorityBond) error { panic("unimplemented") } // ProcessDeleteName removes a CRN -> Record ID mapping. func (k Keeper) ProcessDeleteName(ctx sdk.Context, msg registrytypes.MsgDeleteNameAuthority) error { panic("unimplemented") } func (k Keeper) GetAuthorityExpiryQueue(ctx sdk.Context) []*registrytypes.ExpiryQueueRecord { panic("unimplemented") } // ResolveCRN resolves a CRN to a record. func (k Keeper) ResolveCRN(ctx sdk.Context, crn string) *registrytypes.Record { panic("unimplemented") } func getAuthorityPubKey(pubKey cryptotypes.PubKey) string { if pubKey == nil { return "" } return helpers.BytesToBase64(pubKey.Bytes()) }