diff --git a/x/multi-staking/module.go b/x/multi-staking/module.go index 3ddd8f15..802ce510 100644 --- a/x/multi-staking/module.go +++ b/x/multi-staking/module.go @@ -48,17 +48,18 @@ func (am AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry) { am.stakingAppModBasic.RegisterInterfaces(reg) } -// DefaultGenesis returns feeabs module default genesis state. +// DefaultGenesis returns multi-staking module default genesis state. func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { return cdc.MustMarshalJSON(multistakingtypes.DefaultGenesis()) } -// ValidateGenesis validate genesis state for feeabs module -func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error { +// ValidateGenesis validate genesis state for multi-staking module +func (am AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error { var genState multistakingtypes.GenesisState if err := cdc.UnmarshalJSON(bz, &genState); err != nil { return fmt.Errorf("failed to unmarshal %s genesis state: %w", multistakingtypes.ModuleName, err) } + return genState.Validate() } @@ -142,7 +143,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { stakingtypes.RegisterQueryServer(cfg.QueryServer(), querier) } -// InitGenesis initial genesis state for feeabs module +// InitGenesis initial genesis state for multi-staking module func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate { var genesisState multistakingtypes.GenesisState cdc.MustUnmarshalJSON(data, &genesisState) @@ -150,18 +151,18 @@ func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json. return am.keeper.InitGenesis(ctx, genesisState) } -// ExportGenesis export feeabs state as raw message for feeabs module +// ExportGenesis export multi-staking state as raw message for multi-staking module func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { gs := am.keeper.ExportGenesis(ctx) return cdc.MustMarshalJSON(gs) } -// BeginBlock returns the begin blocker for the feeabs module. +// BeginBlock returns the begin blocker for the multi-staking module. func (am AppModule) BeginBlock(ctx sdk.Context, requestBeginBlock abci.RequestBeginBlock) { am.skAppModule.BeginBlock(ctx, requestBeginBlock) } -// EndBlock returns the end blocker for the feeabs module. It returns no validator +// EndBlock returns the end blocker for the multi-staking module. It returns no validator // updates. func (am AppModule) EndBlock(ctx sdk.Context, requestEndBlock abci.RequestEndBlock) []abci.ValidatorUpdate { // calculate the amount of coin diff --git a/x/multi-staking/types/errors.go b/x/multi-staking/types/errors.go index 48df793c..b92613f7 100644 --- a/x/multi-staking/types/errors.go +++ b/x/multi-staking/types/errors.go @@ -6,6 +6,9 @@ import ( // x/multistaking module sentinel errors var ( - ErrInvalidAddMultiStakingCoinProposal = sdkerrors.Register(ModuleName, 2, "invalid add multi staking coin proposal") - ErrInvalidUpdateBondWeightProposal = sdkerrors.Register(ModuleName, 3, "invalid update bond weight proposal") + ErrInvalidAddMultiStakingCoinProposal = sdkerrors.Register(ModuleName, 2, "invalid add multi staking coin proposal") + ErrInvalidUpdateBondWeightProposal = sdkerrors.Register(ModuleName, 3, "invalid update bond weight proposal") + ErrInvalidTotalMultiStakingLocks = sdkerrors.Register(ModuleName, 4, "invalid total multi-staking lock") + ErrInvalidTotalMultiStakingUnlocks = sdkerrors.Register(ModuleName, 5, "invalid total multi-staking unlock") + ErrInvalidMultiStakingUnlocksCreationHeight = sdkerrors.Register(ModuleName, 6, "invalid unlock creation height") ) diff --git a/x/multi-staking/types/genesis.go b/x/multi-staking/types/genesis.go index bbaffafb..b484b65a 100644 --- a/x/multi-staking/types/genesis.go +++ b/x/multi-staking/types/genesis.go @@ -1,7 +1,10 @@ package types import ( + "cosmossdk.io/errors" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/x/staking" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -14,8 +17,46 @@ func DefaultGenesis() *GenesisState { } // Validate performs basic genesis state validation, returning an error upon any failure. -// TODO: Add validate genesis func (gs GenesisState) Validate() error { + // validate staking genesis + if err := staking.ValidateGenesis(&gs.StakingGenesisState); err != nil { + return err + } + + // validate locks + if len(gs.MultiStakingLocks) != len(gs.StakingGenesisState.Delegations) { + return errors.Wrapf( + ErrInvalidTotalMultiStakingLocks, + "locks and delegations not equal: locks: %v delegations: %v", + len(gs.MultiStakingLocks), + len(gs.StakingGenesisState.Delegations), + ) + } + + for _, lock := range gs.MultiStakingLocks { + err := lock.Validate() + if err != nil { + return err + } + } + + // validate unlocks + if len(gs.MultiStakingUnlocks) != len(gs.StakingGenesisState.UnbondingDelegations) { + return errors.Wrapf( + ErrInvalidTotalMultiStakingUnlocks, + "unlocks and unbondingdelegations not equal: unlocks: %v unbondingdelegations: %v", + len(gs.MultiStakingUnlocks), + len(gs.StakingGenesisState.UnbondingDelegations), + ) + } + + for _, unlock := range gs.MultiStakingUnlocks { + err := unlock.Validate() + if err != nil { + return err + } + } + return nil } diff --git a/x/multi-staking/types/lock.go b/x/multi-staking/types/lock.go index 0549f867..78eadf5b 100644 --- a/x/multi-staking/types/lock.go +++ b/x/multi-staking/types/lock.go @@ -13,6 +13,16 @@ func NewMultiStakingLock(lockID LockID, lockedCoin MultiStakingCoin) MultiStakin } } +func (lock MultiStakingLock) Validate() error { + if _, err := sdk.AccAddressFromBech32(lock.LockID.MultiStakerAddr); err != nil { + return err + } + if _, err := sdk.ValAddressFromBech32(lock.LockID.ValAddr); err != nil { + return err + } + return lock.LockedCoin.Validate() +} + func (lock MultiStakingLock) MultiStakingCoin(withAmount math.Int) MultiStakingCoin { return lock.LockedCoin.WithAmount(withAmount) } diff --git a/x/multi-staking/types/unlock.go b/x/multi-staking/types/unlock.go index 1010c25b..d10aa7f7 100644 --- a/x/multi-staking/types/unlock.go +++ b/x/multi-staking/types/unlock.go @@ -23,6 +23,18 @@ func (e UnlockEntry) String() string { return string(out) } +func (u UnlockEntry) GetBondWeight() sdk.Dec { + return u.UnlockingCoin.BondWeight +} + +func (unlockEntry UnlockEntry) UnbondAmountToUnlockAmount(unbondAmount math.Int) math.Int { + return sdk.NewDecFromInt(unbondAmount).Quo(unlockEntry.GetBondWeight()).TruncateInt() +} + +func (unlockEntry UnlockEntry) UnlockAmountToUnbondAmount(unlockAmount math.Int) math.Int { + return unlockEntry.GetBondWeight().MulInt(unlockAmount).TruncateInt() +} + // NewMultiStakingUnlock - create a new MultiStaking unlock object // //nolint:interfacer @@ -37,6 +49,26 @@ func NewMultiStakingUnlock( } } +func (unlock MultiStakingUnlock) Validate() error { + if _, err := sdk.AccAddressFromBech32(unlock.UnlockID.MultiStakerAddr); err != nil { + return err + } + if _, err := sdk.ValAddressFromBech32(unlock.UnlockID.ValAddr); err != nil { + return err + } + for _, entry := range unlock.Entries { + if entry.CreationHeight <= 0 { + return ErrInvalidMultiStakingUnlocksCreationHeight + } + + if err := entry.UnlockingCoin.Validate(); err != nil { + return err + } + } + + return nil +} + func (unlock *MultiStakingUnlock) FindEntryIndexByHeight(creationHeight int64) (int, bool) { for index, unlockEntry := range unlock.Entries { if unlockEntry.CreationHeight == creationHeight { @@ -101,18 +133,6 @@ func (unlock *MultiStakingUnlock) RemoveEntryAtCreationHeight(creationHeight int } } -func (u UnlockEntry) GetBondWeight() sdk.Dec { - return u.UnlockingCoin.BondWeight -} - -func (unlockEntry UnlockEntry) UnbondAmountToUnlockAmount(unbondAmount math.Int) math.Int { - return sdk.NewDecFromInt(unbondAmount).Quo(unlockEntry.GetBondWeight()).TruncateInt() -} - -func (unlockEntry UnlockEntry) UnlockAmountToUnbondAmount(unlockAmount math.Int) math.Int { - return unlockEntry.GetBondWeight().MulInt(unlockAmount).TruncateInt() -} - // String returns a human readable string representation of an MultiStakingUnlock. func (unlock MultiStakingUnlock) String() string { out := fmt.Sprintf(`Unlock ID: %s