Skip to content

Commit

Permalink
feat(e2e): working on test for verify membership
Browse files Browse the repository at this point in the history
  • Loading branch information
srdtrk committed Jun 9, 2024
1 parent 9f61a95 commit 8c2a796
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 28 deletions.
59 changes: 52 additions & 7 deletions e2e/interchaintestv8/e2esuite/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"cosmossdk.io/math"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/grpc/cmtservice"
"github.com/cosmos/cosmos-sdk/client/tx"
sdk "github.com/cosmos/cosmos-sdk/types"

Expand All @@ -16,6 +17,8 @@ import (
"github.com/strangelove-ventures/interchaintest/v8/chain/cosmos"
"github.com/strangelove-ventures/interchaintest/v8/ibc"
"github.com/strangelove-ventures/interchaintest/v8/testutil"

"github.com/srdtrk/cw-ibc-lite/e2esuite/v8/types"
)

// FundAddressChainA sends funds to the given address on Chain A.
Expand Down Expand Up @@ -100,15 +103,10 @@ func (*TestSuite) ExtractValueFromEvents(events sdk.StringEvents, eventType, att

// QuerySignedHeader queries the signed header from the chain
func (s *TestSuite) QuerySignedHeader(
ctx context.Context, chain ibc.Chain, trustedHeight clienttypes.Height,
ctx context.Context, chain *cosmos.CosmosChain, trustedHeight clienttypes.Height,
) (*ibctm.Header, error) {
cosmosChain, ok := chain.(*cosmos.CosmosChain)
if !ok {
return nil, fmt.Errorf("QueryTxsByEvents must be passed a cosmos.CosmosChain")
}

cmd := []string{"ibc", "client", "header"}
stdout, _, err := cosmosChain.GetNode().ExecQuery(ctx, cmd...)
stdout, _, err := chain.GetNode().ExecQuery(ctx, cmd...)
if err != nil {
return nil, err
}
Expand All @@ -125,3 +123,50 @@ func (s *TestSuite) QuerySignedHeader(

return result, nil
}

// QueryProofs queries the proofs from the chain for the given key
func (s *TestSuite) QueryProofs(
ctx context.Context, chain *cosmos.CosmosChain,
storeKey string, key []byte, height int64,
) ([]byte, int64, error) {
resp, err := GRPCQuery[cmtservice.ABCIQueryResponse](ctx, chain, &cmtservice.ABCIQueryRequest{
Path: fmt.Sprintf("store/%s/key", storeKey),
Height: height - 1, // Copied from ibc-go test
Data: key,
Prove: true,
})
if err != nil {
return nil, 0, err
}

merkleProof, err := types.ConvertProofs(resp.ProofOps)
if err != nil {
return nil, 0, err
}

proof, err := chain.Config().EncodingConfig.Codec.Marshal(&merkleProof)
if err != nil {
return nil, 0, err
}

// proof height + 1 is returned as the proof created corresponds to the height the proof
// was created in the IAVL tree. Tendermint and subsequently the clients that rely on it
// have heights 1 above the IAVL tree. Thus we return proof height + 1
return proof, resp.Height + 1, nil
}

func (s *TestSuite) FetchHeader(ctx context.Context, chain *cosmos.CosmosChain) (*cmtservice.Header, error) {
latestHeight, err := chain.Height(ctx)
if err != nil {
return nil, err
}

headerResp, err := GRPCQuery[cmtservice.GetBlockByHeightResponse](ctx, chain, &cmtservice.GetBlockByHeightRequest{
Height: latestHeight,
})
if err != nil {
return nil, err
}

return &headerResp.SdkBlock.Header, nil
}
6 changes: 3 additions & 3 deletions e2e/interchaintestv8/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ toolchain go1.22.3

require (
cosmossdk.io/api v0.7.5
cosmossdk.io/collections v0.4.0
cosmossdk.io/errors v1.0.1
cosmossdk.io/math v1.3.0
cosmossdk.io/x/tx v0.13.3
cosmossdk.io/x/upgrade v0.1.2
Expand All @@ -14,6 +16,7 @@ require (
github.com/cosmos/gogoproto v1.4.12
github.com/cosmos/ibc-go/modules/light-clients/08-wasm v0.1.1-0.20231213092650-57fcdb9a9a9d
github.com/cosmos/ibc-go/v8 v8.3.0
github.com/cosmos/ics23/go v0.10.0
github.com/docker/docker v24.0.9+incompatible
github.com/strangelove-ventures/interchaintest/v8 v8.3.0
github.com/stretchr/testify v1.9.0
Expand All @@ -29,10 +32,8 @@ require (
cloud.google.com/go/iam v1.1.6 // indirect
cloud.google.com/go/storage v1.38.0 // indirect
cosmossdk.io/client/v2 v2.0.0-beta.1 // indirect
cosmossdk.io/collections v0.4.0 // indirect
cosmossdk.io/core v0.11.0 // indirect
cosmossdk.io/depinject v1.0.0-alpha.4 // indirect
cosmossdk.io/errors v1.0.1 // indirect
cosmossdk.io/log v1.3.1 // indirect
cosmossdk.io/store v1.1.0 // indirect
cosmossdk.io/x/circuit v0.1.0 // indirect
Expand Down Expand Up @@ -78,7 +79,6 @@ require (
github.com/cosmos/gogogateway v1.2.0 // indirect
github.com/cosmos/iavl v1.1.2 // indirect
github.com/cosmos/ibc-go/modules/capability v1.0.0 // indirect
github.com/cosmos/ics23/go v0.10.0 // indirect
github.com/cosmos/interchain-security/v5 v5.0.0-alpha1.0.20240424193412-7cd900ad2a74 // indirect
github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect
github.com/danieljoos/wincred v1.1.2 // indirect
Expand Down
74 changes: 56 additions & 18 deletions e2e/interchaintestv8/ics07tendermint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import (

"github.com/stretchr/testify/suite"

"github.com/cosmos/cosmos-sdk/client/grpc/cmtservice"
sdkmath "cosmossdk.io/math"

codectypes "github.com/cosmos/cosmos-sdk/codec/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/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"
Expand All @@ -22,6 +24,7 @@ import (
"github.com/strangelove-ventures/interchaintest/v8/chain/cosmos"

"github.com/srdtrk/cw-ibc-lite/e2esuite/v8/e2esuite"
"github.com/srdtrk/cw-ibc-lite/e2esuite/v8/testvalues"
"github.com/srdtrk/cw-ibc-lite/e2esuite/v8/types"
"github.com/srdtrk/cw-ibc-lite/e2esuite/v8/types/ics07tendermint"
)
Expand Down Expand Up @@ -137,7 +140,7 @@ func (s *ICS07TendermintTestSuite) TestUpdateClient() {
s.Require().True(s.Run("VerifyClientStatus", func() {
statusResp, err := s.tendermintContract.QueryClient().Status(ctx, &ics07tendermint.QueryMsg_Status{})
s.Require().NoError(err)
s.Require().Equal(statusResp.Status, ibcexported.Active.String())
s.Require().Equal(ibcexported.Active.String(), statusResp.Status)

// if the height isn't present in the client state, this query would failed
_, err = s.tendermintContract.QueryClient().TimestampAtHeight(ctx, &ics07tendermint.QueryMsg_TimestampAtHeight{
Expand All @@ -150,6 +153,57 @@ func (s *ICS07TendermintTestSuite) TestUpdateClient() {
}))
}

// TestVerifyMembership is a test that demonstrates verifying membership in the ICS-07 Tendermint contract.
func (s *ICS07TendermintTestSuite) TestVerifyMembership() {
ctx := context.Background()

s.SetupSuite(ctx)

_, wasmd2 := s.ChainA, s.ChainB

// We will verify the balance of s.UserB on wasmd2
var (
proofHeight int64
proof []byte
value []byte
merklePath *commitmenttypes.MerklePath
)
s.Require().True(s.Run("CreateBankProof", func() {
key, err := types.GetBankBalanceKey(s.UserB.Address(), wasmd2.Config().Denom)
s.Require().NoError(err)
value, err = banktypes.BalanceValueCodec.Encode(sdkmath.NewInt(testvalues.StartingTokenAmount))
s.Require().NoError(err)

merklePath, err = types.ConvertToMerklePath([]byte(banktypes.StoreKey), key)
s.Require().NoError(err)

// Create a proof for the balance of s.UserB on wasmd2
proof, proofHeight, err = s.QueryProofs(ctx, wasmd2, banktypes.StoreKey, key, int64(s.trustedHeight.RevisionHeight))
s.Require().NoError(err)
s.Require().NotEmpty(proof)
s.Require().Equal(int64(s.trustedHeight.RevisionHeight), proofHeight)
}))

s.Require().True(s.Run("VerifyMembership", func() {
_, err := s.tendermintContract.QueryClient().VerifyMembership(ctx, &ics07tendermint.QueryMsg_VerifyMembership{
DelayBlockPeriod: 0,
DelayTimePeriod: 0,
Height: ics07tendermint.Height2{
RevisionNumber: int(s.trustedHeight.RevisionNumber),
RevisionHeight: int(proofHeight),
},
// TODO: ibc-rs only accepts IBC paths
// Therefore, the test is failing
Path: ics07tendermint.MerklePath{
KeyPath: merklePath.KeyPath,
},
Proof: base64.StdEncoding.EncodeToString(proof),
Value: base64.StdEncoding.EncodeToString(value),
})
s.Require().NoError(err)
}))
}

func (s *ICS07TendermintTestSuite) UpdateClientContract(ctx context.Context, tmContract *ics07tendermint.Contract, counterpartyChain *cosmos.CosmosChain) {
signedHeader, err := s.QuerySignedHeader(ctx, counterpartyChain, s.trustedHeight)
s.Require().NoError(err)
Expand All @@ -174,19 +228,3 @@ func (s *ICS07TendermintTestSuite) UpdateClientContract(ctx context.Context, tmC
// NOTE: We assume that revision number does not change
s.trustedHeight.RevisionHeight = uint64(signedHeader.Header.Height)
}

func (s *ICS07TendermintTestSuite) FetchHeader(ctx context.Context, chain *cosmos.CosmosChain) (*cmtservice.Header, error) {
latestHeight, err := chain.Height(ctx)
if err != nil {
return nil, err
}

headerResp, err := e2esuite.GRPCQuery[cmtservice.GetBlockByHeightResponse](ctx, chain, &cmtservice.GetBlockByHeightRequest{
Height: latestHeight,
})
if err != nil {
return nil, err
}

return &headerResp.SdkBlock.Header, nil
}
28 changes: 28 additions & 0 deletions e2e/interchaintestv8/types/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ import (
"io"
"os"

ics23 "github.com/cosmos/ics23/go"

errorsmod "cosmossdk.io/errors"

"github.com/cosmos/cosmos-sdk/client/grpc/cmtservice"

commitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types"

wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"

"github.com/strangelove-ventures/interchaintest/v8/chain/cosmos"
Expand Down Expand Up @@ -52,3 +60,23 @@ func NewCompressedStoreCodeMsg(ctx context.Context, chain *cosmos.CosmosChain, w

return msgStoreCode, nil
}

// ConvertProofs converts cmtservice.ProofOps into MerkleProof
func ConvertProofs(tmProof *cmtservice.ProofOps) (commitmenttypes.MerkleProof, error) {
if tmProof == nil {
return commitmenttypes.MerkleProof{}, errorsmod.Wrapf(commitmenttypes.ErrInvalidMerkleProof, "tendermint proof is nil")
}
// Unmarshal all proof ops to CommitmentProof
proofs := make([]*ics23.CommitmentProof, len(tmProof.Ops))
for i, op := range tmProof.Ops {
var p ics23.CommitmentProof
err := p.Unmarshal(op.Data)
if err != nil || p.Proof == nil {
return commitmenttypes.MerkleProof{}, errorsmod.Wrapf(commitmenttypes.ErrInvalidMerkleProof, "could not unmarshal proof op into CommitmentProof at index %d: %v", i, err)
}
proofs[i] = &p
}
return commitmenttypes.MerkleProof{
Proofs: proofs,
}, nil
}
35 changes: 35 additions & 0 deletions e2e/interchaintestv8/types/storekeys.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package types

import (
"cosmossdk.io/collections"

sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"

commitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types"
)

/*
This package contains helpers to interact with storage keys
*/

func GetBankBalanceKey(address sdk.AccAddress, denom string) ([]byte, error) {
keyCodec := collections.PairKeyCodec(sdk.AccAddressKey, collections.StringKey)
key, err := collections.EncodeKeyWithPrefix(banktypes.BalancesPrefix, keyCodec, collections.Join(address, denom))
if err != nil {
return nil, err
}

return key, nil
}

func ConvertToMerklePath(prefix []byte, key []byte) (*commitmenttypes.MerklePath, error) {
merklePath := commitmenttypes.NewMerklePath(string(key))
merklePrefix := commitmenttypes.NewMerklePrefix(prefix)
path, err := commitmenttypes.ApplyPrefix(merklePrefix, merklePath)
if err != nil {
return nil, err
}

return &path, nil
}

0 comments on commit 8c2a796

Please sign in to comment.