e90b21bc8e
1. add bond,auction, nameserivce module 2. update to v0.12.2 ethermint version 3. fix the test cases 4. add gql server
617 lines
19 KiB
Go
617 lines
19 KiB
Go
package keeper
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
|
auctiontypes "github.com/tharsis/ethermint/x/auction/types"
|
|
"github.com/tharsis/ethermint/x/nameservice/helpers"
|
|
"github.com/tharsis/ethermint/x/nameservice/types"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func getAuthorityPubKey(pubKey cryptotypes.PubKey) string {
|
|
if pubKey != nil {
|
|
return helpers.BytesToBase64(pubKey.Bytes())
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetNameAuthorityIndexKey Generates name -> NameAuthority index key.
|
|
func GetNameAuthorityIndexKey(name string) []byte {
|
|
return append(PrefixNameAuthorityRecordIndex, []byte(name)...)
|
|
}
|
|
|
|
// GetNameRecordIndexKey Generates WRN -> NameRecord index key.
|
|
func GetNameRecordIndexKey(wrn string) []byte {
|
|
return append(PrefixWRNToNameRecordIndex, []byte(wrn)...)
|
|
}
|
|
|
|
func GetCIDToNamesIndexKey(id string) []byte {
|
|
return append(PrefixCIDToNamesIndex, []byte(id)...)
|
|
}
|
|
|
|
func SetNameAuthority(ctx sdk.Context, store sdk.KVStore, codec codec.BinaryCodec, name string, authority *types.NameAuthority) {
|
|
store.Set(GetNameAuthorityIndexKey(name), codec.MustMarshal(authority))
|
|
updateBlockChangeSetForNameAuthority(ctx, codec, store, name)
|
|
}
|
|
|
|
// SetNameAuthority creates the NameAuthority record.
|
|
func (k Keeper) SetNameAuthority(ctx sdk.Context, name string, authority *types.NameAuthority) {
|
|
SetNameAuthority(ctx, ctx.KVStore(k.storeKey), k.cdc, name, authority)
|
|
}
|
|
|
|
func removeAuctionToAuthorityMapping(store sdk.KVStore, auctionID string) {
|
|
store.Delete(GetAuctionToAuthorityIndexKey(auctionID))
|
|
}
|
|
|
|
func (k Keeper) RemoveAuctionToAuthorityMapping(ctx sdk.Context, auctionID string) {
|
|
removeAuctionToAuthorityMapping(ctx.KVStore(k.storeKey), auctionID)
|
|
}
|
|
|
|
// GetNameAuthority - gets a name authority from the store.
|
|
func GetNameAuthority(store sdk.KVStore, codec codec.BinaryCodec, name string) types.NameAuthority {
|
|
authorityKey := GetNameAuthorityIndexKey(name)
|
|
if !store.Has(authorityKey) {
|
|
return types.NameAuthority{}
|
|
}
|
|
|
|
bz := store.Get(authorityKey)
|
|
var obj types.NameAuthority
|
|
codec.MustUnmarshal(bz, &obj)
|
|
|
|
return obj
|
|
}
|
|
|
|
// GetNameAuthority - gets a name authority from the store.
|
|
func (k Keeper) GetNameAuthority(ctx sdk.Context, name string) types.NameAuthority {
|
|
return GetNameAuthority(ctx.KVStore(k.storeKey), k.cdc, name)
|
|
}
|
|
|
|
// HasNameAuthority - checks if a name authority entry exists.
|
|
func HasNameAuthority(store sdk.KVStore, name string) bool {
|
|
return store.Has(GetNameAuthorityIndexKey(name))
|
|
}
|
|
|
|
// HasNameAuthority - checks if a name/authority exists.
|
|
func (k Keeper) HasNameAuthority(ctx sdk.Context, name string) bool {
|
|
return HasNameAuthority(ctx.KVStore(k.storeKey), name)
|
|
}
|
|
|
|
func getBondIDToAuthoritiesIndexKey(bondID string, name string) []byte {
|
|
return append(append(PrefixBondIDToAuthoritiesIndex, []byte(bondID)...), []byte(name)...)
|
|
}
|
|
|
|
// AddBondToAuthorityIndexEntry adds the Bond ID -> [Authority] index entry.
|
|
func (k Keeper) AddBondToAuthorityIndexEntry(ctx sdk.Context, bondID string, name string) {
|
|
store := ctx.KVStore(k.storeKey)
|
|
store.Set(getBondIDToAuthoritiesIndexKey(bondID, name), []byte{})
|
|
}
|
|
|
|
// RemoveBondToAuthorityIndexEntry removes the Bond ID -> [Authority] index entry.
|
|
func (k Keeper) RemoveBondToAuthorityIndexEntry(ctx sdk.Context, bondID string, name string) {
|
|
RemoveBondToAuthorityIndexEntry(ctx.KVStore(k.storeKey), bondID, name)
|
|
}
|
|
|
|
func RemoveBondToAuthorityIndexEntry(store sdk.KVStore, bondID string, name string) {
|
|
store.Delete(getBondIDToAuthoritiesIndexKey(bondID, name))
|
|
}
|
|
|
|
func (k Keeper) updateBlockChangeSetForName(ctx sdk.Context, wrn string) {
|
|
changeSet := k.getOrCreateBlockChangeSet(ctx, ctx.BlockHeight())
|
|
changeSet.Names = append(changeSet.Names, wrn)
|
|
k.saveBlockChangeSet(ctx, changeSet)
|
|
}
|
|
|
|
func (k Keeper) getAuthority(ctx sdk.Context, wrn string) (string, *url.URL, *types.NameAuthority, error) {
|
|
parsedWRN, err := url.Parse(wrn)
|
|
if err != nil {
|
|
return "", nil, nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid WRN.")
|
|
}
|
|
|
|
name := parsedWRN.Host
|
|
if !k.HasNameAuthority(ctx, name) {
|
|
return name, nil, nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Name authority not found.")
|
|
}
|
|
authority := k.GetNameAuthority(ctx, name)
|
|
return name, parsedWRN, &authority, nil
|
|
}
|
|
|
|
func (k Keeper) checkWRNAccess(ctx sdk.Context, signer sdk.AccAddress, wrn string) error {
|
|
name, parsedWRN, authority, err := k.getAuthority(ctx, wrn)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
formattedWRN := fmt.Sprintf("wrn://%s%s", name, parsedWRN.RequestURI())
|
|
if formattedWRN != wrn {
|
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid WRN.")
|
|
}
|
|
|
|
if authority.OwnerAddress != signer.String() {
|
|
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Access denied.")
|
|
}
|
|
|
|
if authority.Status != types.AuthorityActive {
|
|
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Authority is not active.")
|
|
}
|
|
|
|
if authority.BondId == "" || len(authority.BondId) == 0 {
|
|
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Authority bond not found.")
|
|
}
|
|
|
|
if authority.OwnerPublicKey == "" {
|
|
// Try to set owner public key if account has it available now.
|
|
ownerAccount := k.accountKeeper.GetAccount(ctx, signer)
|
|
pubKey := ownerAccount.GetPubKey()
|
|
if pubKey != nil {
|
|
// Update public key in authority record.
|
|
authority.OwnerPublicKey = getAuthorityPubKey(pubKey)
|
|
k.SetNameAuthority(ctx, name, authority)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// HasNameRecord - checks if a name record exists.
|
|
func (k Keeper) HasNameRecord(ctx sdk.Context, wrn string) bool {
|
|
store := ctx.KVStore(k.storeKey)
|
|
return store.Has(GetNameRecordIndexKey(wrn))
|
|
}
|
|
|
|
// GetNameRecord - gets a name record from the store.
|
|
func GetNameRecord(store sdk.KVStore, codec codec.BinaryCodec, wrn string) *types.NameRecord {
|
|
nameRecordKey := GetNameRecordIndexKey(wrn)
|
|
if !store.Has(nameRecordKey) {
|
|
return nil
|
|
}
|
|
|
|
bz := store.Get(nameRecordKey)
|
|
var obj types.NameRecord
|
|
codec.MustUnmarshal(bz, &obj)
|
|
|
|
return &obj
|
|
}
|
|
|
|
// GetNameRecord - gets a name record from the store.
|
|
func (k Keeper) GetNameRecord(ctx sdk.Context, wrn string) *types.NameRecord {
|
|
_, _, authority, err := k.getAuthority(ctx, wrn)
|
|
if err != nil || authority.Status != types.AuthorityActive {
|
|
// If authority is not active (or any other error), lookup fails.
|
|
return nil
|
|
}
|
|
|
|
nameRecord := GetNameRecord(ctx.KVStore(k.storeKey), k.cdc, wrn)
|
|
|
|
// Name record may not exist.
|
|
if nameRecord == nil {
|
|
return nil
|
|
}
|
|
|
|
// Name lookup should fail if the name record is stale.
|
|
// i.e. authority was registered later than the name.
|
|
if authority.Height > nameRecord.Latest.Height {
|
|
return nil
|
|
}
|
|
|
|
return nameRecord
|
|
}
|
|
|
|
// RemoveRecordToNameMapping removes a name from the record ID -> []names index.
|
|
func RemoveRecordToNameMapping(store sdk.KVStore, id string, wrn string) {
|
|
reverseNameIndexKey := GetCIDToNamesIndexKey(id)
|
|
|
|
names, _ := helpers.BytesArrToStringArr(store.Get(reverseNameIndexKey))
|
|
nameSet := helpers.SliceToSet(names)
|
|
nameSet.Remove(wrn)
|
|
|
|
if nameSet.Cardinality() == 0 {
|
|
// Delete as storing empty slice throws error from baseapp.
|
|
store.Delete(reverseNameIndexKey)
|
|
} else {
|
|
data, _ := helpers.StrArrToBytesArr(helpers.SetToSlice(nameSet))
|
|
store.Set(reverseNameIndexKey, data)
|
|
}
|
|
}
|
|
|
|
// AddRecordToNameMapping adds a name to the record ID -> []names index.
|
|
func AddRecordToNameMapping(store sdk.KVStore, id string, wrn string) {
|
|
reverseNameIndexKey := GetCIDToNamesIndexKey(id)
|
|
|
|
var names []string
|
|
if store.Has(reverseNameIndexKey) {
|
|
names, _ = helpers.BytesArrToStringArr(store.Get(reverseNameIndexKey))
|
|
}
|
|
|
|
nameSet := helpers.SliceToSet(names)
|
|
nameSet.Add(wrn)
|
|
bz, _ := helpers.StrArrToBytesArr(helpers.SetToSlice(nameSet))
|
|
store.Set(reverseNameIndexKey, bz)
|
|
}
|
|
|
|
// SetNameRecord - sets a name record.
|
|
func SetNameRecord(store sdk.KVStore, codec codec.BinaryCodec, wrn string, id string, height int64) {
|
|
nameRecordIndexKey := GetNameRecordIndexKey(wrn)
|
|
|
|
var nameRecord types.NameRecord
|
|
if store.Has(nameRecordIndexKey) {
|
|
bz := store.Get(nameRecordIndexKey)
|
|
codec.MustUnmarshal(bz, &nameRecord)
|
|
nameRecord.History = append(nameRecord.History, nameRecord.Latest)
|
|
|
|
// Update old CID -> []Name index.
|
|
if nameRecord.Latest.Id != "" || len(nameRecord.Latest.Id) != 0 {
|
|
RemoveRecordToNameMapping(store, nameRecord.Latest.Id, wrn)
|
|
}
|
|
}
|
|
|
|
nameRecord.Latest = &types.NameRecordEntry{
|
|
Id: id,
|
|
Height: uint64(height),
|
|
}
|
|
|
|
store.Set(nameRecordIndexKey, codec.MustMarshal(&nameRecord))
|
|
|
|
// Update new CID -> []Name index.
|
|
if id != "" {
|
|
AddRecordToNameMapping(store, id, wrn)
|
|
}
|
|
}
|
|
|
|
// SetNameRecord - sets a name record.
|
|
func (k Keeper) SetNameRecord(ctx sdk.Context, wrn string, id string) {
|
|
SetNameRecord(ctx.KVStore(k.storeKey), k.cdc, wrn, id, ctx.BlockHeight())
|
|
|
|
// Update changeSet for name.
|
|
k.updateBlockChangeSetForName(ctx, wrn)
|
|
}
|
|
|
|
// ProcessSetName creates a WRN -> Record ID mapping.
|
|
func (k Keeper) ProcessSetName(ctx sdk.Context, msg types.MsgSetName) error {
|
|
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = k.checkWRNAccess(ctx, signerAddress, msg.Wrn)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
nameRecord := k.GetNameRecord(ctx, msg.Wrn)
|
|
if nameRecord != nil && nameRecord.Latest.Id == msg.Cid {
|
|
return nil
|
|
}
|
|
|
|
k.SetNameRecord(ctx, msg.Wrn, msg.Cid)
|
|
|
|
return nil
|
|
}
|
|
|
|
// ListNameRecords - get all name records.
|
|
func (k Keeper) ListNameRecords(ctx sdk.Context) []types.NameEntry {
|
|
var nameEntries []types.NameEntry
|
|
store := ctx.KVStore(k.storeKey)
|
|
itr := sdk.KVStorePrefixIterator(store, PrefixWRNToNameRecordIndex)
|
|
defer itr.Close()
|
|
for ; itr.Valid(); itr.Next() {
|
|
bz := store.Get(itr.Key())
|
|
if bz != nil {
|
|
var record types.NameRecord
|
|
k.cdc.MustUnmarshal(bz, &record)
|
|
nameEntries = append(nameEntries, types.NameEntry{
|
|
Name: string(itr.Key()[len(PrefixWRNToNameRecordIndex):]),
|
|
Entry: &record,
|
|
})
|
|
}
|
|
}
|
|
|
|
return nameEntries
|
|
}
|
|
|
|
// ProcessReserveSubAuthority reserves a sub-authority.
|
|
func (k Keeper) ProcessReserveSubAuthority(ctx sdk.Context, name string, msg types.MsgReserveAuthority) error {
|
|
// Get parent authority name.
|
|
names := strings.Split(name, ".")
|
|
parent := strings.Join(names[1:], ".")
|
|
|
|
// Check if parent authority exists.
|
|
if !k.HasNameAuthority(ctx, parent) {
|
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Parent authority not found.")
|
|
}
|
|
parentAuthority := k.GetNameAuthority(ctx, parent)
|
|
|
|
// Sub-authority creator needs to be the owner of the parent authority.
|
|
if parentAuthority.OwnerAddress != msg.Signer {
|
|
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Access denied.")
|
|
}
|
|
|
|
// Sub-authority owner defaults to parent authority owner.
|
|
subAuthorityOwner := msg.Signer
|
|
if len(msg.Owner) != 0 {
|
|
// Override sub-authority owner if provided in message.
|
|
subAuthorityOwner = msg.Owner
|
|
}
|
|
|
|
sdkErr := k.createAuthority(ctx, name, subAuthorityOwner, false)
|
|
if sdkErr != nil {
|
|
return sdkErr
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func GetAuctionToAuthorityIndexKey(auctionID string) []byte {
|
|
return append(PrefixAuctionToAuthorityNameIndex, []byte(auctionID)...)
|
|
}
|
|
|
|
func (k Keeper) AddAuctionToAuthorityMapping(ctx sdk.Context, auctionID string, name string) {
|
|
store := ctx.KVStore(k.storeKey)
|
|
store.Set(GetAuctionToAuthorityIndexKey(auctionID), []byte(name))
|
|
}
|
|
|
|
func (k Keeper) createAuthority(ctx sdk.Context, name string, owner string, isRoot bool) error {
|
|
moduleParams := k.GetParams(ctx)
|
|
|
|
if k.HasNameAuthority(ctx, name) {
|
|
authority := k.GetNameAuthority(ctx, name)
|
|
if authority.Status != types.AuthorityExpired {
|
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Name already reserved.")
|
|
}
|
|
}
|
|
|
|
ownerAddress, err := sdk.AccAddressFromBech32(owner)
|
|
if err != nil {
|
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid owner address.")
|
|
}
|
|
ownerAccount := k.accountKeeper.GetAccount(ctx, ownerAddress)
|
|
if ownerAccount == nil {
|
|
return sdkerrors.Wrap(sdkerrors.ErrUnknownAddress, "Account not found.")
|
|
}
|
|
|
|
authority := types.NameAuthority{
|
|
OwnerPublicKey: getAuthorityPubKey(ownerAccount.GetPubKey()),
|
|
OwnerAddress: owner,
|
|
Height: uint64(ctx.BlockHeight()),
|
|
Status: types.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 {
|
|
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
|
|
}
|
|
|
|
// Create auction ID -> authority name index.
|
|
k.AddAuctionToAuthorityMapping(ctx, auction.Id, name)
|
|
|
|
authority.Status = types.AuthorityUnderAuction
|
|
authority.AuctionId = auction.Id
|
|
authority.ExpiryTime = auction.RevealsEndTime.Add(moduleParams.AuthorityGracePeriod)
|
|
}
|
|
|
|
k.SetNameAuthority(ctx, name, &authority)
|
|
k.InsertAuthorityExpiryQueue(ctx, name, authority.ExpiryTime)
|
|
|
|
return nil
|
|
}
|
|
|
|
// ProcessReserveAuthority reserves a name authority.
|
|
func (k Keeper) ProcessReserveAuthority(ctx sdk.Context, msg types.MsgReserveAuthority) error {
|
|
wrn := fmt.Sprintf("wrn://%s", msg.GetName())
|
|
parsedWrn, err := url.Parse(wrn)
|
|
if err != nil {
|
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid name")
|
|
}
|
|
name := parsedWrn.Host
|
|
if fmt.Sprintf("wrn://%s", name) != wrn {
|
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid name")
|
|
}
|
|
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) ProcessSetAuthorityBond(ctx sdk.Context, msg types.MsgSetAuthorityBond) error {
|
|
name := msg.GetName()
|
|
signer := msg.GetSigner()
|
|
if !k.HasNameAuthority(ctx, name) {
|
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Name authority not found.")
|
|
}
|
|
authority := k.GetNameAuthority(ctx, name)
|
|
if authority.OwnerAddress != signer {
|
|
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Access denied")
|
|
}
|
|
|
|
if !k.bondKeeper.HasBond(ctx, msg.BondId) {
|
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Bond not found.")
|
|
}
|
|
//
|
|
bond := k.bondKeeper.GetBond(ctx, msg.BondId)
|
|
if bond.Owner != signer {
|
|
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Bond owner mismatch.")
|
|
}
|
|
|
|
// No-op if bond hasn't changed.
|
|
if authority.BondId == msg.BondId {
|
|
return nil
|
|
}
|
|
|
|
// Remove old bond ID mapping, if any.
|
|
if authority.BondId != "" {
|
|
k.RemoveBondToAuthorityIndexEntry(ctx, authority.BondId, name)
|
|
}
|
|
|
|
// Update bond ID for authority.
|
|
authority.BondId = bond.Id
|
|
k.SetNameAuthority(ctx, name, &authority)
|
|
// Add new bond ID mapping.
|
|
k.AddBondToAuthorityIndexEntry(ctx, authority.BondId, name)
|
|
return nil
|
|
}
|
|
|
|
// ProcessDeleteName removes a WRN -> Record ID mapping.
|
|
func (k Keeper) ProcessDeleteName(ctx sdk.Context, msg types.MsgDeleteNameAuthority) error {
|
|
signerAddress, err := sdk.AccAddressFromBech32(msg.Signer)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = k.checkWRNAccess(ctx, signerAddress, msg.Wrn)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !k.HasNameRecord(ctx, msg.Wrn) {
|
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Name not found.")
|
|
}
|
|
|
|
// Set CID to empty string.
|
|
k.SetNameRecord(ctx, msg.Wrn, "")
|
|
|
|
return nil
|
|
}
|
|
|
|
func (k Keeper) GetAuthorityExpiryQueue(ctx sdk.Context) []*types.ExpiryQueueRecord {
|
|
var authorities []*types.ExpiryQueueRecord
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
|
itr := sdk.KVStorePrefixIterator(store, PrefixExpiryTimeToAuthoritiesIndex)
|
|
defer itr.Close()
|
|
for ; itr.Valid(); itr.Next() {
|
|
var record []string
|
|
record, err := helpers.BytesArrToStringArr(itr.Value())
|
|
if err != nil {
|
|
return authorities
|
|
}
|
|
authorities = append(authorities, &types.ExpiryQueueRecord{
|
|
Id: string(itr.Key()[len(PrefixExpiryTimeToAuthoritiesIndex):]),
|
|
Value: record,
|
|
})
|
|
}
|
|
|
|
return authorities
|
|
}
|
|
|
|
// ResolveWRN resolves a WRN to a record.
|
|
func (k Keeper) ResolveWRN(ctx sdk.Context, wrn string) *types.Record {
|
|
_, _, authority, err := k.getAuthority(ctx, wrn)
|
|
if err != nil || authority.Status != types.AuthorityActive {
|
|
// If authority is not active (or any other error), resolution fails.
|
|
return nil
|
|
}
|
|
|
|
// Name should not resolve if it's stale.
|
|
// i.e. authority was registered later than the name.
|
|
record, nameRecord := ResolveWRN(ctx.KVStore(k.storeKey), wrn, k, ctx)
|
|
if authority.Height > nameRecord.Latest.Height {
|
|
return nil
|
|
}
|
|
|
|
return record
|
|
}
|
|
|
|
// ResolveWRN resolves a WRN to a record.
|
|
func ResolveWRN(store sdk.KVStore, wrn string, k Keeper, c sdk.Context) (*types.Record, *types.NameRecord) {
|
|
nameKey := GetNameRecordIndexKey(wrn)
|
|
|
|
if store.Has(nameKey) {
|
|
bz := store.Get(nameKey)
|
|
var obj types.NameRecord
|
|
k.cdc.MustUnmarshal(bz, &obj)
|
|
|
|
recordExists := k.HasRecord(c, obj.Latest.Id)
|
|
if !recordExists || obj.Latest.Id == "" {
|
|
return nil, &obj
|
|
}
|
|
|
|
record := k.GetRecord(c, obj.Latest.Id)
|
|
return &record, &obj
|
|
}
|
|
|
|
return nil, nil
|
|
}
|
|
|
|
func getAuthorityExpiryQueueTimeKey(timestamp time.Time) []byte {
|
|
timeBytes := sdk.FormatTimeBytes(timestamp)
|
|
return append(PrefixExpiryTimeToAuthoritiesIndex, timeBytes...)
|
|
}
|
|
|
|
func (k Keeper) InsertAuthorityExpiryQueue(ctx sdk.Context, name string, expiryTime time.Time) {
|
|
timeSlice := k.GetAuthorityExpiryQueueTimeSlice(ctx, expiryTime)
|
|
timeSlice = append(timeSlice, name)
|
|
k.SetAuthorityExpiryQueueTimeSlice(ctx, expiryTime, timeSlice)
|
|
}
|
|
|
|
func (k Keeper) GetAuthorityExpiryQueueTimeSlice(ctx sdk.Context, timestamp time.Time) []string {
|
|
store := ctx.KVStore(k.storeKey)
|
|
|
|
bz := store.Get(getAuthorityExpiryQueueTimeKey(timestamp))
|
|
if bz == nil {
|
|
return []string{}
|
|
}
|
|
|
|
names, err := helpers.BytesArrToStringArr(bz)
|
|
if err != nil {
|
|
return []string{}
|
|
}
|
|
|
|
return names
|
|
}
|
|
|
|
func (k Keeper) SetAuthorityExpiryQueueTimeSlice(ctx sdk.Context, timestamp time.Time, names []string) {
|
|
store := ctx.KVStore(k.storeKey)
|
|
bz, _ := helpers.StrArrToBytesArr(names)
|
|
store.Set(getAuthorityExpiryQueueTimeKey(timestamp), bz)
|
|
}
|
|
|
|
// ListNameAuthorityRecords - get all name authority records.
|
|
func (k Keeper) ListNameAuthorityRecords(ctx sdk.Context) map[string]types.NameAuthority {
|
|
nameAuthorityRecords := make(map[string]types.NameAuthority)
|
|
store := ctx.KVStore(k.storeKey)
|
|
|
|
itr := sdk.KVStorePrefixIterator(store, PrefixNameAuthorityRecordIndex)
|
|
defer itr.Close()
|
|
for ; itr.Valid(); itr.Next() {
|
|
bz := store.Get(itr.Key())
|
|
if bz != nil {
|
|
var record types.NameAuthority
|
|
k.cdc.MustUnmarshal(bz, &record)
|
|
nameAuthorityRecords[string(itr.Key()[len(PrefixNameAuthorityRecordIndex):])] = record
|
|
}
|
|
}
|
|
|
|
return nameAuthorityRecords
|
|
}
|