From ec147272e6d56e672f3ee32be50494213b6c67ec Mon Sep 17 00:00:00 2001 From: Prathamesh Musale Date: Wed, 6 Mar 2024 09:24:15 +0000 Subject: [PATCH] Add module invariants and input validations (#14) Reviewed-on: https://git.vdb.to/deep-stack/laconic2d/pulls/14 Co-authored-by: Prathamesh Musale Co-committed-by: Prathamesh Musale --- app/app.go | 7 ++- app/app.yaml | 7 ++- tests/e2e/bond/suite.go | 6 +- x/auction/keeper/invariants.go | 37 +++++++++++++ x/auction/keeper/keeper.go | 9 ++- x/auction/keeper/msg_server.go | 8 +++ x/auction/module/module.go | 7 +++ x/bond/keeper/invariants.go | 37 +++++++++++++ x/bond/keeper/msg_server.go | 18 ++++++ x/bond/module/module.go | 7 +++ x/bond/msgs.go | 48 ++++++++++++++++ x/registry/keeper/invariants.go | 75 +++++++++++++++++++++++++ x/registry/keeper/msg_server.go | 40 ++++++++++++++ x/registry/module/module.go | 7 +++ x/registry/msgs.go | 97 +++++++++++++++++++++++++++++++++ 15 files changed, 400 insertions(+), 10 deletions(-) create mode 100644 x/auction/keeper/invariants.go create mode 100644 x/bond/keeper/invariants.go create mode 100644 x/registry/keeper/invariants.go diff --git a/app/app.go b/app/app.go index aea38d1a..096baad2 100644 --- a/app/app.go +++ b/app/app.go @@ -29,6 +29,7 @@ import ( authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" consensuskeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper" + crisiskeeper "github.com/cosmos/cosmos-sdk/x/crisis/keeper" distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" "github.com/cosmos/cosmos-sdk/x/genutil" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" @@ -42,6 +43,7 @@ import ( _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import for side-effects _ "github.com/cosmos/cosmos-sdk/x/bank" // import for side-effects _ "github.com/cosmos/cosmos-sdk/x/consensus" // import for side-effects + _ "github.com/cosmos/cosmos-sdk/x/crisis" // import for side-effects _ "github.com/cosmos/cosmos-sdk/x/distribution" // import for side-effects _ "github.com/cosmos/cosmos-sdk/x/mint" // import for side-effects _ "github.com/cosmos/cosmos-sdk/x/staking" // import for side-effects @@ -73,6 +75,7 @@ type LaconicApp struct { BankKeeper bankkeeper.Keeper StakingKeeper *stakingkeeper.Keeper DistrKeeper distrkeeper.Keeper + CrisisKeeper *crisiskeeper.Keeper ConsensusParamsKeeper consensuskeeper.Keeper // laconic keepers @@ -137,6 +140,7 @@ func NewLaconicApp( &app.BankKeeper, &app.StakingKeeper, &app.DistrKeeper, + &app.CrisisKeeper, &app.ConsensusParamsKeeper, &app.AuctionKeeper, &app.BondKeeper, @@ -154,7 +158,8 @@ func NewLaconicApp( /**** Module Options ****/ - // TOOD: Required? + app.ModuleManager.RegisterInvariants(app.CrisisKeeper) + // create the simulation manager and define the order of the modules for deterministic simulations // NOTE: this is not required apps that don't use the simulator for fuzz testing transactions app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, make(map[string]module.AppModuleSimulation, 0)) diff --git a/app/app.yaml b/app/app.yaml index 3d432433..5d1601af 100644 --- a/app/app.yaml +++ b/app/app.yaml @@ -7,10 +7,10 @@ modules: # there is nothing left over in the validator fee pool, so as to keep the CanWithdrawInvariant invariant. # NOTE: staking module is required if HistoricalEntries param > 0 begin_blockers: [distribution, staking] - end_blockers: [staking, auction, registry] + end_blockers: [crisis, staking, auction, registry] # NOTE: The genutils module must occur after staking so that pools are properly initialized with tokens from genesis accounts. # NOTE: The genutils module must also occur after auth so that it can access the params from auth. - init_genesis: [auth, bank, distribution, staking, genutil, auction, bond, registry] + init_genesis: [auth, bank, distribution, staking, crisis, genutil, auction, bond, registry] override_store_keys: - module_name: auth kv_store_key: acc @@ -51,6 +51,9 @@ modules: - name: tx config: "@type": cosmos.tx.config.v1.Config + - name: crisis + config: + "@type": cosmos.crisis.module.v1.Module - name: bond config: "@type": cerc.bond.module.v1.Module diff --git a/tests/e2e/bond/suite.go b/tests/e2e/bond/suite.go index 67f435d9..484aad86 100644 --- a/tests/e2e/bond/suite.go +++ b/tests/e2e/bond/suite.go @@ -118,6 +118,8 @@ func (ets *E2ETestSuite) createBond() string { sr.NoError(err) // extract bond id from bonds list - bond := queryResponse.GetBonds()[0] - return bond.GetId() + bonds := queryResponse.GetBonds() + sr.NotEmpty(bonds) + + return queryResponse.GetBonds()[0].GetId() } diff --git a/x/auction/keeper/invariants.go b/x/auction/keeper/invariants.go new file mode 100644 index 00000000..d2a0dcc9 --- /dev/null +++ b/x/auction/keeper/invariants.go @@ -0,0 +1,37 @@ +package keeper + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + + types "git.vdb.to/cerc-io/laconic2d/x/auction" +) + +// RegisterInvariants registers all auction invariants +func RegisterInvariants(ir sdk.InvariantRegistry, k *Keeper) { + ir.RegisterRoute(types.ModuleName, "module-account", ModuleAccountInvariant(k)) +} + +// AllInvariants runs all invariants of the auction module. +func AllInvariants(k *Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + return ModuleAccountInvariant(k)(ctx) + } +} + +// ModuleAccountInvariant checks that the 'auction' module account balance is non-negative. +func ModuleAccountInvariant(k *Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + moduleAddress := k.accountKeeper.GetModuleAddress(types.ModuleName) + if k.bankKeeper.GetAllBalances(ctx, moduleAddress).IsAnyNegative() { + return sdk.FormatInvariant( + types.ModuleName, + "module-account", + fmt.Sprintf("Module account '%s' has negative balance.", types.ModuleName), + ), true + } + + return "", false + } +} diff --git a/x/auction/keeper/keeper.go b/x/auction/keeper/keeper.go index edcb72ba..1ca091b3 100644 --- a/x/auction/keeper/keeper.go +++ b/x/auction/keeper/keeper.go @@ -285,12 +285,11 @@ func (k Keeper) QueryAuctionsByBidder(ctx sdk.Context, bidderAddress string) ([] // CreateAuction creates a new auction. func (k Keeper) CreateAuction(ctx sdk.Context, msg auctiontypes.MsgCreateAuction) (*auctiontypes.Auction, error) { - // TODO: Setup checks // Might be called from another module directly, always validate. - // err := msg.ValidateBasic() - // if err != nil { - // return nil, err - // } + err := msg.ValidateBasic() + if err != nil { + return nil, err + } signerAddress, err := sdk.AccAddressFromBech32(msg.Signer) if err != nil { diff --git a/x/auction/keeper/msg_server.go b/x/auction/keeper/msg_server.go index b2035a9e..b2654d8b 100644 --- a/x/auction/keeper/msg_server.go +++ b/x/auction/keeper/msg_server.go @@ -52,6 +52,10 @@ func (ms msgServer) CreateAuction(c context.Context, msg *auctiontypes.MsgCreate // CommitBid is the command for committing a bid // nolint: all func (ms msgServer) CommitBid(c context.Context, msg *auctiontypes.MsgCommitBid) (*auctiontypes.MsgCommitBidResponse, error) { + if err := msg.ValidateBasic(); err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) signerAddress, err := sdk.AccAddressFromBech32(msg.Signer) @@ -83,6 +87,10 @@ func (ms msgServer) CommitBid(c context.Context, msg *auctiontypes.MsgCommitBid) // RevealBid is the command for revealing a bid // nolint: all func (ms msgServer) RevealBid(c context.Context, msg *auctiontypes.MsgRevealBid) (*auctiontypes.MsgRevealBidResponse, error) { + if err := msg.ValidateBasic(); err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) signerAddress, err := sdk.AccAddressFromBech32(msg.Signer) diff --git a/x/auction/module/module.go b/x/auction/module/module.go index 7eb54db0..e2094d80 100644 --- a/x/auction/module/module.go +++ b/x/auction/module/module.go @@ -27,6 +27,7 @@ var ( _ module.HasServices = AppModule{} _ module.HasConsensusVersion = AppModule{} _ appmodule.HasEndBlocker = AppModule{} + _ module.HasInvariants = AppModule{} ) // ConsensusVersion defines the current module consensus version @@ -126,6 +127,12 @@ func (am AppModule) EndBlock(ctx context.Context) error { return EndBlocker(ctx, am.keeper) } +// module.HasInvariants + +func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { + keeper.RegisterInvariants(ir, am.keeper) +} + // Get the root tx command of this module func (AppModule) GetTxCmd() *cobra.Command { return cli.GetTxCmd() diff --git a/x/bond/keeper/invariants.go b/x/bond/keeper/invariants.go new file mode 100644 index 00000000..f62789a9 --- /dev/null +++ b/x/bond/keeper/invariants.go @@ -0,0 +1,37 @@ +package keeper + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + + types "git.vdb.to/cerc-io/laconic2d/x/bond" +) + +// RegisterInvariants registers all bond invariants +func RegisterInvariants(ir sdk.InvariantRegistry, k *Keeper) { + ir.RegisterRoute(types.ModuleName, "module-account", ModuleAccountInvariant(k)) +} + +// AllInvariants runs all invariants of the bond module. +func AllInvariants(k *Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + return ModuleAccountInvariant(k)(ctx) + } +} + +// ModuleAccountInvariant checks that the 'bond' module account balance is non-negative. +func ModuleAccountInvariant(k *Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + moduleAddress := k.accountKeeper.GetModuleAddress(types.ModuleName) + if k.bankKeeper.GetAllBalances(ctx, moduleAddress).IsAnyNegative() { + return sdk.FormatInvariant( + types.ModuleName, + "module-account", + fmt.Sprintf("Module account '%s' has negative balance.", types.ModuleName), + ), true + } + + return "", false + } +} diff --git a/x/bond/keeper/msg_server.go b/x/bond/keeper/msg_server.go index 719f17b4..21b8630f 100644 --- a/x/bond/keeper/msg_server.go +++ b/x/bond/keeper/msg_server.go @@ -20,6 +20,10 @@ func NewMsgServerImpl(keeper *Keeper) bond.MsgServer { } func (ms msgServer) CreateBond(c context.Context, msg *bond.MsgCreateBond) (*bond.MsgCreateBondResponse, error) { + if err := msg.ValidateBasic(); err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) signerAddress, err := sdk.AccAddressFromBech32(msg.Signer) @@ -50,6 +54,10 @@ func (ms msgServer) CreateBond(c context.Context, msg *bond.MsgCreateBond) (*bon // RefillBond implements bond.MsgServer. func (ms msgServer) RefillBond(c context.Context, msg *bond.MsgRefillBond) (*bond.MsgRefillBondResponse, error) { + if err := msg.ValidateBasic(); err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) signerAddress, err := sdk.AccAddressFromBech32(msg.Signer) @@ -81,6 +89,10 @@ func (ms msgServer) RefillBond(c context.Context, msg *bond.MsgRefillBond) (*bon // WithdrawBond implements bond.MsgServer. func (ms msgServer) WithdrawBond(c context.Context, msg *bond.MsgWithdrawBond) (*bond.MsgWithdrawBondResponse, error) { + if err := msg.ValidateBasic(); err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) signerAddress, err := sdk.AccAddressFromBech32(msg.Signer) @@ -112,11 +124,17 @@ func (ms msgServer) WithdrawBond(c context.Context, msg *bond.MsgWithdrawBond) ( // CancelBond implements bond.MsgServer. func (ms msgServer) CancelBond(c context.Context, msg *bond.MsgCancelBond) (*bond.MsgCancelBondResponse, error) { + if err := msg.ValidateBasic(); err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) + signerAddress, err := sdk.AccAddressFromBech32(msg.Signer) if err != nil { return nil, err } + _, err = ms.k.CancelBond(ctx, msg.Id, signerAddress) if err != nil { return nil, err diff --git a/x/bond/module/module.go b/x/bond/module/module.go index 073f5224..414a64ff 100644 --- a/x/bond/module/module.go +++ b/x/bond/module/module.go @@ -24,6 +24,7 @@ var ( _ module.HasGenesis = AppModule{} _ module.HasServices = AppModule{} _ module.HasConsensusVersion = AppModule{} + _ module.HasInvariants = AppModule{} ) // ConsensusVersion defines the current module consensus version @@ -116,3 +117,9 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { bond.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) bond.RegisterQueryServer(cfg.QueryServer(), keeper.NewQueryServerImpl(am.keeper)) } + +// module.HasInvariants + +func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { + keeper.RegisterInvariants(ir, am.keeper) +} diff --git a/x/bond/msgs.go b/x/bond/msgs.go index c473c612..135127f6 100644 --- a/x/bond/msgs.go +++ b/x/bond/msgs.go @@ -1,7 +1,9 @@ package bond import ( + errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) var ( @@ -15,3 +17,49 @@ func NewMsgCreateBond(coins sdk.Coins, signer sdk.AccAddress) MsgCreateBond { Signer: signer.String(), } } + +func (msg MsgCreateBond) ValidateBasic() error { + if len(msg.Signer) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, msg.Signer) + } + if len(msg.Coins) == 0 || !msg.Coins.IsValid() { + return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, "Invalid amount.") + } + return nil +} + +func (msg MsgRefillBond) ValidateBasic() error { + if len(msg.Id) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, msg.Id) + } + if len(msg.Signer) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, msg.Signer) + } + if len(msg.Coins) == 0 || !msg.Coins.IsValid() { + return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, "Invalid amount.") + } + return nil +} + +func (msg MsgWithdrawBond) ValidateBasic() error { + if len(msg.Id) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, msg.Id) + } + if len(msg.Signer) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, msg.Signer) + } + if len(msg.Coins) == 0 || !msg.Coins.IsValid() { + return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, "Invalid amount.") + } + return nil +} + +func (msg MsgCancelBond) ValidateBasic() error { + if len(msg.Id) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, msg.Id) + } + if len(msg.Signer) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, msg.Signer) + } + return nil +} diff --git a/x/registry/keeper/invariants.go b/x/registry/keeper/invariants.go new file mode 100644 index 00000000..71ee0973 --- /dev/null +++ b/x/registry/keeper/invariants.go @@ -0,0 +1,75 @@ +package keeper + +import ( + "errors" + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + + types "git.vdb.to/cerc-io/laconic2d/x/registry" +) + +// RegisterInvariants registers all registry invariants +func RegisterInvariants(ir sdk.InvariantRegistry, k Keeper) { + ir.RegisterRoute(types.ModuleName, "module-account", ModuleAccountInvariant(&k)) + ir.RegisterRoute(types.ModuleName, "record-bond", RecordBondInvariant(&k)) +} + +// AllInvariants runs all invariants of the registry module. +func AllInvariants(k *Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + res, stop := ModuleAccountInvariant(k)(ctx) + if stop { + return res, stop + } + + return RecordBondInvariant(k)(ctx) + } +} + +// ModuleAccountInvariant checks that the 'registry' module account balance is non-negative. +func ModuleAccountInvariant(k *Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + moduleAddress := k.accountKeeper.GetModuleAddress(types.ModuleName) + if k.bankKeeper.GetAllBalances(ctx, moduleAddress).IsAnyNegative() { + return sdk.FormatInvariant( + types.ModuleName, + "module-account", + fmt.Sprintf("Module account '%s' has negative balance.", types.ModuleName), + ), true + } + + return "", false + } +} + +// RecordBondInvariant checks that for every record: +// if bondId is not null, associated bond exists +func RecordBondInvariant(k *Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + err := k.Records.Walk(ctx, nil, func(key string, record types.Record) (bool, error) { + if record.BondId != "" { + bondExists, err := k.bondKeeper.HasBond(ctx, record.BondId) + if err != nil { + return true, err + } + + if !bondExists { + return true, errors.New(record.Id) + } + } + + return false, nil + }) + + if err != nil { + return sdk.FormatInvariant( + types.ModuleName, + "record-bond", + fmt.Sprintf("Bond not found for record id: '%s'.", err.Error()), + ), true + } + + return "", false + } +} diff --git a/x/registry/keeper/msg_server.go b/x/registry/keeper/msg_server.go index ba48d633..fc9e47a7 100644 --- a/x/registry/keeper/msg_server.go +++ b/x/registry/keeper/msg_server.go @@ -20,6 +20,10 @@ func NewMsgServerImpl(keeper Keeper) registrytypes.MsgServer { } func (ms msgServer) SetRecord(c context.Context, msg *registrytypes.MsgSetRecord) (*registrytypes.MsgSetRecordResponse, error) { + if err := msg.ValidateBasic(); err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) _, err := sdk.AccAddressFromBech32(msg.Signer) @@ -51,6 +55,10 @@ func (ms msgServer) SetRecord(c context.Context, msg *registrytypes.MsgSetRecord // nolint: all func (ms msgServer) SetName(c context.Context, msg *registrytypes.MsgSetName) (*registrytypes.MsgSetNameResponse, error) { + if err := msg.ValidateBasic(); err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) _, err := sdk.AccAddressFromBech32(msg.Signer) @@ -80,6 +88,10 @@ func (ms msgServer) SetName(c context.Context, msg *registrytypes.MsgSetName) (* } func (ms msgServer) ReserveName(c context.Context, msg *registrytypes.MsgReserveAuthority) (*registrytypes.MsgReserveAuthorityResponse, error) { + if err := msg.ValidateBasic(); err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) _, err := sdk.AccAddressFromBech32(msg.Signer) @@ -114,6 +126,10 @@ func (ms msgServer) ReserveName(c context.Context, msg *registrytypes.MsgReserve // nolint: all func (ms msgServer) SetAuthorityBond(c context.Context, msg *registrytypes.MsgSetAuthorityBond) (*registrytypes.MsgSetAuthorityBondResponse, error) { + if err := msg.ValidateBasic(); err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) _, err := sdk.AccAddressFromBech32(msg.Signer) @@ -144,6 +160,10 @@ func (ms msgServer) SetAuthorityBond(c context.Context, msg *registrytypes.MsgSe } func (ms msgServer) DeleteName(c context.Context, msg *registrytypes.MsgDeleteNameAuthority) (*registrytypes.MsgDeleteNameAuthorityResponse, error) { + if err := msg.ValidateBasic(); err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) _, err := sdk.AccAddressFromBech32(msg.Signer) @@ -172,6 +192,10 @@ func (ms msgServer) DeleteName(c context.Context, msg *registrytypes.MsgDeleteNa } func (ms msgServer) RenewRecord(c context.Context, msg *registrytypes.MsgRenewRecord) (*registrytypes.MsgRenewRecordResponse, error) { + if err := msg.ValidateBasic(); err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) _, err := sdk.AccAddressFromBech32(msg.Signer) @@ -201,6 +225,10 @@ func (ms msgServer) RenewRecord(c context.Context, msg *registrytypes.MsgRenewRe // nolint: all func (ms msgServer) AssociateBond(c context.Context, msg *registrytypes.MsgAssociateBond) (*registrytypes.MsgAssociateBondResponse, error) { + if err := msg.ValidateBasic(); err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) _, err := sdk.AccAddressFromBech32(msg.Signer) @@ -231,6 +259,10 @@ func (ms msgServer) AssociateBond(c context.Context, msg *registrytypes.MsgAssoc } func (ms msgServer) DissociateBond(c context.Context, msg *registrytypes.MsgDissociateBond) (*registrytypes.MsgDissociateBondResponse, error) { + if err := msg.ValidateBasic(); err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) _, err := sdk.AccAddressFromBech32(msg.Signer) @@ -260,6 +292,10 @@ func (ms msgServer) DissociateBond(c context.Context, msg *registrytypes.MsgDiss } func (ms msgServer) DissociateRecords(c context.Context, msg *registrytypes.MsgDissociateRecords) (*registrytypes.MsgDissociateRecordsResponse, error) { + if err := msg.ValidateBasic(); err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) _, err := sdk.AccAddressFromBech32(msg.Signer) @@ -289,6 +325,10 @@ func (ms msgServer) DissociateRecords(c context.Context, msg *registrytypes.MsgD } func (ms msgServer) ReassociateRecords(c context.Context, msg *registrytypes.MsgReassociateRecords) (*registrytypes.MsgReassociateRecordsResponse, error) { //nolint: all + if err := msg.ValidateBasic(); err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) _, err := sdk.AccAddressFromBech32(msg.Signer) diff --git a/x/registry/module/module.go b/x/registry/module/module.go index 7e4f5703..d8a325af 100644 --- a/x/registry/module/module.go +++ b/x/registry/module/module.go @@ -27,6 +27,7 @@ var ( _ module.HasServices = AppModule{} _ module.HasConsensusVersion = AppModule{} _ appmodule.HasEndBlocker = AppModule{} + _ module.HasInvariants = AppModule{} ) // ConsensusVersion defines the current module consensus version. @@ -127,6 +128,12 @@ func (am AppModule) EndBlock(ctx context.Context) error { return EndBlocker(ctx, am.keeper) } +// module.HasInvariants + +func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { + keeper.RegisterInvariants(ir, am.keeper) +} + // Get the root tx command of this module func (AppModule) GetTxCmd() *cobra.Command { return cli.GetTxCmd() diff --git a/x/registry/msgs.go b/x/registry/msgs.go index 93f65743..c091441a 100644 --- a/x/registry/msgs.go +++ b/x/registry/msgs.go @@ -1,6 +1,8 @@ package registry import ( + "net/url" + errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -34,6 +36,18 @@ func (msg MsgSetRecord) ValidateBasic() error { return nil } +func (msg MsgRenewRecord) ValidateBasic() error { + if len(msg.RecordId) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "record id is required.") + } + + if len(msg.Signer) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer.") + } + + return nil +} + // NewMsgReserveAuthority is the constructor function for MsgReserveName. func NewMsgReserveAuthority(name string, signer sdk.AccAddress, owner sdk.AccAddress) MsgReserveAuthority { return MsgReserveAuthority{ @@ -65,6 +79,22 @@ func NewMsgSetAuthorityBond(name string, bondID string, signer sdk.AccAddress) M } } +func (msg MsgSetAuthorityBond) ValidateBasic() error { + if len(msg.Name) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "name is required.") + } + + if len(msg.Signer) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer.") + } + + if len(msg.BondId) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "bond id is required.") + } + + return nil +} + // NewMsgSetName is the constructor function for MsgSetName. func NewMsgSetName(lrn string, cid string, signer sdk.AccAddress) *MsgSetName { return &MsgSetName{ @@ -90,3 +120,70 @@ func (msg MsgSetName) ValidateBasic() error { return nil } + +func (msg MsgDeleteNameAuthority) ValidateBasic() error { + if len(msg.Lrn) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "lrn is required.") + } + + if len(msg.Signer) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer.") + } + + _, err := url.Parse(msg.Lrn) + if err != nil { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "invalid lrn.") + } + + return nil +} + +func (msg MsgAssociateBond) ValidateBasic() error { + if len(msg.RecordId) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "record id is required.") + } + if len(msg.BondId) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "bond id is required.") + } + if len(msg.Signer) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer.") + } + + return nil +} + +func (msg MsgDissociateBond) ValidateBasic() error { + if len(msg.RecordId) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "record id is required.") + } + if len(msg.Signer) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer.") + } + + return nil +} + +func (msg MsgDissociateRecords) ValidateBasic() error { + if len(msg.BondId) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "bond id is required.") + } + if len(msg.Signer) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer.") + } + + return nil +} + +func (msg MsgReassociateRecords) ValidateBasic() error { + if len(msg.OldBondId) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "old-bond-id is required.") + } + if len(msg.NewBondId) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "new-bond-id is required.") + } + if len(msg.Signer) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer.") + } + + return nil +}