From 2bd592028dadfb8224aaf99af5d1364f8005af17 Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Wed, 3 Jul 2024 14:54:48 +0200 Subject: [PATCH 1/4] refactor!: add v2 `MerklePath` with bytes in favour of strings (#6644) * refactor: adapt merkle path to use repeated bytes in favour of strings * refactor: update NewMerklePath func sig to take bytes * nit: rm unnecessary variable * nit: rename var * chore: add changelog * fix: introduce legacy merkle path type for encoding compatibility with existing 08-wasm contracts * refactor: adapt code to handle v2 proto MerklePath * chore: add deprecation notices for v1 merkle path * chore: update changelog * fix: use pointer to leverage omitempty correctly in contract api * test: add tests for 08-wasm contract api encoding * refactor: adapt IsValidUTF func per review suggestion and add more tests * refactor: use v2.MerklePath in contract api and update 08-wasm changelog * Update CHANGELOG.md --------- Co-authored-by: Carlos Rodriguez --- CHANGELOG.md | 1 + .../core/02-client/keeper/grpc_query_test.go | 8 +- modules/core/02-client/types/query.pb.go | 269 +++++++-------- modules/core/03-connection/keeper/verify.go | 20 +- .../core/23-commitment/types/commitment.pb.go | 62 ++-- modules/core/23-commitment/types/merkle.go | 33 +- .../core/23-commitment/types/merkle_test.go | 55 +-- .../core/23-commitment/types/utils_test.go | 4 +- .../23-commitment/types/v2/commitment.pb.go | 325 ++++++++++++++++++ modules/core/23-commitment/types/v2/merkle.go | 30 ++ .../06-solomachine/client_state.go | 10 +- .../light_client_module_test.go | 30 +- .../07-tendermint/client_state.go | 9 +- .../07-tendermint/light_client_module_test.go | 34 +- .../light-clients/07-tendermint/upgrade.go | 21 +- modules/light-clients/08-wasm/CHANGELOG.md | 30 +- .../08-wasm/keeper/querier_test.go | 2 +- .../08-wasm/light_client_module.go | 12 +- .../08-wasm/light_client_module_test.go | 10 +- .../08-wasm/types/contract_api.go | 24 +- .../09-localhost/client_state.go | 13 +- .../09-localhost/light_client_module_test.go | 24 +- proto/ibc/core/client/v1/query.proto | 8 +- proto/ibc/core/commitment/v1/commitment.proto | 3 +- proto/ibc/core/commitment/v2/commitment.proto | 12 + testing/solomachine.go | 37 +- 26 files changed, 742 insertions(+), 344 deletions(-) create mode 100644 modules/core/23-commitment/types/v2/commitment.pb.go create mode 100644 modules/core/23-commitment/types/v2/merkle.go create mode 100644 proto/ibc/core/commitment/v2/commitment.proto diff --git a/CHANGELOG.md b/CHANGELOG.md index 74834f51b28..92661f15033 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (apps/transfer) [\#6440](https://github.com/cosmos/ibc-go/pull/6440) Remove `GetPrefixedDenom`. * (apps/transfer) [\#6508](https://github.com/cosmos/ibc-go/pull/6508) Remove the `DenomTrace` type. * (apps/27-interchain-accounts) [\#6598](https://github.com/cosmos/ibc-go/pull/6598) Mark the `requests` repeated field of `MsgModuleQuerySafe` non-nullable. +* (23-commmitment) [\#6644](https://github.com/cosmos/ibc-go/pull/6644) Introduce commitment/v2 `MerklePath` to include `repeated bytes` in favour of `repeated string`. This supports using merkle path keys which include non UTF-8 encoded runes. * (23-commmitment) [\#6633](https://github.com/cosmos/ibc-go/pull/6633) MerklePath has been changed to use `repeated bytes` in favour of `repeated strings`. ### State Machine Breaking diff --git a/modules/core/02-client/keeper/grpc_query_test.go b/modules/core/02-client/keeper/grpc_query_test.go index 2a916d89c8b..132332809f9 100644 --- a/modules/core/02-client/keeper/grpc_query_test.go +++ b/modules/core/02-client/keeper/grpc_query_test.go @@ -803,7 +803,7 @@ func (suite *KeeperTestSuite) TestQueryVerifyMembershipProof() { channelProof, proofHeight := path.EndpointB.QueryProof(host.ChannelKey(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)) - merklePath := commitmenttypes.NewMerklePath(host.ChannelPath(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)) + merklePath := commitmenttypes.NewMerklePath(host.ChannelKey(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)) merklePath, err = commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -890,7 +890,7 @@ func (suite *KeeperTestSuite) TestQueryVerifyMembershipProof() { ClientId: ibctesting.FirstClientID, Proof: []byte{0x01}, ProofHeight: types.NewHeight(1, 100), - MerklePath: commitmenttypes.NewMerklePath("/ibc", host.ChannelPath(mock.PortID, ibctesting.FirstChannelID)), + MerklePath: commitmenttypes.NewMerklePath([]byte("/ibc"), host.ChannelKey(mock.PortID, ibctesting.FirstChannelID)), } }, errors.New("empty value"), @@ -902,7 +902,7 @@ func (suite *KeeperTestSuite) TestQueryVerifyMembershipProof() { ClientId: wasmClientID, // use a client type that is not registered Proof: []byte{0x01}, ProofHeight: types.NewHeight(1, 100), - MerklePath: commitmenttypes.NewMerklePath("/ibc", host.ChannelPath(mock.PortID, ibctesting.FirstChannelID)), + MerklePath: commitmenttypes.NewMerklePath([]byte("/ibc"), host.ChannelKey(mock.PortID, ibctesting.FirstChannelID)), Value: []byte{0x01}, } }, @@ -918,7 +918,7 @@ func (suite *KeeperTestSuite) TestQueryVerifyMembershipProof() { ClientId: path.EndpointA.ClientID, Proof: []byte{0x01}, ProofHeight: types.NewHeight(1, 100), - MerklePath: commitmenttypes.NewMerklePath("/ibc", host.ChannelPath(mock.PortID, ibctesting.FirstChannelID)), + MerklePath: commitmenttypes.NewMerklePath([]byte("/ibc"), host.ChannelKey(mock.PortID, ibctesting.FirstChannelID)), Value: []byte{0x01}, } }, diff --git a/modules/core/02-client/types/query.pb.go b/modules/core/02-client/types/query.pb.go index bad89fe1fdc..8130717af64 100644 --- a/modules/core/02-client/types/query.pb.go +++ b/modules/core/02-client/types/query.pb.go @@ -11,7 +11,7 @@ import ( _ "github.com/cosmos/gogoproto/gogoproto" grpc1 "github.com/cosmos/gogoproto/grpc" proto "github.com/cosmos/gogoproto/proto" - types1 "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" + v2 "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types/v2" _ "google.golang.org/genproto/googleapis/api/annotations" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" @@ -969,14 +969,14 @@ type QueryVerifyMembershipRequest struct { Proof []byte `protobuf:"bytes,2,opt,name=proof,proto3" json:"proof,omitempty"` // the height of the commitment root at which the proof is verified. ProofHeight Height `protobuf:"bytes,3,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height"` - // the commitment key path. - MerklePath types1.MerklePath `protobuf:"bytes,4,opt,name=merkle_path,json=merklePath,proto3" json:"merkle_path"` // the value which is proven. Value []byte `protobuf:"bytes,5,opt,name=value,proto3" json:"value,omitempty"` // optional time delay TimeDelay uint64 `protobuf:"varint,6,opt,name=time_delay,json=timeDelay,proto3" json:"time_delay,omitempty"` // optional block delay BlockDelay uint64 `protobuf:"varint,7,opt,name=block_delay,json=blockDelay,proto3" json:"block_delay,omitempty"` + // the commitment key path. + MerklePath v2.MerklePath `protobuf:"bytes,8,opt,name=merkle_path,json=merklePath,proto3" json:"merkle_path"` } func (m *QueryVerifyMembershipRequest) Reset() { *m = QueryVerifyMembershipRequest{} } @@ -1033,13 +1033,6 @@ func (m *QueryVerifyMembershipRequest) GetProofHeight() Height { return Height{} } -func (m *QueryVerifyMembershipRequest) GetMerklePath() types1.MerklePath { - if m != nil { - return m.MerklePath - } - return types1.MerklePath{} -} - func (m *QueryVerifyMembershipRequest) GetValue() []byte { if m != nil { return m.Value @@ -1061,6 +1054,13 @@ func (m *QueryVerifyMembershipRequest) GetBlockDelay() uint64 { return 0 } +func (m *QueryVerifyMembershipRequest) GetMerklePath() v2.MerklePath { + if m != nil { + return m.MerklePath + } + return v2.MerklePath{} +} + // QueryVerifyMembershipResponse is the response type for the Query/VerifyMembership RPC method type QueryVerifyMembershipResponse struct { // boolean indicating success or failure of proof verification. @@ -1133,85 +1133,86 @@ func init() { func init() { proto.RegisterFile("ibc/core/client/v1/query.proto", fileDescriptor_dc42cdfd1d52d76e) } var fileDescriptor_dc42cdfd1d52d76e = []byte{ - // 1242 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcd, 0x4f, 0x1b, 0x47, - 0x1b, 0x67, 0x08, 0x10, 0x78, 0xec, 0x40, 0x34, 0x01, 0xe2, 0x2c, 0xc4, 0xc0, 0xf2, 0xbe, 0x85, - 0x50, 0xd8, 0xc5, 0xa6, 0x01, 0x1a, 0xa9, 0x52, 0x4b, 0xaa, 0x34, 0x1c, 0x92, 0x52, 0x57, 0xfd, - 0x50, 0xa5, 0xca, 0x5a, 0xaf, 0x07, 0x7b, 0x15, 0xef, 0xae, 0xe3, 0xd9, 0xb5, 0x84, 0x22, 0x2e, - 0x9c, 0x72, 0x6b, 0xa5, 0x4a, 0xbd, 0x56, 0xea, 0xb1, 0x87, 0x28, 0x87, 0x4a, 0xb9, 0xf6, 0xd4, - 0x72, 0x8c, 0xd4, 0x1e, 0x7a, 0x6a, 0x2a, 0xa8, 0xd4, 0x7f, 0xa3, 0xda, 0x99, 0x59, 0x7b, 0xd7, - 0x1e, 0xc7, 0xeb, 0x2a, 0xe9, 0xcd, 0xfb, 0x7c, 0xfe, 0x9e, 0x8f, 0x99, 0xdf, 0xc8, 0x90, 0xb5, - 0x4a, 0xa6, 0x6e, 0xba, 0x0d, 0xa2, 0x9b, 0x35, 0x8b, 0x38, 0x9e, 0xde, 0xcc, 0xe9, 0x0f, 0x7d, - 0xd2, 0x38, 0xd2, 0xea, 0x0d, 0xd7, 0x73, 0x31, 0xb6, 0x4a, 0xa6, 0x16, 0xe8, 0x35, 0xae, 0xd7, - 0x9a, 0x39, 0x65, 0xcd, 0x74, 0xa9, 0xed, 0x52, 0xbd, 0x64, 0x50, 0xc2, 0x8d, 0xf5, 0x66, 0xae, - 0x44, 0x3c, 0x23, 0xa7, 0xd7, 0x8d, 0x8a, 0xe5, 0x18, 0x9e, 0xe5, 0x3a, 0xdc, 0x5f, 0x99, 0x13, - 0xb6, 0xa1, 0x59, 0x34, 0xb8, 0xb2, 0x20, 0x49, 0x2e, 0xd2, 0x70, 0x83, 0x95, 0xb6, 0x81, 0x6b, - 0xdb, 0x96, 0x67, 0x87, 0x46, 0xad, 0x2f, 0x61, 0x78, 0xad, 0xe2, 0xba, 0x95, 0x1a, 0xd1, 0xd9, - 0x57, 0xc9, 0x3f, 0xd4, 0x0d, 0x27, 0x4c, 0x32, 0x2f, 0x54, 0x46, 0xdd, 0xd2, 0x0d, 0xc7, 0x71, - 0x3d, 0x06, 0x8f, 0x0a, 0xed, 0x74, 0xc5, 0xad, 0xb8, 0xec, 0xa7, 0x1e, 0xfc, 0xe2, 0x52, 0x75, - 0x1b, 0xae, 0x7e, 0x14, 0xe0, 0xbc, 0xcd, 0xc0, 0x7c, 0xec, 0x19, 0x1e, 0x29, 0x90, 0x87, 0x3e, - 0xa1, 0x1e, 0x9e, 0x83, 0x09, 0x0e, 0xb1, 0x68, 0x95, 0x33, 0x68, 0x11, 0xad, 0x4e, 0x14, 0xc6, - 0xb9, 0x60, 0xbf, 0xac, 0x3e, 0x41, 0x90, 0xe9, 0x76, 0xa4, 0x75, 0xd7, 0xa1, 0x04, 0xef, 0x40, - 0x5a, 0x78, 0xd2, 0x40, 0xce, 0x9c, 0x53, 0xf9, 0x69, 0x8d, 0xe3, 0xd3, 0x42, 0xe8, 0xda, 0x7b, - 0xce, 0x51, 0x21, 0x65, 0xb6, 0x03, 0xe0, 0x69, 0x18, 0xad, 0x37, 0x5c, 0xf7, 0x30, 0x33, 0xbc, - 0x88, 0x56, 0xd3, 0x05, 0xfe, 0x81, 0x6f, 0x43, 0x9a, 0xfd, 0x28, 0x56, 0x89, 0x55, 0xa9, 0x7a, - 0x99, 0x0b, 0x2c, 0x9c, 0xa2, 0x75, 0x0f, 0x4c, 0xbb, 0xcb, 0x2c, 0xf6, 0x46, 0x4e, 0xff, 0x58, - 0x18, 0x2a, 0xa4, 0x98, 0x17, 0x17, 0xa9, 0xa5, 0x6e, 0xbc, 0x34, 0xac, 0xf4, 0x0e, 0x40, 0x7b, - 0x9c, 0x02, 0xed, 0x1b, 0x1a, 0x9f, 0xa7, 0x16, 0xcc, 0x5e, 0xe3, 0xb3, 0x14, 0xb3, 0xd7, 0x0e, - 0x8c, 0x4a, 0xd8, 0xa5, 0x42, 0xc4, 0x53, 0xfd, 0x0d, 0xc1, 0x35, 0x49, 0x12, 0xd1, 0x15, 0x07, - 0x2e, 0x45, 0xbb, 0x42, 0x33, 0x68, 0xf1, 0xc2, 0x6a, 0x2a, 0x7f, 0x43, 0x56, 0xc7, 0x7e, 0x99, - 0x38, 0x9e, 0x75, 0x68, 0x91, 0x72, 0x24, 0xd4, 0x5e, 0x36, 0x28, 0xeb, 0x87, 0x17, 0x0b, 0xb3, - 0x52, 0x35, 0x2d, 0xa4, 0x23, 0xbd, 0xa4, 0xf8, 0x83, 0x58, 0x55, 0xc3, 0xac, 0xaa, 0x95, 0xbe, - 0x55, 0x71, 0xb0, 0xb1, 0xb2, 0x9e, 0x22, 0x50, 0x78, 0x59, 0x81, 0xca, 0xa1, 0x3e, 0x4d, 0xbc, - 0x27, 0x78, 0x05, 0xa6, 0x1a, 0xa4, 0x69, 0x51, 0xcb, 0x75, 0x8a, 0x8e, 0x6f, 0x97, 0x48, 0x83, - 0x21, 0x19, 0x29, 0x4c, 0x86, 0xe2, 0xfb, 0x4c, 0x1a, 0x33, 0x8c, 0xcc, 0x39, 0x62, 0xc8, 0x07, - 0x89, 0x97, 0xe1, 0x52, 0x2d, 0xa8, 0xcf, 0x0b, 0xcd, 0x46, 0x16, 0xd1, 0xea, 0x78, 0x21, 0xcd, - 0x85, 0x62, 0xda, 0xcf, 0x10, 0xcc, 0x49, 0x21, 0x8b, 0x59, 0xbc, 0x03, 0x53, 0x66, 0xa8, 0x49, - 0xb0, 0xa4, 0x93, 0x66, 0x2c, 0xcc, 0xeb, 0xdc, 0xd3, 0x13, 0x39, 0x72, 0x9a, 0xa8, 0xdb, 0x77, - 0x24, 0x23, 0xff, 0x37, 0x8b, 0xfc, 0x33, 0x82, 0x79, 0x39, 0x08, 0xd1, 0xbf, 0x2f, 0xe1, 0x72, - 0x47, 0xff, 0xc2, 0x75, 0x5e, 0x97, 0x95, 0x1b, 0x0f, 0xf3, 0x99, 0xe5, 0x55, 0x63, 0x0d, 0x98, - 0x8a, 0xb7, 0xf7, 0x15, 0xae, 0xee, 0x63, 0x04, 0x4b, 0x92, 0x42, 0x78, 0xf6, 0xff, 0xb6, 0xa7, - 0xbf, 0x20, 0x50, 0x5f, 0x06, 0x45, 0x74, 0xf6, 0x73, 0xb8, 0xda, 0xd1, 0x59, 0xb1, 0x4e, 0x61, - 0x83, 0xfb, 0xef, 0xd3, 0x8c, 0x29, 0xcb, 0xf0, 0xea, 0x9a, 0xba, 0xd3, 0x75, 0x95, 0xfa, 0x89, - 0x5a, 0xa9, 0x6e, 0x75, 0x5d, 0x8f, 0x7e, 0xbb, 0xf0, 0x59, 0x18, 0xa3, 0x4c, 0x22, 0xdc, 0xc4, - 0x97, 0xaa, 0xc4, 0xb2, 0x1d, 0x18, 0x0d, 0xc3, 0x0e, 0xb3, 0xa9, 0x1f, 0xc6, 0x02, 0x86, 0x3a, - 0x11, 0x30, 0x0f, 0x63, 0x75, 0x26, 0x11, 0x47, 0x5b, 0xda, 0x38, 0xe1, 0x23, 0x2c, 0xd5, 0x25, - 0x58, 0x60, 0x01, 0x3f, 0xa9, 0x57, 0x1a, 0x46, 0x39, 0x76, 0xbd, 0x86, 0x39, 0x6b, 0xb0, 0xd8, - 0xdb, 0x44, 0xa4, 0xbe, 0x0b, 0x33, 0xbe, 0x50, 0x17, 0x13, 0x33, 0xe1, 0x15, 0xbf, 0x3b, 0xa2, - 0xfa, 0x3f, 0xb1, 0x34, 0xad, 0x6c, 0xb2, 0x2b, 0x58, 0xf5, 0x61, 0xf9, 0xa5, 0x56, 0x02, 0xd6, - 0x7d, 0xc8, 0xb4, 0x61, 0x0d, 0x70, 0xfd, 0xcd, 0xfa, 0xd2, 0xb8, 0xea, 0xb3, 0x61, 0x71, 0x4d, - 0x7c, 0x4a, 0x1a, 0xd6, 0xe1, 0xd1, 0x3d, 0x12, 0xdc, 0xe4, 0xb4, 0x6a, 0xd5, 0x13, 0x1d, 0xac, - 0xd7, 0x77, 0x89, 0xe2, 0x7d, 0x48, 0xd9, 0xa4, 0xf1, 0xa0, 0x46, 0x8a, 0x75, 0xc3, 0xab, 0x32, - 0x86, 0x48, 0xe5, 0xd5, 0x48, 0x8c, 0xf6, 0xab, 0xaa, 0x99, 0xd3, 0xee, 0x31, 0xd3, 0x03, 0xc3, - 0xab, 0x8a, 0x58, 0x60, 0xb7, 0x24, 0x01, 0xca, 0xa6, 0x51, 0xf3, 0x49, 0x66, 0x94, 0xa3, 0x64, - 0x1f, 0xf8, 0x3a, 0x80, 0x67, 0xd9, 0xa4, 0x58, 0x26, 0x35, 0xe3, 0x28, 0x33, 0xc6, 0x88, 0x6a, - 0x22, 0x90, 0xbc, 0x1f, 0x08, 0xf0, 0x02, 0xa4, 0x4a, 0x35, 0xd7, 0x7c, 0x20, 0xf4, 0x17, 0x99, - 0x1e, 0x98, 0x88, 0x19, 0xa8, 0x6f, 0xc3, 0xf5, 0x1e, 0x8d, 0x13, 0xa3, 0xca, 0xc0, 0x45, 0xea, - 0x9b, 0x26, 0xa1, 0x7c, 0x7b, 0xc7, 0x0b, 0xe1, 0x67, 0xfe, 0x64, 0x12, 0x46, 0x99, 0x2f, 0xfe, - 0x0e, 0x41, 0x2a, 0xb2, 0x2b, 0xf8, 0x4d, 0x59, 0x93, 0x7a, 0xbc, 0xee, 0x94, 0xf5, 0x64, 0xc6, - 0x1c, 0x8e, 0x7a, 0xf3, 0xe4, 0xd7, 0xbf, 0xbe, 0x19, 0xd6, 0xf1, 0x86, 0xde, 0xf3, 0x21, 0x2b, - 0x68, 0x40, 0x7f, 0xd4, 0x9a, 0xf8, 0x31, 0xfe, 0x16, 0x41, 0x3a, 0xfa, 0x42, 0xc1, 0x89, 0xb2, - 0x86, 0xc7, 0x5b, 0xd9, 0x48, 0x68, 0x2d, 0x40, 0xde, 0x60, 0x20, 0x97, 0xf1, 0x52, 0x5f, 0x90, - 0xf8, 0x05, 0x82, 0xc9, 0xf8, 0x32, 0x63, 0xad, 0x77, 0x32, 0xd9, 0x99, 0x53, 0xf4, 0xc4, 0xf6, - 0x02, 0x5e, 0x8d, 0xc1, 0x3b, 0xc4, 0x65, 0x29, 0xbc, 0x0e, 0x36, 0x8d, 0xb6, 0x51, 0x0f, 0x5f, - 0x40, 0xfa, 0xa3, 0x8e, 0xb7, 0xd4, 0xb1, 0xce, 0x4f, 0x49, 0x44, 0xc1, 0x05, 0xc7, 0xf8, 0x09, - 0x82, 0xa9, 0x0e, 0xf6, 0xc6, 0x49, 0x21, 0xb7, 0x06, 0xb0, 0x99, 0xdc, 0x41, 0x14, 0xb9, 0xcb, - 0x8a, 0xcc, 0xe3, 0xcd, 0x41, 0x8b, 0xc4, 0xa7, 0x08, 0x66, 0xa4, 0xd4, 0x88, 0x6f, 0x26, 0x44, - 0x11, 0x67, 0x75, 0x65, 0x7b, 0x50, 0x37, 0x51, 0xc2, 0xbb, 0xac, 0x84, 0x5b, 0x78, 0x77, 0xe0, - 0x39, 0x09, 0xa2, 0xc6, 0xdf, 0xc7, 0xd6, 0xde, 0x4f, 0xb6, 0xf6, 0xfe, 0x40, 0x6b, 0xdf, 0x26, - 0xce, 0xc4, 0x67, 0xd3, 0x8f, 0xf7, 0xfb, 0xab, 0x16, 0x48, 0xce, 0x81, 0x7d, 0x41, 0xc6, 0xa8, - 0xb7, 0x2f, 0xc8, 0x38, 0x19, 0xab, 0x2a, 0x03, 0x39, 0x8f, 0x15, 0x19, 0x48, 0x4e, 0xbe, 0xf8, - 0x47, 0x04, 0x57, 0x24, 0xac, 0x8a, 0xb7, 0x7a, 0xa6, 0xea, 0x4d, 0xd3, 0xca, 0x5b, 0x83, 0x39, - 0x09, 0x98, 0x79, 0x06, 0x73, 0x1d, 0xaf, 0xc9, 0x60, 0x4a, 0x29, 0x9d, 0xe2, 0x9f, 0x10, 0xcc, - 0xca, 0x89, 0x17, 0x6f, 0xf7, 0x07, 0x21, 0xbd, 0x5b, 0x76, 0x06, 0xf6, 0x4b, 0xb2, 0x0b, 0xbd, - 0xb8, 0x9f, 0x06, 0x97, 0xc5, 0xe5, 0x4e, 0x2a, 0xc2, 0xbd, 0x0f, 0x7f, 0x0f, 0xba, 0x57, 0x72, - 0x03, 0x78, 0x84, 0x80, 0x1f, 0xff, 0xfd, 0x74, 0x0d, 0x31, 0xd4, 0x6b, 0xb7, 0xd0, 0x9a, 0xfa, - 0x7f, 0x19, 0xf0, 0x26, 0xf3, 0x2e, 0xda, 0x2d, 0xf7, 0xbd, 0xc2, 0xe9, 0x59, 0x16, 0x3d, 0x3f, - 0xcb, 0xa2, 0x3f, 0xcf, 0xb2, 0xe8, 0xeb, 0xf3, 0xec, 0xd0, 0xf3, 0xf3, 0xec, 0xd0, 0xef, 0xe7, - 0xd9, 0xa1, 0x2f, 0x76, 0x2b, 0x96, 0x57, 0xf5, 0x4b, 0x01, 0xc5, 0xeb, 0xe2, 0x1f, 0x19, 0xab, - 0x64, 0x6e, 0x54, 0x5c, 0xbd, 0xb9, 0xab, 0xdb, 0x6e, 0xd9, 0xaf, 0x11, 0xca, 0xe3, 0x6f, 0xe6, - 0x37, 0x44, 0x0a, 0xef, 0xa8, 0x4e, 0x68, 0x69, 0x8c, 0xbd, 0x79, 0xb6, 0xfe, 0x09, 0x00, 0x00, - 0xff, 0xff, 0x78, 0xef, 0x8a, 0x42, 0x29, 0x12, 0x00, 0x00, + // 1249 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcb, 0x6f, 0x1b, 0x45, + 0x18, 0xcf, 0xa4, 0x49, 0x9a, 0x7c, 0x76, 0x93, 0x68, 0x9a, 0xa4, 0xee, 0x26, 0x75, 0x92, 0x0d, + 0x90, 0x34, 0x24, 0xbb, 0x89, 0x43, 0x93, 0x50, 0x09, 0x09, 0x52, 0x54, 0x1a, 0xa4, 0x96, 0x60, + 0xc4, 0x43, 0x48, 0xc8, 0x5a, 0xaf, 0x27, 0xf6, 0xaa, 0xde, 0x5d, 0xd7, 0xb3, 0x6b, 0x29, 0xaa, + 0x72, 0xc9, 0xa9, 0x37, 0x90, 0x90, 0xb8, 0x22, 0x71, 0xe4, 0x50, 0xf5, 0x80, 0xc4, 0x09, 0x89, + 0x13, 0xe4, 0x58, 0x09, 0x0e, 0x9c, 0x28, 0x4a, 0x90, 0xf8, 0x37, 0xd0, 0xce, 0xcc, 0xda, 0xbb, + 0xf6, 0xb8, 0x5e, 0xa3, 0x96, 0x9b, 0xf7, 0x7b, 0xfe, 0xbe, 0xc7, 0xcc, 0x6f, 0x64, 0xc8, 0x5a, + 0x45, 0x53, 0x37, 0xdd, 0x3a, 0xd1, 0xcd, 0xaa, 0x45, 0x1c, 0x4f, 0x6f, 0x6c, 0xea, 0x0f, 0x7c, + 0x52, 0x3f, 0xd2, 0x6a, 0x75, 0xd7, 0x73, 0x31, 0xb6, 0x8a, 0xa6, 0x16, 0xe8, 0x35, 0xae, 0xd7, + 0x1a, 0x9b, 0xca, 0xaa, 0xe9, 0x52, 0xdb, 0xa5, 0x7a, 0xd1, 0xa0, 0x84, 0x1b, 0xeb, 0x8d, 0xcd, + 0x22, 0xf1, 0x8c, 0x4d, 0xbd, 0x66, 0x94, 0x2d, 0xc7, 0xf0, 0x2c, 0xd7, 0xe1, 0xfe, 0xca, 0xac, + 0xb0, 0x0d, 0xcd, 0xa2, 0xc1, 0x95, 0x79, 0x49, 0x72, 0x91, 0x86, 0x1b, 0x2c, 0xb7, 0x0c, 0x5c, + 0xdb, 0xb6, 0x3c, 0x9b, 0x19, 0xe5, 0x22, 0x5f, 0xc2, 0xf0, 0x6a, 0xd9, 0x75, 0xcb, 0x55, 0xa2, + 0xb3, 0xaf, 0xa2, 0x7f, 0xa8, 0x1b, 0x4e, 0x98, 0x64, 0x4e, 0xa8, 0x8c, 0x9a, 0xa5, 0x1b, 0x8e, + 0xe3, 0x7a, 0x0c, 0x1e, 0x15, 0xda, 0xa9, 0xb2, 0x5b, 0x76, 0xd9, 0x4f, 0x3d, 0xf8, 0xc5, 0xa5, + 0xea, 0x36, 0x5c, 0xf9, 0x30, 0xc0, 0x79, 0x8b, 0x81, 0xf9, 0xc8, 0x33, 0x3c, 0x92, 0x27, 0x0f, + 0x7c, 0x42, 0x3d, 0x3c, 0x0b, 0x63, 0x1c, 0x62, 0xc1, 0x2a, 0x65, 0xd0, 0x02, 0x5a, 0x19, 0xcb, + 0x8f, 0x72, 0xc1, 0x7e, 0x49, 0x7d, 0x8c, 0x20, 0xd3, 0xe9, 0x48, 0x6b, 0xae, 0x43, 0x09, 0xde, + 0x81, 0xb4, 0xf0, 0xa4, 0x81, 0x9c, 0x39, 0xa7, 0x72, 0x53, 0x1a, 0xc7, 0xa7, 0x85, 0xd0, 0xb5, + 0x77, 0x9c, 0xa3, 0x7c, 0xca, 0x6c, 0x05, 0xc0, 0x53, 0x30, 0x5c, 0xab, 0xbb, 0xee, 0x61, 0x66, + 0x70, 0x01, 0xad, 0xa4, 0xf3, 0xfc, 0x03, 0xdf, 0x82, 0x34, 0xfb, 0x51, 0xa8, 0x10, 0xab, 0x5c, + 0xf1, 0x32, 0x17, 0x58, 0x38, 0x45, 0xeb, 0x1c, 0x98, 0x76, 0x87, 0x59, 0xec, 0x0d, 0x9d, 0xfe, + 0x39, 0x3f, 0x90, 0x4f, 0x31, 0x2f, 0x2e, 0x52, 0x8b, 0x9d, 0x78, 0x69, 0x58, 0xe9, 0x6d, 0x80, + 0xd6, 0x38, 0x05, 0xda, 0xd7, 0x34, 0x3e, 0x4f, 0x2d, 0x98, 0xbd, 0xc6, 0x67, 0x29, 0x66, 0xaf, + 0x1d, 0x18, 0xe5, 0xb0, 0x4b, 0xf9, 0x88, 0xa7, 0xfa, 0x3b, 0x82, 0xab, 0x92, 0x24, 0xa2, 0x2b, + 0x0e, 0x5c, 0x8a, 0x76, 0x85, 0x66, 0xd0, 0xc2, 0x85, 0x95, 0x54, 0xee, 0xba, 0xac, 0x8e, 0xfd, + 0x12, 0x71, 0x3c, 0xeb, 0xd0, 0x22, 0xa5, 0x48, 0xa8, 0xbd, 0x6c, 0x50, 0xd6, 0xf7, 0xcf, 0xe6, + 0x67, 0xa4, 0x6a, 0x9a, 0x4f, 0x47, 0x7a, 0x49, 0xf1, 0x7b, 0xb1, 0xaa, 0x06, 0x59, 0x55, 0xcb, + 0x3d, 0xab, 0xe2, 0x60, 0x63, 0x65, 0x3d, 0x41, 0xa0, 0xf0, 0xb2, 0x02, 0x95, 0x43, 0x7d, 0x9a, + 0x78, 0x4f, 0xf0, 0x32, 0x4c, 0xd4, 0x49, 0xc3, 0xa2, 0x96, 0xeb, 0x14, 0x1c, 0xdf, 0x2e, 0x92, + 0x3a, 0x43, 0x32, 0x94, 0x1f, 0x0f, 0xc5, 0xf7, 0x98, 0x34, 0x66, 0x18, 0x99, 0x73, 0xc4, 0x90, + 0x0f, 0x12, 0x2f, 0xc1, 0xa5, 0x6a, 0x50, 0x9f, 0x17, 0x9a, 0x0d, 0x2d, 0xa0, 0x95, 0xd1, 0x7c, + 0x9a, 0x0b, 0xc5, 0xb4, 0x7f, 0x44, 0x30, 0x2b, 0x85, 0x2c, 0x66, 0xf1, 0x16, 0x4c, 0x98, 0xa1, + 0x26, 0xc1, 0x92, 0x8e, 0x9b, 0xb1, 0x30, 0x2f, 0x73, 0x4f, 0x4f, 0xe4, 0xc8, 0x69, 0xa2, 0x6e, + 0xdf, 0x96, 0x8c, 0xfc, 0xbf, 0x2c, 0xf2, 0x2f, 0x08, 0xe6, 0xe4, 0x20, 0x44, 0xff, 0xbe, 0x80, + 0xc9, 0xb6, 0xfe, 0x85, 0xeb, 0xbc, 0x26, 0x2b, 0x37, 0x1e, 0xe6, 0x53, 0xcb, 0xab, 0xc4, 0x1a, + 0x30, 0x11, 0x6f, 0xef, 0x0b, 0x5c, 0xdd, 0x47, 0x08, 0x16, 0x25, 0x85, 0xf0, 0xec, 0xff, 0x6f, + 0x4f, 0x7f, 0x45, 0xa0, 0x3e, 0x0f, 0x8a, 0xe8, 0xec, 0x67, 0x70, 0xa5, 0xad, 0xb3, 0x62, 0x9d, + 0xc2, 0x06, 0xf7, 0xde, 0xa7, 0x69, 0x53, 0x96, 0xe1, 0xc5, 0x35, 0x75, 0xa7, 0xe3, 0x2a, 0xf5, + 0x13, 0xb5, 0x52, 0xdd, 0xea, 0xb8, 0x1e, 0xfd, 0x56, 0xe1, 0x33, 0x30, 0x42, 0x99, 0x44, 0xb8, + 0x89, 0x2f, 0x55, 0x89, 0x65, 0x3b, 0x30, 0xea, 0x86, 0x1d, 0x66, 0x53, 0x3f, 0x88, 0x05, 0x0c, + 0x75, 0x22, 0x60, 0x0e, 0x46, 0x6a, 0x4c, 0x22, 0x8e, 0xb6, 0xb4, 0x71, 0xc2, 0x47, 0x58, 0xaa, + 0x8b, 0x30, 0xcf, 0x02, 0x7e, 0x5c, 0x2b, 0xd7, 0x8d, 0x52, 0xec, 0x7a, 0x0d, 0x73, 0x56, 0x61, + 0xa1, 0xbb, 0x89, 0x48, 0x7d, 0x07, 0xa6, 0x7d, 0xa1, 0x2e, 0x24, 0x66, 0xc2, 0xcb, 0x7e, 0x67, + 0x44, 0xf5, 0x15, 0xb1, 0x34, 0xcd, 0x6c, 0xb2, 0x2b, 0x58, 0xf5, 0x61, 0xe9, 0xb9, 0x56, 0x02, + 0xd6, 0x3d, 0xc8, 0xb4, 0x60, 0xf5, 0x71, 0xfd, 0xcd, 0xf8, 0xd2, 0xb8, 0xea, 0x4f, 0x83, 0xe2, + 0x9a, 0xf8, 0x84, 0xd4, 0xad, 0xc3, 0xa3, 0xbb, 0x24, 0xb8, 0xc9, 0x69, 0xc5, 0xaa, 0x25, 0x3a, + 0x58, 0x2f, 0xef, 0x12, 0x0d, 0x42, 0x37, 0x8c, 0xaa, 0x4f, 0x32, 0xc3, 0x3c, 0x34, 0xfb, 0xc0, + 0xd7, 0x00, 0x3c, 0xcb, 0x26, 0x85, 0x12, 0xa9, 0x1a, 0x47, 0x99, 0x11, 0xc6, 0x2e, 0x63, 0x81, + 0xe4, 0xdd, 0x40, 0x80, 0xe7, 0x21, 0x55, 0xac, 0xba, 0xe6, 0x7d, 0xa1, 0xbf, 0xc8, 0xf4, 0xc0, + 0x44, 0xdc, 0x60, 0x1f, 0x52, 0x36, 0xa9, 0xdf, 0xaf, 0x92, 0x42, 0xcd, 0xf0, 0x2a, 0x99, 0x51, + 0x86, 0x4c, 0x8d, 0x20, 0x6b, 0xbd, 0xd5, 0x1a, 0x39, 0xed, 0x2e, 0x33, 0x3d, 0x30, 0xbc, 0x8a, + 0x40, 0x08, 0x76, 0x53, 0xf2, 0xfe, 0xd0, 0xe8, 0xd0, 0xe4, 0xb0, 0xfa, 0x26, 0x5c, 0xeb, 0xd2, + 0x3e, 0x31, 0xb0, 0x0c, 0x5c, 0xa4, 0xbe, 0x69, 0x12, 0xca, 0x77, 0x78, 0x34, 0x1f, 0x7e, 0xe6, + 0x4e, 0xc6, 0x61, 0x98, 0xf9, 0xe2, 0x6f, 0x11, 0xa4, 0x22, 0x1b, 0x83, 0x5f, 0x97, 0xb5, 0xaa, + 0xcb, 0x1b, 0x4f, 0x59, 0x4b, 0x66, 0xcc, 0xe1, 0xa8, 0x37, 0x4e, 0x7e, 0xfb, 0xfb, 0xeb, 0x41, + 0x1d, 0xaf, 0xeb, 0x5d, 0x9f, 0xb3, 0x82, 0x0c, 0xf4, 0x87, 0xcd, 0xb9, 0x1f, 0xe3, 0x6f, 0x10, + 0xa4, 0xa3, 0xef, 0x14, 0x9c, 0x28, 0x6b, 0x78, 0xc8, 0x95, 0xf5, 0x84, 0xd6, 0x02, 0xe4, 0x75, + 0x06, 0x72, 0x09, 0x2f, 0xf6, 0x04, 0x89, 0x9f, 0x21, 0x18, 0x8f, 0xaf, 0x34, 0xd6, 0xba, 0x27, + 0x93, 0x9d, 0x3c, 0x45, 0x4f, 0x6c, 0x2f, 0xe0, 0x55, 0x19, 0xbc, 0x43, 0x5c, 0x92, 0xc2, 0x6b, + 0xe3, 0xd4, 0x68, 0x1b, 0xf5, 0xf0, 0x1d, 0xa4, 0x3f, 0x6c, 0x7b, 0x51, 0x1d, 0xeb, 0xfc, 0xac, + 0x44, 0x14, 0x5c, 0x70, 0x8c, 0x1f, 0x23, 0x98, 0x68, 0xe3, 0x70, 0x9c, 0x14, 0x72, 0x73, 0x00, + 0x1b, 0xc9, 0x1d, 0x44, 0x91, 0xbb, 0xac, 0xc8, 0x1c, 0xde, 0xe8, 0xb7, 0x48, 0x7c, 0x8a, 0x60, + 0x5a, 0x4a, 0x90, 0xf8, 0x46, 0x42, 0x14, 0x71, 0x6e, 0x57, 0xb6, 0xfb, 0x75, 0x13, 0x25, 0xbc, + 0xcd, 0x4a, 0xb8, 0x89, 0x77, 0xfb, 0x9e, 0x93, 0xa0, 0x6b, 0xfc, 0x5d, 0x6c, 0xed, 0xfd, 0x64, + 0x6b, 0xef, 0xf7, 0xb5, 0xf6, 0x2d, 0xfa, 0x4c, 0x7c, 0x36, 0xfd, 0x78, 0xbf, 0xbf, 0x6c, 0x82, + 0xe4, 0x4c, 0xd8, 0x13, 0x64, 0x8c, 0x80, 0x7b, 0x82, 0x8c, 0x53, 0xb2, 0xaa, 0x32, 0x90, 0x73, + 0x58, 0x91, 0x81, 0xe4, 0x14, 0x8c, 0x7f, 0x40, 0x70, 0x59, 0xc2, 0xad, 0x78, 0xab, 0x6b, 0xaa, + 0xee, 0x64, 0xad, 0xbc, 0xd1, 0x9f, 0x93, 0x80, 0x99, 0x63, 0x30, 0xd7, 0xf0, 0xaa, 0x0c, 0xa6, + 0x94, 0xd8, 0x29, 0xfe, 0x19, 0xc1, 0x8c, 0x9c, 0x7e, 0xf1, 0x76, 0x6f, 0x10, 0xd2, 0xbb, 0x65, + 0xa7, 0x6f, 0xbf, 0x24, 0xbb, 0xd0, 0xed, 0x05, 0x40, 0x83, 0xcb, 0x62, 0xb2, 0x9d, 0x8a, 0x70, + 0xf7, 0xc3, 0xdf, 0x85, 0xf4, 0x95, 0xcd, 0x3e, 0x3c, 0x42, 0xc0, 0x8f, 0xfe, 0x79, 0xb2, 0x8a, + 0x18, 0xea, 0xd5, 0x9b, 0x68, 0x55, 0x7d, 0x55, 0x06, 0xbc, 0xc1, 0xbc, 0x0b, 0x76, 0xd3, 0x7d, + 0x2f, 0x7f, 0x7a, 0x96, 0x45, 0x4f, 0xcf, 0xb2, 0xe8, 0xaf, 0xb3, 0x2c, 0xfa, 0xea, 0x3c, 0x3b, + 0xf0, 0xf4, 0x3c, 0x3b, 0xf0, 0xc7, 0x79, 0x76, 0xe0, 0xf3, 0xdd, 0xb2, 0xe5, 0x55, 0xfc, 0x62, + 0x40, 0xc9, 0xba, 0xf8, 0x5f, 0xc6, 0x2a, 0x9a, 0xeb, 0x65, 0x57, 0x6f, 0xec, 0xea, 0xb6, 0x5b, + 0xf2, 0xab, 0x84, 0xf2, 0xf8, 0x1b, 0xb9, 0x75, 0x91, 0xc2, 0x3b, 0xaa, 0x11, 0x5a, 0x1c, 0x61, + 0x2f, 0x9f, 0xad, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x99, 0xfd, 0xd9, 0x60, 0x2f, 0x12, 0x00, + 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -2346,6 +2347,16 @@ func (m *QueryVerifyMembershipRequest) MarshalToSizedBuffer(dAtA []byte) (int, e _ = i var l int _ = l + { + size, err := m.MerklePath.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 if m.BlockDelay != 0 { i = encodeVarintQuery(dAtA, i, uint64(m.BlockDelay)) i-- @@ -2363,16 +2374,6 @@ func (m *QueryVerifyMembershipRequest) MarshalToSizedBuffer(dAtA []byte) (int, e i-- dAtA[i] = 0x2a } - { - size, err := m.MerklePath.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 { size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -2729,8 +2730,6 @@ func (m *QueryVerifyMembershipRequest) Size() (n int) { } l = m.ProofHeight.Size() n += 1 + l + sovQuery(uint64(l)) - l = m.MerklePath.Size() - n += 1 + l + sovQuery(uint64(l)) l = len(m.Value) if l > 0 { n += 1 + l + sovQuery(uint64(l)) @@ -2741,6 +2740,8 @@ func (m *QueryVerifyMembershipRequest) Size() (n int) { if m.BlockDelay != 0 { n += 1 + sovQuery(uint64(m.BlockDelay)) } + l = m.MerklePath.Size() + n += 1 + l + sovQuery(uint64(l)) return n } @@ -4672,39 +4673,6 @@ func (m *QueryVerifyMembershipRequest) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MerklePath", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.MerklePath.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) @@ -4777,6 +4745,39 @@ func (m *QueryVerifyMembershipRequest) Unmarshal(dAtA []byte) error { break } } + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MerklePath", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MerklePath.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) diff --git a/modules/core/03-connection/keeper/verify.go b/modules/core/03-connection/keeper/verify.go index c1cf804f91e..31968c304c4 100644 --- a/modules/core/03-connection/keeper/verify.go +++ b/modules/core/03-connection/keeper/verify.go @@ -34,7 +34,7 @@ func (k *Keeper) VerifyClientState( return errorsmod.Wrap(clienttypes.ErrRouteNotFound, clientID) } - merklePath := commitmenttypes.NewMerklePath(host.FullClientStatePath(connection.Counterparty.ClientId)) + merklePath := commitmenttypes.NewMerklePath(host.FullClientStateKey(connection.Counterparty.ClientId)) merklePath, err := commitmenttypes.ApplyPrefix(connection.Counterparty.Prefix, merklePath) if err != nil { return err @@ -76,7 +76,7 @@ func (k *Keeper) VerifyClientConsensusState( return errorsmod.Wrap(clienttypes.ErrRouteNotFound, clientID) } - merklePath := commitmenttypes.NewMerklePath(host.FullConsensusStatePath(connection.Counterparty.ClientId, consensusHeight)) + merklePath := commitmenttypes.NewMerklePath(host.FullConsensusStateKey(connection.Counterparty.ClientId, consensusHeight)) merklePath, err := commitmenttypes.ApplyPrefix(connection.Counterparty.Prefix, merklePath) if err != nil { return err @@ -118,7 +118,7 @@ func (k *Keeper) VerifyConnectionState( return errorsmod.Wrap(clienttypes.ErrRouteNotFound, clientID) } - merklePath := commitmenttypes.NewMerklePath(host.ConnectionPath(connectionID)) + merklePath := commitmenttypes.NewMerklePath(host.ConnectionKey(connectionID)) merklePath, err := commitmenttypes.ApplyPrefix(connection.Counterparty.Prefix, merklePath) if err != nil { return err @@ -161,7 +161,7 @@ func (k *Keeper) VerifyChannelState( return errorsmod.Wrap(clienttypes.ErrRouteNotFound, clientID) } - merklePath := commitmenttypes.NewMerklePath(host.ChannelPath(portID, channelID)) + merklePath := commitmenttypes.NewMerklePath(host.ChannelKey(portID, channelID)) merklePath, err := commitmenttypes.ApplyPrefix(connection.Counterparty.Prefix, merklePath) if err != nil { return err @@ -209,7 +209,7 @@ func (k *Keeper) VerifyPacketCommitment( timeDelay := connection.DelayPeriod blockDelay := k.getBlockDelay(ctx, connection) - merklePath := commitmenttypes.NewMerklePath(host.PacketCommitmentPath(portID, channelID, sequence)) + merklePath := commitmenttypes.NewMerklePath(host.PacketCommitmentKey(portID, channelID, sequence)) merklePath, err := commitmenttypes.ApplyPrefix(connection.Counterparty.Prefix, merklePath) if err != nil { return err @@ -250,7 +250,7 @@ func (k *Keeper) VerifyPacketAcknowledgement( timeDelay := connection.DelayPeriod blockDelay := k.getBlockDelay(ctx, connection) - merklePath := commitmenttypes.NewMerklePath(host.PacketAcknowledgementPath(portID, channelID, sequence)) + merklePath := commitmenttypes.NewMerklePath(host.PacketAcknowledgementKey(portID, channelID, sequence)) merklePath, err := commitmenttypes.ApplyPrefix(connection.Counterparty.Prefix, merklePath) if err != nil { return err @@ -297,7 +297,7 @@ func (k *Keeper) VerifyPacketReceiptAbsence( timeDelay := connection.DelayPeriod blockDelay := k.getBlockDelay(ctx, connection) - merklePath := commitmenttypes.NewMerklePath(host.PacketReceiptPath(portID, channelID, sequence)) + merklePath := commitmenttypes.NewMerklePath(host.PacketReceiptKey(portID, channelID, sequence)) merklePath, err = commitmenttypes.ApplyPrefix(connection.Counterparty.Prefix, merklePath) if err != nil { return err @@ -337,7 +337,7 @@ func (k *Keeper) VerifyNextSequenceRecv( timeDelay := connection.DelayPeriod blockDelay := k.getBlockDelay(ctx, connection) - merklePath := commitmenttypes.NewMerklePath(host.NextSequenceRecvPath(portID, channelID)) + merklePath := commitmenttypes.NewMerklePath(host.NextSequenceRecvKey(portID, channelID)) merklePath, err := commitmenttypes.ApplyPrefix(connection.Counterparty.Prefix, merklePath) if err != nil { return err @@ -374,7 +374,7 @@ func (k *Keeper) VerifyChannelUpgradeError( return errorsmod.Wrap(clienttypes.ErrRouteNotFound, clientID) } - merklePath := commitmenttypes.NewMerklePath(host.ChannelUpgradeErrorPath(portID, channelID)) + merklePath := commitmenttypes.NewMerklePath(host.ChannelUpgradeErrorKey(portID, channelID)) merklePath, err := commitmenttypes.ApplyPrefix(connection.Counterparty.Prefix, merklePath) if err != nil { return err @@ -416,7 +416,7 @@ func (k *Keeper) VerifyChannelUpgrade( return errorsmod.Wrap(clienttypes.ErrRouteNotFound, clientID) } - merklePath := commitmenttypes.NewMerklePath(host.ChannelUpgradePath(portID, channelID)) + merklePath := commitmenttypes.NewMerklePath(host.ChannelUpgradeKey(portID, channelID)) merklePath, err := commitmenttypes.ApplyPrefix(connection.Counterparty.Prefix, merklePath) if err != nil { return err diff --git a/modules/core/23-commitment/types/commitment.pb.go b/modules/core/23-commitment/types/commitment.pb.go index b517747e01e..bf95874a8ac 100644 --- a/modules/core/23-commitment/types/commitment.pb.go +++ b/modules/core/23-commitment/types/commitment.pb.go @@ -114,7 +114,7 @@ func (m *MerklePrefix) GetKeyPrefix() []byte { // arbitrary structured object (defined by a commitment type). // MerklePath is represented from root-to-leaf type MerklePath struct { - KeyPath [][]byte `protobuf:"bytes,1,rep,name=key_path,json=keyPath,proto3" json:"key_path,omitempty"` + KeyPath []string `protobuf:"bytes,1,rep,name=key_path,json=keyPath,proto3" json:"key_path,omitempty"` } func (m *MerklePath) Reset() { *m = MerklePath{} } @@ -150,7 +150,7 @@ func (m *MerklePath) XXX_DiscardUnknown() { var xxx_messageInfo_MerklePath proto.InternalMessageInfo -func (m *MerklePath) GetKeyPath() [][]byte { +func (m *MerklePath) GetKeyPath() []string { if m != nil { return m.KeyPath } @@ -218,27 +218,27 @@ func init() { } var fileDescriptor_7921d88972a41469 = []byte{ - // 310 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x90, 0x31, 0x4e, 0xc3, 0x30, - 0x14, 0x86, 0x13, 0x51, 0x15, 0x70, 0x3b, 0x59, 0x08, 0x41, 0x05, 0xa6, 0xca, 0x40, 0xbb, 0xd4, - 0x56, 0xdb, 0xa5, 0x42, 0x4c, 0x30, 0x30, 0x21, 0x55, 0x19, 0x18, 0x58, 0x50, 0x62, 0xdc, 0xc4, - 0x6a, 0xc3, 0x8b, 0x62, 0x37, 0xa2, 0x37, 0x60, 0xe4, 0x08, 0x1c, 0x87, 0xb1, 0x23, 0x23, 0x6a, - 0x2e, 0x82, 0x6c, 0x37, 0x28, 0xdb, 0x7b, 0x7a, 0x9f, 0x7f, 0xfd, 0xfe, 0xd0, 0x40, 0xc6, 0x9c, - 0x71, 0x28, 0x04, 0xe3, 0x90, 0x65, 0x52, 0x67, 0xe2, 0x4d, 0xb3, 0x72, 0xdc, 0xd8, 0x68, 0x5e, - 0x80, 0x06, 0x7c, 0x2a, 0x63, 0x4e, 0x0d, 0x48, 0x1b, 0xa7, 0x72, 0xdc, 0x3b, 0x49, 0x20, 0x01, - 0x8b, 0x30, 0x33, 0x39, 0xba, 0x77, 0xc1, 0x41, 0x65, 0xa0, 0x98, 0xe4, 0x6a, 0x32, 0x35, 0x79, - 0x79, 0x01, 0xb0, 0x50, 0xee, 0x1a, 0x5c, 0x23, 0xf4, 0x28, 0x8a, 0xe5, 0x4a, 0x84, 0x00, 0x1a, - 0x63, 0xd4, 0x4a, 0x23, 0x95, 0x9e, 0xf9, 0x7d, 0x7f, 0xd8, 0x0d, 0xed, 0x7c, 0xd3, 0xfa, 0xf8, - 0xba, 0xf2, 0x82, 0x11, 0xea, 0x3a, 0x6e, 0x5e, 0x88, 0x85, 0x7c, 0xc7, 0x97, 0x08, 0x2d, 0xc5, - 0xe6, 0x25, 0xb7, 0xdb, 0x9e, 0x3f, 0x5e, 0x8a, 0x8d, 0x3b, 0x07, 0x83, 0x3a, 0x76, 0x1e, 0xe9, - 0x14, 0x9f, 0xa3, 0x23, 0x0b, 0x47, 0xda, 0x44, 0x1f, 0x0c, 0xbb, 0xe1, 0xa1, 0x41, 0x23, 0x9d, - 0x06, 0x0f, 0xa8, 0x53, 0xe7, 0x02, 0x2c, 0xf0, 0x0c, 0xb5, 0x5d, 0x3d, 0xcb, 0x75, 0x26, 0x7d, - 0xea, 0xda, 0x53, 0xdb, 0x9e, 0x96, 0x63, 0x7a, 0xff, 0xff, 0x65, 0xfb, 0x22, 0xdc, 0xf3, 0x77, - 0x4f, 0xdf, 0x3b, 0xe2, 0x6f, 0x77, 0xc4, 0xff, 0xdd, 0x11, 0xff, 0xb3, 0x22, 0xde, 0xb6, 0x22, - 0xde, 0x4f, 0x45, 0xbc, 0xe7, 0xdb, 0x44, 0xea, 0x74, 0x1d, 0x1b, 0x59, 0xac, 0x76, 0x11, 0xf3, - 0x51, 0x02, 0xac, 0x9c, 0xb1, 0x0c, 0x5e, 0xd7, 0x2b, 0xa1, 0x9c, 0xf7, 0xc9, 0x74, 0xd4, 0x50, - 0xaf, 0x37, 0xb9, 0x50, 0x71, 0xdb, 0x7a, 0x9a, 0xfe, 0x05, 0x00, 0x00, 0xff, 0xff, 0x0c, 0xb3, - 0xc0, 0xc0, 0x9e, 0x01, 0x00, 0x00, + // 312 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x90, 0xb1, 0x4e, 0xeb, 0x30, + 0x14, 0x86, 0x13, 0xdd, 0xaa, 0x97, 0xba, 0x9d, 0x2c, 0x84, 0xa0, 0x02, 0x53, 0x65, 0xa0, 0x5d, + 0x6a, 0xab, 0xed, 0x52, 0x21, 0x26, 0x18, 0x98, 0x90, 0xaa, 0x0c, 0x0c, 0x2c, 0x28, 0x31, 0x6e, + 0x62, 0xb5, 0xe1, 0x44, 0xb1, 0x1b, 0xd1, 0x37, 0x60, 0xe4, 0x11, 0x78, 0x1c, 0xc6, 0x8e, 0x8c, + 0xa8, 0x79, 0x11, 0x64, 0xbb, 0x41, 0xd9, 0xce, 0xd1, 0xf9, 0xfc, 0xeb, 0xf7, 0x87, 0x86, 0x32, + 0xe6, 0x8c, 0x43, 0x21, 0x18, 0x87, 0x2c, 0x93, 0x3a, 0x13, 0xaf, 0x9a, 0x95, 0x93, 0xc6, 0x46, + 0xf3, 0x02, 0x34, 0xe0, 0x13, 0x19, 0x73, 0x6a, 0x40, 0xda, 0x38, 0x95, 0x93, 0xfe, 0x71, 0x02, + 0x09, 0x58, 0x84, 0x99, 0xc9, 0xd1, 0xfd, 0x73, 0x0e, 0x2a, 0x03, 0xc5, 0x24, 0x57, 0xd3, 0x99, + 0xc9, 0xcb, 0x0b, 0x80, 0xa5, 0x72, 0xd7, 0xe0, 0x0a, 0xa1, 0x07, 0x51, 0xac, 0xd6, 0x22, 0x04, + 0xd0, 0x18, 0xa3, 0x56, 0x1a, 0xa9, 0xf4, 0xd4, 0x1f, 0xf8, 0xa3, 0x5e, 0x68, 0xe7, 0xeb, 0xd6, + 0xfb, 0xe7, 0xa5, 0x17, 0x8c, 0x51, 0xcf, 0x71, 0x8b, 0x42, 0x2c, 0xe5, 0x1b, 0xbe, 0x40, 0x68, + 0x25, 0xb6, 0xcf, 0xb9, 0xdd, 0x0e, 0x7c, 0x67, 0x25, 0xb6, 0xee, 0x1c, 0x0c, 0xeb, 0xd8, 0x45, + 0xa4, 0x53, 0x7c, 0x86, 0x8e, 0x2c, 0x1c, 0x69, 0x13, 0xfd, 0x6f, 0xd4, 0x09, 0xff, 0x1b, 0x34, + 0xd2, 0x69, 0x70, 0x8f, 0xba, 0x75, 0x2e, 0xc0, 0x12, 0xcf, 0x51, 0xdb, 0xd5, 0xb3, 0x5c, 0x77, + 0x3a, 0xa0, 0xae, 0x3d, 0xb5, 0xed, 0x69, 0x39, 0xa1, 0x77, 0x7f, 0x5f, 0xb6, 0x2f, 0xc2, 0x03, + 0x7f, 0xfb, 0xf8, 0xb5, 0x27, 0xfe, 0x6e, 0x4f, 0xfc, 0x9f, 0x3d, 0xf1, 0x3f, 0x2a, 0xe2, 0xed, + 0x2a, 0xe2, 0x7d, 0x57, 0xc4, 0x7b, 0xba, 0x49, 0xa4, 0x4e, 0x37, 0xb1, 0x91, 0xc5, 0x6a, 0x17, + 0x31, 0x1f, 0x27, 0xc0, 0xca, 0x39, 0xcb, 0xe0, 0x65, 0xb3, 0x16, 0xca, 0x79, 0x9f, 0xce, 0xc6, + 0x0d, 0xf5, 0x7a, 0x9b, 0x0b, 0x15, 0xb7, 0xad, 0xa7, 0xd9, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x55, 0x02, 0x17, 0xe1, 0x9e, 0x01, 0x00, 0x00, } func (m *MerkleRoot) Marshal() (dAtA []byte, err error) { @@ -414,8 +414,8 @@ func (m *MerklePath) Size() (n int) { var l int _ = l if len(m.KeyPath) > 0 { - for _, b := range m.KeyPath { - l = len(b) + for _, s := range m.KeyPath { + l = len(s) n += 1 + l + sovCommitment(uint64(l)) } } @@ -644,7 +644,7 @@ func (m *MerklePath) Unmarshal(dAtA []byte) error { if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field KeyPath", wireType) } - var byteLen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowCommitment @@ -654,23 +654,23 @@ func (m *MerklePath) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - byteLen |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - if byteLen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthCommitment } - postIndex := iNdEx + byteLen + postIndex := iNdEx + intStringLen if postIndex < 0 { return ErrInvalidLengthCommitment } if postIndex > l { return io.ErrUnexpectedEOF } - m.KeyPath = append(m.KeyPath, make([]byte, postIndex-iNdEx)) - copy(m.KeyPath[len(m.KeyPath)-1], dAtA[iNdEx:postIndex]) + m.KeyPath = append(m.KeyPath, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex default: iNdEx = preIndex diff --git a/modules/core/23-commitment/types/merkle.go b/modules/core/23-commitment/types/merkle.go index 9e28936bbd9..52c6c1775e6 100644 --- a/modules/core/23-commitment/types/merkle.go +++ b/modules/core/23-commitment/types/merkle.go @@ -11,6 +11,7 @@ import ( cmtcrypto "github.com/cometbft/cometbft/proto/tendermint/crypto" + "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types/v2" "github.com/cosmos/ibc-go/v8/modules/core/exported" ) @@ -69,39 +70,33 @@ func (mp MerklePrefix) Empty() bool { var _ exported.Path = (*MerklePath)(nil) // NewMerklePath creates a new MerklePath instance -// The keys must be passed in from root-to-leaf order -func NewMerklePath(keyPath ...string) MerklePath { - var path [][]byte - for _, key := range keyPath { - path = append(path, []byte(key)) - } - - return MerklePath{ - KeyPath: path, - } -} +// The keys must be passed in from root-to-leaf order. +// NOTE: NewMerklePath returns a commitment/v2 MerklePath. +var NewMerklePath = v2.NewMerklePath // GetKey will return a byte representation of the key -func (mp MerklePath) GetKey(i uint64) ([]byte, error) { +// Deprecated: Please use commitment/v2 MerklePath instead. +func (mp MerklePath) GetKey(i uint64) (string, error) { if i >= uint64(len(mp.KeyPath)) { - return nil, fmt.Errorf("index out of range. %d (index) >= %d (len)", i, len(mp.KeyPath)) + return "", fmt.Errorf("index out of range. %d (index) >= %d (len)", i, len(mp.KeyPath)) } return mp.KeyPath[i], nil } // Empty returns true if the path is empty +// Deprecated: Please use commitment/v2 MerklePath instead. func (mp MerklePath) Empty() bool { return len(mp.KeyPath) == 0 } // ApplyPrefix constructs a new commitment path from the arguments. It prepends the prefix key // with the given path. -func ApplyPrefix(prefix exported.Prefix, path MerklePath) (MerklePath, error) { +func ApplyPrefix(prefix exported.Prefix, path v2.MerklePath) (v2.MerklePath, error) { if prefix == nil || prefix.Empty() { - return MerklePath{}, errorsmod.Wrap(ErrInvalidPrefix, "prefix can't be empty") + return v2.MerklePath{}, errorsmod.Wrap(ErrInvalidPrefix, "prefix can't be empty") } - return MerklePath{ + return v2.MerklePath{ KeyPath: append([][]byte{prefix.Bytes()}, path.KeyPath...), }, nil } @@ -114,7 +109,7 @@ func (proof MerkleProof) VerifyMembership(specs []*ics23.ProofSpec, root exporte } // VerifyMembership specific argument validation - mpath, ok := path.(MerklePath) + mpath, ok := path.(v2.MerklePath) if !ok { return errorsmod.Wrapf(ErrInvalidProof, "path %v is not of type MerklePath", path) } @@ -140,7 +135,7 @@ func (proof MerkleProof) VerifyNonMembership(specs []*ics23.ProofSpec, root expo } // VerifyNonMembership specific argument validation - mpath, ok := path.(MerklePath) + mpath, ok := path.(v2.MerklePath) if !ok { return errorsmod.Wrapf(ErrInvalidProof, "path %v is not of type MerkleProof", path) } @@ -196,7 +191,7 @@ func (MerkleProof) BatchVerifyNonMembership(specs []*ics23.ProofSpec, root expor // The proofs and specs are passed in from lowest subtree to the highest subtree, but the keys are passed in from highest subtree to lowest. // The index specifies what index to start chaining the membership proofs, this is useful since the lowest proof may not be a membership proof, thus we // will want to start the membership proof chaining from index 1 with value being the lowest subroot -func verifyChainedMembershipProof(root []byte, specs []*ics23.ProofSpec, proofs []*ics23.CommitmentProof, keys MerklePath, value []byte, index int) error { +func verifyChainedMembershipProof(root []byte, specs []*ics23.ProofSpec, proofs []*ics23.CommitmentProof, keys v2.MerklePath, value []byte, index int) error { var ( subroot []byte err error diff --git a/modules/core/23-commitment/types/merkle_test.go b/modules/core/23-commitment/types/merkle_test.go index b8aedb0e967..d0089799c67 100644 --- a/modules/core/23-commitment/types/merkle_test.go +++ b/modules/core/23-commitment/types/merkle_test.go @@ -9,6 +9,7 @@ import ( storetypes "cosmossdk.io/store/types" "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" + "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types/v2" ) func (suite *MerkleTestSuite) TestVerifyMembership() { @@ -32,22 +33,22 @@ func (suite *MerkleTestSuite) TestVerifyMembership() { cases := []struct { name string root []byte - pathArr []string + pathArr [][]byte value []byte malleate func() shouldPass bool }{ - {"valid proof", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, []byte("MYVALUE"), func() {}, true}, // valid proof - {"wrong value", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, []byte("WRONGVALUE"), func() {}, false}, // invalid proof with wrong value - {"nil value", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, []byte(nil), func() {}, false}, // invalid proof with nil value - {"wrong key", cid.Hash, []string{suite.storeKey.Name(), "NOTMYKEY"}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong key - {"wrong path 1", cid.Hash, []string{suite.storeKey.Name(), "MYKEY", "MYKEY"}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong path - {"wrong path 2", cid.Hash, []string{suite.storeKey.Name()}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong path - {"wrong path 3", cid.Hash, []string{"MYKEY"}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong path - {"wrong storekey", cid.Hash, []string{"otherStoreKey", "MYKEY"}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong store prefix - {"wrong root", []byte("WRONGROOT"), []string{suite.storeKey.Name(), "MYKEY"}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong root - {"nil root", []byte(nil), []string{suite.storeKey.Name(), "MYKEY"}, []byte("MYVALUE"), func() {}, false}, // invalid proof with nil root - {"proof is wrong length", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, []byte("MYVALUE"), func() { + {"valid proof", cid.Hash, [][]byte{[]byte(suite.storeKey.Name()), []byte("MYKEY")}, []byte("MYVALUE"), func() {}, true}, // valid proof + {"wrong value", cid.Hash, [][]byte{[]byte(suite.storeKey.Name()), []byte("MYKEY")}, []byte("WRONGVALUE"), func() {}, false}, // invalid proof with wrong value + {"nil value", cid.Hash, [][]byte{[]byte(suite.storeKey.Name()), []byte("MYKEY")}, []byte(nil), func() {}, false}, // invalid proof with nil value + {"wrong key", cid.Hash, [][]byte{[]byte(suite.storeKey.Name()), []byte("NOTMYKEY")}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong key + {"wrong path 1", cid.Hash, [][]byte{[]byte(suite.storeKey.Name()), []byte("MYKEY"), []byte("MYKEY")}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong path + {"wrong path 2", cid.Hash, [][]byte{[]byte(suite.storeKey.Name())}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong path + {"wrong path 3", cid.Hash, [][]byte{[]byte("MYKEY")}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong path + {"wrong storekey", cid.Hash, [][]byte{[]byte("otherStoreKey"), []byte("MYKEY")}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong store prefix + {"wrong root", []byte("WRONGROOT"), [][]byte{[]byte(suite.storeKey.Name()), []byte("MYKEY")}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong root + {"nil root", []byte(nil), [][]byte{[]byte(suite.storeKey.Name()), []byte("MYKEY")}, []byte("MYVALUE"), func() {}, false}, // invalid proof with nil root + {"proof is wrong length", cid.Hash, [][]byte{[]byte(suite.storeKey.Name()), []byte("MYKEY")}, []byte("MYVALUE"), func() { proof = types.MerkleProof{ Proofs: proof.Proofs[1:], } @@ -97,20 +98,20 @@ func (suite *MerkleTestSuite) TestVerifyNonMembership() { cases := []struct { name string root []byte - pathArr []string + pathArr [][]byte malleate func() shouldPass bool }{ - {"valid proof", cid.Hash, []string{suite.storeKey.Name(), "MYABSENTKEY"}, func() {}, true}, // valid proof - {"wrong key", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, func() {}, false}, // invalid proof with existent key - {"wrong path 1", cid.Hash, []string{suite.storeKey.Name(), "MYKEY", "MYABSENTKEY"}, func() {}, false}, // invalid proof with wrong path - {"wrong path 2", cid.Hash, []string{suite.storeKey.Name(), "MYABSENTKEY", "MYKEY"}, func() {}, false}, // invalid proof with wrong path - {"wrong path 3", cid.Hash, []string{suite.storeKey.Name()}, func() {}, false}, // invalid proof with wrong path - {"wrong path 4", cid.Hash, []string{"MYABSENTKEY"}, func() {}, false}, // invalid proof with wrong path - {"wrong storeKey", cid.Hash, []string{"otherStoreKey", "MYABSENTKEY"}, func() {}, false}, // invalid proof with wrong store prefix - {"wrong root", []byte("WRONGROOT"), []string{suite.storeKey.Name(), "MYABSENTKEY"}, func() {}, false}, // invalid proof with wrong root - {"nil root", []byte(nil), []string{suite.storeKey.Name(), "MYABSENTKEY"}, func() {}, false}, // invalid proof with nil root - {"proof is wrong length", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, func() { + {"valid proof", cid.Hash, [][]byte{[]byte(suite.storeKey.Name()), []byte("MYABSENTKEY")}, func() {}, true}, // valid proof + {"wrong key", cid.Hash, [][]byte{[]byte(suite.storeKey.Name()), []byte("MYKEY")}, func() {}, false}, // invalid proof with existent key + {"wrong path 1", cid.Hash, [][]byte{[]byte(suite.storeKey.Name()), []byte("MYKEY"), []byte("MYABSENTKEY")}, func() {}, false}, // invalid proof with wrong path + {"wrong path 2", cid.Hash, [][]byte{[]byte(suite.storeKey.Name()), []byte("MYABSENTKEY"), []byte("MYKEY")}, func() {}, false}, // invalid proof with wrong path + {"wrong path 3", cid.Hash, [][]byte{[]byte(suite.storeKey.Name())}, func() {}, false}, // invalid proof with wrong path + {"wrong path 4", cid.Hash, [][]byte{[]byte("MYABSENTKEY")}, func() {}, false}, // invalid proof with wrong path + {"wrong storeKey", cid.Hash, [][]byte{[]byte("otherStoreKey"), []byte("MYABSENTKEY")}, func() {}, false}, // invalid proof with wrong store prefix + {"wrong root", []byte("WRONGROOT"), [][]byte{[]byte(suite.storeKey.Name()), []byte("MYABSENTKEY")}, func() {}, false}, // invalid proof with wrong root + {"nil root", []byte(nil), [][]byte{[]byte(suite.storeKey.Name()), []byte("MYABSENTKEY")}, func() {}, false}, // invalid proof with nil root + {"proof is wrong length", cid.Hash, [][]byte{[]byte(suite.storeKey.Name()), []byte("MYKEY")}, func() { proof = types.MerkleProof{ Proofs: proof.Proofs[1:], } @@ -143,9 +144,9 @@ func (suite *MerkleTestSuite) TestVerifyNonMembership() { func TestApplyPrefix(t *testing.T) { prefix := types.NewMerklePrefix([]byte("storePrefixKey")) - pathStr := "pathone/pathtwo/paththree/key" - path := types.MerklePath{ - KeyPath: [][]byte{[]byte(pathStr)}, + pathBz := []byte("pathone/pathtwo/paththree/key") + path := v2.MerklePath{ + KeyPath: [][]byte{pathBz}, } prefixedPath, err := types.ApplyPrefix(prefix, path) @@ -158,5 +159,5 @@ func TestApplyPrefix(t *testing.T) { key1, err := prefixedPath.GetKey(1) require.NoError(t, err, "get key 1 returns error") - require.Equal(t, []byte(pathStr), key1, "key 1 does not match expected value") + require.Equal(t, pathBz, key1, "key 1 does not match expected value") } diff --git a/modules/core/23-commitment/types/utils_test.go b/modules/core/23-commitment/types/utils_test.go index 22afcf60a52..cd7f9a8bf50 100644 --- a/modules/core/23-commitment/types/utils_test.go +++ b/modules/core/23-commitment/types/utils_test.go @@ -17,8 +17,8 @@ func (suite *MerkleTestSuite) TestConvertProofs() { cid := suite.store.Commit() root := types.NewMerkleRoot(cid.Hash) - existsPath := types.NewMerklePath(suite.storeKey.Name(), "MYKEY") - nonexistPath := types.NewMerklePath(suite.storeKey.Name(), "NOTMYKEY") + existsPath := types.NewMerklePath([]byte(suite.storeKey.Name()), []byte("MYKEY")) + nonexistPath := types.NewMerklePath([]byte(suite.storeKey.Name()), []byte("NOTMYKEY")) value := []byte("MYVALUE") var proofOps *crypto.ProofOps diff --git a/modules/core/23-commitment/types/v2/commitment.pb.go b/modules/core/23-commitment/types/v2/commitment.pb.go new file mode 100644 index 00000000000..fed8615f431 --- /dev/null +++ b/modules/core/23-commitment/types/v2/commitment.pb.go @@ -0,0 +1,325 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: ibc/core/commitment/v2/commitment.proto + +package v2 + +import ( + fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// MerklePath is the path used to verify commitment proofs, which can be an +// arbitrary structured object (defined by a commitment type). +// MerklePath is represented from root-to-leaf +type MerklePath struct { + KeyPath [][]byte `protobuf:"bytes,1,rep,name=key_path,json=keyPath,proto3" json:"key_path,omitempty"` +} + +func (m *MerklePath) Reset() { *m = MerklePath{} } +func (m *MerklePath) String() string { return proto.CompactTextString(m) } +func (*MerklePath) ProtoMessage() {} +func (*MerklePath) Descriptor() ([]byte, []int) { + return fileDescriptor_8f65a9eb5e4ee5fc, []int{0} +} +func (m *MerklePath) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MerklePath) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MerklePath.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MerklePath) XXX_Merge(src proto.Message) { + xxx_messageInfo_MerklePath.Merge(m, src) +} +func (m *MerklePath) XXX_Size() int { + return m.Size() +} +func (m *MerklePath) XXX_DiscardUnknown() { + xxx_messageInfo_MerklePath.DiscardUnknown(m) +} + +var xxx_messageInfo_MerklePath proto.InternalMessageInfo + +func (m *MerklePath) GetKeyPath() [][]byte { + if m != nil { + return m.KeyPath + } + return nil +} + +func init() { + proto.RegisterType((*MerklePath)(nil), "ibc.core.commitment.v2.MerklePath") +} + +func init() { + proto.RegisterFile("ibc/core/commitment/v2/commitment.proto", fileDescriptor_8f65a9eb5e4ee5fc) +} + +var fileDescriptor_8f65a9eb5e4ee5fc = []byte{ + // 191 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0xcf, 0x4c, 0x4a, 0xd6, + 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x4f, 0xce, 0xcf, 0xcd, 0xcd, 0x2c, 0xc9, 0x4d, 0xcd, 0x2b, 0xd1, + 0x2f, 0x33, 0x42, 0xe2, 0xe9, 0x15, 0x14, 0xe5, 0x97, 0xe4, 0x0b, 0x89, 0x65, 0x26, 0x25, 0xeb, + 0x81, 0x14, 0xea, 0x21, 0x49, 0x95, 0x19, 0x29, 0xa9, 0x73, 0x71, 0xf9, 0xa6, 0x16, 0x65, 0xe7, + 0xa4, 0x06, 0x24, 0x96, 0x64, 0x08, 0x49, 0x72, 0x71, 0x64, 0xa7, 0x56, 0xc6, 0x17, 0x24, 0x96, + 0x64, 0x48, 0x30, 0x2a, 0x30, 0x6b, 0xf0, 0x04, 0xb1, 0x67, 0xa7, 0x56, 0x82, 0xa4, 0x9c, 0x22, + 0x4f, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, + 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0xca, 0x3e, 0x3d, 0xb3, 0x24, 0xa3, + 0x34, 0x09, 0x64, 0xb0, 0x7e, 0x72, 0x7e, 0x71, 0x6e, 0x7e, 0xb1, 0x7e, 0x66, 0x52, 0xb2, 0x6e, + 0x7a, 0xbe, 0x7e, 0x99, 0x85, 0x7e, 0x6e, 0x7e, 0x4a, 0x69, 0x4e, 0x6a, 0x31, 0xc4, 0x8d, 0x46, + 0xc6, 0xba, 0x48, 0xce, 0x2c, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2f, 0x33, 0x4a, 0x62, 0x03, 0x3b, + 0xd1, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xc4, 0xd4, 0x6b, 0x94, 0xcd, 0x00, 0x00, 0x00, +} + +func (m *MerklePath) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MerklePath) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MerklePath) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.KeyPath) > 0 { + for iNdEx := len(m.KeyPath) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.KeyPath[iNdEx]) + copy(dAtA[i:], m.KeyPath[iNdEx]) + i = encodeVarintCommitment(dAtA, i, uint64(len(m.KeyPath[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintCommitment(dAtA []byte, offset int, v uint64) int { + offset -= sovCommitment(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MerklePath) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.KeyPath) > 0 { + for _, b := range m.KeyPath { + l = len(b) + n += 1 + l + sovCommitment(uint64(l)) + } + } + return n +} + +func sovCommitment(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozCommitment(x uint64) (n int) { + return sovCommitment(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MerklePath) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCommitment + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MerklePath: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MerklePath: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field KeyPath", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCommitment + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCommitment + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthCommitment + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.KeyPath = append(m.KeyPath, make([]byte, postIndex-iNdEx)) + copy(m.KeyPath[len(m.KeyPath)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCommitment(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthCommitment + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipCommitment(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCommitment + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCommitment + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCommitment + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthCommitment + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupCommitment + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthCommitment + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthCommitment = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowCommitment = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupCommitment = fmt.Errorf("proto: unexpected end of group") +) diff --git a/modules/core/23-commitment/types/v2/merkle.go b/modules/core/23-commitment/types/v2/merkle.go new file mode 100644 index 00000000000..84944565788 --- /dev/null +++ b/modules/core/23-commitment/types/v2/merkle.go @@ -0,0 +1,30 @@ +package v2 + +import ( + "fmt" + + "github.com/cosmos/ibc-go/v8/modules/core/exported" +) + +var _ exported.Path = (*MerklePath)(nil) + +// NewMerklePath creates a new MerklePath instance +// The keys must be passed in from root-to-leaf order +func NewMerklePath(keyPath ...[]byte) MerklePath { + return MerklePath{ + KeyPath: keyPath, + } +} + +// GetKey will return a byte representation of the key +func (mp MerklePath) GetKey(i uint64) ([]byte, error) { + if i >= uint64(len(mp.KeyPath)) { + return nil, fmt.Errorf("index out of range. %d (index) >= %d (len)", i, len(mp.KeyPath)) + } + return mp.KeyPath[i], nil +} + +// Empty returns true if the path is empty +func (mp MerklePath) Empty() bool { + return len(mp.KeyPath) == 0 +} diff --git a/modules/light-clients/06-solomachine/client_state.go b/modules/light-clients/06-solomachine/client_state.go index 43d30fc4577..1bbac3c2314 100644 --- a/modules/light-clients/06-solomachine/client_state.go +++ b/modules/light-clients/06-solomachine/client_state.go @@ -10,7 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/tx/signing" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" - commitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" + commitmenttypesv2 "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types/v2" host "github.com/cosmos/ibc-go/v8/modules/core/24-host" ibcerrors "github.com/cosmos/ibc-go/v8/modules/core/errors" "github.com/cosmos/ibc-go/v8/modules/core/exported" @@ -61,9 +61,9 @@ func (cs *ClientState) VerifyMembership( return err } - merklePath, ok := path.(commitmenttypes.MerklePath) + merklePath, ok := path.(commitmenttypesv2.MerklePath) if !ok { - return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypes.MerklePath{}, path) + return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypesv2.MerklePath{}, path) } if len(merklePath.GetKeyPath()) != 2 { @@ -117,9 +117,9 @@ func (cs *ClientState) VerifyNonMembership( return err } - merklePath, ok := path.(commitmenttypes.MerklePath) + merklePath, ok := path.(commitmenttypesv2.MerklePath) if !ok { - return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypes.MerklePath{}, path) + return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypesv2.MerklePath{}, path) } if len(merklePath.GetKeyPath()) != 2 { 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 d80691462a8..46bce0a6ef8 100644 --- a/modules/light-clients/06-solomachine/light_client_module_test.go +++ b/modules/light-clients/06-solomachine/light_client_module_test.go @@ -8,7 +8,7 @@ import ( 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" + commitmenttypesv2 "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types/v2" host "github.com/cosmos/ibc-go/v8/modules/core/24-host" ibcerrors "github.com/cosmos/ibc-go/v8/modules/core/errors" "github.com/cosmos/ibc-go/v8/modules/core/exported" @@ -247,7 +247,7 @@ func (suite *SoloMachineTestSuite) TestVerifyMembership() { suite.Require().NoError(err) path = sm.GetClientStatePath(counterpartyClientIdentifier) - merklePath, ok := path.(commitmenttypes.MerklePath) + merklePath, ok := path.(commitmenttypesv2.MerklePath) suite.Require().True(ok) key, err := merklePath.GetKey(1) // in a multistore context: index 0 is the key for the IBC store in the multistore, index 1 is the key in the IBC store suite.Require().NoError(err) @@ -283,7 +283,7 @@ func (suite *SoloMachineTestSuite) TestVerifyMembership() { suite.Require().NoError(err) path = sm.GetConsensusStatePath(counterpartyClientIdentifier, clienttypes.NewHeight(0, 1)) - merklePath, ok := path.(commitmenttypes.MerklePath) + merklePath, ok := path.(commitmenttypesv2.MerklePath) suite.Require().True(ok) key, err := merklePath.GetKey(1) // in a multistore context: index 0 is the key for the IBC store in the multistore, index 1 is the key in the IBC store suite.Require().NoError(err) @@ -322,7 +322,7 @@ func (suite *SoloMachineTestSuite) TestVerifyMembership() { suite.Require().NoError(err) path = sm.GetConnectionStatePath(ibctesting.FirstConnectionID) - merklePath, ok := path.(commitmenttypes.MerklePath) + merklePath, ok := path.(commitmenttypesv2.MerklePath) suite.Require().True(ok) key, err := merklePath.GetKey(1) // in a multistore context: index 0 is the key for the IBC store in the multistore, index 1 is the key in the IBC store suite.Require().NoError(err) @@ -362,7 +362,7 @@ func (suite *SoloMachineTestSuite) TestVerifyMembership() { suite.Require().NoError(err) path = sm.GetChannelStatePath(ibctesting.MockPort, ibctesting.FirstChannelID) - merklePath, ok := path.(commitmenttypes.MerklePath) + merklePath, ok := path.(commitmenttypesv2.MerklePath) suite.Require().True(ok) key, err := merklePath.GetKey(1) // in a multistore context: index 0 is the key for the IBC store in the multistore, index 1 is the key in the IBC store suite.Require().NoError(err) @@ -399,7 +399,7 @@ func (suite *SoloMachineTestSuite) TestVerifyMembership() { suite.Require().True(found) path = sm.GetNextSequenceRecvPath(ibctesting.MockPort, ibctesting.FirstChannelID) - merklePath, ok := path.(commitmenttypes.MerklePath) + merklePath, ok := path.(commitmenttypesv2.MerklePath) suite.Require().True(ok) key, err := merklePath.GetKey(1) // in a multistore context: index 0 is the key for the IBC store in the multistore, index 1 is the key in the IBC store suite.Require().NoError(err) @@ -442,7 +442,7 @@ func (suite *SoloMachineTestSuite) TestVerifyMembership() { commitmentBz := channeltypes.CommitPacket(suite.chainA.Codec, packet) path = sm.GetPacketCommitmentPath(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - merklePath, ok := path.(commitmenttypes.MerklePath) + merklePath, ok := path.(commitmenttypesv2.MerklePath) suite.Require().True(ok) key, err := merklePath.GetKey(1) // in a multistore context: index 0 is the key for the IBC store in the multistore, index 1 is the key in the IBC store suite.Require().NoError(err) @@ -473,7 +473,7 @@ func (suite *SoloMachineTestSuite) TestVerifyMembership() { "success: packet acknowledgement verification", func() { path = sm.GetPacketAcknowledgementPath(ibctesting.MockPort, ibctesting.FirstChannelID, 1) - merklePath, ok := path.(commitmenttypes.MerklePath) + merklePath, ok := path.(commitmenttypesv2.MerklePath) suite.Require().True(ok) key, err := merklePath.GetKey(1) // index 0 is the key for the IBC store in the multistore, index 1 is the key in the IBC store suite.Require().NoError(err) @@ -504,7 +504,7 @@ func (suite *SoloMachineTestSuite) TestVerifyMembership() { "success: packet receipt verification", func() { path = sm.GetPacketReceiptPath(ibctesting.MockPort, ibctesting.FirstChannelID, 1) - merklePath, ok := path.(commitmenttypes.MerklePath) + merklePath, ok := path.(commitmenttypesv2.MerklePath) suite.Require().True(ok) key, err := merklePath.GetKey(1) // in a multistore context: index 0 is the key for the IBC store in the multistore, index 1 is the key in the IBC store suite.Require().NoError(err) @@ -617,7 +617,7 @@ func (suite *SoloMachineTestSuite) TestVerifyMembership() { { "failure: empty path", func() { - path = commitmenttypes.MerklePath{} + path = commitmenttypesv2.MerklePath{} }, fmt.Errorf("path must be of length 2: []: %s", host.ErrInvalidPath), }, @@ -633,8 +633,8 @@ func (suite *SoloMachineTestSuite) TestVerifyMembership() { clientID = sm.ClientID clientState = sm.ClientState() - path = commitmenttypes.NewMerklePath("ibc", "solomachine") - merklePath, ok := path.(commitmenttypes.MerklePath) + path = commitmenttypesv2.NewMerklePath([]byte("ibc"), []byte("solomachine")) + merklePath, ok := path.(commitmenttypesv2.MerklePath) suite.Require().True(ok) key, err := merklePath.GetKey(1) // in a multistore context: index 0 is the key for the IBC store in the multistore, index 1 is the key in the IBC store suite.Require().NoError(err) @@ -724,7 +724,7 @@ func (suite *SoloMachineTestSuite) TestVerifyNonMembership() { "success: packet receipt absence verification", func() { path = sm.GetPacketReceiptPath(ibctesting.MockPort, ibctesting.FirstChannelID, 1) - merklePath, ok := path.(commitmenttypes.MerklePath) + merklePath, ok := path.(commitmenttypesv2.MerklePath) suite.Require().True(ok) key, err := merklePath.GetKey(1) // in a multistore context: index 0 is the key for the IBC store in the multistore, index 1 is the key in the IBC store suite.Require().NoError(err) @@ -858,8 +858,8 @@ func (suite *SoloMachineTestSuite) TestVerifyNonMembership() { clientState = sm.ClientState() clientID = sm.ClientID - path = commitmenttypes.NewMerklePath("ibc", "solomachine") - merklePath, ok := path.(commitmenttypes.MerklePath) + path = commitmenttypesv2.NewMerklePath([]byte("ibc"), []byte("solomachine")) + merklePath, ok := path.(commitmenttypesv2.MerklePath) suite.Require().True(ok) key, err := merklePath.GetKey(1) // in a multistore context: index 0 is the key for the IBC store in the multistore, index 1 is the key in the IBC store suite.Require().NoError(err) diff --git a/modules/light-clients/07-tendermint/client_state.go b/modules/light-clients/07-tendermint/client_state.go index daa14c9e0a1..c089b80a1f5 100644 --- a/modules/light-clients/07-tendermint/client_state.go +++ b/modules/light-clients/07-tendermint/client_state.go @@ -17,6 +17,7 @@ import ( clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" commitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" + commitmenttypesv2 "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types/v2" ibcerrors "github.com/cosmos/ibc-go/v8/modules/core/errors" "github.com/cosmos/ibc-go/v8/modules/core/exported" ) @@ -230,9 +231,9 @@ func (cs ClientState) VerifyMembership( return errorsmod.Wrap(commitmenttypes.ErrInvalidProof, "failed to unmarshal proof into ICS 23 commitment merkle proof") } - merklePath, ok := path.(commitmenttypes.MerklePath) + merklePath, ok := path.(commitmenttypesv2.MerklePath) if !ok { - return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypes.MerklePath{}, path) + return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypesv2.MerklePath{}, path) } consensusState, found := GetConsensusState(clientStore, cdc, height) @@ -272,9 +273,9 @@ func (cs ClientState) VerifyNonMembership( return errorsmod.Wrap(commitmenttypes.ErrInvalidProof, "failed to unmarshal proof into ICS 23 commitment merkle proof") } - merklePath, ok := path.(commitmenttypes.MerklePath) + merklePath, ok := path.(commitmenttypesv2.MerklePath) if !ok { - return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypes.MerklePath{}, path) + return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypesv2.MerklePath{}, path) } consensusState, found := GetConsensusState(clientStore, cdc, height) 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 77c446e5a70..90f401a5b29 100644 --- a/modules/light-clients/07-tendermint/light_client_module_test.go +++ b/modules/light-clients/07-tendermint/light_client_module_test.go @@ -284,7 +284,7 @@ func (suite *TendermintTestSuite) TestVerifyMembership() { latestHeight := testingpath.EndpointB.GetClientLatestHeight() key := host.FullConsensusStateKey(testingpath.EndpointB.ClientID, latestHeight) - merklePath := commitmenttypes.NewMerklePath(string(key)) + merklePath := commitmenttypes.NewMerklePath(key) path, err = commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -300,7 +300,7 @@ func (suite *TendermintTestSuite) TestVerifyMembership() { { "successful Connection verification", func() { key := host.ConnectionKey(testingpath.EndpointB.ConnectionID) - merklePath := commitmenttypes.NewMerklePath(string(key)) + merklePath := commitmenttypes.NewMerklePath(key) path, err = commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -315,7 +315,7 @@ func (suite *TendermintTestSuite) TestVerifyMembership() { { "successful Channel verification", func() { key := host.ChannelKey(testingpath.EndpointB.ChannelConfig.PortID, testingpath.EndpointB.ChannelID) - merklePath := commitmenttypes.NewMerklePath(string(key)) + merklePath := commitmenttypes.NewMerklePath(key) path, err = commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -336,7 +336,7 @@ func (suite *TendermintTestSuite) TestVerifyMembership() { // make packet commitment proof packet := channeltypes.NewPacket(ibctesting.MockPacketData, sequence, testingpath.EndpointB.ChannelConfig.PortID, testingpath.EndpointB.ChannelID, testingpath.EndpointA.ChannelConfig.PortID, testingpath.EndpointA.ChannelID, clienttypes.NewHeight(1, 100), 0) key := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - merklePath := commitmenttypes.NewMerklePath(string(key)) + merklePath := commitmenttypes.NewMerklePath(key) path, err = commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -357,7 +357,7 @@ func (suite *TendermintTestSuite) TestVerifyMembership() { suite.Require().NoError(err) key := host.PacketAcknowledgementKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - merklePath := commitmenttypes.NewMerklePath(string(key)) + merklePath := commitmenttypes.NewMerklePath(key) path, err = commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -381,7 +381,7 @@ func (suite *TendermintTestSuite) TestVerifyMembership() { suite.Require().NoError(err) key := host.NextSequenceRecvKey(packet.GetSourcePort(), packet.GetSourceChannel()) - merklePath := commitmenttypes.NewMerklePath(string(key)) + merklePath := commitmenttypes.NewMerklePath(key) path, err = commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -394,7 +394,7 @@ func (suite *TendermintTestSuite) TestVerifyMembership() { { "successful verification outside IBC store", func() { key := transfertypes.PortKey - merklePath := commitmenttypes.NewMerklePath(string(key)) + merklePath := commitmenttypes.NewMerklePath(key) path, err = commitmenttypes.ApplyPrefix(commitmenttypes.NewMerklePrefix([]byte(transfertypes.StoreKey)), merklePath) suite.Require().NoError(err) @@ -494,7 +494,7 @@ func (suite *TendermintTestSuite) TestVerifyMembership() { // create default proof, merklePath, and value which passes // may be overwritten by malleate() key := host.FullClientStateKey(testingpath.EndpointB.ClientID) - merklePath := commitmenttypes.NewMerklePath(string(key)) + merklePath := commitmenttypes.NewMerklePath(key) path, err = commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -554,7 +554,7 @@ func (suite *TendermintTestSuite) TestVerifyNonMembership() { { "successful ConsensusState verification of non membership", func() { key := host.FullConsensusStateKey(invalidClientID, testingpath.EndpointB.GetClientLatestHeight()) - merklePath := commitmenttypes.NewMerklePath(string(key)) + merklePath := commitmenttypes.NewMerklePath(key) path, err = commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -565,7 +565,7 @@ func (suite *TendermintTestSuite) TestVerifyNonMembership() { { "successful Connection verification of non membership", func() { key := host.ConnectionKey(invalidConnectionID) - merklePath := commitmenttypes.NewMerklePath(string(key)) + merklePath := commitmenttypes.NewMerklePath(key) path, err = commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -576,7 +576,7 @@ func (suite *TendermintTestSuite) TestVerifyNonMembership() { { "successful Channel verification of non membership", func() { key := host.ChannelKey(testingpath.EndpointB.ChannelConfig.PortID, invalidChannelID) - merklePath := commitmenttypes.NewMerklePath(string(key)) + merklePath := commitmenttypes.NewMerklePath(key) path, err = commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -588,7 +588,7 @@ func (suite *TendermintTestSuite) TestVerifyNonMembership() { "successful PacketCommitment verification of non membership", func() { // make packet commitment proof key := host.PacketCommitmentKey(invalidPortID, invalidChannelID, 1) - merklePath := commitmenttypes.NewMerklePath(string(key)) + merklePath := commitmenttypes.NewMerklePath(key) path, err = commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -599,7 +599,7 @@ func (suite *TendermintTestSuite) TestVerifyNonMembership() { { "successful Acknowledgement verification of non membership", func() { key := host.PacketAcknowledgementKey(invalidPortID, invalidChannelID, 1) - merklePath := commitmenttypes.NewMerklePath(string(key)) + merklePath := commitmenttypes.NewMerklePath(key) path, err = commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -610,7 +610,7 @@ func (suite *TendermintTestSuite) TestVerifyNonMembership() { { "successful NextSequenceRecv verification of non membership", func() { key := host.NextSequenceRecvKey(invalidPortID, invalidChannelID) - merklePath := commitmenttypes.NewMerklePath(string(key)) + merklePath := commitmenttypes.NewMerklePath(key) path, err = commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -621,7 +621,7 @@ func (suite *TendermintTestSuite) TestVerifyNonMembership() { { "successful verification of non membership outside IBC store", func() { key := []byte{0x08} - merklePath := commitmenttypes.NewMerklePath(string(key)) + merklePath := commitmenttypes.NewMerklePath(key) path, err = commitmenttypes.ApplyPrefix(commitmenttypes.NewMerklePrefix([]byte(transfertypes.StoreKey)), merklePath) suite.Require().NoError(err) @@ -682,7 +682,7 @@ func (suite *TendermintTestSuite) TestVerifyNonMembership() { "verify non membership fails as path exists", func() { // change the value being proved key := host.FullClientStateKey(testingpath.EndpointB.ClientID) - merklePath := commitmenttypes.NewMerklePath(string(key)) + merklePath := commitmenttypes.NewMerklePath(key) path, err = commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -724,7 +724,7 @@ func (suite *TendermintTestSuite) TestVerifyNonMembership() { // may be overwritten by malleate() key := host.FullClientStateKey("invalid-client-id") - merklePath := commitmenttypes.NewMerklePath(string(key)) + merklePath := commitmenttypes.NewMerklePath(key) path, err = commitmenttypes.ApplyPrefix(suite.chainB.GetPrefix(), merklePath) suite.Require().NoError(err) diff --git a/modules/light-clients/07-tendermint/upgrade.go b/modules/light-clients/07-tendermint/upgrade.go index ef62e707795..f45208c36ea 100644 --- a/modules/light-clients/07-tendermint/upgrade.go +++ b/modules/light-clients/07-tendermint/upgrade.go @@ -12,6 +12,7 @@ import ( clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" commitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" + commitmenttypesv2 "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types/v2" "github.com/cosmos/ibc-go/v8/modules/core/exported" ) @@ -124,7 +125,7 @@ func (cs ClientState) VerifyUpgradeAndUpdateState( } // construct MerklePath for the committed client from upgradePath -func constructUpgradeClientMerklePath(upgradePath []string, lastHeight exported.Height) commitmenttypes.MerklePath { +func constructUpgradeClientMerklePath(upgradePath []string, lastHeight exported.Height) commitmenttypesv2.MerklePath { // copy all elements from upgradePath except final element clientPath := make([]string, len(upgradePath)-1) copy(clientPath, upgradePath) @@ -135,11 +136,17 @@ func constructUpgradeClientMerklePath(upgradePath []string, lastHeight exported. appendedKey := fmt.Sprintf("%s/%d/%s", lastKey, lastHeight.GetRevisionHeight(), upgradetypes.KeyUpgradedClient) clientPath = append(clientPath, appendedKey) - return commitmenttypes.NewMerklePath(clientPath...) + + var clientKey [][]byte + for _, part := range clientPath { + clientKey = append(clientKey, []byte(part)) + } + + return commitmenttypes.NewMerklePath(clientKey...) } // construct MerklePath for the committed consensus state from upgradePath -func constructUpgradeConsStateMerklePath(upgradePath []string, lastHeight exported.Height) commitmenttypes.MerklePath { +func constructUpgradeConsStateMerklePath(upgradePath []string, lastHeight exported.Height) commitmenttypesv2.MerklePath { // copy all elements from upgradePath except final element consPath := make([]string, len(upgradePath)-1) copy(consPath, upgradePath) @@ -150,5 +157,11 @@ func constructUpgradeConsStateMerklePath(upgradePath []string, lastHeight export appendedKey := fmt.Sprintf("%s/%d/%s", lastKey, lastHeight.GetRevisionHeight(), upgradetypes.KeyUpgradedConsState) consPath = append(consPath, appendedKey) - return commitmenttypes.NewMerklePath(consPath...) + + var consStateKey [][]byte + for _, part := range consPath { + consStateKey = append(consStateKey, []byte(part)) + } + + return commitmenttypes.NewMerklePath(consStateKey...) } diff --git a/modules/light-clients/08-wasm/CHANGELOG.md b/modules/light-clients/08-wasm/CHANGELOG.md index d6172125d31..f989ec6b5c6 100644 --- a/modules/light-clients/08-wasm/CHANGELOG.md +++ b/modules/light-clients/08-wasm/CHANGELOG.md @@ -34,28 +34,40 @@ Ref: https://keepachangelog.com/en/1.0.0/ # Changelog -## [Unreleased] +## [[Unreleased]] ### Dependencies -* [\#6193](https://github.com/cosmos/ibc-go/pull/6193) Bump Cosmos SDK to v0.50.6. -* [\#6193](https://github.com/cosmos/ibc-go/pull/6193) Bump `cosmossdk.io/store` to v1.1.0. -* [#\6097](https://github.com/cosmos/ibc-go/pull/6097) Update wasmvm to v2.0.1. -* [\#6239](https://github.com/cosmos/ibc-go/pull/6239) Bump CometBFT to v0.38.7. - ### API Breaking +* [\#6644](https://github.com/cosmos/ibc-go/pull/6644) api!: add `v2.MerklePath` for contract api `VerifyMembershipMsg` and `VerifyNonMembershipMsg` structs. Note, this requires a migration for existing client contracts to correctly handle deserialization of `MerklePath.KeyPath` which has changed from `repeated string` to `repeated bytes`. In JSON message structures this change is reflected as the `KeyPath` being a marshalled as a list of base64 encoded byte strings. + ### State Machine Breaking ### Improvements +* [\#5923](https://github.com/cosmos/ibc-go/pull/5923) imp: add 08-wasm build opts for libwasmvm linking disabled + ### Features -* [#\5821](https://github.com/cosmos/ibc-go/pull/5821) feat: add `VerifyMembershipProof` RPC query (querier approach for conditional clients). -* [#\6231](https://github.com/cosmos/ibc-go/pull/6231) feat: add CLI to broadcast transaction with `MsgMigrateContract`. +* [\#6055](https://github.com/cosmos/ibc-go/pull/6055) feat: add 08-wasm `ConsensusHost` implementation for custom self client/consensus state validation in 03-connection handshake. ### Bug Fixes + +## [v0.2.0+ibc-go-v8.3-wasmvm-v2.0](https://github.com/cosmos/ibc-go/releases/tag/modules%2Flight-clients%2F08-wasm%2Fv0.2.0%2Bibc-go-v8.3-wasmvm-v2.0) - 2024-05-23 + +### Dependencies + +* [\#5909](https://github.com/cosmos/ibc-go/pull/5909) Update wasmvm to v2.0.0 and cometBFT to v0.38.6. +* [\#6097](https://github.com/cosmos/ibc-go/pull/6097) Update wasmvm to v2.0.1. +* [\#6350](https://github.com/cosmos/ibc-go/pull/6350) Upgrade Cosmos SDK to v0.50.6. + +### Features + +* [\#5821](https://github.com/cosmos/ibc-go/pull/5821) feat: add `VerifyMembershipProof` RPC query (querier approach for conditional clients). +* [\#6231](https://github.com/cosmos/ibc-go/pull/6231) feat: add CLI to broadcast transaction with `MsgMigrateContract`. + ## [v0.1.0+ibc-go-v8.0-wasmvm-v1.5](https://github.com/cosmos/ibc-go/releases/tag/modules%2Flight-clients%2F08-wasm%2Fv0.1.0%2Bibc-go-v7.3-wasmvm-v1.5) - 2023-12-18 @@ -68,4 +80,4 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Features -* [\#5079](https://github.com/cosmos/ibc-go/pull/5079) feat: 08-wasm light client proxy module for wasm clients. +* [\#5079](https://github.com/cosmos/ibc-go/pull/5079) feat: 08-wasm light client proxy module for wasm clients. \ No newline at end of file diff --git a/modules/light-clients/08-wasm/keeper/querier_test.go b/modules/light-clients/08-wasm/keeper/querier_test.go index 5fb1cf52173..74afd53d121 100644 --- a/modules/light-clients/08-wasm/keeper/querier_test.go +++ b/modules/light-clients/08-wasm/keeper/querier_test.go @@ -213,7 +213,7 @@ func (suite *KeeperTestSuite) TestStargateQuery() { suite.coordinator.CommitBlock(suite.chainA) proof, proofHeight := endpoint.QueryProofAtHeight(proofKey, uint64(suite.chainA.GetContext().BlockHeight())) - merklePath := commitmenttypes.NewMerklePath(string(proofKey)) + merklePath := commitmenttypes.NewMerklePath(proofKey) merklePath, err := commitmenttypes.ApplyPrefix(suite.chainA.GetPrefix(), merklePath) suite.Require().NoError(err) diff --git a/modules/light-clients/08-wasm/light_client_module.go b/modules/light-clients/08-wasm/light_client_module.go index 8e44931ef15..b2d2783f83f 100644 --- a/modules/light-clients/08-wasm/light_client_module.go +++ b/modules/light-clients/08-wasm/light_client_module.go @@ -14,7 +14,7 @@ import ( wasmkeeper "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/keeper" "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/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" + commitmenttypesv2 "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types/v2" ibcerrors "github.com/cosmos/ibc-go/v8/modules/core/errors" "github.com/cosmos/ibc-go/v8/modules/core/exported" ) @@ -249,9 +249,9 @@ func (l LightClientModule) VerifyMembership( ) } - merklePath, ok := path.(commitmenttypes.MerklePath) + merklePath, ok := path.(commitmenttypesv2.MerklePath) if !ok { - return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypes.MerklePath{}, path) + return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypesv2.MerklePath{}, path) } payload := types.SudoMsg{ @@ -264,6 +264,7 @@ func (l LightClientModule) VerifyMembership( Value: value, }, } + _, err := l.keeper.WasmSudo(ctx, clientID, clientStore, clientState, payload) return err } @@ -303,9 +304,9 @@ func (l LightClientModule) VerifyNonMembership( ) } - merklePath, ok := path.(commitmenttypes.MerklePath) + merklePath, ok := path.(commitmenttypesv2.MerklePath) if !ok { - return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypes.MerklePath{}, path) + return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypesv2.MerklePath{}, path) } payload := types.SudoMsg{ @@ -317,6 +318,7 @@ func (l LightClientModule) VerifyNonMembership( Path: merklePath, }, } + _, err := l.keeper.WasmSudo(ctx, clientID, clientStore, clientState, payload) return err } diff --git a/modules/light-clients/08-wasm/light_client_module_test.go b/modules/light-clients/08-wasm/light_client_module_test.go index ecac00a24d1..03d07daa791 100644 --- a/modules/light-clients/08-wasm/light_client_module_test.go +++ b/modules/light-clients/08-wasm/light_client_module_test.go @@ -412,8 +412,8 @@ func (suite *WasmTestSuite) TestVerifyMembership() { suite.Require().Nil(payload.VerifyNonMembership) suite.Require().Nil(payload.VerifyUpgradeAndUpdateState) suite.Require().Equal(proofHeight, payload.VerifyMembership.Height) - suite.Require().Equal(path, payload.VerifyMembership.Path) suite.Require().Equal(proof, payload.VerifyMembership.Proof) + suite.Require().Equal(path, payload.VerifyMembership.Path) suite.Require().Equal(value, payload.VerifyMembership.Value) bz, err := json.Marshal(types.EmptyResult{}) @@ -480,7 +480,7 @@ func (suite *WasmTestSuite) TestVerifyMembership() { suite.Require().NoError(err) clientID = endpoint.ClientID - path = commitmenttypes.NewMerklePath("/ibc/key/path") + path = commitmenttypes.NewMerklePath([]byte("/ibc/key/path")) proof = wasmtesting.MockValidProofBz proofHeight = clienttypes.NewHeight(0, 1) value = []byte("value") @@ -540,8 +540,8 @@ func (suite *WasmTestSuite) TestVerifyNonMembership() { suite.Require().Nil(payload.VerifyMembership) suite.Require().Nil(payload.VerifyUpgradeAndUpdateState) suite.Require().Equal(proofHeight, payload.VerifyNonMembership.Height) - suite.Require().Equal(path, payload.VerifyNonMembership.Path) suite.Require().Equal(proof, payload.VerifyNonMembership.Proof) + suite.Require().Equal(path, payload.VerifyNonMembership.Path) bz, err := json.Marshal(types.EmptyResult{}) suite.Require().NoError(err) @@ -567,8 +567,8 @@ func (suite *WasmTestSuite) TestVerifyNonMembership() { suite.Require().Nil(payload.VerifyMembership) suite.Require().Nil(payload.VerifyUpgradeAndUpdateState) suite.Require().Equal(proofHeight, payload.VerifyNonMembership.Height) - suite.Require().Equal(path, payload.VerifyNonMembership.Path) suite.Require().Equal(proof, payload.VerifyNonMembership.Proof) + suite.Require().Equal(path, payload.VerifyNonMembership.Path) bz, err := json.Marshal(types.EmptyResult{}) suite.Require().NoError(err) @@ -647,7 +647,7 @@ func (suite *WasmTestSuite) TestVerifyNonMembership() { suite.Require().NoError(err) clientID = endpoint.ClientID - path = commitmenttypes.NewMerklePath("/ibc/key/path") + path = commitmenttypes.NewMerklePath([]byte("/ibc/key/path")) proof = wasmtesting.MockInvalidProofBz proofHeight = clienttypes.NewHeight(0, 1) diff --git a/modules/light-clients/08-wasm/types/contract_api.go b/modules/light-clients/08-wasm/types/contract_api.go index 217818d439e..1c1383682cc 100644 --- a/modules/light-clients/08-wasm/types/contract_api.go +++ b/modules/light-clients/08-wasm/types/contract_api.go @@ -2,7 +2,7 @@ package types import ( clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" - commitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" + commitmenttypesv2 "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types/v2" ) // InstantiateMessage is the message that is sent to the contract's instantiate entry point. @@ -66,21 +66,21 @@ type UpdateStateOnMisbehaviourMsg struct { // VerifyMembershipMsg is a sudoMsg sent to the contract to verify a membership proof. type VerifyMembershipMsg struct { - Height clienttypes.Height `json:"height"` - DelayTimePeriod uint64 `json:"delay_time_period"` - DelayBlockPeriod uint64 `json:"delay_block_period"` - Proof []byte `json:"proof"` - Path commitmenttypes.MerklePath `json:"path"` - Value []byte `json:"value"` + Height clienttypes.Height `json:"height"` + DelayTimePeriod uint64 `json:"delay_time_period"` + DelayBlockPeriod uint64 `json:"delay_block_period"` + Proof []byte `json:"proof"` + Path commitmenttypesv2.MerklePath `json:"path"` + Value []byte `json:"value"` } // VerifyNonMembershipMsg is a sudoMsg sent to the contract to verify a non-membership proof. type VerifyNonMembershipMsg struct { - Height clienttypes.Height `json:"height"` - DelayTimePeriod uint64 `json:"delay_time_period"` - DelayBlockPeriod uint64 `json:"delay_block_period"` - Proof []byte `json:"proof"` - Path commitmenttypes.MerklePath `json:"path"` + Height clienttypes.Height `json:"height"` + DelayTimePeriod uint64 `json:"delay_time_period"` + DelayBlockPeriod uint64 `json:"delay_block_period"` + Proof []byte `json:"proof"` + Path commitmenttypesv2.MerklePath `json:"path"` } // VerifyUpgradeAndUpdateStateMsg is a sudoMsg sent to the contract to verify an upgrade and update its state. diff --git a/modules/light-clients/09-localhost/client_state.go b/modules/light-clients/09-localhost/client_state.go index 114a6837cc4..b5e7cef2d79 100644 --- a/modules/light-clients/09-localhost/client_state.go +++ b/modules/light-clients/09-localhost/client_state.go @@ -11,6 +11,7 @@ import ( clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" commitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" + commitmenttypesv2 "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types/v2" host "github.com/cosmos/ibc-go/v8/modules/core/24-host" ibcerrors "github.com/cosmos/ibc-go/v8/modules/core/errors" "github.com/cosmos/ibc-go/v8/modules/core/exported" @@ -79,9 +80,9 @@ func (ClientState) VerifyMembership( return errorsmod.Wrapf(commitmenttypes.ErrInvalidProof, "expected %s, got %s", string(SentinelProof), string(proof)) } - merklePath, ok := path.(commitmenttypes.MerklePath) + merklePath, ok := path.(commitmenttypesv2.MerklePath) if !ok { - return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypes.MerklePath{}, path) + return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypesv2.MerklePath{}, path) } if len(merklePath.GetKeyPath()) != 2 { @@ -89,7 +90,7 @@ func (ClientState) VerifyMembership( } // The commitment prefix (eg: "ibc") is omitted when operating on the core IBC store - bz := store.Get([]byte(merklePath.KeyPath[1])) + bz := store.Get(merklePath.KeyPath[1]) if bz == nil { return errorsmod.Wrapf(clienttypes.ErrFailedMembershipVerification, "value not found for path %s", path) } @@ -119,9 +120,9 @@ func (ClientState) VerifyNonMembership( return errorsmod.Wrapf(commitmenttypes.ErrInvalidProof, "expected %s, got %s", string(SentinelProof), string(proof)) } - merklePath, ok := path.(commitmenttypes.MerklePath) + merklePath, ok := path.(commitmenttypesv2.MerklePath) if !ok { - return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypes.MerklePath{}, path) + return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypesv2.MerklePath{}, path) } if len(merklePath.GetKeyPath()) != 2 { @@ -129,7 +130,7 @@ func (ClientState) VerifyNonMembership( } // The commitment prefix (eg: "ibc") is omitted when operating on the core IBC store - if store.Has([]byte(merklePath.KeyPath[1])) { + if store.Has(merklePath.KeyPath[1]) { return errorsmod.Wrapf(clienttypes.ErrFailedNonMembershipVerification, "value found for path %s", path) } diff --git a/modules/light-clients/09-localhost/light_client_module_test.go b/modules/light-clients/09-localhost/light_client_module_test.go index 8ea737a1cd9..e0cf02291d3 100644 --- a/modules/light-clients/09-localhost/light_client_module_test.go +++ b/modules/light-clients/09-localhost/light_client_module_test.go @@ -36,7 +36,7 @@ func (suite *LocalhostTestSuite) TestVerifyMembership() { func() { clientState := suite.chain.GetClientState(exported.LocalhostClientID) - merklePath := commitmenttypes.NewMerklePath(host.FullClientStatePath(exported.LocalhostClientID)) + merklePath := commitmenttypes.NewMerklePath(host.FullClientStateKey(exported.LocalhostClientID)) merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -57,7 +57,7 @@ func (suite *LocalhostTestSuite) TestVerifyMembership() { suite.chain.GetSimApp().GetIBCKeeper().ConnectionKeeper.SetConnection(suite.chain.GetContext(), exported.LocalhostConnectionID, connectionEnd) - merklePath := commitmenttypes.NewMerklePath(host.ConnectionPath(exported.LocalhostConnectionID)) + merklePath := commitmenttypes.NewMerklePath(host.ConnectionKey(exported.LocalhostConnectionID)) merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -79,7 +79,7 @@ func (suite *LocalhostTestSuite) TestVerifyMembership() { suite.chain.GetSimApp().GetIBCKeeper().ChannelKeeper.SetChannel(suite.chain.GetContext(), mock.PortID, ibctesting.FirstChannelID, channel) - merklePath := commitmenttypes.NewMerklePath(host.ChannelPath(mock.PortID, ibctesting.FirstChannelID)) + merklePath := commitmenttypes.NewMerklePath(host.ChannelKey(mock.PortID, ibctesting.FirstChannelID)) merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -94,7 +94,7 @@ func (suite *LocalhostTestSuite) TestVerifyMembership() { nextSeqRecv := uint64(100) suite.chain.GetSimApp().GetIBCKeeper().ChannelKeeper.SetNextSequenceRecv(suite.chain.GetContext(), mock.PortID, ibctesting.FirstChannelID, nextSeqRecv) - merklePath := commitmenttypes.NewMerklePath(host.NextSequenceRecvPath(mock.PortID, ibctesting.FirstChannelID)) + merklePath := commitmenttypes.NewMerklePath(host.NextSequenceRecvKey(mock.PortID, ibctesting.FirstChannelID)) merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -120,7 +120,7 @@ func (suite *LocalhostTestSuite) TestVerifyMembership() { commitmentBz := channeltypes.CommitPacket(suite.chain.Codec, packet) suite.chain.GetSimApp().GetIBCKeeper().ChannelKeeper.SetPacketCommitment(suite.chain.GetContext(), mock.PortID, ibctesting.FirstChannelID, 1, commitmentBz) - merklePath := commitmenttypes.NewMerklePath(host.PacketCommitmentPath(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())) + merklePath := commitmenttypes.NewMerklePath(host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())) merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -134,7 +134,7 @@ func (suite *LocalhostTestSuite) TestVerifyMembership() { func() { suite.chain.GetSimApp().GetIBCKeeper().ChannelKeeper.SetPacketAcknowledgement(suite.chain.GetContext(), mock.PortID, ibctesting.FirstChannelID, 1, ibctesting.MockAcknowledgement) - merklePath := commitmenttypes.NewMerklePath(host.PacketAcknowledgementPath(mock.PortID, ibctesting.FirstChannelID, 1)) + merklePath := commitmenttypes.NewMerklePath(host.PacketAcknowledgementKey(mock.PortID, ibctesting.FirstChannelID, 1)) merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -153,14 +153,14 @@ func (suite *LocalhostTestSuite) TestVerifyMembership() { { "key path has too many elements", func() { - path = commitmenttypes.NewMerklePath("ibc", "test", "key") + path = commitmenttypes.NewMerklePath([]byte("ibc"), []byte("test"), []byte("key")) }, false, }, { "no value found at provided key path", func() { - merklePath := commitmenttypes.NewMerklePath(host.PacketAcknowledgementPath(mock.PortID, ibctesting.FirstChannelID, 100)) + merklePath := commitmenttypes.NewMerklePath(host.PacketAcknowledgementKey(mock.PortID, ibctesting.FirstChannelID, 100)) merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -182,7 +182,7 @@ func (suite *LocalhostTestSuite) TestVerifyMembership() { suite.chain.GetSimApp().GetIBCKeeper().ChannelKeeper.SetChannel(suite.chain.GetContext(), mock.PortID, ibctesting.FirstChannelID, channel) - merklePath := commitmenttypes.NewMerklePath(host.ChannelPath(mock.PortID, ibctesting.FirstChannelID)) + merklePath := commitmenttypes.NewMerklePath(host.ChannelKey(mock.PortID, ibctesting.FirstChannelID)) merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -237,7 +237,7 @@ func (suite *LocalhostTestSuite) TestVerifyNonMembership() { { "success: packet receipt absence verification", func() { - merklePath := commitmenttypes.NewMerklePath(host.PacketReceiptPath(mock.PortID, ibctesting.FirstChannelID, 1)) + merklePath := commitmenttypes.NewMerklePath(host.PacketReceiptKey(mock.PortID, ibctesting.FirstChannelID, 1)) merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -250,7 +250,7 @@ func (suite *LocalhostTestSuite) TestVerifyNonMembership() { func() { suite.chain.GetSimApp().GetIBCKeeper().ChannelKeeper.SetPacketReceipt(suite.chain.GetContext(), mock.PortID, ibctesting.FirstChannelID, 1) - merklePath := commitmenttypes.NewMerklePath(host.PacketReceiptPath(mock.PortID, ibctesting.FirstChannelID, 1)) + merklePath := commitmenttypes.NewMerklePath(host.PacketReceiptKey(mock.PortID, ibctesting.FirstChannelID, 1)) merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath) suite.Require().NoError(err) @@ -268,7 +268,7 @@ func (suite *LocalhostTestSuite) TestVerifyNonMembership() { { "key path has too many elements", func() { - path = commitmenttypes.NewMerklePath("ibc", "test", "key") + path = commitmenttypes.NewMerklePath([]byte("ibc"), []byte("test"), []byte("key")) }, false, }, diff --git a/proto/ibc/core/client/v1/query.proto b/proto/ibc/core/client/v1/query.proto index 905a9188b16..804618dc1df 100644 --- a/proto/ibc/core/client/v1/query.proto +++ b/proto/ibc/core/client/v1/query.proto @@ -7,7 +7,7 @@ option go_package = "github.com/cosmos/ibc-go/v8/modules/core/02-client/types"; import "cosmos/base/query/v1beta1/pagination.proto"; import "cosmos/query/v1/query.proto"; import "ibc/core/client/v1/client.proto"; -import "ibc/core/commitment/v1/commitment.proto"; +import "ibc/core/commitment/v2/commitment.proto"; import "google/protobuf/any.proto"; import "google/api/annotations.proto"; import "gogoproto/gogo.proto"; @@ -225,14 +225,16 @@ message QueryVerifyMembershipRequest { bytes proof = 2; // the height of the commitment root at which the proof is verified. ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false]; - // the commitment key path. - ibc.core.commitment.v1.MerklePath merkle_path = 4 [(gogoproto.nullable) = false]; + // reserved: deprecated field. + reserved 4; // the value which is proven. bytes value = 5; // optional time delay uint64 time_delay = 6; // optional block delay uint64 block_delay = 7; + // the commitment key path. + ibc.core.commitment.v2.MerklePath merkle_path = 8 [(gogoproto.nullable) = false]; } // QueryVerifyMembershipResponse is the response type for the Query/VerifyMembership RPC method diff --git a/proto/ibc/core/commitment/v1/commitment.proto b/proto/ibc/core/commitment/v1/commitment.proto index 3cdaadffd04..8fec9ec45e7 100644 --- a/proto/ibc/core/commitment/v1/commitment.proto +++ b/proto/ibc/core/commitment/v1/commitment.proto @@ -25,8 +25,9 @@ message MerklePrefix { // MerklePath is the path used to verify commitment proofs, which can be an // arbitrary structured object (defined by a commitment type). // MerklePath is represented from root-to-leaf +// Deprecated: Please use commitment/v2 MerklePath instead which supports non UTF-8 key paths. message MerklePath { - repeated bytes key_path = 1; + repeated string key_path = 1; } // MerkleProof is a wrapper type over a chain of CommitmentProofs. diff --git a/proto/ibc/core/commitment/v2/commitment.proto b/proto/ibc/core/commitment/v2/commitment.proto new file mode 100644 index 00000000000..d86c69538a6 --- /dev/null +++ b/proto/ibc/core/commitment/v2/commitment.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +package ibc.core.commitment.v2; + +option go_package = "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types/v2"; + +// MerklePath is the path used to verify commitment proofs, which can be an +// arbitrary structured object (defined by a commitment type). +// MerklePath is represented from root-to-leaf +message MerklePath { + repeated bytes key_path = 1; +} \ No newline at end of file diff --git a/testing/solomachine.go b/testing/solomachine.go index 9d431313457..47cf78a2e21 100644 --- a/testing/solomachine.go +++ b/testing/solomachine.go @@ -20,6 +20,7 @@ import ( connectiontypes "github.com/cosmos/ibc-go/v8/modules/core/03-connection/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" + commitmenttypesv2 "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types/v2" host "github.com/cosmos/ibc-go/v8/modules/core/24-host" "github.com/cosmos/ibc-go/v8/modules/core/exported" solomachine "github.com/cosmos/ibc-go/v8/modules/light-clients/06-solomachine" @@ -200,7 +201,7 @@ func (solo *Solomachine) CreateHeader(newDiversifier string) *solomachine.Header // CreateMisbehaviour constructs testing misbehaviour for the solo machine client // by signing over two different data bytes at the same sequence. func (solo *Solomachine) CreateMisbehaviour() *solomachine.Misbehaviour { - merklePath := commitmenttypes.NewMerklePath(host.FullClientStatePath("counterparty")) + merklePath := commitmenttypes.NewMerklePath(host.FullClientStateKey("counterparty")) path, err := solo.cdc.Marshal(&merklePath) require.NoError(solo.t, err) @@ -229,7 +230,7 @@ func (solo *Solomachine) CreateMisbehaviour() *solomachine.Misbehaviour { // misbehaviour signaturess can have different timestamps solo.Time++ - merklePath = commitmenttypes.NewMerklePath(host.FullConsensusStatePath("counterparty", clienttypes.NewHeight(0, 1))) + merklePath = commitmenttypes.NewMerklePath(host.FullConsensusStateKey("counterparty", clienttypes.NewHeight(0, 1))) path, err = solo.cdc.Marshal(&merklePath) require.NoError(solo.t, err) @@ -657,24 +658,24 @@ func (solo *Solomachine) GenerateReceiptAbsenceProof(packet channeltypes.Packet) } // GetClientStatePath returns the commitment path for the client state. -func (solo *Solomachine) GetClientStatePath(counterpartyClientIdentifier string) commitmenttypes.MerklePath { - path, err := commitmenttypes.ApplyPrefix(prefix, commitmenttypes.NewMerklePath(host.FullClientStatePath(counterpartyClientIdentifier))) +func (solo *Solomachine) GetClientStatePath(counterpartyClientIdentifier string) commitmenttypesv2.MerklePath { + path, err := commitmenttypes.ApplyPrefix(prefix, commitmenttypes.NewMerklePath(host.FullClientStateKey(counterpartyClientIdentifier))) require.NoError(solo.t, err) return path } // GetConsensusStatePath returns the commitment path for the consensus state. -func (solo *Solomachine) GetConsensusStatePath(counterpartyClientIdentifier string, consensusHeight exported.Height) commitmenttypes.MerklePath { - path, err := commitmenttypes.ApplyPrefix(prefix, commitmenttypes.NewMerklePath(host.FullConsensusStatePath(counterpartyClientIdentifier, consensusHeight))) +func (solo *Solomachine) GetConsensusStatePath(counterpartyClientIdentifier string, consensusHeight exported.Height) commitmenttypesv2.MerklePath { + path, err := commitmenttypes.ApplyPrefix(prefix, commitmenttypes.NewMerklePath(host.FullConsensusStateKey(counterpartyClientIdentifier, consensusHeight))) require.NoError(solo.t, err) return path } // GetConnectionStatePath returns the commitment path for the connection state. -func (solo *Solomachine) GetConnectionStatePath(connID string) commitmenttypes.MerklePath { - connectionPath := commitmenttypes.NewMerklePath(host.ConnectionPath(connID)) +func (solo *Solomachine) GetConnectionStatePath(connID string) commitmenttypesv2.MerklePath { + connectionPath := commitmenttypes.NewMerklePath(host.ConnectionKey(connID)) path, err := commitmenttypes.ApplyPrefix(prefix, connectionPath) require.NoError(solo.t, err) @@ -682,8 +683,8 @@ func (solo *Solomachine) GetConnectionStatePath(connID string) commitmenttypes.M } // GetChannelStatePath returns the commitment path for that channel state. -func (solo *Solomachine) GetChannelStatePath(portID, channelID string) commitmenttypes.MerklePath { - channelPath := commitmenttypes.NewMerklePath(host.ChannelPath(portID, channelID)) +func (solo *Solomachine) GetChannelStatePath(portID, channelID string) commitmenttypesv2.MerklePath { + channelPath := commitmenttypes.NewMerklePath(host.ChannelKey(portID, channelID)) path, err := commitmenttypes.ApplyPrefix(prefix, channelPath) require.NoError(solo.t, err) @@ -691,8 +692,8 @@ func (solo *Solomachine) GetChannelStatePath(portID, channelID string) commitmen } // GetPacketCommitmentPath returns the commitment path for a packet commitment. -func (solo *Solomachine) GetPacketCommitmentPath(portID, channelID string, sequence uint64) commitmenttypes.MerklePath { - commitmentPath := commitmenttypes.NewMerklePath(host.PacketCommitmentPath(portID, channelID, sequence)) +func (solo *Solomachine) GetPacketCommitmentPath(portID, channelID string, sequence uint64) commitmenttypesv2.MerklePath { + commitmentPath := commitmenttypes.NewMerklePath(host.PacketCommitmentKey(portID, channelID, sequence)) path, err := commitmenttypes.ApplyPrefix(prefix, commitmentPath) require.NoError(solo.t, err) @@ -700,8 +701,8 @@ func (solo *Solomachine) GetPacketCommitmentPath(portID, channelID string, seque } // GetPacketAcknowledgementPath returns the commitment path for a packet acknowledgement. -func (solo *Solomachine) GetPacketAcknowledgementPath(portID, channelID string, sequence uint64) commitmenttypes.MerklePath { - ackPath := commitmenttypes.NewMerklePath(host.PacketAcknowledgementPath(portID, channelID, sequence)) +func (solo *Solomachine) GetPacketAcknowledgementPath(portID, channelID string, sequence uint64) commitmenttypesv2.MerklePath { + ackPath := commitmenttypes.NewMerklePath(host.PacketAcknowledgementKey(portID, channelID, sequence)) path, err := commitmenttypes.ApplyPrefix(prefix, ackPath) require.NoError(solo.t, err) @@ -710,8 +711,8 @@ func (solo *Solomachine) GetPacketAcknowledgementPath(portID, channelID string, // GetPacketReceiptPath returns the commitment path for a packet receipt // and an absent receipts. -func (solo *Solomachine) GetPacketReceiptPath(portID, channelID string, sequence uint64) commitmenttypes.MerklePath { - receiptPath := commitmenttypes.NewMerklePath(host.PacketReceiptPath(portID, channelID, sequence)) +func (solo *Solomachine) GetPacketReceiptPath(portID, channelID string, sequence uint64) commitmenttypesv2.MerklePath { + receiptPath := commitmenttypes.NewMerklePath(host.PacketReceiptKey(portID, channelID, sequence)) path, err := commitmenttypes.ApplyPrefix(prefix, receiptPath) require.NoError(solo.t, err) @@ -719,8 +720,8 @@ func (solo *Solomachine) GetPacketReceiptPath(portID, channelID string, sequence } // GetNextSequenceRecvPath returns the commitment path for the next sequence recv counter. -func (solo *Solomachine) GetNextSequenceRecvPath(portID, channelID string) commitmenttypes.MerklePath { - nextSequenceRecvPath := commitmenttypes.NewMerklePath(host.NextSequenceRecvPath(portID, channelID)) +func (solo *Solomachine) GetNextSequenceRecvPath(portID, channelID string) commitmenttypesv2.MerklePath { + nextSequenceRecvPath := commitmenttypes.NewMerklePath(host.NextSequenceRecvKey(portID, channelID)) path, err := commitmenttypes.ApplyPrefix(prefix, nextSequenceRecvPath) require.NoError(solo.t, err) From db955c4d86f11841d070b6f070372c71e37b30d2 Mon Sep 17 00:00:00 2001 From: Gjermund Garaba Date: Wed, 3 Jul 2024 16:43:32 +0200 Subject: [PATCH 2/4] feat: make 09-localhost stateless (#6683) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove client state from localhost light client * Initial store upgrade for v9 localhost statelessness * Remove localhost creation and self state proof * Wire up migrations * Update docs for 09-localhost for 09-localhost * lint * refactor: simplify migrations, remove unnecessary iteration over client state * refactor: remove localhost client state from queries * refactor: remove localhost client state, condense localhost impl into single file * rename: MigrateToStatelessLocalhost * lint * Update docs/docs/05-migrations/13-v8-to-v9.md * Update docs/docs/05-migrations/13-v8-to-v9.md Co-authored-by: Damian Nolan * review: docs + linting cleanups * refactor: remove unused func * Update modules/core/02-client/keeper/migrations.go * markdown lint --------- Co-authored-by: Carlos Rodriguez Co-authored-by: Colin Axnér <25233464+colin-axner@users.noreply.github.com> Co-authored-by: Damian Nolan --- .../02-localhost/01-overview.md | 42 ++- .../02-localhost/03-client-state.md | 60 +--- .../02-localhost/05-state-verification.md | 3 +- docs/docs/05-migrations/13-v8-to-v9.md | 8 + e2e/tests/core/02-client/client_test.go | 4 + e2e/tests/transfer/localhost_test.go | 15 - e2e/testsuite/codec.go | 2 - modules/core/02-client/abci.go | 8 - modules/core/02-client/genesis.go | 6 - modules/core/02-client/keeper/client_test.go | 6 +- .../core/02-client/keeper/grpc_query_test.go | 20 +- modules/core/02-client/keeper/keeper.go | 10 - modules/core/02-client/keeper/keeper_test.go | 9 +- modules/core/02-client/keeper/migrations.go | 18 +- .../core/02-client/keeper/migrations_test.go | 17 + .../migrations/v7/expected_keepers.go | 1 - .../core/02-client/migrations/v7/localhost.go | 10 - .../02-client/migrations/v7/localhost_test.go | 26 -- modules/core/module.go | 15 +- modules/core/types/codec.go | 2 - .../08-wasm/keeper/contract_keeper_test.go | 22 +- .../08-wasm/keeper/msg_server_test.go | 5 +- .../09-localhost/client_state.go | 163 --------- .../09-localhost/client_state_test.go | 123 ------- modules/light-clients/09-localhost/codec.go | 16 - .../light-clients/09-localhost/codec_test.go | 49 --- modules/light-clients/09-localhost/keys.go | 12 - .../09-localhost/light_client_module.go | 133 +++++--- .../09-localhost/light_client_module_test.go | 89 +++-- .../09-localhost/localhost.pb.go | 322 ------------------ .../09-localhost/localhost_test.go | 25 -- modules/light-clients/09-localhost/store.go | 30 -- .../lightclients/localhost/v2/localhost.proto | 16 - 33 files changed, 232 insertions(+), 1055 deletions(-) delete mode 100644 modules/core/02-client/migrations/v7/localhost.go delete mode 100644 modules/core/02-client/migrations/v7/localhost_test.go delete mode 100644 modules/light-clients/09-localhost/client_state.go delete mode 100644 modules/light-clients/09-localhost/client_state_test.go delete mode 100644 modules/light-clients/09-localhost/codec.go delete mode 100644 modules/light-clients/09-localhost/codec_test.go delete mode 100644 modules/light-clients/09-localhost/keys.go delete mode 100644 modules/light-clients/09-localhost/localhost.pb.go delete mode 100644 modules/light-clients/09-localhost/localhost_test.go delete mode 100644 modules/light-clients/09-localhost/store.go delete mode 100644 proto/ibc/lightclients/localhost/v2/localhost.proto diff --git a/docs/docs/03-light-clients/02-localhost/01-overview.md b/docs/docs/03-light-clients/02-localhost/01-overview.md index d32ccb01684..c6754004097 100644 --- a/docs/docs/03-light-clients/02-localhost/01-overview.md +++ b/docs/docs/03-light-clients/02-localhost/01-overview.md @@ -14,33 +14,43 @@ slug: /ibc/light-clients/localhost/overview Learn about the 09-localhost light client module. ::: -The 09-localhost light client module implements a localhost loopback client with the ability to send and receive IBC packets to and from the same state machine. +The 09-localhost light client module implements a stateless localhost loopback client with the ability to send and +receive IBC packets to and from the same state machine. ### Context -In a multichain environment, application developers will be used to developing cross-chain applications through IBC. From their point of view, whether or not they are interacting with multiple modules on the same chain or on different chains should not matter. The localhost client module enables a unified interface to interact with different applications on a single chain, using the familiar IBC application layer semantics. +In a multichain environment, application developers will be used to developing cross-chain applications through IBC. +From their point of view, whether or not they are interacting with multiple modules on the same chain or on different +chains should not matter. The localhost client module enables a unified interface to interact with different +applications on a single chain, using the familiar IBC application layer semantics. ### Implementation -There exists a [single sentinel `ClientState`](03-client-state.md) instance with the client identifier `09-localhost`. +There exists a localhost light client module which can be invoked with the client identifier `09-localhost`. The light +client is stateless, so the `ClientState` is constructed on demand when required. -To supplement this, a [sentinel `ConnectionEnd` is stored in core IBC](04-connection.md) state with the connection identifier `connection-localhost`. This enables IBC applications to create channels directly on top of the sentinel connection which leverage the 09-localhost loopback functionality. +To supplement this, a [sentinel `ConnectionEnd` is stored in core IBC](04-connection.md) state with the connection +identifier `connection-localhost`. This enables IBC applications to create channels directly on top of the sentinel +connection which leverage the 09-localhost loopback functionality. -[State verification](05-state-verification.md) for channel state in handshakes or processing packets is reduced in complexity, the `09-localhost` client can simply compare bytes stored under the standardized key paths. +[State verification](05-state-verification.md) for channel state in handshakes or processing packets is reduced in +complexity, the `09-localhost` client can simply compare bytes stored under the standardized key paths. ### Localhost vs *regular* client -The localhost client aims to provide a unified approach to interacting with applications on a single chain, as the IBC application layer provides for cross-chain interactions. To achieve this unified interface though, there are a number of differences under the hood compared to a 'regular' IBC client (excluding `06-solomachine` and `09-localhost` itself). +The localhost client aims to provide a unified approach to interacting with applications on a single chain, as the IBC +application layer provides for cross-chain interactions. To achieve this unified interface though, there are a number of +differences under the hood compared to a 'regular' IBC client (excluding `06-solomachine` and `09-localhost` itself). The table below lists some important differences: -| | Regular client | Localhost | -| -------------------------------------------- | --------------------------------------------------------------------------- | --------- | -| Number of clients | Many instances of a client *type* corresponding to different counterparties | A single sentinel client with the client identifier `09-localhost`| -| Client creation | Relayer (permissionless) | `ClientState` is instantiated in the `InitGenesis` handler of the 02-client submodule in core IBC | -| Client updates | Relayer submits headers using `MsgUpdateClient` | Latest height is updated periodically through the ABCI [`BeginBlock`](https://docs.cosmos.network/v0.47/building-modules/beginblock-endblock) interface of the 02-client submodule in core IBC | -| Number of connections | Many connections, 1 (or more) per client | A single sentinel connection with the connection identifier `connection-localhost` | -| Connection creation | Connection handshake, provided underlying client | Sentinel `ConnectionEnd` is created and set in store in the `InitGenesis` handler of the 03-connection submodule in core IBC | -| Counterparty | Underlying client, representing another chain | Client with identifier `09-localhost` in same chain | -| `VerifyMembership` and `VerifyNonMembership` | Performs proof verification using consensus state roots | Performs state verification using key-value lookups in the core IBC store | -| Integration | Expected to register codec types using the `AppModuleBasic` interface | Registers codec types within the core IBC module | +| | Regular client | Localhost | +|----------------------------------------------|-----------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------| +| Number of clients | Many instances of a client *type* corresponding to different counterparties | A single sentinel client with the client identifier `09-localhost` | +| Client creation | Relayer (permissionless) | Implicitly made available by the 02-client submodule in core IBC | +| Client updates | Relayer submits headers using `MsgUpdateClient` | No client updates are required as the localhost implementation is stateless | +| Number of connections | Many connections, 1 (or more) per client | A single sentinel connection with the connection identifier `connection-localhost` | +| Connection creation | Connection handshake, provided underlying client | Sentinel `ConnectionEnd` is created and set in store in the `InitGenesis` handler of the 03-connection submodule in core IBC | +| Counterparty | Underlying client, representing another chain | Client with identifier `09-localhost` in same chain | +| `VerifyMembership` and `VerifyNonMembership` | Performs proof verification using consensus state roots | Performs state verification using key-value lookups in the core IBC store | +| `ClientState` storage | `ClientState` stored and directly provable with `VerifyMembership` | Stateless, so `ClientState` is not provable directly with `VerifyMembership` | 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 a242a2b649c..3cbdf05442a 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 @@ -5,64 +5,6 @@ sidebar_position: 3 slug: /ibc/light-clients/localhost/client-state --- - # `ClientState` -The 09-localhost `ClientState` maintains a single field used to track the latest sequence of the state machine i.e. the height of the blockchain. - -```go -type ClientState struct { - // the latest height of the blockchain - LatestHeight clienttypes.Height -} -``` - -The 09-localhost `ClientState` is instantiated in the `InitGenesis` handler of the 02-client submodule in core IBC. -It calls `CreateLocalhostClient`, declaring a new `ClientState` and initializing it with its own client prefixed store. - -```go -func (k Keeper) CreateLocalhostClient(ctx sdk.Context) error { - clientModule, found := k.router.GetRoute(exported.LocalhostClientID) - if !found { - return errorsmod.Wrap(types.ErrRouteNotFound, exported.LocalhostClientID) - } - - return clientModule.Initialize(ctx, exported.LocalhostClientID, nil, nil) -} -``` - -It is possible to disable the localhost client by removing the `09-localhost` entry from the `allowed_clients` list through governance. - -## Client updates - -The latest height is updated periodically through the ABCI [`BeginBlock`](https://docs.cosmos.network/v0.47/building-modules/beginblock-endblock) interface of the 02-client submodule in core IBC. - -[See `BeginBlocker` in abci.go.](https://github.com/cosmos/ibc-go/blob/v8.1.1/modules/core/02-client/abci.go#L12) - -```go -func BeginBlocker(ctx sdk.Context, k keeper.Keeper) { - // ... - - if clientState, found := k.GetClientState(ctx, exported.Localhost); found { - if k.GetClientStatus(ctx, clientState, exported.Localhost) == exported.Active { - k.UpdateLocalhostClient(ctx, clientState) - } - } -} -``` - -The above calls into the 09-localhost `UpdateState` method of the `ClientState` . -It retrieves the current block height from the application context and sets the `LatestHeight` of the 09-localhost client. - -```go -func (cs ClientState) UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg exported.ClientMessage) []exported.Height { - height := clienttypes.GetSelfHeight(ctx) - cs.LatestHeight = height - - clientStore.Set(host.ClientStateKey(), clienttypes.MustMarshalClientState(cdc, &cs)) - - return []exported.Height{height} -} -``` - -Note that the 09-localhost `ClientState` is not updated through the 02-client interface leveraged by conventional IBC light clients. +The 09-localhost client is stateless and has no types. 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 eb92f2899e9..82d10d6ff40 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 @@ -5,7 +5,6 @@ sidebar_position: 5 slug: /ibc/light-clients/localhost/state-verification --- - # State verification 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. @@ -20,3 +19,5 @@ The 09-localhost light client module defines a `SentinelProof` as a single byte. ```go var SentinelProof = []byte{0x01} ``` + +The `ClientState` of `09-localhost` is stateless, so it is not directly provable with `VerifyMembership` or `VerifyNonMembership`. diff --git a/docs/docs/05-migrations/13-v8-to-v9.md b/docs/docs/05-migrations/13-v8-to-v9.md index 02c205f74e8..3a5c2242aba 100644 --- a/docs/docs/05-migrations/13-v8-to-v9.md +++ b/docs/docs/05-migrations/13-v8-to-v9.md @@ -102,6 +102,7 @@ func NewMsgModuleQuerySafe( - The utility function `QueryLatestConsensusState` of `04-channel` CLI has been removed. - `UnmarshalPacketData` now takes in the context, portID, and channelID. This allows the packet data to be unmarshaled based on the channel version. - `Router` reference has been removed from IBC core keeper: [#6138](https://github.com/cosmos/ibc-go/pull/6138). Please use `PortKeeper.Router` instead. +- The function `CreateLocalhostClient` has been removed. The localhost client is now stateless. ### 02-client @@ -185,3 +186,10 @@ The `IterateConsensusMetadata` function has been removed. - The `VerifyMembershipMsg` and `VerifyNonMembershipMsg` payloads for `SudoMsg` have been extended to include a new field, `MerklePath`. The existing `Path` field will remain the same. The new `MerklePath` field is used if and only if the provided key path contains non-utf8 encoded symbols, and as a result will encode the JSON field `merkle_path` as a base64 encoded bytestring. See [23-commitment](#23-commitment). - The `ExportMetadataMsg` struct has been removed and is no longer required for contracts to implement. Core IBC will handle exporting all key/value's written to the store by a light client contract. - The `ZeroCustomFields` interface function has been removed from the `ClientState` interface. Core IBC only used this function to set tendermint client states when scheduling an IBC software upgrade. The interface function has been replaced by a type assertion. + +### 09-localhost + +The `09-localhost` light client has been made stateless and will no longer update the client on every block. The `ClientState` is constructed on demand when required. +The `ClientState` itself is therefore no longer provable direcly with `VerifyMembership` or `VerifyNonMembership`. + +Previously stored client state data is pruned automatically on IBC module store migration from `ConsensusVersion` 6 to 7. diff --git a/e2e/tests/core/02-client/client_test.go b/e2e/tests/core/02-client/client_test.go index cb1da13cc7c..ae041a3b4cb 100644 --- a/e2e/tests/core/02-client/client_test.go +++ b/e2e/tests/core/02-client/client_test.go @@ -487,6 +487,10 @@ func (s *ClientTestSuite) TestAllowedClientsParam() { status, err := query.ClientStatus(ctx, chainA, ibctesting.FirstClientID) s.Require().NoError(err) s.Require().Equal(ibcexported.Unauthorized.String(), status) + + status, err = query.ClientStatus(ctx, chainA, ibcexported.Localhost) + s.Require().NoError(err) + s.Require().Equal(ibcexported.Unauthorized.String(), status) }) } diff --git a/e2e/tests/transfer/localhost_test.go b/e2e/tests/transfer/localhost_test.go index c24a4d19425..982f05a6b68 100644 --- a/e2e/tests/transfer/localhost_test.go +++ b/e2e/tests/transfer/localhost_test.go @@ -53,21 +53,6 @@ func (s *LocalhostTransferTestSuite) TestMsgTransfer_Localhost() { s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA), "failed to wait for blocks") - t.Run("verify begin blocker was executed", func(t *testing.T) { - cs, err := query.ClientState(ctx, chainA, exported.LocalhostClientID) - s.Require().NoError(err) - - localhostClientState, ok := cs.(*localhost.ClientState) - s.Require().True(ok) - originalHeight := localhostClientState.LatestHeight - - s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA), "failed to wait for blocks") - - cs, err = query.ClientState(ctx, chainA, exported.LocalhostClientID) - s.Require().NoError(err) - s.Require().True(cs.(*localhost.ClientState).LatestHeight.GT(originalHeight), "client state height was not incremented") - }) - t.Run("channel open init localhost", func(t *testing.T) { msgChanOpenInit := channeltypes.NewMsgChannelOpenInit( transfertypes.PortID, channelA.Version, diff --git a/e2e/testsuite/codec.go b/e2e/testsuite/codec.go index 42f790a78e6..5fabcf48671 100644 --- a/e2e/testsuite/codec.go +++ b/e2e/testsuite/codec.go @@ -34,7 +34,6 @@ import ( channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" solomachine "github.com/cosmos/ibc-go/v8/modules/light-clients/06-solomachine" ibctmtypes "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" - localhost "github.com/cosmos/ibc-go/v8/modules/light-clients/09-localhost" ibctesting "github.com/cosmos/ibc-go/v8/testing" simappparams "github.com/cosmos/ibc-go/v8/testing/simapp/params" ) @@ -76,7 +75,6 @@ func codecAndEncodingConfig() (*codec.ProtoCodec, simappparams.EncodingConfig) { channeltypes.RegisterInterfaces(cfg.InterfaceRegistry) connectiontypes.RegisterInterfaces(cfg.InterfaceRegistry) ibctmtypes.RegisterInterfaces(cfg.InterfaceRegistry) - localhost.RegisterInterfaces(cfg.InterfaceRegistry) wasmtypes.RegisterInterfaces(cfg.InterfaceRegistry) // all other types diff --git a/modules/core/02-client/abci.go b/modules/core/02-client/abci.go index c8d36b414ec..c7ebd8bcfd7 100644 --- a/modules/core/02-client/abci.go +++ b/modules/core/02-client/abci.go @@ -5,7 +5,6 @@ import ( "github.com/cosmos/ibc-go/v8/modules/core/02-client/keeper" "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" - "github.com/cosmos/ibc-go/v8/modules/core/exported" ibctm "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" ) @@ -33,11 +32,4 @@ func BeginBlocker(ctx sdk.Context, k *keeper.Keeper) { keeper.EmitUpgradeChainEvent(ctx, plan.Height) } } - - // update the localhost client with the latest block height if it is active. - if clientState, found := k.GetClientState(ctx, exported.Localhost); found { - if k.GetClientStatus(ctx, exported.LocalhostClientID) == exported.Active { - k.UpdateLocalhostClient(ctx, clientState) - } - } } diff --git a/modules/core/02-client/genesis.go b/modules/core/02-client/genesis.go index d89cc5073ed..1e72b363554 100644 --- a/modules/core/02-client/genesis.go +++ b/modules/core/02-client/genesis.go @@ -50,12 +50,6 @@ func InitGenesis(ctx sdk.Context, k *keeper.Keeper, gs types.GenesisState) { } k.SetNextClientSequence(ctx, gs.NextClientSequence) - - // if the localhost already exists in state (included in the genesis file), - // it must be overwritten to ensure its stored height equals the context block height - if err := k.CreateLocalhostClient(ctx); err != nil { - panic(fmt.Errorf("failed to initialise localhost client: %s", err.Error())) - } } // ExportGenesis returns the ibc client submodule's exported genesis. diff --git a/modules/core/02-client/keeper/client_test.go b/modules/core/02-client/keeper/client_test.go index 51939164938..275567c195f 100644 --- a/modules/core/02-client/keeper/client_test.go +++ b/modules/core/02-client/keeper/client_test.go @@ -14,7 +14,6 @@ import ( "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" - localhost "github.com/cosmos/ibc-go/v8/modules/light-clients/09-localhost" ibctesting "github.com/cosmos/ibc-go/v8/testing" ) @@ -64,10 +63,7 @@ func (suite *KeeperTestSuite) TestCreateClient() { }, { "failure: 09-localhost client type not supported", - func() { - lhClientState := localhost.NewClientState(clienttypes.GetSelfHeight(suite.chainA.GetContext())) - clientState = suite.chainA.App.AppCodec().MustMarshal(lhClientState) - }, + func() {}, exported.Localhost, false, }, diff --git a/modules/core/02-client/keeper/grpc_query_test.go b/modules/core/02-client/keeper/grpc_query_test.go index 132332809f9..c231423fcb7 100644 --- a/modules/core/02-client/keeper/grpc_query_test.go +++ b/modules/core/02-client/keeper/grpc_query_test.go @@ -119,26 +119,11 @@ func (suite *KeeperTestSuite) TestQueryClientStates() { { "empty pagination", func() { - localhost := types.NewIdentifiedClientState(exported.LocalhostClientID, suite.chainA.GetClientState(exported.LocalhostClientID)) - expClientStates = types.IdentifiedClientStates{localhost} + expClientStates = nil req = &types.QueryClientStatesRequest{} }, true, }, - { - "success, only localhost", - func() { - localhost := types.NewIdentifiedClientState(exported.LocalhostClientID, suite.chainA.GetClientState(exported.LocalhostClientID)) - expClientStates = types.IdentifiedClientStates{localhost} - req = &types.QueryClientStatesRequest{ - Pagination: &query.PageRequest{ - Limit: 3, - CountTotal: true, - }, - } - }, - true, - }, { "success", func() { @@ -151,12 +136,11 @@ func (suite *KeeperTestSuite) TestQueryClientStates() { clientStateA1 := path1.EndpointA.GetClientState() clientStateA2 := path2.EndpointA.GetClientState() - localhost := types.NewIdentifiedClientState(exported.LocalhostClientID, suite.chainA.GetClientState(exported.LocalhostClientID)) idcs := types.NewIdentifiedClientState(path1.EndpointA.ClientID, clientStateA1) idcs2 := types.NewIdentifiedClientState(path2.EndpointA.ClientID, clientStateA2) // order is sorted by client id - expClientStates = types.IdentifiedClientStates{localhost, idcs, idcs2}.Sort() + expClientStates = types.IdentifiedClientStates{idcs, idcs2}.Sort() req = &types.QueryClientStatesRequest{ Pagination: &query.PageRequest{ Limit: 20, diff --git a/modules/core/02-client/keeper/keeper.go b/modules/core/02-client/keeper/keeper.go index d30d50554e4..cb3097dbb89 100644 --- a/modules/core/02-client/keeper/keeper.go +++ b/modules/core/02-client/keeper/keeper.go @@ -68,16 +68,6 @@ func (k *Keeper) Route(clientID string) (exported.LightClientModule, bool) { return k.router.GetRoute(clientID) } -// CreateLocalhostClient initialises the 09-localhost client state and sets it in state. -func (k *Keeper) CreateLocalhostClient(ctx sdk.Context) error { - clientModule, found := k.router.GetRoute(exported.LocalhostClientID) - if !found { - return errorsmod.Wrap(types.ErrRouteNotFound, exported.LocalhostClientID) - } - - return clientModule.Initialize(ctx, exported.LocalhostClientID, nil, nil) -} - // UpdateLocalhostClient updates the 09-localhost client to the latest block height and chain ID. func (k *Keeper) UpdateLocalhostClient(ctx sdk.Context, clientState exported.ClientState) []exported.Height { clientModule, found := k.router.GetRoute(exported.LocalhostClientID) diff --git a/modules/core/02-client/keeper/keeper_test.go b/modules/core/02-client/keeper/keeper_test.go index 739d735ea54..3d8eb4c3a90 100644 --- a/modules/core/02-client/keeper/keeper_test.go +++ b/modules/core/02-client/keeper/keeper_test.go @@ -26,7 +26,6 @@ import ( host "github.com/cosmos/ibc-go/v8/modules/core/24-host" "github.com/cosmos/ibc-go/v8/modules/core/exported" ibctm "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" - localhost "github.com/cosmos/ibc-go/v8/modules/light-clients/09-localhost" ibctesting "github.com/cosmos/ibc-go/v8/testing" "github.com/cosmos/ibc-go/v8/testing/simapp" ) @@ -143,10 +142,9 @@ func (suite *KeeperTestSuite) TestSetClientConsensusState() { func (suite *KeeperTestSuite) TestGetAllGenesisClients() { clientIDs := []string{ - exported.LocalhostClientID, testClientID2, testClientID3, testClientID, + testClientID2, testClientID3, testClientID, } expClients := []exported.ClientState{ - localhost.NewClientState(types.GetSelfHeight(suite.chainA.GetContext())), ibctm.NewClientState(testChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath), ibctm.NewClientState(testChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath), ibctm.NewClientState(testChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath), @@ -305,10 +303,7 @@ func (suite *KeeperTestSuite) TestIterateClientStates() { "all clientIDs", nil, func() []string { - allClientIDs := []string{exported.LocalhostClientID} - allClientIDs = append(allClientIDs, expSMClientIDs...) - allClientIDs = append(allClientIDs, expTMClientIDs...) - return allClientIDs + return append(expSMClientIDs, expTMClientIDs...) }, }, { diff --git a/modules/core/02-client/keeper/migrations.go b/modules/core/02-client/keeper/migrations.go index cefdd5da0fc..3dd32bbbf46 100644 --- a/modules/core/02-client/keeper/migrations.go +++ b/modules/core/02-client/keeper/migrations.go @@ -5,6 +5,8 @@ import ( "github.com/cosmos/ibc-go/v8/modules/core/02-client/migrations/v7" "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" + host "github.com/cosmos/ibc-go/v8/modules/core/24-host" + "github.com/cosmos/ibc-go/v8/modules/core/exported" ) // Migrator is a struct for handling in-place store migrations. @@ -27,12 +29,6 @@ func (m Migrator) Migrate2to3(ctx sdk.Context) error { return v7.MigrateStore(ctx, m.keeper.storeKey, m.keeper.cdc, m.keeper) } -// Migrate3to4 migrates from consensus version 3 to 4. -// This migration enables the localhost client. -func (m Migrator) Migrate3to4(ctx sdk.Context) error { - return v7.MigrateLocalhostClient(ctx, m.keeper) -} - // MigrateParams migrates from consensus version 4 to 5. // This migration takes the parameters that are currently stored and managed by x/params // and stores them directly in the ibc module's state. @@ -47,3 +43,13 @@ func (m Migrator) MigrateParams(ctx sdk.Context) error { m.keeper.Logger(ctx).Info("successfully migrated client to self-manage params") return nil } + +// MigrateToStatelessLocalhost deletes the localhost client state. The localhost +// implementation is now stateless. +func (m Migrator) MigrateToStatelessLocalhost(ctx sdk.Context) error { + clientStore := m.keeper.ClientStore(ctx, exported.LocalhostClientID) + + // delete the client state + clientStore.Delete(host.ClientStateKey()) + return nil +} diff --git a/modules/core/02-client/keeper/migrations_test.go b/modules/core/02-client/keeper/migrations_test.go index 7bdd26b8a12..7b9370307bf 100644 --- a/modules/core/02-client/keeper/migrations_test.go +++ b/modules/core/02-client/keeper/migrations_test.go @@ -3,6 +3,7 @@ package keeper_test import ( "github.com/cosmos/ibc-go/v8/modules/core/02-client/keeper" "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" + host "github.com/cosmos/ibc-go/v8/modules/core/24-host" ibcexported "github.com/cosmos/ibc-go/v8/modules/core/exported" ) @@ -41,3 +42,19 @@ func (suite *KeeperTestSuite) TestMigrateParams() { }) } } + +func (suite *KeeperTestSuite) TestMigrateToStatelessLocalhost() { + // set localhost in state + clientStore := suite.chainA.GetSimApp().IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), ibcexported.LocalhostClientID) + clientStore.Set(host.ClientStateKey(), []byte("clientState")) + + m := keeper.NewMigrator(suite.chainA.GetSimApp().IBCKeeper.ClientKeeper) + err := m.MigrateToStatelessLocalhost(suite.chainA.GetContext()) + suite.Require().NoError(err) + suite.Require().False(clientStore.Has(host.ClientStateKey())) + + // rerun migration on no localhost set + err = m.MigrateToStatelessLocalhost(suite.chainA.GetContext()) + suite.Require().NoError(err) + suite.Require().False(clientStore.Has(host.ClientStateKey())) +} diff --git a/modules/core/02-client/migrations/v7/expected_keepers.go b/modules/core/02-client/migrations/v7/expected_keepers.go index 4a73d42d20f..0485b120558 100644 --- a/modules/core/02-client/migrations/v7/expected_keepers.go +++ b/modules/core/02-client/migrations/v7/expected_keepers.go @@ -13,5 +13,4 @@ type ClientKeeper interface { GetClientState(ctx sdk.Context, clientID string) (exported.ClientState, bool) SetClientState(ctx sdk.Context, clientID string, clientState exported.ClientState) ClientStore(ctx sdk.Context, clientID string) storetypes.KVStore - CreateLocalhostClient(ctx sdk.Context) error } diff --git a/modules/core/02-client/migrations/v7/localhost.go b/modules/core/02-client/migrations/v7/localhost.go deleted file mode 100644 index 49709b9db9f..00000000000 --- a/modules/core/02-client/migrations/v7/localhost.go +++ /dev/null @@ -1,10 +0,0 @@ -package v7 - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// MigrateLocalhostClient initialises the 09-localhost client state and sets it in state. -func MigrateLocalhostClient(ctx sdk.Context, clientKeeper ClientKeeper) error { - return clientKeeper.CreateLocalhostClient(ctx) -} diff --git a/modules/core/02-client/migrations/v7/localhost_test.go b/modules/core/02-client/migrations/v7/localhost_test.go deleted file mode 100644 index 1a6d657477c..00000000000 --- a/modules/core/02-client/migrations/v7/localhost_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package v7_test - -import ( - "github.com/cosmos/ibc-go/v8/modules/core/02-client/migrations/v7" - host "github.com/cosmos/ibc-go/v8/modules/core/24-host" - "github.com/cosmos/ibc-go/v8/modules/core/exported" -) - -func (suite *MigrationsV7TestSuite) TestMigrateLocalhostClient() { - suite.SetupTest() - - // note: explicitly remove the localhost client before running migration handler - clientStore := suite.chainA.GetSimApp().GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), exported.LocalhostClientID) - clientStore.Delete(host.ClientStateKey()) - - clientState, found := suite.chainA.GetSimApp().GetIBCKeeper().ClientKeeper.GetClientState(suite.chainA.GetContext(), exported.LocalhostClientID) - suite.Require().False(found) - suite.Require().Nil(clientState) - - err := v7.MigrateLocalhostClient(suite.chainA.GetContext(), suite.chainA.GetSimApp().GetIBCKeeper().ClientKeeper) - suite.Require().NoError(err) - - clientState, found = suite.chainA.GetSimApp().GetIBCKeeper().ClientKeeper.GetClientState(suite.chainA.GetContext(), exported.LocalhostClientID) - suite.Require().True(found) - suite.Require().NotNil(clientState) -} diff --git a/modules/core/module.go b/modules/core/module.go index e7f6ebd4a94..9a3fc9d9084 100644 --- a/modules/core/module.go +++ b/modules/core/module.go @@ -140,11 +140,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { connectionMigrator := connectionkeeper.NewMigrator(am.keeper.ConnectionKeeper) if err := cfg.RegisterMigration(exported.ModuleName, 3, func(ctx sdk.Context) error { - if err := connectionMigrator.Migrate3to4(ctx); err != nil { - return err - } - - return clientMigrator.Migrate3to4(ctx) + return connectionMigrator.Migrate3to4(ctx) }); err != nil { panic(err) } @@ -160,8 +156,11 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { } channelMigrator := channelkeeper.NewMigrator(am.keeper.ChannelKeeper) - err := cfg.RegisterMigration(exported.ModuleName, 5, channelMigrator.MigrateParams) - if err != nil { + if err := cfg.RegisterMigration(exported.ModuleName, 5, channelMigrator.MigrateParams); err != nil { + panic(err) + } + + if err := cfg.RegisterMigration(exported.ModuleName, 6, clientMigrator.MigrateToStatelessLocalhost); err != nil { panic(err) } } @@ -184,7 +183,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw } // ConsensusVersion implements AppModule/ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 6 } +func (AppModule) ConsensusVersion() uint64 { return 7 } // BeginBlock returns the begin blocker for the ibc module. func (am AppModule) BeginBlock(ctx context.Context) error { diff --git a/modules/core/types/codec.go b/modules/core/types/codec.go index 57b4018adb8..1216ab22864 100644 --- a/modules/core/types/codec.go +++ b/modules/core/types/codec.go @@ -7,7 +7,6 @@ import ( connectiontypes "github.com/cosmos/ibc-go/v8/modules/core/03-connection/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" - localhost "github.com/cosmos/ibc-go/v8/modules/light-clients/09-localhost" ) // RegisterInterfaces registers ibc types against interfaces using the global InterfaceRegistry. @@ -17,5 +16,4 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { connectiontypes.RegisterInterfaces(registry) channeltypes.RegisterInterfaces(registry) commitmenttypes.RegisterInterfaces(registry) - localhost.RegisterInterfaces(registry) } diff --git a/modules/light-clients/08-wasm/keeper/contract_keeper_test.go b/modules/light-clients/08-wasm/keeper/contract_keeper_test.go index b7b59bbcdec..35517fa1536 100644 --- a/modules/light-clients/08-wasm/keeper/contract_keeper_test.go +++ b/modules/light-clients/08-wasm/keeper/contract_keeper_test.go @@ -12,7 +12,6 @@ import ( host "github.com/cosmos/ibc-go/v8/modules/core/24-host" "github.com/cosmos/ibc-go/v8/modules/core/exported" ibctm "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" - localhost "github.com/cosmos/ibc-go/v8/modules/light-clients/09-localhost" ) func (suite *KeeperTestSuite) TestWasmInstantiate() { @@ -105,8 +104,7 @@ func (suite *KeeperTestSuite) TestWasmInstantiate() { "failure: change clientstate type", func() { suite.mockVM.InstantiateFn = func(_ wasmvm.Checksum, _ wasmvmtypes.Env, _ wasmvmtypes.MessageInfo, _ []byte, store wasmvm.KVStore, _ wasmvm.GoAPI, _ wasmvm.Querier, _ wasmvm.GasMeter, _ uint64, _ wasmvmtypes.UFraction) (*wasmvmtypes.ContractResult, uint64, error) { - newClientState := localhost.NewClientState(clienttypes.NewHeight(1, 1)) - store.Set(host.ClientStateKey(), clienttypes.MustMarshalClientState(suite.chainA.App.AppCodec(), newClientState)) + store.Set(host.ClientStateKey(), []byte("changed client state")) data, err := json.Marshal(types.EmptyResult{}) suite.Require().NoError(err) @@ -269,8 +267,7 @@ func (suite *KeeperTestSuite) TestWasmMigrate() { "failure: change clientstate type", func() { suite.mockVM.MigrateFn = func(_ wasmvm.Checksum, _ wasmvmtypes.Env, _ []byte, store wasmvm.KVStore, _ wasmvm.GoAPI, _ wasmvm.Querier, _ wasmvm.GasMeter, _ uint64, _ wasmvmtypes.UFraction) (*wasmvmtypes.ContractResult, uint64, error) { - newClientState := localhost.NewClientState(clienttypes.NewHeight(1, 1)) - store.Set(host.ClientStateKey(), clienttypes.MustMarshalClientState(suite.chainA.App.AppCodec(), newClientState)) + store.Set(host.ClientStateKey(), []byte("changed client state")) data, err := json.Marshal(types.EmptyResult{}) suite.Require().NoError(err) @@ -486,21 +483,6 @@ func (suite *KeeperTestSuite) TestWasmSudo() { }, types.ErrWasmAttributesNotAllowed, }, - { - "failure: invalid clientstate type", - func() { - suite.mockVM.RegisterSudoCallback(types.UpdateStateMsg{}, func(_ wasmvm.Checksum, _ wasmvmtypes.Env, _ []byte, store wasmvm.KVStore, _ wasmvm.GoAPI, _ wasmvm.Querier, _ wasmvm.GasMeter, _ uint64, _ wasmvmtypes.UFraction) (*wasmvmtypes.ContractResult, uint64, error) { - newClientState := localhost.NewClientState(clienttypes.NewHeight(1, 1)) - store.Set(host.ClientStateKey(), clienttypes.MustMarshalClientState(suite.chainA.App.AppCodec(), newClientState)) - - resp, err := json.Marshal(types.UpdateStateResult{}) - suite.Require().NoError(err) - - return &wasmvmtypes.ContractResult{Ok: &wasmvmtypes.Response{Data: resp}}, wasmtesting.DefaultGasUsed, nil - }) - }, - types.ErrWasmInvalidContractModification, - }, { "failure: unmarshallable clientstate bytes", func() { diff --git a/modules/light-clients/08-wasm/keeper/msg_server_test.go b/modules/light-clients/08-wasm/keeper/msg_server_test.go index cb17191c69f..def0351b2a3 100644 --- a/modules/light-clients/08-wasm/keeper/msg_server_test.go +++ b/modules/light-clients/08-wasm/keeper/msg_server_test.go @@ -17,7 +17,6 @@ import ( clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" host "github.com/cosmos/ibc-go/v8/modules/core/24-host" ibcerrors "github.com/cosmos/ibc-go/v8/modules/core/errors" - localhost "github.com/cosmos/ibc-go/v8/modules/light-clients/09-localhost" ibctesting "github.com/cosmos/ibc-go/v8/testing" ) @@ -249,9 +248,7 @@ func (suite *KeeperTestSuite) TestMsgMigrateContract() { suite.mockVM.MigrateFn = func(_ wasmvm.Checksum, _ wasmvmtypes.Env, _ []byte, store wasmvm.KVStore, _ wasmvm.GoAPI, _ wasmvm.Querier, _ wasmvm.GasMeter, _ uint64, _ wasmvmtypes.UFraction) (*wasmvmtypes.ContractResult, uint64, error) { // the checksum written in here will be overwritten - newClientState := localhost.NewClientState(clienttypes.NewHeight(1, 1)) - - store.Set(host.ClientStateKey(), clienttypes.MustMarshalClientState(suite.chainA.App.AppCodec(), newClientState)) + store.Set(host.ClientStateKey(), []byte("changed client state")) data, err := json.Marshal(types.EmptyResult{}) suite.Require().NoError(err) diff --git a/modules/light-clients/09-localhost/client_state.go b/modules/light-clients/09-localhost/client_state.go deleted file mode 100644 index b5e7cef2d79..00000000000 --- a/modules/light-clients/09-localhost/client_state.go +++ /dev/null @@ -1,163 +0,0 @@ -package localhost - -import ( - "bytes" - - errorsmod "cosmossdk.io/errors" - storetypes "cosmossdk.io/store/types" - - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/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" - commitmenttypesv2 "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types/v2" - host "github.com/cosmos/ibc-go/v8/modules/core/24-host" - ibcerrors "github.com/cosmos/ibc-go/v8/modules/core/errors" - "github.com/cosmos/ibc-go/v8/modules/core/exported" -) - -var _ exported.ClientState = (*ClientState)(nil) - -// NewClientState creates a new 09-localhost ClientState instance. -func NewClientState(height clienttypes.Height) *ClientState { - return &ClientState{ - LatestHeight: height, - } -} - -// ClientType returns the 09-localhost client type. -func (ClientState) ClientType() string { - return exported.Localhost -} - -// Validate performs a basic validation of the client state fields. -func (cs ClientState) Validate() error { - if cs.LatestHeight.RevisionHeight == 0 { - return errorsmod.Wrapf(ibcerrors.ErrInvalidHeight, "local revision height cannot be zero") - } - - return nil -} - -// Initialize ensures that initial consensus state for localhost is nil. -func (ClientState) Initialize(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, consState exported.ConsensusState) error { - if consState != nil { - return errorsmod.Wrap(clienttypes.ErrInvalidConsensus, "initial consensus state for localhost must be nil.") - } - - clientState := ClientState{ - LatestHeight: clienttypes.GetSelfHeight(ctx), - } - - clientStore.Set(host.ClientStateKey(), clienttypes.MustMarshalClientState(cdc, &clientState)) - - return nil -} - -// GetTimestampAtHeight returns the current block time retrieved from the application context. The localhost client does not store consensus states and thus -// cannot provide a timestamp for the provided height. -func (ClientState) GetTimestampAtHeight(ctx sdk.Context, _ storetypes.KVStore, _ codec.BinaryCodec, _ exported.Height) (uint64, error) { - return uint64(ctx.BlockTime().UnixNano()), nil -} - -// VerifyMembership is a generic proof verification method which verifies the existence of a given key and value within the IBC store. -// The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24). -// The caller must provide the full IBC store. -func (ClientState) VerifyMembership( - ctx sdk.Context, - store storetypes.KVStore, - _ codec.BinaryCodec, - _ exported.Height, - _ uint64, - _ uint64, - proof []byte, - path exported.Path, - value []byte, -) error { - // ensure the proof provided is the expected sentinel localhost client proof - if !bytes.Equal(proof, SentinelProof) { - return errorsmod.Wrapf(commitmenttypes.ErrInvalidProof, "expected %s, got %s", string(SentinelProof), string(proof)) - } - - merklePath, ok := path.(commitmenttypesv2.MerklePath) - if !ok { - return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypesv2.MerklePath{}, path) - } - - if len(merklePath.GetKeyPath()) != 2 { - return errorsmod.Wrapf(host.ErrInvalidPath, "path must be of length 2: %s", merklePath.GetKeyPath()) - } - - // The commitment prefix (eg: "ibc") is omitted when operating on the core IBC store - bz := store.Get(merklePath.KeyPath[1]) - if bz == nil { - return errorsmod.Wrapf(clienttypes.ErrFailedMembershipVerification, "value not found for path %s", path) - } - - if !bytes.Equal(bz, value) { - return errorsmod.Wrapf(clienttypes.ErrFailedMembershipVerification, "value provided does not equal value stored at path: %s", path) - } - - return nil -} - -// VerifyNonMembership is a generic proof verification method which verifies the absence of a given CommitmentPath within the IBC store. -// The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24). -// The caller must provide the full IBC store. -func (ClientState) VerifyNonMembership( - ctx sdk.Context, - store storetypes.KVStore, - _ codec.BinaryCodec, - _ exported.Height, - _ uint64, - _ uint64, - proof []byte, - path exported.Path, -) error { - // ensure the proof provided is the expected sentinel localhost client proof - if !bytes.Equal(proof, SentinelProof) { - return errorsmod.Wrapf(commitmenttypes.ErrInvalidProof, "expected %s, got %s", string(SentinelProof), string(proof)) - } - - merklePath, ok := path.(commitmenttypesv2.MerklePath) - if !ok { - return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypesv2.MerklePath{}, path) - } - - if len(merklePath.GetKeyPath()) != 2 { - return errorsmod.Wrapf(host.ErrInvalidPath, "path must be of length 2: %s", merklePath.GetKeyPath()) - } - - // The commitment prefix (eg: "ibc") is omitted when operating on the core IBC store - if store.Has(merklePath.KeyPath[1]) { - return errorsmod.Wrapf(clienttypes.ErrFailedNonMembershipVerification, "value found for path %s", path) - } - - return nil -} - -// VerifyClientMessage is unsupported by the 09-localhost client type and returns an error. -func (ClientState) VerifyClientMessage(_ sdk.Context, _ codec.BinaryCodec, _ storetypes.KVStore, _ exported.ClientMessage) error { - return errorsmod.Wrap(clienttypes.ErrUpdateClientFailed, "client message verification is unsupported by the localhost client") -} - -// CheckForMisbehaviour is unsupported by the 09-localhost client type and performs a no-op, returning false. -func (ClientState) CheckForMisbehaviour(_ sdk.Context, _ codec.BinaryCodec, _ storetypes.KVStore, _ exported.ClientMessage) bool { - return false -} - -// UpdateStateOnMisbehaviour is unsupported by the 09-localhost client type and performs a no-op. -func (ClientState) UpdateStateOnMisbehaviour(_ sdk.Context, _ codec.BinaryCodec, _ storetypes.KVStore, _ exported.ClientMessage) { -} - -// UpdateState updates and stores as necessary any associated information for an IBC client, such as the ClientState and corresponding ConsensusState. -// Upon successful update, a list of consensus heights is returned. It assumes the ClientMessage has already been verified. -func (cs ClientState) UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, _ exported.ClientMessage) []exported.Height { - height := clienttypes.GetSelfHeight(ctx) - cs.LatestHeight = height - - clientStore.Set(host.ClientStateKey(), clienttypes.MustMarshalClientState(cdc, &cs)) - - return []exported.Height{height} -} diff --git a/modules/light-clients/09-localhost/client_state_test.go b/modules/light-clients/09-localhost/client_state_test.go deleted file mode 100644 index 2eac5411d97..00000000000 --- a/modules/light-clients/09-localhost/client_state_test.go +++ /dev/null @@ -1,123 +0,0 @@ -package localhost_test - -import ( - clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" - "github.com/cosmos/ibc-go/v8/modules/core/exported" - ibctm "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" - localhost "github.com/cosmos/ibc-go/v8/modules/light-clients/09-localhost" -) - -func (suite *LocalhostTestSuite) TestClientType() { - clientState := localhost.NewClientState(clienttypes.NewHeight(3, 10)) - suite.Require().Equal(exported.Localhost, clientState.ClientType()) -} - -func (suite *LocalhostTestSuite) TestGetLatestHeight() { - expectedHeight := clienttypes.NewHeight(3, 10) - clientState := localhost.NewClientState(expectedHeight) - suite.Require().Equal(expectedHeight, clientState.LatestHeight) -} - -func (suite *LocalhostTestSuite) TestGetTimestampAtHeight() { - ctx := suite.chain.GetContext() - clientState := localhost.NewClientState(clienttypes.NewHeight(1, 10)) - - timestamp, err := clientState.GetTimestampAtHeight(ctx, nil, nil, nil) - suite.Require().NoError(err) - suite.Require().Equal(uint64(ctx.BlockTime().UnixNano()), timestamp) -} - -func (suite *LocalhostTestSuite) TestValidate() { - testCases := []struct { - name string - clientState exported.ClientState - expPass bool - }{ - { - name: "valid client", - clientState: localhost.NewClientState(clienttypes.NewHeight(3, 10)), - expPass: true, - }, - { - name: "invalid height", - clientState: localhost.NewClientState(clienttypes.ZeroHeight()), - expPass: false, - }, - } - - for _, tc := range testCases { - tc := tc - suite.Run(tc.name, func() { - err := tc.clientState.Validate() - if tc.expPass { - suite.Require().NoError(err, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - }) - } -} - -func (suite *LocalhostTestSuite) TestInitialize() { - testCases := []struct { - name string - consState exported.ConsensusState - expPass bool - }{ - { - "valid initialization", - nil, - true, - }, - { - "invalid consenus state", - &ibctm.ConsensusState{}, - false, - }, - } - - for _, tc := range testCases { - tc := tc - suite.Run(tc.name, func() { - clientState := localhost.NewClientState(clienttypes.NewHeight(3, 10)) - clientStore := suite.chain.GetSimApp().GetIBCKeeper().ClientKeeper.ClientStore(suite.chain.GetContext(), exported.LocalhostClientID) - - err := clientState.Initialize(suite.chain.GetContext(), suite.chain.Codec, clientStore, tc.consState) - - if tc.expPass { - suite.Require().NoError(err, "valid testcase: %s failed", tc.name) - } else { - suite.Require().Error(err, "invalid testcase: %s passed", tc.name) - } - }) - suite.SetupTest() - - } -} - -func (suite *LocalhostTestSuite) TestVerifyClientMessage() { - clientState := localhost.NewClientState(clienttypes.NewHeight(1, 10)) - suite.Require().Error(clientState.VerifyClientMessage(suite.chain.GetContext(), nil, nil, nil)) -} - -func (suite *LocalhostTestSuite) TestVerifyCheckForMisbehaviour() { - clientState := localhost.NewClientState(clienttypes.NewHeight(1, 10)) - suite.Require().False(clientState.CheckForMisbehaviour(suite.chain.GetContext(), nil, nil, nil)) -} - -func (suite *LocalhostTestSuite) TestUpdateState() { - clientState := localhost.NewClientState(clienttypes.NewHeight(1, uint64(suite.chain.GetContext().BlockHeight()))) - store := suite.chain.GetSimApp().GetIBCKeeper().ClientKeeper.ClientStore(suite.chain.GetContext(), exported.LocalhostClientID) - - suite.coordinator.CommitBlock(suite.chain) - - heights := clientState.UpdateState(suite.chain.GetContext(), suite.chain.Codec, store, nil) - - expHeight := clienttypes.NewHeight(1, uint64(suite.chain.GetContext().BlockHeight())) - suite.Require().True(heights[0].EQ(expHeight)) - - var ok bool - clientState, ok = suite.chain.GetClientState(exported.LocalhostClientID).(*localhost.ClientState) - suite.Require().True(ok) - suite.Require().True(heights[0].EQ(clientState.LatestHeight)) -} diff --git a/modules/light-clients/09-localhost/codec.go b/modules/light-clients/09-localhost/codec.go deleted file mode 100644 index 89d4e6980c1..00000000000 --- a/modules/light-clients/09-localhost/codec.go +++ /dev/null @@ -1,16 +0,0 @@ -package localhost - -import ( - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - - "github.com/cosmos/ibc-go/v8/modules/core/exported" -) - -// RegisterInterfaces registers the tendermint concrete client-related -// implementations and interfaces. -func RegisterInterfaces(registry codectypes.InterfaceRegistry) { - registry.RegisterImplementations( - (*exported.ClientState)(nil), - &ClientState{}, - ) -} diff --git a/modules/light-clients/09-localhost/codec_test.go b/modules/light-clients/09-localhost/codec_test.go deleted file mode 100644 index 5b90faf2160..00000000000 --- a/modules/light-clients/09-localhost/codec_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package localhost_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - sdk "github.com/cosmos/cosmos-sdk/types" - moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" - - ibc "github.com/cosmos/ibc-go/v8/modules/core" - localhost "github.com/cosmos/ibc-go/v8/modules/light-clients/09-localhost" -) - -func TestCodecTypeRegistration(t *testing.T) { - testCases := []struct { - name string - typeURL string - expPass bool - }{ - { - "success: ClientState", - sdk.MsgTypeURL(&localhost.ClientState{}), - true, - }, - { - "type not registered on codec", - "ibc.invalid.MsgTypeURL", - false, - }, - } - - for _, tc := range testCases { - tc := tc - - t.Run(tc.name, func(t *testing.T) { - encodingCfg := moduletestutil.MakeTestEncodingConfig(ibc.AppModuleBasic{}) - msg, err := encodingCfg.Codec.InterfaceRegistry().Resolve(tc.typeURL) - - if tc.expPass { - require.NotNil(t, msg) - require.NoError(t, err) - } else { - require.Nil(t, msg) - require.Error(t, err) - } - }) - } -} diff --git a/modules/light-clients/09-localhost/keys.go b/modules/light-clients/09-localhost/keys.go deleted file mode 100644 index bf10ed0d800..00000000000 --- a/modules/light-clients/09-localhost/keys.go +++ /dev/null @@ -1,12 +0,0 @@ -package localhost - -const ( - // ModuleName defines the 09-localhost light client module name - ModuleName = "09-localhost" -) - -// SentinelProof defines the 09-localhost sentinel proof. -// Submission of nil or empty proofs is disallowed in core IBC messaging. -// This serves as a placeholder value for relayers to leverage as the proof field in various message types. -// Localhost client state verification will fail if the sentintel proof value is not provided. -var SentinelProof = []byte{0x01} diff --git a/modules/light-clients/09-localhost/light_client_module.go b/modules/light-clients/09-localhost/light_client_module.go index 3c4570514b2..a362ab151a6 100644 --- a/modules/light-clients/09-localhost/light_client_module.go +++ b/modules/light-clients/09-localhost/light_client_module.go @@ -1,6 +1,8 @@ package localhost import ( + "bytes" + errorsmod "cosmossdk.io/errors" storetypes "cosmossdk.io/store/types" @@ -8,10 +10,24 @@ import ( sdk "github.com/cosmos/cosmos-sdk/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" + commitmenttypesv2 "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types/v2" host "github.com/cosmos/ibc-go/v8/modules/core/24-host" + ibcerrors "github.com/cosmos/ibc-go/v8/modules/core/errors" "github.com/cosmos/ibc-go/v8/modules/core/exported" ) +const ( + // ModuleName defines the 09-localhost light client module name + ModuleName = "09-localhost" +) + +// SentinelProof defines the 09-localhost sentinel proof. +// Submission of nil or empty proofs is disallowed in core IBC messaging. +// This serves as a placeholder value for relayers to leverage as the proof field in various message types. +// Localhost client state verification will fail if the sentintel proof value is not provided. +var SentinelProof = []byte{0x01} + var _ exported.LightClientModule = (*LightClientModule)(nil) // LightClientModule implements the core IBC api.LightClientModule interface. @@ -36,56 +52,40 @@ func (l *LightClientModule) RegisterStoreProvider(storeProvider exported.ClientS l.storeProvider = storeProvider } -// Initialize ensures that initial consensus state for localhost is nil. +// Initialize returns an error because it is stateless. // // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to be 09-localhost. -func (l LightClientModule) Initialize(ctx sdk.Context, clientID string, _, consensusStateBz []byte) error { - if len(consensusStateBz) != 0 { - return errorsmod.Wrap(clienttypes.ErrInvalidConsensus, "initial consensus state for localhost must be nil.") - } - - clientState := ClientState{ - LatestHeight: clienttypes.GetSelfHeight(ctx), - } - - clientStore := l.storeProvider.ClientStore(ctx, exported.LocalhostClientID) - clientStore.Set(host.ClientStateKey(), clienttypes.MustMarshalClientState(l.cdc, &clientState)) - return nil +func (LightClientModule) Initialize(_ sdk.Context, _ string, _, _ []byte) error { + return errorsmod.Wrap(clienttypes.ErrClientExists, "localhost is stateless and cannot be initialized") } // VerifyClientMessage is unsupported by the 09-localhost client type and returns an error. // // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to be 09-localhost. -func (LightClientModule) VerifyClientMessage(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) error { +func (LightClientModule) VerifyClientMessage(_ sdk.Context, _ string, _ exported.ClientMessage) error { return errorsmod.Wrap(clienttypes.ErrUpdateClientFailed, "client message verification is unsupported by the localhost client") } // CheckForMisbehaviour is unsupported by the 09-localhost client type and performs a no-op, returning false. -func (LightClientModule) CheckForMisbehaviour(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) bool { +func (LightClientModule) CheckForMisbehaviour(_ sdk.Context, _ string, _ exported.ClientMessage) bool { return false } // UpdateStateOnMisbehaviour is unsupported by the 09-localhost client type and performs a no-op. -func (LightClientModule) UpdateStateOnMisbehaviour(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) { +func (LightClientModule) UpdateStateOnMisbehaviour(_ sdk.Context, _ string, _ exported.ClientMessage) { // no-op } -// UpdateState obtains the localhost client state and calls into the clientState.UpdateState method. +// UpdateState performs a no-op and returns the context height in the updated heights return value. // // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to be 09-localhost. -func (l LightClientModule) UpdateState(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) []exported.Height { - clientStore := l.storeProvider.ClientStore(ctx, clientID) - cdc := l.cdc - - clientState, found := getClientState(clientStore, cdc) - if !found { - panic(errorsmod.Wrap(clienttypes.ErrClientNotFound, clientID)) - } - - return clientState.UpdateState(ctx, cdc, clientStore, clientMsg) +func (LightClientModule) UpdateState(ctx sdk.Context, _ string, _ exported.ClientMessage) []exported.Height { + return []exported.Height{clienttypes.GetSelfHeight(ctx)} } -// VerifyMembership obtains the localhost client state and calls into the clientState.VerifyMembership method. +// VerifyMembership is a generic proof verification method which verifies the existence of a given key and value within the IBC store. +// The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24). +// The caller must provide the full IBC store. // // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to be 09-localhost. func (l LightClientModule) VerifyMembership( @@ -98,19 +98,38 @@ func (l LightClientModule) VerifyMembership( path exported.Path, value []byte, ) error { - clientStore := l.storeProvider.ClientStore(ctx, clientID) ibcStore := ctx.KVStore(l.key) - cdc := l.cdc - clientState, found := getClientState(clientStore, cdc) - if !found { - return errorsmod.Wrap(clienttypes.ErrClientNotFound, clientID) + // ensure the proof provided is the expected sentinel localhost client proof + if !bytes.Equal(proof, SentinelProof) { + return errorsmod.Wrapf(commitmenttypes.ErrInvalidProof, "expected %s, got %s", string(SentinelProof), string(proof)) + } + + merklePath, ok := path.(commitmenttypesv2.MerklePath) + if !ok { + return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypes.MerklePath{}, path) + } + + if len(merklePath.GetKeyPath()) != 2 { + return errorsmod.Wrapf(host.ErrInvalidPath, "path must be of length 2: %s", merklePath.GetKeyPath()) } - return clientState.VerifyMembership(ctx, ibcStore, cdc, height, delayTimePeriod, delayBlockPeriod, proof, path, value) + // The commitment prefix (eg: "ibc") is omitted when operating on the core IBC store + bz := ibcStore.Get(merklePath.KeyPath[1]) + if bz == nil { + return errorsmod.Wrapf(clienttypes.ErrFailedMembershipVerification, "value not found for path %s", path) + } + + if !bytes.Equal(bz, value) { + return errorsmod.Wrapf(clienttypes.ErrFailedMembershipVerification, "value provided does not equal value stored at path: %s", path) + } + + return nil } -// VerifyNonMembership obtains the localhost client state and calls into the clientState.VerifyNonMembership method. +// VerifyNonMembership is a generic proof verification method which verifies the absence of a given CommitmentPath within the IBC store. +// The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24). +// The caller must provide the full IBC store. // // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to be 09-localhost. func (l LightClientModule) VerifyNonMembership( @@ -122,41 +141,45 @@ func (l LightClientModule) VerifyNonMembership( proof []byte, path exported.Path, ) error { - clientStore := l.storeProvider.ClientStore(ctx, clientID) ibcStore := ctx.KVStore(l.key) - cdc := l.cdc - clientState, found := getClientState(clientStore, cdc) - if !found { - return errorsmod.Wrap(clienttypes.ErrClientNotFound, clientID) + // ensure the proof provided is the expected sentinel localhost client proof + if !bytes.Equal(proof, SentinelProof) { + return errorsmod.Wrapf(commitmenttypes.ErrInvalidProof, "expected %s, got %s", string(SentinelProof), string(proof)) + } + + merklePath, ok := path.(commitmenttypesv2.MerklePath) + if !ok { + return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", commitmenttypes.MerklePath{}, path) } - return clientState.VerifyNonMembership(ctx, ibcStore, cdc, height, delayTimePeriod, delayBlockPeriod, proof, path) + if len(merklePath.GetKeyPath()) != 2 { + return errorsmod.Wrapf(host.ErrInvalidPath, "path must be of length 2: %s", merklePath.GetKeyPath()) + } + + // The commitment prefix (eg: "ibc") is omitted when operating on the core IBC store + if ibcStore.Has(merklePath.KeyPath[1]) { + return errorsmod.Wrapf(clienttypes.ErrFailedNonMembershipVerification, "value found for path %s", path) + } + + return nil } // Status always returns Active. The 09-localhost status cannot be changed. -func (LightClientModule) Status(ctx sdk.Context, clientID string) exported.Status { +func (LightClientModule) Status(_ sdk.Context, _ string) exported.Status { return exported.Active } -// LatestHeight returns the latest height for the client state for the given client identifier. -// If no client is present for the provided client identifier a zero value height is returned. +// LatestHeight returns the context height. // // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to be 09-localhost. -func (l LightClientModule) LatestHeight(ctx sdk.Context, clientID string) exported.Height { - clientStore := l.storeProvider.ClientStore(ctx, clientID) - - clientState, found := getClientState(clientStore, l.cdc) - if !found { - return clienttypes.ZeroHeight() - } - - return clientState.LatestHeight +func (LightClientModule) LatestHeight(ctx sdk.Context, _ string) exported.Height { + return clienttypes.GetSelfHeight(ctx) } // TimestampAtHeight returns the current block time retrieved from the application context. The localhost client does not store consensus states and thus // cannot provide a timestamp for the provided height. -func (LightClientModule) TimestampAtHeight(ctx sdk.Context, clientID string, height exported.Height) (uint64, error) { +func (LightClientModule) TimestampAtHeight(ctx sdk.Context, _ string, _ exported.Height) (uint64, error) { return uint64(ctx.BlockTime().UnixNano()), nil } @@ -166,6 +189,6 @@ func (LightClientModule) RecoverClient(_ sdk.Context, _, _ string) error { } // VerifyUpgradeAndUpdateState returns an error since localhost cannot be upgraded. -func (LightClientModule) VerifyUpgradeAndUpdateState(ctx sdk.Context, clientID string, newClient, newConsState, upgradeClientProof, upgradeConsensusStateProof []byte) error { +func (LightClientModule) VerifyUpgradeAndUpdateState(_ sdk.Context, _ string, _, _, _, _ []byte) error { return errorsmod.Wrap(clienttypes.ErrInvalidUpgradeClient, "cannot upgrade localhost client") } diff --git a/modules/light-clients/09-localhost/light_client_module_test.go b/modules/light-clients/09-localhost/light_client_module_test.go index e0cf02291d3..cccb09de28f 100644 --- a/modules/light-clients/09-localhost/light_client_module_test.go +++ b/modules/light-clients/09-localhost/light_client_module_test.go @@ -1,6 +1,10 @@ package localhost_test import ( + "testing" + + testifysuite "github.com/stretchr/testify/suite" + sdk "github.com/cosmos/cosmos-sdk/types" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" @@ -14,10 +18,53 @@ import ( "github.com/cosmos/ibc-go/v8/testing/mock" ) -func (suite *LocalhostTestSuite) TestStatus() { +type LocalhostTestSuite struct { + testifysuite.Suite + + coordinator ibctesting.Coordinator + chain *ibctesting.TestChain +} + +func (suite *LocalhostTestSuite) SetupTest() { + suite.coordinator = *ibctesting.NewCoordinator(suite.T(), 1) + suite.chain = suite.coordinator.GetChain(ibctesting.GetChainID(1)) +} + +func TestLocalhostTestSuite(t *testing.T) { + testifysuite.Run(t, new(LocalhostTestSuite)) +} + +func (suite *LocalhostTestSuite) TestInitialize() { lightClientModule, found := suite.chain.GetSimApp().IBCKeeper.ClientKeeper.Route(exported.LocalhostClientID) suite.Require().True(found) - suite.Require().Equal(exported.Active, lightClientModule.Status(suite.chain.GetContext(), exported.LocalhostClientID)) + + err := lightClientModule.Initialize(suite.chain.GetContext(), exported.LocalhostClientID, nil, nil) + suite.Require().Error(err) +} + +func (suite *LocalhostTestSuite) TestVerifyClientMessage() { + lightClientModule, found := suite.chain.GetSimApp().IBCKeeper.ClientKeeper.Route(exported.LocalhostClientID) + suite.Require().True(found) + + err := lightClientModule.Initialize(suite.chain.GetContext(), exported.LocalhostClientID, nil, nil) + suite.Require().Error(err) +} + +func (suite *LocalhostTestSuite) TestVerifyCheckForMisbehaviour() { + lightClientModule, found := suite.chain.GetSimApp().IBCKeeper.ClientKeeper.Route(exported.LocalhostClientID) + suite.Require().True(found) + + suite.Require().False(lightClientModule.CheckForMisbehaviour(suite.chain.GetContext(), exported.LocalhostClientID, nil)) +} + +func (suite *LocalhostTestSuite) TestUpdateState() { + lightClientModule, found := suite.chain.GetSimApp().IBCKeeper.ClientKeeper.Route(exported.LocalhostClientID) + suite.Require().True(found) + + heights := lightClientModule.UpdateState(suite.chain.GetContext(), exported.LocalhostClientID, nil) + + expHeight := clienttypes.NewHeight(1, uint64(suite.chain.GetContext().BlockHeight())) + suite.Require().True(heights[0].EQ(expHeight)) } func (suite *LocalhostTestSuite) TestVerifyMembership() { @@ -31,20 +78,6 @@ func (suite *LocalhostTestSuite) TestVerifyMembership() { malleate func() expPass bool }{ - { - "success: client state verification", - func() { - clientState := suite.chain.GetClientState(exported.LocalhostClientID) - - merklePath := commitmenttypes.NewMerklePath(host.FullClientStateKey(exported.LocalhostClientID)) - merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath) - suite.Require().NoError(err) - - path = merklePath - value = clienttypes.MustMarshalClientState(suite.chain.Codec, clientState) - }, - true, - }, { "success: connection state verification", func() { @@ -144,21 +177,21 @@ func (suite *LocalhostTestSuite) TestVerifyMembership() { true, }, { - "invalid type for key path", + "failure: invalid type for key path", func() { path = mock.KeyPath{} }, false, }, { - "key path has too many elements", + "failure: key path has too many elements", func() { path = commitmenttypes.NewMerklePath([]byte("ibc"), []byte("test"), []byte("key")) }, false, }, { - "no value found at provided key path", + "failure: no value found at provided key path", func() { merklePath := commitmenttypes.NewMerklePath(host.PacketAcknowledgementKey(mock.PortID, ibctesting.FirstChannelID, 100)) merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath) @@ -170,7 +203,7 @@ func (suite *LocalhostTestSuite) TestVerifyMembership() { false, }, { - "invalid value, bytes are not equal", + "failure: invalid value, bytes are not equal", func() { channel := channeltypes.NewChannel( channeltypes.OPEN, @@ -303,6 +336,22 @@ func (suite *LocalhostTestSuite) TestVerifyNonMembership() { } } +func (suite *LocalhostTestSuite) TestStatus() { + lightClientModule, found := suite.chain.GetSimApp().IBCKeeper.ClientKeeper.Route(exported.LocalhostClientID) + suite.Require().True(found) + suite.Require().Equal(exported.Active, lightClientModule.Status(suite.chain.GetContext(), exported.LocalhostClientID)) +} + +func (suite *LocalhostTestSuite) TestGetTimestampAtHeight() { + lightClientModule, found := suite.chain.GetSimApp().IBCKeeper.ClientKeeper.Route(exported.LocalhostClientID) + suite.Require().True(found) + + ctx := suite.chain.GetContext() + timestamp, err := lightClientModule.TimestampAtHeight(ctx, exported.LocalhostClientID, nil) + suite.Require().NoError(err) + suite.Require().Equal(uint64(ctx.BlockTime().UnixNano()), timestamp) +} + func (suite *LocalhostTestSuite) TestRecoverClient() { lightClientModule, found := suite.chain.GetSimApp().IBCKeeper.ClientKeeper.Route(exported.LocalhostClientID) suite.Require().True(found) diff --git a/modules/light-clients/09-localhost/localhost.pb.go b/modules/light-clients/09-localhost/localhost.pb.go deleted file mode 100644 index 61c3999c56d..00000000000 --- a/modules/light-clients/09-localhost/localhost.pb.go +++ /dev/null @@ -1,322 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/lightclients/localhost/v2/localhost.proto - -package localhost - -import ( - fmt "fmt" - _ "github.com/cosmos/gogoproto/gogoproto" - proto "github.com/cosmos/gogoproto/proto" - types "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" - io "io" - math "math" - math_bits "math/bits" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package - -// ClientState defines the 09-localhost client state -type ClientState struct { - // the latest block height - LatestHeight types.Height `protobuf:"bytes,1,opt,name=latest_height,json=latestHeight,proto3" json:"latest_height"` -} - -func (m *ClientState) Reset() { *m = ClientState{} } -func (m *ClientState) String() string { return proto.CompactTextString(m) } -func (*ClientState) ProtoMessage() {} -func (*ClientState) Descriptor() ([]byte, []int) { - return fileDescriptor_60e51cfed1fd7859, []int{0} -} -func (m *ClientState) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ClientState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ClientState.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *ClientState) XXX_Merge(src proto.Message) { - xxx_messageInfo_ClientState.Merge(m, src) -} -func (m *ClientState) XXX_Size() int { - return m.Size() -} -func (m *ClientState) XXX_DiscardUnknown() { - xxx_messageInfo_ClientState.DiscardUnknown(m) -} - -var xxx_messageInfo_ClientState proto.InternalMessageInfo - -func init() { - proto.RegisterType((*ClientState)(nil), "ibc.lightclients.localhost.v2.ClientState") -} - -func init() { - proto.RegisterFile("ibc/lightclients/localhost/v2/localhost.proto", fileDescriptor_60e51cfed1fd7859) -} - -var fileDescriptor_60e51cfed1fd7859 = []byte{ - // 257 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0xcd, 0x4c, 0x4a, 0xd6, - 0xcf, 0xc9, 0x4c, 0xcf, 0x28, 0x49, 0xce, 0xc9, 0x4c, 0xcd, 0x2b, 0x29, 0xd6, 0xcf, 0xc9, 0x4f, - 0x4e, 0xcc, 0xc9, 0xc8, 0x2f, 0x2e, 0xd1, 0x2f, 0x33, 0x42, 0x70, 0xf4, 0x0a, 0x8a, 0xf2, 0x4b, - 0xf2, 0x85, 0x64, 0x33, 0x93, 0x92, 0xf5, 0x90, 0x95, 0xeb, 0x21, 0x54, 0x94, 0x19, 0x49, 0xc9, - 0x83, 0x4c, 0x4b, 0xce, 0x2f, 0x4a, 0xd5, 0x87, 0x48, 0xeb, 0x97, 0x19, 0x42, 0x59, 0x10, 0xfd, - 0x52, 0x22, 0xe9, 0xf9, 0xe9, 0xf9, 0x60, 0xa6, 0x3e, 0x88, 0x05, 0x11, 0x55, 0x8a, 0xe2, 0xe2, - 0x76, 0x06, 0xab, 0x0a, 0x2e, 0x49, 0x2c, 0x49, 0x15, 0x72, 0xe5, 0xe2, 0xcd, 0x49, 0x2c, 0x49, - 0x2d, 0x2e, 0x89, 0xcf, 0x48, 0x05, 0x59, 0x25, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0x6d, 0x24, 0xa5, - 0x07, 0xb2, 0x1c, 0x64, 0xba, 0x1e, 0xd4, 0xcc, 0x32, 0x43, 0x3d, 0x0f, 0xb0, 0x0a, 0x27, 0x96, - 0x13, 0xf7, 0xe4, 0x19, 0x82, 0x78, 0x20, 0xda, 0x20, 0x62, 0x56, 0x2c, 0x1d, 0x0b, 0xe4, 0x19, - 0x9c, 0x92, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, - 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0xca, 0x23, 0x3d, 0xb3, - 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0x3f, 0x39, 0xbf, 0x38, 0x37, 0xbf, 0x58, 0x3f, - 0x33, 0x29, 0x59, 0x37, 0x3d, 0x5f, 0xbf, 0xcc, 0x42, 0x3f, 0x37, 0x3f, 0xa5, 0x34, 0x27, 0xb5, - 0x18, 0x12, 0x34, 0xba, 0xb0, 0xb0, 0x31, 0xb0, 0xd4, 0x85, 0xfb, 0xd7, 0x1a, 0xce, 0x4a, 0x62, - 0x03, 0x7b, 0xc3, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xac, 0xfc, 0x52, 0xb3, 0x4d, 0x01, 0x00, - 0x00, -} - -func (m *ClientState) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *ClientState) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ClientState) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.LatestHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintLocalhost(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - return len(dAtA) - i, nil -} - -func encodeVarintLocalhost(dAtA []byte, offset int, v uint64) int { - offset -= sovLocalhost(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *ClientState) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = m.LatestHeight.Size() - n += 1 + l + sovLocalhost(uint64(l)) - return n -} - -func sovLocalhost(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozLocalhost(x uint64) (n int) { - return sovLocalhost(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *ClientState) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowLocalhost - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ClientState: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ClientState: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field LatestHeight", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowLocalhost - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthLocalhost - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthLocalhost - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.LatestHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipLocalhost(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthLocalhost - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipLocalhost(dAtA []byte) (n int, err error) { - l := len(dAtA) - iNdEx := 0 - depth := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowLocalhost - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowLocalhost - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if dAtA[iNdEx-1] < 0x80 { - break - } - } - case 1: - iNdEx += 8 - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowLocalhost - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if length < 0 { - return 0, ErrInvalidLengthLocalhost - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupLocalhost - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthLocalhost - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthLocalhost = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowLocalhost = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupLocalhost = fmt.Errorf("proto: unexpected end of group") -) diff --git a/modules/light-clients/09-localhost/localhost_test.go b/modules/light-clients/09-localhost/localhost_test.go deleted file mode 100644 index c12c4546cd8..00000000000 --- a/modules/light-clients/09-localhost/localhost_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package localhost_test - -import ( - "testing" - - testifysuite "github.com/stretchr/testify/suite" - - ibctesting "github.com/cosmos/ibc-go/v8/testing" -) - -type LocalhostTestSuite struct { - testifysuite.Suite - - coordinator ibctesting.Coordinator - chain *ibctesting.TestChain -} - -func (suite *LocalhostTestSuite) SetupTest() { - suite.coordinator = *ibctesting.NewCoordinator(suite.T(), 1) - suite.chain = suite.coordinator.GetChain(ibctesting.GetChainID(1)) -} - -func TestLocalhostTestSuite(t *testing.T) { - testifysuite.Run(t, new(LocalhostTestSuite)) -} diff --git a/modules/light-clients/09-localhost/store.go b/modules/light-clients/09-localhost/store.go deleted file mode 100644 index c80b371bc22..00000000000 --- a/modules/light-clients/09-localhost/store.go +++ /dev/null @@ -1,30 +0,0 @@ -package localhost - -import ( - "fmt" - - storetypes "cosmossdk.io/store/types" - - "github.com/cosmos/cosmos-sdk/codec" - - clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" - host "github.com/cosmos/ibc-go/v8/modules/core/24-host" -) - -// getClientState retrieves the client state from the store using the provided KVStore and codec. -// It returns the unmarshaled ClientState and a boolean indicating if the state was found. -func getClientState(store storetypes.KVStore, cdc codec.BinaryCodec) (*ClientState, bool) { - bz := store.Get(host.ClientStateKey()) - if len(bz) == 0 { - return nil, false - } - - clientStateI := clienttypes.MustUnmarshalClientState(cdc, bz) - var clientState *ClientState - clientState, ok := clientStateI.(*ClientState) - if !ok { - panic(fmt.Errorf("cannot convert %T into %T", clientStateI, clientState)) - } - - return clientState, true -} diff --git a/proto/ibc/lightclients/localhost/v2/localhost.proto b/proto/ibc/lightclients/localhost/v2/localhost.proto deleted file mode 100644 index 635db85214e..00000000000 --- a/proto/ibc/lightclients/localhost/v2/localhost.proto +++ /dev/null @@ -1,16 +0,0 @@ -syntax = "proto3"; - -package ibc.lightclients.localhost.v2; - -option go_package = "github.com/cosmos/ibc-go/v8/modules/light-clients/09-localhost;localhost"; - -import "ibc/core/client/v1/client.proto"; -import "gogoproto/gogo.proto"; - -// ClientState defines the 09-localhost client state -message ClientState { - option (gogoproto.goproto_getters) = false; - - // the latest block height - ibc.core.client.v1.Height latest_height = 1 [(gogoproto.nullable) = false]; -} From 9a0493ae73251d5e38df14be4c63dab5acc42c5c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jul 2024 16:45:30 +0200 Subject: [PATCH 3/4] chore(deps): bump docker/build-push-action from 6.2.0 to 6.3.0 (#6751) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.2.0 to 6.3.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/15560696de535e4014efeff63c48f16952e52dd1...1a162644f9a7e87d8f4b053101d1d9a712edc18c) --- updated-dependencies: - dependency-name: docker/build-push-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> --- .github/workflows/docker.yml | 4 ++-- .github/workflows/e2e-test-workflow-call.yml | 4 ++-- .github/workflows/release.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index bc4b992b93d..0ab44d55de2 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -28,7 +28,7 @@ jobs: images: ${{ env.REGISTRY }}/cosmos/${{ env.IMAGE_NAME }} - name: Build Docker image - uses: docker/build-push-action@15560696de535e4014efeff63c48f16952e52dd1 + uses: docker/build-push-action@1a162644f9a7e87d8f4b053101d1d9a712edc18c with: context: . tags: ${{ steps.meta.outputs.tags }} @@ -46,7 +46,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Push Docker image - uses: docker/build-push-action@15560696de535e4014efeff63c48f16952e52dd1 + uses: docker/build-push-action@1a162644f9a7e87d8f4b053101d1d9a712edc18c with: context: . push: true diff --git a/.github/workflows/e2e-test-workflow-call.yml b/.github/workflows/e2e-test-workflow-call.yml index e5175aaa4a8..c19fb6ed2d4 100644 --- a/.github/workflows/e2e-test-workflow-call.yml +++ b/.github/workflows/e2e-test-workflow-call.yml @@ -127,7 +127,7 @@ jobs: - name: Build and push Docker image if: ${{ inputs.build-and-push-docker-image }} - uses: docker/build-push-action@15560696de535e4014efeff63c48f16952e52dd1 + uses: docker/build-push-action@1a162644f9a7e87d8f4b053101d1d9a712edc18c with: context: . push: true @@ -174,7 +174,7 @@ jobs: - name: Build and push Docker image if: ${{ inputs.build-and-push-docker-image-wasm }} - uses: docker/build-push-action@15560696de535e4014efeff63c48f16952e52dd1 + uses: docker/build-push-action@1a162644f9a7e87d8f4b053101d1d9a712edc18c with: context: . push: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3d435543ac2..1cfdeec011f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -52,7 +52,7 @@ jobs: images: ${{ env.REGISTRY }}/cosmos/${{ env.IMAGE_NAME }} - name: Build and push Docker image - uses: docker/build-push-action@15560696de535e4014efeff63c48f16952e52dd1 + uses: docker/build-push-action@1a162644f9a7e87d8f4b053101d1d9a712edc18c with: context: . push: true From 356e433cf99e9d69d718f4fd46e2f85a8d197743 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Wed, 3 Jul 2024 21:47:51 +0200 Subject: [PATCH 4/4] imp: modify ica controller `NewIBCMiddleware` to default to nil auth module (#6749) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * changed NewIBCMiddleware signature * update docs * Update docs/docs/05-migrations/13-v8-to-v9.md * Update modules/apps/27-interchain-accounts/controller/ibc_middleware.go Co-authored-by: DimitrisJim * Update docs/docs/05-migrations/13-v8-to-v9.md * add changelog --------- Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> Co-authored-by: DimitrisJim --- CHANGELOG.md | 1 + .../02-interchain-accounts/04-integration.md | 4 ++-- .../10-legacy/02-integration.md | 4 ++-- docs/docs/05-migrations/13-v8-to-v9.md | 11 +++++++++++ .../controller/ibc_middleware.go | 14 ++++++++++++-- .../controller/ibc_middleware_test.go | 18 +++++++++--------- modules/apps/29-fee/fee_test.go | 2 +- modules/apps/callbacks/testing/simapp/app.go | 2 +- .../08-wasm/testing/simapp/app.go | 2 +- testing/simapp/app.go | 2 +- 10 files changed, 41 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92661f15033..f142469a87a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (apps/27-interchain-accounts) [\#6598](https://github.com/cosmos/ibc-go/pull/6598) Mark the `requests` repeated field of `MsgModuleQuerySafe` non-nullable. * (23-commmitment) [\#6644](https://github.com/cosmos/ibc-go/pull/6644) Introduce commitment/v2 `MerklePath` to include `repeated bytes` in favour of `repeated string`. This supports using merkle path keys which include non UTF-8 encoded runes. * (23-commmitment) [\#6633](https://github.com/cosmos/ibc-go/pull/6633) MerklePath has been changed to use `repeated bytes` in favour of `repeated strings`. +* (apps/27-interchain-accounts) [\#6749](https://github.com/cosmos/ibc-go/pull/6749) The ICA controller `NewIBCMiddleware` constructor function sets by default the auth module to nil. ### State Machine Breaking diff --git a/docs/docs/02-apps/02-interchain-accounts/04-integration.md b/docs/docs/02-apps/02-interchain-accounts/04-integration.md index 8547c2198ef..3c5cb2e62aa 100644 --- a/docs/docs/02-apps/02-interchain-accounts/04-integration.md +++ b/docs/docs/02-apps/02-interchain-accounts/04-integration.md @@ -104,7 +104,7 @@ app.ICAAuthKeeper = icaauthkeeper.NewKeeper(appCodec, keys[icaauthtypes.StoreKey icaAuthModule := icaauth.NewAppModule(appCodec, app.ICAAuthKeeper) // Create controller IBC application stack and host IBC module as desired -icaControllerStack := icacontroller.NewIBCMiddleware(nil, app.ICAControllerKeeper) +icaControllerStack := icacontroller.NewIBCMiddleware(app.ICAControllerKeeper) icaHostIBCModule := icahost.NewIBCModule(app.ICAHostKeeper) // Register host and authentication routes @@ -194,7 +194,7 @@ icaModule := ica.NewAppModule(&app.ICAControllerKeeper, nil) ... // Create controller IBC application stack -icaControllerStack := icacontroller.NewIBCMiddleware(nil, app.ICAControllerKeeper) +icaControllerStack := icacontroller.NewIBCMiddleware(app.ICAControllerKeeper) // Register controller route ibcRouter.AddRoute(icacontrollertypes.SubModuleName, icaControllerStack) diff --git a/docs/docs/02-apps/02-interchain-accounts/10-legacy/02-integration.md b/docs/docs/02-apps/02-interchain-accounts/10-legacy/02-integration.md index 90a645aaabd..1999223c02f 100644 --- a/docs/docs/02-apps/02-interchain-accounts/10-legacy/02-integration.md +++ b/docs/docs/02-apps/02-interchain-accounts/10-legacy/02-integration.md @@ -110,7 +110,7 @@ icaAuthModule := icaauth.NewAppModule(appCodec, app.ICAAuthKeeper) icaAuthIBCModule := icaauth.NewIBCModule(app.ICAAuthKeeper) // Create controller IBC application stack and host IBC module as desired -icaControllerStack := icacontroller.NewIBCMiddleware(icaAuthIBCModule, app.ICAControllerKeeper) +icaControllerStack := icacontroller.NewIBCMiddlewareWithAuth(icaAuthIBCModule, app.ICAControllerKeeper) icaHostIBCModule := icahost.NewIBCModule(app.ICAHostKeeper) // Register host and authentication routes @@ -192,7 +192,7 @@ icaAuthModule := icaauth.NewAppModule(appCodec, app.ICAAuthKeeper) icaAuthIBCModule := icaauth.NewIBCModule(app.ICAAuthKeeper) // Create controller IBC application stack -icaControllerStack := icacontroller.NewIBCMiddleware(icaAuthIBCModule, app.ICAControllerKeeper) +icaControllerStack := icacontroller.NewIBCMiddlewareWithAuth(icaAuthIBCModule, app.ICAControllerKeeper) // Register controller and authentication routes ibcRouter. diff --git a/docs/docs/05-migrations/13-v8-to-v9.md b/docs/docs/05-migrations/13-v8-to-v9.md index 3a5c2242aba..e3f681e9bd1 100644 --- a/docs/docs/05-migrations/13-v8-to-v9.md +++ b/docs/docs/05-migrations/13-v8-to-v9.md @@ -88,6 +88,17 @@ func NewMsgModuleQuerySafe( ) *MsgModuleQuerySafe { ``` +The signature of the [`NewIBCMiddleware` constructor function](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/apps/27-interchain-accounts/controller/ibc_middleware.go#L35) in the controller submodule now only takes the controller keeper as an argument: + +```diff +func NewIBCMiddleware( +- app porttypes.IBCModule, + k keeper.Keeper, +) IBCMiddleware { +``` + +The base application is then set by default to nil and thus authentication is assumed to be done by a Cosmos SDK module, such as the `x/gov`, `x/group` or `x/auth`, that sends messages to the controller submodule's message server. An authentication module can be set using the newly added [`NewIBCMiddlewareWithAuth` constructor function](https://github.com/cosmos/ibc-go/blob/82b5fb668b6f1c918023fb7be72a8606d2329d81/modules/apps/27-interchain-accounts/controller/ibc_middleware.go#L46). + ### IBC core ### API removals diff --git a/modules/apps/27-interchain-accounts/controller/ibc_middleware.go b/modules/apps/27-interchain-accounts/controller/ibc_middleware.go index dc27eeda2d8..3ab3144e26d 100644 --- a/modules/apps/27-interchain-accounts/controller/ibc_middleware.go +++ b/modules/apps/27-interchain-accounts/controller/ibc_middleware.go @@ -32,8 +32,18 @@ type IBCMiddleware struct { keeper keeper.Keeper } -// NewIBCMiddleware creates a new IBCMiddleware given the associated keeper and underlying application -func NewIBCMiddleware(app porttypes.IBCModule, k keeper.Keeper) IBCMiddleware { +// NewIBCMiddleware creates a new IBCMiddleware given the associated keeper. +// The underlying application is set to nil and authentication is assumed to +// be performed by a Cosmos SDK module that sends messages to controller message server. +func NewIBCMiddleware(k keeper.Keeper) IBCMiddleware { + return IBCMiddleware{ + app: nil, + keeper: k, + } +} + +// NewIBCMiddlewareWithAuth creates a new IBCMiddleware given the associated keeper and underlying application +func NewIBCMiddlewareWithAuth(app porttypes.IBCModule, k keeper.Keeper) IBCMiddleware { return IBCMiddleware{ app: app, keeper: k, diff --git a/modules/apps/27-interchain-accounts/controller/ibc_middleware_test.go b/modules/apps/27-interchain-accounts/controller/ibc_middleware_test.go index 634b66fed31..f5ba5299ef0 100644 --- a/modules/apps/27-interchain-accounts/controller/ibc_middleware_test.go +++ b/modules/apps/27-interchain-accounts/controller/ibc_middleware_test.go @@ -234,7 +234,7 @@ func (suite *InterchainAccountsTestSuite) TestOnChanOpenInit() { suite.Require().True(ok) if isNilApp { - cbs = controller.NewIBCMiddleware(nil, suite.chainA.GetSimApp().ICAControllerKeeper) + cbs = controller.NewIBCMiddleware(suite.chainA.GetSimApp().ICAControllerKeeper) } version, err := cbs.OnChanOpenInit(suite.chainA.GetContext(), channel.Ordering, channel.ConnectionHops, @@ -384,7 +384,7 @@ func (suite *InterchainAccountsTestSuite) TestOnChanOpenAck() { err = cbs.OnChanOpenAck(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelID, path.EndpointB.ChannelConfig.Version) if isNilApp { - cbs = controller.NewIBCMiddleware(nil, suite.chainA.GetSimApp().ICAControllerKeeper) + cbs = controller.NewIBCMiddleware(suite.chainA.GetSimApp().ICAControllerKeeper) } if tc.expPass { @@ -517,7 +517,7 @@ func (suite *InterchainAccountsTestSuite) TestOnChanCloseConfirm() { suite.Require().True(ok) if isNilApp { - cbs = controller.NewIBCMiddleware(nil, suite.chainA.GetSimApp().ICAControllerKeeper) + cbs = controller.NewIBCMiddleware(suite.chainA.GetSimApp().ICAControllerKeeper) } err = cbs.OnChanCloseConfirm( @@ -679,7 +679,7 @@ func (suite *InterchainAccountsTestSuite) TestOnAcknowledgementPacket() { suite.Require().True(ok) if isNilApp { - cbs = controller.NewIBCMiddleware(nil, suite.chainA.GetSimApp().ICAControllerKeeper) + cbs = controller.NewIBCMiddleware(suite.chainA.GetSimApp().ICAControllerKeeper) } err = cbs.OnAcknowledgementPacket(suite.chainA.GetContext(), packet, []byte("ack"), nil) @@ -776,7 +776,7 @@ func (suite *InterchainAccountsTestSuite) TestOnTimeoutPacket() { suite.Require().True(ok) if isNilApp { - cbs = controller.NewIBCMiddleware(nil, suite.chainA.GetSimApp().ICAControllerKeeper) + cbs = controller.NewIBCMiddleware(suite.chainA.GetSimApp().ICAControllerKeeper) } err = cbs.OnTimeoutPacket(suite.chainA.GetContext(), packet, nil) @@ -867,7 +867,7 @@ func (suite *InterchainAccountsTestSuite) TestOnChanUpgradeInit() { suite.Require().True(ok) if isNilApp { - cbs = controller.NewIBCMiddleware(nil, suite.chainA.GetSimApp().ICAControllerKeeper) + cbs = controller.NewIBCMiddleware(suite.chainA.GetSimApp().ICAControllerKeeper) } version, err = cbs.OnChanUpgradeInit( @@ -995,7 +995,7 @@ func (suite *InterchainAccountsTestSuite) TestOnChanUpgradeAck() { suite.Require().True(ok) if isNilApp { - cbs = controller.NewIBCMiddleware(nil, suite.chainA.GetSimApp().ICAControllerKeeper) + cbs = controller.NewIBCMiddleware(suite.chainA.GetSimApp().ICAControllerKeeper) } err = cbs.OnChanUpgradeAck( @@ -1098,12 +1098,12 @@ func (suite *InterchainAccountsTestSuite) TestOnChanUpgradeOpen() { if tc.expPanic != nil { mockModule := ibcmock.NewAppModule(suite.chainA.App.GetIBCKeeper().PortKeeper) mockApp := ibcmock.NewIBCApp(path.EndpointA.ChannelConfig.PortID, suite.chainA.App.GetScopedIBCKeeper()) - cbs = controller.NewIBCMiddleware(ibcmock.NewBlockUpgradeMiddleware(&mockModule, mockApp), suite.chainA.GetSimApp().ICAControllerKeeper) + cbs = controller.NewIBCMiddlewareWithAuth(ibcmock.NewBlockUpgradeMiddleware(&mockModule, mockApp), suite.chainA.GetSimApp().ICAControllerKeeper) suite.Require().PanicsWithError(tc.expPanic.Error(), func() { upgradeOpenCb(cbs) }) } else { if isNilApp { - cbs = controller.NewIBCMiddleware(nil, suite.chainA.GetSimApp().ICAControllerKeeper) + cbs = controller.NewIBCMiddleware(suite.chainA.GetSimApp().ICAControllerKeeper) } upgradeOpenCb(cbs) diff --git a/modules/apps/29-fee/fee_test.go b/modules/apps/29-fee/fee_test.go index fa36aee8093..a5431424a14 100644 --- a/modules/apps/29-fee/fee_test.go +++ b/modules/apps/29-fee/fee_test.go @@ -88,7 +88,7 @@ func RemoveFeeMiddleware(chain *ibctesting.TestChain) { // Remove Fee middleware from icacontroller submodule chain.GetSimApp().ICAControllerKeeper.WithICS4Wrapper(channelKeeper) - icaControllerStack := icacontroller.NewIBCMiddleware(nil, chain.GetSimApp().ICAControllerKeeper) + icaControllerStack := icacontroller.NewIBCMiddleware(chain.GetSimApp().ICAControllerKeeper) newRouter.AddRoute(icacontrollertypes.SubModuleName, icaControllerStack) // Override and seal the router diff --git a/modules/apps/callbacks/testing/simapp/app.go b/modules/apps/callbacks/testing/simapp/app.go index 2cad843b1a8..a01a8e01657 100644 --- a/modules/apps/callbacks/testing/simapp/app.go +++ b/modules/apps/callbacks/testing/simapp/app.go @@ -535,7 +535,7 @@ func NewSimApp( if !ok { panic(fmt.Errorf("cannot convert %T to %T", icaControllerStack, app.ICAAuthModule)) } - icaControllerStack = icacontroller.NewIBCMiddleware(icaControllerStack, app.ICAControllerKeeper) + icaControllerStack = icacontroller.NewIBCMiddlewareWithAuth(icaControllerStack, app.ICAControllerKeeper) icaControllerStack = ibccallbacks.NewIBCMiddleware(icaControllerStack, app.IBCFeeKeeper, app.MockContractKeeper, maxCallbackGas) var icaICS4Wrapper porttypes.ICS4Wrapper icaICS4Wrapper, ok = icaControllerStack.(porttypes.ICS4Wrapper) diff --git a/modules/light-clients/08-wasm/testing/simapp/app.go b/modules/light-clients/08-wasm/testing/simapp/app.go index c663f035104..1d41543aeb0 100644 --- a/modules/light-clients/08-wasm/testing/simapp/app.go +++ b/modules/light-clients/08-wasm/testing/simapp/app.go @@ -571,7 +571,7 @@ func NewSimApp( if !ok { panic(fmt.Errorf("cannot convert %T into %T", icaControllerStack, app.ICAAuthModule)) } - icaControllerStack = icacontroller.NewIBCMiddleware(icaControllerStack, app.ICAControllerKeeper) + icaControllerStack = icacontroller.NewIBCMiddlewareWithAuth(icaControllerStack, app.ICAControllerKeeper) icaControllerStack = ibcfee.NewIBCMiddleware(icaControllerStack, app.IBCFeeKeeper) // RecvPacket, message that originates from core IBC and goes down to app, the flow is: diff --git a/testing/simapp/app.go b/testing/simapp/app.go index 8f6f4def7c6..5fdd714d43a 100644 --- a/testing/simapp/app.go +++ b/testing/simapp/app.go @@ -528,7 +528,7 @@ func NewSimApp( if !ok { panic(fmt.Errorf("cannot convert %T into %T", icaControllerStack, app.ICAAuthModule)) } - icaControllerStack = icacontroller.NewIBCMiddleware(icaControllerStack, app.ICAControllerKeeper) + icaControllerStack = icacontroller.NewIBCMiddlewareWithAuth(icaControllerStack, app.ICAControllerKeeper) icaControllerStack = ibcfee.NewIBCMiddleware(icaControllerStack, app.IBCFeeKeeper) // RecvPacket, message that originates from core IBC and goes down to app, the flow is: