Skip to content

Commit

Permalink
packet-forward-middleware packet memo, retry on timeout, and atomic f…
Browse files Browse the repository at this point in the history
…orwards (#306)

* Make examples its own module

* Make cosmos specific module and run in CI in separate task

* Update e2e test for memo refactor

* Update test to chain-level params

* Use gaia with pfm with configurable timeout and retries

* Update SendIBCTransfer uses

* fix interchain test

* Add GetClients method to Relayer and helper for getting transfer channel between chains

* Update packet forward test for multi-hop, add multi-hop refund test

* Update tests for atomic forwards

* Wait for a block after ack before checking balances

* reduce wait to 1 block

* Add multi-hop flow with refund through chain with native denom. Add assertions for escrow accounts

* Remove stale comment

* handle feedback

* Add TransferOptions
  • Loading branch information
agouin authored Nov 8, 2022
1 parent 097da3a commit 9af4ad0
Show file tree
Hide file tree
Showing 21 changed files with 879 additions and 199 deletions.
37 changes: 30 additions & 7 deletions chain/cosmos/chain_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,14 +225,28 @@ func (tn *ChainNode) SetTestConfig(ctx context.Context) error {

c["rpc"] = rpc

return testutil.ModifyTomlConfigFile(
if err := testutil.ModifyTomlConfigFile(
ctx,
tn.logger(),
tn.DockerClient,
tn.TestName,
tn.VolumeName,
"config/config.toml",
c,
); err != nil {
return err
}

a := make(testutil.Toml)
a["minimum-gas-prices"] = tn.Chain.Config().GasPrices
return testutil.ModifyTomlConfigFile(
ctx,
tn.logger(),
tn.DockerClient,
tn.TestName,
tn.VolumeName,
"config/app.toml",
a,
)
}

Expand Down Expand Up @@ -570,18 +584,27 @@ type CosmosTx struct {
RawLog string `json:"raw_log"`
}

func (tn *ChainNode) SendIBCTransfer(ctx context.Context, channelID string, keyName string, amount ibc.WalletAmount, timeout *ibc.IBCTimeout) (string, error) {
func (tn *ChainNode) SendIBCTransfer(
ctx context.Context,
channelID string,
keyName string,
amount ibc.WalletAmount,
options ibc.TransferOptions,
) (string, error) {
command := []string{
"ibc-transfer", "transfer", "transfer", channelID,
amount.Address, fmt.Sprintf("%d%s", amount.Amount, amount.Denom),
}
if timeout != nil {
if timeout.NanoSeconds > 0 {
command = append(command, "--packet-timeout-timestamp", fmt.Sprint(timeout.NanoSeconds))
} else if timeout.Height > 0 {
command = append(command, "--packet-timeout-height", fmt.Sprintf("0-%d", timeout.Height))
if options.Timeout != nil {
if options.Timeout.NanoSeconds > 0 {
command = append(command, "--packet-timeout-timestamp", fmt.Sprint(options.Timeout.NanoSeconds))
} else if options.Timeout.Height > 0 {
command = append(command, "--packet-timeout-height", fmt.Sprintf("0-%d", options.Timeout.Height))
}
}
if options.Memo != "" {
command = append(command, "--memo", options.Memo)
}
return tn.ExecTx(ctx, keyName, command...)
}

Expand Down
10 changes: 8 additions & 2 deletions chain/cosmos/cosmos_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,14 @@ func (c *CosmosChain) SendFunds(ctx context.Context, keyName string, amount ibc.
}

// Implements Chain interface
func (c *CosmosChain) SendIBCTransfer(ctx context.Context, channelID, keyName string, amount ibc.WalletAmount, timeout *ibc.IBCTimeout) (tx ibc.Tx, _ error) {
txHash, err := c.getFullNode().SendIBCTransfer(ctx, channelID, keyName, amount, timeout)
func (c *CosmosChain) SendIBCTransfer(
ctx context.Context,
channelID string,
keyName string,
amount ibc.WalletAmount,
options ibc.TransferOptions,
) (tx ibc.Tx, _ error) {
txHash, err := c.getFullNode().SendIBCTransfer(ctx, channelID, keyName, amount, options)
if err != nil {
return tx, fmt.Errorf("send ibc transfer: %w", err)
}
Expand Down
22 changes: 22 additions & 0 deletions chain/cosmos/poll.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"

codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/strangelove-ventures/ibctest/v6/ibc"
"github.com/strangelove-ventures/ibctest/v6/testutil"
)

Expand Down Expand Up @@ -58,3 +59,24 @@ func PollForMessage[T any](ctx context.Context, chain *CosmosChain, registry cod
bp := testutil.BlockPoller[T]{CurrentHeight: chain.Height, PollFunc: doPoll}
return bp.DoPoll(ctx, startHeight, maxHeight)
}

// PollForBalance polls until the balance matches
func PollForBalance(ctx context.Context, chain *CosmosChain, deltaBlocks uint64, balance ibc.WalletAmount) error {
h, err := chain.Height(ctx)
if err != nil {
return fmt.Errorf("failed to get height: %w", err)
}
doPoll := func(ctx context.Context, height uint64) (any, error) {
bal, err := chain.GetBalance(ctx, balance.Address, balance.Denom)
if err != nil {
return nil, err
}
if bal != balance.Amount {
return nil, fmt.Errorf("balance (%d) does not match expected: (%d)", bal, balance.Amount)
}
return nil, nil
}
bp := testutil.BlockPoller[any]{CurrentHeight: chain.Height, PollFunc: doPoll}
_, err = bp.DoPoll(ctx, h, h+deltaBlocks)
return err
}
8 changes: 7 additions & 1 deletion chain/penumbra/penumbra_app_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,13 @@ func (p *PenumbraAppNode) SendFunds(ctx context.Context, keyName string, amount
return errors.New("not yet implemented")
}

func (p *PenumbraAppNode) SendIBCTransfer(ctx context.Context, channelID, keyName string, amount ibc.WalletAmount, timeout *ibc.IBCTimeout) (ibc.Tx, error) {
func (p *PenumbraAppNode) SendIBCTransfer(
ctx context.Context,
channelID string,
keyName string,
amount ibc.WalletAmount,
options ibc.TransferOptions,
) (ibc.Tx, error) {
return ibc.Tx{}, errors.New("not yet implemented")
}

Expand Down
10 changes: 8 additions & 2 deletions chain/penumbra/penumbra_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,14 @@ func (c *PenumbraChain) SendFunds(ctx context.Context, keyName string, amount ib
}

// Implements Chain interface
func (c *PenumbraChain) SendIBCTransfer(ctx context.Context, channelID, keyName string, amount ibc.WalletAmount, timeout *ibc.IBCTimeout) (ibc.Tx, error) {
return c.getRelayerNode().PenumbraAppNode.SendIBCTransfer(ctx, channelID, keyName, amount, timeout)
func (c *PenumbraChain) SendIBCTransfer(
ctx context.Context,
channelID string,
keyName string,
amount ibc.WalletAmount,
options ibc.TransferOptions,
) (ibc.Tx, error) {
return c.getRelayerNode().PenumbraAppNode.SendIBCTransfer(ctx, channelID, keyName, amount, options)
}

// Implements Chain interface
Expand Down
8 changes: 7 additions & 1 deletion chain/polkadot/polkadot_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,13 @@ func (c *PolkadotChain) SendFunds(ctx context.Context, keyName string, amount ib

// SendIBCTransfer sends an IBC transfer returning a transaction or an error if the transfer failed.
// Implements Chain interface.
func (c *PolkadotChain) SendIBCTransfer(ctx context.Context, channelID, keyName string, amount ibc.WalletAmount, timeout *ibc.IBCTimeout) (ibc.Tx, error) {
func (c *PolkadotChain) SendIBCTransfer(
ctx context.Context,
channelID string,
keyName string,
amount ibc.WalletAmount,
options ibc.TransferOptions,
) (ibc.Tx, error) {
panic("not implemented yet")
}

Expand Down
2 changes: 1 addition & 1 deletion conformance/flush.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func TestRelayerFlushing(t *testing.T, ctx context.Context, cf ibctest.ChainFact
Address: c1FaucetAddr,
Denom: c0.Config().Denom,
Amount: txAmount,
}, nil)
}, ibc.TransferOptions{})
req.NoError(err)
req.NoError(tx.Validate())

Expand Down
4 changes: 2 additions & 2 deletions conformance/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ func sendIBCTransfersFromBothChainsWithTimeout(
eg.Go(func() (err error) {
for i, channel := range channels {
srcChannelID := channel.ChannelID
srcTxs[i], err = srcChain.SendIBCTransfer(ctx, srcChannelID, srcUser.KeyName, testCoinSrcToDst, timeout)
srcTxs[i], err = srcChain.SendIBCTransfer(ctx, srcChannelID, srcUser.KeyName, testCoinSrcToDst, ibc.TransferOptions{Timeout: timeout})
if err != nil {
return fmt.Errorf("failed to send ibc transfer from source: %w", err)
}
Expand All @@ -180,7 +180,7 @@ func sendIBCTransfersFromBothChainsWithTimeout(
eg.Go(func() (err error) {
for i, channel := range channels {
dstChannelID := channel.Counterparty.ChannelID
dstTxs[i], err = dstChain.SendIBCTransfer(ctx, dstChannelID, dstUser.KeyName, testCoinDstToSrc, timeout)
dstTxs[i], err = dstChain.SendIBCTransfer(ctx, dstChannelID, dstUser.KeyName, testCoinDstToSrc, ibc.TransferOptions{Timeout: timeout})
if err != nil {
return fmt.Errorf("failed to send ibc transfer from destination: %w", err)
}
Expand Down
7 changes: 3 additions & 4 deletions docs/writeCustomTests.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,13 +216,12 @@ osmosisRPC := osmosis.GetGRPCAddress()
Here we send an IBC Transaction:
```go
amountToSend := int64(1_000_000)
tx, err := gaia.SendIBCTransfer(ctx, gaiaChannelID, gaiaUser.KeyName, ibc.WalletAmount{
transfer := ibc.WalletAmount{
Address: osmosisUser.Bech32Address(osmosis.Config().Bech32Prefix),
Denom: gaia.Config().Denom,
Amount: amountToSend,
},
nil,
)
}
tx, err := gaia.SendIBCTransfer(ctx, gaiaChannelID, gaiaUser.KeyName, transfer, ibc.TransferOptions{})
```

The `Exec` method allows any arbitrary command to be passed into a chain binary or relayer binary.
Expand Down
7 changes: 3 additions & 4 deletions examples/cosmos/light_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,12 @@ func TestUpdateLightClients(t *testing.T) {

amountToSend := int64(553255) // Unique amount to make log searching easier.
dstAddress := osmoUser.Bech32Address(osmosis.Config().Bech32Prefix)
tx, err := gaia.SendIBCTransfer(ctx, chanID, gaiaUser.KeyName, ibc.WalletAmount{
transfer := ibc.WalletAmount{
Address: dstAddress,
Denom: gaia.Config().Denom,
Amount: amountToSend,
},
nil,
)
}
tx, err := gaia.SendIBCTransfer(ctx, chanID, gaiaUser.KeyName, transfer, ibc.TransferOptions{})
require.NoError(t, err)
require.NoError(t, tx.Validate())

Expand Down
7 changes: 3 additions & 4 deletions examples/ibc/learn_ibc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,12 @@ func TestLearn(t *testing.T) {
// Send Transaction
amountToSend := int64(1_000_000)
dstAddress := osmosisUser.Bech32Address(osmosis.Config().Bech32Prefix)
tx, err := gaia.SendIBCTransfer(ctx, gaiaChannelID, gaiaUser.KeyName, ibc.WalletAmount{
transfer := ibc.WalletAmount{
Address: dstAddress,
Denom: gaia.Config().Denom,
Amount: amountToSend,
},
nil,
)
}
tx, err := gaia.SendIBCTransfer(ctx, gaiaChannelID, gaiaUser.KeyName, transfer, ibc.TransferOptions{})
require.NoError(t, err)
require.NoError(t, tx.Validate())

Expand Down
Loading

0 comments on commit 9af4ad0

Please sign in to comment.