Setup hooks between laconic modules #9

Merged
ashwin merged 8 commits from pm-hooks into main 2024-02-28 04:35:00 +00:00
11 changed files with 94 additions and 28 deletions
Showing only changes of commit ca635ebfe6 - Show all commits

View File

@ -77,7 +77,7 @@ type LaconicApp struct {
// laconic keepers // laconic keepers
AuctionKeeper *auctionkeeper.Keeper // (Use * as per ProvideModule implementation) AuctionKeeper *auctionkeeper.Keeper // (Use * as per ProvideModule implementation)
BondKeeper bondkeeper.Keeper BondKeeper *bondkeeper.Keeper
RegistryKeeper registrykeeper.Keeper RegistryKeeper registrykeeper.Keeper
// RegistryRecordKeeper registrykeeper.RecordKeeper // RegistryRecordKeeper registrykeeper.RecordKeeper

19
x/bond/expected_keeper.go Normal file
View File

@ -0,0 +1,19 @@
package bond
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// BondUsageKeeper keep track of bond usage in other modules.
// Used to, for example, prevent deletion of a bond that's in use.
type BondUsageKeeper interface {
ModuleName() string
UsesBond(ctx sdk.Context, bondId string) bool
}
// BondHooksWrapper is a wrapper for modules to inject BondUsageKeeper using depinject.
// Reference: https://github.com/cosmos/cosmos-sdk/tree/v0.50.3/core/appmodule#resolving-circular-dependencies
type BondHooksWrapper struct{ BondUsageKeeper }
// IsOnePerModuleType implements the depinject.OnePerModuleType interface.
func (BondHooksWrapper) IsOnePerModuleType() {}

View File

@ -49,7 +49,7 @@ type Keeper struct {
bankKeeper bank.Keeper bankKeeper bank.Keeper
// Track bond usage in other cosmos-sdk modules (more like a usage tracker). // Track bond usage in other cosmos-sdk modules (more like a usage tracker).
// usageKeepers []types.BondUsageKeeper usageKeepers []bondtypes.BondUsageKeeper
// State management // State management
Schema collections.Schema Schema collections.Schema
@ -63,8 +63,7 @@ func NewKeeper(
storeService store.KVStoreService, storeService store.KVStoreService,
accountKeeper auth.AccountKeeper, accountKeeper auth.AccountKeeper,
bankKeeper bank.Keeper, bankKeeper bank.Keeper,
// usageKeepers []types.BondUsageKeeper, ) *Keeper {
) Keeper {
sb := collections.NewSchemaBuilder(storeService) sb := collections.NewSchemaBuilder(storeService)
k := Keeper{ k := Keeper{
cdc: cdc, cdc: cdc,
@ -72,7 +71,7 @@ func NewKeeper(
bankKeeper: bankKeeper, bankKeeper: bankKeeper,
Params: collections.NewItem(sb, bondtypes.ParamsPrefix, "params", codec.CollValue[bondtypes.Params](cdc)), Params: collections.NewItem(sb, bondtypes.ParamsPrefix, "params", codec.CollValue[bondtypes.Params](cdc)),
Bonds: collections.NewIndexedMap(sb, bondtypes.BondsPrefix, "bonds", collections.StringKey, codec.CollValue[bondtypes.Bond](cdc), newBondIndexes(sb)), Bonds: collections.NewIndexedMap(sb, bondtypes.BondsPrefix, "bonds", collections.StringKey, codec.CollValue[bondtypes.Bond](cdc), newBondIndexes(sb)),
// usageKeepers: usageKeepers, usageKeepers: nil,
} }
schema, err := sb.Build() schema, err := sb.Build()
@ -82,7 +81,15 @@ func NewKeeper(
k.Schema = schema k.Schema = schema
return k return &k
}
func (k *Keeper) SetUsageKeepers(usageKeepers []bondtypes.BondUsageKeeper) {
if k.usageKeepers != nil {
panic("cannot set bond hooks twice")
}
k.usageKeepers = usageKeepers
} }
// BondId simplifies generation of bond Ids. // BondId simplifies generation of bond Ids.
@ -318,13 +325,12 @@ func (k Keeper) CancelBond(ctx sdk.Context, id string, ownerAddress sdk.AccAddre
return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "Bond owner mismatch.") return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "Bond owner mismatch.")
} }
// TODO
// Check if bond is used in other modules. // Check if bond is used in other modules.
// for _, usageKeeper := range k.usageKeepers { for _, usageKeeper := range k.usageKeepers {
// if usageKeeper.UsesBond(ctx, id) { if usageKeeper.UsesBond(ctx, id) {
// return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, fmt.Sprintf("Bond in use by the '%s' module.", usageKeeper.ModuleName())) return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, fmt.Sprintf("Bond in use by the '%s' module.", usageKeeper.ModuleName()))
// } }
// } }
// Move funds from the bond into the account. // Move funds from the bond into the account.
err = k.bankKeeper.SendCoinsFromModuleToAccount(ctx, bondtypes.ModuleName, ownerAddress, bond.Balance) err = k.bankKeeper.SendCoinsFromModuleToAccount(ctx, bondtypes.ModuleName, ownerAddress, bond.Balance)

