diff --git a/CHANGELOG.md b/CHANGELOG.md index a253b02dd6c0..e3f787a08fab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/gov) [#15151](https://github.com/cosmos/cosmos-sdk/pull/15151) Add `burn_vote_quorum`, `burn_proposal_deposit_prevote` and `burn_vote_veto` params to allow applications to decide if they would like to burn deposits * (runtime) [#15547](https://github.com/cosmos/cosmos-sdk/pull/15547) Allow runtime to pass event core api service to modules * (telemetry) [#15657](https://github.com/cosmos/cosmos-sdk/pull/15657) Emit more data (go version, sdk version, upgrade height) in prom metrics +* (modulemanager) [#15829](https://github.com/cosmos/cosmos-sdk/pull/15829) add new endblocker interface to handle valset updates ### Improvements diff --git a/docs/docs/building-modules/05-beginblock-endblock.md b/docs/docs/building-modules/05-beginblock-endblock.md index 4cfdda370f05..3e5667ed7d97 100644 --- a/docs/docs/building-modules/05-beginblock-endblock.md +++ b/docs/docs/building-modules/05-beginblock-endblock.md @@ -43,3 +43,5 @@ and an example implementation of `EndBlocker` from the `staking` module: ```go reference https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/staking/abci.go#L22-L27 ``` + + diff --git a/runtime/app.go b/runtime/app.go index 90ad970f2490..4bfd07798f20 100644 --- a/runtime/app.go +++ b/runtime/app.go @@ -4,13 +4,11 @@ import ( "encoding/json" "fmt" - abci "github.com/cometbft/cometbft/abci/types" - "golang.org/x/exp/slices" - runtimev1alpha1 "cosmossdk.io/api/cosmos/app/runtime/v1alpha1" appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1" - storetypes "cosmossdk.io/store/types" + abci "github.com/cometbft/cometbft/abci/types" + "golang.org/x/exp/slices" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" diff --git a/runtime/services.go b/runtime/services.go index 2de85cdd3aad..34f86e612d08 100644 --- a/runtime/services.go +++ b/runtime/services.go @@ -1,8 +1,6 @@ package runtime import ( - "context" - appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1" @@ -26,14 +24,9 @@ func (a *App) registerRuntimeServices(cfg module.Configurator) error { } // ====================================================== -// ValidatorUpdateService & BlockInfoService +// BlockInfoService // ====================================================== -// ValidatorUpdateService is the service that runtime will provide to the module that sets validator updates. -type ValidatorUpdateService interface { - SetValidatorUpdates(context.Context, []abci.ValidatorUpdate) -} - // BlockInfoService is the service that runtime will provide to modules which need Comet block information. type BlockInfoService interface { GetHeight() int64 // GetHeight returns the height of the block diff --git a/tests/integration/evidence/keeper/infraction_test.go b/tests/integration/evidence/keeper/infraction_test.go index a53947486061..41fe09ec5e97 100644 --- a/tests/integration/evidence/keeper/infraction_test.go +++ b/tests/integration/evidence/keeper/infraction_test.go @@ -25,7 +25,6 @@ import ( minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" - "github.com/cosmos/cosmos-sdk/x/staking" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtestutil "github.com/cosmos/cosmos-sdk/x/staking/testutil" ) @@ -100,7 +99,7 @@ func TestHandleDoubleSign(t *testing.T) { selfDelegation := tstaking.CreateValidatorWithValPower(operatorAddr, val, power, true) // execute end-blocker and verify validator attributes - staking.EndBlocker(ctx, f.stakingKeeper) + f.stakingKeeper.EndBlocker(f.ctx) assert.DeepEqual(t, f.bankKeeper.GetAllBalances(ctx, sdk.AccAddress(operatorAddr)).String(), sdk.NewCoins(sdk.NewCoin(stakingParams.BondDenom, initAmt.Sub(selfDelegation))).String(), @@ -172,7 +171,7 @@ func TestHandleDoubleSign_TooOld(t *testing.T) { amt := tstaking.CreateValidatorWithValPower(operatorAddr, val, power, true) // execute end-blocker and verify validator attributes - staking.EndBlocker(ctx, f.stakingKeeper) + f.stakingKeeper.EndBlocker(f.ctx) assert.DeepEqual(t, f.bankKeeper.GetAllBalances(ctx, sdk.AccAddress(operatorAddr)), sdk.NewCoins(sdk.NewCoin(stakingParams.BondDenom, initAmt.Sub(amt))), diff --git a/tests/integration/gov/keeper/common_test.go b/tests/integration/gov/keeper/common_test.go index 8bd1518752b4..f11589e92419 100644 --- a/tests/integration/gov/keeper/common_test.go +++ b/tests/integration/gov/keeper/common_test.go @@ -15,7 +15,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/gov/types" v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" - "github.com/cosmos/cosmos-sdk/x/staking" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -73,7 +72,7 @@ func createValidators(t *testing.T, ctx sdk.Context, app *simapp.SimApp, powers _, _ = app.StakingKeeper.Delegate(ctx, addrs[1], app.StakingKeeper.TokensFromConsensusPower(ctx, powers[1]), stakingtypes.Unbonded, val2, true) _, _ = app.StakingKeeper.Delegate(ctx, addrs[2], app.StakingKeeper.TokensFromConsensusPower(ctx, powers[2]), stakingtypes.Unbonded, val3, true) - _ = staking.EndBlocker(ctx, app.StakingKeeper) + app.StakingKeeper.EndBlocker(ctx) return addrs, valAddrs } diff --git a/tests/integration/gov/keeper/tally_test.go b/tests/integration/gov/keeper/tally_test.go index cda35b0d61ec..a021a3c8537a 100644 --- a/tests/integration/gov/keeper/tally_test.go +++ b/tests/integration/gov/keeper/tally_test.go @@ -8,7 +8,6 @@ import ( simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" - "github.com/cosmos/cosmos-sdk/x/staking" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -271,7 +270,7 @@ func TestTallyDelgatorOverride(t *testing.T) { _, err := app.StakingKeeper.Delegate(ctx, addrs[4], delTokens, stakingtypes.Unbonded, val1, true) assert.NilError(t, err) - _ = staking.EndBlocker(ctx, app.StakingKeeper) + app.StakingKeeper.EndBlocker(ctx) tp := TestProposal proposal, err := app.GovKeeper.SubmitProposal(ctx, tp, "", "test", "description", addrs[0], false) @@ -309,7 +308,7 @@ func TestTallyDelgatorInherit(t *testing.T) { _, err := app.StakingKeeper.Delegate(ctx, addrs[3], delTokens, stakingtypes.Unbonded, val3, true) assert.NilError(t, err) - _ = staking.EndBlocker(ctx, app.StakingKeeper) + app.StakingKeeper.EndBlocker(ctx) tp := TestProposal proposal, err := app.GovKeeper.SubmitProposal(ctx, tp, "", "test", "description", addrs[0], false) @@ -350,7 +349,7 @@ func TestTallyDelgatorMultipleOverride(t *testing.T) { _, err = app.StakingKeeper.Delegate(ctx, addrs[3], delTokens, stakingtypes.Unbonded, val2, true) assert.NilError(t, err) - _ = staking.EndBlocker(ctx, app.StakingKeeper) + app.StakingKeeper.EndBlocker(ctx) tp := TestProposal proposal, err := app.GovKeeper.SubmitProposal(ctx, tp, "", "test", "description", addrs[0], false) @@ -394,7 +393,7 @@ func TestTallyDelgatorMultipleInherit(t *testing.T) { _, err = app.StakingKeeper.Delegate(ctx, addrs[3], delTokens, stakingtypes.Unbonded, val3, true) assert.NilError(t, err) - _ = staking.EndBlocker(ctx, app.StakingKeeper) + app.StakingKeeper.EndBlocker(ctx) tp := TestProposal proposal, err := app.GovKeeper.SubmitProposal(ctx, tp, "", "test", "description", addrs[0], false) @@ -435,7 +434,7 @@ func TestTallyJailedValidator(t *testing.T) { _, err = app.StakingKeeper.Delegate(ctx, addrs[3], delTokens, stakingtypes.Unbonded, val3, true) assert.NilError(t, err) - _ = staking.EndBlocker(ctx, app.StakingKeeper) + app.StakingKeeper.EndBlocker(ctx) consAddr, err := val2.GetConsAddr() assert.NilError(t, err) diff --git a/tests/integration/slashing/keeper/keeper_test.go b/tests/integration/slashing/keeper/keeper_test.go index 0fb2cb66c293..74c97015a6c5 100644 --- a/tests/integration/slashing/keeper/keeper_test.go +++ b/tests/integration/slashing/keeper/keeper_test.go @@ -5,12 +5,12 @@ import ( "time" cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + "github.com/stretchr/testify/require" "gotest.tools/v3/assert" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/slashing/testutil" - "github.com/cosmos/cosmos-sdk/x/staking" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" @@ -79,7 +79,7 @@ func TestUnJailNotBonded(t *testing.T) { tstaking.CreateValidatorWithValPower(addr, val, 100, true) } - staking.EndBlocker(f.ctx, f.stakingKeeper) + f.stakingKeeper.EndBlocker(f.ctx) f.ctx = f.ctx.WithBlockHeight(f.ctx.BlockHeight() + 1) // create a 6th validator with less power than the cliff validator (won't be bonded) @@ -91,7 +91,7 @@ func TestUnJailNotBonded(t *testing.T) { assert.NilError(t, err) assert.Assert(t, res != nil) - staking.EndBlocker(f.ctx, f.stakingKeeper) + f.stakingKeeper.EndBlocker(f.ctx) f.ctx = f.ctx.WithBlockHeight(f.ctx.BlockHeight() + 1) tstaking.CheckValidator(addr, stakingtypes.Unbonded, false) @@ -100,7 +100,7 @@ func TestUnJailNotBonded(t *testing.T) { assert.Equal(t, p.BondDenom, tstaking.Denom) tstaking.Undelegate(sdk.AccAddress(addr), addr, f.stakingKeeper.TokensFromConsensusPower(f.ctx, 1), true) - staking.EndBlocker(f.ctx, f.stakingKeeper) + f.stakingKeeper.EndBlocker(f.ctx) f.ctx = f.ctx.WithBlockHeight(f.ctx.BlockHeight() + 1) // verify that validator is jailed @@ -109,12 +109,12 @@ func TestUnJailNotBonded(t *testing.T) { // verify we cannot unjail (yet) assert.ErrorContains(t, f.slashingKeeper.Unjail(f.ctx, addr), "cannot be unjailed") - staking.EndBlocker(f.ctx, f.stakingKeeper) + f.stakingKeeper.EndBlocker(f.ctx) f.ctx = f.ctx.WithBlockHeight(f.ctx.BlockHeight() + 1) // bond to meet minimum self-delegation tstaking.DelegateWithPower(sdk.AccAddress(addr), addr, 1) - staking.EndBlocker(f.ctx, f.stakingKeeper) + f.stakingKeeper.EndBlocker(f.ctx) f.ctx = f.ctx.WithBlockHeight(f.ctx.BlockHeight() + 1) // verify we can immediately unjail @@ -140,7 +140,7 @@ func TestHandleNewValidator(t *testing.T) { // Validator created amt := tstaking.CreateValidatorWithValPower(addr, val, 100, true) - staking.EndBlocker(f.ctx, f.stakingKeeper) + f.stakingKeeper.EndBlocker(f.ctx) assert.DeepEqual( t, f.bankKeeper.GetAllBalances(f.ctx, sdk.AccAddress(addr)), sdk.NewCoins(sdk.NewCoin(f.stakingKeeper.GetParams(f.ctx).BondDenom, InitTokens.Sub(amt))), @@ -184,7 +184,7 @@ func TestHandleAlreadyJailed(t *testing.T) { amt := tstaking.CreateValidatorWithValPower(addr, val, power, true) - staking.EndBlocker(f.ctx, f.stakingKeeper) + f.stakingKeeper.EndBlocker(f.ctx) // 1000 first blocks OK height := int64(0) @@ -200,7 +200,7 @@ func TestHandleAlreadyJailed(t *testing.T) { } // end block - staking.EndBlocker(f.ctx, f.stakingKeeper) + f.stakingKeeper.EndBlocker(f.ctx) // validator should have been jailed and slashed validator, _ := f.stakingKeeper.GetValidatorByConsAddr(f.ctx, sdk.GetConsAddress(val)) @@ -240,7 +240,8 @@ func TestValidatorDippingInAndOut(t *testing.T) { valAddr := sdk.ValAddress(addr) tstaking.CreateValidatorWithValPower(valAddr, val, power, true) - validatorUpdates := staking.EndBlocker(f.ctx, f.stakingKeeper) + validatorUpdates, err := f.stakingKeeper.EndBlocker(f.ctx) + require.NoError(t, err) assert.Equal(t, 2, len(validatorUpdates)) tstaking.CheckValidator(valAddr, stakingtypes.Bonded, false) @@ -253,7 +254,8 @@ func TestValidatorDippingInAndOut(t *testing.T) { // kick first validator out of validator set tstaking.CreateValidatorWithValPower(sdk.ValAddress(pks[1].Address()), pks[1], power+1, true) - validatorUpdates = staking.EndBlocker(f.ctx, f.stakingKeeper) + validatorUpdates, err = f.stakingKeeper.EndBlocker(f.ctx) + require.NoError(t, err) assert.Equal(t, 2, len(validatorUpdates)) tstaking.CheckValidator(sdk.ValAddress(pks[1].Address()), stakingtypes.Bonded, false) tstaking.CheckValidator(valAddr, stakingtypes.Unbonding, false) @@ -265,7 +267,8 @@ func TestValidatorDippingInAndOut(t *testing.T) { // validator added back in tstaking.DelegateWithPower(sdk.AccAddress(pks[2].Address()), valAddr, 50) - validatorUpdates = staking.EndBlocker(f.ctx, f.stakingKeeper) + validatorUpdates, err = f.stakingKeeper.EndBlocker(f.ctx) + require.NoError(t, err) assert.Equal(t, 2, len(validatorUpdates)) tstaking.CheckValidator(valAddr, stakingtypes.Bonded, false) newPower := power + 50 @@ -287,7 +290,7 @@ func TestValidatorDippingInAndOut(t *testing.T) { } // should now be jailed & kicked - staking.EndBlocker(f.ctx, f.stakingKeeper) + f.stakingKeeper.EndBlocker(f.ctx) tstaking.CheckValidator(valAddr, stakingtypes.Unbonding, true) // check all the signing information @@ -307,7 +310,7 @@ func TestValidatorDippingInAndOut(t *testing.T) { f.slashingKeeper.HandleValidatorSignature(f.ctx, val.Address(), newPower, true) // validator should not be kicked since we reset counter/array when it was jailed - staking.EndBlocker(f.ctx, f.stakingKeeper) + f.stakingKeeper.EndBlocker(f.ctx) tstaking.CheckValidator(valAddr, stakingtypes.Bonded, false) // check start height is correctly set @@ -323,6 +326,6 @@ func TestValidatorDippingInAndOut(t *testing.T) { } // validator should now be jailed & kicked - staking.EndBlocker(f.ctx, f.stakingKeeper) + f.stakingKeeper.EndBlocker(f.ctx) tstaking.CheckValidator(valAddr, stakingtypes.Unbonding, true) } diff --git a/tests/integration/staking/keeper/validator_test.go b/tests/integration/staking/keeper/validator_test.go index 7d41655fd65d..2b462860e060 100644 --- a/tests/integration/staking/keeper/validator_test.go +++ b/tests/integration/staking/keeper/validator_test.go @@ -13,7 +13,6 @@ import ( simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" banktestutil "github.com/cosmos/cosmos-sdk/x/bank/testutil" - "github.com/cosmos/cosmos-sdk/x/staking" "github.com/cosmos/cosmos-sdk/x/staking/keeper" "github.com/cosmos/cosmos-sdk/x/staking/testutil" "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -48,7 +47,7 @@ func bootstrapValidatorTest(t testing.TB, power int64, numAddrs int) (*simapp.Si assert.NilError(t, err) // end block to unbond genesis validator - staking.EndBlocker(ctx, app.StakingKeeper) + app.StakingKeeper.EndBlocker(ctx) return app, ctx, addrDels, addrVals } diff --git a/testutil/mock/types_module_module.go b/testutil/mock/types_module_module.go index 8b3a79c80fa9..c406366748c0 100644 --- a/testutil/mock/types_module_module.go +++ b/testutil/mock/types_module_module.go @@ -5,6 +5,7 @@ package mock import ( + context "context" json "encoding/json" reflect "reflect" @@ -879,3 +880,119 @@ func (mr *MockEndBlockAppModuleMockRecorder) RegisterLegacyAminoCodec(arg0 inter mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterLegacyAminoCodec", reflect.TypeOf((*MockEndBlockAppModule)(nil).RegisterLegacyAminoCodec), arg0) } + +// MockHasABCIEndblock is a mock of HasABCIEndblock interface. +type MockHasABCIEndblock struct { + ctrl *gomock.Controller + recorder *MockHasABCIEndblockMockRecorder +} + +// MockHasABCIEndblockMockRecorder is the mock recorder for MockHasABCIEndblock. +type MockHasABCIEndblockMockRecorder struct { + mock *MockHasABCIEndblock +} + +// NewMockHasABCIEndblock creates a new mock instance. +func NewMockHasABCIEndblock(ctrl *gomock.Controller) *MockHasABCIEndblock { + mock := &MockHasABCIEndblock{ctrl: ctrl} + mock.recorder = &MockHasABCIEndblockMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockHasABCIEndblock) EXPECT() *MockHasABCIEndblockMockRecorder { + return m.recorder +} + +// EndBlock mocks base method. +func (m *MockHasABCIEndblock) EndBlock(arg0 context.Context) ([]types.ValidatorUpdate, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "EndBlock", arg0) + ret0, _ := ret[0].([]types.ValidatorUpdate) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// EndBlock indicates an expected call of EndBlock. +func (mr *MockHasABCIEndblockMockRecorder) EndBlock(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EndBlock", reflect.TypeOf((*MockHasABCIEndblock)(nil).EndBlock), arg0) +} + +// GetQueryCmd mocks base method. +func (m *MockHasABCIEndblock) GetQueryCmd() *cobra.Command { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetQueryCmd") + ret0, _ := ret[0].(*cobra.Command) + return ret0 +} + +// GetQueryCmd indicates an expected call of GetQueryCmd. +func (mr *MockHasABCIEndblockMockRecorder) GetQueryCmd() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetQueryCmd", reflect.TypeOf((*MockHasABCIEndblock)(nil).GetQueryCmd)) +} + +// GetTxCmd mocks base method. +func (m *MockHasABCIEndblock) GetTxCmd() *cobra.Command { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTxCmd") + ret0, _ := ret[0].(*cobra.Command) + return ret0 +} + +// GetTxCmd indicates an expected call of GetTxCmd. +func (mr *MockHasABCIEndblockMockRecorder) GetTxCmd() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTxCmd", reflect.TypeOf((*MockHasABCIEndblock)(nil).GetTxCmd)) +} + +// Name mocks base method. +func (m *MockHasABCIEndblock) Name() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Name") + ret0, _ := ret[0].(string) + return ret0 +} + +// Name indicates an expected call of Name. +func (mr *MockHasABCIEndblockMockRecorder) Name() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockHasABCIEndblock)(nil).Name)) +} + +// RegisterGRPCGatewayRoutes mocks base method. +func (m *MockHasABCIEndblock) RegisterGRPCGatewayRoutes(arg0 client.Context, arg1 *runtime.ServeMux) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterGRPCGatewayRoutes", arg0, arg1) +} + +// RegisterGRPCGatewayRoutes indicates an expected call of RegisterGRPCGatewayRoutes. +func (mr *MockHasABCIEndblockMockRecorder) RegisterGRPCGatewayRoutes(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterGRPCGatewayRoutes", reflect.TypeOf((*MockHasABCIEndblock)(nil).RegisterGRPCGatewayRoutes), arg0, arg1) +} + +// RegisterInterfaces mocks base method. +func (m *MockHasABCIEndblock) RegisterInterfaces(arg0 types0.InterfaceRegistry) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterInterfaces", arg0) +} + +// RegisterInterfaces indicates an expected call of RegisterInterfaces. +func (mr *MockHasABCIEndblockMockRecorder) RegisterInterfaces(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterInterfaces", reflect.TypeOf((*MockHasABCIEndblock)(nil).RegisterInterfaces), arg0) +} + +// RegisterLegacyAminoCodec mocks base method. +func (m *MockHasABCIEndblock) RegisterLegacyAminoCodec(arg0 *codec.LegacyAmino) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterLegacyAminoCodec", arg0) +} + +// RegisterLegacyAminoCodec indicates an expected call of RegisterLegacyAminoCodec. +func (mr *MockHasABCIEndblockMockRecorder) RegisterLegacyAminoCodec(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterLegacyAminoCodec", reflect.TypeOf((*MockHasABCIEndblock)(nil).RegisterLegacyAminoCodec), arg0) +} diff --git a/types/module/module.go b/types/module/module.go index ba73d3d9d7d8..e1891edda90a 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -29,6 +29,7 @@ needlessly defining many placeholder functions package module import ( + "context" "encoding/json" "errors" "fmt" @@ -212,6 +213,11 @@ type EndBlockAppModule interface { EndBlock(sdk.Context, abci.RequestEndBlock) []abci.ValidatorUpdate } +type HasABCIEndblock interface { + AppModule + EndBlock(context.Context) ([]abci.ValidatorUpdate, error) +} + // GenesisOnlyAppModule is an AppModule that only has import/export functionality type GenesisOnlyAppModule struct { AppModuleGenesis @@ -695,6 +701,22 @@ func (m *Manager) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) (abci.Resp if err != nil { return abci.ResponseEndBlock{}, err } + } else if module, ok := m.Modules[moduleName].(HasABCIEndblock); ok { + moduleValUpdates, err := module.EndBlock(ctx) + if err != nil { + return abci.ResponseEndBlock{}, err + } + // use these validator updates if provided, the module manager assumes + // only one module will update the validator set + if len(moduleValUpdates) > 0 { + if len(validatorUpdates) > 0 { + return abci.ResponseEndBlock{}, errors.New("validator EndBlock updates already set by a previous module") + } + + for _, updates := range moduleValUpdates { + validatorUpdates = append(validatorUpdates, abci.ValidatorUpdate{PubKey: updates.PubKey, Power: updates.Power}) + } + } } else { continue } diff --git a/x/auth/migrations/v2/store_test.go b/x/auth/migrations/v2/store_test.go index b2af5f9e8632..0663f29f1a3a 100644 --- a/x/auth/migrations/v2/store_test.go +++ b/x/auth/migrations/v2/store_test.go @@ -26,7 +26,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported" "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" - "github.com/cosmos/cosmos-sdk/x/staking" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -714,7 +713,7 @@ func createValidator(t *testing.T, ctx sdk.Context, bankKeeper bankkeeper.Keeper _, err = stakingKeeper.Delegate(ctx, addrs[0], valTokens, stakingtypes.Unbonded, val1, true) require.NoError(t, err) - _ = staking.EndBlocker(ctx, stakingKeeper) + stakingKeeper.EndBlocker(ctx) return addrs[0], valAddrs[0] } diff --git a/x/feegrant/testutil/expected_keepers_mocks.go b/x/feegrant/testutil/expected_keepers_mocks.go index e659ee5cf601..b73d1735322d 100644 --- a/x/feegrant/testutil/expected_keepers_mocks.go +++ b/x/feegrant/testutil/expected_keepers_mocks.go @@ -5,7 +5,7 @@ package testutil import ( - "context" + context "context" reflect "reflect" types "github.com/cosmos/cosmos-sdk/types" diff --git a/x/gov/abci_test.go b/x/gov/abci_test.go index f5850027e542..2423c488d498 100644 --- a/x/gov/abci_test.go +++ b/x/gov/abci_test.go @@ -17,7 +17,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/gov/keeper" "github.com/cosmos/cosmos-sdk/x/gov/types" v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" - "github.com/cosmos/cosmos-sdk/x/staking" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -361,7 +360,7 @@ func TestProposalPassedEndblocker(t *testing.T) { proposer := addrs[0] createValidators(t, stakingMsgSvr, ctx, []sdk.ValAddress{valAddr}, []int64{10}) - staking.EndBlocker(ctx, suite.StakingKeeper) + suite.StakingKeeper.EndBlocker(ctx) macc := suite.GovKeeper.GetGovernanceAccount(ctx) require.NotNil(t, macc) @@ -416,7 +415,7 @@ func TestEndBlockerProposalHandlerFailed(t *testing.T) { proposer := addrs[0] createValidators(t, stakingMsgSvr, ctx, []sdk.ValAddress{valAddr}, []int64{10}) - staking.EndBlocker(ctx, suite.StakingKeeper) + suite.StakingKeeper.EndBlocker(ctx) msg := banktypes.NewMsgSend(authtypes.NewModuleAddress(types.ModuleName), addrs[0], sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100000)))) proposal, err := suite.GovKeeper.SubmitProposal(ctx, []sdk.Msg{msg}, "", "title", "summary", proposer, false) @@ -497,7 +496,7 @@ func TestExpeditedProposal_PassAndConversionToRegular(t *testing.T) { // Create a validator so that able to vote on proposal. createValidators(t, stakingMsgSvr, ctx, []sdk.ValAddress{valAddr}, []int64{10}) - staking.EndBlocker(ctx, suite.StakingKeeper) + suite.StakingKeeper.EndBlocker(ctx) inactiveQueue := suite.GovKeeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) require.False(t, inactiveQueue.Valid()) diff --git a/x/slashing/abci_test.go b/x/slashing/abci_test.go index 367486040340..a87cf4bf827f 100644 --- a/x/slashing/abci_test.go +++ b/x/slashing/abci_test.go @@ -15,7 +15,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/slashing" slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" "github.com/cosmos/cosmos-sdk/x/slashing/testutil" - "github.com/cosmos/cosmos-sdk/x/staking" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtestutil "github.com/cosmos/cosmos-sdk/x/staking/testutil" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -46,7 +45,7 @@ func TestBeginBlocker(t *testing.T) { // bond the validator power := int64(100) amt := tstaking.CreateValidatorWithValPower(addr, pk, power, true) - staking.EndBlocker(ctx, stakingKeeper) + stakingKeeper.EndBlocker(ctx) require.Equal( t, bankKeeper.GetAllBalances(ctx, sdk.AccAddress(addr)), sdk.NewCoins(sdk.NewCoin(stakingKeeper.GetParams(ctx).BondDenom, InitTokens.Sub(amt))), @@ -97,7 +96,7 @@ func TestBeginBlocker(t *testing.T) { } // end block - staking.EndBlocker(ctx, stakingKeeper) + stakingKeeper.EndBlocker(ctx) // validator should be jailed validator, found := stakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(pk)) diff --git a/x/staking/abci.go b/x/staking/keeper/abci.go similarity index 73% rename from x/staking/abci.go rename to x/staking/keeper/abci.go index 1912beb99747..fcb65377eba8 100644 --- a/x/staking/abci.go +++ b/x/staking/keeper/abci.go @@ -1,27 +1,26 @@ -package staking +package keeper import ( + "context" "time" abci "github.com/cometbft/cometbft/abci/types" - "github.com/cosmos/cosmos-sdk/telemetry" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/staking/keeper" "github.com/cosmos/cosmos-sdk/x/staking/types" ) // BeginBlocker will persist the current header and validator set as a historical entry // and prune the oldest entry based on the HistoricalEntries parameter -func BeginBlocker(ctx sdk.Context, k *keeper.Keeper) { +func (k *Keeper) BeginBlocker(ctx sdk.Context) { defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyBeginBlocker) k.TrackHistoricalInfo(ctx) } // Called every block, update validator set -func EndBlocker(ctx sdk.Context, k *keeper.Keeper) []abci.ValidatorUpdate { +func (k *Keeper) EndBlocker(ctx context.Context) ([]abci.ValidatorUpdate, error) { defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyEndBlocker) - return k.BlockValidatorUpdates(ctx) + return k.BlockValidatorUpdates(sdk.UnwrapSDKContext(ctx)), nil } diff --git a/x/staking/module.go b/x/staking/module.go index 5e93989da5d6..bd60ca1d5f83 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -6,20 +6,14 @@ import ( "fmt" "sort" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - "github.com/cosmos/cosmos-sdk/x/staking/exported" - - abci "github.com/cometbft/cometbft/abci/types" - gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime" - "github.com/spf13/cobra" - "golang.org/x/exp/maps" - modulev1 "cosmossdk.io/api/cosmos/staking/module/v1" "cosmossdk.io/core/appmodule" "cosmossdk.io/depinject" - store "cosmossdk.io/store/types" + abci "github.com/cometbft/cometbft/abci/types" + gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + "golang.org/x/exp/maps" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" @@ -27,7 +21,10 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/cosmos/cosmos-sdk/x/staking/client/cli" + "github.com/cosmos/cosmos-sdk/x/staking/exported" "github.com/cosmos/cosmos-sdk/x/staking/keeper" "github.com/cosmos/cosmos-sdk/x/staking/simulation" "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -38,7 +35,9 @@ const ( ) var ( - _ module.EndBlockAppModule = AppModule{} + _ appmodule.AppModule = AppModule{} + _ appmodule.HasBeginBlocker = AppModule{} + _ module.HasABCIEndblock = AppModule{} _ module.AppModuleBasic = AppModuleBasic{} _ module.AppModuleSimulation = AppModule{} ) @@ -191,14 +190,15 @@ func (AppModule) ConsensusVersion() uint64 { return consensusVersion } // BeginBlock returns the begin blocker for the staking module. func (am AppModule) BeginBlock(ctx context.Context) error { c := sdk.UnwrapSDKContext(ctx) - BeginBlocker(c, am.keeper) + + am.keeper.BeginBlocker(c) return nil } // EndBlock returns the end blocker for the staking module. It returns no validator // updates. -func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { - return EndBlocker(ctx, am.keeper) +func (am AppModule) EndBlock(ctx context.Context) ([]abci.ValidatorUpdate, error) { + return am.keeper.EndBlocker(ctx) } func init() { diff --git a/x/staking/testutil/helpers.go b/x/staking/testutil/helpers.go index 3dae28b09a06..38f75a0d5fa4 100644 --- a/x/staking/testutil/helpers.go +++ b/x/staking/testutil/helpers.go @@ -10,7 +10,6 @@ import ( cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/staking" "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -127,7 +126,7 @@ func (sh *Helper) CheckDelegator(delegator sdk.AccAddress, val sdk.ValAddress, f // TurnBlock calls EndBlocker and updates the block time func (sh *Helper) TurnBlock(newTime time.Time) sdk.Context { sh.Ctx = sh.Ctx.WithBlockTime(newTime) - staking.EndBlocker(sh.Ctx, sh.k) + sh.k.EndBlocker(sh.Ctx) return sh.Ctx } @@ -135,7 +134,7 @@ func (sh *Helper) TurnBlock(newTime time.Time) sdk.Context { // duration to the current block time func (sh *Helper) TurnBlockTimeDiff(diff time.Duration) sdk.Context { sh.Ctx = sh.Ctx.WithBlockTime(sh.Ctx.BlockHeader().Time.Add(diff)) - staking.EndBlocker(sh.Ctx, sh.k) + sh.k.EndBlocker(sh.Ctx) return sh.Ctx }