Skip to content

Commit

Permalink
chore: v0.47 branch merge and bumps (#406)
Browse files Browse the repository at this point in the history
* Param proposals, balance inquiries, and IBC transfer error handling (#393)

* Extract file writing/copying logic to helpers

* Add ParamChangeProposal

* Update file naming for param change proposal

* Use Code to detect errors in IBC transfers

* Add AllBalances and ParamChangeProposal

* Add support for the Hermes relayer (#396)

* adding some scaffolding for hermes relayer

* chore: updating interface to accept create connection options type

* chore: wip

* wip: adding path map to hermes relayer type

* writing mnemonic file

* correctly reading toml config

* ibc test passing with hermes relayer

* learn ibc test passing with hermes relayer

* adding parse client and connection output

* adding hermes test cases

* remove unused types

* undid import change

* reverted import change

* reverted some unintentional changes

* fix linting error

* adding hermes to conformance matrix

* adding default value for matrix file for CI

* pass absolute value for matrix file

* removed extra part of path

* adding hermes to Labels function

* add capabilities for hermes

* temporarily strip down number of tests to verify hermes relayer

* fixing conformance tests

* fixing channel tests in TestRelayerSetup

* revert to go rly to test

* bump hermes version

* extract json response correctly

* extract json result from stdout

* correct channel parsing json stdout

* set field ClearOnStart to true

* switch back to go relayer as default

* add hermes to the default relayers list

* Update version of ibc-go from v6 to v7 from merge

* Bump sdk and ibc-go

---------

Co-authored-by: bigs <[email protected]>
Co-authored-by: Cian Hatton <[email protected]>
  • Loading branch information
3 people authored and agouin committed Mar 9, 2023
1 parent c2607f2 commit 094d0ea
Show file tree
Hide file tree
Showing 22 changed files with 1,082 additions and 113 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Don't commit the interchaintest.test file,
# regardless of where it was built.
interchaintest.test

/bin
.idea
/bin
vendor
70 changes: 53 additions & 17 deletions chain/cosmos/chain_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/types"
paramsutils "github.com/cosmos/cosmos-sdk/x/params/client/utils"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
dockertypes "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
Expand Down Expand Up @@ -145,8 +146,8 @@ func (tn *ChainNode) genesisFileContent(ctx context.Context) ([]byte, error) {
}

func (tn *ChainNode) overwriteGenesisFile(ctx context.Context, content []byte) error {
fw := dockerutil.NewFileWriter(tn.logger(), tn.DockerClient, tn.TestName)
if err := fw.WriteFile(ctx, tn.VolumeName, "config/genesis.json", content); err != nil {
err := tn.WriteFile(ctx, content, "config/genesis.json")
if err != nil {
return fmt.Errorf("overwriting genesis.json: %w", err)
}

Expand All @@ -167,8 +168,8 @@ func (tn *ChainNode) copyGentx(ctx context.Context, destVal *ChainNode) error {
return fmt.Errorf("getting gentx content: %w", err)
}

fw := dockerutil.NewFileWriter(destVal.logger(), destVal.DockerClient, destVal.TestName)
if err := fw.WriteFile(ctx, destVal.VolumeName, relPath, gentx); err != nil {
err = destVal.WriteFile(ctx, gentx, relPath)
if err != nil {
return fmt.Errorf("overwriting gentx: %w", err)
}

Expand Down Expand Up @@ -510,6 +511,25 @@ func (tn *ChainNode) InitHomeFolder(ctx context.Context) error {
return err
}

// WriteFile accepts file contents in a byte slice and writes the contents to
// the docker filesystem. relPath describes the location of the file in the
// docker volume relative to the home directory
func (tn *ChainNode) WriteFile(ctx context.Context, content []byte, relPath string) error {
fw := dockerutil.NewFileWriter(tn.logger(), tn.DockerClient, tn.TestName)
return fw.WriteFile(ctx, tn.VolumeName, relPath, content)
}

// CopyFile adds a file from the host filesystem to the docker filesystem
// relPath describes the location of the file in the docker volume relative to
// the home directory
func (tn *ChainNode) CopyFile(ctx context.Context, srcPath, dstPath string) error {
content, err := os.ReadFile(srcPath)
if err != nil {
return err
}
return tn.WriteFile(ctx, content, dstPath)
}

// CreateKey creates a key in the keyring backend test for the given node
func (tn *ChainNode) CreateKey(ctx context.Context, name string) error {
tn.lock.Lock()
Expand Down Expand Up @@ -653,14 +673,9 @@ type CodeInfosResponse struct {

// StoreContract takes a file path to smart contract and stores it on-chain. Returns the contracts code id.
func (tn *ChainNode) StoreContract(ctx context.Context, keyName string, fileName string) (string, error) {
content, err := os.ReadFile(fileName)
if err != nil {
return "", err
}

_, file := filepath.Split(fileName)
fw := dockerutil.NewFileWriter(tn.logger(), tn.DockerClient, tn.TestName)
if err := fw.WriteFile(ctx, tn.VolumeName, file, content); err != nil {
err := tn.CopyFile(ctx, fileName, file)
if err != nil {
return "", fmt.Errorf("writing contract file to docker volume: %w", err)
}

Expand Down Expand Up @@ -736,13 +751,9 @@ func (tn *ChainNode) QueryContract(ctx context.Context, contractAddress string,
// StoreClientContract takes a file path to a client smart contract and stores it on-chain. Returns the contracts code id.
func (tn *ChainNode) StoreClientContract(ctx context.Context, keyName string, fileName string) (string, error) {
content, err := os.ReadFile(fileName)
if err != nil {
return "", err
}

_, file := filepath.Split(fileName)
fw := dockerutil.NewFileWriter(tn.logger(), tn.DockerClient, tn.TestName)
if err := fw.WriteFile(ctx, tn.VolumeName, file, content); err != nil {
err = tn.WriteFile(ctx, content, file)
if err != nil {
return "", fmt.Errorf("writing contract file to docker volume: %w", err)
}

Expand Down Expand Up @@ -824,6 +835,31 @@ func (tn *ChainNode) TextProposal(ctx context.Context, keyName string, prop Text
return tn.ExecTx(ctx, keyName, command...)
}

// ParamChangeProposal submits a param change proposal to the chain, signed by keyName.
func (tn *ChainNode) ParamChangeProposal(ctx context.Context, keyName string, prop *paramsutils.ParamChangeProposalJSON) (string, error) {
content, err := json.Marshal(prop)
if err != nil {
return "", err
}

hash := sha256.Sum256(content)
proposalFilename := fmt.Sprintf("%x.json", hash)
err = tn.WriteFile(ctx, content, proposalFilename)
if err != nil {
return "", fmt.Errorf("writing param change proposal: %w", err)
}

proposalPath := filepath.Join(tn.HomeDir(), proposalFilename)

command := []string{
"gov", "submit-proposal",
"param-change",
proposalPath,
}

return tn.ExecTx(ctx, keyName, command...)
}

// DumpContractState dumps the state of a contract at a block height.
func (tn *ChainNode) DumpContractState(ctx context.Context, contractAddress string, height int64) (*DumpContractStateResponse, error) {
stdout, _, err := tn.ExecQuery(ctx,
Expand Down
34 changes: 34 additions & 0 deletions chain/cosmos/cosmos_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/cosmos/cosmos-sdk/types"
authTx "github.com/cosmos/cosmos-sdk/x/auth/tx"
bankTypes "github.com/cosmos/cosmos-sdk/x/bank/types"
paramsutils "github.com/cosmos/cosmos-sdk/x/params/client/utils"
chanTypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
dockertypes "github.com/docker/docker/api/types"
volumetypes "github.com/docker/docker/api/types/volume"
Expand Down Expand Up @@ -304,6 +305,9 @@ func (c *CosmosChain) SendIBCTransfer(
if err != nil {
return tx, fmt.Errorf("failed to get transaction %s: %w", txHash, err)
}
if txResp.Code != 0 {
return tx, fmt.Errorf("error in transaction (code: %d): %s", txResp.Code, txResp.RawLog)
}
tx.Height = uint64(txResp.Height)
tx.TxHash = txHash
// In cosmos, user is charged for entire gas requested, not the actual gas used.
Expand Down Expand Up @@ -367,6 +371,16 @@ func (c *CosmosChain) TextProposal(ctx context.Context, keyName string, prop Tex
return c.txProposal(txHash)
}

// ParamChangeProposal submits a param change proposal to the chain, signed by keyName.
func (c *CosmosChain) ParamChangeProposal(ctx context.Context, keyName string, prop *paramsutils.ParamChangeProposalJSON) (tx TxProposal, _ error) {
txHash, err := c.getFullNode().ParamChangeProposal(ctx, keyName, prop)
if err != nil {
return tx, fmt.Errorf("failed to submit param change proposal: %w", err)
}

return c.txProposal(txHash)
}

func (c *CosmosChain) txProposal(txHash string) (tx TxProposal, _ error) {
txResp, err := c.getTransaction(txHash)
if err != nil {
Expand Down Expand Up @@ -449,6 +463,26 @@ func (c *CosmosChain) GetBalance(ctx context.Context, address string, denom stri
return res.Balance.Amount.Int64(), nil
}

// AllBalances fetches an account address's balance for all denoms it holds
func (c *CosmosChain) AllBalances(ctx context.Context, address string) (types.Coins, error) {
params := bankTypes.QueryAllBalancesRequest{Address: address}
grpcAddress := c.getFullNode().hostGRPCPort
conn, err := grpc.Dial(grpcAddress, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
return nil, err
}
defer conn.Close()

queryClient := bankTypes.NewQueryClient(conn)
res, err := queryClient.AllBalances(ctx, &params)

if err != nil {
return nil, err
}

return res.GetBalances(), nil
}

func (c *CosmosChain) getTransaction(txHash string) (*types.TxResponse, error) {
// Retry because sometimes the tx is not committed to state yet.
var txResp *types.TxResponse
Expand Down
2 changes: 1 addition & 1 deletion cmd/interchaintest/example_matrix.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"Relayers": ["rly"],
"Relayers": ["rly", "hermes"],

"ChainSets": [
[
Expand Down
2 changes: 1 addition & 1 deletion cmd/interchaintest/interchaintest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func setUpTestMatrix() error {
if extraFlags.MatrixFile == "" {
fmt.Fprintln(os.Stderr, "No matrix file provided, falling back to rly with gaia and osmosis")

testMatrix.Relayers = []string{"rly"}
testMatrix.Relayers = []string{"rly", "hermes"}
testMatrix.ChainSets = [][]*interchaintest.ChainSpec{
{
{Name: "gaia", Version: "v7.0.1"},
Expand Down
15 changes: 8 additions & 7 deletions conformance/relayersetup.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import (
"fmt"
"testing"

conntypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types"
interchaintest "github.com/strangelove-ventures/interchaintest/v7"
"github.com/strangelove-ventures/interchaintest/v7/ibc"
"github.com/strangelove-ventures/interchaintest/v7/testreporter"
"github.com/strangelove-ventures/interchaintest/v7/testutil"
"github.com/stretchr/testify/require"
"golang.org/x/sync/errgroup"

conntypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types"
)

// TestRelayerSetup contains a series of subtests that configure a relayer step-by-step.
Expand Down Expand Up @@ -102,7 +103,7 @@ func TestRelayerSetup(t *testing.T, ctx context.Context, cf interchaintest.Chain
conn0 := conns0[0]
req.NotEmpty(conn0.ID)
req.NotEmpty(conn0.ClientID)
req.Equal(conn0.State, conntypes.OPEN.String())
req.Subset([]string{conntypes.OPEN.String(), "Open"}, []string{conn0.State})

conns1, err := r.GetConnections(ctx, eRep, c1.Config().ChainID)
req.NoError(err)
Expand All @@ -111,7 +112,7 @@ func TestRelayerSetup(t *testing.T, ctx context.Context, cf interchaintest.Chain
conn1 := conns1[0]
req.NotEmpty(conn1.ID)
req.NotEmpty(conn1.ClientID)
req.Equal(conn1.State, conntypes.OPEN.String())
req.Subset([]string{conntypes.OPEN.String(), "Open"}, []string{conn1.State})

// Now validate counterparties.
req.Equal(conn0.Counterparty.ClientId, conn1.ClientID)
Expand Down Expand Up @@ -160,14 +161,14 @@ func TestRelayerSetup(t *testing.T, ctx context.Context, cf interchaintest.Chain

// Piecemeal assertions against each channel.
// Not asserting against ConnectionHops or ChannelID.
req.Equal(ch0.State, "STATE_OPEN")
req.Equal(ch0.Ordering, "ORDER_UNORDERED")
req.Subset([]string{"STATE_OPEN", "Open"}, []string{ch0.State})
req.Subset([]string{"ORDER_UNORDERED", "Unordered"}, []string{ch0.Ordering})
req.Equal(ch0.Counterparty, ibc.ChannelCounterparty{PortID: "transfer", ChannelID: ch1.ChannelID})
req.Equal(ch0.Version, "ics20-1")
req.Equal(ch0.PortID, "transfer")

req.Equal(ch1.State, "STATE_OPEN")
req.Equal(ch1.Ordering, "ORDER_UNORDERED")
req.Subset([]string{"STATE_OPEN", "Open"}, []string{ch1.State})
req.Subset([]string{"ORDER_UNORDERED", "Unordered"}, []string{ch1.Ordering})
req.Equal(ch1.Counterparty, ibc.ChannelCounterparty{PortID: "transfer", ChannelID: ch0.ChannelID})
req.Equal(ch1.Version, "ics20-1")
req.Equal(ch1.PortID, "transfer")
Expand Down
4 changes: 3 additions & 1 deletion conformance/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import (
"testing"
"time"

transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
"github.com/docker/docker/client"
interchaintest "github.com/strangelove-ventures/interchaintest/v7"
"github.com/strangelove-ventures/interchaintest/v7/chain/cosmos"
Expand All @@ -47,6 +46,8 @@ import (
"github.com/strangelove-ventures/interchaintest/v7/testutil"
"github.com/stretchr/testify/require"
"golang.org/x/sync/errgroup"

transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
)

const (
Expand Down Expand Up @@ -328,6 +329,7 @@ func TestChainPair(
}

if relayerImpl == nil {
t.Logf("creating relayer: %s", rf.Name())
// startup both chains.
// creates wallets in the relayer for src and dst chain.
// funds relayer src and dst wallets on respective chain in genesis.
Expand Down
8 changes: 4 additions & 4 deletions examples/ibc/interchain_accounts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,12 +268,12 @@ func TestInterchainAccounts(t *testing.T) {
chain1Chans, err := r.GetChannels(ctx, eRep, chain1.Config().ChainID)
require.NoError(t, err)
require.Equal(t, 1, len(chain1Chans))
require.Equal(t, "STATE_CLOSED", chain1Chans[0].State)
require.Subset(t, []string{"STATE_CLOSED", "Closed"}, []string{chain1Chans[0].State})

chain2Chans, err := r.GetChannels(ctx, eRep, chain2.Config().ChainID)
require.NoError(t, err)
require.Equal(t, 1, len(chain2Chans))
require.Equal(t, "STATE_CLOSED", chain2Chans[0].State)
require.Subset(t, []string{"STATE_CLOSED", "Closed"}, []string{chain2Chans[0].State})

// Attempt to open another channel for the same ICA
_, _, err = chain1.Exec(ctx, registerICA, nil)
Expand All @@ -294,12 +294,12 @@ func TestInterchainAccounts(t *testing.T) {
chain1Chans, err = r.GetChannels(ctx, eRep, chain1.Config().ChainID)
require.NoError(t, err)
require.Equal(t, 2, len(chain1Chans))
require.Equal(t, "STATE_OPEN", chain1Chans[1].State)
require.Subset(t, []string{"STATE_OPEN", "Open"}, []string{chain1Chans[1].State})

chain2Chans, err = r.GetChannels(ctx, eRep, chain2.Config().ChainID)
require.NoError(t, err)
require.Equal(t, 2, len(chain2Chans))
require.Equal(t, "STATE_OPEN", chain2Chans[1].State)
require.Subset(t, []string{"STATE_OPEN", "Open"}, []string{chain2Chans[1].State})
}

// parseInterchainAccountField takes a slice of bytes which should be returned when querying for an ICA via
Expand Down
Loading

0 comments on commit 094d0ea

Please sign in to comment.