From b01d5a000dae823c46d3eb22ccf499d1b5cee157 Mon Sep 17 00:00:00 2001 From: Gin Date: Fri, 16 Aug 2024 01:40:48 -0500 Subject: [PATCH 01/11] refactor(scripts): remove unused variable (#21320) --- scripts/validate-gentxs.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/validate-gentxs.sh b/scripts/validate-gentxs.sh index 7ab14f47561e..42640199973a 100755 --- a/scripts/validate-gentxs.sh +++ b/scripts/validate-gentxs.sh @@ -107,7 +107,6 @@ if [ "$(ls -A $GENTXS_DIR)" ]; then GENACC=$(cat $GENTX_FILE | sed -n 's|.*"delegator_address":"\([^"]*\)".*|\1|p') denomquery=$(jq -r '.body.messages[0].value.denom' $GENTX_FILE) - amountquery=$(jq -r '.body.messages[0].value.amount' $GENTX_FILE) # only allow $DENOM tokens to be bonded if [ $denomquery != $DENOM ]; then From e2ec889bb7d02ffae1d11f670727b351b5716e85 Mon Sep 17 00:00:00 2001 From: Facundo Medica <14063057+facundomedica@users.noreply.github.com> Date: Fri, 16 Aug 2024 10:18:31 +0200 Subject: [PATCH 02/11] fix(baseapp)!: Halt at height now does not produce the halt height block (#21256) --- CHANGELOG.md | 3 +++ baseapp/abci.go | 4 ++-- baseapp/abci_test.go | 8 +++++--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b3eb5d26e5e..db41a1eda64a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,9 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i ### Bug Fixes +* (baseapp) [#21256](https://github.com/cosmos/cosmos-sdk/pull/21256) Halt height will not commit the block indicated, meaning that if halt-height is set to 10, only blocks until 9 (included) will be committed. This is to go back to the original behavior before a change was introduced in v0.50.0. + + ### API Breaking Changes ## [v0.52.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.52.0) - 2024-XX-XX diff --git a/baseapp/abci.go b/baseapp/abci.go index d2d87a5cf562..49470e0af771 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -914,10 +914,10 @@ func (app *BaseApp) FinalizeBlock(req *abci.FinalizeBlockRequest) (res *abci.Fin func (app *BaseApp) checkHalt(height int64, time time.Time) error { var halt bool switch { - case app.haltHeight > 0 && uint64(height) > app.haltHeight: + case app.haltHeight > 0 && uint64(height) >= app.haltHeight: halt = true - case app.haltTime > 0 && time.Unix() > int64(app.haltTime): + case app.haltTime > 0 && time.Unix() >= int64(app.haltTime): halt = true } diff --git a/baseapp/abci_test.go b/baseapp/abci_test.go index b7fb67fad216..43b2c06d550e 100644 --- a/baseapp/abci_test.go +++ b/baseapp/abci_test.go @@ -2257,9 +2257,11 @@ func TestABCI_HaltChain(t *testing.T) { expHalt bool }{ {"default", 0, 0, 10, 0, false}, - {"halt-height-edge", 10, 0, 10, 0, false}, - {"halt-height", 10, 0, 11, 0, true}, - {"halt-time-edge", 0, 10, 1, 10, false}, + {"halt-height-edge", 11, 0, 10, 0, false}, + {"halt-height-equal", 10, 0, 10, 0, true}, + {"halt-height", 10, 0, 10, 0, true}, + {"halt-time-edge", 0, 11, 1, 10, false}, + {"halt-time-equal", 0, 10, 1, 10, true}, {"halt-time", 0, 10, 1, 11, true}, } From aeeaca64da2c1d579196557d63f8c053bcb6bb33 Mon Sep 17 00:00:00 2001 From: Randy Grok <98407738+randygrok@users.noreply.github.com> Date: Fri, 16 Aug 2024 13:15:45 +0200 Subject: [PATCH 03/11] feat: export genesis in simapp v2 (#21199) Co-authored-by: marbar3778 --- runtime/v2/app.go | 5 + runtime/v2/builder.go | 15 ++- runtime/v2/manager.go | 32 ++---- server/v2/appmanager/appmanager.go | 19 +++- server/v2/cometbft/go.mod | 2 +- simapp/app.go | 7 +- simapp/v2/app_di.go | 2 - simapp/v2/app_test.go | 155 +++++++++++++++++++++++++++++ simapp/v2/export.go | 27 ++++- simapp/v2/go.mod | 9 +- simapp/v2/simdv2/cmd/commands.go | 37 +++---- x/genutil/v2/cli/commands.go | 47 +++++++++ x/genutil/v2/cli/export.go | 106 ++++++++++++++++++++ x/genutil/v2/types.go | 27 +++++ x/staking/genesis.go | 3 +- 15 files changed, 426 insertions(+), 67 deletions(-) create mode 100644 simapp/v2/app_test.go create mode 100644 x/genutil/v2/cli/commands.go create mode 100644 x/genutil/v2/cli/export.go create mode 100644 x/genutil/v2/types.go diff --git a/runtime/v2/app.go b/runtime/v2/app.go index ba46e001fcb3..08f2498255c5 100644 --- a/runtime/v2/app.go +++ b/runtime/v2/app.go @@ -79,6 +79,11 @@ func (a *App[T]) LoadHeight(height uint64) error { return a.db.LoadVersion(height) } +// LoadLatestHeight loads the latest height. +func (a *App[T]) LoadLatestHeight() (uint64, error) { + return a.db.GetLatestVersion() +} + // Close is called in start cmd to gracefully cleanup resources. func (a *App[T]) Close() error { return nil diff --git a/runtime/v2/builder.go b/runtime/v2/builder.go index b7869fa3f0a7..578cd9934a6e 100644 --- a/runtime/v2/builder.go +++ b/runtime/v2/builder.go @@ -69,7 +69,7 @@ func (a *AppBuilder[T]) RegisterModules(modules map[string]appmodulev2.AppModule // RegisterStores registers the provided store keys. // This method should only be used for registering extra stores -// wiich is necessary for modules that not registered using the app config. +// which is necessary for modules that not registered using the app config. // To be used in combination of RegisterModules. func (a *AppBuilder[T]) RegisterStores(keys ...string) { a.app.storeKeys = append(a.app.storeKeys, keys...) @@ -175,6 +175,19 @@ func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) { } return nil }, + ExportGenesis: func(ctx context.Context, version uint64) ([]byte, error) { + genesisJson, err := a.app.moduleManager.ExportGenesisForModules(ctx) + if err != nil { + return nil, fmt.Errorf("failed to export genesis: %w", err) + } + + bz, err := json.Marshal(genesisJson) + if err != nil { + return nil, fmt.Errorf("failed to marshal genesis: %w", err) + } + + return bz, nil + }, } appManager, err := appManagerBuilder.Build() diff --git a/runtime/v2/manager.go b/runtime/v2/manager.go index a773f52a1dfc..093140bcd370 100644 --- a/runtime/v2/manager.go +++ b/runtime/v2/manager.go @@ -203,16 +203,13 @@ func (m *MM[T]) ExportGenesisForModules( return nil, err } - type genesisResult struct { - bz json.RawMessage - err error - } - type ModuleI interface { ExportGenesis(ctx context.Context) (json.RawMessage, error) } - channels := make(map[string]chan genesisResult) + genesisData := make(map[string]json.RawMessage) + + // TODO: make async export genesis https://github.com/cosmos/cosmos-sdk/issues/21303 for _, moduleName := range modulesToExport { mod := m.modules[moduleName] var moduleI ModuleI @@ -221,27 +218,16 @@ func (m *MM[T]) ExportGenesisForModules( moduleI = module.(ModuleI) } else if module, hasABCIGenesis := mod.(appmodulev2.HasGenesis); hasABCIGenesis { moduleI = module.(ModuleI) + } else { + continue } - channels[moduleName] = make(chan genesisResult) - go func(moduleI ModuleI, ch chan genesisResult) { - jm, err := moduleI.ExportGenesis(ctx) - if err != nil { - ch <- genesisResult{nil, err} - return - } - ch <- genesisResult{jm, nil} - }(moduleI, channels[moduleName]) - } - - genesisData := make(map[string]json.RawMessage) - for moduleName := range channels { - res := <-channels[moduleName] - if res.err != nil { - return nil, fmt.Errorf("genesis export error in %s: %w", moduleName, res.err) + res, err := moduleI.ExportGenesis(ctx) + if err != nil { + return nil, err } - genesisData[moduleName] = res.bz + genesisData[moduleName] = res } return genesisData, nil diff --git a/server/v2/appmanager/appmanager.go b/server/v2/appmanager/appmanager.go index 66e38a762a18..284b1dcb0965 100644 --- a/server/v2/appmanager/appmanager.go +++ b/server/v2/appmanager/appmanager.go @@ -89,7 +89,24 @@ func (a AppManager[T]) InitGenesis( // ExportGenesis exports the genesis state of the application. func (a AppManager[T]) ExportGenesis(ctx context.Context, version uint64) ([]byte, error) { - bz, err := a.exportGenesis(ctx, version) + zeroState, err := a.db.StateAt(version) + if err != nil { + return nil, fmt.Errorf("unable to get latest state: %w", err) + } + + bz := make([]byte, 0) + _, err = a.stf.RunWithCtx(ctx, zeroState, func(ctx context.Context) error { + if a.exportGenesis == nil { + return errors.New("export genesis function not set") + } + + bz, err = a.exportGenesis(ctx, version) + if err != nil { + return fmt.Errorf("failed to export genesis state: %w", err) + } + + return nil + }) if err != nil { return nil, fmt.Errorf("failed to export genesis state: %w", err) } diff --git a/server/v2/cometbft/go.mod b/server/v2/cometbft/go.mod index a64492e9b093..b3925a04cec6 100644 --- a/server/v2/cometbft/go.mod +++ b/server/v2/cometbft/go.mod @@ -26,7 +26,7 @@ require ( cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.0 cosmossdk.io/server/v2 v2.0.0-00010101000000-000000000000 - cosmossdk.io/server/v2/appmanager v0.0.0-00010101000000-000000000000 + cosmossdk.io/server/v2/appmanager v0.0.0-20240802110823-cffeedff643d cosmossdk.io/store/v2 v2.0.0-00010101000000-000000000000 cosmossdk.io/x/consensus v0.0.0-00010101000000-000000000000 github.com/cometbft/cometbft v1.0.0-rc1 diff --git a/simapp/app.go b/simapp/app.go index a03a9e69f518..118b4a3746b0 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -50,7 +50,6 @@ import ( circuittypes "cosmossdk.io/x/circuit/types" "cosmossdk.io/x/consensus" consensusparamkeeper "cosmossdk.io/x/consensus/keeper" - consensusparamtypes "cosmossdk.io/x/consensus/types" consensustypes "cosmossdk.io/x/consensus/types" distr "cosmossdk.io/x/distribution" distrkeeper "cosmossdk.io/x/distribution/keeper" @@ -265,7 +264,7 @@ func NewSimApp( keys := storetypes.NewKVStoreKeys( authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, - govtypes.StoreKey, consensusparamtypes.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey, + govtypes.StoreKey, consensustypes.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey, evidencetypes.StoreKey, circuittypes.StoreKey, authzkeeper.StoreKey, nftkeeper.StoreKey, group.StoreKey, pooltypes.StoreKey, accounts.StoreKey, epochstypes.StoreKey, @@ -288,7 +287,7 @@ func NewSimApp( cometService := runtime.NewContextAwareCometInfoService() // set the BaseApp's parameter store - app.ConsensusParamsKeeper = consensusparamkeeper.NewKeeper(appCodec, runtime.NewEnvironment(runtime.NewKVStoreService(keys[consensusparamtypes.StoreKey]), logger.With(log.ModuleKey, "x/consensus")), authtypes.NewModuleAddress(govtypes.ModuleName).String()) + app.ConsensusParamsKeeper = consensusparamkeeper.NewKeeper(appCodec, runtime.NewEnvironment(runtime.NewKVStoreService(keys[consensustypes.StoreKey]), logger.With(log.ModuleKey, "x/consensus")), authtypes.NewModuleAddress(govtypes.ModuleName).String()) bApp.SetParamStore(app.ConsensusParamsKeeper.ParamsStore) // add keepers @@ -519,7 +518,7 @@ func NewSimApp( group.ModuleName, upgradetypes.ModuleName, vestingtypes.ModuleName, - consensusparamtypes.ModuleName, + consensustypes.ModuleName, circuittypes.ModuleName, pooltypes.ModuleName, epochstypes.ModuleName, diff --git a/simapp/v2/app_di.go b/simapp/v2/app_di.go index 7cde4042f3c8..4e87bcc305df 100644 --- a/simapp/v2/app_di.go +++ b/simapp/v2/app_di.go @@ -12,7 +12,6 @@ import ( "cosmossdk.io/depinject" "cosmossdk.io/log" "cosmossdk.io/runtime/v2" - serverv2 "cosmossdk.io/server/v2" "cosmossdk.io/x/accounts" authkeeper "cosmossdk.io/x/auth/keeper" authzkeeper "cosmossdk.io/x/authz/keeper" @@ -92,7 +91,6 @@ func NewSimApp[T transaction.Tx]( logger log.Logger, viper *viper.Viper, ) *SimApp[T] { - viper.Set(serverv2.FlagHome, DefaultNodeHome) // TODO possibly set earlier when viper is created var ( app = &SimApp[T]{} appBuilder *runtime.AppBuilder[T] diff --git a/simapp/v2/app_test.go b/simapp/v2/app_test.go new file mode 100644 index 000000000000..a2ffdcee4ef5 --- /dev/null +++ b/simapp/v2/app_test.go @@ -0,0 +1,155 @@ +package simapp + +import ( + "context" + "crypto/sha256" + "encoding/json" + "testing" + "time" + + "github.com/cometbft/cometbft/types" + "github.com/spf13/viper" + "github.com/stretchr/testify/require" + + app2 "cosmossdk.io/core/app" + "cosmossdk.io/core/comet" + context2 "cosmossdk.io/core/context" + "cosmossdk.io/core/store" + "cosmossdk.io/core/transaction" + "cosmossdk.io/log" + sdkmath "cosmossdk.io/math" + serverv2 "cosmossdk.io/server/v2" + comettypes "cosmossdk.io/server/v2/cometbft/types" + "cosmossdk.io/store/v2/db" + authtypes "cosmossdk.io/x/auth/types" + banktypes "cosmossdk.io/x/bank/types" + + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/testutil/mock" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func NewTestApp(t *testing.T) (*SimApp[transaction.Tx], context.Context) { + t.Helper() + + logger := log.NewTestLogger(t) + + vp := viper.New() + vp.Set("store.app-db-backend", string(db.DBTypeGoLevelDB)) + vp.Set(serverv2.FlagHome, t.TempDir()) + + app := NewSimApp[transaction.Tx](logger, vp) + genesis := app.ModuleManager().DefaultGenesis() + + privVal := mock.NewPV() + pubKey, err := privVal.GetPubKey() + require.NoError(t, err) + + // create validator set with single validator + validator := types.NewValidator(pubKey, 1) + valSet := types.NewValidatorSet([]*types.Validator{validator}) + + // generate genesis account + senderPrivKey := secp256k1.GenPrivKey() + acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0) + balance := banktypes.Balance{ + Address: acc.GetAddress().String(), + Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(100000000000000))), + } + + genesis, err = simtestutil.GenesisStateWithValSet( + app.AppCodec(), + genesis, + valSet, + []authtypes.GenesisAccount{acc}, + balance, + ) + require.NoError(t, err) + + genesisBytes, err := json.Marshal(genesis) + require.NoError(t, err) + + st := app.GetStore().(comettypes.Store) + ci, err := st.LastCommitID() + require.NoError(t, err) + + bz := sha256.Sum256([]byte{}) + + ctx := context.Background() + + _, newState, err := app.InitGenesis( + ctx, + &app2.BlockRequest[transaction.Tx]{ + Time: time.Now(), + Hash: bz[:], + ChainId: "theChain", + AppHash: ci.Hash, + IsGenesis: true, + }, + genesisBytes, + nil, + ) + require.NoError(t, err) + + changes, err := newState.GetStateChanges() + require.NoError(t, err) + + _, err = st.Commit(&store.Changeset{Changes: changes}) + require.NoError(t, err) + + return app, ctx +} + +func MoveNextBlock(t *testing.T, app *SimApp[transaction.Tx], ctx context.Context) { + t.Helper() + + bz := sha256.Sum256([]byte{}) + + st := app.GetStore().(comettypes.Store) + ci, err := st.LastCommitID() + require.NoError(t, err) + + height, err := app.LoadLatestHeight() + require.NoError(t, err) + + // TODO: this is a hack to set the comet info in the context for distribution module dependency. + ctx = context.WithValue(ctx, context2.CometInfoKey, comet.Info{ + Evidence: nil, + ValidatorsHash: nil, + ProposerAddress: nil, + LastCommit: comet.CommitInfo{}, + }) + + _, newState, err := app.DeliverBlock( + ctx, + &app2.BlockRequest[transaction.Tx]{ + Height: height + 1, + Time: time.Now(), + Hash: bz[:], + AppHash: ci.Hash, + }) + require.NoError(t, err) + + changes, err := newState.GetStateChanges() + require.NoError(t, err) + + _, err = st.Commit(&store.Changeset{Changes: changes}) + require.NoError(t, err) +} + +func TestSimAppExportAndBlockedAddrs_WithOneBlockProduced(t *testing.T) { + app, ctx := NewTestApp(t) + + MoveNextBlock(t, app, ctx) + + _, err := app.ExportAppStateAndValidators(nil) + require.NoError(t, err) +} + +func TestSimAppExportAndBlockedAddrs_NoBlocksProduced(t *testing.T) { + app, _ := NewTestApp(t) + + _, err := app.ExportAppStateAndValidators(nil) + require.NoError(t, err) +} diff --git a/simapp/v2/export.go b/simapp/v2/export.go index 41b8d94e9e7a..5a1757b16535 100644 --- a/simapp/v2/export.go +++ b/simapp/v2/export.go @@ -1,10 +1,29 @@ package simapp import ( - servertypes "github.com/cosmos/cosmos-sdk/server/types" + "context" + + v2 "github.com/cosmos/cosmos-sdk/x/genutil/v2" ) -// ExportAppStateAndValidators exports the state of the application for a genesis file. -func (app *SimApp[T]) ExportAppStateAndValidators(forZeroHeight bool, jailAllowedAddrs, modulesToExport []string) (servertypes.ExportedApp, error) { - panic("not implemented") +// ExportAppStateAndValidators exports the state of the application for a genesis +// file. +func (app *SimApp[T]) ExportAppStateAndValidators(jailAllowedAddrs []string) (v2.ExportedApp, error) { + // as if they could withdraw from the start of the next block + ctx := context.Background() + + latestHeight, err := app.LoadLatestHeight() + if err != nil { + return v2.ExportedApp{}, err + } + + genesis, err := app.ExportGenesis(ctx, latestHeight) + if err != nil { + return v2.ExportedApp{}, err + } + + return v2.ExportedApp{ + AppState: genesis, + Height: int64(latestHeight), + }, nil } diff --git a/simapp/v2/go.mod b/simapp/v2/go.mod index fc9b70f451ca..209b5f547801 100644 --- a/simapp/v2/go.mod +++ b/simapp/v2/go.mod @@ -12,7 +12,7 @@ require ( cosmossdk.io/runtime/v2 v2.0.0-00010101000000-000000000000 cosmossdk.io/server/v2 v2.0.0-20240718121635-a877e3e8048a cosmossdk.io/server/v2/cometbft v0.0.0-00010101000000-000000000000 - cosmossdk.io/store/v2 v2.0.0 // indirect + cosmossdk.io/store/v2 v2.0.0 cosmossdk.io/tools/confix v0.0.0-00010101000000-000000000000 cosmossdk.io/x/accounts v0.0.0-20240226161501-23359a0b6d91 cosmossdk.io/x/auth v0.0.0-00010101000000-000000000000 @@ -32,7 +32,7 @@ require ( cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 cosmossdk.io/x/upgrade v0.0.0-20230613133644-0a778132a60f github.com/cometbft/cometbft v1.0.0-rc1 - github.com/cosmos/cosmos-db v1.0.2 + github.com/cosmos/cosmos-db v1.0.2 // indirect // this version is not used as it is always replaced by the latest Cosmos SDK version github.com/cosmos/cosmos-sdk v0.53.0 github.com/spf13/cobra v1.8.1 @@ -42,8 +42,6 @@ require ( google.golang.org/protobuf v1.34.2 ) -require cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect - require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect @@ -54,10 +52,11 @@ require ( cloud.google.com/go/iam v1.1.8 // indirect cloud.google.com/go/storage v1.42.0 // indirect cosmossdk.io/collections v0.4.0 // indirect + cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 // indirect cosmossdk.io/schema v0.1.1 // indirect - cosmossdk.io/server/v2/appmanager v0.0.0-00010101000000-000000000000 // indirect + cosmossdk.io/server/v2/appmanager v0.0.0-20240802110823-cffeedff643d // indirect cosmossdk.io/server/v2/stf v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 // indirect diff --git a/simapp/v2/simdv2/cmd/commands.go b/simapp/v2/simdv2/cmd/commands.go index ec9998f5c8f2..b4d13aa7a78c 100644 --- a/simapp/v2/simdv2/cmd/commands.go +++ b/simapp/v2/simdv2/cmd/commands.go @@ -3,9 +3,7 @@ package cmd import ( "errors" "fmt" - "io" - dbm "github.com/cosmos/cosmos-db" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -26,17 +24,21 @@ import ( "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/client/rpc" "github.com/cosmos/cosmos-sdk/server" - servertypes "github.com/cosmos/cosmos-sdk/server/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/genutil" genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + genutilv2 "github.com/cosmos/cosmos-sdk/x/genutil/v2" + v2 "github.com/cosmos/cosmos-sdk/x/genutil/v2/cli" ) func newApp[T transaction.Tx]( logger log.Logger, viper *viper.Viper, ) serverv2.AppI[T] { - return serverv2.AppI[T](simapp.NewSimApp[T](logger, viper)) + viper.Set(serverv2.FlagHome, simapp.DefaultNodeHome) + + return serverv2.AppI[T]( + simapp.NewSimApp[T](logger, viper)) } func initRootCmd[T transaction.Tx]( @@ -84,25 +86,11 @@ func initRootCmd[T transaction.Tx]( // genesisCommand builds genesis-related `simd genesis` command. Users may provide application specific commands as a parameter func genesisCommand[T transaction.Tx]( moduleManager *runtimev2.MM[T], - appExport func(logger log.Logger, - height int64, - forZeroHeight bool, - jailAllowedAddrs []string, - viper *viper.Viper, - modulesToExport []string, - ) (servertypes.ExportedApp, error), + appExport genutilv2.AppExporter, cmds ...*cobra.Command, ) *cobra.Command { - compatAppExporter := func(logger log.Logger, db dbm.DB, traceWriter io.Writer, height int64, forZeroHeight bool, jailAllowedAddrs []string, appOpts servertypes.AppOptions, modulesToExport []string) (servertypes.ExportedApp, error) { - viperAppOpts, ok := appOpts.(*viper.Viper) - if !ok { - return servertypes.ExportedApp{}, errors.New("appOpts is not viper.Viper") - } - - return appExport(logger, height, forZeroHeight, jailAllowedAddrs, viperAppOpts, modulesToExport) - } + cmd := v2.Commands(moduleManager.Modules()[genutiltypes.ModuleName].(genutil.AppModule), moduleManager, appExport) - cmd := genutilcli.Commands(moduleManager.Modules()[genutiltypes.ModuleName].(genutil.AppModule), moduleManager, compatAppExporter) for _, subCmd := range cmds { cmd.AddCommand(subCmd) } @@ -159,26 +147,25 @@ func txCommand() *cobra.Command { func appExport[T transaction.Tx]( logger log.Logger, height int64, - forZeroHeight bool, jailAllowedAddrs []string, viper *viper.Viper, - modulesToExport []string, -) (servertypes.ExportedApp, error) { +) (genutilv2.ExportedApp, error) { // overwrite the FlagInvCheckPeriod viper.Set(server.FlagInvCheckPeriod, 1) + viper.Set(serverv2.FlagHome, simapp.DefaultNodeHome) var simApp *simapp.SimApp[T] if height != -1 { simApp = simapp.NewSimApp[T](logger, viper) if err := simApp.LoadHeight(uint64(height)); err != nil { - return servertypes.ExportedApp{}, err + return genutilv2.ExportedApp{}, err } } else { simApp = simapp.NewSimApp[T](logger, viper) } - return simApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs, modulesToExport) + return simApp.ExportAppStateAndValidators(jailAllowedAddrs) } var _ transaction.Codec[transaction.Tx] = &genericTxDecoder[transaction.Tx]{} diff --git a/x/genutil/v2/cli/commands.go b/x/genutil/v2/cli/commands.go new file mode 100644 index 000000000000..93052d1e4907 --- /dev/null +++ b/x/genutil/v2/cli/commands.go @@ -0,0 +1,47 @@ +package cli + +import ( + "encoding/json" + + "github.com/spf13/cobra" + + banktypes "cosmossdk.io/x/bank/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/x/genutil" + "github.com/cosmos/cosmos-sdk/x/genutil/client/cli" + genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + v2 "github.com/cosmos/cosmos-sdk/x/genutil/v2" +) + +type genesisMM interface { + DefaultGenesis() map[string]json.RawMessage + ValidateGenesis(genesisData map[string]json.RawMessage) error +} + +// Commands adds core sdk's sub-commands into genesis command. +func Commands(genutilModule genutil.AppModule, genMM genesisMM, appExport v2.AppExporter) *cobra.Command { + return CommandsWithCustomMigrationMap(genutilModule, genMM, appExport, genutiltypes.MigrationMap{}) +} + +// CommandsWithCustomMigrationMap adds core sdk's sub-commands into genesis command with custom migration map. +// This custom migration map can be used by the application to add its own migration map. +func CommandsWithCustomMigrationMap(genutilModule genutil.AppModule, genMM genesisMM, appExport v2.AppExporter, migrationMap genutiltypes.MigrationMap) *cobra.Command { + cmd := &cobra.Command{ + Use: "genesis", + Short: "Application's genesis-related subcommands", + DisableFlagParsing: false, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + cmd.AddCommand( + cli.GenTxCmd(genMM, banktypes.GenesisBalancesIterator{}), + cli.MigrateGenesisCmd(migrationMap), + cli.CollectGenTxsCmd(genutilModule.GenTxValidator()), + cli.ValidateGenesisCmd(genMM), + cli.AddGenesisAccountCmd(), + ExportCmd(appExport), + ) + + return cmd +} diff --git a/x/genutil/v2/cli/export.go b/x/genutil/v2/cli/export.go new file mode 100644 index 000000000000..c19a02f870e3 --- /dev/null +++ b/x/genutil/v2/cli/export.go @@ -0,0 +1,106 @@ +package cli + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "os" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/version" + genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + v2 "github.com/cosmos/cosmos-sdk/x/genutil/v2" +) + +const ( + flagHeight = "height" + flagJailAllowedAddrs = "jail-allowed-addrs" +) + +// ExportCmd dumps app state to JSON. +func ExportCmd(appExporter v2.AppExporter) *cobra.Command { + cmd := &cobra.Command{ + Use: "export", + Short: "Export state to JSON", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, _ []string) error { + config := client.GetConfigFromCmd(cmd) + viper := client.GetViperFromCmd(cmd) + logger := client.GetLoggerFromCmd(cmd) + + if _, err := os.Stat(config.GenesisFile()); os.IsNotExist(err) { + return err + } + + if appExporter == nil { + if _, err := fmt.Fprintln(cmd.ErrOrStderr(), "WARNING: App exporter not defined. Returning genesis file."); err != nil { + return err + } + + // Open file in read-only mode so we can copy it to stdout. + // It is possible that the genesis file is large, + // so we don't need to read it all into memory + // before we stream it out. + f, err := os.OpenFile(config.GenesisFile(), os.O_RDONLY, 0) + if err != nil { + return err + } + defer f.Close() + + if _, err := io.Copy(cmd.OutOrStdout(), f); err != nil { + return err + } + + return nil + } + + height, _ := cmd.Flags().GetInt64(flagHeight) + jailAllowedAddrs, _ := cmd.Flags().GetStringSlice(flagJailAllowedAddrs) + outputDocument, _ := cmd.Flags().GetString(flags.FlagOutputDocument) + + exported, err := appExporter(logger, height, jailAllowedAddrs, viper) + if err != nil { + return fmt.Errorf("error exporting state: %w", err) + } + + appGenesis, err := genutiltypes.AppGenesisFromFile(config.GenesisFile()) + if err != nil { + return err + } + + // set current binary version + appGenesis.AppName = version.AppName + appGenesis.AppVersion = version.Version + + appGenesis.AppState = exported.AppState + appGenesis.InitialHeight = exported.Height + + out, err := json.Marshal(appGenesis) + if err != nil { + return err + } + + if outputDocument == "" { + // Copy the entire genesis file to stdout. + _, err := io.Copy(cmd.OutOrStdout(), bytes.NewReader(out)) + return err + } + + if err = appGenesis.SaveAs(outputDocument); err != nil { + return err + } + + return nil + }, + } + + cmd.Flags().Int64(flagHeight, -1, "Export state from a particular height (-1 means latest height)") + cmd.Flags().StringSlice(flagJailAllowedAddrs, []string{}, "Comma-separated list of operator addresses of jailed validators to unjail") + cmd.Flags().String(flags.FlagOutputDocument, "", "Exported state is written to the given file instead of STDOUT") + + return cmd +} diff --git a/x/genutil/v2/types.go b/x/genutil/v2/types.go new file mode 100644 index 000000000000..1b94c8bbc9be --- /dev/null +++ b/x/genutil/v2/types.go @@ -0,0 +1,27 @@ +package v2 + +import ( + "encoding/json" + + "github.com/spf13/viper" + + "cosmossdk.io/log" +) + +// AppExporter is a function that dumps all app state to +// JSON-serializable structure and returns the current validator set. +type AppExporter func( + logger log.Logger, + height int64, + jailAllowedAddrs []string, + viper *viper.Viper, +) (ExportedApp, error) + +// ExportedApp represents an exported app state, along with +// validators, consensus params and latest app height. +type ExportedApp struct { + // AppState is the application state as JSON. + AppState json.RawMessage + // Height is the app's latest block height. + Height int64 +} diff --git a/x/staking/genesis.go b/x/staking/genesis.go index edb7548fc7fd..fcd758952e0d 100644 --- a/x/staking/genesis.go +++ b/x/staking/genesis.go @@ -1,6 +1,7 @@ package staking import ( + "context" "fmt" cmttypes "github.com/cometbft/cometbft/types" @@ -14,7 +15,7 @@ import ( ) // WriteValidators returns a slice of bonded genesis validators. -func WriteValidators(ctx sdk.Context, keeper *keeper.Keeper) (vals []cmttypes.GenesisValidator, returnErr error) { +func WriteValidators(ctx context.Context, keeper *keeper.Keeper) (vals []cmttypes.GenesisValidator, returnErr error) { err := keeper.LastValidatorPower.Walk(ctx, nil, func(key []byte, _ gogotypes.Int64Value) (bool, error) { validator, err := keeper.GetValidator(ctx, key) if err != nil { From f8ab520ad7850ef416a253922ca7af82b9e22967 Mon Sep 17 00:00:00 2001 From: Cosmos SDK <113218068+github-prbot@users.noreply.github.com> Date: Fri, 16 Aug 2024 14:09:01 +0200 Subject: [PATCH 04/11] chore: fix spelling errors (#21327) Co-authored-by: github-merge-queue <118344674+github-merge-queue@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c4f1c1a03b79..da3187c88568 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ The version matrix below shows which versions of the Cosmos SDK, modules and lib #### Core Dependencies Core dependencies are the core libraries that an application may depend on. -Core dependencies not mentionned here as compatible across all maintained SDK versions. +Core dependencies not mentioned here as compatible across all maintained SDK versions. | Cosmos SDK | cosmossdk.io/core | cosmossdk.io/api | cosmossdk.io/x/tx | | ---------- | ----------------- | ---------------- | ----------------- | From 825e81b688a13dfb1559ad386c5862816398905d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Toledano?= Date: Fri, 16 Aug 2024 14:55:45 +0200 Subject: [PATCH 05/11] refactor(x/mint): v0.52 audit x/mint (#21301) --- x/mint/CHANGELOG.md | 2 +- x/mint/README.md | 4 +- x/mint/epoch_hooks.go | 2 +- x/mint/keeper/genesis_test.go | 16 +++---- x/mint/keeper/grpc_query_test.go | 4 +- x/mint/keeper/keeper_test.go | 10 +++-- x/mint/keeper/migrator.go | 2 +- x/mint/keeper/migrator_test.go | 33 ++++++++++++++ x/mint/module.go | 2 +- x/mint/simulation/genesis_test.go | 4 +- x/mint/simulation/proposals.go | 2 +- x/mint/types/minter_test.go | 72 +++++++++++++++++++++++++++++++ x/mint/types/params.go | 2 +- x/mint/types/params_test.go | 43 ++++++++++++++++++ 14 files changed, 173 insertions(+), 25 deletions(-) create mode 100644 x/mint/keeper/migrator_test.go diff --git a/x/mint/CHANGELOG.md b/x/mint/CHANGELOG.md index 014ac8759a9d..285fab6b5c3b 100644 --- a/x/mint/CHANGELOG.md +++ b/x/mint/CHANGELOG.md @@ -35,6 +35,6 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### API Breaking Changes * [#20363](https://github.com/cosmos/cosmos-sdk/pull/20363) Deprecated InflationCalculationFn in favor of MintFn, `keeper.DefaultMintFn` wrapper must be used in order to continue using it in `NewAppModule`. This is not breaking for depinject users, as both `MintFn` and `InflationCalculationFn` are accepted. -* [#19367](https://github.com/cosmos/cosmos-sdk/pull/19398) `appmodule.Environment` is received on the Keeper to get access to different application services +* [#19367](https://github.com/cosmos/cosmos-sdk/pull/19398) `appmodule.Environment` is received on the Keeper to get access to different application services. ### Bug Fixes diff --git a/x/mint/README.md b/x/mint/README.md index 849164f04131..5a885208eca1 100644 --- a/x/mint/README.md +++ b/x/mint/README.md @@ -109,7 +109,7 @@ related to minting (in the `data` field) * Minter: `0x00 -> ProtocolBuffer(minter)` ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/ace7bca105a8d5363782cfd19c6f169b286cd3b2/x/mint/proto/cosmos/mint/v1beta1/mint.proto#L11-L29 +https://github.com/cosmos/cosmos-sdk/blob/release/v0.52.x/x/mint/proto/cosmos/mint/v1beta1/mint.proto#L11-L29 ``` ### Params @@ -122,7 +122,7 @@ A value of `0` indicates an unlimited supply. * Params: `mint/params -> legacy_amino(params)` ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/7068d0da52d954430054768b2c56aff44666933b/x/mint/proto/cosmos/mint/v1beta1/mint.proto#L26-L68 +https://github.com/cosmos/cosmos-sdk/blob/release/v0.52.x/x/mint/proto/cosmos/mint/v1beta1/mint.proto#L31-L73 ``` ## Epoch minting diff --git a/x/mint/epoch_hooks.go b/x/mint/epoch_hooks.go index 2a63245036e6..9c1ae6ff1c04 100644 --- a/x/mint/epoch_hooks.go +++ b/x/mint/epoch_hooks.go @@ -35,6 +35,6 @@ func (am AppModule) BeforeEpochStart(ctx context.Context, epochIdentifier string } // AfterEpochEnd is a noop -func (am AppModule) AfterEpochEnd(ctx context.Context, epochIdentifier string, epochNumber int64) error { +func (am AppModule) AfterEpochEnd(_ context.Context, _ string, _ int64) error { return nil } diff --git a/x/mint/keeper/genesis_test.go b/x/mint/keeper/genesis_test.go index 754055066c27..56b1171a5dcb 100644 --- a/x/mint/keeper/genesis_test.go +++ b/x/mint/keeper/genesis_test.go @@ -75,21 +75,21 @@ func (s *GenesisTestSuite) TestImportExportGenesis() { ) err := s.keeper.InitGenesis(s.sdkCtx, s.accountKeeper, genesisState) - s.Require().NoError(err) + s.NoError(err) minter, err := s.keeper.Minter.Get(s.sdkCtx) - s.Require().Equal(genesisState.Minter, minter) - s.Require().NoError(err) + s.Equal(genesisState.Minter, minter) + s.NoError(err) invalidCtx := testutil.DefaultContextWithDB(s.T(), s.key, storetypes.NewTransientStoreKey("transient_test")) _, err = s.keeper.Minter.Get(invalidCtx.Ctx) - s.Require().ErrorIs(err, collections.ErrNotFound) + s.ErrorIs(err, collections.ErrNotFound) params, err := s.keeper.Params.Get(s.sdkCtx) - s.Require().Equal(genesisState.Params, params) - s.Require().NoError(err) + s.Equal(genesisState.Params, params) + s.NoError(err) genesisState2, err := s.keeper.ExportGenesis(s.sdkCtx) - s.Require().NoError(err) - s.Require().Equal(genesisState, genesisState2) + s.NoError(err) + s.Equal(genesisState, genesisState2) } diff --git a/x/mint/keeper/grpc_query_test.go b/x/mint/keeper/grpc_query_test.go index f2f80689b759..eb83b895a7e1 100644 --- a/x/mint/keeper/grpc_query_test.go +++ b/x/mint/keeper/grpc_query_test.go @@ -34,7 +34,7 @@ type MintTestSuite struct { func (suite *MintTestSuite) SetupTest() { encCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, mint.AppModule{}) key := storetypes.NewKVStoreKey(types.StoreKey) - storeService := runtime.NewEnvironment(runtime.NewKVStoreService(key), log.NewNopLogger()) + env := runtime.NewEnvironment(runtime.NewKVStoreService(key), log.NewNopLogger()) testCtx := testutil.DefaultContextWithDB(suite.T(), key, storetypes.NewTransientStoreKey("transient_test")) suite.ctx = testCtx.Ctx @@ -48,7 +48,7 @@ func (suite *MintTestSuite) SetupTest() { suite.mintKeeper = keeper.NewKeeper( encCfg.Codec, - storeService, + env, stakingKeeper, accountKeeper, bankKeeper, diff --git a/x/mint/keeper/keeper_test.go b/x/mint/keeper/keeper_test.go index 012917777901..215ac12b4ddd 100644 --- a/x/mint/keeper/keeper_test.go +++ b/x/mint/keeper/keeper_test.go @@ -111,7 +111,7 @@ func (s *KeeperTestSuite) TestDefaultMintFn() { err = s.mintKeeper.DefaultMintFn(types.DefaultInflationCalculationFn)(s.ctx, s.mintKeeper.Environment, &minter, "block", 0) s.NoError(err) - // set a maxsupply and call again + // set a maxSupply and call again. totalSupply will be bigger than maxSupply. params, err := s.mintKeeper.Params.Get(s.ctx) s.NoError(err) params.MaxSupply = math.NewInt(10000000000) @@ -122,14 +122,16 @@ func (s *KeeperTestSuite) TestDefaultMintFn() { s.NoError(err) // modify max supply to be almost reached - // we tried to mint 2059stake but we only get to mint 2000stake + // modify blocksPerYear to mint 2053 coins per block + // we tried to mint 2053stake, but we only get to mint 2000stake params, err = s.mintKeeper.Params.Get(s.ctx) s.NoError(err) params.MaxSupply = math.NewInt(100000000000 + 2000) + params.BlocksPerYear = 2434275 err = s.mintKeeper.Params.Set(s.ctx, params) s.NoError(err) - s.bankKeeper.EXPECT().MintCoins(s.ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(792)))).Return(nil) + s.bankKeeper.EXPECT().MintCoins(s.ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(2000)))).Return(nil) s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(s.ctx, types.ModuleName, authtypes.FeeCollectorName, gomock.Any()).Return(nil) err = s.mintKeeper.DefaultMintFn(types.DefaultInflationCalculationFn)(s.ctx, s.mintKeeper.Environment, &minter, "block", 0) @@ -143,7 +145,7 @@ func (s *KeeperTestSuite) TestBeginBlocker() { s.bankKeeper.EXPECT().MintCoins(s.ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(792)))).Return(nil) s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(s.ctx, types.ModuleName, authtypes.FeeCollectorName, gomock.Any()).Return(nil) - // get minter (it should get modified aftwerwards) + // get minter (it should get modified afterwards) minter, err := s.mintKeeper.Minter.Get(s.ctx) s.NoError(err) diff --git a/x/mint/keeper/migrator.go b/x/mint/keeper/migrator.go index a2dc25e2e365..199757c1f1a2 100644 --- a/x/mint/keeper/migrator.go +++ b/x/mint/keeper/migrator.go @@ -22,7 +22,7 @@ func NewMigrator(k Keeper) Migrator { // version 2. Specifically, it takes the parameters that are currently stored // and managed by the x/params modules and stores them directly into the x/mint // module state. -func (m Migrator) Migrate1to2(ctx context.Context) error { +func (m Migrator) Migrate1to2(_ context.Context) error { return nil } diff --git a/x/mint/keeper/migrator_test.go b/x/mint/keeper/migrator_test.go new file mode 100644 index 000000000000..ce585da36c60 --- /dev/null +++ b/x/mint/keeper/migrator_test.go @@ -0,0 +1,33 @@ +package keeper_test + +import ( + "cosmossdk.io/math" + "cosmossdk.io/x/mint/keeper" + "cosmossdk.io/x/mint/types" +) + +func (s *KeeperTestSuite) TestMigrator_Migrate2to3() { + migrator := keeper.NewMigrator(s.mintKeeper) + + params, err := s.mintKeeper.Params.Get(s.ctx) + s.NoError(err) + + err = migrator.Migrate2to3(s.ctx) + s.NoError(err) + + migratedParams, err := s.mintKeeper.Params.Get(s.ctx) + s.NoError(err) + s.Equal(params, migratedParams) + + params.MaxSupply = math.NewInt(1000000) + err = s.mintKeeper.Params.Set(s.ctx, params) + s.NoError(err) + + err = migrator.Migrate2to3(s.ctx) + s.NoError(err) + + migratedParams, err = s.mintKeeper.Params.Get(s.ctx) + s.NoError(err) + s.NotEqual(params, migratedParams) + s.Equal(migratedParams, types.DefaultParams()) +} diff --git a/x/mint/module.go b/x/mint/module.go index b0f6b2a14ec9..6607b371c16d 100644 --- a/x/mint/module.go +++ b/x/mint/module.go @@ -49,7 +49,7 @@ type AppModule struct { } // NewAppModule creates a new AppModule object. -// If the mintFn argument is nil, then the SDK's default minting function will be used. +// If the mintFn argument is nil, then the default minting function will be used. func NewAppModule( cdc codec.Codec, keeper keeper.Keeper, diff --git a/x/mint/simulation/genesis_test.go b/x/mint/simulation/genesis_test.go index ba31c32e4b2a..a9ca7c6185fb 100644 --- a/x/mint/simulation/genesis_test.go +++ b/x/mint/simulation/genesis_test.go @@ -20,7 +20,7 @@ import ( ) // TestRandomizedGenState tests the normal scenario of applying RandomizedGenState. -// Abonormal scenarios are not tested here. +// Abnormal scenarios are not tested here. func TestRandomizedGenState(t *testing.T) { cdcOpts := codectestutil.CodecOptions{} encCfg := moduletestutil.MakeTestEncodingConfig(cdcOpts, mint.AppModule{}) @@ -84,8 +84,6 @@ func TestRandomizedGenState1(t *testing.T) { } for _, tt := range tests { - tt := tt - require.Panicsf(t, func() { simulation.RandomizedGenState(&tt.simState) }, tt.panicMsg) } } diff --git a/x/mint/simulation/proposals.go b/x/mint/simulation/proposals.go index 570bf203efcc..eb0b140f5e3e 100644 --- a/x/mint/simulation/proposals.go +++ b/x/mint/simulation/proposals.go @@ -21,7 +21,7 @@ const ( OpWeightMsgUpdateParams = "op_weight_msg_update_params" ) -// ProposalMsgs defines the module weighted proposals' contents +// ProposalMsgs defines the module's weighted proposals contents func ProposalMsgs() []simtypes.WeightedProposalMsg { return []simtypes.WeightedProposalMsg{ simulation.NewWeightedProposalMsgX( diff --git a/x/mint/types/minter_test.go b/x/mint/types/minter_test.go index 8bff2334995a..7e18a3e1b173 100644 --- a/x/mint/types/minter_test.go +++ b/x/mint/types/minter_test.go @@ -110,6 +110,78 @@ func TestValidateMinter(t *testing.T) { } } +func TestIsEqualMinter(t *testing.T) { + tests := []struct { + name string + a Minter + b Minter + equal bool + }{ + { + name: "equal minters", + a: Minter{ + Inflation: math.LegacyNewDec(10), + AnnualProvisions: math.LegacyNewDec(10), + Data: []byte("data"), + }, + b: Minter{ + Inflation: math.LegacyNewDec(10), + AnnualProvisions: math.LegacyNewDec(10), + Data: []byte("data"), + }, + equal: true, + }, + { + name: "different inflation", + a: Minter{ + Inflation: math.LegacyNewDec(10), + AnnualProvisions: math.LegacyNewDec(10), + Data: []byte("data"), + }, + b: Minter{ + Inflation: math.LegacyNewDec(100), + AnnualProvisions: math.LegacyNewDec(10), + Data: []byte("data"), + }, + equal: false, + }, + { + name: "different Annual Provisions", + a: Minter{ + Inflation: math.LegacyNewDec(10), + AnnualProvisions: math.LegacyNewDec(10), + Data: []byte("data"), + }, + b: Minter{ + Inflation: math.LegacyNewDec(10), + AnnualProvisions: math.LegacyNewDec(100), + Data: []byte("data"), + }, + equal: false, + }, + { + name: "different data", + a: Minter{ + Inflation: math.LegacyNewDec(10), + AnnualProvisions: math.LegacyNewDec(10), + Data: []byte("data"), + }, + b: Minter{ + Inflation: math.LegacyNewDec(10), + AnnualProvisions: math.LegacyNewDec(10), + Data: []byte("no data"), + }, + equal: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + equal := tt.a.IsEqual(tt.b) + require.Equal(t, tt.equal, equal) + }) + } +} + // Benchmarking :) // previously using math.Int operations: // BenchmarkBlockProvision-4 5000000 220 ns/op diff --git a/x/mint/types/params.go b/x/mint/types/params.go index dfc00348b3db..af4a01d2daed 100644 --- a/x/mint/types/params.go +++ b/x/mint/types/params.go @@ -31,7 +31,7 @@ func DefaultParams() Params { InflationMax: math.LegacyNewDecWithPrec(5, 2), InflationMin: math.LegacyNewDecWithPrec(0, 2), GoalBonded: math.LegacyNewDecWithPrec(67, 2), - BlocksPerYear: uint64(60 * 60 * 8766 / 5), // assuming 5 second block times + BlocksPerYear: uint64(60 * 60 * 8766 / 5), // assuming 5-second block times MaxSupply: math.ZeroInt(), // assuming zero is infinite } } diff --git a/x/mint/types/params_test.go b/x/mint/types/params_test.go index b43c6212d058..25f34ee02571 100644 --- a/x/mint/types/params_test.go +++ b/x/mint/types/params_test.go @@ -110,3 +110,46 @@ func TestValidate(t *testing.T) { err = params.Validate() require.Error(t, err) } + +func Test_validateInflationFields(t *testing.T) { + fns := []func(dec math.LegacyDec) error{ + validateInflationRateChange, + validateInflationMax, + validateInflationMin, + validateGoalBonded, + } + tests := []struct { + name string + v math.LegacyDec + wantErr bool + }{ + { + name: "valid", + v: math.LegacyNewDecWithPrec(12, 2), + }, + { + name: "nil", + v: math.LegacyDec{}, + wantErr: true, + }, + { + name: "negative", + v: math.LegacyNewDec(-1), + wantErr: true, + }, + { + name: "greater than one", + v: math.LegacyOneDec().Add(math.LegacyOneDec()), + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + for _, fn := range fns { + if err := fn(tt.v); (err != nil) != tt.wantErr { + t.Errorf("validateInflationRateChange() error = %v, wantErr %v", err, tt.wantErr) + } + } + }) + } +} From 6276b015bbab06cf563a7e6ec5d8bbc85f7708cc Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 16 Aug 2024 15:03:24 +0200 Subject: [PATCH 06/11] chore: fix all lint issue since golangci-lint bump (#21326) --- .github/workflows/lint.yml | 1 + client/v2/autocli/keyring/keyring.go | 4 +++- log/CHANGELOG.md | 4 ++++ log/logger.go | 4 +++- simapp/simd/cmd/root_di.go | 2 +- tests/integration/slashing/slashing_test.go | 2 +- tests/systemtests/system.go | 2 +- tools/cosmovisor/cmd/cosmovisor/version_test.go | 2 +- x/auth/keeper/grpc_query.go | 8 ++++---- x/authz/keeper/grpc_query.go | 8 ++++---- x/distribution/keeper/grpc_query.go | 4 ++-- x/distribution/keeper/msg_server.go | 2 +- x/evidence/keeper/grpc_query.go | 2 +- x/feegrant/keeper/grpc_query.go | 4 ++-- x/gov/keeper/msg_server.go | 2 +- x/gov/keeper/proposal.go | 4 ++-- x/group/client/cli/tx.go | 2 +- x/group/keeper/keeper.go | 2 +- x/slashing/keeper/signing_info.go | 2 +- x/upgrade/keeper/abci_test.go | 4 ++-- 20 files changed, 37 insertions(+), 28 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4b4ce5a76bff..846bde4c75a9 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -24,6 +24,7 @@ jobs: id: git_diff with: PATTERNS: | + **/*.mk Makefile **/Makefile .golangci.yml diff --git a/client/v2/autocli/keyring/keyring.go b/client/v2/autocli/keyring/keyring.go index a838b12d8455..70c2d27d08ed 100644 --- a/client/v2/autocli/keyring/keyring.go +++ b/client/v2/autocli/keyring/keyring.go @@ -10,7 +10,9 @@ import ( // KeyringContextKey is the key used to store the keyring in the context. // The keyring must be wrapped using the KeyringImpl. -var KeyringContextKey struct{} +var KeyringContextKey keyringContextKey + +type keyringContextKey struct{} var _ Keyring = &KeyringImpl{} diff --git a/log/CHANGELOG.md b/log/CHANGELOG.md index 2b8c5ba0da53..c9f2475683e9 100644 --- a/log/CHANGELOG.md +++ b/log/CHANGELOG.md @@ -22,6 +22,10 @@ Each entry must include the Github issue reference in the following format: ## [Unreleased] +## [v1.4.1](https://github.com/cosmos/cosmos-sdk/releases/tag/log/v1.4.1) - 2024-08-16 + +* [#21326](https://github.com/cosmos/cosmos-sdk/pull/21326) Avoid context key collision. + ## [v1.4.0](https://github.com/cosmos/cosmos-sdk/releases/tag/log/v1.4.0) - 2024-08-07 * [#21045](https://github.com/cosmos/cosmos-sdk/pull/21045) Add `WithContext` method implementations to make all returned loggers compatible with `cosmossdk.io/core/log.Logger` (v1) without a direct dependency. diff --git a/log/logger.go b/log/logger.go index 38802ed88e73..8a27538e80ff 100644 --- a/log/logger.go +++ b/log/logger.go @@ -30,7 +30,9 @@ func init() { const ModuleKey = "module" // ContextKey is used to store the logger in the context. -var ContextKey struct{} +var ContextKey contextKey + +type contextKey struct{} // Logger is the Cosmos SDK logger interface. // It extends cosmossdk.io/core/log.Logger to return a child logger. diff --git a/simapp/simd/cmd/root_di.go b/simapp/simd/cmd/root_di.go index 640ebdf1c5fd..863835f7d979 100644 --- a/simapp/simd/cmd/root_di.go +++ b/simapp/simd/cmd/root_di.go @@ -19,10 +19,10 @@ import ( "cosmossdk.io/x/auth/tx" authtxconfig "cosmossdk.io/x/auth/tx/config" "cosmossdk.io/x/auth/types" - nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/config" + nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/server" diff --git a/tests/integration/slashing/slashing_test.go b/tests/integration/slashing/slashing_test.go index bec39e2449f8..36d9ec53e493 100644 --- a/tests/integration/slashing/slashing_test.go +++ b/tests/integration/slashing/slashing_test.go @@ -114,5 +114,5 @@ func TestSlashingMsgs(t *testing.T) { headerInfo = header.Info{Height: app.LastBlockHeight() + 1} _, _, err = sims.SignCheckDeliver(t, txConfig, app.BaseApp, headerInfo, []sdk.Msg{unjailMsg}, "", []uint64{0}, []uint64{1}, false, false, priv1) require.Error(t, err) - require.True(t, errors.Is(types.ErrValidatorNotJailed, err)) + require.True(t, errors.Is(err, types.ErrValidatorNotJailed)) } diff --git a/tests/systemtests/system.go b/tests/systemtests/system.go index bc8f4351b33d..1c39cc150df5 100644 --- a/tests/systemtests/system.go +++ b/tests/systemtests/system.go @@ -247,7 +247,7 @@ func (s *SystemUnderTest) AwaitUpgradeInfo(t *testing.T) { case err == nil: found = true case !os.IsNotExist(err): - t.Fatalf(err.Error()) + t.Fatal(err.Error()) } }) time.Sleep(s.blockTime / 2) diff --git a/tools/cosmovisor/cmd/cosmovisor/version_test.go b/tools/cosmovisor/cmd/cosmovisor/version_test.go index 8f51ea47dafb..9f4cfb896072 100644 --- a/tools/cosmovisor/cmd/cosmovisor/version_test.go +++ b/tools/cosmovisor/cmd/cosmovisor/version_test.go @@ -20,7 +20,7 @@ func TestVersionCommand_Error(t *testing.T) { rootCmd.SetOut(out) rootCmd.SetErr(out) - ctx := context.WithValue(context.Background(), log.ContextKey, logger) + ctx := context.WithValue(context.Background(), log.ContextKey, logger) //nolint:staticcheck // temporary issue in dependency require.Error(t, rootCmd.ExecuteContext(ctx)) require.Contains(t, out.String(), "DAEMON_NAME is not set") diff --git a/x/auth/keeper/grpc_query.go b/x/auth/keeper/grpc_query.go index 6025b6f932b3..4305358c304f 100644 --- a/x/auth/keeper/grpc_query.go +++ b/x/auth/keeper/grpc_query.go @@ -86,7 +86,7 @@ func (s queryServer) Account(ctx context.Context, req *types.QueryAccountRequest any, err := codectypes.NewAnyWithValue(account) if err != nil { - return nil, status.Errorf(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } return &types.QueryAccountResponse{Account: any}, nil @@ -124,7 +124,7 @@ func (s queryServer) ModuleAccounts(ctx context.Context, req *types.QueryModuleA } any, err := codectypes.NewAnyWithValue(account) if err != nil { - return nil, status.Errorf(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } modAccounts = append(modAccounts, any) } @@ -150,7 +150,7 @@ func (s queryServer) ModuleAccountByName(ctx context.Context, req *types.QueryMo } any, err := codectypes.NewAnyWithValue(account) if err != nil { - return nil, status.Errorf(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } return &types.QueryModuleAccountByNameResponse{Account: any}, nil @@ -234,7 +234,7 @@ func (s queryServer) AccountInfo(ctx context.Context, req *types.QueryAccountInf if pubKey != nil { pkAny, err = codectypes.NewAnyWithValue(account.GetPubKey()) if err != nil { - return nil, status.Errorf(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } } diff --git a/x/authz/keeper/grpc_query.go b/x/authz/keeper/grpc_query.go index 4d73afac4e6c..89cb8ac67d65 100644 --- a/x/authz/keeper/grpc_query.go +++ b/x/authz/keeper/grpc_query.go @@ -48,7 +48,7 @@ func (k Keeper) Grants(ctx context.Context, req *authz.QueryGrantsRequest) (*aut authorizationAny, err := codectypes.NewAnyWithValue(authorization) if err != nil { - return nil, status.Errorf(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } return &authz.QueryGrantsResponse{ Grants: []*authz.Grant{{ @@ -70,7 +70,7 @@ func (k Keeper) Grants(ctx context.Context, req *authz.QueryGrantsRequest) (*aut authorizationAny, err := codectypes.NewAnyWithValue(auth1) if err != nil { - return nil, status.Errorf(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } return &authz.Grant{ Authorization: authorizationAny, @@ -111,7 +111,7 @@ func (k Keeper) GranterGrants(ctx context.Context, req *authz.QueryGranterGrants any, err := codectypes.NewAnyWithValue(auth1) if err != nil { - return nil, status.Errorf(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } grantee := firstAddressFromGrantStoreKey(key) @@ -166,7 +166,7 @@ func (k Keeper) GranteeGrants(ctx context.Context, req *authz.QueryGranteeGrants authorizationAny, err := codectypes.NewAnyWithValue(auth1) if err != nil { - return nil, status.Errorf(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } granterAddr, err := k.authKeeper.AddressCodec().BytesToString(granter) diff --git a/x/distribution/keeper/grpc_query.go b/x/distribution/keeper/grpc_query.go index de8657276fbe..5337ec58c342 100644 --- a/x/distribution/keeper/grpc_query.go +++ b/x/distribution/keeper/grpc_query.go @@ -119,7 +119,7 @@ func (k Querier) ValidatorOutstandingRewards(ctx context.Context, req *types.Que } if validator == nil { - return nil, errors.Wrapf(types.ErrNoValidatorExists, req.ValidatorAddress) + return nil, errors.Wrap(types.ErrNoValidatorExists, req.ValidatorAddress) } rewards, err := k.Keeper.ValidatorOutstandingRewards.Get(ctx, valAdr) @@ -151,7 +151,7 @@ func (k Querier) ValidatorCommission(ctx context.Context, req *types.QueryValida } if validator == nil { - return nil, errors.Wrapf(types.ErrNoValidatorExists, req.ValidatorAddress) + return nil, errors.Wrap(types.ErrNoValidatorExists, req.ValidatorAddress) } commission, err := k.ValidatorsAccumulatedCommission.Get(ctx, valAdr) if err != nil && !errors.IsOf(err, collections.ErrNotFound) { diff --git a/x/distribution/keeper/msg_server.go b/x/distribution/keeper/msg_server.go index 2b405f9b053a..0a4b9f32ca49 100644 --- a/x/distribution/keeper/msg_server.go +++ b/x/distribution/keeper/msg_server.go @@ -189,7 +189,7 @@ func (k msgServer) DepositValidatorRewardsPool(ctx context.Context, msg *types.M } if validator == nil { - return nil, errors.Wrapf(types.ErrNoValidatorExists, msg.ValidatorAddress) + return nil, errors.Wrap(types.ErrNoValidatorExists, msg.ValidatorAddress) } // Allocate tokens from the distribution module to the validator, which are diff --git a/x/evidence/keeper/grpc_query.go b/x/evidence/keeper/grpc_query.go index a665c820ce31..854dbbd33846 100644 --- a/x/evidence/keeper/grpc_query.go +++ b/x/evidence/keeper/grpc_query.go @@ -53,7 +53,7 @@ func (k Querier) Evidence(ctx context.Context, req *types.QueryEvidenceRequest) evidenceAny, err := codectypes.NewAnyWithValue(msg) if err != nil { - return nil, status.Errorf(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } return &types.QueryEvidenceResponse{Evidence: evidenceAny}, nil diff --git a/x/feegrant/keeper/grpc_query.go b/x/feegrant/keeper/grpc_query.go index 0bc3db1839cc..f5ff7df04370 100644 --- a/x/feegrant/keeper/grpc_query.go +++ b/x/feegrant/keeper/grpc_query.go @@ -35,7 +35,7 @@ func (q Keeper) Allowance(ctx context.Context, req *feegrant.QueryAllowanceReque feeAllowance, err := q.GetAllowance(ctx, granterAddr, granteeAddr) if err != nil { - return nil, status.Errorf(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } msg, ok := feeAllowance.(proto.Message) @@ -45,7 +45,7 @@ func (q Keeper) Allowance(ctx context.Context, req *feegrant.QueryAllowanceReque feeAllowanceAny, err := codectypes.NewAnyWithValue(msg) if err != nil { - return nil, status.Errorf(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } return &feegrant.QueryAllowanceResponse{ diff --git a/x/gov/keeper/msg_server.go b/x/gov/keeper/msg_server.go index ec3e33a44c3d..5c7b623f045f 100644 --- a/x/gov/keeper/msg_server.go +++ b/x/gov/keeper/msg_server.go @@ -383,7 +383,7 @@ func (k msgServer) SudoExec(ctx context.Context, msg *v1.MsgSudoExec) (*v1.MsgSu if err := k.BranchService.Execute(ctx, func(ctx context.Context) error { // TODO add route check here if err := k.MsgRouterService.CanInvoke(ctx, sdk.MsgTypeURL(sudoedMsg)); err != nil { - return errors.Wrapf(govtypes.ErrInvalidProposal, err.Error()) + return errors.Wrap(govtypes.ErrInvalidProposal, err.Error()) } msgResp, err = k.MsgRouterService.InvokeUntyped(ctx, sudoedMsg) diff --git a/x/gov/keeper/proposal.go b/x/gov/keeper/proposal.go index 4f378e6fcab9..d095d7053ae6 100644 --- a/x/gov/keeper/proposal.go +++ b/x/gov/keeper/proposal.go @@ -83,9 +83,9 @@ func (k Keeper) SubmitProposal(ctx context.Context, messages []sdk.Msg, metadata if !bytes.Equal(signers[0], k.GetGovernanceAccount(ctx).GetAddress()) { addr, err := k.authKeeper.AddressCodec().BytesToString(signers[0]) if err != nil { - return v1.Proposal{}, errorsmod.Wrapf(types.ErrInvalidSigner, err.Error()) + return v1.Proposal{}, errorsmod.Wrap(types.ErrInvalidSigner, err.Error()) } - return v1.Proposal{}, errorsmod.Wrapf(types.ErrInvalidSigner, addr) + return v1.Proposal{}, errorsmod.Wrap(types.ErrInvalidSigner, addr) } if err := k.MsgRouterService.CanInvoke(ctx, sdk.MsgTypeURL(msg)); err != nil { diff --git a/x/group/client/cli/tx.go b/x/group/client/cli/tx.go index 52c998ebed60..0578b24dfff4 100644 --- a/x/group/client/cli/tx.go +++ b/x/group/client/cli/tx.go @@ -498,7 +498,7 @@ metadata example: // Since the --from flag is not required on this CLI command, we // ignore it, and just use the 1st proposer in the JSON file. - if prop.Proposers == nil || len(prop.Proposers) == 0 { + if len(prop.Proposers) == 0 { return errors.New("no proposers specified in proposal") } err = cmd.Flags().Set(flags.FlagFrom, prop.Proposers[0]) diff --git a/x/group/keeper/keeper.go b/x/group/keeper/keeper.go index 667c62ab0bc1..b1fc76f920cc 100644 --- a/x/group/keeper/keeper.go +++ b/x/group/keeper/keeper.go @@ -455,7 +455,7 @@ func (k Keeper) TallyProposalsAtVPEnd(ctx context.Context) error { // is greater than defined MaxMetadataLen in the module configuration func (k Keeper) assertMetadataLength(metadata, description string) error { if uint64(len(metadata)) > k.config.MaxMetadataLen { - return errors.ErrMetadataTooLong.Wrapf(description) + return errors.ErrMetadataTooLong.Wrap(description) } return nil } diff --git a/x/slashing/keeper/signing_info.go b/x/slashing/keeper/signing_info.go index 352590e24e73..64e4b7421066 100644 --- a/x/slashing/keeper/signing_info.go +++ b/x/slashing/keeper/signing_info.go @@ -31,7 +31,7 @@ func (k Keeper) JailUntil(ctx context.Context, consAddr sdk.ConsAddress, jailTim if err != nil { return types.ErrNoSigningInfoFound.Wrapf("could not convert consensus address to string. Error: %s", err.Error()) } - return types.ErrNoSigningInfoFound.Wrapf(fmt.Sprintf("cannot jail validator with consensus address %s that does not have any signing information", addr)) + return types.ErrNoSigningInfoFound.Wrapf("cannot jail validator with consensus address %s that does not have any signing information", addr) } signInfo.JailedUntil = jailTime diff --git a/x/upgrade/keeper/abci_test.go b/x/upgrade/keeper/abci_test.go index 4360a37797c1..c55d47fe0e73 100644 --- a/x/upgrade/keeper/abci_test.go +++ b/x/upgrade/keeper/abci_test.go @@ -148,7 +148,7 @@ func TestRequireFutureBlock(t *testing.T) { s := setupTest(t, 10, map[int64]bool{}) err := s.keeper.ScheduleUpgrade(s.ctx, types.Plan{Name: "test", Height: s.ctx.HeaderInfo().Height - 1}) require.Error(t, err) - require.True(t, errors.Is(sdkerrors.ErrInvalidRequest, err), err) + require.True(t, errors.Is(err, sdkerrors.ErrInvalidRequest), err) } func TestDoHeightUpgrade(t *testing.T) { @@ -223,7 +223,7 @@ func TestCantApplySameUpgradeTwice(t *testing.T) { t.Log("Verify an executed upgrade \"test\" can't be rescheduled") err = s.keeper.ScheduleUpgrade(s.ctx, types.Plan{Name: "test", Height: height}) require.Error(t, err) - require.True(t, errors.Is(sdkerrors.ErrInvalidRequest, err), err) + require.True(t, errors.Is(err, sdkerrors.ErrInvalidRequest), err) } func TestNoSpuriousUpgrades(t *testing.T) { From 54df7585a2488de0d0cba6c7a93eb28edff436f4 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 16 Aug 2024 15:26:30 +0200 Subject: [PATCH 07/11] fix(x/authz): bring back msg response in `DispatchActions` (#21044) --- x/authz/CHANGELOG.md | 1 + x/authz/keeper/keeper.go | 13 ++++++++++++- x/authz/keeper/keeper_test.go | 30 +++++++++++++++++++++++------- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/x/authz/CHANGELOG.md b/x/authz/CHANGELOG.md index cf61dc2da57b..db05ded12f05 100644 --- a/x/authz/CHANGELOG.md +++ b/x/authz/CHANGELOG.md @@ -37,6 +37,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### API Breaking Changes +* [#21044](https://github.com/cosmos/cosmos-sdk/pull/21044) `k.DispatchActions` returns a slice of byte slices of proto marshaled anys instead of a slice of byte slices of `sdk.Result.Data`. * [#20502](https://github.com/cosmos/cosmos-sdk/pull/20502) `Accept` on the `Authorization` interface now expects the authz environment in the `context.Context`. This is already done when `Accept` is called by `k.DispatchActions`, but should be done manually if `Accept` is called directly. * [#19783](https://github.com/cosmos/cosmos-sdk/pull/19783) Removes the use of Accounts String() method * `NewMsgExec`, `NewMsgGrant` and `NewMsgRevoke` now takes strings as arguments instead of `sdk.AccAddress`. diff --git a/x/authz/keeper/keeper.go b/x/authz/keeper/keeper.go index 4818ca9506f3..e2708a55ff31 100644 --- a/x/authz/keeper/keeper.go +++ b/x/authz/keeper/keeper.go @@ -7,6 +7,7 @@ import ( "time" gogoproto "github.com/cosmos/gogoproto/proto" + gogoprotoany "github.com/cosmos/gogoproto/types/any" "cosmossdk.io/core/appmodule" corecontext "cosmossdk.io/core/context" @@ -145,10 +146,20 @@ func (k Keeper) DispatchActions(ctx context.Context, grantee sdk.AccAddress, msg } // no need to use the branch service here, as if the transaction fails, the transaction will be reverted - _, err = k.MsgRouterService.InvokeUntyped(ctx, msg) + resp, err := k.MsgRouterService.InvokeUntyped(ctx, msg) if err != nil { return nil, fmt.Errorf("failed to execute message %d; message %v: %w", i, msg, err) } + + msgRespAny, err := gogoprotoany.NewAnyWithCacheWithValue(resp) + if err != nil { + return nil, fmt.Errorf("failed to create any for response %d; message %s: %w", i, gogoproto.MessageName(msg), err) + } + + results[i], err = gogoproto.Marshal(msgRespAny) + if err != nil { + return nil, fmt.Errorf("failed to marshal response %d; message %s: %w", i, gogoproto.MessageName(msg), err) + } } return results, nil diff --git a/x/authz/keeper/keeper_test.go b/x/authz/keeper/keeper_test.go index 72bd049b1c79..dcfd710fc264 100644 --- a/x/authz/keeper/keeper_test.go +++ b/x/authz/keeper/keeper_test.go @@ -4,6 +4,8 @@ import ( "testing" "time" + gogoproto "github.com/cosmos/gogoproto/proto" + gogoprotoany "github.com/cosmos/gogoproto/types/any" "github.com/golang/mock/gomock" "github.com/stretchr/testify/suite" @@ -245,12 +247,13 @@ func (s *TestSuite) TestDispatchAction() { a := banktypes.NewSendAuthorization(coins100, nil, s.accountKeeper.AddressCodec()) testCases := []struct { - name string - req authz.MsgExec - expectErr bool - errMsg string - preRun func() sdk.Context - postRun func() + name string + req authz.MsgExec + expectErr bool + errMsg string + expectResp string + preRun func() sdk.Context + postRun func() }{ { "expect error authorization not found", @@ -263,6 +266,7 @@ func (s *TestSuite) TestDispatchAction() { }), true, "authorization not found", + "", func() sdk.Context { // remove any existing authorizations err := s.authzKeeper.DeleteGrant(s.ctx, granteeAddr, granterAddr, bankSendAuthMsgType) @@ -282,6 +286,7 @@ func (s *TestSuite) TestDispatchAction() { }), true, "authorization expired", + "", func() sdk.Context { e := now.AddDate(0, 0, 1) err := s.authzKeeper.SaveGrant(s.ctx, granteeAddr, granterAddr, a, &e) @@ -301,6 +306,7 @@ func (s *TestSuite) TestDispatchAction() { }), true, "requested amount is more than spend limit", + "", func() sdk.Context { e := now.AddDate(0, 1, 0) err := s.authzKeeper.SaveGrant(s.ctx, granteeAddr, granterAddr, a, &e) @@ -320,6 +326,7 @@ func (s *TestSuite) TestDispatchAction() { }), false, "", + "/cosmos.bank.v1beta1.MsgSendResponse", func() sdk.Context { e := now.AddDate(0, 1, 0) err := s.authzKeeper.SaveGrant(s.ctx, granteeAddr, granterAddr, a, &e) @@ -346,6 +353,7 @@ func (s *TestSuite) TestDispatchAction() { }), false, "", + "/cosmos.bank.v1beta1.MsgSendResponse", func() sdk.Context { e := now.AddDate(0, 1, 0) err := s.authzKeeper.SaveGrant(s.ctx, granteeAddr, granterAddr, a, &e) @@ -372,7 +380,15 @@ func (s *TestSuite) TestDispatchAction() { require.Contains(err.Error(), tc.errMsg) } else { require.NoError(err) - require.NotNil(result) + require.NotEmpty(result) + // unmarshal the result + for _, res := range result { + var msgRes gogoprotoany.Any + err := gogoproto.Unmarshal(res, &msgRes) + require.NoError(err) + require.NotNil(msgRes) + require.Equal(msgRes.TypeUrl, tc.expectResp) + } } tc.postRun() }) From e57a9370fafa768dafa4e619463ae4a45bb6878e Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Fri, 16 Aug 2024 10:35:38 -0400 Subject: [PATCH 08/11] feat(schema): specify JSON mapping (#21243) --- schema/kind.go | 112 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 83 insertions(+), 29 deletions(-) diff --git a/schema/kind.go b/schema/kind.go index 44d18e100ffd..e5457420149b 100644 --- a/schema/kind.go +++ b/schema/kind.go @@ -9,81 +9,135 @@ import ( ) // Kind represents the basic type of a field in an object. -// Each kind defines the types of go values which should be accepted -// by listeners and generated by decoders when providing entity updates. +// Each kind defines the following encodings: +// Go Encoding: the golang type which should be accepted by listeners and +// generated by decoders when providing entity updates. +// JSON Encoding: the JSON encoding which should be used when encoding the field to JSON. +// When there is some non-determinism in an encoding, kinds should specify what +// values they accept and also what is the canonical, deterministic encoding which +// should be preferably emitted by serializers. type Kind int const ( // InvalidKind indicates that an invalid type. InvalidKind Kind = iota - // StringKind is a string type and values of this type must be of the go type string - // containing valid UTF-8 and cannot contain null characters. + // StringKind is a string type. + // Go Encoding: UTF-8 string with no null characters. + // JSON Encoding: string StringKind - // BytesKind is a bytes type and values of this type must be of the go type []byte. + // BytesKind is a bytes type. + // Go Encoding: []byte + // JSON Encoding: base64 encoded string, canonical values should be encoded with standard encoding and padding. + // Either standard or URL encoding with or without padding should be accepted. BytesKind - // Int8Kind is an int8 type and values of this type must be of the go type int8. + // Int8Kind represents an 8-bit signed integer. + // Go Encoding: int8 + // JSON Encoding: number Int8Kind - // Uint8Kind is a uint8 type and values of this type must be of the go type uint8. + // Uint8Kind represents an 8-bit unsigned integer. + // Go Encoding: uint8 + // JSON Encoding: number Uint8Kind - // Int16Kind is an int16 type and values of this type must be of the go type int16. + // Int16Kind represents a 16-bit signed integer. + // Go Encoding: int16 + // JSON Encoding: number Int16Kind - // Uint16Kind is a uint16 type and values of this type must be of the go type uint16. + // Uint16Kind represents a 16-bit unsigned integer. + // Go Encoding: uint16 + // JSON Encoding: number Uint16Kind - // Int32Kind is an int32 type and values of this type must be of the go type int32. + // Int32Kind represents a 32-bit signed integer. + // Go Encoding: int32 + // JSON Encoding: number Int32Kind - // Uint32Kind is a uint32 type and values of this type must be of the go type uint32. + // Uint32Kind represents a 32-bit unsigned integer. + // Go Encoding: uint32 + // JSON Encoding: number Uint32Kind - // Int64Kind is an int64 type and values of this type must be of the go type int64. + // Int64Kind represents a 64-bit signed integer. + // Go Encoding: int64 + // JSON Encoding: base10 integer string which matches the IntegerFormat regex + // The canonical encoding should include no leading zeros. Int64Kind - // Uint64Kind is a uint64 type and values of this type must be of the go type uint64. + // Uint64Kind represents a 64-bit unsigned integer. + // Go Encoding: uint64 + // JSON Encoding: base10 integer string which matches the IntegerFormat regex + // Canonically encoded values should include no leading zeros. Uint64Kind - // IntegerStringKind represents an arbitrary precision integer number. Values of this type must - // be of the go type string and formatted as base10 integers, specifically matching to - // the IntegerFormat regex. + // IntegerStringKind represents an arbitrary precision integer number. + // Go Encoding: string which matches the IntegerFormat regex + // JSON Encoding: base10 integer string + // Canonically encoded values should include no leading zeros. IntegerStringKind - // DecimalStringKind represents an arbitrary precision decimal or integer number. Values of this type - // must be of the go type string and match the DecimalFormat regex. + // DecimalStringKind represents an arbitrary precision decimal or integer number. + // Go Encoding: string which matches the DecimalFormat regex + // JSON Encoding: base10 decimal string + // Canonically encoded values should include no leading zeros or trailing zeros, + // and exponential notation with a lowercase 'e' should be used for any numbers + // with an absolute value less than or equal to 1e-6 or greater than or equal to 1e6. DecimalStringKind - // BoolKind is a boolean type and values of this type must be of the go type bool. + // BoolKind represents a boolean true or false value. + // Go Encoding: bool + // JSON Encoding: boolean BoolKind - // TimeKind is a time type and values of this type must be of the go type time.Time. + // TimeKind represents a nanosecond precision UNIX time value (with zero representing January 1, 1970 UTC). + // Its valid range is +/- 2^63 (the range of a 64-bit signed integer). + // Go Encoding: time.Time + // JSON Encoding: Any value IS0 8601 time stamp should be accepted. + // Canonical values should be encoded with UTC time zone Z, nanoseconds should + // be encoded with no trailing zeros, and T time values should always be present + // even at 00:00:00. TimeKind - // DurationKind is a duration type and values of this type must be of the go type time.Duration. + // DurationKind represents the elapsed time between two nanosecond precision time values. + // Its valid range is +/- 2^63 (the range of a 64-bit signed integer). + // Go Encoding: time.Duration + // JSON Encoding: the number of seconds as a decimal string with no trailing zeros followed by + // a lowercase 's' character to represent seconds. DurationKind - // Float32Kind is a float32 type and values of this type must be of the go type float32. + // Float32Kind represents an IEEE-754 32-bit floating point number. + // Go Encoding: float32 + // JSON Encoding: number Float32Kind - // Float64Kind is a float64 type and values of this type must be of the go type float64. + // Float64Kind represents an IEEE-754 64-bit floating point number. + // Go Encoding: float64 + // JSON Encoding: number Float64Kind - // AddressKind represents an account address and must be of type []byte. Addresses usually have a - // human-readable rendering, such as bech32, and tooling should provide a way for apps to define a - // string encoder for friendly user-facing display. + // AddressKind represents an account address which is represented by a variable length array of bytes. + // Addresses usually have a human-readable rendering, such as bech32, and tooling should provide + // a way for apps to define a string encoder for friendly user-facing display. + // Go Encoding: []byte + // JSON Encoding: addresses should be encoded as strings using the human-readable address renderer + // provided to the JSON encoder. AddressKind - // EnumKind is an enum type and values of this type must be of the go type string. + // EnumKind represents a value of an enum type. // Fields of this type are expected to set the EnumType field in the field definition to the enum // definition. + // Go Encoding: string + // JSON Encoding: string EnumKind - // JSONKind is a JSON type and values of this type should be of go type json.RawMessage and represent - // valid JSON. + // JSONKind represents arbitrary JSON data. + // Go Encoding: json.RawMessage + // JSON Encoding: any valid JSON value JSONKind ) From 651868a177d00c423e3086e6c255bf729ccd25f3 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Sat, 17 Aug 2024 09:33:15 +0200 Subject: [PATCH 09/11] docs: rename app v2 to app di when talking about runtime v0 (#21329) --- UPGRADING.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 7b8761e0c6a9..7eb30257dafa 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -67,9 +67,9 @@ clientCtx = clientCtx. + WithValidatorPrefix("cosmosvaloper") ``` -**When using `depinject` / `app v2`, the client codecs can be provided directly from application config.** +**When using `depinject` / `app_di`, the client codecs can be provided directly from application config.** -Refer to SimApp `root_v2.go` and `root.go` for an example with an app v2 and a legacy app. +Refer to SimApp `root_di.go` and `root.go` for an example with an app di and a legacy app. Additionally, a simplification of the start command leads to the following change: @@ -467,7 +467,7 @@ for more info. A `SetPreBlocker` method has been added to BaseApp. This is essential for BaseApp to run `PreBlock` which runs before begin blocker other modules, and allows to modify consensus parameters, and the changes are visible to the following state machine logics. Read more about other use cases [here](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-068-preblock.md). -`depinject` / app v2 users need to add `x/upgrade` in their `app_config.go` / `app.yml`: +`depinject` / app di users need to add `x/upgrade` in their `app_config.go` / `app.yml`: ```diff + PreBlockers: []string{ @@ -575,7 +575,7 @@ The following modules `NewKeeper` function now take a `KVStoreService` instead o * `x/slashing` * `x/upgrade` -**Users using `depinject` / app v2 do not need any changes, this is abstracted for them.** +**Users using `depinject` / app di do not need any changes, this is abstracted for them.** Users manually wiring their chain need to use the `runtime.NewKVStoreService` method to create a `KVStoreService` from a `StoreKey`: @@ -592,7 +592,7 @@ app.ConsensusParamsKeeper = consensusparamkeeper.NewKeeper( Replace all your CometBFT logger imports by `cosmossdk.io/log`. -Additionally, `depinject` / app v2 users must now supply a logger through the main `depinject.Supply` function instead of passing it to `appBuilder.Build`. +Additionally, `depinject` / app di users must now supply a logger through the main `depinject.Supply` function instead of passing it to `appBuilder.Build`. ```diff appConfig = depinject.Configs( @@ -616,7 +616,7 @@ User manually wiring their chain need to add the logger argument when creating t Previously, the `ModuleBasics` was a global variable that was used to register all modules' `AppModuleBasic` implementation. The global variable has been removed and the basic module manager can be now created from the module manager. -This is automatically done for `depinject` / app v2 users, however for supplying different app module implementation, pass them via `depinject.Supply` in the main `AppConfig` (`app_config.go`): +This is automatically done for `depinject` / app di users, however for supplying different app module implementation, pass them via `depinject.Supply` in the main `AppConfig` (`app_config.go`): ```go depinject.Supply( From ee04cee0cafbf806dab9fcc21f00270f21fb6aea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Francisco=20L=C3=B3pez?= Date: Sat, 17 Aug 2024 21:49:32 +0200 Subject: [PATCH 10/11] refactor(x/distribution): audit QA (#21316) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Randy Grok <98407738+randygrok@users.noreply.github.com> Co-authored-by: marbar3778 Co-authored-by: Cosmos SDK <113218068+github-prbot@users.noreply.github.com> Co-authored-by: github-merge-queue <118344674+github-merge-queue@users.noreply.github.com> Co-authored-by: Julián Toledano Co-authored-by: Julien Robert Co-authored-by: Aaron Craelius --- x/distribution/README.md | 8 +- x/distribution/keeper/allocation_test.go | 128 +++++++++++++++++++++++ x/distribution/keeper/keeper.go | 2 +- x/distribution/keeper/validator.go | 12 ++- x/distribution/migrations/v4/migrate.go | 16 +-- 5 files changed, 149 insertions(+), 17 deletions(-) diff --git a/x/distribution/README.md b/x/distribution/README.md index 03e1e5baff21..d49b309f50fe 100644 --- a/x/distribution/README.md +++ b/x/distribution/README.md @@ -186,7 +186,7 @@ it can be updated with governance or the address with authority. * Params: `0x09 | ProtocolBuffer(Params)` ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/distribution/v1beta1/distribution.proto#L12-L42 +https://github.com/cosmos/cosmos-sdk/blob/release/v0.52.x/x/distribution/proto/cosmos/distribution/v1beta1/distribution.proto#L12-L44 ``` ## Begin Block @@ -272,7 +272,7 @@ The withdraw address cannot be any of the module accounts. These accounts are bl Response: ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/distribution/v1beta1/tx.proto#L49-L60 +https://github.com/cosmos/cosmos-sdk/blob/release/v0.52.x/x/distribution/proto/cosmos/distribution/v1beta1/tx.proto#L62-L73 ``` ```go @@ -324,7 +324,7 @@ The final calculated stake is equivalent to the actual staked coins in the deleg Response: ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/distribution/v1beta1/tx.proto#L66-L77 +https://github.com/cosmos/cosmos-sdk/blob/release/v0.52.x/x/distribution/proto/cosmos/distribution/v1beta1/tx.proto#L79-L90 ``` ### WithdrawValidatorCommission @@ -368,7 +368,7 @@ func (k Keeper) initializeDelegation(ctx context.Context, val sdk.ValAddress, de Distribution module params can be updated through `MsgUpdateParams`, which can be done using governance proposal and the signer will always be gov module account address. ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/distribution/v1beta1/tx.proto#L133-L147 +https://github.com/cosmos/cosmos-sdk/blob/release/v0.52.x/x/distribution/proto/cosmos/distribution/v1beta1/tx.proto#L159:L172 ``` The message handling can fail if: diff --git a/x/distribution/keeper/allocation_test.go b/x/distribution/keeper/allocation_test.go index f319ad456cbe..21d788c97843 100644 --- a/x/distribution/keeper/allocation_test.go +++ b/x/distribution/keeper/allocation_test.go @@ -375,3 +375,131 @@ func TestAllocateTokensTruncation(t *testing.T) { require.NoError(t, err) require.True(t, val2OutstandingRewards.Rewards.IsValid()) } + +func TestAllocateTokensToValidatorWithoutCommission(t *testing.T) { + ctrl := gomock.NewController(t) + key := storetypes.NewKVStoreKey(disttypes.StoreKey) + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + cdcOpts := codectestutil.CodecOptions{} + encCfg := moduletestutil.MakeTestEncodingConfig(cdcOpts, distribution.AppModule{}) + ctx := testCtx.Ctx.WithHeaderInfo(header.Info{Time: time.Now()}) + + bankKeeper := distrtestutil.NewMockBankKeeper(ctrl) + stakingKeeper := distrtestutil.NewMockStakingKeeper(ctrl) + accountKeeper := distrtestutil.NewMockAccountKeeper(ctrl) + + env := runtime.NewEnvironment(runtime.NewKVStoreService(key), coretesting.NewNopLogger()) + + valCodec := address.NewBech32Codec("cosmosvaloper") + + accountKeeper.EXPECT().GetModuleAddress("distribution").Return(distrAcc.GetAddress()) + stakingKeeper.EXPECT().ValidatorAddressCodec().Return(valCodec).AnyTimes() + + authorityAddr, err := cdcOpts.GetAddressCodec().BytesToString(authtypes.NewModuleAddress("gov")) + require.NoError(t, err) + + distrKeeper := keeper.NewKeeper( + encCfg.Codec, + env, + accountKeeper, + bankKeeper, + stakingKeeper, + testCometService, + "fee_collector", + authorityAddr, + ) + + // create validator with 0% commission + operatorAddr, err := stakingKeeper.ValidatorAddressCodec().BytesToString(valConsPk0.Address()) + require.NoError(t, err) + val, err := distrtestutil.CreateValidator(valConsPk0, operatorAddr, math.NewInt(100)) + require.NoError(t, err) + val.Commission = stakingtypes.NewCommission(math.LegacyNewDec(0), math.LegacyNewDec(0), math.LegacyNewDec(0)) + stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk0)).Return(val, nil).AnyTimes() + + // allocate tokens + tokens := sdk.DecCoins{ + {Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDec(10)}, + } + require.NoError(t, distrKeeper.AllocateTokensToValidator(ctx, val, tokens)) + + // check commission + var expectedCommission sdk.DecCoins = nil + + valBz, err := valCodec.StringToBytes(val.GetOperator()) + require.NoError(t, err) + + valCommission, err := distrKeeper.ValidatorsAccumulatedCommission.Get(ctx, valBz) + require.NoError(t, err) + require.Equal(t, expectedCommission, valCommission.Commission) + + // check current rewards + expectedRewards := tokens + + currentRewards, err := distrKeeper.ValidatorCurrentRewards.Get(ctx, valBz) + require.NoError(t, err) + require.Equal(t, expectedRewards, currentRewards.Rewards) +} + +func TestAllocateTokensWithZeroTokens(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + key := storetypes.NewKVStoreKey(disttypes.StoreKey) + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + cdcOpts := codectestutil.CodecOptions{} + encCfg := moduletestutil.MakeTestEncodingConfig(cdcOpts, distribution.AppModule{}) + ctx := testCtx.Ctx.WithHeaderInfo(header.Info{Time: time.Now()}) + + bankKeeper := distrtestutil.NewMockBankKeeper(ctrl) + stakingKeeper := distrtestutil.NewMockStakingKeeper(ctrl) + accountKeeper := distrtestutil.NewMockAccountKeeper(ctrl) + + env := runtime.NewEnvironment(runtime.NewKVStoreService(key), coretesting.NewNopLogger()) + + valCodec := address.NewBech32Codec("cosmosvaloper") + + accountKeeper.EXPECT().GetModuleAddress("distribution").Return(distrAcc.GetAddress()) + stakingKeeper.EXPECT().ValidatorAddressCodec().Return(valCodec).AnyTimes() + + authorityAddr, err := cdcOpts.GetAddressCodec().BytesToString(authtypes.NewModuleAddress("gov")) + require.NoError(t, err) + + distrKeeper := keeper.NewKeeper( + encCfg.Codec, + env, + accountKeeper, + bankKeeper, + stakingKeeper, + testCometService, + "fee_collector", + authorityAddr, + ) + + // create validator with 50% commission + operatorAddr, err := stakingKeeper.ValidatorAddressCodec().BytesToString(valConsPk0.Address()) + require.NoError(t, err) + val, err := distrtestutil.CreateValidator(valConsPk0, operatorAddr, math.NewInt(100)) + require.NoError(t, err) + val.Commission = stakingtypes.NewCommission(math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDec(0)) + stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk0)).Return(val, nil).AnyTimes() + + // allocate zero tokens + tokens := sdk.DecCoins{} + require.NoError(t, distrKeeper.AllocateTokensToValidator(ctx, val, tokens)) + + // check commission + var expected sdk.DecCoins = nil + + valBz, err := valCodec.StringToBytes(val.GetOperator()) + require.NoError(t, err) + + valCommission, err := distrKeeper.ValidatorsAccumulatedCommission.Get(ctx, valBz) + require.NoError(t, err) + require.Equal(t, expected, valCommission.Commission) + + // check current rewards + currentRewards, err := distrKeeper.ValidatorCurrentRewards.Get(ctx, valBz) + require.NoError(t, err) + require.Equal(t, expected, currentRewards.Rewards) +} diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index 0c3238353eba..0ded047e93d6 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -46,7 +46,7 @@ type Keeper struct { DelegatorStartingInfo collections.Map[collections.Pair[sdk.ValAddress, sdk.AccAddress], types.DelegatorStartingInfo] // ValidatorsAccumulatedCommission key: valAddr | value: ValidatorAccumulatedCommission ValidatorsAccumulatedCommission collections.Map[sdk.ValAddress, types.ValidatorAccumulatedCommission] - // ValidatorOutstandingRewards key: valAddr | value: ValidatorOustandingRewards + // ValidatorOutstandingRewards key: valAddr | value: ValidatorOutstandingRewards ValidatorOutstandingRewards collections.Map[sdk.ValAddress, types.ValidatorOutstandingRewards] // ValidatorHistoricalRewards key: valAddr+period | value: ValidatorHistoricalRewards ValidatorHistoricalRewards collections.Map[collections.Pair[sdk.ValAddress, uint64], types.ValidatorHistoricalRewards] diff --git a/x/distribution/keeper/validator.go b/x/distribution/keeper/validator.go index 812fbbe5086b..0c9246e0136a 100644 --- a/x/distribution/keeper/validator.go +++ b/x/distribution/keeper/validator.go @@ -13,6 +13,10 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +const ( + maxReferenceCount = 2 +) + // initialize rewards for a new validator func (k Keeper) initializeValidator(ctx context.Context, val sdk.ValidatorI) error { valBz, err := k.stakingKeeper.ValidatorAddressCodec().StringToBytes(val.GetOperator()) @@ -126,8 +130,8 @@ func (k Keeper) incrementReferenceCount(ctx context.Context, valAddr sdk.ValAddr } historical.ReferenceCount++ - if historical.ReferenceCount > 2 { - panic("reference count should never exceed 2") + if historical.ReferenceCount > maxReferenceCount { + return fmt.Errorf("reference count should never exceed %d", maxReferenceCount) } return k.ValidatorHistoricalRewards.Set(ctx, collections.Join(valAddr, period), historical) } @@ -140,7 +144,7 @@ func (k Keeper) decrementReferenceCount(ctx context.Context, valAddr sdk.ValAddr } if historical.ReferenceCount == 0 { - panic("cannot set negative reference count") + return fmt.Errorf("cannot set negative reference count") } historical.ReferenceCount-- if historical.ReferenceCount == 0 { @@ -152,7 +156,7 @@ func (k Keeper) decrementReferenceCount(ctx context.Context, valAddr sdk.ValAddr func (k Keeper) updateValidatorSlashFraction(ctx context.Context, valAddr sdk.ValAddress, fraction math.LegacyDec) error { if fraction.GT(math.LegacyOneDec()) || fraction.IsNegative() { - panic(fmt.Sprintf("fraction must be >=0 and <=1, current fraction: %v", fraction)) + return fmt.Errorf("fraction must be >=0 and <=1, current fraction: %v", fraction) } headerinfo := k.HeaderService.HeaderInfo(ctx) diff --git a/x/distribution/migrations/v4/migrate.go b/x/distribution/migrations/v4/migrate.go index 783dc91218c7..1ecfd4a2d8f6 100644 --- a/x/distribution/migrations/v4/migrate.go +++ b/x/distribution/migrations/v4/migrate.go @@ -16,16 +16,16 @@ import ( var OldProposerKey = []byte{0x01} // MigrateStore removes the last proposer from store. -func MigrateStore(ctx context.Context, env appmodule.Environment, cdc codec.BinaryCodec) error { - store := env.KVStoreService.OpenKVStore(ctx) - return store.Delete(OldProposerKey) +func MigrateStore(ctx context.Context, env appmodule.Environment, _ codec.BinaryCodec) error { + kvStore := env.KVStoreService.OpenKVStore(ctx) + return kvStore.Delete(OldProposerKey) } // GetPreviousProposerConsAddr returns the proposer consensus address for the // current block. func GetPreviousProposerConsAddr(ctx context.Context, storeService store.KVStoreService, cdc codec.BinaryCodec) (sdk.ConsAddress, error) { - store := storeService.OpenKVStore(ctx) - bz, err := store.Get(OldProposerKey) + kvStore := storeService.OpenKVStore(ctx) + bz, err := kvStore.Get(OldProposerKey) if err != nil { return nil, err } @@ -43,9 +43,9 @@ func GetPreviousProposerConsAddr(ctx context.Context, storeService store.KVStore return addrValue.GetValue(), nil } -// set the proposer public key for this block +// SetPreviousProposerConsAddr set the proposer public key for this block. func SetPreviousProposerConsAddr(ctx context.Context, storeService store.KVStoreService, cdc codec.BinaryCodec, consAddr sdk.ConsAddress) error { - store := storeService.OpenKVStore(ctx) + kvStore := storeService.OpenKVStore(ctx) bz := cdc.MustMarshal(&gogotypes.BytesValue{Value: consAddr}) - return store.Set(OldProposerKey, bz) + return kvStore.Set(OldProposerKey, bz) } From cd929906198a638103d35a1905fd238de6df4a87 Mon Sep 17 00:00:00 2001 From: Oksana <107276324+Ocheretovich@users.noreply.github.com> Date: Sun, 18 Aug 2024 17:04:13 +0300 Subject: [PATCH 11/11] chore: update link in disclaimer (#21339) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index da3187c88568..2741dc837fdd 100644 --- a/README.md +++ b/README.md @@ -105,4 +105,4 @@ Module Dependencies are the modules that an application may depend on and which ## Disambiguation -This Cosmos SDK project is not related to the [React-Cosmos](https://github.com/react-cosmos/react-cosmos) project (yet). Many thanks to Evan Coury and Ovidiu (@skidding) for this Github organization name. As per our agreement, this disambiguation notice will stay here. +This Cosmos SDK project is not related to the [React-Cosmos](https://github.com/react-cosmos/react-cosmos) project (yet). Many thanks to Evan Coury and Ovidiu [(@skidding)](https://github.com/skidding) for this Github organization name. As per our agreement, this disambiguation notice will stay here.