Setup hooks between laconic modules (#9)

- Implement auction and bond module hooks in registry module
- Code cleanup

Reviewed-on: deep-stack/laconic2d#9
Co-authored-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
Co-committed-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
This commit is contained in:
2024-02-28 04:34:58 +00:00
committed by ashwin
parent ba7a127d7f
commit c79b7bea7d
33 changed files with 495 additions and 2683 deletions
-6
View File
@@ -43,12 +43,6 @@ func (k *Keeper) InitGenesis(ctx sdk.Context, data *registry.GenesisState) error
if err := k.insertAuthorityExpiryQueue(ctx, authority.Name, authority.Entry.ExpiryTime); err != nil {
return err
}
// TODO
// Note: Bond genesis runs first, so bonds will already be present.
// if authority.Entry.BondId != "" {
// k.AddBondToAuthorityIndexEntry(ctx, authority.Entry.BondId, authority.Name)
// }
}
}
+28 -19
View File
@@ -11,6 +11,7 @@ import (
"cosmossdk.io/collections/indexes"
storetypes "cosmossdk.io/core/store"
errorsmod "cosmossdk.io/errors"
"cosmossdk.io/log"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/legacy"
sdk "github.com/cosmos/cosmos-sdk/types"
@@ -28,8 +29,6 @@ import (
"git.vdb.to/cerc-io/laconic2d/x/registry/helpers"
)
// TODO: Add required methods
type RecordsIndexes struct {
BondId *indexes.Multi[string, string, registrytypes.Record]
}
@@ -50,16 +49,24 @@ func newRecordIndexes(sb *collections.SchemaBuilder) RecordsIndexes {
}
}
// TODO
type AuthoritiesIndexes struct {
AuctionId *indexes.Multi[string, string, registrytypes.NameAuthority]
}
func (b AuthoritiesIndexes) IndexesList() []collections.Index[string, registrytypes.NameAuthority] {
return []collections.Index[string, registrytypes.NameAuthority]{}
func (a AuthoritiesIndexes) IndexesList() []collections.Index[string, registrytypes.NameAuthority] {
return []collections.Index[string, registrytypes.NameAuthority]{a.AuctionId}
}
func newAuthorityIndexes(sb *collections.SchemaBuilder) AuthoritiesIndexes {
return AuthoritiesIndexes{}
return AuthoritiesIndexes{
AuctionId: indexes.NewMulti(
sb, registrytypes.AuthoritiesByAuctionIdIndexPrefix, "authorities_by_auction_id",
collections.StringKey, collections.StringKey,
func(name string, v registrytypes.NameAuthority) (string, error) {
return v.AuctionId, nil
},
),
}
}
type NameRecordsIndexes struct {
@@ -87,9 +94,8 @@ type Keeper struct {
accountKeeper auth.AccountKeeper
bankKeeper bank.Keeper
recordKeeper RecordKeeper
bondKeeper bondkeeper.Keeper
auctionKeeper auctionkeeper.Keeper
bondKeeper *bondkeeper.Keeper
auctionKeeper *auctionkeeper.Keeper
// state management
Schema collections.Schema
@@ -107,16 +113,14 @@ func NewKeeper(
storeService storetypes.KVStoreService,
accountKeeper auth.AccountKeeper,
bankKeeper bank.Keeper,
recordKeeper RecordKeeper,
bondKeeper bondkeeper.Keeper,
auctionKeeper auctionkeeper.Keeper,
bondKeeper *bondkeeper.Keeper,
auctionKeeper *auctionkeeper.Keeper,
) Keeper {
sb := collections.NewSchemaBuilder(storeService)
k := Keeper{
cdc: cdc,
accountKeeper: accountKeeper,
bankKeeper: bankKeeper,
recordKeeper: recordKeeper,
bondKeeper: bondKeeper,
auctionKeeper: auctionKeeper,
Params: collections.NewItem(sb, registrytypes.ParamsPrefix, "params", codec.CollValue[registrytypes.Params](cdc)),
@@ -155,6 +159,15 @@ func NewKeeper(
return k
}
// Logger returns a module-specific logger.
func (k Keeper) Logger(ctx sdk.Context) log.Logger {
return logger(ctx)
}
func logger(ctx sdk.Context) log.Logger {
return ctx.Logger().With("module", registrytypes.ModuleName)
}
// HasRecord - checks if a record by the given id exists.
func (k Keeper) HasRecord(ctx sdk.Context, id string) (bool, error) {
has, err := k.Records.Has(ctx, id)
@@ -230,9 +243,6 @@ func (k Keeper) RecordsFromAttributes(ctx sdk.Context, attributes []*registrytyp
// PutRecord - saves a record to the store.
func (k Keeper) SaveRecord(ctx sdk.Context, record registrytypes.Record) error {
return k.Records.Set(ctx, record.Id, record)
// TODO
// k.updateBlockChangeSetForRecord(ctx, record.Id)
}
// ProcessSetRecord creates a record.
@@ -274,7 +284,7 @@ func (k Keeper) SetRecord(ctx sdk.Context, msg registrytypes.MsgSetRecord) (*reg
// Sort owners list.
sort.Strings(record.Owners)
sdkErr := k.processRecord(ctx, &record, false)
sdkErr := k.processRecord(ctx, &record)
if sdkErr != nil {
return nil, sdkErr
}
@@ -282,7 +292,7 @@ func (k Keeper) SetRecord(ctx sdk.Context, msg registrytypes.MsgSetRecord) (*reg
return &record, nil
}
func (k Keeper) processRecord(ctx sdk.Context, record *registrytypes.ReadableRecord, isRenewal bool) error {
func (k Keeper) processRecord(ctx sdk.Context, record *registrytypes.ReadableRecord) error {
params, err := k.GetParams(ctx)
if err != nil {
return err
@@ -420,7 +430,6 @@ func (k Keeper) GetModuleBalances(ctx sdk.Context) []*registrytypes.AccountBalan
// ProcessRecordExpiryQueue tries to renew expiring records (by collecting rent) else marks them as deleted.
func (k Keeper) ProcessRecordExpiryQueue(ctx sdk.Context) error {
// TODO: process expired records
cids, err := k.getAllExpiredRecords(ctx, ctx.BlockHeader().Time)
if err != nil {
return err
+9 -37
View File
@@ -132,16 +132,7 @@ func (k Keeper) SaveNameRecord(ctx sdk.Context, crn string, id string) error {
Height: uint64(ctx.BlockHeight()),
}
// TODO: Check if index gets updated on entry updates
if err := k.NameRecords.Set(ctx, crn, nameRecord); err != nil {
return err
}
// TODO
// Update changeSet for name.
// k.updateBlockChangeSetForName(ctx, crn)
return nil
return k.NameRecords.Set(ctx, crn, nameRecord)
}
// SetName creates a CRN -> Record ID mapping.
@@ -169,9 +160,6 @@ func (k Keeper) SetName(ctx sdk.Context, msg registrytypes.MsgSetName) error {
// 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)
}
// ReserveAuthority reserves a name authority.
@@ -282,12 +270,9 @@ func (k Keeper) createAuthority(ctx sdk.Context, name string, owner string, isRo
// 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 = ""
}
authority.BondId = ""
params := auctiontypes.Params{
CommitsDuration: moduleParams.AuthorityAuctionCommitsDuration,
@@ -305,10 +290,6 @@ func (k Keeper) createAuthority(ctx sdk.Context, name string, owner string, isRo
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)
@@ -362,22 +343,12 @@ func (k Keeper) SetAuthorityBond(ctx sdk.Context, msg registrytypes.MsgSetAuthor
return nil
}
// TODO
// Remove old bond ID mapping, if any.
// if authority.BondId != "" {
// k.RemoveBondToAuthorityIndexEntry(ctx, authority.BondId, name)
// }
// Update bond id and save name authority in store.
authority.BondId = bond.Id
if err = k.SaveNameAuthority(ctx, name, &authority); err != nil {
return err
}
// TODO
// Add new bond ID mapping.
// k.AddBondToAuthorityIndexEntry(ctx, authority.BondId, name)
return nil
}
@@ -546,8 +517,7 @@ func (k Keeper) ProcessAuthorityExpiryQueue(ctx sdk.Context) error {
return err
}
// TODO: Setup logger
// k.Logger(ctx).Info(fmt.Sprintf("Marking authority expired as no bond present: %s", name))
k.Logger(ctx).Info(fmt.Sprintf("Marking authority expired as no bond present: %s", name))
return nil
}
@@ -620,7 +590,7 @@ func (k Keeper) deleteAuthorityExpiryQueue(ctx sdk.Context, name string, authori
// tryTakeAuthorityRent tries to take rent from the authority bond.
func (k Keeper) tryTakeAuthorityRent(ctx sdk.Context, name string, authority registrytypes.NameAuthority) error {
// k.Logger(ctx).Info(fmt.Sprintf("Trying to take rent for authority: %s", name))
k.Logger(ctx).Info(fmt.Sprintf("Trying to take rent for authority: %s", name))
params, err := k.GetParams(ctx)
if err != nil {
@@ -636,7 +606,8 @@ func (k Keeper) tryTakeAuthorityRent(ctx sdk.Context, name string, authority reg
return err
}
// k.Logger(ctx).Info(fmt.Sprintf("Insufficient funds in owner account to pay authority rent, marking as expired: %s", name))
k.Logger(ctx).Info(fmt.Sprintf("Insufficient funds in owner account to pay authority rent, marking as expired: %s", name))
return k.deleteAuthorityExpiryQueue(ctx, name, authority)
}
@@ -653,7 +624,8 @@ func (k Keeper) tryTakeAuthorityRent(ctx sdk.Context, name string, authority reg
// Save authority.
authority.Status = registrytypes.AuthorityActive
// k.Logger(ctx).Info(fmt.Sprintf("Authority rent paid successfully: %s", name))
k.Logger(ctx).Info(fmt.Sprintf("Authority rent paid successfully: %s", name))
return k.SaveNameAuthority(ctx, name, &authority)
}
+117 -4
View File
@@ -1,24 +1,137 @@
package keeper
import (
"errors"
"fmt"
"time"
"cosmossdk.io/collections"
errorsmod "cosmossdk.io/errors"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
auctiontypes "git.vdb.to/cerc-io/laconic2d/x/auction"
auctionkeeper "git.vdb.to/cerc-io/laconic2d/x/auction/keeper"
bondtypes "git.vdb.to/cerc-io/laconic2d/x/bond"
registrytypes "git.vdb.to/cerc-io/laconic2d/x/registry"
)
// TODO: Add methods
// Record keeper implements the bond usage keeper interface.
var (
_ auctiontypes.AuctionUsageKeeper = RecordKeeper{}
_ bondtypes.BondUsageKeeper = RecordKeeper{}
)
// RecordKeeper exposes the bare minimal read-only API for other modules.
type RecordKeeper struct {
cdc codec.BinaryCodec // The wire codec for binary encoding/decoding.
auctionKeeper auctionkeeper.Keeper
// storeKey storetypes.StoreKey // Unexposed key to access store from sdk.Context
k *Keeper
auctionKeeper *auctionkeeper.Keeper
}
// NewRecordKeeper creates new instances of the registry RecordKeeper
func NewRecordKeeper(cdc codec.BinaryCodec, k *Keeper, auctionKeeper *auctionkeeper.Keeper) RecordKeeper {
return RecordKeeper{
cdc: cdc,
k: k,
auctionKeeper: auctionKeeper,
}
}
// ModuleName returns the module name.
func (rk RecordKeeper) ModuleName() string {
return registrytypes.ModuleName
}
func (rk RecordKeeper) UsesAuction(ctx sdk.Context, auctionId string) bool {
iter, err := rk.k.Authorities.Indexes.AuctionId.MatchExact(ctx, auctionId)
if err != nil {
panic(err)
}
return iter.Valid()
}
func (rk RecordKeeper) OnAuctionWinnerSelected(ctx sdk.Context, auctionId string) {
// Update authority status based on auction status/winner.
iter, err := rk.k.Authorities.Indexes.AuctionId.MatchExact(ctx, auctionId)
if err != nil && !errors.Is(err, collections.ErrNotFound) {
panic(err)
}
names, err := iter.PrimaryKeys()
if err != nil {
panic(err)
}
if len(names) == 0 {
// We don't know about this auction, ignore.
logger(ctx).Info(fmt.Sprintf("Ignoring auction notification, name mapping not found: %s", auctionId))
return
}
// Take the first one as an auction (non-empty) will map to only one name
// MultiIndex being used as there can be multiple entries with empty auction id ("")
name := names[0]
if has, err := rk.k.HasNameAuthority(ctx, name); !has {
if err != nil {
panic(err)
}
// We don't know about this authority, ignore.
logger(ctx).Info(fmt.Sprintf("Ignoring auction notification, authority not found: %s", auctionId))
return
}
authority, err := rk.k.GetNameAuthority(ctx, name)
if err != nil {
panic(err)
}
auctionObj, err := rk.auctionKeeper.GetAuctionById(ctx, auctionId)
if err != nil {
panic(err)
}
if auctionObj.Status == auctiontypes.AuctionStatusCompleted {
if auctionObj.WinnerAddress != "" {
// Mark authority owner and change status to active.
authority.OwnerAddress = auctionObj.WinnerAddress
authority.Status = registrytypes.AuthorityActive
// Reset bond id if required, as owner has changed.
authority.BondId = ""
// Update height for updated/changed authority (owner).
// Can be used to check if names are older than the authority itself (stale names).
authority.Height = uint64(ctx.BlockHeight())
logger(ctx).Info(fmt.Sprintf("Winner selected, marking authority as active: %s", name))
} else {
// Mark as expired.
authority.Status = registrytypes.AuthorityExpired
logger(ctx).Info(fmt.Sprintf("No winner, marking authority as expired: %s", name))
}
// Forget about this auction now, we no longer need it.
authority.AuctionId = ""
if err = rk.k.SaveNameAuthority(ctx, name, &authority); err != nil {
panic(err)
}
} else {
logger(ctx).Info(fmt.Sprintf("Ignoring auction notification, status: %s", auctionObj.Status))
}
}
// UsesBond returns true if the bond has associated records.
func (rk RecordKeeper) UsesBond(ctx sdk.Context, bondId string) bool {
iter, err := rk.k.Records.Indexes.BondId.MatchExact(ctx, bondId)
if err != nil {
panic(err)
}
return iter.Valid()
}
// RenewRecord renews a record.
@@ -46,7 +159,7 @@ func (k Keeper) RenewRecord(ctx sdk.Context, msg registrytypes.MsgRenewRecord) e
}
readableRecord := record.ToReadableRecord()
return k.processRecord(ctx, &readableRecord, true)
return k.processRecord(ctx, &readableRecord)
}
// AssociateBond associates a record with a bond.