From cfaa3098a6258ab3b47e2dd93de67428ea780771 Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Wed, 21 Feb 2024 15:09:30 +0100 Subject: [PATCH 1/6] fix: return correct types in wasm tests and add expected err (#5883) Co-authored-by: Cian Hatton cian@interchain.io (cherry picked from commit 6b118957b44f65bcde91463babe4e8e4b40d661b) # Conflicts: # modules/light-clients/08-wasm/types/querier_test.go --- .../08-wasm/types/querier_test.go | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/modules/light-clients/08-wasm/types/querier_test.go b/modules/light-clients/08-wasm/types/querier_test.go index 89a9cf911f6..423a82496f4 100644 --- a/modules/light-clients/08-wasm/types/querier_test.go +++ b/modules/light-clients/08-wasm/types/querier_test.go @@ -121,6 +121,7 @@ func (suite *TypesTestSuite) TestStargateQuery() { testCases := []struct { name string malleate func() + expError error }{ { "success: custom query", @@ -153,11 +154,107 @@ func (suite *TypesTestSuite) TestStargateQuery() { suite.Require().Len(respData.Checksums, 1) suite.Require().Equal(expChecksum, respData.Checksums[0]) +<<<<<<< HEAD return resp, wasmtesting.DefaultGasUsed, nil +======= + store.Set(testKey, value) + + result, err := json.Marshal(types.TimestampAtHeightResult{}) + suite.Require().NoError(err) + + return result, wasmtesting.DefaultGasUsed, nil +>>>>>>> 6b118957 (fix: return correct types in wasm tests and add expected err (#5883)) + }) + }, + nil, + }, + { +<<<<<<< HEAD +======= + // The following test sets a mock proof key and value in the ibc store and registers a query callback on the Status msg. + // The Status handler will then perform the QueryVerifyMembershipRequest using the wasmvm.Querier. + // As the VerifyMembership query rpc will call directly back into the same client, we also register a callback for VerifyMembership. + // Here we decode the proof and verify the mock proof key and value are set in the ibc store. + // This exercises the full flow through the grpc handler and into the light client for verification, handling encoding and routing. + // Furthermore we write a test key and assert that the state changes made by this handler were discarded by the cachedCtx at the grpc handler. + "success: verify membership query", + func() { + querierPlugin := types.QueryPlugins{ + Stargate: types.AcceptListStargateQuerier([]string{""}), + } + + ibcwasm.SetQueryPlugins(&querierPlugin) + + store := suite.chainA.GetContext().KVStore(GetSimApp(suite.chainA).GetKey(exported.StoreKey)) + store.Set(proofKey, value) + + suite.coordinator.CommitBlock(suite.chainA) + proof, proofHeight := endpoint.QueryProofAtHeight(proofKey, uint64(suite.chainA.GetContext().BlockHeight())) + + merklePath := commitmenttypes.NewMerklePath(string(proofKey)) + merklePath, err := commitmenttypes.ApplyPrefix(suite.chainA.GetPrefix(), merklePath) + suite.Require().NoError(err) + + suite.mockVM.RegisterQueryCallback(types.TimestampAtHeightMsg{}, func(_ wasmvm.Checksum, _ wasmvmtypes.Env, _ []byte, _ wasmvm.KVStore, _ wasmvm.GoAPI, querier wasmvm.Querier, _ wasmvm.GasMeter, _ uint64, _ wasmvmtypes.UFraction) ([]byte, uint64, error) { + queryRequest := clienttypes.QueryVerifyMembershipRequest{ + ClientId: endpoint.ClientID, + Proof: proof, + ProofHeight: proofHeight, + MerklePath: merklePath, + Value: value, + } + + bz, err := queryRequest.Marshal() + suite.Require().NoError(err) + + resp, err := querier.Query(wasmvmtypes.QueryRequest{ + Stargate: &wasmvmtypes.StargateQuery{ + Path: "/ibc.core.client.v1.Query/VerifyMembership", + Data: bz, + }, + }, math.MaxUint64) + suite.Require().NoError(err) + + var respData clienttypes.QueryVerifyMembershipResponse + err = respData.Unmarshal(resp) + suite.Require().NoError(err) + + suite.Require().True(respData.Success) + + result, err := json.Marshal(types.TimestampAtHeightResult{}) + suite.Require().NoError(err) + + return result, wasmtesting.DefaultGasUsed, nil + }) + + suite.mockVM.RegisterSudoCallback(types.VerifyMembershipMsg{}, func(_ wasmvm.Checksum, _ wasmvmtypes.Env, sudoMsg []byte, store wasmvm.KVStore, + _ wasmvm.GoAPI, _ wasmvm.Querier, _ wasmvm.GasMeter, _ uint64, _ wasmvmtypes.UFraction, + ) (*wasmvmtypes.Response, uint64, error) { + var payload types.SudoMsg + err := json.Unmarshal(sudoMsg, &payload) + suite.Require().NoError(err) + + var merkleProof commitmenttypes.MerkleProof + err = suite.chainA.Codec.Unmarshal(payload.VerifyMembership.Proof, &merkleProof) + suite.Require().NoError(err) + + root := commitmenttypes.NewMerkleRoot(suite.chainA.App.LastCommitID().Hash) + err = merkleProof.VerifyMembership(commitmenttypes.GetSDKSpecs(), root, merklePath, payload.VerifyMembership.Value) + suite.Require().NoError(err) + + bz, err := json.Marshal(types.EmptyResult{}) + suite.Require().NoError(err) + + expDiscardedState = true + store.Set(testKey, value) + + return &wasmvmtypes.Response{Data: bz}, wasmtesting.DefaultGasUsed, nil }) }, + nil, }, { +>>>>>>> 6b118957 (fix: return correct types in wasm tests and add expected err (#5883)) "failure: default querier", func() { suite.mockVM.RegisterQueryCallback(types.StatusMsg{}, func(_ wasmvm.Checksum, _ wasmvmtypes.Env, _ []byte, _ wasmvm.KVStore, _ wasmvm.GoAPI, querier wasmvm.Querier, _ wasmvm.GasMeter, _ uint64, _ wasmvmtypes.UFraction) ([]byte, uint64, error) { @@ -177,6 +274,7 @@ func (suite *TypesTestSuite) TestStargateQuery() { return nil, wasmtesting.DefaultGasUsed, err }) }, + wasmvmtypes.UnsupportedRequest{Kind: fmt.Sprintf("'%s' path is not allowed from the contract", typeURL)}, }, } @@ -192,7 +290,29 @@ func (suite *TypesTestSuite) TestStargateQuery() { clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), endpoint.ClientID) clientState := endpoint.GetClientState() +<<<<<<< HEAD clientState.Status(suite.chainA.GetContext(), clientStore, suite.chainA.App.AppCodec()) +======= + + // NOTE: we register query callbacks against: types.TimestampAtHeightMsg{} + // in practise, this can against any client state msg, however registering against types.StatusMsg{} introduces recursive loops + // due to test case: "success: verify membership query" + _, err = clientState.GetTimestampAtHeight(suite.chainA.GetContext(), clientStore, suite.chainA.App.AppCodec(), clienttypes.NewHeight(1, 100)) + + expPass := tc.expError == nil + if expPass { + suite.Require().NoError(err) + } else { + // use error contains as wasmvm errors do not implement errors.Is method + suite.Require().ErrorContains(err, tc.expError.Error()) + } + + if expDiscardedState { + suite.Require().False(clientStore.Has(testKey)) + } else { + suite.Require().True(clientStore.Has(testKey)) + } +>>>>>>> 6b118957 (fix: return correct types in wasm tests and add expected err (#5883)) // reset query plugins after each test ibcwasm.SetQueryPlugins(types.NewDefaultQueryPlugins()) From 91106f5aeb045fd32b2dfad1fabbc7c62ef24ab4 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Wed, 21 Feb 2024 21:50:21 +0100 Subject: [PATCH 2/6] fix conflicts --- modules/light-clients/08-wasm/types/querier_test.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/modules/light-clients/08-wasm/types/querier_test.go b/modules/light-clients/08-wasm/types/querier_test.go index 423a82496f4..197f839360c 100644 --- a/modules/light-clients/08-wasm/types/querier_test.go +++ b/modules/light-clients/08-wasm/types/querier_test.go @@ -154,23 +154,17 @@ func (suite *TypesTestSuite) TestStargateQuery() { suite.Require().Len(respData.Checksums, 1) suite.Require().Equal(expChecksum, respData.Checksums[0]) -<<<<<<< HEAD - return resp, wasmtesting.DefaultGasUsed, nil -======= store.Set(testKey, value) result, err := json.Marshal(types.TimestampAtHeightResult{}) suite.Require().NoError(err) return result, wasmtesting.DefaultGasUsed, nil ->>>>>>> 6b118957 (fix: return correct types in wasm tests and add expected err (#5883)) }) }, nil, }, { -<<<<<<< HEAD -======= // The following test sets a mock proof key and value in the ibc store and registers a query callback on the Status msg. // The Status handler will then perform the QueryVerifyMembershipRequest using the wasmvm.Querier. // As the VerifyMembership query rpc will call directly back into the same client, we also register a callback for VerifyMembership. @@ -254,7 +248,6 @@ func (suite *TypesTestSuite) TestStargateQuery() { nil, }, { ->>>>>>> 6b118957 (fix: return correct types in wasm tests and add expected err (#5883)) "failure: default querier", func() { suite.mockVM.RegisterQueryCallback(types.StatusMsg{}, func(_ wasmvm.Checksum, _ wasmvmtypes.Env, _ []byte, _ wasmvm.KVStore, _ wasmvm.GoAPI, querier wasmvm.Querier, _ wasmvm.GasMeter, _ uint64, _ wasmvmtypes.UFraction) ([]byte, uint64, error) { @@ -290,9 +283,6 @@ func (suite *TypesTestSuite) TestStargateQuery() { clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), endpoint.ClientID) clientState := endpoint.GetClientState() -<<<<<<< HEAD - clientState.Status(suite.chainA.GetContext(), clientStore, suite.chainA.App.AppCodec()) -======= // NOTE: we register query callbacks against: types.TimestampAtHeightMsg{} // in practise, this can against any client state msg, however registering against types.StatusMsg{} introduces recursive loops @@ -312,7 +302,6 @@ func (suite *TypesTestSuite) TestStargateQuery() { } else { suite.Require().True(clientStore.Has(testKey)) } ->>>>>>> 6b118957 (fix: return correct types in wasm tests and add expected err (#5883)) // reset query plugins after each test ibcwasm.SetQueryPlugins(types.NewDefaultQueryPlugins()) From ae665a188af1eb6319ff228df0f82bcc99b12ee9 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Wed, 21 Feb 2024 22:43:21 +0100 Subject: [PATCH 3/6] remove duplicate code --- modules/light-clients/08-wasm/types/querier_test.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/modules/light-clients/08-wasm/types/querier_test.go b/modules/light-clients/08-wasm/types/querier_test.go index 474ea4f49a5..481f77902c5 100644 --- a/modules/light-clients/08-wasm/types/querier_test.go +++ b/modules/light-clients/08-wasm/types/querier_test.go @@ -395,12 +395,6 @@ func (suite *TypesTestSuite) TestStargateQuery() { suite.Require().True(clientStore.Has(testKey)) } - if expDiscardedState { - suite.Require().False(clientStore.Has(testKey)) - } else { - suite.Require().True(clientStore.Has(testKey)) - } - // reset query plugins after each test ibcwasm.SetQueryPlugins(types.NewDefaultQueryPlugins()) }) From 753cf69894bce808b8f073e754e9468f94adc3b5 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Thu, 22 Feb 2024 08:52:31 +0100 Subject: [PATCH 4/6] remove duplicate code --- .../08-wasm/types/querier_test.go | 79 ------------------- 1 file changed, 79 deletions(-) diff --git a/modules/light-clients/08-wasm/types/querier_test.go b/modules/light-clients/08-wasm/types/querier_test.go index 481f77902c5..78e0d58bfab 100644 --- a/modules/light-clients/08-wasm/types/querier_test.go +++ b/modules/light-clients/08-wasm/types/querier_test.go @@ -257,85 +257,6 @@ func (suite *TypesTestSuite) TestStargateQuery() { }, nil, }, - { - // The following test sets a mock proof key and value in the ibc store and registers a query callback on the Status msg. - // The Status handler will then perform the QueryVerifyMembershipRequest using the wasmvm.Querier. - // As the VerifyMembership query rpc will call directly back into the same client, we also register a callback for VerifyMembership. - // Here we decode the proof and verify the mock proof key and value are set in the ibc store. - // This exercises the full flow through the grpc handler and into the light client for verification, handling encoding and routing. - // Furthermore we write a test key and assert that the state changes made by this handler were discarded by the cachedCtx at the grpc handler. - "success: verify membership query", - func() { - querierPlugin := types.QueryPlugins{ - Stargate: types.AcceptListStargateQuerier([]string{""}), - } - - ibcwasm.SetQueryPlugins(&querierPlugin) - - store := suite.chainA.GetContext().KVStore(GetSimApp(suite.chainA).GetKey(exported.StoreKey)) - store.Set(proofKey, value) - - suite.coordinator.CommitBlock(suite.chainA) - proof, proofHeight := endpoint.QueryProofAtHeight(proofKey, uint64(suite.chainA.GetContext().BlockHeight())) - - merklePath := commitmenttypes.NewMerklePath(string(proofKey)) - merklePath, err := commitmenttypes.ApplyPrefix(suite.chainA.GetPrefix(), merklePath) - suite.Require().NoError(err) - - suite.mockVM.RegisterQueryCallback(types.StatusMsg{}, func(_ wasmvm.Checksum, _ wasmvmtypes.Env, _ []byte, _ wasmvm.KVStore, _ wasmvm.GoAPI, querier wasmvm.Querier, _ wasmvm.GasMeter, _ uint64, _ wasmvmtypes.UFraction) ([]byte, uint64, error) { - queryRequest := clienttypes.QueryVerifyMembershipRequest{ - ClientId: endpoint.ClientID, - Proof: proof, - ProofHeight: proofHeight, - MerklePath: merklePath, - Value: value, - } - - bz, err := queryRequest.Marshal() - suite.Require().NoError(err) - - resp, err := querier.Query(wasmvmtypes.QueryRequest{ - Stargate: &wasmvmtypes.StargateQuery{ - Path: "/ibc.core.client.v1.Query/VerifyMembership", - Data: bz, - }, - }, math.MaxUint64) - suite.Require().NoError(err) - - var respData clienttypes.QueryVerifyMembershipResponse - err = respData.Unmarshal(resp) - suite.Require().NoError(err) - - suite.Require().True(respData.Success) - - return resp, wasmtesting.DefaultGasUsed, nil - }) - - suite.mockVM.RegisterSudoCallback(types.VerifyMembershipMsg{}, func(_ wasmvm.Checksum, _ wasmvmtypes.Env, sudoMsg []byte, store wasmvm.KVStore, - _ wasmvm.GoAPI, _ wasmvm.Querier, _ wasmvm.GasMeter, _ uint64, _ wasmvmtypes.UFraction, - ) (*wasmvmtypes.Response, uint64, error) { - var payload types.SudoMsg - err := json.Unmarshal(sudoMsg, &payload) - suite.Require().NoError(err) - - var merkleProof commitmenttypes.MerkleProof - err = suite.chainA.Codec.Unmarshal(payload.VerifyMembership.Proof, &merkleProof) - suite.Require().NoError(err) - - root := commitmenttypes.NewMerkleRoot(suite.chainA.App.LastCommitID().Hash) - err = merkleProof.VerifyMembership(commitmenttypes.GetSDKSpecs(), root, merklePath, payload.VerifyMembership.Value) - suite.Require().NoError(err) - - bz, err := json.Marshal(types.EmptyResult{}) - suite.Require().NoError(err) - - expDiscardedState = true - store.Set(testKey, value) - - return &wasmvmtypes.Response{Data: bz}, wasmtesting.DefaultGasUsed, nil - }) - }, - }, { "failure: default querier", func() { From 11ce9f879e3a48afd350f8f68bd46dd1719a3c44 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Thu, 22 Feb 2024 09:00:15 +0100 Subject: [PATCH 5/6] fix test --- modules/light-clients/08-wasm/types/querier_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/light-clients/08-wasm/types/querier_test.go b/modules/light-clients/08-wasm/types/querier_test.go index 78e0d58bfab..378d16a823d 100644 --- a/modules/light-clients/08-wasm/types/querier_test.go +++ b/modules/light-clients/08-wasm/types/querier_test.go @@ -199,7 +199,7 @@ func (suite *TypesTestSuite) TestStargateQuery() { merklePath, err := commitmenttypes.ApplyPrefix(suite.chainA.GetPrefix(), merklePath) suite.Require().NoError(err) - suite.mockVM.RegisterQueryCallback(types.TimestampAtHeightMsg{}, func(_ wasmvm.Checksum, _ wasmvmtypes.Env, _ []byte, _ wasmvm.KVStore, _ wasmvm.GoAPI, querier wasmvm.Querier, _ wasmvm.GasMeter, _ uint64, _ wasmvmtypes.UFraction) ([]byte, uint64, error) { + suite.mockVM.RegisterQueryCallback(types.StatusMsg{}, func(_ wasmvm.Checksum, _ wasmvmtypes.Env, _ []byte, _ wasmvm.KVStore, _ wasmvm.GoAPI, querier wasmvm.Querier, _ wasmvm.GasMeter, _ uint64, _ wasmvmtypes.UFraction) ([]byte, uint64, error) { queryRequest := clienttypes.QueryVerifyMembershipRequest{ ClientId: endpoint.ClientID, Proof: proof, From d231a22586f2557a85732aa1f7cbcee82a504fdb Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Thu, 22 Feb 2024 15:36:10 +0100 Subject: [PATCH 6/6] fix: address test failures --- modules/light-clients/08-wasm/types/querier_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/light-clients/08-wasm/types/querier_test.go b/modules/light-clients/08-wasm/types/querier_test.go index 378d16a823d..f912480864b 100644 --- a/modules/light-clients/08-wasm/types/querier_test.go +++ b/modules/light-clients/08-wasm/types/querier_test.go @@ -142,7 +142,7 @@ func (suite *TypesTestSuite) TestStargateQuery() { ibcwasm.SetQueryPlugins(&querierPlugin) - suite.mockVM.RegisterQueryCallback(types.StatusMsg{}, func(_ wasmvm.Checksum, _ wasmvmtypes.Env, _ []byte, store wasmvm.KVStore, _ wasmvm.GoAPI, querier wasmvm.Querier, _ wasmvm.GasMeter, _ uint64, _ wasmvmtypes.UFraction) ([]byte, uint64, error) { + suite.mockVM.RegisterQueryCallback(types.TimestampAtHeightMsg{}, func(_ wasmvm.Checksum, _ wasmvmtypes.Env, _ []byte, store wasmvm.KVStore, _ wasmvm.GoAPI, querier wasmvm.Querier, _ wasmvm.GasMeter, _ uint64, _ wasmvmtypes.UFraction) ([]byte, uint64, error) { queryRequest := types.QueryChecksumsRequest{} bz, err := queryRequest.Marshal() suite.Require().NoError(err) @@ -199,7 +199,7 @@ func (suite *TypesTestSuite) TestStargateQuery() { merklePath, err := commitmenttypes.ApplyPrefix(suite.chainA.GetPrefix(), merklePath) suite.Require().NoError(err) - suite.mockVM.RegisterQueryCallback(types.StatusMsg{}, func(_ wasmvm.Checksum, _ wasmvmtypes.Env, _ []byte, _ wasmvm.KVStore, _ wasmvm.GoAPI, querier wasmvm.Querier, _ wasmvm.GasMeter, _ uint64, _ wasmvmtypes.UFraction) ([]byte, uint64, error) { + suite.mockVM.RegisterQueryCallback(types.TimestampAtHeightMsg{}, func(_ wasmvm.Checksum, _ wasmvmtypes.Env, _ []byte, _ wasmvm.KVStore, _ wasmvm.GoAPI, querier wasmvm.Querier, _ wasmvm.GasMeter, _ uint64, _ wasmvmtypes.UFraction) ([]byte, uint64, error) { queryRequest := clienttypes.QueryVerifyMembershipRequest{ ClientId: endpoint.ClientID, Proof: proof, @@ -260,7 +260,7 @@ func (suite *TypesTestSuite) TestStargateQuery() { { "failure: default querier", func() { - suite.mockVM.RegisterQueryCallback(types.StatusMsg{}, func(_ wasmvm.Checksum, _ wasmvmtypes.Env, _ []byte, store wasmvm.KVStore, _ wasmvm.GoAPI, querier wasmvm.Querier, _ wasmvm.GasMeter, _ uint64, _ wasmvmtypes.UFraction) ([]byte, uint64, error) { + suite.mockVM.RegisterQueryCallback(types.TimestampAtHeightMsg{}, func(_ wasmvm.Checksum, _ wasmvmtypes.Env, _ []byte, store wasmvm.KVStore, _ wasmvm.GoAPI, querier wasmvm.Querier, _ wasmvm.GasMeter, _ uint64, _ wasmvmtypes.UFraction) ([]byte, uint64, error) { queryRequest := types.QueryChecksumsRequest{} bz, err := queryRequest.Marshal() suite.Require().NoError(err)