laconicd/x/registry/keeper/naming_keeper.go

208 lines
6.0 KiB
Go

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())
}