View File

@ -11,11 +11,11 @@ import (
var _ bond.MsgServer = msgServer{} var _ bond.MsgServer = msgServer{}
type msgServer struct { type msgServer struct {
k Keeper k *Keeper
} }
// NewMsgServerImpl returns an implementation of the module MsgServer interface. // NewMsgServerImpl returns an implementation of the module MsgServer interface.
func NewMsgServerImpl(keeper Keeper) bond.MsgServer { func NewMsgServerImpl(keeper *Keeper) bond.MsgServer {
return &msgServer{k: keeper} return &msgServer{k: keeper}
} }

View File

@ -13,11 +13,11 @@ import (
var _ bondtypes.QueryServer = queryServer{} var _ bondtypes.QueryServer = queryServer{}
type queryServer struct { type queryServer struct {
k Keeper k *Keeper
} }
// NewQueryServerImpl returns an implementation of the module QueryServer. // NewQueryServerImpl returns an implementation of the module QueryServer.
func NewQueryServerImpl(k Keeper) bondtypes.QueryServer { func NewQueryServerImpl(k *Keeper) bondtypes.QueryServer {
return queryServer{k} return queryServer{k}
} }

View File

@ -4,12 +4,14 @@ import (
"cosmossdk.io/core/appmodule" "cosmossdk.io/core/appmodule"
"cosmossdk.io/core/store" "cosmossdk.io/core/store"
"cosmossdk.io/depinject" "cosmossdk.io/depinject"
"golang.org/x/exp/maps"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
auth "github.com/cosmos/cosmos-sdk/x/auth/keeper" auth "github.com/cosmos/cosmos-sdk/x/auth/keeper"
bank "github.com/cosmos/cosmos-sdk/x/bank/keeper" bank "github.com/cosmos/cosmos-sdk/x/bank/keeper"
modulev1 "git.vdb.to/cerc-io/laconic2d/api/cerc/bond/module/v1" modulev1 "git.vdb.to/cerc-io/laconic2d/api/cerc/bond/module/v1"
"git.vdb.to/cerc-io/laconic2d/x/bond"
"git.vdb.to/cerc-io/laconic2d/x/bond/keeper" "git.vdb.to/cerc-io/laconic2d/x/bond/keeper"
) )
@ -25,6 +27,7 @@ func init() {
appmodule.Register( appmodule.Register(
&modulev1.Module{}, &modulev1.Module{},
appmodule.Provide(ProvideModule), appmodule.Provide(ProvideModule),
appmodule.Invoke(InvokeSetBondHooks),
) )
} }
@ -41,7 +44,7 @@ type ModuleInputs struct {
type ModuleOutputs struct { type ModuleOutputs struct {
depinject.Out depinject.Out
Keeper keeper.Keeper Keeper *keeper.Keeper
Module appmodule.AppModule Module appmodule.AppModule
} }
@ -51,3 +54,25 @@ func ProvideModule(in ModuleInputs) ModuleOutputs {
return ModuleOutputs{Module: m, Keeper: k} return ModuleOutputs{Module: m, Keeper: k}
} }
func InvokeSetBondHooks(
config *modulev1.Module,
keeper *keeper.Keeper,
bondHooks map[string]bond.BondHooksWrapper,
) error {
// all arguments to invokers are optional
if keeper == nil || config == nil {
return nil
}
var usageKeepers []bond.BondUsageKeeper
for _, modName := range maps.Keys(bondHooks) {
hook := bondHooks[modName]
usageKeepers = append(usageKeepers, hook)
}
keeper.SetUsageKeepers(usageKeepers)
return nil
}

View File

