diff --git a/CHANGELOG.md b/CHANGELOG.md index db0f3cdace0..c670b35a8c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,7 +66,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (modules/core/02-client) [\#1195](https://github.com/cosmos/ibc-go/pull/1210) Removing `CheckHeaderAndUpdateState` from `ClientState` interface & associated light client implementations. * (modules/core/02-client) [\#1189](https://github.com/cosmos/ibc-go/pull/1212) Removing `CheckMisbehaviourAndUpdateState` from `ClientState` interface & associated light client implementations. * (modules/core/exported) [\#1206](https://github.com/cosmos/ibc-go/pull/1206) Adding new method `UpdateState` to `ClientState` interface. -* (testing) [\#1302](https://github.com/cosmos/ibc-go/pull/1302) Change testchain default behaviour to use a chainID in the revision format. Set `ChainIDSuffix` to an empty string to disable this functionality. +* (testing) [\#1302](https://github.com/cosmos/ibc-go/pull/1302) Change testchain default behaviour to use a chainID in the revision format. Set `ChainIDSuffix` to an empty string to disable this functionality. +* (modules/core/02-client) [\#1741](https://github.com/cosmos/ibc-go/pull/1741) Emitting a new `upgrade_chain` event upon setting upgrade consensus state. ### Features diff --git a/modules/core/02-client/abci.go b/modules/core/02-client/abci.go index f32fd129309..0fb1cb5233a 100644 --- a/modules/core/02-client/abci.go +++ b/modules/core/02-client/abci.go @@ -26,6 +26,7 @@ func BeginBlocker(ctx sdk.Context, k keeper.Keeper) { bz := k.MustMarshalConsensusState(upgradedConsState) k.SetUpgradedConsensusState(ctx, plan.Height, bz) + keeper.EmitUpgradeChainEvent(ctx, plan.Height) } } } diff --git a/modules/core/02-client/abci_test.go b/modules/core/02-client/abci_test.go index 16aee80088a..72e9fbe44dd 100644 --- a/modules/core/02-client/abci_test.go +++ b/modules/core/02-client/abci_test.go @@ -1,13 +1,15 @@ package client_test import ( + "strings" "testing" + sdk "github.com/cosmos/cosmos-sdk/types" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" "github.com/stretchr/testify/suite" abci "github.com/tendermint/tendermint/abci/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" client "github.com/cosmos/ibc-go/v3/modules/core/02-client" "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" ibctmtypes "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint" @@ -74,3 +76,55 @@ func (suite *ClientTestSuite) TestBeginBlockerConsensusState() { suite.Require().NoError(err) suite.Require().Equal(bz, consState) } + +func (suite *ClientTestSuite) TestBeginBlockerUpgradeEvents() { + plan := &upgradetypes.Plan{ + Name: "test", + Height: suite.chainA.GetContext().BlockHeight() + 1, + } + // set upgrade plan in the upgrade store + store := suite.chainA.GetContext().KVStore(suite.chainA.GetSimApp().GetKey(upgradetypes.StoreKey)) + bz := suite.chainA.App.AppCodec().MustMarshal(plan) + store.Set(upgradetypes.PlanKey(), bz) + + nextValsHash := []byte("nextValsHash") + newCtx := suite.chainA.GetContext().WithBlockHeader(tmproto.Header{ + Height: suite.chainA.GetContext().BlockHeight(), + NextValidatorsHash: nextValsHash, + }) + + err := suite.chainA.GetSimApp().UpgradeKeeper.SetUpgradedClient(newCtx, plan.Height, []byte("client state")) + suite.Require().NoError(err) + + cacheCtx, writeCache := suite.chainA.GetContext().CacheContext() + + client.BeginBlocker(cacheCtx, suite.chainA.App.GetIBCKeeper().ClientKeeper) + writeCache() + + suite.requireContainsEvent(cacheCtx.EventManager().Events(), types.EventTypeUpgradeChain, true) +} + +func (suite *ClientTestSuite) TestBeginBlockerUpgradeEventsAbsence() { + cacheCtx, writeCache := suite.chainA.GetContext().CacheContext() + client.BeginBlocker(suite.chainA.GetContext(), suite.chainA.App.GetIBCKeeper().ClientKeeper) + writeCache() + suite.requireContainsEvent(cacheCtx.EventManager().Events(), types.EventTypeUpgradeChain, false) +} + +// requireContainsEvent verifies if an event of a specific type was emitted. +func (suite *ClientTestSuite) requireContainsEvent(events sdk.Events, eventType string, shouldContain bool) { + found := false + var eventTypes []string + for _, e := range events { + eventTypes = append(eventTypes, e.Type) + if e.Type == eventType { + found = true + break + } + } + if shouldContain { + suite.Require().True(found, "event type %s was not found in %s", eventType, strings.Join(eventTypes, ",")) + } else { + suite.Require().False(found, "event type %s was found in %s", eventType, strings.Join(eventTypes, ",")) + } +} diff --git a/modules/core/02-client/keeper/events.go b/modules/core/02-client/keeper/events.go index ec15ca41f4e..56c537b224b 100644 --- a/modules/core/02-client/keeper/events.go +++ b/modules/core/02-client/keeper/events.go @@ -2,10 +2,12 @@ package keeper import ( "encoding/hex" + "strconv" "strings" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" "github.com/cosmos/ibc-go/v3/modules/core/exported" @@ -101,3 +103,14 @@ func EmitSubmitMisbehaviourEvent(ctx sdk.Context, clientID string, clientState e ), ) } + +// EmitUpgradeChainEvent emits an upgrade chain event. +func EmitUpgradeChainEvent(ctx sdk.Context, height int64) { + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + types.EventTypeUpgradeChain, + sdk.NewAttribute(types.AttributeKeyUpgradePlanHeight, strconv.FormatInt(height, 10)), + sdk.NewAttribute(types.AttributeKeyUpgradeStore, upgradetypes.StoreKey), // which store to query proof of consensus state from + ), + }) +} diff --git a/modules/core/02-client/types/events.go b/modules/core/02-client/types/events.go index 05708a84859..6975bcd6e66 100644 --- a/modules/core/02-client/types/events.go +++ b/modules/core/02-client/types/events.go @@ -8,12 +8,14 @@ import ( // IBC client events const ( - AttributeKeyClientID = "client_id" - AttributeKeySubjectClientID = "subject_client_id" - AttributeKeyClientType = "client_type" - AttributeKeyConsensusHeight = "consensus_height" - AttributeKeyConsensusHeights = "consensus_heights" - AttributeKeyHeader = "header" + AttributeKeyClientID = "client_id" + AttributeKeySubjectClientID = "subject_client_id" + AttributeKeyClientType = "client_type" + AttributeKeyConsensusHeight = "consensus_height" + AttributeKeyConsensusHeights = "consensus_heights" + AttributeKeyHeader = "header" + AttributeKeyUpgradeStore = "upgrade_store" + AttributeKeyUpgradePlanHeight = "upgrade_plan_height" ) // IBC client events vars @@ -23,6 +25,7 @@ var ( EventTypeUpgradeClient = "upgrade_client" EventTypeSubmitMisbehaviour = "client_misbehaviour" EventTypeUpdateClientProposal = "update_client_proposal" + EventTypeUpgradeChain = "upgrade_chain" AttributeValueCategory = fmt.Sprintf("%s_%s", host.ModuleName, SubModuleName) )