From 76eb0daa672cb35846c2e3ee0c76871730e9b6f0 Mon Sep 17 00:00:00 2001 From: Tuan Tran Date: Fri, 17 May 2024 02:58:16 +0700 Subject: [PATCH 01/16] chore(ante): refactor ante tests to use expected errors (#6310) * add expErr and fix nil updateClientMessage on testcase setup * linting --------- Co-authored-by: DimitrisJim --- modules/core/ante/ante_test.go | 49 +++++++++++++++++----------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/modules/core/ante/ante_test.go b/modules/core/ante/ante_test.go index 2033f1f4e18..68b75fab0a7 100644 --- a/modules/core/ante/ante_test.go +++ b/modules/core/ante/ante_test.go @@ -3,6 +3,7 @@ package ante_test import ( "testing" + "github.com/cosmos/btcutil/bech32" "github.com/stretchr/testify/require" testifysuite "github.com/stretchr/testify/suite" @@ -180,7 +181,7 @@ func (suite *AnteTestSuite) TestAnteDecorator() { testCases := []struct { name string malleate func(suite *AnteTestSuite) []sdk.Msg - expPass bool + expError error }{ { "success on one new RecvPacket message", @@ -188,7 +189,7 @@ func (suite *AnteTestSuite) TestAnteDecorator() { // the RecvPacket message has not been submitted to the chain yet, so it will succeed return []sdk.Msg{suite.createRecvPacketMessage(false)} }, - true, + nil, }, { "success on one new Acknowledgement message", @@ -196,7 +197,7 @@ func (suite *AnteTestSuite) TestAnteDecorator() { // the Acknowledgement message has not been submitted to the chain yet, so it will succeed return []sdk.Msg{suite.createAcknowledgementMessage(false)} }, - true, + nil, }, { "success on one new Timeout message", @@ -204,7 +205,7 @@ func (suite *AnteTestSuite) TestAnteDecorator() { // the Timeout message has not been submitted to the chain yet, so it will succeed return []sdk.Msg{suite.createTimeoutMessage(false)} }, - true, + nil, }, { "success on one new TimeoutOnClose message", @@ -212,7 +213,7 @@ func (suite *AnteTestSuite) TestAnteDecorator() { // the TimeoutOnClose message has not been submitted to the chain yet, so it will succeed return []sdk.Msg{suite.createTimeoutOnCloseMessage(false)} }, - true, + nil, }, { "success on three new messages of each type", @@ -241,7 +242,7 @@ func (suite *AnteTestSuite) TestAnteDecorator() { } return msgs }, - true, + nil, }, { "success on three redundant messages of RecvPacket, Acknowledgement and TimeoutOnClose, and one new Timeout message", @@ -271,7 +272,7 @@ func (suite *AnteTestSuite) TestAnteDecorator() { } return msgs }, - true, + nil, }, { "success on one new message and two redundant messages of each type", @@ -301,21 +302,21 @@ func (suite *AnteTestSuite) TestAnteDecorator() { } return msgs }, - true, + nil, }, { "success on one new UpdateClient message", func(suite *AnteTestSuite) []sdk.Msg { return []sdk.Msg{suite.createUpdateClientMessage()} }, - true, + nil, }, { "success on three new UpdateClient messages", func(suite *AnteTestSuite) []sdk.Msg { return []sdk.Msg{suite.createUpdateClientMessage(), suite.createUpdateClientMessage(), suite.createUpdateClientMessage()} }, - true, + nil, }, { "success on three new Updateclient messages and one new RecvPacket message", @@ -327,7 +328,7 @@ func (suite *AnteTestSuite) TestAnteDecorator() { suite.createRecvPacketMessage(false), } }, - true, + nil, }, { "success on three redundant RecvPacket messages and one SubmitMisbehaviour message", @@ -342,14 +343,14 @@ func (suite *AnteTestSuite) TestAnteDecorator() { msgs = append(msgs, &clienttypes.MsgSubmitMisbehaviour{}) //nolint:staticcheck // we're using the deprecated message for testing return msgs }, - true, + nil, }, { "no success on one redundant RecvPacket message", func(suite *AnteTestSuite) []sdk.Msg { return []sdk.Msg{suite.createRecvPacketMessage(true)} }, - false, + channeltypes.ErrRedundantTx, }, { "no success on three redundant messages of each type", @@ -374,12 +375,12 @@ func (suite *AnteTestSuite) TestAnteDecorator() { } return msgs }, - false, + channeltypes.ErrRedundantTx, }, { "no success on one new UpdateClient message and three redundant RecvPacket messages", func(suite *AnteTestSuite) []sdk.Msg { - msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{}} + msgs := []sdk.Msg{suite.createUpdateClientMessage()} for i := 1; i <= 3; i++ { msgs = append(msgs, suite.createRecvPacketMessage(true)) @@ -387,7 +388,7 @@ func (suite *AnteTestSuite) TestAnteDecorator() { return msgs }, - false, + channeltypes.ErrRedundantTx, }, { "no success on one new UpdateClient message: invalid client identifier", @@ -398,7 +399,7 @@ func (suite *AnteTestSuite) TestAnteDecorator() { msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: ibctesting.InvalidID, ClientMessage: clientMsg}} return msgs }, - false, + clienttypes.ErrClientNotActive, }, { "no success on one new UpdateClient message: client module not found", @@ -409,7 +410,7 @@ func (suite *AnteTestSuite) TestAnteDecorator() { msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: clienttypes.FormatClientIdentifier("08-wasm", 1), ClientMessage: clientMsg}} return msgs }, - false, + clienttypes.ErrClientNotActive, }, { "no success on one new UpdateClient message: no consensus state for trusted height", @@ -420,7 +421,7 @@ func (suite *AnteTestSuite) TestAnteDecorator() { msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: suite.path.EndpointA.ClientID, ClientMessage: clientMsg}} return msgs }, - false, + clienttypes.ErrConsensusStateNotFound, }, { "no success on three new UpdateClient messages and three redundant messages of each type", @@ -445,7 +446,7 @@ func (suite *AnteTestSuite) TestAnteDecorator() { } return msgs }, - false, + channeltypes.ErrRedundantTx, }, { "no success on one new message and one invalid message", @@ -460,7 +461,7 @@ func (suite *AnteTestSuite) TestAnteDecorator() { channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(1, 1), "signer"), } }, - false, + bech32.ErrInvalidLength(6), }, { "no success on one new message and one redundant message in the same block", @@ -484,7 +485,7 @@ func (suite *AnteTestSuite) TestAnteDecorator() { return []sdk.Msg{msg} }, - false, + channeltypes.ErrRedundantTx, }, } @@ -515,10 +516,10 @@ func (suite *AnteTestSuite) TestAnteDecorator() { suite.Require().NoError(err, "antedecorator should not error on DeliverTx") _, err = decorator.AnteHandle(checkCtx, tx, false, next) - if tc.expPass { + if tc.expError == nil { suite.Require().NoError(err, "non-strict decorator did not pass as expected") } else { - suite.Require().Error(err, "non-strict antehandler did not return error as expected") + suite.Require().ErrorIs(err, tc.expError, "non-strict antehandler did not return error as expected") } }) } From ca240f80f5666f64f08e9bffe5f7b3347cf25010 Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Sun, 19 May 2024 22:44:07 +0200 Subject: [PATCH 02/16] fix: no-op rather than panic in solomachine update state (#6313) * fix: no-op rather than panic in solomachine update state * Update modules/light-clients/06-solomachine/update.go Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * add changelog --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Carlos Rodriguez --- CHANGELOG.md | 1 + .../06-solomachine/light_client_module_test.go | 9 +++++++-- modules/light-clients/06-solomachine/update.go | 6 +++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43ceb250514..5506ddc1cd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### State Machine Breaking * (light-clients/07-tendermint) [\#6276](https://github.com/cosmos/ibc-go/pull/6276) Fix: No-op to avoid panicking on `UpdateState` for invalid misbehaviour submissions. +* (light-clients/06-solomachine) [\#6313](https://github.com/cosmos/ibc-go/pull/6313) Fix: No-op to avoid panicking on `UpdateState` for invalid misbehaviour submissions. ### Improvements diff --git a/modules/light-clients/06-solomachine/light_client_module_test.go b/modules/light-clients/06-solomachine/light_client_module_test.go index d853cbf42d5..d80691462a8 100644 --- a/modules/light-clients/06-solomachine/light_client_module_test.go +++ b/modules/light-clients/06-solomachine/light_client_module_test.go @@ -1042,13 +1042,13 @@ func (suite *SoloMachineTestSuite) TestUpdateState() { nil, }, { - "failure: invalid type misbehaviour", + "invalid type misbehaviour no-ops", func() { clientState = sm.ClientState() clientMsg = sm.CreateMisbehaviour() suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), clientID, clientState) }, - fmt.Errorf("unsupported ClientMessage: %T", sm.CreateMisbehaviour()), + nil, }, { "failure: cannot find client state", @@ -1092,6 +1092,11 @@ func (suite *SoloMachineTestSuite) TestUpdateState() { newClientState := clienttypes.MustUnmarshalClientState(suite.chainA.Codec, clientStateBz) + if len(consensusHeights) == 0 { + suite.Require().Equal(clientState, newClientState) + return + } + suite.Require().Len(consensusHeights, 1) suite.Require().Equal(uint64(0), consensusHeights[0].GetRevisionNumber()) suite.Require().Equal(newClientState.(*solomachine.ClientState).Sequence, consensusHeights[0].GetRevisionHeight()) diff --git a/modules/light-clients/06-solomachine/update.go b/modules/light-clients/06-solomachine/update.go index 359bb118be4..53e4ef26ea2 100644 --- a/modules/light-clients/06-solomachine/update.go +++ b/modules/light-clients/06-solomachine/update.go @@ -1,8 +1,6 @@ package solomachine import ( - "fmt" - errorsmod "cosmossdk.io/errors" storetypes "cosmossdk.io/store/types" @@ -79,10 +77,12 @@ func (cs ClientState) verifyHeader(cdc codec.BinaryCodec, header *Header) error // UpdateState updates the consensus state to the new public key and an incremented sequence. // A list containing the updated consensus height is returned. +// If the provided clientMsg is not of type Header, the handler will no-op and return an empty slice. func (cs ClientState) UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) []exported.Height { smHeader, ok := clientMsg.(*Header) if !ok { - panic(fmt.Errorf("unsupported ClientMessage: %T", clientMsg)) + // clientMsg is invalid Misbehaviour, no update necessary + return []exported.Height{} } // create new solomachine ConsensusState From 67b23cd8ff542730dd51bedae46bea352a654fc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Mon, 20 May 2024 15:23:39 +0200 Subject: [PATCH 03/16] perf: exclude pruning from tendermint update client in ante handler execution (#6278) * performance: exit early on recvpacket to exclude app callbacks * perf: skip pruning on check tx and recheck tx * change fmt.Errorf to errors.New * fix: check execMode simulate in conditional * revert: recv packet changes * fix: account for simulation in pruning check * fix: reuse checkTx ctx * chore: add changelog --------- Co-authored-by: Damian Nolan --- CHANGELOG.md | 1 + modules/light-clients/07-tendermint/update.go | 6 +- .../07-tendermint/update_test.go | 74 +++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5506ddc1cd6..64e4b71993a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (core/02-client, core/03-connection, apps/27-interchain-accounts) [\#6256](https://github.com/cosmos/ibc-go/pull/6256) Add length checking of array fields in messages. * (apps/27-interchain-accounts, apps/tranfer, apps/29-fee) [\#6253](https://github.com/cosmos/ibc-go/pull/6253) Allow channel handshake to succeed if fee middleware is wired up on one side, but not the other. * (apps/transfer) [\#6268](https://github.com/cosmos/ibc-go/pull/6268) Use memo strings instead of JSON keys in `AllowedPacketData` of transfer authorization. +* (core/ante) [\#6278](https://github.com/cosmos/ibc-go/pull/6278) Performance: Exclude pruning from tendermint client updates in ante handler executions. ### Features diff --git a/modules/light-clients/07-tendermint/update.go b/modules/light-clients/07-tendermint/update.go index 1a88eee5859..9a710f9e686 100644 --- a/modules/light-clients/07-tendermint/update.go +++ b/modules/light-clients/07-tendermint/update.go @@ -139,7 +139,11 @@ func (cs ClientState) UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, client return []exported.Height{} } - cs.pruneOldestConsensusState(ctx, cdc, clientStore) + // performance: do not prune in checkTx + // simulation must prune for accurate gas estimation + if (!ctx.IsCheckTx() && !ctx.IsReCheckTx()) || ctx.ExecMode() == sdk.ExecModeSimulate { + cs.pruneOldestConsensusState(ctx, cdc, clientStore) + } // check for duplicate update if _, found := GetConsensusState(clientStore, cdc, header.GetHeight()); found { diff --git a/modules/light-clients/07-tendermint/update_test.go b/modules/light-clients/07-tendermint/update_test.go index 93ef5638e7e..178ffa6195b 100644 --- a/modules/light-clients/07-tendermint/update_test.go +++ b/modules/light-clients/07-tendermint/update_test.go @@ -5,6 +5,8 @@ import ( storetypes "cosmossdk.io/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + cmttypes "github.com/cometbft/cometbft/types" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" @@ -560,6 +562,78 @@ func (suite *TendermintTestSuite) TestUpdateState() { } } +func (suite *TendermintTestSuite) TestUpdateStateCheckTx() { + path := ibctesting.NewPath(suite.chainA, suite.chainB) + path.SetupClients() + + createClientMessage := func() exported.ClientMessage { + trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) + suite.Require().True(ok) + header, err := path.EndpointB.Chain.IBCClientHeader(path.EndpointB.Chain.LatestCommittedHeader, trustedHeight) + suite.Require().NoError(err) + return header + } + + // get the first height as it will be pruned first. + var pruneHeight exported.Height + getFirstHeightCb := func(height exported.Height) bool { + pruneHeight = height + return true + } + ctx := path.EndpointA.Chain.GetContext() + clientStore := path.EndpointA.Chain.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, path.EndpointA.ClientID) + ibctm.IterateConsensusStateAscending(clientStore, getFirstHeightCb) + + // Increment the time by a week + suite.coordinator.IncrementTimeBy(7 * 24 * time.Hour) + + lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(path.EndpointA.ClientID) + suite.Require().True(found) + + ctx = path.EndpointA.Chain.GetContext().WithIsCheckTx(true) + lightClientModule.UpdateState(ctx, path.EndpointA.ClientID, createClientMessage()) + + // Increment the time by another week, then update the client. + // This will cause the first two consensus states to become expired. + suite.coordinator.IncrementTimeBy(7 * 24 * time.Hour) + ctx = path.EndpointA.Chain.GetContext().WithIsCheckTx(true) + lightClientModule.UpdateState(ctx, path.EndpointA.ClientID, createClientMessage()) + + assertPrune := func(pruned bool) { + // check consensus states and associated metadata + consState, ok := path.EndpointA.Chain.GetConsensusState(path.EndpointA.ClientID, pruneHeight) + suite.Require().Equal(!pruned, ok) + + processTime, ok := ibctm.GetProcessedTime(clientStore, pruneHeight) + suite.Require().Equal(!pruned, ok) + + processHeight, ok := ibctm.GetProcessedHeight(clientStore, pruneHeight) + suite.Require().Equal(!pruned, ok) + + consKey := ibctm.GetIterationKey(clientStore, pruneHeight) + + if pruned { + suite.Require().Nil(consState, "expired consensus state not pruned") + suite.Require().Empty(processTime, "processed time metadata not pruned") + suite.Require().Nil(processHeight, "processed height metadata not pruned") + suite.Require().Nil(consKey, "iteration key not pruned") + } else { + suite.Require().NotNil(consState, "expired consensus state pruned") + suite.Require().NotEqual(uint64(0), processTime, "processed time metadata pruned") + suite.Require().NotNil(processHeight, "processed height metadata pruned") + suite.Require().NotNil(consKey, "iteration key pruned") + } + } + + assertPrune(false) + + // simulation mode must prune to calculate gas correctly + ctx = ctx.WithExecMode(sdk.ExecModeSimulate) + lightClientModule.UpdateState(ctx, path.EndpointA.ClientID, createClientMessage()) + + assertPrune(true) +} + func (suite *TendermintTestSuite) TestPruneConsensusState() { // create path and setup clients path := ibctesting.NewPath(suite.chainA, suite.chainB) From 0993246ffe6d9776f4165ede02c49b7bc753a213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Mon, 20 May 2024 15:49:45 +0200 Subject: [PATCH 04/16] perf: minimize necessary execution on recvpacket checktx (#6302) * perf: only perform core ibc logic on recvpacket checktx * try me linter * fix: reorder if and add comment * chore: add changelog entry --- CHANGELOG.md | 1 + modules/core/ante/ante.go | 40 +++++++++++++++++++++++++++++++++- modules/core/ante/ante_test.go | 31 +++++++++++++++++++++++--- 3 files changed, 68 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64e4b71993a..661fcabf228 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,6 +66,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (apps/27-interchain-accounts, apps/tranfer, apps/29-fee) [\#6253](https://github.com/cosmos/ibc-go/pull/6253) Allow channel handshake to succeed if fee middleware is wired up on one side, but not the other. * (apps/transfer) [\#6268](https://github.com/cosmos/ibc-go/pull/6268) Use memo strings instead of JSON keys in `AllowedPacketData` of transfer authorization. * (core/ante) [\#6278](https://github.com/cosmos/ibc-go/pull/6278) Performance: Exclude pruning from tendermint client updates in ante handler executions. +* (core/ante) [\#6302](https://github.com/cosmos/ibc-go/pull/6302) Performance: Skip app callbacks during RecvPacket execution in checkTx within the redundant relay ante handler. ### Features diff --git a/modules/core/ante/ante.go b/modules/core/ante/ante.go index ac4950964a0..4036c046067 100644 --- a/modules/core/ante/ante.go +++ b/modules/core/ante/ante.go @@ -33,10 +33,22 @@ func (rrd RedundantRelayDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula for _, m := range tx.GetMsgs() { switch msg := m.(type) { case *channeltypes.MsgRecvPacket: - response, err := rrd.k.RecvPacket(ctx, msg) + var ( + response *channeltypes.MsgRecvPacketResponse + err error + ) + // when we are in ReCheckTx mode, ctx.IsCheckTx() will also return true + // there we must start the if statement on ctx.IsReCheckTx() to correctly + // determine which mode we are in + if ctx.IsReCheckTx() { + response, err = rrd.k.RecvPacket(ctx, msg) + } else { + response, err = rrd.recvPacketCheckTx(ctx, msg) + } if err != nil { return ctx, err } + if response.Result == channeltypes.NOOP { redundancies++ } @@ -93,6 +105,32 @@ func (rrd RedundantRelayDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula return next(ctx, tx, simulate) } +// recvPacketCheckTx runs a subset of ibc recv packet logic to be used specifically within the RedundantRelayDecorator AnteHandler. +// It only performs core IBC receiving logic and skips any application logic. +func (rrd RedundantRelayDecorator) recvPacketCheckTx(ctx sdk.Context, msg *channeltypes.MsgRecvPacket) (*channeltypes.MsgRecvPacketResponse, error) { + // grab channel capability + _, capability, err := rrd.k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.DestinationPort, msg.Packet.DestinationChannel) + if err != nil { + return nil, errorsmod.Wrap(err, "could not retrieve module from port-id") + } + + // If the packet was already received, perform a no-op + // Use a cached context to prevent accidental state changes + cacheCtx, writeFn := ctx.CacheContext() + err = rrd.k.ChannelKeeper.RecvPacket(cacheCtx, capability, msg.Packet, msg.ProofCommitment, msg.ProofHeight) + + switch err { + case nil: + writeFn() + case channeltypes.ErrNoOpMsg: + return &channeltypes.MsgRecvPacketResponse{Result: channeltypes.NOOP}, nil + default: + return nil, errorsmod.Wrap(err, "receive packet verification failed") + } + + return &channeltypes.MsgRecvPacketResponse{Result: channeltypes.SUCCESS}, nil +} + // updateClientCheckTx runs a subset of ibc client update logic to be used specifically within the RedundantRelayDecorator AnteHandler. // The following function performs ibc client message verification for CheckTx only and state updates in both CheckTx and ReCheckTx. // Note that misbehaviour checks are omitted. diff --git a/modules/core/ante/ante_test.go b/modules/core/ante/ante_test.go index 68b75fab0a7..fdb8d7cdfa8 100644 --- a/modules/core/ante/ante_test.go +++ b/modules/core/ante/ante_test.go @@ -1,17 +1,19 @@ package ante_test import ( + "fmt" "testing" - "github.com/cosmos/btcutil/bech32" "github.com/stretchr/testify/require" testifysuite "github.com/stretchr/testify/suite" codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" + capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" + commitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" host "github.com/cosmos/ibc-go/v8/modules/core/24-host" "github.com/cosmos/ibc-go/v8/modules/core/ante" "github.com/cosmos/ibc-go/v8/modules/core/exported" @@ -49,7 +51,7 @@ func TestAnteTestSuite(t *testing.T) { } // createRecvPacketMessage creates a RecvPacket message for a packet sent from chain A to chain B. -func (suite *AnteTestSuite) createRecvPacketMessage(isRedundant bool) sdk.Msg { +func (suite *AnteTestSuite) createRecvPacketMessage(isRedundant bool) *channeltypes.MsgRecvPacket { sequence, err := suite.path.EndpointA.SendPacket(clienttypes.NewHeight(2, 0), 0, ibctesting.MockPacketData) suite.Require().NoError(err) @@ -345,6 +347,20 @@ func (suite *AnteTestSuite) TestAnteDecorator() { }, nil, }, + { + "success on app callback error, app callbacks are skipped for performance", + func(suite *AnteTestSuite) []sdk.Msg { + suite.chainB.GetSimApp().IBCMockModule.IBCApp.OnRecvPacket = func( + ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress, + ) exported.Acknowledgement { + panic(fmt.Errorf("failed OnRecvPacket mock callback")) + } + + // the RecvPacket message has not been submitted to the chain yet, so it will succeed + return []sdk.Msg{suite.createRecvPacketMessage(false)} + }, + nil, + }, { "no success on one redundant RecvPacket message", func(suite *AnteTestSuite) []sdk.Msg { @@ -461,7 +477,7 @@ func (suite *AnteTestSuite) TestAnteDecorator() { channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(1, 1), "signer"), } }, - bech32.ErrInvalidLength(6), + commitmenttypes.ErrInvalidProof, }, { "no success on one new message and one redundant message in the same block", @@ -487,6 +503,15 @@ func (suite *AnteTestSuite) TestAnteDecorator() { }, channeltypes.ErrRedundantTx, }, + { + "no success on recvPacket checkTx, no capability found", + func(suite *AnteTestSuite) []sdk.Msg { + msg := suite.createRecvPacketMessage(false) + msg.Packet.DestinationPort = "invalid-port" + return []sdk.Msg{msg} + }, + capabilitytypes.ErrCapabilityNotFound, + }, } for _, tc := range testCases { From 60d91e14ffad767f89cceac8092110aa85696b36 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 14:04:14 +0000 Subject: [PATCH 05/16] build(deps): Bump JamesIves/github-pages-deploy-action (#6332) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [JamesIves/github-pages-deploy-action](https://github.com/jamesives/github-pages-deploy-action) from 4.6.0 to 4.6.1. - [Release notes](https://github.com/jamesives/github-pages-deploy-action/releases) - [Commits](https://github.com/jamesives/github-pages-deploy-action/compare/v4.6.0...v4.6.1) --- updated-dependencies: - dependency-name: JamesIves/github-pages-deploy-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> --- .github/workflows/deploy-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 41646fad44e..eee6de1c329 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -27,7 +27,7 @@ jobs: run: make build-docs - name: Deploy 🚀 - uses: JamesIves/github-pages-deploy-action@v4.6.0 + uses: JamesIves/github-pages-deploy-action@v4.6.1 with: branch: gh-pages folder: docs/build From b6e7de5031606cf40566284a263b43c8d3a97ec7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 14:25:31 +0000 Subject: [PATCH 06/16] build(deps): Bump bufbuild/buf-setup-action from 1.31.0 to 1.32.0 (#6326) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [bufbuild/buf-setup-action](https://github.com/bufbuild/buf-setup-action) from 1.31.0 to 1.32.0. - [Release notes](https://github.com/bufbuild/buf-setup-action/releases) - [Commits](https://github.com/bufbuild/buf-setup-action/compare/v1.31.0...v1.32.0) --- updated-dependencies: - dependency-name: bufbuild/buf-setup-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> --- .github/workflows/proto-registry.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/proto-registry.yml b/.github/workflows/proto-registry.yml index 77c9b6766f2..029d3db46e5 100644 --- a/.github/workflows/proto-registry.yml +++ b/.github/workflows/proto-registry.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: bufbuild/buf-setup-action@v1.31.0 + - uses: bufbuild/buf-setup-action@v1.32.0 - uses: bufbuild/buf-push-action@v1 with: input: "proto" From 895aac9d07d2badc52ff0109704704210e496ace Mon Sep 17 00:00:00 2001 From: srdtrk <59252793+srdtrk@users.noreply.github.com> Date: Tue, 21 May 2024 00:18:10 +0800 Subject: [PATCH 07/16] docs: fix kapa analytics config (#6338) --- docs/docusaurus.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 5abc6369b72..e95b8e2b262 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -347,7 +347,7 @@ const config = { src: "https://widget.kapa.ai/kapa-widget.bundle.js", "data-website-id": "806aa1dc-0d46-4563-a8b8-880eecac59f1", "data-project-name": "Interchain", - "data-user-analytics-fingerprint-enabled": true, + "data-user-analytics-fingerprint-enabled": "true", "data-project-color": "#1878FF", "data-modal-title": "IBC Docs AI", "data-modal-disclaimer": "This is a custom LLM for the Inter-Blockchain Communication Protocol in Golang (ibc-go). It is trained on the IBC developer documentation, code base, and resources. Answers are AI-generated. Please use your best judgment before implementing. The bot is not trained on documentation, code, or resources for the Cosmos SDK, CometBFT, CosmJS, CosmWasm, or interchain ecosystem blockchains. Please refer to those specific documentation sites for answers to those questions.", From 56ae97d806339cd83cb346502bae20775a2b7ca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Tue, 21 May 2024 11:28:16 +0200 Subject: [PATCH 08/16] perf: minimize logic on rechecktx for recvpacket (#6280) * perf: minimize logic on rechecktx for recvpacket * refactor: rework layout for recvpacket rechecktx * test: add tests for 04-channel rechecktx func * test: add tests for core ante handler * chore: add comment explaining is rechecktx usage * linter appeasement * chore: add changelog entry * Update modules/core/ante/ante.go Co-authored-by: Carlos Rodriguez * imp: use cached ctx for consistency * refactor: change added test to use expected errors * lint --------- Co-authored-by: Carlos Rodriguez --- CHANGELOG.md | 1 + modules/core/04-channel/keeper/ante.go | 24 ++++++ modules/core/04-channel/keeper/ante_test.go | 64 ++++++++++++++ modules/core/04-channel/keeper/packet.go | 36 +++++--- modules/core/ante/ante.go | 24 +++++- modules/core/ante/ante_test.go | 94 ++++++++++++++++++++- 6 files changed, 227 insertions(+), 16 deletions(-) create mode 100644 modules/core/04-channel/keeper/ante.go create mode 100644 modules/core/04-channel/keeper/ante_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 661fcabf228..86c31d29c68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (apps/transfer) [\#6268](https://github.com/cosmos/ibc-go/pull/6268) Use memo strings instead of JSON keys in `AllowedPacketData` of transfer authorization. * (core/ante) [\#6278](https://github.com/cosmos/ibc-go/pull/6278) Performance: Exclude pruning from tendermint client updates in ante handler executions. * (core/ante) [\#6302](https://github.com/cosmos/ibc-go/pull/6302) Performance: Skip app callbacks during RecvPacket execution in checkTx within the redundant relay ante handler. +* (core/ante) [\#6280](https://github.com/cosmos/ibc-go/pull/6280) Performance: Skip redundant proof checking in RecvPacket execution in reCheckTx within the redundant relay ante handler. ### Features diff --git a/modules/core/04-channel/keeper/ante.go b/modules/core/04-channel/keeper/ante.go new file mode 100644 index 00000000000..ac387569c68 --- /dev/null +++ b/modules/core/04-channel/keeper/ante.go @@ -0,0 +1,24 @@ +package keeper + +import ( + errorsmod "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" +) + +// RecvPacketReCheckTx applies replay protection ensuring that when relay messages are +// re-executed in ReCheckTx, we can appropriately filter out redundant relay transactions. +func (k *Keeper) RecvPacketReCheckTx(ctx sdk.Context, packet types.Packet) error { + channel, found := k.GetChannel(ctx, packet.GetDestPort(), packet.GetDestChannel()) + if !found { + return errorsmod.Wrap(types.ErrChannelNotFound, packet.GetDestChannel()) + } + + if err := k.applyReplayProtection(ctx, packet, channel); err != nil { + return err + } + + return nil +} diff --git a/modules/core/04-channel/keeper/ante_test.go b/modules/core/04-channel/keeper/ante_test.go new file mode 100644 index 00000000000..4bc62ff2ae6 --- /dev/null +++ b/modules/core/04-channel/keeper/ante_test.go @@ -0,0 +1,64 @@ +package keeper_test + +import ( + "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" + ibctesting "github.com/cosmos/ibc-go/v8/testing" +) + +func (suite *KeeperTestSuite) TestRecvPacketReCheckTx() { + var ( + path *ibctesting.Path + packet types.Packet + ) + + testCases := []struct { + name string + malleate func() + expError error + }{ + { + "success", + func() {}, + nil, + }, + { + "channel not found", + func() { + packet.DestinationPort = "invalid-port" //nolint:goconst + }, + types.ErrChannelNotFound, + }, + { + "redundant relay", + func() { + err := suite.chainB.App.GetIBCKeeper().ChannelKeeper.RecvPacketReCheckTx(suite.chainB.GetContext(), packet) + suite.Require().NoError(err) + }, + types.ErrNoOpMsg, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + suite.SetupTest() // reset + path = ibctesting.NewPath(suite.chainA, suite.chainB) + path.Setup() + + sequence, err := path.EndpointA.SendPacket(defaultTimeoutHeight, disabledTimeoutTimestamp, ibctesting.MockPacketData) + suite.Require().NoError(err) + packet = types.NewPacket(ibctesting.MockPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, defaultTimeoutHeight, disabledTimeoutTimestamp) + + tc.malleate() + + err = suite.chainB.App.GetIBCKeeper().ChannelKeeper.RecvPacketReCheckTx(suite.chainB.GetContext(), packet) + + expPass := tc.expError == nil + if expPass { + suite.Require().NoError(err) + } else { + suite.Require().ErrorIs(err, tc.expError) + } + }) + } +} diff --git a/modules/core/04-channel/keeper/packet.go b/modules/core/04-channel/keeper/packet.go index 08d1d678538..b48fd41b667 100644 --- a/modules/core/04-channel/keeper/packet.go +++ b/modules/core/04-channel/keeper/packet.go @@ -188,6 +188,29 @@ func (k *Keeper) RecvPacket( return errorsmod.Wrap(err, "couldn't verify counterparty packet commitment") } + if err := k.applyReplayProtection(ctx, packet, channel); err != nil { + return err + } + + // log that a packet has been received & executed + k.Logger(ctx).Info( + "packet received", + "sequence", strconv.FormatUint(packet.GetSequence(), 10), + "src_port", packet.GetSourcePort(), + "src_channel", packet.GetSourceChannel(), + "dst_port", packet.GetDestPort(), + "dst_channel", packet.GetDestChannel(), + ) + + // emit an event that the relayer can query for + emitRecvPacketEvent(ctx, packet, channel) + + return nil +} + +// applyReplayProtection ensures a packet has not already been received +// and performs the necessary state changes to ensure it cannot be received again. +func (k *Keeper) applyReplayProtection(ctx sdk.Context, packet types.Packet, channel types.Channel) error { // REPLAY PROTECTION: The recvStartSequence will prevent historical proofs from allowing replay // attacks on packets processed in previous lifecycles of a channel. After a successful channel // upgrade all packets under the recvStartSequence will have been processed and thus should be @@ -253,19 +276,6 @@ func (k *Keeper) RecvPacket( k.SetNextSequenceRecv(ctx, packet.GetDestPort(), packet.GetDestChannel(), nextSequenceRecv) } - // log that a packet has been received & executed - k.Logger(ctx).Info( - "packet received", - "sequence", strconv.FormatUint(packet.GetSequence(), 10), - "src_port", packet.GetSourcePort(), - "src_channel", packet.GetSourceChannel(), - "dst_port", packet.GetDestPort(), - "dst_channel", packet.GetDestChannel(), - ) - - // emit an event that the relayer can query for - emitRecvPacketEvent(ctx, packet, channel) - return nil } diff --git a/modules/core/ante/ante.go b/modules/core/ante/ante.go index 4036c046067..c456ed45a6f 100644 --- a/modules/core/ante/ante.go +++ b/modules/core/ante/ante.go @@ -38,10 +38,10 @@ func (rrd RedundantRelayDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula err error ) // when we are in ReCheckTx mode, ctx.IsCheckTx() will also return true - // there we must start the if statement on ctx.IsReCheckTx() to correctly + // therefore we must start the if statement on ctx.IsReCheckTx() to correctly // determine which mode we are in if ctx.IsReCheckTx() { - response, err = rrd.k.RecvPacket(ctx, msg) + response, err = rrd.recvPacketReCheckTx(ctx, msg) } else { response, err = rrd.recvPacketCheckTx(ctx, msg) } @@ -131,6 +131,26 @@ func (rrd RedundantRelayDecorator) recvPacketCheckTx(ctx sdk.Context, msg *chann return &channeltypes.MsgRecvPacketResponse{Result: channeltypes.SUCCESS}, nil } +// recvPacketReCheckTx runs a subset of ibc recv packet logic to be used specifically within the RedundantRelayDecorator AnteHandler. +// It only performs core IBC receiving logic and skips any application logic. +func (rrd RedundantRelayDecorator) recvPacketReCheckTx(ctx sdk.Context, msg *channeltypes.MsgRecvPacket) (*channeltypes.MsgRecvPacketResponse, error) { + // If the packet was already received, perform a no-op + // Use a cached context to prevent accidental state changes + cacheCtx, writeFn := ctx.CacheContext() + err := rrd.k.ChannelKeeper.RecvPacketReCheckTx(cacheCtx, msg.Packet) + + switch err { + case nil: + writeFn() + case channeltypes.ErrNoOpMsg: + return &channeltypes.MsgRecvPacketResponse{Result: channeltypes.NOOP}, nil + default: + return nil, errorsmod.Wrap(err, "receive packet verification failed") + } + + return &channeltypes.MsgRecvPacketResponse{Result: channeltypes.SUCCESS}, nil +} + // updateClientCheckTx runs a subset of ibc client update logic to be used specifically within the RedundantRelayDecorator AnteHandler. // The following function performs ibc client message verification for CheckTx only and state updates in both CheckTx and ReCheckTx. // Note that misbehaviour checks are omitted. diff --git a/modules/core/ante/ante_test.go b/modules/core/ante/ante_test.go index fdb8d7cdfa8..6c59bcd4fc3 100644 --- a/modules/core/ante/ante_test.go +++ b/modules/core/ante/ante_test.go @@ -179,7 +179,7 @@ func (suite *AnteTestSuite) createUpdateClientMessage() sdk.Msg { return msg } -func (suite *AnteTestSuite) TestAnteDecorator() { +func (suite *AnteTestSuite) TestAnteDecoratorCheckTx() { testCases := []struct { name string malleate func(suite *AnteTestSuite) []sdk.Msg @@ -549,3 +549,95 @@ func (suite *AnteTestSuite) TestAnteDecorator() { }) } } + +func (suite *AnteTestSuite) TestAnteDecoratorReCheckTx() { + testCases := []struct { + name string + malleate func(suite *AnteTestSuite) []sdk.Msg + expError error + }{ + { + "success on one new RecvPacket message", + func(suite *AnteTestSuite) []sdk.Msg { + // the RecvPacket message has not been submitted to the chain yet, so it will succeed + return []sdk.Msg{suite.createRecvPacketMessage(false)} + }, + nil, + }, + { + "success on one redundant and one new RecvPacket message", + func(suite *AnteTestSuite) []sdk.Msg { + return []sdk.Msg{ + suite.createRecvPacketMessage(true), + suite.createRecvPacketMessage(false), + } + }, + nil, + }, + { + "success on invalid proof (proof checks occur in checkTx)", + func(suite *AnteTestSuite) []sdk.Msg { + msg := suite.createRecvPacketMessage(false) + msg.ProofCommitment = []byte("invalid-proof") + return []sdk.Msg{msg} + }, + nil, + }, + { + "success on app callback error, app callbacks are skipped for performance", + func(suite *AnteTestSuite) []sdk.Msg { + suite.chainB.GetSimApp().IBCMockModule.IBCApp.OnRecvPacket = func( + ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress, + ) exported.Acknowledgement { + panic(fmt.Errorf("failed OnRecvPacket mock callback")) + } + + // the RecvPacket message has not been submitted to the chain yet, so it will succeed + return []sdk.Msg{suite.createRecvPacketMessage(false)} + }, + nil, + }, + { + "no success on one redundant RecvPacket message", + func(suite *AnteTestSuite) []sdk.Msg { + return []sdk.Msg{suite.createRecvPacketMessage(true)} + }, + channeltypes.ErrRedundantTx, + }, + } + + for _, tc := range testCases { + tc := tc + + suite.Run(tc.name, func() { + // reset suite + suite.SetupTest() + + k := suite.chainB.App.GetIBCKeeper() + decorator := ante.NewRedundantRelayDecorator(k) + + msgs := tc.malleate(suite) + + deliverCtx := suite.chainB.GetContext().WithIsCheckTx(false) + reCheckCtx := suite.chainB.GetContext().WithIsReCheckTx(true) + + // create multimsg tx + txBuilder := suite.chainB.TxConfig.NewTxBuilder() + err := txBuilder.SetMsgs(msgs...) + suite.Require().NoError(err) + tx := txBuilder.GetTx() + + next := func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) { return ctx, nil } + + _, err = decorator.AnteHandle(deliverCtx, tx, false, next) + suite.Require().NoError(err, "antedecorator should not error on DeliverTx") + + _, err = decorator.AnteHandle(reCheckCtx, tx, false, next) + if tc.expError == nil { + suite.Require().NoError(err, "non-strict decorator did not pass as expected") + } else { + suite.Require().ErrorIs(err, tc.expError, "non-strict antehandler did not return error as expected") + } + }) + } +} From 7e7017937079d9523e485d4881df0908c56ebee6 Mon Sep 17 00:00:00 2001 From: srdtrk <59252793+srdtrk@users.noreply.github.com> Date: Tue, 21 May 2024 17:48:04 +0800 Subject: [PATCH 09/16] ci: added paths-ignore to e2e-wasm (#6340) --- .github/workflows/e2e-wasm.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/e2e-wasm.yaml b/.github/workflows/e2e-wasm.yaml index c6cd042584d..fd030761eae 100644 --- a/.github/workflows/e2e-wasm.yaml +++ b/.github/workflows/e2e-wasm.yaml @@ -16,7 +16,10 @@ on: - synchronize # trigger workflow if PR is marked ready for review. - ready_for_review - + paths-ignore: + - 'docs/**' + - '**.md' + - 'LICENSE' jobs: # determine-image-tag will either output the PR number e.g. pr-1234 or the string main. From 074d341e59346e3d1fa906aa57e590cfb52949ca Mon Sep 17 00:00:00 2001 From: srdtrk <59252793+srdtrk@users.noreply.github.com> Date: Tue, 21 May 2024 21:37:22 +0800 Subject: [PATCH 10/16] docs: added a version matrix to callbacks and 08-wasm (#6339) * docs: 08-wasm README.md * docs: added readme for callbacks * docs: added callbacks middleware version matrix to the docs * docs: added 08-wasm versin matrix to docs * imp: added to readme --- .../04-wasm/03-integration.md | 16 ++++++++++ .../02-callbacks/02-integration.md | 15 ++++++++++ .../04-wasm/03-integration.md | 10 +++++++ .../02-callbacks/02-integration.md | 10 +++++++ .../04-wasm/03-integration.md | 10 +++++++ .../02-callbacks/02-integration.md | 10 +++++++ modules/apps/callbacks/README.md | 19 ++++++++++++ modules/light-clients/08-wasm/README.md | 29 +++++++++++++++++++ 8 files changed, 119 insertions(+) create mode 100644 modules/apps/callbacks/README.md create mode 100644 modules/light-clients/08-wasm/README.md diff --git a/docs/docs/03-light-clients/04-wasm/03-integration.md b/docs/docs/03-light-clients/04-wasm/03-integration.md index 33fd75fad9d..7d6d4541430 100644 --- a/docs/docs/03-light-clients/04-wasm/03-integration.md +++ b/docs/docs/03-light-clients/04-wasm/03-integration.md @@ -9,6 +9,22 @@ slug: /ibc/light-clients/wasm/integration Learn how to integrate the `08-wasm` module in a chain binary and about the recommended approaches depending on whether the [`x/wasm` module](https://github.com/CosmWasm/wasmd/tree/main/x/wasm) is already used in the chain. The following document only applies for Cosmos SDK chains. +## Importing the `08-wasm` module + +`08-wasm` has no stable releases yet. To use it, you need to import the git commit that contains the module with the compatible versions of `ibc-go` and `wasmvm`. To do so, run the following command with the desired git commit in your project: + +```sh +go get github.com/cosmos/ibc-go/modules/light-clients/08-wasm@7ee2a2452b79d0bc8316dc622a1243afa058e8cb +``` + +The following table shows the compatibility matrix between the `08-wasm` module, `ibc-go`, and `wasmvm`. + +| **Version** | **Git commit to import** | +|:--------------------------------:|:----------------------------------------:| +| `v0.1.1+ibc-go-v7.3-wasmvm-v1.5` | 7ee2a2452b79d0bc8316dc622a1243afa058e8cb | +| `v0.1.0+ibc-go-v8.0-wasmvm-v1.5` | 57fcdb9a9a9db9b206f7df2f955866dc4e10fef4 | +| `v0.1.0+ibc-go-v7.3-wasmvm-v1.5` | b306e7a706e1f84a5e11af0540987bd68de9bae5 | + ## `app.go` setup The sample code below shows the relevant integration points in `app.go` required to setup the `08-wasm` module in a chain binary. Since `08-wasm` is a light client module itself, please check out as well the section [Integrating light clients](../../01-ibc/02-integration.md#integrating-light-clients) for more information: diff --git a/docs/docs/04-middleware/02-callbacks/02-integration.md b/docs/docs/04-middleware/02-callbacks/02-integration.md index 404a4f22d38..d0ec7e03e1a 100644 --- a/docs/docs/04-middleware/02-callbacks/02-integration.md +++ b/docs/docs/04-middleware/02-callbacks/02-integration.md @@ -19,6 +19,21 @@ The callbacks middleware is a minimal and stateless implementation of the IBC mi The callbacks middleware, as the name suggests, plays the role of an IBC middleware and as such must be configured by chain developers to route and handle IBC messages correctly. For Cosmos SDK chains this setup is done via the `app/app.go` file, where modules are constructed and configured in order to bootstrap the blockchain application. +## Importing the callbacks middleware + +The callbacks middleware has no stable releases yet. To use it, you need to import the git commit that contains the module with the compatible version of `ibc-go`. To do so, run the following command with the desired git commit in your project: + +```sh +go get github.com/cosmos/ibc-go/modules/apps/callbacks@342c00b0f8bd7feeebf0780f208a820b0faf90d1 +``` + +The following table shows the compatibility matrix between the callbacks middleware, `ibc-go`. + +| **Version** | **Git commit to import** | +|:--------------------:|:----------------------------------------:| +| `v0.2.0+ibc-go-v8.0` | 342c00b0f8bd7feeebf0780f208a820b0faf90d1 | +| `v0.1.0+ibc-go-v7.3` | 17cf1260a9cdc5292512acc9bcf6336ef0d917f4 | + ## Configuring an application stack with the callbacks middleware As mentioned in [IBC middleware development](../../01-ibc/04-middleware/02-develop.md) an application stack may be composed of many or no middlewares that nest a base application. diff --git a/docs/versioned_docs/version-v7.5.x/03-light-clients/04-wasm/03-integration.md b/docs/versioned_docs/version-v7.5.x/03-light-clients/04-wasm/03-integration.md index 5e1246a4594..f3388627904 100644 --- a/docs/versioned_docs/version-v7.5.x/03-light-clients/04-wasm/03-integration.md +++ b/docs/versioned_docs/version-v7.5.x/03-light-clients/04-wasm/03-integration.md @@ -9,6 +9,16 @@ slug: /ibc/light-clients/wasm/integration Learn how to integrate the `08-wasm` module in a chain binary and about the recommended approaches depending on whether the [`x/wasm` module](https://github.com/CosmWasm/wasmd/tree/main/x/wasm) is already used in the chain. The following document only applies for Cosmos SDK chains. +## Importing the `08-wasm` module + +`08-wasm` has no stable releases yet. To use it, you need to import the git commit that contains the module with the compatible versions of `ibc-go` and `wasmvm`. To do so, run the following command with the desired git commit in your project: + +```sh +go get github.com/cosmos/ibc-go/modules/light-clients/08-wasm@7ee2a2452b79d0bc8316dc622a1243afa058e8cb +``` + +You can find the version matrix in [here](../../../../docs/03-light-clients/04-wasm/03-integration.md#importing-the-08-wasm-module). + ## `app.go` setup The sample code below shows the relevant integration points in `app.go` required to setup the `08-wasm` module in a chain binary. Since `08-wasm` is a light client module itself, please check out as well the section [Integrating light clients](../../01-ibc/02-integration.md#integrating-light-clients) for more information: diff --git a/docs/versioned_docs/version-v7.5.x/04-middleware/02-callbacks/02-integration.md b/docs/versioned_docs/version-v7.5.x/04-middleware/02-callbacks/02-integration.md index 57f484841d0..85b2a3b5889 100644 --- a/docs/versioned_docs/version-v7.5.x/04-middleware/02-callbacks/02-integration.md +++ b/docs/versioned_docs/version-v7.5.x/04-middleware/02-callbacks/02-integration.md @@ -19,6 +19,16 @@ The callbacks middleware is a minimal and stateless implementation of the IBC mi The callbacks middleware, as the name suggests, plays the role of an IBC middleware and as such must be configured by chain developers to route and handle IBC messages correctly. For Cosmos SDK chains this setup is done via the `app/app.go` file, where modules are constructed and configured in order to bootstrap the blockchain application. +## Importing the callbacks middleware + +The callbacks middleware has no stable releases yet. To use it, you need to import the git commit that contains the module with the compatible version of `ibc-go`. To do so, run the following command with the desired git commit in your project: + +```sh +go get github.com/cosmos/ibc-go/modules/apps/callbacks@17cf1260a9cdc5292512acc9bcf6336ef0d917f4 +``` + +You can find the version matrix in [here](../../../../docs/04-middleware/02-callbacks/02-integration.md#importing-the-callbacks-middleware). + ## Configuring an application stack with the callbacks middleware As mentioned in [IBC middleware development](../../01-ibc/04-middleware/01-develop.md) an application stack may be composed of many or no middlewares that nest a base application. diff --git a/docs/versioned_docs/version-v8.3.x/03-light-clients/04-wasm/03-integration.md b/docs/versioned_docs/version-v8.3.x/03-light-clients/04-wasm/03-integration.md index b1c333660c8..74bc33452de 100644 --- a/docs/versioned_docs/version-v8.3.x/03-light-clients/04-wasm/03-integration.md +++ b/docs/versioned_docs/version-v8.3.x/03-light-clients/04-wasm/03-integration.md @@ -9,6 +9,16 @@ slug: /ibc/light-clients/wasm/integration Learn how to integrate the `08-wasm` module in a chain binary and about the recommended approaches depending on whether the [`x/wasm` module](https://github.com/CosmWasm/wasmd/tree/main/x/wasm) is already used in the chain. The following document only applies for Cosmos SDK chains. +## Importing the `08-wasm` module + +`08-wasm` has no stable releases yet. To use it, you need to import the git commit that contains the module with the compatible versions of `ibc-go` and `wasmvm`. To do so, run the following command with the desired git commit in your project: + +```sh +go get github.com/cosmos/ibc-go/modules/light-clients/08-wasm@57fcdb9a9a9db9b206f7df2f955866dc4e10fef4 +``` + +You can find the version matrix in [here](../../../../docs/03-light-clients/04-wasm/03-integration.md#importing-the-08-wasm-module). + ## `app.go` setup The sample code below shows the relevant integration points in `app.go` required to setup the `08-wasm` module in a chain binary. Since `08-wasm` is a light client module itself, please check out as well the section [Integrating light clients](../../01-ibc/02-integration.md#integrating-light-clients) for more information: diff --git a/docs/versioned_docs/version-v8.3.x/04-middleware/02-callbacks/02-integration.md b/docs/versioned_docs/version-v8.3.x/04-middleware/02-callbacks/02-integration.md index 404a4f22d38..bcc2a2502eb 100644 --- a/docs/versioned_docs/version-v8.3.x/04-middleware/02-callbacks/02-integration.md +++ b/docs/versioned_docs/version-v8.3.x/04-middleware/02-callbacks/02-integration.md @@ -19,6 +19,16 @@ The callbacks middleware is a minimal and stateless implementation of the IBC mi The callbacks middleware, as the name suggests, plays the role of an IBC middleware and as such must be configured by chain developers to route and handle IBC messages correctly. For Cosmos SDK chains this setup is done via the `app/app.go` file, where modules are constructed and configured in order to bootstrap the blockchain application. +## Importing the callbacks middleware + +The callbacks middleware has no stable releases yet. To use it, you need to import the git commit that contains the module with the compatible version of `ibc-go`. To do so, run the following command with the desired git commit in your project: + +```sh +go get github.com/cosmos/ibc-go/modules/apps/callbacks@342c00b0f8bd7feeebf0780f208a820b0faf90d1 +``` + +You can find the version matrix in [here](../../../../docs/04-middleware/02-callbacks/02-integration.md#importing-the-callbacks-middleware). + ## Configuring an application stack with the callbacks middleware As mentioned in [IBC middleware development](../../01-ibc/04-middleware/02-develop.md) an application stack may be composed of many or no middlewares that nest a base application. diff --git a/modules/apps/callbacks/README.md b/modules/apps/callbacks/README.md new file mode 100644 index 00000000000..002fb414e8c --- /dev/null +++ b/modules/apps/callbacks/README.md @@ -0,0 +1,19 @@ +# Callbacks Middleware + +IBC was designed with callbacks between core IBC and IBC applications. IBC apps would send a packet to core IBC, and receive a callback on every step of that packet's lifecycle. This allows IBC applications to be built on top of core IBC, and to be able to execute custom logic on packet lifecycle events (e.g. unescrow tokens for ICS-20). + +This setup worked well for off-chain users interacting with IBC applications. However, we are now seeing the desire for secondary applications (e.g. smart contracts, modules) to call into IBC apps as part of their state machine logic and then do some actions on packet lifecycle events. + +The Callbacks Middleware allows for this functionality by allowing the packets of the underlying IBC applications to register callbacks to secondary applications for lifecycle events. These callbacks are then executed by the Callbacks Middleware when the corresponding packet lifecycle event occurs. + +After much discussion, the design was expanded to [an ADR](/architecture/adr-008-app-caller-cbs), and the Callbacks Middleware is an implementation of that ADR. + +## Version Matrix + +The callbacks middleware has no stable releases yet. To use it, you need to import the git commit that contains the module with the compatible version of `ibc-go`. To do so, run the following command with the desired git commit in your project: + +```sh +go get github.com/cosmos/ibc-go/modules/apps/callbacks@342c00b0f8bd7feeebf0780f208a820b0faf90d1 +``` + +You can find the version matrix for the callbacks middleware [here](https://github.com/cosmos/ibc-go/blob/main/docs/docs/04-middleware/02-callbacks/02-integration.md#importing-the-callbacks-middleware) diff --git a/modules/light-clients/08-wasm/README.md b/modules/light-clients/08-wasm/README.md new file mode 100644 index 00000000000..b9cdf984b2e --- /dev/null +++ b/modules/light-clients/08-wasm/README.md @@ -0,0 +1,29 @@ +# `08-wasm` + +## Overview + +Learn about the `08-wasm` light client proxy module. + +### Context + +Traditionally, light clients used by ibc-go have been implemented only in Go, and since ibc-go v7 (with the release of the 02-client refactor), they are [first-class Cosmos SDK modules](/architecture/adr-010-light-clients-as-sdk-modules). This means that updating existing light client implementations or adding support for new light clients is a multi-step, time-consuming process involving on-chain governance: it is necessary to modify the codebase of ibc-go (if the light client is part of its codebase), re-build chains' binaries, pass a governance proposal and have validators upgrade their nodes. + +### Motivation + +To break the limitation of being able to write light client implementations only in Go, the `08-wasm` adds support to run light clients written in a Wasm-compilable language. The light client byte code implements the entry points of a [CosmWasm](https://docs.cosmwasm.com/docs/) smart contract, and runs inside a Wasm VM. The `08-wasm` module exposes a proxy light client interface that routes incoming messages to the appropriate handler function, inside the Wasm VM, for execution. + +Adding a new light client to a chain is just as simple as submitting a governance proposal with the message that stores the byte code of the light client contract. No coordinated upgrade is needed. When the governance proposal passes and the message is executed, the contract is ready to be instantiated upon receiving a relayer-submitted `MsgCreateClient`. The process of creating a Wasm light client is the same as with a regular light client implemented in Go. + +### Use cases + +- Development of light clients for non-Cosmos ecosystem chains: state machines in other ecosystems are, in many cases, implemented in Rust, and thus there are probably libraries used in their light client implementations for which there is no equivalent in Go. This makes the development of a light client in Go very difficult, but relatively simple to do it in Rust. Therefore, writing a CosmWasm smart contract in Rust that implements the light client algorithm becomes a lower effort. + +## Version Matrix + +`08-wasm` has no stable releases yet. To use it, you need to import the git commit that contains the module with the compatible versions of `ibc-go` and `wasmvm`. To do so, run the following command with the desired git commit in your project: + +```sh +go get github.com/cosmos/ibc-go/modules/light-clients/08-wasm@7ee2a2452b79d0bc8316dc622a1243afa058e8cb +``` + +You can find the compatibility matrix between the `08-wasm` module, `ibc-go`, and `wasmvm` in [here](https://github.com/cosmos/ibc-go/blob/main/docs/docs/03-light-clients/04-wasm/03-integration.md#importing-the-08-wasm-module). From 5069ab673b9cedc88916debaada7fdc2f293e513 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Tue, 21 May 2024 22:20:24 +0200 Subject: [PATCH 11/16] chore: update compatibility tests after v8.3.0 release (#6322) --- .../main/ica-chain-a.json | 1 + .../main/ica-chain-b.json | 1 + .../main/ica-channel-upgrade-chain-a.json | 1 + .../main/ica-channel-upgrade-chain-b.json | 1 + .../main/ica-gov-chain-a.json | 1 + .../main/ica-gov-chain-b.json | 1 + .../main/ica-groups-chain-a.json | 1 + .../main/ica-groups-chain-b.json | 1 + .../main/ica-unordered-channel-chain-a.json | 1 + .../main/ica-unordered-channel-chain-b.json | 1 + .../main/incentivized-ica-chain-a.json | 1 + .../main/incentivized-ica-chain-b.json | 1 + .../main/incentivized-transfer-chain-a.json | 1 + .../main/incentivized-transfer-chain-b.json | 1 + .../main/localhost-ica-chain-a.json | 1 + .../main/localhost-ica-chain-b.json | 1 + .../main/localhost-transfer-chain-a.json | 1 + .../main/localhost-transfer-chain-b.json | 1 + .../main/transfer-authz-chain-a.json | 1 + .../main/transfer-authz-chain-b.json | 1 + .../main/transfer-chain-a.json | 1 + .../main/transfer-chain-b.json | 1 + .../transfer-channel-upgrade-chain-a.json | 1 + .../transfer-channel-upgrade-chain-b.json | 1 + .../release-v7.4.x/ica-chain-a.json | 1 + .../release-v7.4.x/ica-chain-b.json | 1 + .../release-v7.4.x/ica-gov-chain-a.json | 1 + .../release-v7.4.x/ica-gov-chain-b.json | 1 + .../release-v7.4.x/ica-groups-chain-a.json | 1 + .../release-v7.4.x/ica-groups-chain-b.json | 1 + .../incentivized-ica-chain-a.json | 1 + .../incentivized-ica-chain-b.json | 1 + .../incentivized-transfer-chain-a.json | 1 + .../incentivized-transfer-chain-b.json | 1 + .../release-v7.4.x/localhost-ica-chain-a.json | 1 + .../localhost-transfer-chain-a.json | 1 + .../transfer-authz-chain-a.json | 1 + .../transfer-authz-chain-b.json | 1 + .../release-v7.4.x/transfer-chain-a.json | 1 + .../release-v7.4.x/transfer-chain-b.json | 1 + .../release-v7.5.x/ica-chain-a.json | 1 + .../release-v7.5.x/ica-chain-b.json | 1 + .../release-v7.5.x/ica-gov-chain-a.json | 1 + .../release-v7.5.x/ica-gov-chain-b.json | 1 + .../release-v7.5.x/ica-groups-chain-a.json | 1 + .../release-v7.5.x/ica-groups-chain-b.json | 1 + .../release-v7.5.x/ica-queries-chain-a.json | 1 + .../release-v7.5.x/ica-queries-chain-b.json | 1 + .../ica-unordered-channel-chain-a.json | 1 + .../ica-unordered-channel-chain-b.json | 1 + .../incentivized-ica-chain-a.json | 1 + .../incentivized-ica-chain-b.json | 1 + .../incentivized-transfer-chain-a.json | 1 + .../incentivized-transfer-chain-b.json | 1 + .../release-v7.5.x/localhost-ica-chain-a.json | 1 + .../localhost-transfer-chain-a.json | 1 + .../transfer-authz-chain-a.json | 1 + .../transfer-authz-chain-b.json | 1 + .../release-v7.5.x/transfer-chain-a.json | 1 + .../release-v7.5.x/transfer-chain-b.json | 1 + .../release-v8.2.x/ica-chain-a.json | 1 + .../release-v8.2.x/ica-chain-b.json | 1 + .../ica-channel-upgrade-chain-a.json | 1 + .../ica-channel-upgrade-chain-b.json | 1 + .../release-v8.2.x/ica-gov-chain-a.json | 1 + .../release-v8.2.x/ica-gov-chain-b.json | 1 + .../release-v8.2.x/ica-groups-chain-a.json | 1 + .../release-v8.2.x/ica-groups-chain-b.json | 1 + .../ica-unordered-channel-chain-a.json | 1 + .../ica-unordered-channel-chain-b.json | 1 + .../incentivized-ica-chain-a.json | 1 + .../incentivized-ica-chain-b.json | 1 + .../incentivized-transfer-chain-a.json | 1 + .../incentivized-transfer-chain-b.json | 1 + .../release-v8.2.x/localhost-ica-chain-a.json | 1 + .../localhost-transfer-chain-a.json | 1 + .../transfer-authz-chain-a.json | 1 + .../transfer-authz-chain-b.json | 1 + .../release-v8.2.x/transfer-chain-a.json | 1 + .../release-v8.2.x/transfer-chain-b.json | 1 + .../transfer-channel-upgrade-chain-a.json | 1 + .../transfer-channel-upgrade-chain-b.json | 1 + .../release-v8.3.x/ica-chain-a.json | 1 + .../release-v8.3.x/ica-chain-b.json | 1 + .../ica-channel-upgrade-chain-a.json | 1 + .../ica-channel-upgrade-chain-b.json | 1 + .../release-v8.3.x/ica-gov-chain-a.json | 1 + .../release-v8.3.x/ica-gov-chain-b.json | 1 + .../release-v8.3.x/ica-groups-chain-a.json | 1 + .../release-v8.3.x/ica-groups-chain-b.json | 1 + .../release-v8.3.x/ica-queries-chain-a.json | 1 + .../release-v8.3.x/ica-queries-chain-b.json | 1 + .../ica-unordered-channel-chain-a.json | 1 + .../ica-unordered-channel-chain-b.json | 1 + .../incentivized-ica-chain-a.json | 1 + .../incentivized-ica-chain-b.json | 1 + .../incentivized-transfer-chain-a.json | 1 + .../incentivized-transfer-chain-b.json | 1 + .../release-v8.3.x/localhost-ica-chain-a.json | 1 + .../localhost-transfer-chain-a.json | 1 + .../transfer-authz-chain-a.json | 1 + .../transfer-authz-chain-b.json | 1 + .../release-v8.3.x/transfer-chain-a.json | 1 + .../release-v8.3.x/transfer-chain-b.json | 1 + .../transfer-channel-upgrade-chain-a.json | 1 + .../transfer-channel-upgrade-chain-b.json | 1 + .github/workflows/e2e-manual-simd.yaml | 4 +++- CHANGELOG.md | 22 ++++++++++++++++++- RELEASES.md | 2 ++ 109 files changed, 132 insertions(+), 2 deletions(-) diff --git a/.github/compatibility-test-matrices/main/ica-chain-a.json b/.github/compatibility-test-matrices/main/ica-chain-a.json index 2e4b8d6e271..6f45180d1d7 100644 --- a/.github/compatibility-test-matrices/main/ica-chain-a.json +++ b/.github/compatibility-test-matrices/main/ica-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/main/ica-chain-b.json b/.github/compatibility-test-matrices/main/ica-chain-b.json index 4b23f47b3f8..6a89f79a392 100644 --- a/.github/compatibility-test-matrices/main/ica-chain-b.json +++ b/.github/compatibility-test-matrices/main/ica-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/main/ica-channel-upgrade-chain-a.json b/.github/compatibility-test-matrices/main/ica-channel-upgrade-chain-a.json index 55117258a89..551c34419da 100644 --- a/.github/compatibility-test-matrices/main/ica-channel-upgrade-chain-a.json +++ b/.github/compatibility-test-matrices/main/ica-channel-upgrade-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v8.3.0", "v8.2.0" ], "entrypoint": [ diff --git a/.github/compatibility-test-matrices/main/ica-channel-upgrade-chain-b.json b/.github/compatibility-test-matrices/main/ica-channel-upgrade-chain-b.json index ef21e2854dd..52cab2f11ac 100644 --- a/.github/compatibility-test-matrices/main/ica-channel-upgrade-chain-b.json +++ b/.github/compatibility-test-matrices/main/ica-channel-upgrade-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v8.3.0", "v8.2.0" ], "chain-b": [ diff --git a/.github/compatibility-test-matrices/main/ica-gov-chain-a.json b/.github/compatibility-test-matrices/main/ica-gov-chain-a.json index 62fa689d7f6..7486c16f8a6 100644 --- a/.github/compatibility-test-matrices/main/ica-gov-chain-a.json +++ b/.github/compatibility-test-matrices/main/ica-gov-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/main/ica-gov-chain-b.json b/.github/compatibility-test-matrices/main/ica-gov-chain-b.json index f3a0950a8ad..fd80f7f575a 100644 --- a/.github/compatibility-test-matrices/main/ica-gov-chain-b.json +++ b/.github/compatibility-test-matrices/main/ica-gov-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/main/ica-groups-chain-a.json b/.github/compatibility-test-matrices/main/ica-groups-chain-a.json index 359560d9297..865bc9565cb 100644 --- a/.github/compatibility-test-matrices/main/ica-groups-chain-a.json +++ b/.github/compatibility-test-matrices/main/ica-groups-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/main/ica-groups-chain-b.json b/.github/compatibility-test-matrices/main/ica-groups-chain-b.json index c902bfb6f72..67386347420 100644 --- a/.github/compatibility-test-matrices/main/ica-groups-chain-b.json +++ b/.github/compatibility-test-matrices/main/ica-groups-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/main/ica-unordered-channel-chain-a.json b/.github/compatibility-test-matrices/main/ica-unordered-channel-chain-a.json index 66b51f645ea..9d5a1e7e675 100644 --- a/.github/compatibility-test-matrices/main/ica-unordered-channel-chain-a.json +++ b/.github/compatibility-test-matrices/main/ica-unordered-channel-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v8.3.0", "v8.2.0" ], "entrypoint": [ diff --git a/.github/compatibility-test-matrices/main/ica-unordered-channel-chain-b.json b/.github/compatibility-test-matrices/main/ica-unordered-channel-chain-b.json index d3cda9cf973..279760bfb23 100644 --- a/.github/compatibility-test-matrices/main/ica-unordered-channel-chain-b.json +++ b/.github/compatibility-test-matrices/main/ica-unordered-channel-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v8.3.0", "v8.2.0" ], "chain-b": [ diff --git a/.github/compatibility-test-matrices/main/incentivized-ica-chain-a.json b/.github/compatibility-test-matrices/main/incentivized-ica-chain-a.json index 6696832953d..0be0c7a39f3 100644 --- a/.github/compatibility-test-matrices/main/incentivized-ica-chain-a.json +++ b/.github/compatibility-test-matrices/main/incentivized-ica-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/main/incentivized-ica-chain-b.json b/.github/compatibility-test-matrices/main/incentivized-ica-chain-b.json index 95e368039e9..2b4836d72bd 100644 --- a/.github/compatibility-test-matrices/main/incentivized-ica-chain-b.json +++ b/.github/compatibility-test-matrices/main/incentivized-ica-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/main/incentivized-transfer-chain-a.json b/.github/compatibility-test-matrices/main/incentivized-transfer-chain-a.json index c704a6f68e9..69bbf8af9c5 100644 --- a/.github/compatibility-test-matrices/main/incentivized-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/main/incentivized-transfer-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/main/incentivized-transfer-chain-b.json b/.github/compatibility-test-matrices/main/incentivized-transfer-chain-b.json index 11f61cfbbac..ca6ca66cac7 100644 --- a/.github/compatibility-test-matrices/main/incentivized-transfer-chain-b.json +++ b/.github/compatibility-test-matrices/main/incentivized-transfer-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/main/localhost-ica-chain-a.json b/.github/compatibility-test-matrices/main/localhost-ica-chain-a.json index aa4d12bc5c1..3bfdc301413 100644 --- a/.github/compatibility-test-matrices/main/localhost-ica-chain-a.json +++ b/.github/compatibility-test-matrices/main/localhost-ica-chain-a.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0" diff --git a/.github/compatibility-test-matrices/main/localhost-ica-chain-b.json b/.github/compatibility-test-matrices/main/localhost-ica-chain-b.json index ccfd292c186..839595aa257 100644 --- a/.github/compatibility-test-matrices/main/localhost-ica-chain-b.json +++ b/.github/compatibility-test-matrices/main/localhost-ica-chain-b.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0" diff --git a/.github/compatibility-test-matrices/main/localhost-transfer-chain-a.json b/.github/compatibility-test-matrices/main/localhost-transfer-chain-a.json index 264cfb02a8f..61610647bd9 100644 --- a/.github/compatibility-test-matrices/main/localhost-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/main/localhost-transfer-chain-a.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0" diff --git a/.github/compatibility-test-matrices/main/localhost-transfer-chain-b.json b/.github/compatibility-test-matrices/main/localhost-transfer-chain-b.json index 72747eb558e..a1e13c7f379 100644 --- a/.github/compatibility-test-matrices/main/localhost-transfer-chain-b.json +++ b/.github/compatibility-test-matrices/main/localhost-transfer-chain-b.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0" diff --git a/.github/compatibility-test-matrices/main/transfer-authz-chain-a.json b/.github/compatibility-test-matrices/main/transfer-authz-chain-a.json index 84ba42aa585..1fd202b014e 100644 --- a/.github/compatibility-test-matrices/main/transfer-authz-chain-a.json +++ b/.github/compatibility-test-matrices/main/transfer-authz-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0" diff --git a/.github/compatibility-test-matrices/main/transfer-authz-chain-b.json b/.github/compatibility-test-matrices/main/transfer-authz-chain-b.json index 953af8a6679..a703658d00c 100644 --- a/.github/compatibility-test-matrices/main/transfer-authz-chain-b.json +++ b/.github/compatibility-test-matrices/main/transfer-authz-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0" diff --git a/.github/compatibility-test-matrices/main/transfer-chain-a.json b/.github/compatibility-test-matrices/main/transfer-chain-a.json index 5f759dd4e98..2d6643dc68d 100644 --- a/.github/compatibility-test-matrices/main/transfer-chain-a.json +++ b/.github/compatibility-test-matrices/main/transfer-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/main/transfer-chain-b.json b/.github/compatibility-test-matrices/main/transfer-chain-b.json index 7dc6ad968c7..84ff5e70905 100644 --- a/.github/compatibility-test-matrices/main/transfer-chain-b.json +++ b/.github/compatibility-test-matrices/main/transfer-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/main/transfer-channel-upgrade-chain-a.json b/.github/compatibility-test-matrices/main/transfer-channel-upgrade-chain-a.json index 967f2dfe965..664f0383ba8 100644 --- a/.github/compatibility-test-matrices/main/transfer-channel-upgrade-chain-a.json +++ b/.github/compatibility-test-matrices/main/transfer-channel-upgrade-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v8.3.0", "v8.2.0" ], "entrypoint": [ diff --git a/.github/compatibility-test-matrices/main/transfer-channel-upgrade-chain-b.json b/.github/compatibility-test-matrices/main/transfer-channel-upgrade-chain-b.json index b2eb76dc12c..c0e18b16fcc 100644 --- a/.github/compatibility-test-matrices/main/transfer-channel-upgrade-chain-b.json +++ b/.github/compatibility-test-matrices/main/transfer-channel-upgrade-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v8.3.0", "v8.2.0" ], "chain-b": [ diff --git a/.github/compatibility-test-matrices/release-v7.4.x/ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.4.x/ica-chain-a.json index 2e79fbfb7a8..f09bb24fc44 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.4.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/ica-chain-b.json b/.github/compatibility-test-matrices/release-v7.4.x/ica-chain-b.json index a4f5ba6003a..c863ea0712a 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/ica-gov-chain-a.json b/.github/compatibility-test-matrices/release-v7.4.x/ica-gov-chain-a.json index c3713a19869..7dd5eeb843d 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/ica-gov-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/ica-gov-chain-a.json @@ -3,6 +3,7 @@ "release-v7.4.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/ica-gov-chain-b.json b/.github/compatibility-test-matrices/release-v7.4.x/ica-gov-chain-b.json index aae63198dfd..b8a9a9d3570 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/ica-gov-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/ica-gov-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/ica-groups-chain-a.json b/.github/compatibility-test-matrices/release-v7.4.x/ica-groups-chain-a.json index 3a343d8dba9..2600d445330 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/ica-groups-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/ica-groups-chain-a.json @@ -3,6 +3,7 @@ "release-v7.4.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/ica-groups-chain-b.json b/.github/compatibility-test-matrices/release-v7.4.x/ica-groups-chain-b.json index 696d09a60fd..17dc807d75f 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/ica-groups-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/ica-groups-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/incentivized-ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.4.x/incentivized-ica-chain-a.json index d22db4e376d..dfdae0bef3b 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/incentivized-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/incentivized-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.4.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/incentivized-ica-chain-b.json b/.github/compatibility-test-matrices/release-v7.4.x/incentivized-ica-chain-b.json index f511c98c7f2..7b61d245c4c 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/incentivized-ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/incentivized-ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/incentivized-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.4.x/incentivized-transfer-chain-a.json index fdda0a38153..120904e937a 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/incentivized-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/incentivized-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.4.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/incentivized-transfer-chain-b.json b/.github/compatibility-test-matrices/release-v7.4.x/incentivized-transfer-chain-b.json index 39bc990af43..bc855beeae7 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/incentivized-transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/incentivized-transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/localhost-ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.4.x/localhost-ica-chain-a.json index 4059640ddd2..bb4c4aed56c 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/localhost-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/localhost-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.4.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/localhost-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.4.x/localhost-transfer-chain-a.json index f27b4ac403e..2744392355a 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/localhost-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/localhost-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.4.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/transfer-authz-chain-a.json b/.github/compatibility-test-matrices/release-v7.4.x/transfer-authz-chain-a.json index cb94296877e..e63e8a7b607 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/transfer-authz-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/transfer-authz-chain-a.json @@ -3,6 +3,7 @@ "release-v7.4.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/transfer-authz-chain-b.json b/.github/compatibility-test-matrices/release-v7.4.x/transfer-authz-chain-b.json index 6d9fc088d30..58c8cc4d715 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/transfer-authz-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/transfer-authz-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.4.x/transfer-chain-a.json index fbe390e2507..187a3dbaa2a 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.4.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/transfer-chain-b.json b/.github/compatibility-test-matrices/release-v7.4.x/transfer-chain-b.json index c2655811011..c5a15cded6e 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/ica-chain-a.json index 831b79f650f..28f5a47b4f8 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/ica-chain-b.json b/.github/compatibility-test-matrices/release-v7.5.x/ica-chain-b.json index f6cc5bdb8d4..40adfb552c6 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/ica-gov-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/ica-gov-chain-a.json index 712414b6859..21cdade8e72 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/ica-gov-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/ica-gov-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/ica-gov-chain-b.json b/.github/compatibility-test-matrices/release-v7.5.x/ica-gov-chain-b.json index 0f8f28db6ee..f053b4d578d 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/ica-gov-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/ica-gov-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/ica-groups-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/ica-groups-chain-a.json index 18419c31616..69166983d3b 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/ica-groups-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/ica-groups-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/ica-groups-chain-b.json b/.github/compatibility-test-matrices/release-v7.5.x/ica-groups-chain-b.json index 6dd4abe50d5..8938641dd08 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/ica-groups-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/ica-groups-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/ica-queries-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/ica-queries-chain-a.json index 9af2187b44f..044bacf2c9a 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/ica-queries-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/ica-queries-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v7.5.0", "release-v7.5.x" ], "entrypoint": [ diff --git a/.github/compatibility-test-matrices/release-v7.5.x/ica-queries-chain-b.json b/.github/compatibility-test-matrices/release-v7.5.x/ica-queries-chain-b.json index 9af2187b44f..e47d03996a3 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/ica-queries-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/ica-queries-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v7.5.0", "release-v7.5.x" ], "chain-b": [ diff --git a/.github/compatibility-test-matrices/release-v7.5.x/ica-unordered-channel-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/ica-unordered-channel-chain-a.json index 628b48e6691..ee89cb349d1 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/ica-unordered-channel-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/ica-unordered-channel-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "release-v7.5.x" ], diff --git a/.github/compatibility-test-matrices/release-v7.5.x/ica-unordered-channel-chain-b.json b/.github/compatibility-test-matrices/release-v7.5.x/ica-unordered-channel-chain-b.json index b9322e61db4..c65d4efa747 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/ica-unordered-channel-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/ica-unordered-channel-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "release-v7.5.x" ], diff --git a/.github/compatibility-test-matrices/release-v7.5.x/incentivized-ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/incentivized-ica-chain-a.json index e0a332bfe29..7b45c7a6294 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/incentivized-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/incentivized-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/incentivized-ica-chain-b.json b/.github/compatibility-test-matrices/release-v7.5.x/incentivized-ica-chain-b.json index c7fc14afa2c..ab8278e2f3f 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/incentivized-ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/incentivized-ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/incentivized-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/incentivized-transfer-chain-a.json index c3350ab6076..2cb959608dc 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/incentivized-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/incentivized-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/incentivized-transfer-chain-b.json b/.github/compatibility-test-matrices/release-v7.5.x/incentivized-transfer-chain-b.json index 8a70b96b9c7..57e60987b5f 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/incentivized-transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/incentivized-transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/localhost-ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/localhost-ica-chain-a.json index df83c5796e6..dbc954929c3 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/localhost-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/localhost-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/localhost-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/localhost-transfer-chain-a.json index 9c12c2af42a..c7d61755f98 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/localhost-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/localhost-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/transfer-authz-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/transfer-authz-chain-a.json index 47d242d547f..646d14280ee 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/transfer-authz-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/transfer-authz-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/transfer-authz-chain-b.json b/.github/compatibility-test-matrices/release-v7.5.x/transfer-authz-chain-b.json index 438a7bebd06..58f1fe4968e 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/transfer-authz-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/transfer-authz-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/transfer-chain-a.json index b6d2423ca23..74840e2206f 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/transfer-chain-b.json b/.github/compatibility-test-matrices/release-v7.5.x/transfer-chain-b.json index e7b793e9d24..76d03e46da7 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.2.x/ica-chain-a.json b/.github/compatibility-test-matrices/release-v8.2.x/ica-chain-a.json index 08c289a3f8b..9997e845e83 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/ica-chain-a.json @@ -3,6 +3,7 @@ "release-v8.2.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.2.x/ica-chain-b.json b/.github/compatibility-test-matrices/release-v8.2.x/ica-chain-b.json index a4de1853c20..f30678fd877 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.2.x/ica-channel-upgrade-chain-a.json b/.github/compatibility-test-matrices/release-v8.2.x/ica-channel-upgrade-chain-a.json index 6c1bbee0c73..da95757d7ba 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/ica-channel-upgrade-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/ica-channel-upgrade-chain-a.json @@ -3,6 +3,7 @@ "release-v8.2.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "release-v8.2.x" ], diff --git a/.github/compatibility-test-matrices/release-v8.2.x/ica-channel-upgrade-chain-b.json b/.github/compatibility-test-matrices/release-v8.2.x/ica-channel-upgrade-chain-b.json index ab914abf8a3..ab13dadcded 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/ica-channel-upgrade-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/ica-channel-upgrade-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "release-v8.2.x" ], diff --git a/.github/compatibility-test-matrices/release-v8.2.x/ica-gov-chain-a.json b/.github/compatibility-test-matrices/release-v8.2.x/ica-gov-chain-a.json index 08ac5d33487..0707f1ef7a2 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/ica-gov-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/ica-gov-chain-a.json @@ -3,6 +3,7 @@ "release-v8.2.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.2.x/ica-gov-chain-b.json b/.github/compatibility-test-matrices/release-v8.2.x/ica-gov-chain-b.json index cb3fa3f503d..e01e4c57d87 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/ica-gov-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/ica-gov-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.2.x/ica-groups-chain-a.json b/.github/compatibility-test-matrices/release-v8.2.x/ica-groups-chain-a.json index 658160b2bf1..4129bd71b82 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/ica-groups-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/ica-groups-chain-a.json @@ -3,6 +3,7 @@ "release-v8.2.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.2.x/ica-groups-chain-b.json b/.github/compatibility-test-matrices/release-v8.2.x/ica-groups-chain-b.json index 2300a333803..019ee14f8a8 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/ica-groups-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/ica-groups-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.2.x/ica-unordered-channel-chain-a.json b/.github/compatibility-test-matrices/release-v8.2.x/ica-unordered-channel-chain-a.json index 08f47ba02bc..742eb38ad89 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/ica-unordered-channel-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/ica-unordered-channel-chain-a.json @@ -3,6 +3,7 @@ "release-v8.2.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "release-v8.2.x" ], diff --git a/.github/compatibility-test-matrices/release-v8.2.x/ica-unordered-channel-chain-b.json b/.github/compatibility-test-matrices/release-v8.2.x/ica-unordered-channel-chain-b.json index fdd8db8ced8..41eed4dcbfa 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/ica-unordered-channel-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/ica-unordered-channel-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "release-v8.2.x" ], diff --git a/.github/compatibility-test-matrices/release-v8.2.x/incentivized-ica-chain-a.json b/.github/compatibility-test-matrices/release-v8.2.x/incentivized-ica-chain-a.json index 20083ea8692..366aaf81706 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/incentivized-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/incentivized-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v8.2.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.2.x/incentivized-ica-chain-b.json b/.github/compatibility-test-matrices/release-v8.2.x/incentivized-ica-chain-b.json index 426396c8bd7..f501e83465b 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/incentivized-ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/incentivized-ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.2.x/incentivized-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v8.2.x/incentivized-transfer-chain-a.json index 55a7a01ea48..e204aa04cf7 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/incentivized-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/incentivized-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v8.2.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.2.x/incentivized-transfer-chain-b.json b/.github/compatibility-test-matrices/release-v8.2.x/incentivized-transfer-chain-b.json index f91bb5f7c6e..d2198ade38c 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/incentivized-transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/incentivized-transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.2.x/localhost-ica-chain-a.json b/.github/compatibility-test-matrices/release-v8.2.x/localhost-ica-chain-a.json index 3643014a857..23dd1bca0f1 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/localhost-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/localhost-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v8.2.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.2.x/localhost-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v8.2.x/localhost-transfer-chain-a.json index e39ebfc20cf..e7f0ae0247e 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/localhost-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/localhost-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v8.2.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.2.x/transfer-authz-chain-a.json b/.github/compatibility-test-matrices/release-v8.2.x/transfer-authz-chain-a.json index 94f2cfccb8a..298a807ead4 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/transfer-authz-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/transfer-authz-chain-a.json @@ -3,6 +3,7 @@ "release-v8.2.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.2.x/transfer-authz-chain-b.json b/.github/compatibility-test-matrices/release-v8.2.x/transfer-authz-chain-b.json index 9ad2b678b09..8eaeb9bf8f6 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/transfer-authz-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/transfer-authz-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.2.x/transfer-chain-a.json b/.github/compatibility-test-matrices/release-v8.2.x/transfer-chain-a.json index 38c126aa5f8..1500ea1bb12 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v8.2.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.2.x/transfer-chain-b.json b/.github/compatibility-test-matrices/release-v8.2.x/transfer-chain-b.json index 72f6b68b7a4..23360e4cfdb 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.2.x/transfer-channel-upgrade-chain-a.json b/.github/compatibility-test-matrices/release-v8.2.x/transfer-channel-upgrade-chain-a.json index c1c4bb35a87..e0ffaae4975 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/transfer-channel-upgrade-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/transfer-channel-upgrade-chain-a.json @@ -3,6 +3,7 @@ "release-v8.2.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "release-v8.2.x" ], diff --git a/.github/compatibility-test-matrices/release-v8.2.x/transfer-channel-upgrade-chain-b.json b/.github/compatibility-test-matrices/release-v8.2.x/transfer-channel-upgrade-chain-b.json index 5896d3deec0..11002468020 100644 --- a/.github/compatibility-test-matrices/release-v8.2.x/transfer-channel-upgrade-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.2.x/transfer-channel-upgrade-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "release-v8.2.x" ], diff --git a/.github/compatibility-test-matrices/release-v8.3.x/ica-chain-a.json b/.github/compatibility-test-matrices/release-v8.3.x/ica-chain-a.json index 813a387a5d7..ebffd1c0950 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/ica-chain-a.json @@ -3,6 +3,7 @@ "release-v8.3.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.3.x/ica-chain-b.json b/.github/compatibility-test-matrices/release-v8.3.x/ica-chain-b.json index 95674a4c301..2d6c4cba741 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.3.x/ica-channel-upgrade-chain-a.json b/.github/compatibility-test-matrices/release-v8.3.x/ica-channel-upgrade-chain-a.json index 4b1912c32a4..c91005eebca 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/ica-channel-upgrade-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/ica-channel-upgrade-chain-a.json @@ -3,6 +3,7 @@ "release-v8.3.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "release-v8.3.x" ], diff --git a/.github/compatibility-test-matrices/release-v8.3.x/ica-channel-upgrade-chain-b.json b/.github/compatibility-test-matrices/release-v8.3.x/ica-channel-upgrade-chain-b.json index 5a0227ff746..fd64a4eef65 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/ica-channel-upgrade-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/ica-channel-upgrade-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "release-v8.3.x" ], diff --git a/.github/compatibility-test-matrices/release-v8.3.x/ica-gov-chain-a.json b/.github/compatibility-test-matrices/release-v8.3.x/ica-gov-chain-a.json index 7453df5a2cb..2c5801b2e7f 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/ica-gov-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/ica-gov-chain-a.json @@ -3,6 +3,7 @@ "release-v8.3.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.3.x/ica-gov-chain-b.json b/.github/compatibility-test-matrices/release-v8.3.x/ica-gov-chain-b.json index 4bde89de66e..2686e6adcd3 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/ica-gov-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/ica-gov-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.3.x/ica-groups-chain-a.json b/.github/compatibility-test-matrices/release-v8.3.x/ica-groups-chain-a.json index 52235f351c5..4513e64cea1 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/ica-groups-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/ica-groups-chain-a.json @@ -3,6 +3,7 @@ "release-v8.3.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.3.x/ica-groups-chain-b.json b/.github/compatibility-test-matrices/release-v8.3.x/ica-groups-chain-b.json index e019a5616e8..c2709711f5a 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/ica-groups-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/ica-groups-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.3.x/ica-queries-chain-a.json b/.github/compatibility-test-matrices/release-v8.3.x/ica-queries-chain-a.json index c4485bb0b02..fdae0cadda7 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/ica-queries-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/ica-queries-chain-a.json @@ -3,6 +3,7 @@ "release-v8.3.x" ], "chain-b": [ + "v8.3.0", "v7.5.0", "release-v8.3.x" ], diff --git a/.github/compatibility-test-matrices/release-v8.3.x/ica-queries-chain-b.json b/.github/compatibility-test-matrices/release-v8.3.x/ica-queries-chain-b.json index ff1b966f5ba..39efdb64e7e 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/ica-queries-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/ica-queries-chain-b.json @@ -4,6 +4,7 @@ "release-v8.3.x" ], "chain-b": [ + "v8.3.0", "release-v8.3.x" ], "entrypoint": [ diff --git a/.github/compatibility-test-matrices/release-v8.3.x/ica-unordered-channel-chain-a.json b/.github/compatibility-test-matrices/release-v8.3.x/ica-unordered-channel-chain-a.json index 62d3c665cff..7a97ad65395 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/ica-unordered-channel-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/ica-unordered-channel-chain-a.json @@ -3,6 +3,7 @@ "release-v8.3.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "release-v8.3.x" diff --git a/.github/compatibility-test-matrices/release-v8.3.x/ica-unordered-channel-chain-b.json b/.github/compatibility-test-matrices/release-v8.3.x/ica-unordered-channel-chain-b.json index b9d1b4ab770..e79e6f03ec1 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/ica-unordered-channel-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/ica-unordered-channel-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "release-v8.3.x" diff --git a/.github/compatibility-test-matrices/release-v8.3.x/incentivized-ica-chain-a.json b/.github/compatibility-test-matrices/release-v8.3.x/incentivized-ica-chain-a.json index f1e871e5ae4..20bf89e3c7b 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/incentivized-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/incentivized-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v8.3.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.3.x/incentivized-ica-chain-b.json b/.github/compatibility-test-matrices/release-v8.3.x/incentivized-ica-chain-b.json index cd7552628c9..6bb7231a423 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/incentivized-ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/incentivized-ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.3.x/incentivized-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v8.3.x/incentivized-transfer-chain-a.json index ac179162c61..54d14fb6011 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/incentivized-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/incentivized-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v8.3.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.3.x/incentivized-transfer-chain-b.json b/.github/compatibility-test-matrices/release-v8.3.x/incentivized-transfer-chain-b.json index 6bbfd56076e..2df8138fc40 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/incentivized-transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/incentivized-transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.3.x/localhost-ica-chain-a.json b/.github/compatibility-test-matrices/release-v8.3.x/localhost-ica-chain-a.json index ac41d542992..01d25602c9c 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/localhost-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/localhost-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v8.3.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.3.x/localhost-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v8.3.x/localhost-transfer-chain-a.json index f2fe7fa4093..d6b7033d4e4 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/localhost-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/localhost-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v8.3.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.3.x/transfer-authz-chain-a.json b/.github/compatibility-test-matrices/release-v8.3.x/transfer-authz-chain-a.json index 51516741d71..c1744f712c2 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/transfer-authz-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/transfer-authz-chain-a.json @@ -3,6 +3,7 @@ "release-v8.3.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.3.x/transfer-authz-chain-b.json b/.github/compatibility-test-matrices/release-v8.3.x/transfer-authz-chain-b.json index 1dface1752b..7961fa0c5d0 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/transfer-authz-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/transfer-authz-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.3.x/transfer-chain-a.json b/.github/compatibility-test-matrices/release-v8.3.x/transfer-chain-a.json index 8833b286ef4..15e6c5c9b7e 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v8.3.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.3.x/transfer-chain-b.json b/.github/compatibility-test-matrices/release-v8.3.x/transfer-chain-b.json index b65f5c2d9a7..09fe8e07db0 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "v7.5.0", "v7.4.0", diff --git a/.github/compatibility-test-matrices/release-v8.3.x/transfer-channel-upgrade-chain-a.json b/.github/compatibility-test-matrices/release-v8.3.x/transfer-channel-upgrade-chain-a.json index 8c1f0d0b1fe..cd9140406ca 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/transfer-channel-upgrade-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/transfer-channel-upgrade-chain-a.json @@ -3,6 +3,7 @@ "release-v8.3.x" ], "chain-b": [ + "v8.3.0", "v8.2.0", "release-v8.3.x" ], diff --git a/.github/compatibility-test-matrices/release-v8.3.x/transfer-channel-upgrade-chain-b.json b/.github/compatibility-test-matrices/release-v8.3.x/transfer-channel-upgrade-chain-b.json index 8e98221cfe8..8bba5a2bafa 100644 --- a/.github/compatibility-test-matrices/release-v8.3.x/transfer-channel-upgrade-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.3.x/transfer-channel-upgrade-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v8.3.0", "v8.2.0", "release-v8.3.x" ], diff --git a/.github/workflows/e2e-manual-simd.yaml b/.github/workflows/e2e-manual-simd.yaml index 4d8a40c19a5..e89e09971cb 100644 --- a/.github/workflows/e2e-manual-simd.yaml +++ b/.github/workflows/e2e-manual-simd.yaml @@ -35,6 +35,7 @@ on: default: main options: - main + - v8.3.0 - v8.2.0 - v7.4.0 - v7.5.0 @@ -43,12 +44,13 @@ on: required: false type: string chain-b-tag: - default: v8.2.0 + default: v8.3.0 description: 'The tag to use for chain B' required: true type: choice options: - main + - v8.3.0 - v8.2.0 - v7.4.0 - v7.5.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 86c31d29c68..d9299281e19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,7 +63,25 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (apps/27-interchain-accounts) [\#5533](https://github.com/cosmos/ibc-go/pull/5533) ICA host sets the host connection ID on `OnChanOpenTry`, so that ICA controller implementations are not obliged to set the value on `OnChanOpenInit` if they are not able. * (core/02-client, core/03-connection, apps/27-interchain-accounts) [\#6256](https://github.com/cosmos/ibc-go/pull/6256) Add length checking of array fields in messages. + +### Features + +### Bug Fixes + +## [v8.3.0](https://github.com/cosmos/ibc-go/releases/tag/v8.3.0) - 2024-05-16 + +### Dependencies + +* [\#6300](https://github.com/cosmos/ibc-go/pull/6300) Bump Cosmos SDK to v0.50.6 and CometBFT to v0.38.7. + +### State Machine Breaking + +* (light-clients/07-tendermint) [\#6276](https://github.com/cosmos/ibc-go/pull/6276) Fix: No-op to avoid panicking on `UpdateState` for invalid misbehaviour submissions. + +### Improvements + * (apps/27-interchain-accounts, apps/tranfer, apps/29-fee) [\#6253](https://github.com/cosmos/ibc-go/pull/6253) Allow channel handshake to succeed if fee middleware is wired up on one side, but not the other. +* (apps/27-interchain-accounts) [\#6251](https://github.com/cosmos/ibc-go/pull/6251) Use `UNORDERED` as the default ordering for new ICA channels. * (apps/transfer) [\#6268](https://github.com/cosmos/ibc-go/pull/6268) Use memo strings instead of JSON keys in `AllowedPacketData` of transfer authorization. * (core/ante) [\#6278](https://github.com/cosmos/ibc-go/pull/6278) Performance: Exclude pruning from tendermint client updates in ante handler executions. * (core/ante) [\#6302](https://github.com/cosmos/ibc-go/pull/6302) Performance: Skip app callbacks during RecvPacket execution in checkTx within the redundant relay ante handler. @@ -71,8 +89,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Features -* (apps/27-interchain-accounts) [\#5785](https://github.com/cosmos/ibc-go/pull/5785) Introduce a new tx message that ICA host submodule can use to query the chain (only those marked with `module_query_safe`) and write the responses to the acknowledgement. * (core) [\#6055](https://github.com/cosmos/ibc-go/pull/6055) Introduce a new interface `ConsensusHost` used to validate an IBC `ClientState` and `ConsensusState` against the host chain's underlying consensus parameters. +* (core/02-client) [\#5821](https://github.com/cosmos/ibc-go/pull/5821) Add rpc `VerifyMembershipProof` (querier approach for conditional clients). +* (core/04-channel) [\#5788](https://github.com/cosmos/ibc-go/pull/5788) Add `NewErrorAcknowledgementWithCodespace` to allow codespaces in ack errors. +* (apps/27-interchain-accounts) [\#5785](https://github.com/cosmos/ibc-go/pull/5785) Introduce a new tx message that ICA host submodule can use to query the chain (only those marked with `module_query_safe`) and write the responses to the acknowledgement. ### Bug Fixes diff --git a/RELEASES.md b/RELEASES.md index b68108982ca..08d2f2ddb63 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -74,6 +74,7 @@ We reserve the right to drop support for releases if they are deemed unused (for |`v7.4.x`|September 17, 2024| |`v7.5.x`|September 17, 2024| |`v8.2.x`|May 10, 2025| +|`v8.3.x`|May 10, 2025| ### Callbacks middleware @@ -125,6 +126,7 @@ Versions of Golang, Cosmos SDK and CometBFT used by ibc-go in the currently acti | 1.19 | v7.4.0 | v0.47.8 | v0.37.4 | | 1.19 | v7.5.0 | v0.47.11 | v0.37.5 | | 1.21 | v8.2.0 | v0.50.5 | v0.38.5 | +| 1.21 | v8.3.0 | v0.50.6 | v0.38.7 | ### Callbacks middleware From 6993618b62ade4694553bbbf4150752d45e215e7 Mon Sep 17 00:00:00 2001 From: Charly Date: Wed, 22 May 2024 09:31:47 +0200 Subject: [PATCH 12/16] chore: follow up for testing rest of methods on 07-tendermint light client module (#6135) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * move tests from client state to lcm, use lcm entry point * linter * update Initialise test + coverage * linter * import naming * update for pr review * followup to lcm testing pr * linter * update: use lcm entrypoint * update: use lcm entrypoint * linter * linter * merge artifact * add single test for panics cases * a bit of linting a day keeps the doctor away * more linting * fix test * test: fixup testing logic * nit: use errors.New() where no args are present for formatting --------- Co-authored-by: Damian Nolan Co-authored-by: Carlos Rodriguez Co-authored-by: Colin Axnér <25233464+colin-axner@users.noreply.github.com> --- modules/core/02-client/keeper/client_test.go | 4 +- modules/core/02-client/keeper/keeper_test.go | 4 +- .../07-tendermint/light_client_module_test.go | 952 +++++++++++------- .../07-tendermint/misbehaviour_handle_test.go | 18 +- .../07-tendermint/update_test.go | 38 +- .../07-tendermint/upgrade_test.go | 184 +++- 6 files changed, 730 insertions(+), 470 deletions(-) diff --git a/modules/core/02-client/keeper/client_test.go b/modules/core/02-client/keeper/client_test.go index 847bdee6968..51939164938 100644 --- a/modules/core/02-client/keeper/client_test.go +++ b/modules/core/02-client/keeper/client_test.go @@ -508,7 +508,9 @@ func (suite *KeeperTestSuite) TestUpdateClientEventEmission() { path := ibctesting.NewPath(suite.chainA, suite.chainB) path.SetupClients() - trustedHeight := path.EndpointA.GetClientState().(*ibctm.ClientState).LatestHeight + tmClientState, ok := path.EndpointA.GetClientState().(*ibctm.ClientState) + suite.Require().True(ok) + trustedHeight := tmClientState.LatestHeight header, err := path.EndpointA.Counterparty.Chain.IBCClientHeader(path.EndpointA.Counterparty.Chain.LatestCommittedHeader, trustedHeight) suite.Require().NoError(err) diff --git a/modules/core/02-client/keeper/keeper_test.go b/modules/core/02-client/keeper/keeper_test.go index fd120c12b54..739d735ea54 100644 --- a/modules/core/02-client/keeper/keeper_test.go +++ b/modules/core/02-client/keeper/keeper_test.go @@ -570,7 +570,9 @@ func (suite *KeeperTestSuite) TestIBCSoftwareUpgrade() { path := ibctesting.NewPath(suite.chainA, suite.chainB) path.SetupClients() - upgradedClientState = path.EndpointA.GetClientState().(*ibctm.ClientState).ZeroCustomFields() + tmClientState, ok := path.EndpointA.GetClientState().(*ibctm.ClientState) + suite.Require().True(ok) + upgradedClientState = tmClientState.ZeroCustomFields() // use height 1000 to distinguish from old plan plan = upgradetypes.Plan{ diff --git a/modules/light-clients/07-tendermint/light_client_module_test.go b/modules/light-clients/07-tendermint/light_client_module_test.go index 6a30ec13785..77c446e5a70 100644 --- a/modules/light-clients/07-tendermint/light_client_module_test.go +++ b/modules/light-clients/07-tendermint/light_client_module_test.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + errorsmod "cosmossdk.io/errors" upgradetypes "cosmossdk.io/x/upgrade/types" codectypes "github.com/cosmos/cosmos-sdk/codec/types" @@ -27,157 +28,6 @@ var ( solomachineClientID = clienttypes.FormatClientIdentifier(exported.Solomachine, 0) ) -func (suite *TendermintTestSuite) TestStatus() { - var ( - path *ibctesting.Path - clientState *ibctm.ClientState - ) - - testCases := []struct { - name string - malleate func() - expStatus exported.Status - }{ - { - "client is active", - func() {}, - exported.Active, - }, - { - "client is frozen", - func() { - clientState.FrozenHeight = clienttypes.NewHeight(0, 1) - path.EndpointA.SetClientState(clientState) - }, - exported.Frozen, - }, - { - "client status without consensus state", - func() { - var ok bool - clientState.LatestHeight, ok = clientState.LatestHeight.Increment().(clienttypes.Height) - suite.Require().True(ok) - path.EndpointA.SetClientState(clientState) - }, - exported.Expired, - }, - { - "client status is expired", - func() { - suite.coordinator.IncrementTimeBy(clientState.TrustingPeriod) - }, - exported.Expired, - }, - { - "client state not found", - func() { - store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID) - store.Delete(host.ClientStateKey()) - }, - exported.Unknown, - }, - } - - for _, tc := range testCases { - tc := tc - suite.Run(tc.name, func() { - suite.SetupTest() - - path = ibctesting.NewPath(suite.chainA, suite.chainB) - path.SetupClients() - - lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(path.EndpointA.ClientID) - suite.Require().True(found) - - var ok bool - clientState, ok = path.EndpointA.GetClientState().(*ibctm.ClientState) - suite.Require().True(ok) - - tc.malleate() - - status := lightClientModule.Status(suite.chainA.GetContext(), path.EndpointA.ClientID) - suite.Require().Equal(tc.expStatus, status) - }) - - } -} - -func (suite *TendermintTestSuite) TestGetTimestampAtHeight() { - var ( - path *ibctesting.Path - height exported.Height - ) - expectedTimestamp := time.Unix(1, 0) - - testCases := []struct { - name string - malleate func() - expErr error - }{ - { - "success", - func() {}, - nil, - }, - { - "failure: client state not found for height", - func() { - store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID) - store.Delete(host.ClientStateKey()) - }, - clienttypes.ErrClientNotFound, - }, - { - "failure: consensus state not found for height", - func() { - clientState, ok := path.EndpointA.GetClientState().(*ibctm.ClientState) - suite.Require().True(ok) - height = clientState.LatestHeight.Increment() - }, - clienttypes.ErrConsensusStateNotFound, - }, - } - - for _, tc := range testCases { - tc := tc - suite.Run(tc.name, func() { - suite.SetupTest() - - path = ibctesting.NewPath(suite.chainA, suite.chainB) - path.SetupClients() - - clientState, ok := path.EndpointA.GetClientState().(*ibctm.ClientState) - suite.Require().True(ok) - height = clientState.LatestHeight - - // grab consensusState from store and update with a predefined timestamp - consensusState := path.EndpointA.GetConsensusState(height) - tmConsensusState, ok := consensusState.(*ibctm.ConsensusState) - suite.Require().True(ok) - - tmConsensusState.Timestamp = expectedTimestamp - path.EndpointA.SetConsensusState(tmConsensusState, height) - - lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(path.EndpointA.ClientID) - suite.Require().True(found) - - tc.malleate() - - timestamp, err := lightClientModule.TimestampAtHeight(suite.chainA.GetContext(), path.EndpointA.ClientID, height) - - expPass := tc.expErr == nil - if expPass { - suite.Require().NoError(err) - - expectedTimestamp := uint64(expectedTimestamp.UnixNano()) - suite.Require().Equal(expectedTimestamp, timestamp) - } else { - suite.Require().ErrorIs(err, tc.expErr) - } - }) - } -} - func (suite *TendermintTestSuite) TestInitialize() { var consensusState exported.ConsensusState var clientState exported.ClientState @@ -267,11 +117,8 @@ func (suite *TendermintTestSuite) TestInitialize() { } } -func (suite *TendermintTestSuite) TestRecoverClient() { - var ( - subjectClientID, substituteClientID string - subjectClientState exported.ClientState - ) +func (suite *TendermintTestSuite) TestVerifyClientMessage() { + var path *ibctesting.Path testCases := []struct { name string @@ -280,35 +127,14 @@ func (suite *TendermintTestSuite) TestRecoverClient() { }{ { "success", - func() { - }, + func() {}, nil, }, { - "cannot parse malformed substitute client ID", - func() { - substituteClientID = ibctesting.InvalidID - }, - host.ErrInvalidID, - }, - { - "substitute client ID does not contain 07-tendermint prefix", - func() { - substituteClientID = solomachineClientID - }, - clienttypes.ErrInvalidClientType, - }, - { - "cannot find subject client state", - func() { - subjectClientID = tmClientID - }, - clienttypes.ErrClientNotFound, - }, - { - "cannot find substitute client state", + "failure: client state not found", func() { - substituteClientID = tmClientID + store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID) + store.Delete(host.ClientStateKey()) }, clienttypes.ErrClientNotFound, }, @@ -317,54 +143,128 @@ func (suite *TendermintTestSuite) TestRecoverClient() { for _, tc := range testCases { tc := tc suite.Run(tc.name, func() { - suite.SetupTest() // reset - ctx := suite.chainA.GetContext() + suite.SetupTest() - subjectPath := ibctesting.NewPath(suite.chainA, suite.chainB) - subjectPath.SetupClients() - subjectClientID = subjectPath.EndpointA.ClientID - subjectClientState = suite.chainA.GetClientState(subjectClientID) + path = ibctesting.NewPath(suite.chainA, suite.chainB) + path.SetupClients() - substitutePath := ibctesting.NewPath(suite.chainA, suite.chainB) - substitutePath.SetupClients() - substituteClientID = substitutePath.EndpointA.ClientID + lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(path.EndpointA.ClientID) + suite.Require().True(found) - tmClientState, ok := subjectClientState.(*ibctm.ClientState) + // ensure counterparty state is committed + suite.coordinator.CommitBlock(suite.chainB) + trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - tmClientState.FrozenHeight = tmClientState.LatestHeight - suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(ctx, subjectPath.EndpointA.ClientID, tmClientState) - - lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(subjectClientID) - suite.Require().True(found) + header, err := path.EndpointA.Counterparty.Chain.IBCClientHeader(path.EndpointA.Counterparty.Chain.LatestCommittedHeader, trustedHeight) + suite.Require().NoError(err) tc.malleate() - err := lightClientModule.RecoverClient(ctx, subjectClientID, substituteClientID) + err = lightClientModule.VerifyClientMessage(suite.chainA.GetContext(), path.EndpointA.ClientID, header) expPass := tc.expErr == nil if expPass { suite.Require().NoError(err) - - // assert that status of subject client is now Active - clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, subjectClientID) - tmClientState, ok := subjectPath.EndpointA.GetClientState().(*ibctm.ClientState) - suite.Require().True(ok) - suite.Require().Equal(exported.Active, tmClientState.Status(ctx, clientStore, suite.chainA.App.AppCodec())) } else { - suite.Require().Error(err) suite.Require().ErrorIs(err, tc.expErr) } }) } } -func (suite *TendermintTestSuite) TestVerifyUpgradeAndUpdateState() { +func (suite *TendermintTestSuite) TestCheckForMisbehaviourPanicsOnClientStateNotFound() { + suite.SetupTest() + + path := ibctesting.NewPath(suite.chainA, suite.chainB) + path.SetupClients() + + lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(path.EndpointA.ClientID) + suite.Require().True(found) + + // ensure counterparty state is committed + suite.coordinator.CommitBlock(suite.chainB) + trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) + suite.Require().True(ok) + header, err := path.EndpointA.Counterparty.Chain.IBCClientHeader(path.EndpointA.Counterparty.Chain.LatestCommittedHeader, trustedHeight) + suite.Require().NoError(err) + + // delete client state + store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID) + store.Delete(host.ClientStateKey()) + + suite.Require().PanicsWithError(errorsmod.Wrap(clienttypes.ErrClientNotFound, path.EndpointA.ClientID).Error(), + func() { + lightClientModule.CheckForMisbehaviour(suite.chainA.GetContext(), path.EndpointA.ClientID, header) + }, + ) +} + +func (suite *TendermintTestSuite) TestUpdateStateOnMisbehaviourPanicsOnClientStateNotFound() { + suite.SetupTest() + + path := ibctesting.NewPath(suite.chainA, suite.chainB) + path.SetupClients() + + lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(path.EndpointA.ClientID) + suite.Require().True(found) + + // ensure counterparty state is committed + suite.coordinator.CommitBlock(suite.chainB) + trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) + suite.Require().True(ok) + header, err := path.EndpointA.Counterparty.Chain.IBCClientHeader(path.EndpointA.Counterparty.Chain.LatestCommittedHeader, trustedHeight) + suite.Require().NoError(err) + + // delete client state + store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID) + store.Delete(host.ClientStateKey()) + + suite.Require().PanicsWithError( + errorsmod.Wrap(clienttypes.ErrClientNotFound, path.EndpointA.ClientID).Error(), + func() { + lightClientModule.UpdateStateOnMisbehaviour(suite.chainA.GetContext(), path.EndpointA.ClientID, header) + }, + ) +} + +func (suite *TendermintTestSuite) TestUpdateStatePanicsOnClientStateNotFound() { + suite.SetupTest() + + path := ibctesting.NewPath(suite.chainA, suite.chainB) + path.SetupClients() + + lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(path.EndpointA.ClientID) + suite.Require().True(found) + + // ensure counterparty state is committed + suite.coordinator.CommitBlock(suite.chainB) + trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) + suite.Require().True(ok) + header, err := path.EndpointA.Counterparty.Chain.IBCClientHeader(path.EndpointA.Counterparty.Chain.LatestCommittedHeader, trustedHeight) + suite.Require().NoError(err) + + // delete client state + store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID) + store.Delete(host.ClientStateKey()) + + suite.Require().PanicsWithError( + errorsmod.Wrap(clienttypes.ErrClientNotFound, path.EndpointA.ClientID).Error(), + func() { + lightClientModule.UpdateState(suite.chainA.GetContext(), path.EndpointA.ClientID, header) + }, + ) +} + +func (suite *TendermintTestSuite) TestVerifyMembership() { var ( - clientID string - path *ibctesting.Path - upgradedClientState exported.ClientState - upgradedClientStateAny, upgradedConsensusStateAny *codectypes.Any - upgradedClientStateProof, upgradedConsensusStateProof []byte + testingpath *ibctesting.Path + delayTimePeriod uint64 + delayBlockPeriod uint64 + err error + proofHeight exported.Height + proof []byte + path exported.Path + value []byte ) testCases := []struct { @@ -373,178 +273,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgradeAndUpdateState() { expErr error }{ { - "success", - func() { - // upgrade height is at next block - upgradeHeight := clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - // zero custom fields and store in upgrade store - zeroedUpgradedClient := upgradedClientState.(*ibctm.ClientState).ZeroCustomFields() - zeroedUpgradedClientAny, err := codectypes.NewAnyWithValue(zeroedUpgradedClient) - suite.Require().NoError(err) - - err = suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetRevisionHeight()), suite.chainB.Codec.MustMarshal(zeroedUpgradedClientAny)) - suite.Require().NoError(err) - - err = suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(upgradeHeight.GetRevisionHeight()), suite.chainB.Codec.MustMarshal(upgradedConsensusStateAny)) - suite.Require().NoError(err) - - // commit upgrade store changes and update clients - suite.coordinator.CommitBlock(suite.chainB) - err = path.EndpointA.UpdateClient() - suite.Require().NoError(err) - - upgradedClientStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetRevisionHeight())), path.EndpointA.GetClientLatestHeight().GetRevisionHeight()) - upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(upgradeHeight.GetRevisionHeight())), path.EndpointA.GetClientLatestHeight().GetRevisionHeight()) - }, - nil, - }, - { - "cannot find client state", - func() { - clientID = tmClientID - }, - clienttypes.ErrClientNotFound, - }, - { - "upgraded client state is not for tendermint client state", - func() { - upgradedClientStateAny = &codectypes.Any{ - Value: []byte("invalid client state bytes"), - } - }, - clienttypes.ErrInvalidClient, - }, - { - "upgraded consensus state is not tendermint consensus state", - func() { - upgradedConsensusStateAny = &codectypes.Any{ - Value: []byte("invalid consensus state bytes"), - } - }, - clienttypes.ErrInvalidConsensus, - }, - { - "upgraded client state height is not greater than current height", - func() { - // upgrade height is at next block - upgradeHeight := clienttypes.NewHeight(1, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - // zero custom fields and store in upgrade store - zeroedUpgradedClient := upgradedClientState.(*ibctm.ClientState).ZeroCustomFields() - zeroedUpgradedClientAny, err := codectypes.NewAnyWithValue(zeroedUpgradedClient) - suite.Require().NoError(err) - - err = suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetRevisionHeight()), suite.chainB.Codec.MustMarshal(zeroedUpgradedClientAny)) - suite.Require().NoError(err) - - err = suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(upgradeHeight.GetRevisionHeight()), suite.chainB.Codec.MustMarshal(upgradedConsensusStateAny)) - suite.Require().NoError(err) - - // change upgraded client state height to be lower than current client state height - tmClient, ok := upgradedClientState.(*ibctm.ClientState) - suite.Require().True(ok) - - newLatestheight, ok := path.EndpointA.GetClientLatestHeight().Decrement() - suite.Require().True(ok) - - tmClient.LatestHeight, ok = newLatestheight.(clienttypes.Height) - suite.Require().True(ok) - upgradedClientStateAny, err = codectypes.NewAnyWithValue(tmClient) - suite.Require().NoError(err) - - suite.coordinator.CommitBlock(suite.chainB) - err = path.EndpointA.UpdateClient() - suite.Require().NoError(err) - - upgradedClientStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetRevisionHeight())), path.EndpointA.GetClientLatestHeight().GetRevisionHeight()) - upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(upgradeHeight.GetRevisionHeight())), path.EndpointA.GetClientLatestHeight().GetRevisionHeight()) - }, - ibcerrors.ErrInvalidHeight, - }, - } - - for _, tc := range testCases { - tc := tc - suite.Run(tc.name, func() { - suite.SetupTest() // reset - - path = ibctesting.NewPath(suite.chainA, suite.chainB) - path.SetupClients() - - clientID = path.EndpointA.ClientID - clientState, ok := path.EndpointA.GetClientState().(*ibctm.ClientState) - suite.Require().True(ok) - revisionNumber := clienttypes.ParseChainID(clientState.ChainId) - - newUnbondindPeriod := ubdPeriod + trustingPeriod - newChainID, err := clienttypes.SetRevisionNumber(clientState.ChainId, revisionNumber+1) - suite.Require().NoError(err) - - upgradedClientState = ibctm.NewClientState(newChainID, ibctm.DefaultTrustLevel, trustingPeriod, newUnbondindPeriod, maxClockDrift, clienttypes.NewHeight(revisionNumber+1, clientState.LatestHeight.GetRevisionHeight()+1), commitmenttypes.GetSDKSpecs(), upgradePath) - upgradedClientStateAny, err = codectypes.NewAnyWithValue(upgradedClientState) - suite.Require().NoError(err) - - nextValsHash := sha256.Sum256([]byte("new-nextValsHash")) - upgradedConsensusState := ibctm.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("new-hash")), nextValsHash[:]) - - upgradedConsensusStateAny, err = codectypes.NewAnyWithValue(upgradedConsensusState) - suite.Require().NoError(err) - - tc.malleate() - - lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(clientID) - suite.Require().True(found) - - err = lightClientModule.VerifyUpgradeAndUpdateState( - suite.chainA.GetContext(), - clientID, - upgradedClientStateAny.Value, - upgradedConsensusStateAny.Value, - upgradedClientStateProof, - upgradedConsensusStateProof, - ) - - expPass := tc.expErr == nil - if expPass { - suite.Require().NoError(err) - - expClientState := path.EndpointA.GetClientState() - expClientStateBz := suite.chainA.Codec.MustMarshal(expClientState) - suite.Require().Equal(upgradedClientStateAny.Value, expClientStateBz) - - expConsensusState := ibctm.NewConsensusState(upgradedConsensusState.Timestamp, commitmenttypes.NewMerkleRoot([]byte(ibctm.SentinelRoot)), upgradedConsensusState.NextValidatorsHash) - expConsensusStateBz := suite.chainA.Codec.MustMarshal(expConsensusState) - - consensusStateBz := suite.chainA.Codec.MustMarshal(path.EndpointA.GetConsensusState(path.EndpointA.GetClientLatestHeight())) - suite.Require().Equal(expConsensusStateBz, consensusStateBz) - } else { - suite.Require().Error(err) - suite.Require().ErrorIs(err, tc.expErr) - } - }) - } -} - -func (suite *TendermintTestSuite) TestVerifyMembership() { - var ( - testingpath *ibctesting.Path - delayTimePeriod uint64 - delayBlockPeriod uint64 - err error - proofHeight exported.Height - proof []byte - path exported.Path - value []byte - ) - - testCases := []struct { - name string - malleate func() - expErr error - }{ - { - "successful ClientState verification", + "successful ClientState verification", func() { // default proof construction uses ClientState }, @@ -740,7 +469,7 @@ func (suite *TendermintTestSuite) TestVerifyMembership() { commitmenttypes.ErrInvalidMerkleProof, }, { - "client state not found for height", + "client state not found", func() { store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), testingpath.EndpointA.ClientID) store.Delete(host.ClientStateKey()) @@ -969,7 +698,7 @@ func (suite *TendermintTestSuite) TestVerifyNonMembership() { commitmenttypes.ErrInvalidMerkleProof, }, { - "client state not found for height", + "client state not found", func() { store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), testingpath.EndpointA.ClientID) store.Delete(host.ClientStateKey()) @@ -1020,3 +749,458 @@ func (suite *TendermintTestSuite) TestVerifyNonMembership() { }) } } + +func (suite *TendermintTestSuite) TestStatus() { + var ( + path *ibctesting.Path + clientState *ibctm.ClientState + ) + + testCases := []struct { + name string + malleate func() + expStatus exported.Status + }{ + { + "client is active", + func() {}, + exported.Active, + }, + { + "client is frozen", + func() { + clientState.FrozenHeight = clienttypes.NewHeight(0, 1) + path.EndpointA.SetClientState(clientState) + }, + exported.Frozen, + }, + { + "client status without consensus state", + func() { + newLatestHeight, ok := clientState.LatestHeight.Increment().(clienttypes.Height) + suite.Require().True(ok) + clientState.LatestHeight = newLatestHeight + path.EndpointA.SetClientState(clientState) + }, + exported.Expired, + }, + { + "client status is expired", + func() { + suite.coordinator.IncrementTimeBy(clientState.TrustingPeriod) + }, + exported.Expired, + }, + { + "client state not found", + func() { + store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID) + store.Delete(host.ClientStateKey()) + }, + exported.Unknown, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + suite.SetupTest() + + path = ibctesting.NewPath(suite.chainA, suite.chainB) + path.SetupClients() + + lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(path.EndpointA.ClientID) + suite.Require().True(found) + + var ok bool + clientState, ok = path.EndpointA.GetClientState().(*ibctm.ClientState) + suite.Require().True(ok) + + tc.malleate() + + status := lightClientModule.Status(suite.chainA.GetContext(), path.EndpointA.ClientID) + suite.Require().Equal(tc.expStatus, status) + }) + + } +} + +func (suite *TendermintTestSuite) TestLatestHeight() { + var ( + path *ibctesting.Path + height exported.Height + ) + + testCases := []struct { + name string + malleate func() + expHeight exported.Height + }{ + { + "success", + func() {}, + clienttypes.Height{RevisionNumber: 0x1, RevisionHeight: 0x4}, + }, + { + "client state not found", + func() { + store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID) + store.Delete(host.ClientStateKey()) + }, + clienttypes.ZeroHeight(), + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + suite.SetupTest() + + path = ibctesting.NewPath(suite.chainA, suite.chainB) + path.SetupClients() + + lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(path.EndpointA.ClientID) + suite.Require().True(found) + + tc.malleate() + + height = lightClientModule.LatestHeight(suite.chainA.GetContext(), path.EndpointA.ClientID) + suite.Require().Equal(tc.expHeight, height) + }) + } +} + +func (suite *TendermintTestSuite) TestGetTimestampAtHeight() { + var ( + path *ibctesting.Path + height exported.Height + ) + expectedTimestamp := time.Unix(1, 0) + + testCases := []struct { + name string + malleate func() + expErr error + }{ + { + "success", + func() {}, + nil, + }, + { + "failure: client state not found", + func() { + store := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID) + store.Delete(host.ClientStateKey()) + }, + clienttypes.ErrClientNotFound, + }, + { + "failure: consensus state not found for height", + func() { + clientState, ok := path.EndpointA.GetClientState().(*ibctm.ClientState) + suite.Require().True(ok) + height = clientState.LatestHeight.Increment() + }, + clienttypes.ErrConsensusStateNotFound, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + suite.SetupTest() + + path = ibctesting.NewPath(suite.chainA, suite.chainB) + path.SetupClients() + + clientState, ok := path.EndpointA.GetClientState().(*ibctm.ClientState) + suite.Require().True(ok) + height = clientState.LatestHeight + + // grab consensusState from store and update with a predefined timestamp + consensusState := path.EndpointA.GetConsensusState(height) + tmConsensusState, ok := consensusState.(*ibctm.ConsensusState) + suite.Require().True(ok) + + tmConsensusState.Timestamp = expectedTimestamp + path.EndpointA.SetConsensusState(tmConsensusState, height) + + lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(path.EndpointA.ClientID) + suite.Require().True(found) + + tc.malleate() + + timestamp, err := lightClientModule.TimestampAtHeight(suite.chainA.GetContext(), path.EndpointA.ClientID, height) + + expPass := tc.expErr == nil + if expPass { + suite.Require().NoError(err) + + expectedTimestamp := uint64(expectedTimestamp.UnixNano()) + suite.Require().Equal(expectedTimestamp, timestamp) + } else { + suite.Require().ErrorIs(err, tc.expErr) + } + }) + } +} + +func (suite *TendermintTestSuite) TestRecoverClient() { + var ( + subjectClientID, substituteClientID string + subjectClientState exported.ClientState + ) + + testCases := []struct { + name string + malleate func() + expErr error + }{ + { + "success", + func() { + }, + nil, + }, + { + "cannot parse malformed substitute client ID", + func() { + substituteClientID = ibctesting.InvalidID + }, + host.ErrInvalidID, + }, + { + "substitute client ID does not contain 07-tendermint prefix", + func() { + substituteClientID = solomachineClientID + }, + clienttypes.ErrInvalidClientType, + }, + { + "cannot find subject client state", + func() { + subjectClientID = tmClientID + }, + clienttypes.ErrClientNotFound, + }, + { + "cannot find substitute client state", + func() { + substituteClientID = tmClientID + }, + clienttypes.ErrClientNotFound, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + suite.SetupTest() // reset + ctx := suite.chainA.GetContext() + + subjectPath := ibctesting.NewPath(suite.chainA, suite.chainB) + subjectPath.SetupClients() + subjectClientID = subjectPath.EndpointA.ClientID + subjectClientState = suite.chainA.GetClientState(subjectClientID) + + substitutePath := ibctesting.NewPath(suite.chainA, suite.chainB) + substitutePath.SetupClients() + substituteClientID = substitutePath.EndpointA.ClientID + + tmClientState, ok := subjectClientState.(*ibctm.ClientState) + suite.Require().True(ok) + tmClientState.FrozenHeight = tmClientState.LatestHeight + suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(ctx, subjectPath.EndpointA.ClientID, tmClientState) + + lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(subjectClientID) + suite.Require().True(found) + + tc.malleate() + + err := lightClientModule.RecoverClient(ctx, subjectClientID, substituteClientID) + + expPass := tc.expErr == nil + if expPass { + suite.Require().NoError(err) + + // assert that status of subject client is now Active + clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, subjectClientID) + tmClientState, ok := subjectPath.EndpointA.GetClientState().(*ibctm.ClientState) + suite.Require().True(ok) + suite.Require().Equal(exported.Active, tmClientState.Status(ctx, clientStore, suite.chainA.App.AppCodec())) + } else { + suite.Require().Error(err) + suite.Require().ErrorIs(err, tc.expErr) + } + }) + } +} + +func (suite *TendermintTestSuite) TestVerifyUpgradeAndUpdateState() { + var ( + clientID string + path *ibctesting.Path + upgradedClientState exported.ClientState + upgradedClientStateAny, upgradedConsensusStateAny *codectypes.Any + upgradedClientStateProof, upgradedConsensusStateProof []byte + ) + + testCases := []struct { + name string + malleate func() + expErr error + }{ + { + "success", + func() { + // upgrade height is at next block + upgradeHeight := clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) + + // zero custom fields and store in upgrade store + zeroedUpgradedClient := upgradedClientState.(*ibctm.ClientState).ZeroCustomFields() + zeroedUpgradedClientAny, err := codectypes.NewAnyWithValue(zeroedUpgradedClient) + suite.Require().NoError(err) + + err = suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetRevisionHeight()), suite.chainB.Codec.MustMarshal(zeroedUpgradedClientAny)) + suite.Require().NoError(err) + + err = suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(upgradeHeight.GetRevisionHeight()), suite.chainB.Codec.MustMarshal(upgradedConsensusStateAny)) + suite.Require().NoError(err) + + // commit upgrade store changes and update clients + suite.coordinator.CommitBlock(suite.chainB) + err = path.EndpointA.UpdateClient() + suite.Require().NoError(err) + + upgradedClientStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetRevisionHeight())), path.EndpointA.GetClientLatestHeight().GetRevisionHeight()) + upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(upgradeHeight.GetRevisionHeight())), path.EndpointA.GetClientLatestHeight().GetRevisionHeight()) + }, + nil, + }, + { + "cannot find client state", + func() { + clientID = tmClientID + }, + clienttypes.ErrClientNotFound, + }, + { + "upgraded client state is not for tendermint client state", + func() { + upgradedClientStateAny = &codectypes.Any{ + Value: []byte("invalid client state bytes"), + } + }, + clienttypes.ErrInvalidClient, + }, + { + "upgraded consensus state is not tendermint consensus state", + func() { + upgradedConsensusStateAny = &codectypes.Any{ + Value: []byte("invalid consensus state bytes"), + } + }, + clienttypes.ErrInvalidConsensus, + }, + { + "upgraded client state height is not greater than current height", + func() { + // upgrade height is at next block + upgradeHeight := clienttypes.NewHeight(1, uint64(suite.chainB.GetContext().BlockHeight()+1)) + + // zero custom fields and store in upgrade store + zeroedUpgradedClient := upgradedClientState.(*ibctm.ClientState).ZeroCustomFields() + zeroedUpgradedClientAny, err := codectypes.NewAnyWithValue(zeroedUpgradedClient) + suite.Require().NoError(err) + + err = suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetRevisionHeight()), suite.chainB.Codec.MustMarshal(zeroedUpgradedClientAny)) + suite.Require().NoError(err) + + err = suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(upgradeHeight.GetRevisionHeight()), suite.chainB.Codec.MustMarshal(upgradedConsensusStateAny)) + suite.Require().NoError(err) + + // change upgraded client state height to be lower than current client state height + tmClient, ok := upgradedClientState.(*ibctm.ClientState) + suite.Require().True(ok) + + newLatestheight, ok := path.EndpointA.GetClientLatestHeight().Decrement() + suite.Require().True(ok) + + tmClient.LatestHeight, ok = newLatestheight.(clienttypes.Height) + suite.Require().True(ok) + upgradedClientStateAny, err = codectypes.NewAnyWithValue(tmClient) + suite.Require().NoError(err) + + suite.coordinator.CommitBlock(suite.chainB) + err = path.EndpointA.UpdateClient() + suite.Require().NoError(err) + + upgradedClientStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetRevisionHeight())), path.EndpointA.GetClientLatestHeight().GetRevisionHeight()) + upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(upgradeHeight.GetRevisionHeight())), path.EndpointA.GetClientLatestHeight().GetRevisionHeight()) + }, + ibcerrors.ErrInvalidHeight, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + suite.SetupTest() // reset + + path = ibctesting.NewPath(suite.chainA, suite.chainB) + path.SetupClients() + + clientID = path.EndpointA.ClientID + clientState, ok := path.EndpointA.GetClientState().(*ibctm.ClientState) + suite.Require().True(ok) + revisionNumber := clienttypes.ParseChainID(clientState.ChainId) + + newUnbondindPeriod := ubdPeriod + trustingPeriod + newChainID, err := clienttypes.SetRevisionNumber(clientState.ChainId, revisionNumber+1) + suite.Require().NoError(err) + + upgradedClientState = ibctm.NewClientState(newChainID, ibctm.DefaultTrustLevel, trustingPeriod, newUnbondindPeriod, maxClockDrift, clienttypes.NewHeight(revisionNumber+1, clientState.LatestHeight.GetRevisionHeight()+1), commitmenttypes.GetSDKSpecs(), upgradePath) + upgradedClientStateAny, err = codectypes.NewAnyWithValue(upgradedClientState) + suite.Require().NoError(err) + + nextValsHash := sha256.Sum256([]byte("new-nextValsHash")) + upgradedConsensusState := ibctm.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("new-hash")), nextValsHash[:]) + + upgradedConsensusStateAny, err = codectypes.NewAnyWithValue(upgradedConsensusState) + suite.Require().NoError(err) + + tc.malleate() + + lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(clientID) + suite.Require().True(found) + + err = lightClientModule.VerifyUpgradeAndUpdateState( + suite.chainA.GetContext(), + clientID, + upgradedClientStateAny.Value, + upgradedConsensusStateAny.Value, + upgradedClientStateProof, + upgradedConsensusStateProof, + ) + + expPass := tc.expErr == nil + if expPass { + suite.Require().NoError(err) + + expClientState := path.EndpointA.GetClientState() + expClientStateBz := suite.chainA.Codec.MustMarshal(expClientState) + suite.Require().Equal(upgradedClientStateAny.Value, expClientStateBz) + + expConsensusState := ibctm.NewConsensusState(upgradedConsensusState.Timestamp, commitmenttypes.NewMerkleRoot([]byte(ibctm.SentinelRoot)), upgradedConsensusState.NextValidatorsHash) + expConsensusStateBz := suite.chainA.Codec.MustMarshal(expConsensusState) + + consensusStateBz := suite.chainA.Codec.MustMarshal(path.EndpointA.GetConsensusState(path.EndpointA.GetClientLatestHeight())) + suite.Require().Equal(expConsensusStateBz, consensusStateBz) + } else { + suite.Require().Error(err) + suite.Require().ErrorIs(err, tc.expErr) + } + }) + } +} diff --git a/modules/light-clients/07-tendermint/misbehaviour_handle_test.go b/modules/light-clients/07-tendermint/misbehaviour_handle_test.go index f44dd836688..074cb8f65f5 100644 --- a/modules/light-clients/07-tendermint/misbehaviour_handle_test.go +++ b/modules/light-clients/07-tendermint/misbehaviour_handle_test.go @@ -368,13 +368,12 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviour() { err := path.EndpointA.CreateClient() suite.Require().NoError(err) - tc.malleate() + lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(path.EndpointA.ClientID) + suite.Require().True(found) - clientState, ok := path.EndpointA.GetClientState().(*ibctm.ClientState) - suite.Require().True(ok) - clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID) + tc.malleate() - err = clientState.VerifyClientMessage(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, misbehaviour) + err = lightClientModule.VerifyClientMessage(suite.chainA.GetContext(), path.EndpointA.ClientID, misbehaviour) if tc.expPass { suite.Require().NoError(err) @@ -678,13 +677,12 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviourNonRevisionChainID() { err := path.EndpointA.CreateClient() suite.Require().NoError(err) - tc.malleate() + lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(path.EndpointA.ClientID) + suite.Require().True(found) - clientState, ok := path.EndpointA.GetClientState().(*ibctm.ClientState) - suite.Require().True(ok) - clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID) + tc.malleate() - err = clientState.VerifyClientMessage(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, misbehaviour) + err = lightClientModule.VerifyClientMessage(suite.chainA.GetContext(), path.EndpointA.ClientID, misbehaviour) if tc.expPass { suite.Require().NoError(err) diff --git a/modules/light-clients/07-tendermint/update_test.go b/modules/light-clients/07-tendermint/update_test.go index 178ffa6195b..b0e46db7d6f 100644 --- a/modules/light-clients/07-tendermint/update_test.go +++ b/modules/light-clients/07-tendermint/update_test.go @@ -307,14 +307,12 @@ func (suite *TendermintTestSuite) TestVerifyHeader() { header, err = path.EndpointA.Counterparty.Chain.IBCClientHeader(path.EndpointA.Counterparty.Chain.LatestCommittedHeader, trustedHeight) suite.Require().NoError(err) - tc.malleate() - - clientState, ok := path.EndpointA.GetClientState().(*ibctm.ClientState) - suite.Require().True(ok) + lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(path.EndpointA.ClientID) + suite.Require().True(found) - clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID) + tc.malleate() - err = clientState.VerifyClientMessage(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, header) + err = lightClientModule.VerifyClientMessage(suite.chainA.GetContext(), path.EndpointA.ClientID, header) if tc.expPass { suite.Require().NoError(err, tc.name) @@ -524,14 +522,15 @@ func (suite *TendermintTestSuite) TestUpdateState() { clientMessage, err = path.EndpointA.Counterparty.Chain.IBCClientHeader(path.EndpointA.Counterparty.Chain.LatestCommittedHeader, trustedHeight) suite.Require().NoError(err) + lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(path.EndpointA.ClientID) + suite.Require().True(found) + tc.malleate() - clientState, ok := path.EndpointA.GetClientState().(*ibctm.ClientState) - suite.Require().True(ok) clientStore = suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID) if tc.expPass { - consensusHeights = clientState.UpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, clientMessage) + consensusHeights = lightClientModule.UpdateState(suite.chainA.GetContext(), path.EndpointA.ClientID, clientMessage) header, ok := clientMessage.(*ibctm.Header) suite.Require().True(ok) @@ -548,7 +547,7 @@ func (suite *TendermintTestSuite) TestUpdateState() { suite.Require().Equal(expConsensusState, updatedConsensusState) } else { - consensusHeights = clientState.UpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, clientMessage) + consensusHeights = lightClientModule.UpdateState(suite.chainA.GetContext(), path.EndpointA.ClientID, clientMessage) suite.Require().Empty(consensusHeights) consensusState, found := suite.chainA.GetSimApp().GetIBCKeeper().ClientKeeper.GetClientConsensusState(suite.chainA.GetContext(), path.EndpointA.ClientID, clienttypes.NewHeight(1, uint64(suite.chainB.GetContext().BlockHeight()))) @@ -895,16 +894,14 @@ func (suite *TendermintTestSuite) TestCheckForMisbehaviour() { clientMessage, err = path.EndpointA.Counterparty.Chain.IBCClientHeader(path.EndpointA.Counterparty.Chain.LatestCommittedHeader, trustedHeight) suite.Require().NoError(err) - tc.malleate() + lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(path.EndpointA.ClientID) + suite.Require().True(found) - clientState, ok := path.EndpointA.GetClientState().(*ibctm.ClientState) - suite.Require().True(ok) - clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID) + tc.malleate() - foundMisbehaviour := clientState.CheckForMisbehaviour( + foundMisbehaviour := lightClientModule.CheckForMisbehaviour( suite.chainA.GetContext(), - suite.chainA.App.AppCodec(), - clientStore, // pass in clientID prefixed clientStore + path.EndpointA.ClientID, clientMessage, ) @@ -943,13 +940,14 @@ func (suite *TendermintTestSuite) TestUpdateStateOnMisbehaviour() { err := path.EndpointA.CreateClient() suite.Require().NoError(err) + lightClientModule, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.Route(path.EndpointA.ClientID) + suite.Require().True(found) + tc.malleate() - clientState, ok := path.EndpointA.GetClientState().(*ibctm.ClientState) - suite.Require().True(ok) clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID) - clientState.UpdateStateOnMisbehaviour(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, nil) + lightClientModule.UpdateStateOnMisbehaviour(suite.chainA.GetContext(), path.EndpointA.ClientID, nil) if tc.expPass { clientStateBz := clientStore.Get(host.ClientStateKey()) diff --git a/modules/light-clients/07-tendermint/upgrade_test.go b/modules/light-clients/07-tendermint/upgrade_test.go index cf71574c377..2f71d0ee29f 100644 --- a/modules/light-clients/07-tendermint/upgrade_test.go +++ b/modules/light-clients/07-tendermint/upgrade_test.go @@ -1,11 +1,14 @@ package tendermint_test import ( + "errors" + upgradetypes "cosmossdk.io/x/upgrade/types" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" commitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" "github.com/cosmos/ibc-go/v8/modules/core/exported" + solomachine "github.com/cosmos/ibc-go/v8/modules/light-clients/06-solomachine" ibctm "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" ibctesting "github.com/cosmos/ibc-go/v8/testing" ) @@ -13,7 +16,7 @@ import ( func (suite *TendermintTestSuite) TestVerifyUpgrade() { var ( newChainID string - upgradedClient *ibctm.ClientState + upgradedClient exported.ClientState upgradedConsState exported.ConsensusState lastHeight clienttypes.Height path *ibctesting.Path @@ -23,9 +26,9 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { ) testCases := []struct { - name string - setup func() - expPass bool + name string + setup func() + expErr error }{ { name: "successful upgrade", @@ -38,7 +41,6 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) //nolint:errcheck // ignore error for test // commit upgrade store changes and update clients - suite.coordinator.CommitBlock(suite.chainB) err := path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -51,13 +53,13 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) }, - expPass: true, + expErr: nil, }, { name: "successful upgrade to same revision", setup: func() { - upgradedClient = ibctm.NewClientState(suite.chainB.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, clienttypes.NewHeight(clienttypes.ParseChainID(suite.chainB.ChainID), upgradedClient.LatestHeight.GetRevisionHeight()+10), commitmenttypes.GetSDKSpecs(), upgradePath) - upgradedClient = upgradedClient.ZeroCustomFields() + upgradedClient = ibctm.NewClientState(suite.chainB.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, clienttypes.NewHeight(clienttypes.ParseChainID(suite.chainB.ChainID), upgradedClient.(*ibctm.ClientState).LatestHeight.GetRevisionHeight()+10), commitmenttypes.GetSDKSpecs(), upgradePath) + upgradedClient = upgradedClient.(*ibctm.ClientState).ZeroCustomFields() upgradedClientBz, err = clienttypes.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient) suite.Require().NoError(err) @@ -82,9 +84,48 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) }, - expPass: true, + expErr: nil, + }, + { + name: "unsuccessful upgrade: upgrade path not set", + setup: func() { + suite.coordinator.CommitBlock(suite.chainB) + err := path.EndpointA.UpdateClient() + suite.Require().NoError(err) + + cs, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID) + suite.Require().True(found) + tmCs, ok := cs.(*ibctm.ClientState) + suite.Require().True(ok) + + // set upgrade path to empty + tmCs.UpgradePath = []string{} + suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID, tmCs) + + upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) + upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) + }, + expErr: clienttypes.ErrInvalidUpgradeClient, }, + { + name: "unsuccessful upgrade: upgrade consensus state must be tendermint consensus state", + setup: func() { + upgradedConsState = &solomachine.ConsensusState{} + + suite.coordinator.CommitBlock(suite.chainB) + err := path.EndpointA.UpdateClient() + suite.Require().NoError(err) + cs, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID) + suite.Require().True(found) + tmCs, ok := cs.(*ibctm.ClientState) + suite.Require().True(ok) + + upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) + upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) + }, + expErr: clienttypes.ErrInvalidConsensus, + }, { name: "unsuccessful upgrade: upgrade height revision height is more than the current client revision height", setup: func() { @@ -109,7 +150,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) }, - expPass: false, + expErr: commitmenttypes.ErrInvalidProof, }, { name: "unsuccessful upgrade: committed client does not have zeroed custom fields", @@ -140,7 +181,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) }, - expPass: false, + expErr: commitmenttypes.ErrInvalidProof, }, { name: "unsuccessful upgrade: chain-specified parameters do not match committed client", @@ -149,14 +190,16 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) // zero custom fields and store in upgrade store - suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) //nolint:errcheck // ignore error for test - suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) //nolint:errcheck // ignore error for test + err := suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) + suite.Require().NoError(err) + err = suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) + suite.Require().NoError(err) // change upgradedClient client-specified parameters upgradedClient = ibctm.NewClientState("wrongchainID", ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath) suite.coordinator.CommitBlock(suite.chainB) - err := path.EndpointA.UpdateClient() + err = path.EndpointA.UpdateClient() suite.Require().NoError(err) cs, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID) @@ -167,20 +210,25 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) }, - expPass: false, + expErr: commitmenttypes.ErrInvalidProof, }, { name: "unsuccessful upgrade: client-specified parameters do not match previous client", setup: func() { + // upgrade Height is at next block + lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) + // zero custom fields and store in upgrade store - suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) //nolint:errcheck // ignore error for test - suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) //nolint:errcheck // ignore error for test + err := suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) + suite.Require().NoError(err) + err = suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) + suite.Require().NoError(err) // change upgradedClient client-specified parameters upgradedClient = ibctm.NewClientState(newChainID, ibctm.DefaultTrustLevel, ubdPeriod, ubdPeriod+trustingPeriod, maxClockDrift+5, lastHeight, commitmenttypes.GetSDKSpecs(), upgradePath) suite.coordinator.CommitBlock(suite.chainB) - err := path.EndpointA.UpdateClient() + err = path.EndpointA.UpdateClient() suite.Require().NoError(err) cs, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID) @@ -191,25 +239,24 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) }, - expPass: false, + expErr: commitmenttypes.ErrInvalidProof, + }, + { + name: "unsuccessful upgrade: upgrade client is not tendermint", + setup: func() { + upgradedClient = &solomachine.ClientState{} + }, + expErr: clienttypes.ErrInvalidClientType, }, { name: "unsuccessful upgrade: relayer-submitted consensus state does not match counterparty-committed consensus state", setup: func() { - // upgrade Height is at next block - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - // zero custom fields and store in upgrade store - suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) //nolint:errcheck // ignore error for test - suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) //nolint:errcheck // ignore error for test - // change submitted upgradedConsensusState upgradedConsState = &ibctm.ConsensusState{ NextValidatorsHash: []byte("maliciousValidators"), } // commit upgrade store changes and update clients - suite.coordinator.CommitBlock(suite.chainB) err := path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -222,13 +269,11 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) }, - expPass: false, + expErr: commitmenttypes.ErrInvalidProof, }, { name: "unsuccessful upgrade: client proof unmarshal failed", setup: func() { - suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) //nolint:errcheck // ignore error for test - cs, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID) suite.Require().True(found) tmCs, ok := cs.(*ibctm.ClientState) @@ -238,13 +283,11 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { upgradedClientProof = []byte("proof") }, - expPass: false, + expErr: errors.New("could not unmarshal client merkle proof"), }, { name: "unsuccessful upgrade: consensus state proof unmarshal failed", setup: func() { - suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) //nolint:errcheck // ignore error for test - cs, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID) suite.Require().True(found) tmCs, ok := cs.(*ibctm.ClientState) @@ -254,7 +297,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { upgradedConsensusStateProof = []byte("proof") }, - expPass: false, + expErr: errors.New("could not unmarshal consensus state merkle proof"), }, { name: "unsuccessful upgrade: client proof verification failed", @@ -274,7 +317,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) }, - expPass: false, + expErr: commitmenttypes.ErrInvalidProof, }, { name: "unsuccessful upgrade: consensus state proof verification failed", @@ -294,10 +337,10 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) }, - expPass: false, + expErr: commitmenttypes.ErrInvalidProof, }, { - name: "unsuccessful upgrade: upgrade path is empty", + name: "unsuccessful upgrade: client state merkle path is empty", setup: func() { // upgrade Height is at next block lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) @@ -306,7 +349,6 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) //nolint:errcheck // ignore error for test // commit upgrade store changes and update clients - suite.coordinator.CommitBlock(suite.chainB) err := path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -319,13 +361,13 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) - // SetClientState with empty upgrade path + // SetClientState with empty string upgrade path tmClient, ok := cs.(*ibctm.ClientState) suite.Require().True(ok) tmClient.UpgradePath = []string{""} suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID, tmClient) }, - expPass: false, + expErr: errors.New("client state proof failed"), }, { name: "unsuccessful upgrade: upgraded height is not greater than current height", @@ -337,7 +379,6 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) //nolint:errcheck // ignore error for test // commit upgrade store changes and update clients - suite.coordinator.CommitBlock(suite.chainB) err := path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -350,7 +391,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) }, - expPass: false, + expErr: errors.New("consensus state proof failed"), }, { name: "unsuccessful upgrade: consensus state for upgrade height cannot be found", @@ -362,7 +403,6 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) //nolint:errcheck // ignore error for // commit upgrade store changes and update clients - suite.coordinator.CommitBlock(suite.chainB) err := path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -375,7 +415,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) }, - expPass: false, + expErr: commitmenttypes.ErrInvalidProof, }, { name: "unsuccessful upgrade: client is expired", @@ -384,7 +424,6 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) //nolint:errcheck // ignore error for test // commit upgrade store changes and update clients - suite.coordinator.CommitBlock(suite.chainB) err := path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -400,7 +439,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) }, - expPass: false, + expErr: commitmenttypes.ErrInvalidProof, }, { name: "unsuccessful upgrade: updated unbonding period is equal to trusting period", @@ -412,7 +451,6 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) //nolint:errcheck // ignore error for test // commit upgrade store changes and update clients - suite.coordinator.CommitBlock(suite.chainB) err := path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -425,7 +463,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) }, - expPass: false, + expErr: commitmenttypes.ErrInvalidProof, }, { name: "unsuccessful upgrade: final client is not valid", @@ -443,7 +481,6 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) //nolint:errcheck // ignore error for testing // commit upgrade store changes and update clients - suite.coordinator.CommitBlock(suite.chainB) err := path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -456,7 +493,39 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), tmCs.LatestHeight.GetRevisionHeight()) }, - expPass: false, + expErr: commitmenttypes.ErrInvalidProof, + }, + { + name: "unsuccessful upgrade: consensus state not found for latest height", + setup: func() { + // upgrade Height is at next block + lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) + + // zero custom fields and store in upgrade store + suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) //nolint:errcheck // ignore error for test + suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) //nolint:errcheck // ignore error for test + + // commit upgrade store changes and update clients + + suite.coordinator.CommitBlock(suite.chainB) + err := path.EndpointA.UpdateClient() + suite.Require().NoError(err) + + cs, found := suite.chainA.App.GetIBCKeeper().ClientKeeper.GetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID) + suite.Require().True(found) + tmCs, ok := cs.(*ibctm.ClientState) + suite.Require().True(ok) + + revisionHeight := tmCs.LatestHeight.GetRevisionHeight() + + // set latest height to a height where consensus state does not exist + tmCs.LatestHeight = clienttypes.NewHeight(tmCs.LatestHeight.GetRevisionNumber(), tmCs.LatestHeight.GetRevisionHeight()+5) + suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID, tmCs) + + upgradedClientProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), revisionHeight) + upgradedConsensusStateProof, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), revisionHeight) + }, + expErr: clienttypes.ErrConsensusStateNotFound, }, } @@ -479,7 +548,11 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { suite.Require().NoError(err) upgradedClient = ibctm.NewClientState(newChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, clienttypes.NewHeight(revisionNumber+1, clientState.LatestHeight.GetRevisionHeight()+1), commitmenttypes.GetSDKSpecs(), upgradePath) - upgradedClient = upgradedClient.ZeroCustomFields() + + if upgraded, ok := upgradedClient.(*ibctm.ClientState); ok { + upgradedClient = upgraded.ZeroCustomFields() + } + upgradedClientBz, err = clienttypes.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient) suite.Require().NoError(err) @@ -496,7 +569,9 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID) // Call ZeroCustomFields on upgraded clients to clear any client-chosen parameters in test-case upgradedClient - upgradedClient = upgradedClient.ZeroCustomFields() + if upgraded, ok := upgradedClient.(*ibctm.ClientState); ok { + upgradedClient = upgraded.ZeroCustomFields() + } err = cs.VerifyUpgradeAndUpdateState( suite.chainA.GetContext(), @@ -508,7 +583,8 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { upgradedConsensusStateProof, ) - if tc.expPass { + expPass := tc.expErr == nil + if expPass { suite.Require().NoError(err, "verify upgrade failed on valid case: %s", tc.name) clientState, ok := suite.chainA.GetClientState(path.EndpointA.ClientID).(*ibctm.ClientState) @@ -519,7 +595,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { suite.Require().NotNil(consensusState, "verify upgrade failed on valid case: %s", tc.name) suite.Require().True(found) } else { - suite.Require().Error(err, "verify upgrade passed on invalid case: %s", tc.name) + suite.Require().ErrorContains(err, tc.expErr.Error(), "verify upgrade passed on invalid case: %s", tc.name) } }) } From 23f6751bfd93f9c34eb8b70bda3d32165efd432c Mon Sep 17 00:00:00 2001 From: PolyMa <151764357+polymaer@users.noreply.github.com> Date: Wed, 22 May 2024 15:40:01 +0800 Subject: [PATCH 13/16] docs: fix the warning syntax error across docs (#6351) * fix the warning syntax error across docs. * fix rendering of tip admonition --------- Co-authored-by: Carlos Rodriguez Co-authored-by: Damian Nolan --- docs/docs/01-ibc/03-apps/01-apps.md | 2 +- docs/docs/01-ibc/06-channel-upgrades.md | 2 +- docs/docs/02-apps/01-transfer/07-params.md | 4 ++-- docs/docs/04-middleware/02-callbacks/02-integration.md | 4 ++-- docs/docs/04-middleware/02-callbacks/05-end-users.md | 8 ++++---- .../version-v7.5.x/01-ibc/03-apps/02-ibcmodule.md | 2 +- .../04-middleware/02-callbacks/02-integration.md | 4 ++-- .../04-middleware/02-callbacks/05-end-users.md | 8 ++++---- .../version-v8.3.x/01-ibc/03-apps/01-apps.md | 2 +- .../version-v8.3.x/01-ibc/06-channel-upgrades.md | 2 +- .../version-v8.3.x/02-apps/01-transfer/07-params.md | 4 ++-- .../04-middleware/02-callbacks/02-integration.md | 4 ++-- .../04-middleware/02-callbacks/05-end-users.md | 8 ++++---- 13 files changed, 27 insertions(+), 27 deletions(-) diff --git a/docs/docs/01-ibc/03-apps/01-apps.md b/docs/docs/01-ibc/03-apps/01-apps.md index 48ea8fc82c3..eacd37d24cc 100644 --- a/docs/docs/01-ibc/03-apps/01-apps.md +++ b/docs/docs/01-ibc/03-apps/01-apps.md @@ -314,7 +314,7 @@ sequence, err := IBCChannelKeeper.SendPacket( ) ``` -::: warning +:::warning In order to prevent modules from sending packets on channels they do not own, IBC expects modules to pass in the correct channel capability for the packet's source channel. ::: diff --git a/docs/docs/01-ibc/06-channel-upgrades.md b/docs/docs/01-ibc/06-channel-upgrades.md index 45c0cfd77c6..841d11f42fd 100644 --- a/docs/docs/01-ibc/06-channel-upgrades.md +++ b/docs/docs/01-ibc/06-channel-upgrades.md @@ -70,7 +70,7 @@ As part of the handling of the `MsgChannelUpgradeInit` message, the application' After this message is handled successfully, the channel's upgrade sequence will be incremented. This upgrade sequence will serve as a nonce for the upgrade process to provide replay protection. -::: warning +:::warning Initiating an upgrade in the same block as opening a channel may potentially prevent the counterparty channel from also opening. ::: diff --git a/docs/docs/02-apps/01-transfer/07-params.md b/docs/docs/02-apps/01-transfer/07-params.md index 635344edea4..f3aeee45d48 100644 --- a/docs/docs/02-apps/01-transfer/07-params.md +++ b/docs/docs/02-apps/01-transfer/07-params.md @@ -26,7 +26,7 @@ To prevent a single token from being transferred from the chain, set the `SendEn - For Cosmos SDK v0.46.x or earlier, set the bank module's [`SendEnabled` parameter](https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/x/bank/spec/05_params.md#sendenabled) for the denomination to `false`. - For Cosmos SDK versions above v0.46.x, set the bank module's `SendEnabled` entry for the denomination to `false` using `MsgSetSendEnabled` as a governance proposal. -::: warning +:::warning Doing so will prevent the token from being transferred between any accounts in the blockchain. ::: @@ -39,7 +39,7 @@ To prevent a single token from being transferred to the chain, set the `ReceiveE - For Cosmos SDK v0.46.x or earlier, set the bank module's [`SendEnabled` parameter](https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/x/bank/spec/05_params.md#sendenabled) for the denomination to `false`. - For Cosmos SDK versions above v0.46.x, set the bank module's `SendEnabled` entry for the denomination to `false` using `MsgSetSendEnabled` as a governance proposal. -::: warning +:::warning Doing so will prevent the token from being transferred between any accounts in the blockchain. ::: diff --git a/docs/docs/04-middleware/02-callbacks/02-integration.md b/docs/docs/04-middleware/02-callbacks/02-integration.md index d0ec7e03e1a..189848c6963 100644 --- a/docs/docs/04-middleware/02-callbacks/02-integration.md +++ b/docs/docs/04-middleware/02-callbacks/02-integration.md @@ -74,7 +74,7 @@ app.TransferKeeper.WithICS4Wrapper(transferICS4Wrapper) ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferStack) ``` -::: warning +:::warning The usage of `WithICS4Wrapper` after `transferStack`'s configuration is critical! It allows the callbacks middleware to do `SendPacket` callbacks and asynchronous `ReceivePacket` callbacks. You must do this regardless of whether you are using the `29-fee` middleware or not. ::: @@ -108,6 +108,6 @@ AddRoute(icacontrollertypes.SubModuleName, icaControllerStack). AddRoute(icahosttypes.SubModuleName, icaHostStack). ``` -::: warning +:::warning The usage of `WithICS4Wrapper` here is also critical! ::: diff --git a/docs/docs/04-middleware/02-callbacks/05-end-users.md b/docs/docs/04-middleware/02-callbacks/05-end-users.md index f2500ae3c05..fe74a6a747e 100644 --- a/docs/docs/04-middleware/02-callbacks/05-end-users.md +++ b/docs/docs/04-middleware/02-callbacks/05-end-users.md @@ -18,11 +18,11 @@ This section explains how to use the callbacks middleware from the perspective o For a given channel, the source callbacks are supported if the source chain has the callbacks middleware wired up in the channel's IBC stack. Similarly, the destination callbacks are supported if the destination chain has the callbacks middleware wired up in the channel's IBC stack. -::: tip +:::tip Callbacks are always executed after the packet has been processed by the underlying IBC module. ::: -::: warning +:::warning If the underlying application module is doing an asynchronous acknowledgement on packet receive (for example, if the [packet forward middleware](https://github.com/cosmos/ibc-apps/tree/main/middleware/packet-forward-middleware) is in the stack, and is being used by this packet), then the callbacks middleware will execute the `ReceivePacket` callback after the acknowledgement has been received. ::: @@ -85,12 +85,12 @@ User defined gas limit was added for the following reasons: - To prevent callbacks from blocking packet lifecycle. - To prevent relayers from being able to DOS the callback execution by sending a packet with a low amount of gas. -::: tip +:::tip There is a chain wide parameter that sets the maximum gas limit that a user can set for a callback. This is to prevent a user from setting a gas limit that is too high for relayers. If the `"gas_limit"` is not set in the packet memo, then the maximum gas limit is used. ::: These goals are achieved by creating a minimum gas amount required for callback execution. If the relayer provides at least the minimum gas limit for the callback execution, then the packet lifecycle will not be blocked if the callback runs out of gas during execution, and the callback cannot be retried. If the relayer does not provided the minimum amount of gas and the callback executions runs out of gas, the entire tx is reverted and it may be executed again. -::: tip +:::tip `SendPacket` callback is always reverted if the callback execution fails or returns an error for any reason. This is so that the packet is not sent if the callback execution fails. ::: diff --git a/docs/versioned_docs/version-v7.5.x/01-ibc/03-apps/02-ibcmodule.md b/docs/versioned_docs/version-v7.5.x/01-ibc/03-apps/02-ibcmodule.md index e654a6a03ad..c082784a407 100644 --- a/docs/versioned_docs/version-v7.5.x/01-ibc/03-apps/02-ibcmodule.md +++ b/docs/versioned_docs/version-v7.5.x/01-ibc/03-apps/02-ibcmodule.md @@ -254,7 +254,7 @@ sequence, err := IBCChannelKeeper.SendPacket( ) ``` -::: warning +:::warning In order to prevent modules from sending packets on channels they do not own, IBC expects modules to pass in the correct channel capability for the packet's source channel. ::: diff --git a/docs/versioned_docs/version-v7.5.x/04-middleware/02-callbacks/02-integration.md b/docs/versioned_docs/version-v7.5.x/04-middleware/02-callbacks/02-integration.md index 85b2a3b5889..4b4e78688c9 100644 --- a/docs/versioned_docs/version-v7.5.x/04-middleware/02-callbacks/02-integration.md +++ b/docs/versioned_docs/version-v7.5.x/04-middleware/02-callbacks/02-integration.md @@ -69,7 +69,7 @@ app.TransferKeeper.WithICS4Wrapper(transferICS4Wrapper) ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferStack) ``` -::: warning +:::warning The usage of `WithICS4Wrapper` after `transferStack`'s configuration is critical! It allows the callbacks middleware to do `SendPacket` callbacks and asynchronous `ReceivePacket` callbacks. You must do this regardless of whether you are using the `29-fee` middleware or not. ::: @@ -103,6 +103,6 @@ AddRoute(icacontrollertypes.SubModuleName, icaControllerStack). AddRoute(icahosttypes.SubModuleName, icaHostStack). ``` -::: warning +:::warning The usage of `WithICS4Wrapper` here is also critical! ::: diff --git a/docs/versioned_docs/version-v7.5.x/04-middleware/02-callbacks/05-end-users.md b/docs/versioned_docs/version-v7.5.x/04-middleware/02-callbacks/05-end-users.md index f2500ae3c05..fe74a6a747e 100644 --- a/docs/versioned_docs/version-v7.5.x/04-middleware/02-callbacks/05-end-users.md +++ b/docs/versioned_docs/version-v7.5.x/04-middleware/02-callbacks/05-end-users.md @@ -18,11 +18,11 @@ This section explains how to use the callbacks middleware from the perspective o For a given channel, the source callbacks are supported if the source chain has the callbacks middleware wired up in the channel's IBC stack. Similarly, the destination callbacks are supported if the destination chain has the callbacks middleware wired up in the channel's IBC stack. -::: tip +:::tip Callbacks are always executed after the packet has been processed by the underlying IBC module. ::: -::: warning +:::warning If the underlying application module is doing an asynchronous acknowledgement on packet receive (for example, if the [packet forward middleware](https://github.com/cosmos/ibc-apps/tree/main/middleware/packet-forward-middleware) is in the stack, and is being used by this packet), then the callbacks middleware will execute the `ReceivePacket` callback after the acknowledgement has been received. ::: @@ -85,12 +85,12 @@ User defined gas limit was added for the following reasons: - To prevent callbacks from blocking packet lifecycle. - To prevent relayers from being able to DOS the callback execution by sending a packet with a low amount of gas. -::: tip +:::tip There is a chain wide parameter that sets the maximum gas limit that a user can set for a callback. This is to prevent a user from setting a gas limit that is too high for relayers. If the `"gas_limit"` is not set in the packet memo, then the maximum gas limit is used. ::: These goals are achieved by creating a minimum gas amount required for callback execution. If the relayer provides at least the minimum gas limit for the callback execution, then the packet lifecycle will not be blocked if the callback runs out of gas during execution, and the callback cannot be retried. If the relayer does not provided the minimum amount of gas and the callback executions runs out of gas, the entire tx is reverted and it may be executed again. -::: tip +:::tip `SendPacket` callback is always reverted if the callback execution fails or returns an error for any reason. This is so that the packet is not sent if the callback execution fails. ::: diff --git a/docs/versioned_docs/version-v8.3.x/01-ibc/03-apps/01-apps.md b/docs/versioned_docs/version-v8.3.x/01-ibc/03-apps/01-apps.md index 48ea8fc82c3..eacd37d24cc 100644 --- a/docs/versioned_docs/version-v8.3.x/01-ibc/03-apps/01-apps.md +++ b/docs/versioned_docs/version-v8.3.x/01-ibc/03-apps/01-apps.md @@ -314,7 +314,7 @@ sequence, err := IBCChannelKeeper.SendPacket( ) ``` -::: warning +:::warning In order to prevent modules from sending packets on channels they do not own, IBC expects modules to pass in the correct channel capability for the packet's source channel. ::: diff --git a/docs/versioned_docs/version-v8.3.x/01-ibc/06-channel-upgrades.md b/docs/versioned_docs/version-v8.3.x/01-ibc/06-channel-upgrades.md index 45c0cfd77c6..841d11f42fd 100644 --- a/docs/versioned_docs/version-v8.3.x/01-ibc/06-channel-upgrades.md +++ b/docs/versioned_docs/version-v8.3.x/01-ibc/06-channel-upgrades.md @@ -70,7 +70,7 @@ As part of the handling of the `MsgChannelUpgradeInit` message, the application' After this message is handled successfully, the channel's upgrade sequence will be incremented. This upgrade sequence will serve as a nonce for the upgrade process to provide replay protection. -::: warning +:::warning Initiating an upgrade in the same block as opening a channel may potentially prevent the counterparty channel from also opening. ::: diff --git a/docs/versioned_docs/version-v8.3.x/02-apps/01-transfer/07-params.md b/docs/versioned_docs/version-v8.3.x/02-apps/01-transfer/07-params.md index 635344edea4..f3aeee45d48 100644 --- a/docs/versioned_docs/version-v8.3.x/02-apps/01-transfer/07-params.md +++ b/docs/versioned_docs/version-v8.3.x/02-apps/01-transfer/07-params.md @@ -26,7 +26,7 @@ To prevent a single token from being transferred from the chain, set the `SendEn - For Cosmos SDK v0.46.x or earlier, set the bank module's [`SendEnabled` parameter](https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/x/bank/spec/05_params.md#sendenabled) for the denomination to `false`. - For Cosmos SDK versions above v0.46.x, set the bank module's `SendEnabled` entry for the denomination to `false` using `MsgSetSendEnabled` as a governance proposal. -::: warning +:::warning Doing so will prevent the token from being transferred between any accounts in the blockchain. ::: @@ -39,7 +39,7 @@ To prevent a single token from being transferred to the chain, set the `ReceiveE - For Cosmos SDK v0.46.x or earlier, set the bank module's [`SendEnabled` parameter](https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/x/bank/spec/05_params.md#sendenabled) for the denomination to `false`. - For Cosmos SDK versions above v0.46.x, set the bank module's `SendEnabled` entry for the denomination to `false` using `MsgSetSendEnabled` as a governance proposal. -::: warning +:::warning Doing so will prevent the token from being transferred between any accounts in the blockchain. ::: diff --git a/docs/versioned_docs/version-v8.3.x/04-middleware/02-callbacks/02-integration.md b/docs/versioned_docs/version-v8.3.x/04-middleware/02-callbacks/02-integration.md index bcc2a2502eb..37bc87c2482 100644 --- a/docs/versioned_docs/version-v8.3.x/04-middleware/02-callbacks/02-integration.md +++ b/docs/versioned_docs/version-v8.3.x/04-middleware/02-callbacks/02-integration.md @@ -69,7 +69,7 @@ app.TransferKeeper.WithICS4Wrapper(transferICS4Wrapper) ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferStack) ``` -::: warning +:::warning The usage of `WithICS4Wrapper` after `transferStack`'s configuration is critical! It allows the callbacks middleware to do `SendPacket` callbacks and asynchronous `ReceivePacket` callbacks. You must do this regardless of whether you are using the `29-fee` middleware or not. ::: @@ -103,6 +103,6 @@ AddRoute(icacontrollertypes.SubModuleName, icaControllerStack). AddRoute(icahosttypes.SubModuleName, icaHostStack). ``` -::: warning +:::warning The usage of `WithICS4Wrapper` here is also critical! ::: diff --git a/docs/versioned_docs/version-v8.3.x/04-middleware/02-callbacks/05-end-users.md b/docs/versioned_docs/version-v8.3.x/04-middleware/02-callbacks/05-end-users.md index f2500ae3c05..fe74a6a747e 100644 --- a/docs/versioned_docs/version-v8.3.x/04-middleware/02-callbacks/05-end-users.md +++ b/docs/versioned_docs/version-v8.3.x/04-middleware/02-callbacks/05-end-users.md @@ -18,11 +18,11 @@ This section explains how to use the callbacks middleware from the perspective o For a given channel, the source callbacks are supported if the source chain has the callbacks middleware wired up in the channel's IBC stack. Similarly, the destination callbacks are supported if the destination chain has the callbacks middleware wired up in the channel's IBC stack. -::: tip +:::tip Callbacks are always executed after the packet has been processed by the underlying IBC module. ::: -::: warning +:::warning If the underlying application module is doing an asynchronous acknowledgement on packet receive (for example, if the [packet forward middleware](https://github.com/cosmos/ibc-apps/tree/main/middleware/packet-forward-middleware) is in the stack, and is being used by this packet), then the callbacks middleware will execute the `ReceivePacket` callback after the acknowledgement has been received. ::: @@ -85,12 +85,12 @@ User defined gas limit was added for the following reasons: - To prevent callbacks from blocking packet lifecycle. - To prevent relayers from being able to DOS the callback execution by sending a packet with a low amount of gas. -::: tip +:::tip There is a chain wide parameter that sets the maximum gas limit that a user can set for a callback. This is to prevent a user from setting a gas limit that is too high for relayers. If the `"gas_limit"` is not set in the packet memo, then the maximum gas limit is used. ::: These goals are achieved by creating a minimum gas amount required for callback execution. If the relayer provides at least the minimum gas limit for the callback execution, then the packet lifecycle will not be blocked if the callback runs out of gas during execution, and the callback cannot be retried. If the relayer does not provided the minimum amount of gas and the callback executions runs out of gas, the entire tx is reverted and it may be executed again. -::: tip +:::tip `SendPacket` callback is always reverted if the callback execution fails or returns an error for any reason. This is so that the packet is not sent if the callback execution fails. ::: From af57c5daef5264500ccf8e26cb7b37fb2206ac96 Mon Sep 17 00:00:00 2001 From: srdtrk <59252793+srdtrk@users.noreply.github.com> Date: Wed, 22 May 2024 18:19:10 +0800 Subject: [PATCH 14/16] test: added packet data forwards compatibility test (#6089) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test: added packet data backwards compatibility test * imp: fixed test case * imp: use expError --------- Co-authored-by: Carlos Rodriguez Co-authored-by: Colin Axnér <25233464+colin-axner@users.noreply.github.com> --- modules/apps/transfer/keeper/relay_test.go | 86 ++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/modules/apps/transfer/keeper/relay_test.go b/modules/apps/transfer/keeper/relay_test.go index 1eb02bba9bd..821a76a877c 100644 --- a/modules/apps/transfer/keeper/relay_test.go +++ b/modules/apps/transfer/keeper/relay_test.go @@ -13,6 +13,7 @@ import ( "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" + ibcerrors "github.com/cosmos/ibc-go/v8/modules/core/errors" ibctesting "github.com/cosmos/ibc-go/v8/testing" ) @@ -913,3 +914,88 @@ func (suite *KeeperTestSuite) TestOnTimeoutPacketSetsTotalEscrowAmountForSourceI totalEscrowChainB = suite.chainB.GetSimApp().TransferKeeper.GetTotalEscrowForDenom(suite.chainB.GetContext(), coin.GetDenom()) suite.Require().Equal(sdkmath.ZeroInt(), totalEscrowChainB.Amount) } + +func (suite *KeeperTestSuite) TestPacketForwardsCompatibility() { + // We are testing a scenario where a packet in the future has a new populated + // field called "new_field". And this packet is being sent to this module which + // doesn't have this field in the packet data. The module should be able to handle + // this packet without any issues. + + var packetData []byte + + testCases := []struct { + msg string + malleate func() + expError error + }{ + { + "success: new field", + func() { + jsonString := fmt.Sprintf(`{"denom":"denom","amount":"100","sender":"%s","receiver":"%s","memo":"memo","new_field":"value"}`, suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String()) + packetData = []byte(jsonString) + }, + nil, + }, + { + "success: no new field with memo", + func() { + jsonString := fmt.Sprintf(`{"denom":"denom","amount":"100","sender":"%s","receiver":"%s","memo":"memo"}`, suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String()) + packetData = []byte(jsonString) + }, + nil, + }, + { + "success: no new field without memo", + func() { + jsonString := fmt.Sprintf(`{"denom":"denom","amount":"100","sender":"%s","receiver":"%s"}`, suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String()) + packetData = []byte(jsonString) + }, + nil, + }, + { + "failure: invalid packet data", + func() { + packetData = []byte("invalid packet data") + }, + ibcerrors.ErrUnknownRequest, + }, + { + "failure: missing field", + func() { + jsonString := fmt.Sprintf(`{"amount":"100","sender":%s","receiver":"%s"}`, suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String()) + packetData = []byte(jsonString) + }, + ibcerrors.ErrUnknownRequest, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.msg, func() { + suite.SetupTest() // reset + packetData = nil + + path := ibctesting.NewTransferPath(suite.chainA, suite.chainB) + path.Setup() + + tc.malleate() + + timeoutHeight := suite.chainB.GetTimeoutHeight() + + seq, err := path.EndpointB.SendPacket(timeoutHeight, 0, packetData) + suite.Require().NoError(err) + + packet := channeltypes.NewPacket(packetData, seq, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, timeoutHeight, 0) + + // receive packet on chainA + err = path.RelayPacket(packet) + + expPass := tc.expError == nil + if expPass { + suite.Require().NoError(err) + } else { + suite.Require().ErrorContains(err, tc.expError.Error()) + } + }) + } +} From a1c5adead115c04ac67ed074410e6662fbfb98a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 May 2024 16:26:48 +0200 Subject: [PATCH 15/16] --- (#6355) updated-dependencies: - dependency-name: bufbuild/buf-setup-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/proto-registry.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/proto-registry.yml b/.github/workflows/proto-registry.yml index 029d3db46e5..2031be3083c 100644 --- a/.github/workflows/proto-registry.yml +++ b/.github/workflows/proto-registry.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: bufbuild/buf-setup-action@v1.32.0 + - uses: bufbuild/buf-setup-action@v1.32.1 - uses: bufbuild/buf-push-action@v1 with: input: "proto" From 180501e6389d602a69b922f82b32de012f400133 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Wed, 22 May 2024 23:34:38 +0200 Subject: [PATCH 16/16] docs: updates due to `02-client` routing refactoring (#6049) * docs: updates due to 02-client routing refactoring * lint * fix up grammar suggestions * Update 02-light-client-module.md * remove empty space --------- Co-authored-by: Charly Co-authored-by: Charly --- .../01-developer-guide/01-overview.md | 2 +- .../02-light-client-module.md | 28 ++++++++++++- .../05-updates-and-misbehaviour.md | 42 +++++++++++-------- .../01-developer-guide/06-upgrades.md | 19 +++++---- .../01-developer-guide/07-proofs.md | 17 +++++--- .../01-developer-guide/08-proposals.md | 28 ++++++------- .../01-developer-guide/09-setup.md | 4 +- .../02-localhost/03-client-state.md | 8 +++- .../02-localhost/05-state-verification.md | 2 +- .../03-light-clients/04-wasm/02-concepts.md | 18 +++++++- .../04-wasm/03-integration.md | 11 +++-- .../03-light-clients/04-wasm/04-messages.md | 2 +- .../01-developer-guide/06-proofs.md | 2 +- .../01-developer-guide/01-overview.md | 2 +- .../01-developer-guide/06-proofs.md | 2 +- modules/apps/callbacks/testing/simapp/app.go | 2 +- .../08-wasm/testing/simapp/app.go | 2 +- testing/README.md | 2 +- testing/simapp/app.go | 2 +- 19 files changed, 129 insertions(+), 66 deletions(-) diff --git a/docs/docs/03-light-clients/01-developer-guide/01-overview.md b/docs/docs/03-light-clients/01-developer-guide/01-overview.md index 89459264f7f..e4abc31574e 100644 --- a/docs/docs/03-light-clients/01-developer-guide/01-overview.md +++ b/docs/docs/03-light-clients/01-developer-guide/01-overview.md @@ -23,7 +23,7 @@ Learn how to build IBC light client modules and fulfill the interfaces required IBC uses light clients in order to provide trust-minimized interoperability between sovereign blockchains. Light clients operate under a strict set of rules which provide security guarantees for state updates and facilitate the ability to verify the state of a remote blockchain using merkle proofs. -The following aims to provide a high level IBC light client module developer guide. Access to IBC light clients are gated by the core IBC `MsgServer` which utilizes the abstractions set by the `02-client` submodule to call into a light client module. A light client module developer is only required to implement a set interfaces as defined in the `modules/core/exported` package of ibc-go. +The following aims to provide a high level IBC light client module developer guide. Access to IBC light clients are gated by the core IBC `MsgServer` which utilizes the abstractions set by the `02-client` submodule to call into a light client module. A light client module developer is only required to implement a set of interfaces as defined in the `modules/core/exported` package of ibc-go. A light client module developer should be concerned with three main interfaces: diff --git a/docs/docs/03-light-clients/01-developer-guide/02-light-client-module.md b/docs/docs/03-light-clients/01-developer-guide/02-light-client-module.md index 783b1c74524..2ec8d18eea2 100644 --- a/docs/docs/03-light-clients/01-developer-guide/02-light-client-module.md +++ b/docs/docs/03-light-clients/01-developer-guide/02-light-client-module.md @@ -8,6 +8,10 @@ slug: /ibc/light-clients/light-client-module # Implementing the `LightClientModule` interface +## `RegisterStoreProvider` method + +`RegisterStoreProvider` is called by core IBC when a `LightClientModule` is added to the router. It allows the `LightClientModule` to set a `ClientStoreProvider` ([interface defined in `modules/core/exported`](https://github.com/cosmos/ibc-go/blob/06fd8eb5ee1697e3b43be7528a6e42f5e4a4613c/modules/core/exported/client.go#L49-L52)) which supplies isolated prefix client stores to IBC light client instances. + ## `Status` method `Status` must return the status of the client. @@ -26,6 +30,10 @@ This field is returned in the response of the gRPC [`ibc.core.client.v1.Query/Cl `TimestampAtHeight` must return the timestamp for the consensus state associated with the provided height. This value is used to facilitate timeouts by checking the packet timeout timestamp against the returned value. +## `LatestHeight` method + +`LatestHeight` should return the latest block height that the client state represents. + ## `Initialize` method Clients must validate the initial consensus state, and set the initial client state and consensus state in the provided client store. @@ -33,6 +41,14 @@ Clients may also store any necessary client-specific metadata. `Initialize` is called when a [client is created](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/02-client/keeper/client.go#L30). +## `UpdateState` method + +`UpdateState` updates and stores as necessary any associated information for an IBC client, such as the `ClientState` and corresponding `ConsensusState`. See section [`UpdateState`](05-updates-and-misbehaviour.md#updatestate) for more information. + +## `UpdateStateOnMisbehaviour` method + +`UpdateStateOnMisbehaviour` should perform appropriate state changes on a client state given that misbehaviour has been detected and verified. See section [`UpdateStateOnMisbehaviour`](05-updates-and-misbehaviour.md#updatestateonmisbehaviour) for more information. + ## `VerifyMembership` method `VerifyMembership` must verify the existence of a value at a given commitment path at the specified height. For more information about membership proofs @@ -48,9 +64,17 @@ see the [Existence and non-existence proofs section](07-proofs.md). `VerifyClientMessage` must verify a `ClientMessage`. A `ClientMessage` could be a `Header`, `Misbehaviour`, or batch update. It must handle each type of `ClientMessage` appropriately. Calls to `CheckForMisbehaviour`, `UpdateState`, and `UpdateStateOnMisbehaviour` will assume that the content of the `ClientMessage` has been verified and can be trusted. An error should be returned -if the ClientMessage fails to verify. +if the ClientMessage fails to verify. See section [`VerifyClientMessage`](05-updates-and-misbehaviour.md#verifyclientmessage) for more information. ## `CheckForMisbehaviour` method Checks for evidence of a misbehaviour in `Header` or `Misbehaviour` type. It assumes the `ClientMessage` -has already been verified. +has already been verified. See section [`CheckForMisbehaviour`](05-updates-and-misbehaviour.md#checkformisbehaviour) for more information. + +## `RecoverClient` method + +`RecoverClient` is used to recover an expired or frozen client by updating the client with the state of a substitute client. The method must verify that the provided substitute may be used to update the subject client. See section [Implementing `RecoverClient`](./08-proposals.md#implementing-recoverclient) for more information. + +## `VerifyUpgradeAndUpdateState` method + +`VerifyUpgradeAndUpdateState` provides a path to upgrading clients given an upgraded `ClientState`, upgraded `ConsensusState` and proofs for each. See section [Implementing `VerifyUpgradeAndUpdateState`](./06-upgrades.md#implementing-verifyupgradeandupdatestate) for more information. diff --git a/docs/docs/03-light-clients/01-developer-guide/05-updates-and-misbehaviour.md b/docs/docs/03-light-clients/01-developer-guide/05-updates-and-misbehaviour.md index b32d8b90087..57b92a0fcc1 100644 --- a/docs/docs/03-light-clients/01-developer-guide/05-updates-and-misbehaviour.md +++ b/docs/docs/03-light-clients/01-developer-guide/05-updates-and-misbehaviour.md @@ -10,8 +10,8 @@ slug: /ibc/light-clients/updates-and-misbehaviour As mentioned before in the documentation about [implementing the `ConsensusState` interface](04-consensus-state.md), [`ClientMessage`](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/exported/client.go#L147) is an interface used to update an IBC client. This update may be performed by: -- a single header -- a batch of headers +- a single header, +- a batch of headers, - evidence of misbehaviour, - or any type which when verified produces a change to the consensus state of the IBC client. @@ -19,7 +19,7 @@ This interface has been purposefully kept generic in order to give the maximum a ## Implementing the `ClientMessage` interface -Find the `ClientMessage`interface in `modules/core/exported`: +Find the `ClientMessage` interface in `modules/core/exported`: ```go type ClientMessage interface { @@ -30,20 +30,20 @@ type ClientMessage interface { } ``` -The `ClientMessage` will be passed to the client to be used in [`UpdateClient`](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/02-client/keeper/client.go#L48), which retrieves the `ClientState` by client ID (available in `MsgUpdateClient`). This `ClientState` implements the [`ClientState` interface](03-client-state.md) for its specific consenus type (e.g. Tendermint). +The `ClientMessage` will be passed to the client to be used in [`UpdateClient`](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/02-client/keeper/client.go#L48), which retrieves the `LightClientModule` by client type (parsed from the client ID available in `MsgUpdateClient`). This `LightClientModule` implements the [`LightClientModule` interface](02-light-client-module.md) for its specific consenus type (e.g. Tendermint). -`UpdateClient` will then handle a number of cases including misbehaviour and/or updating the consensus state, utilizing the specific methods defined in the relevant `ClientState`. +`UpdateClient` will then handle a number of cases including misbehaviour and/or updating the consensus state, utilizing the specific methods defined in the relevant `LightClientModule`. ```go -VerifyClientMessage(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg ClientMessage) error -CheckForMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg ClientMessage) bool -UpdateStateOnMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg ClientMessage) -UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg ClientMessage) []Height +VerifyClientMessage(ctx sdk.Context, clientID string, clientMsg ClientMessage) error +CheckForMisbehaviour(ctx sdk.Context, clientID string, clientMsg ClientMessage) bool +UpdateStateOnMisbehaviour(ctx sdk.Context, clientID string, clientMsg ClientMessage) +UpdateState(ctx sdk.Context, clientID string, clientMsg ClientMessage) []Height ``` ## Handling updates and misbehaviour -The functions for handling updates to a light client and evidence of misbehaviour are all found in the [`ClientState`](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/exported/client.go#L36) interface, and will be discussed below. +The functions for handling updates to a light client and evidence of misbehaviour are all found in the [`LightClientModule`](https://github.com/cosmos/ibc-go/blob/501a8462345da099144efe91d495bfcfa18d760d/modules/core/exported/client.go#L51) interface, and will be discussed below. > It is important to note that `Misbehaviour` in this particular context is referring to misbehaviour on the chain level intended to fool the light client. This will be defined by each light client. @@ -53,13 +53,13 @@ The functions for handling updates to a light client and evidence of misbehaviou It must handle each type of `ClientMessage` appropriately. Calls to `CheckForMisbehaviour`, `UpdateState`, and `UpdateStateOnMisbehaviour` will assume that the content of the `ClientMessage` has been verified and can be trusted. An error should be returned if the `ClientMessage` fails to verify. -For an example of a `VerifyClientMessage` implementation, please check the [Tendermint light client](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/light-clients/07-tendermint/update.go#L20). +For an example of a `VerifyClientMessage` implementation, please check the [Tendermint light client](https://github.com/cosmos/ibc-go/blob/76730ff030b52a351096ee941b7e4da44af9f059/modules/light-clients/07-tendermint/update.go#L23). ## `CheckForMisbehaviour` Checks for evidence of a misbehaviour in `Header` or `Misbehaviour` type. It assumes the `ClientMessage` has already been verified. -For an example of a `CheckForMisbehaviour` implementation, please check the [Tendermint light client](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/light-clients/07-tendermint/misbehaviour_handle.go#L19). +For an example of a `CheckForMisbehaviour` implementation, please check the [Tendermint light client](https://github.com/cosmos/ibc-go/blob/76730ff030b52a351096ee941b7e4da44af9f059/modules/light-clients/07-tendermint/misbehaviour_handle.go#L22). > The Tendermint light client [defines `Misbehaviour`](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/light-clients/07-tendermint/misbehaviour.go) as two different types of situations: a situation where two conflicting `Header`s with the same height have been submitted to update a client's `ConsensusState` within the same trusting period, or that the two conflicting `Header`s have been submitted at different heights but the consensus states are not in the correct monotonic time ordering (BFT time violation). More explicitly, updating to a new height must have a timestamp greater than the previous consensus state, or, if inserting a consensus at a past height, then time must be less than those heights which come after and greater than heights which come before. @@ -67,7 +67,7 @@ For an example of a `CheckForMisbehaviour` implementation, please check the [Ten `UpdateStateOnMisbehaviour` should perform appropriate state changes on a client state given that misbehaviour has been detected and verified. This method should only be called when misbehaviour is detected, as it does not perform any misbehaviour checks. Notably, it should freeze the client so that calling the `Status` function on the associated client state no longer returns `Active`. -For an example of a `UpdateStateOnMisbehaviour` implementation, please check the [Tendermint light client](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/light-clients/07-tendermint/update.go#L199). +For an example of a `UpdateStateOnMisbehaviour` implementation, please check the [Tendermint light client](https://github.com/cosmos/ibc-go/blob/76730ff030b52a351096ee941b7e4da44af9f059/modules/light-clients/07-tendermint/update.go#L202). ## `UpdateState` @@ -75,24 +75,30 @@ For an example of a `UpdateStateOnMisbehaviour` implementation, please check the It assumes the `ClientMessage` has already been verified. -For an example of a `UpdateState` implementation, please check the [Tendermint light client](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/light-clients/07-tendermint/update.go#L131). +For an example of a `UpdateState` implementation, please check the [Tendermint light client](https://github.com/cosmos/ibc-go/blob/76730ff030b52a351096ee941b7e4da44af9f059/modules/light-clients/07-tendermint/update.go#L134). ## Putting it all together The `02-client` `Keeper` module in ibc-go offers a reference as to how these functions will be used to [update the client](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/02-client/keeper/client.go#L48). ```go -if err := clientState.VerifyClientMessage(clientMessage); err != nil { +clientModule, found := k.router.GetRoute(clientID) +if !found { + return errorsmod.Wrap(types.ErrRouteNotFound, clientID) +} + +if err := clientModule.VerifyClientMessage(ctx, clientID, clientMsg); err != nil { return err } -foundMisbehaviour := clientState.CheckForMisbehaviour(clientMessage) +foundMisbehaviour := clientModule.CheckForMisbehaviour(ctx, clientID, clientMsg) if foundMisbehaviour { - clientState.UpdateStateOnMisbehaviour(clientMessage) + clientModule.UpdateStateOnMisbehaviour(ctx, clientID, clientMsg) // emit misbehaviour event return } -clientState.UpdateState(clientMessage) // expects no-op on duplicate header +clientModule.UpdateState(ctx, clientID, clientMsg) // expects no-op on duplicate header // emit update event return +``` diff --git a/docs/docs/03-light-clients/01-developer-guide/06-upgrades.md b/docs/docs/03-light-clients/01-developer-guide/06-upgrades.md index 461e63703d1..b0be176ac5a 100644 --- a/docs/docs/03-light-clients/01-developer-guide/06-upgrades.md +++ b/docs/docs/03-light-clients/01-developer-guide/06-upgrades.md @@ -15,21 +15,23 @@ It is vital that high-value IBC clients can upgrade along with their underlying The IBC protocol allows client implementations to provide a path to upgrading clients given the upgraded `ClientState`, upgraded `ConsensusState` and proofs for each. This path is provided in the `VerifyUpgradeAndUpdateState` method: ```go -// NOTE: proof heights are not included as upgrade to a new revision is expected to pass only on the last height committed by the current revision. Clients are responsible for ensuring that the planned last height of the current revision is somehow encoded in the proof verification process. -// This is to ensure that no premature upgrades occur, since upgrade plans committed to by the counterparty may be cancelled or modified before the last planned height. +// NOTE: proof heights are not included as upgrade to a new revision is expected to pass only on the last +// height committed by the current revision. Clients are responsible for ensuring that the planned last +// height of the current revision is somehow encoded in the proof verification process. +// This is to ensure that no premature upgrades occur, since upgrade plans committed to by the counterparty +// may be cancelled or modified before the last planned height. // If the upgrade is verified, the upgraded client and consensus states must be set in the client store. -func (cs ClientState) VerifyUpgradeAndUpdateState( +func (l LightClientModule) VerifyUpgradeAndUpdateState( ctx sdk.Context, - cdc codec.BinaryCodec, - store sdk.KVStore, - newClient ClientState, - newConsState ConsensusState, + clientID string, + newClient []byte, + newConsState []byte, upgradeClientProof, upgradeConsensusStateProof []byte, ) error ``` -> Please refer to the [Tendermint light client implementation](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/light-clients/07-tendermint/upgrade.go#L27) as an example for implementation. +> Please refer to the [Tendermint light client implementation](https://github.com/cosmos/ibc-go/blob/47162061bcbfe74df791161059715a635e31c604/modules/light-clients/07-tendermint/light_client_module.go#L257) as an example for implementation. It is important to note that light clients **must** handle all management of client and consensus states including the setting of updated `ClientState` and `ConsensusState` in the client store. This can include verifying that the submitted upgraded `ClientState` is of a valid `ClientState` type, that the height of the upgraded client is not greater than the height of the current client (in order to preserve BFT monotonic time), or that certain parameters which should not be changed have not been altered in the upgraded `ClientState`. @@ -38,6 +40,7 @@ Developers must ensure that the `MsgUpgradeClient` does not pass until the last ### Upgrade path Clients should have **prior knowledge of the merkle path** that the upgraded client and upgraded consensus states will use. The height at which the upgrade has occurred should also be encoded in the proof. + > The Tendermint client implementation accomplishes this by including an `UpgradePath` in the `ClientState` itself, which is used along with the upgrade height to construct the merkle path under which the client state and consensus state are committed. ## Chain specific vs client specific client parameters diff --git a/docs/docs/03-light-clients/01-developer-guide/07-proofs.md b/docs/docs/03-light-clients/01-developer-guide/07-proofs.md index b6951842be0..67663baff32 100644 --- a/docs/docs/03-light-clients/01-developer-guide/07-proofs.md +++ b/docs/docs/03-light-clients/01-developer-guide/07-proofs.md @@ -18,7 +18,7 @@ For the purposes of ibc-go, there are two types of proofs which are important: e Existence proofs are used in IBC transactions which involve verification of counterparty state for transactions which will result in the writing of provable state. For example, this includes verification of IBC store state for handshakes and packets. -Put simply, existence proofs prove that a particular key and value exists in the tree. Under the hood, an IBC existence proof comprises of two proofs: an IAVL proof that the key exists in IBC store/IBC root hash, and a proof that the IBC root hash exists in the multistore root hash. +Put simply, existence proofs prove that a particular key and value exists in the tree. Under the hood, an IBC existence proof is comprised of two proofs: an IAVL proof that the key exists in IBC store/IBC root hash, and a proof that the IBC root hash exists in the multistore root hash. ## Non-existence proofs @@ -32,13 +32,16 @@ In some cases, there is a necessity to "mock" non-existence proofs if the counte The state verification functions for all IBC data types have been consolidated into two generic methods, `VerifyMembership` and `VerifyNonMembership`. -From the [`ClientState` interface definition](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/exported/client.go#L68-L91), we find: +From the [`LightClientModule` interface definition](https://github.com/cosmos/ibc-go/blob/main/modules/core/exported/client.go#L56), we find: ```go +// VerifyMembership is a generic proof verification method which verifies +// a proof of the existence of a value at a given CommitmentPath at the +// specified height. The caller is expected to construct the full CommitmentPath +// from a CommitmentPrefix and a standardized path (as defined in ICS 24). VerifyMembership( ctx sdk.Context, - clientStore sdk.KVStore, - cdc codec.BinaryCodec, + clientID string, height Height, delayTimePeriod uint64, delayBlockPeriod uint64, @@ -47,8 +50,10 @@ VerifyMembership( value []byte, ) error -// VerifyNonMembership is a generic proof verification method which verifies the absence of a given CommitmentPath at a specified height. -// The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24). +// VerifyNonMembership is a generic proof verification method which verifies +// the absence of a given CommitmentPath at a specified height. The caller is +// expected to construct the full CommitmentPath from a CommitmentPrefix and +// a standardized path (as defined in ICS 24). VerifyNonMembership( ctx sdk.Context, clientStore sdk.KVStore, diff --git a/docs/docs/03-light-clients/01-developer-guide/08-proposals.md b/docs/docs/03-light-clients/01-developer-guide/08-proposals.md index 579a9e372e4..c7e4a2da51e 100644 --- a/docs/docs/03-light-clients/01-developer-guide/08-proposals.md +++ b/docs/docs/03-light-clients/01-developer-guide/08-proposals.md @@ -8,29 +8,29 @@ slug: /ibc/light-clients/proposals # Handling proposals -It is possible to update the client with the state of the substitute client through a governance proposal. [This type of governance proposal](https://ibc.cosmos.network/main/ibc/proposals.html) is typically used to recover an expired or frozen client, as it can recover the entire state and therefore all existing channels built on top of the client. `CheckSubstituteAndUpdateState` should be implemented to handle the proposal. +It is possible to update the client with the state of the substitute client through a governance proposal. [This type of governance proposal](https://ibc.cosmos.network/main/ibc/proposals.html) is typically used to recover an expired or frozen client, as it can recover the entire state and therefore all existing channels built on top of the client. `RecoverClient` should be implemented to handle the proposal. -## Implementing `CheckSubstituteAndUpdateState` +## Implementing `RecoverClient` -In the [`ClientState`interface](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/exported/client.go), we find: +In the [`LightClientModule` interface](https://github.com/cosmos/ibc-go/blob/501a8462345da099144efe91d495bfcfa18d760d/modules/core/exported/client.go#L51), we find: ```go -// CheckSubstituteAndUpdateState must verify that the provided substitute may be used to update the subject client. -// The light client must set the updated client and consensus states within the clientStore for the subject client. -CheckSubstituteAndUpdateState( - ctx sdk.Context, - cdc codec.BinaryCodec, - subjectClientStore, - substituteClientStore sdk.KVStore, - substituteClient ClientState, +// RecoverClient must verify that the provided substitute +// may be used to update the subject client. The light client +// must set the updated client and consensus states within +// the clientStore for the subject client. +RecoverClient( + ctx sdk.Context, + clientID, + substituteClientID string, ) error ``` Prior to updating, this function must verify that: -- the substitute client is the same type as the subject client. For a reference implementation, please see the [Tendermint light client](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/light-clients/07-tendermint/proposal_handle.go#L32). -- the provided substitute may be used to update the subject client. This may mean that certain parameters must remain unaltered. For example, a [valid substitute Tendermint light client](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/light-clients/07-tendermint/proposal_handle.go#L84) must NOT change the chain ID, trust level, max clock drift, unbonding period, proof specs or upgrade path. Please note that `AllowUpdateAfterMisbehaviour` and `AllowUpdateAfterExpiry` have been deprecated (see ADR 026 for more information). +- the substitute client is the same type as the subject client. For a reference implementation, please see the [Tendermint light client](https://github.com/cosmos/ibc-go/blob/47162061bcbfe74df791161059715a635e31c604/modules/light-clients/07-tendermint/proposal_handle.go#L34). +- the provided substitute may be used to update the subject client. This may mean that certain parameters must remain unaltered. For example, a [valid substitute Tendermint light client](https://github.com/cosmos/ibc-go/blob/47162061bcbfe74df791161059715a635e31c604/modules/light-clients/07-tendermint/proposal_handle.go#L86) must NOT change the chain ID, trust level, max clock drift, unbonding period, proof specs or upgrade path. Please note that `AllowUpdateAfterMisbehaviour` and `AllowUpdateAfterExpiry` have been deprecated (see ADR 026 for more information). After these checks are performed, the function must [set the updated client and consensus states](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/light-clients/07-tendermint/proposal_handle.go#L77) within the client store for the subject client. -Please refer to the [Tendermint light client implementation](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/light-clients/07-tendermint/proposal_handle.go#L27) for reference. +Please refer to the [Tendermint light client implementation](https://github.com/cosmos/ibc-go/blob/47162061bcbfe74df791161059715a635e31c604/modules/light-clients/07-tendermint/proposal_handle.go#L79) for reference. diff --git a/docs/docs/03-light-clients/01-developer-guide/09-setup.md b/docs/docs/03-light-clients/01-developer-guide/09-setup.md index 31481ea7642..23ced3cf80a 100644 --- a/docs/docs/03-light-clients/01-developer-guide/09-setup.md +++ b/docs/docs/03-light-clients/01-developer-guide/09-setup.md @@ -100,9 +100,9 @@ message MsgCreateClient { } ``` -Leveraging protobuf `Any` encoding allows core IBC to [unpack](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/keeper/msg_server.go#L28-L36) both the `ClientState` and `ConsensusState` into their respective interface types registered previously using the light client module's `RegisterInterfaces` method. +Leveraging protobuf `Any` encoding allows core IBC to [unpack](https://github.com/cosmos/ibc-go/blob/47162061bcbfe74df791161059715a635e31c604/modules/core/keeper/msg_server.go#L38) the `ClientState` into its respective interface type registered previously using the light client module's `RegisterInterfaces` method. -Within the `02-client` submodule, the [`ClientState` is then initialized](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/02-client/keeper/client.go#L30-L32) with its own isolated key-value store, namespaced using a unique client identifier. +Within the `02-client` submodule, the [`ClientState` is then initialized](https://github.com/cosmos/ibc-go/blob/47162061bcbfe74df791161059715a635e31c604/modules/core/02-client/keeper/client.go#L40-L42) with its own isolated key-value store, namespaced using a unique client identifier. In order to successfully create an IBC client using a new client type, it [must be supported](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/02-client/keeper/client.go#L19-L25). Light client support in IBC is gated by on-chain governance. The allow list may be updated by submitting a new governance proposal to update the `02-client` parameter `AllowedClients`. diff --git a/docs/docs/03-light-clients/02-localhost/03-client-state.md b/docs/docs/03-light-clients/02-localhost/03-client-state.md index 377f06c7358..a242a2b649c 100644 --- a/docs/docs/03-light-clients/02-localhost/03-client-state.md +++ b/docs/docs/03-light-clients/02-localhost/03-client-state.md @@ -22,8 +22,12 @@ It calls `CreateLocalhostClient`, declaring a new `ClientState` and initializing ```go func (k Keeper) CreateLocalhostClient(ctx sdk.Context) error { - var clientState localhost.ClientState - return clientState.Initialize(ctx, k.cdc, k.ClientStore(ctx, exported.LocalhostClientID), nil) + clientModule, found := k.router.GetRoute(exported.LocalhostClientID) + if !found { + return errorsmod.Wrap(types.ErrRouteNotFound, exported.LocalhostClientID) + } + + return clientModule.Initialize(ctx, exported.LocalhostClientID, nil, nil) } ``` diff --git a/docs/docs/03-light-clients/02-localhost/05-state-verification.md b/docs/docs/03-light-clients/02-localhost/05-state-verification.md index ddf4f03de10..eb92f2899e9 100644 --- a/docs/docs/03-light-clients/02-localhost/05-state-verification.md +++ b/docs/docs/03-light-clients/02-localhost/05-state-verification.md @@ -8,7 +8,7 @@ slug: /ibc/light-clients/localhost/state-verification # State verification -The localhost client handles state verification through the `ClientState` interface methods `VerifyMembership` and `VerifyNonMembership` by performing read-only operations directly on the core IBC store. +The localhost client handles state verification through the `LightClientModule` interface methods `VerifyMembership` and `VerifyNonMembership` by performing read-only operations directly on the core IBC store. When verifying channel state in handshakes or processing packets the `09-localhost` client can simply compare bytes stored under the standardized key paths defined by [ICS-24](https://github.com/cosmos/ibc/tree/main/spec/core/ics-024-host-requirements). diff --git a/docs/docs/03-light-clients/04-wasm/02-concepts.md b/docs/docs/03-light-clients/04-wasm/02-concepts.md index ac9fa18f1f6..978b77d3c73 100644 --- a/docs/docs/03-light-clients/04-wasm/02-concepts.md +++ b/docs/docs/03-light-clients/04-wasm/02-concepts.md @@ -11,7 +11,23 @@ Learn about the differences between a proxy light client and a Wasm light client ## Proxy light client -The `08-wasm` module is not a regular light client in the same sense as, for example, the 07-tendermint light client. `08-wasm` is instead a *proxy* light client module, and this means that the module acts a proxy to the actual implementations of light clients. The module will act as a wrapper for the actual light clients uploaded as Wasm byte code and will delegate all operations to them (i.e. `08-wasm` just passes through the requests to the Wasm light clients). Still, the `08-wasm` module implements all the required interfaces necessary to integrate with core IBC, so that 02-client can call into it as it would for any other light client module. These interfaces are `ClientState`, `ConsensusState` and `ClientMessage`, and we will describe them in the context of `08-wasm` in the following sections. For more information about this set of interfaces, please read section [Overview of the light client module developer guide](../01-developer-guide/01-overview.md#overview). +The `08-wasm` module is not a regular light client in the same sense as, for example, the 07-tendermint light client. `08-wasm` is instead a *proxy* light client module, and this means that the module acts a proxy to the actual implementations of light clients. The module will act as a wrapper for the actual light clients uploaded as Wasm byte code and will delegate all operations to them (i.e. `08-wasm` just passes through the requests to the Wasm light clients). Still, the `08-wasm` module implements all the required interfaces necessary to integrate with core IBC, so that 02-client can call into it as it would for any other light client module. These interfaces are `LightClientModule`, `ClientState`, `ConsensusState` and `ClientMessage`, and we will describe them in the context of `08-wasm` in the following sections. For more information about this set of interfaces, please read section [Overview of the light client module developer guide](../01-developer-guide/01-overview.md#overview). + +### `LightClientModule` + +The `08-wasm`'s `LightClientModule` data structure contains two fields: + +- `keeper` is the `08-wasm` module keeper. +- `storeProvider` encapsulates the IBC core store key and provides access to isolated prefix stores for each client so they can read/write in separate namespaces. + +```go +type LightClientModule struct { + keeper wasmkeeper.Keeper + storeProvider exported.ClientStoreProvider +} +``` + +See section [`LightClientModule` of the light client module developer guide](../01-developer-guide/01-overview.md#lightclientmodule) for more information about the `LightClientModule` interface. ### `ClientState` diff --git a/docs/docs/03-light-clients/04-wasm/03-integration.md b/docs/docs/03-light-clients/04-wasm/03-integration.md index 7d6d4541430..69697560761 100644 --- a/docs/docs/03-light-clients/04-wasm/03-integration.md +++ b/docs/docs/03-light-clients/04-wasm/03-integration.md @@ -27,7 +27,7 @@ The following table shows the compatibility matrix between the `08-wasm` module, ## `app.go` setup -The sample code below shows the relevant integration points in `app.go` required to setup the `08-wasm` module in a chain binary. Since `08-wasm` is a light client module itself, please check out as well the section [Integrating light clients](../../01-ibc/02-integration.md#integrating-light-clients) for more information: +The sample code below shows the relevant integration points in `app.go` required to set up the `08-wasm` module in a chain binary. Since `08-wasm` is a light client module itself, please check out as well the section [Integrating light clients](../../01-ibc/02-integration.md#integrating-light-clients) for more information: ```go // app.go @@ -87,6 +87,11 @@ func NewSimApp( wasmVM, app.GRPCQueryRouter(), ) + + clientRouter := app.IBCKeeper.ClientKeeper.GetRouter() + wasmLightClientModule := wasm.NewLightClientModule(app.WasmClientKeeper) + clientRouter.AddRoute(ibcwasmtypes.ModuleName, &wasmLightClientModule) + app.ModuleManager = module.NewManager( // SDK app modules ... @@ -141,13 +146,13 @@ func NewSimApp( ## Keeper instantiation -When it comes to instantiating `08-wasm`'s keeper there are two recommended ways of doing it. Choosing one or the other will depend on whether the chain already integrates [`x/wasm`](https://github.com/CosmWasm/wasmd/tree/main/x/wasm) or not. +When it comes to instantiating `08-wasm`'s keeper, there are two recommended ways of doing it. Choosing one or the other will depend on whether the chain already integrates [`x/wasm`](https://github.com/CosmWasm/wasmd/tree/main/x/wasm) or not. ### If `x/wasm` is present If the chain where the module is integrated uses `x/wasm` then we recommend that both `08-wasm` and `x/wasm` share the same Wasm VM instance. Having two separate Wasm VM instances is still possible, but care should be taken to make sure that both instances do not share the directory when the VM stores blobs and various caches, otherwise unexpected behaviour is likely to happen (from `x/wasm` v0.51 and `08-wasm` v0.2.0+ibc-go-v8.3-wasmvm-v2.0 this will be forbidden anyway, since wasmvm v2.0.0 and above will not allow two different Wasm VM instances to shared the same data folder). -In order to share the Wasm VM instance please follow the guideline below. Please note that this requires `x/wasm` v0.41 or above. +In order to share the Wasm VM instance, please follow the guideline below. Please note that this requires `x/wasm` v0.41 or above. - Instantiate the Wasm VM in `app.go` with the parameters of your choice. - [Create an `Option` with this Wasm VM instance](https://github.com/CosmWasm/wasmd/blob/db93d7b6c7bb6f4a340d74b96a02cec885729b59/x/wasm/keeper/options.go#L21-L25). diff --git a/docs/docs/03-light-clients/04-wasm/04-messages.md b/docs/docs/03-light-clients/04-wasm/04-messages.md index 6b8321583c2..cbb9571616b 100644 --- a/docs/docs/03-light-clients/04-wasm/04-messages.md +++ b/docs/docs/03-light-clients/04-wasm/04-messages.md @@ -27,7 +27,7 @@ This message is expected to fail if: Only light client contracts stored using `MsgStoreCode` are allowed to be instantiated. An attempt to create a light client from contracts uploaded via other means (e.g. through `x/wasm` if the module shares the same Wasm VM instance with 08-wasm) will fail. Due to the idempotent nature of the Wasm VM's `StoreCode` function, it is possible to store the same byte code multiple times. -When execution of `MsgStoreCode` succeeds, the checksum of the contract (i.e. the sha256 hash of the contract's byte code) is stored in an allow list. When a relayer submits [`MsgCreateClient`](https://github.com/cosmos/ibc-go/blob/v8.0.0/proto/ibc/core/client/v1/tx.proto#L25-L37) with 08-wasm's `ClientState`, the client state includes the checksum of the Wasm byte code that should be called. Then 02-client calls [08-wasm's implementation of `Initialize` function](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/02-client/keeper/client.go#L36) (which is an interface function part of `ClientState`), and it will check that the checksum in the client state matches one of the checksums in the allow list. If a match is found, the light client is initialized; otherwise, the transaction is aborted. +When execution of `MsgStoreCode` succeeds, the checksum of the contract (i.e. the sha256 hash of the contract's byte code) is stored in an allow list. When a relayer submits [`MsgCreateClient`](https://github.com/cosmos/ibc-go/blob/v8.0.0/proto/ibc/core/client/v1/tx.proto#L25-L37) with 08-wasm's `ClientState`, the client state includes the checksum of the Wasm byte code that should be called. Then 02-client calls [08-wasm's implementation of `Initialize` function](https://github.com/cosmos/ibc-go/blob/06fd8eb5ee1697e3b43be7528a6e42f5e4a4613c/modules/core/02-client/keeper/client.go#L40) (which is an interface function part of `LightClientModule`), and it will check that the checksum in the client state matches one of the checksums in the allow list. If a match is found, the light client is initialized; otherwise, the transaction is aborted. ## `MsgMigrateContract` diff --git a/docs/versioned_docs/version-v7.5.x/03-light-clients/01-developer-guide/06-proofs.md b/docs/versioned_docs/version-v7.5.x/03-light-clients/01-developer-guide/06-proofs.md index c5a651d0dea..c168865b303 100644 --- a/docs/versioned_docs/version-v7.5.x/03-light-clients/01-developer-guide/06-proofs.md +++ b/docs/versioned_docs/version-v7.5.x/03-light-clients/01-developer-guide/06-proofs.md @@ -18,7 +18,7 @@ For the purposes of ibc-go, there are two types of proofs which are important: e Existence proofs are used in IBC transactions which involve verification of counterparty state for transactions which will result in the writing of provable state. For example, this includes verification of IBC store state for handshakes and packets. -Put simply, existence proofs prove that a particular key and value exists in the tree. Under the hood, an IBC existence proof comprises of two proofs: an IAVL proof that the key exists in IBC store/IBC root hash, and a proof that the IBC root hash exists in the multistore root hash. +Put simply, existence proofs prove that a particular key and value exists in the tree. Under the hood, an IBC existence proof is comprised of two proofs: an IAVL proof that the key exists in IBC store/IBC root hash, and a proof that the IBC root hash exists in the multistore root hash. ## Non-existence proofs diff --git a/docs/versioned_docs/version-v8.3.x/03-light-clients/01-developer-guide/01-overview.md b/docs/versioned_docs/version-v8.3.x/03-light-clients/01-developer-guide/01-overview.md index eeef65a7be7..9626d45ebb1 100644 --- a/docs/versioned_docs/version-v8.3.x/03-light-clients/01-developer-guide/01-overview.md +++ b/docs/versioned_docs/version-v8.3.x/03-light-clients/01-developer-guide/01-overview.md @@ -23,7 +23,7 @@ Learn how to build IBC light client modules and fulfill the interfaces required IBC uses light clients in order to provide trust-minimized interoperability between sovereign blockchains. Light clients operate under a strict set of rules which provide security guarantees for state updates and facilitate the ability to verify the state of a remote blockchain using merkle proofs. -The following aims to provide a high level IBC light client module developer guide. Access to IBC light clients are gated by the core IBC `MsgServer` which utilizes the abstractions set by the `02-client` submodule to call into a light client module. A light client module developer is only required to implement a set interfaces as defined in the `modules/core/exported` package of ibc-go. +The following aims to provide a high level IBC light client module developer guide. Access to IBC light clients is gated by the core IBC `MsgServer` which utilizes the abstractions set by the `02-client` submodule to call into a light client module. A light client module developer is only required to implement a set interfaces as defined in the `modules/core/exported` package of ibc-go. A light client module developer should be concerned with three main interfaces: diff --git a/docs/versioned_docs/version-v8.3.x/03-light-clients/01-developer-guide/06-proofs.md b/docs/versioned_docs/version-v8.3.x/03-light-clients/01-developer-guide/06-proofs.md index 636e2b70e80..c3a41b7340e 100644 --- a/docs/versioned_docs/version-v8.3.x/03-light-clients/01-developer-guide/06-proofs.md +++ b/docs/versioned_docs/version-v8.3.x/03-light-clients/01-developer-guide/06-proofs.md @@ -18,7 +18,7 @@ For the purposes of ibc-go, there are two types of proofs which are important: e Existence proofs are used in IBC transactions which involve verification of counterparty state for transactions which will result in the writing of provable state. For example, this includes verification of IBC store state for handshakes and packets. -Put simply, existence proofs prove that a particular key and value exists in the tree. Under the hood, an IBC existence proof comprises of two proofs: an IAVL proof that the key exists in IBC store/IBC root hash, and a proof that the IBC root hash exists in the multistore root hash. +Put simply, existence proofs prove that a particular key and value exists in the tree. Under the hood, an IBC existence proof is comprised of two proofs: an IAVL proof that the key exists in IBC store/IBC root hash, and a proof that the IBC root hash exists in the multistore root hash. ## Non-existence proofs diff --git a/modules/apps/callbacks/testing/simapp/app.go b/modules/apps/callbacks/testing/simapp/app.go index db4eee5c2fc..de62728bfa8 100644 --- a/modules/apps/callbacks/testing/simapp/app.go +++ b/modules/apps/callbacks/testing/simapp/app.go @@ -767,7 +767,7 @@ func NewSimApp( // meaning that both `runMsgs` and `postHandler` state will be committed if // both are successful, and both will be reverted if any of the two fails. // - // The SDK exposes a default postHandlers chain, which comprises of only + // The SDK exposes a default postHandlers chain, which is comprised of only // one decorator: the Transaction Tips decorator. However, some chains do // not need it by default, so feel free to comment the next line if you do // not need tips. diff --git a/modules/light-clients/08-wasm/testing/simapp/app.go b/modules/light-clients/08-wasm/testing/simapp/app.go index 8537c7f797d..9370edef704 100644 --- a/modules/light-clients/08-wasm/testing/simapp/app.go +++ b/modules/light-clients/08-wasm/testing/simapp/app.go @@ -814,7 +814,7 @@ func NewSimApp( // meaning that both `runMsgs` and `postHandler` state will be committed if // both are successful, and both will be reverted if any of the two fails. // - // The SDK exposes a default postHandlers chain, which comprises of only + // The SDK exposes a default postHandlers chain, which is comprised of only // one decorator: the Transaction Tips decorator. However, some chains do // not need it by default, so feel free to comment the next line if you do // not need tips. diff --git a/testing/README.md b/testing/README.md index dfef3e73604..b06b6c652d6 100644 --- a/testing/README.md +++ b/testing/README.md @@ -2,7 +2,7 @@ ## Components -The testing package comprises of four parts constructed as a stack. +The testing package is comprised of four parts constructed as a stack. - coordinator - chain diff --git a/testing/simapp/app.go b/testing/simapp/app.go index cbb77eac3db..5b52e5f1f52 100644 --- a/testing/simapp/app.go +++ b/testing/simapp/app.go @@ -755,7 +755,7 @@ func NewSimApp( // meaning that both `runMsgs` and `postHandler` state will be committed if // both are successful, and both will be reverted if any of the two fails. // - // The SDK exposes a default postHandlers chain, which comprises of only + // The SDK exposes a default postHandlers chain, which is comprised of only // one decorator: the Transaction Tips decorator. However, some chains do // not need it by default, so feel free to comment the next line if you do // not need tips.