@ -33,11 +33,11 @@ const ConsensusVersion = 1
type AppModule struct { type AppModule struct {
cdc codec.Codec cdc codec.Codec
keeper keeper.Keeper keeper *keeper.Keeper
} }
// NewAppModule creates a new AppModule object // NewAppModule creates a new AppModule object
func NewAppModule(cdc codec.Codec, keeper keeper.Keeper) AppModule { func NewAppModule(cdc codec.Codec, keeper *keeper.Keeper) AppModule {
return AppModule{ return AppModule{
cdc: cdc, cdc: cdc,
keeper: keeper, keeper: keeper,

View File

@ -97,7 +97,7 @@ type Keeper struct {
accountKeeper auth.AccountKeeper accountKeeper auth.AccountKeeper
bankKeeper bank.Keeper bankKeeper bank.Keeper
bondKeeper bondkeeper.Keeper bondKeeper *bondkeeper.Keeper
auctionKeeper *auctionkeeper.Keeper auctionKeeper *auctionkeeper.Keeper
// state management // state management
@ -116,7 +116,7 @@ func NewKeeper(
storeService storetypes.KVStoreService, storeService storetypes.KVStoreService,
accountKeeper auth.AccountKeeper, accountKeeper auth.AccountKeeper,
bankKeeper bank.Keeper, bankKeeper bank.Keeper,
bondKeeper bondkeeper.Keeper, bondKeeper *bondkeeper.Keeper,
auctionKeeper *auctionkeeper.Keeper, auctionKeeper *auctionkeeper.Keeper,
) Keeper { ) Keeper {
sb := collections.NewSchemaBuilder(storeService) sb := collections.NewSchemaBuilder(storeService)

View File

@ -46,12 +46,12 @@ func (rk RecordKeeper) ModuleName() string {
} }
func (rk RecordKeeper) UsesAuction(ctx sdk.Context, auctionId string) bool { func (rk RecordKeeper) UsesAuction(ctx sdk.Context, auctionId string) bool {
if _, err := rk.k.Authorities.Indexes.AuctionId.MatchExact(ctx, auctionId); err != nil { iter, err := rk.k.Authorities.Indexes.AuctionId.MatchExact(ctx, auctionId)
// ErrNotFound if err != nil {
return false panic(err)
} }
return true return iter.Valid()
} }
func (rk RecordKeeper) OnAuction(ctx sdk.Context, auctionId string) { func (rk RecordKeeper) OnAuction(ctx sdk.Context, auctionId string) {
@ -133,6 +133,16 @@ func (rk RecordKeeper) OnAuctionWinnerSelected(ctx sdk.Context, auctionId string
} }
} }
// 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. // RenewRecord renews a record.
func (k Keeper) RenewRecord(ctx sdk.Context, msg registrytypes.MsgRenewRecord) error { func (k Keeper) RenewRecord(ctx sdk.Context, msg registrytypes.MsgRenewRecord) error {
if has, err := k.HasRecord(ctx, msg.RecordId); !has { if has, err := k.HasRecord(ctx, msg.RecordId); !has {

View File

@ -10,8 +10,9 @@ import (
bank "github.com/cosmos/cosmos-sdk/x/bank/keeper" bank "github.com/cosmos/cosmos-sdk/x/bank/keeper"
modulev1 "git.vdb.to/cerc-io/laconic2d/api/cerc/registry/module/v1" modulev1 "git.vdb.to/cerc-io/laconic2d/api/cerc/registry/module/v1"
auction "git.vdb.to/cerc-io/laconic2d/x/auction" "git.vdb.to/cerc-io/laconic2d/x/auction"
auctionkeeper "git.vdb.to/cerc-io/laconic2d/x/auction/keeper" auctionkeeper "git.vdb.to/cerc-io/laconic2d/x/auction/keeper"
"git.vdb.to/cerc-io/laconic2d/x/bond"
bondkeeper "git.vdb.to/cerc-io/laconic2d/x/bond/keeper" bondkeeper "git.vdb.to/cerc-io/laconic2d/x/bond/keeper"
"git.vdb.to/cerc-io/laconic2d/x/registry/keeper" "git.vdb.to/cerc-io/laconic2d/x/registry/keeper"
) )
@ -40,7 +41,7 @@ type ModuleInputs struct {
AccountKeeper auth.AccountKeeper AccountKeeper auth.AccountKeeper
BankKeeper bank.Keeper BankKeeper bank.Keeper
BondKeeper bondkeeper.Keeper BondKeeper *bondkeeper.Keeper
AuctionKeeper *auctionkeeper.Keeper AuctionKeeper *auctionkeeper.Keeper
} }
@ -51,6 +52,7 @@ type ModuleOutputs struct {
Module appmodule.AppModule Module appmodule.AppModule
AuctionHooks auction.AuctionHooksWrapper AuctionHooks auction.AuctionHooksWrapper
BondHooks bond.BondHooksWrapper
} }
func ProvideModule(in ModuleInputs) ModuleOutputs { func ProvideModule(in ModuleInputs) ModuleOutputs {
@ -66,5 +68,9 @@ func ProvideModule(in ModuleInputs) ModuleOutputs {
recordKeeper := keeper.NewRecordKeeper(in.Cdc, &k, in.AuctionKeeper) recordKeeper := keeper.NewRecordKeeper(in.Cdc, &k, in.AuctionKeeper)
return ModuleOutputs{Module: m, Keeper: k, AuctionHooks: auction.AuctionHooksWrapper{AuctionUsageKeeper: recordKeeper}} return ModuleOutputs{
Module: m, Keeper: k,
AuctionHooks: auction.AuctionHooksWrapper{AuctionUsageKeeper: recordKeeper},
BondHooks: bond.BondHooksWrapper{BondUsageKeeper: recordKeeper},
}
} }