Skip to content

Commit

Permalink
Test for AsyncSingleSender (E2E #6) (cosmos#1682)
Browse files Browse the repository at this point in the history
  • Loading branch information
chatton authored Jul 20, 2022
1 parent bdd797e commit 8987888
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 10 deletions.
125 changes: 120 additions & 5 deletions e2e/fee_middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import (
"github.com/strangelove-ventures/ibctest/broadcast"
"github.com/strangelove-ventures/ibctest/chain/cosmos"
"github.com/strangelove-ventures/ibctest/ibc"
"github.com/strangelove-ventures/ibctest/test"
"github.com/stretchr/testify/suite"

"e2e/testsuite"
"e2e/testvalues"

feetypes "github.com/cosmos/ibc-go/v4/modules/apps/29-fee/types"
channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types"
Expand Down Expand Up @@ -75,11 +77,124 @@ func (s *FeeMiddlewareTestSuite) QueryIncentivizedPacketsForChannel(
return res.IncentivizedPackets, err
}

func (s *FeeMiddlewareTestSuite) TestPlaceholder() {
ctx := context.Background()
r := s.SetupChainsRelayerAndChannel(ctx, feeMiddlewareChannelOptions())
s.T().Run("start relayer", func(t *testing.T) {
s.StartRelayer(r)
func (s *FeeMiddlewareTestSuite) TestMsgPayPacketFeeAsyncSingleSender() {
t := s.T()
ctx := context.TODO()

relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, feeMiddlewareChannelOptions())
chainA, chainB := s.GetChains()

var (
chainADenom = chainA.Config().Denom
testFee = testvalues.DefaultFee(chainADenom)
chainATx ibc.Tx
payPacketFeeTxResp sdk.TxResponse
)

chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount)

t.Run("relayer wallets recovered", func(t *testing.T) {
err := s.RecoverRelayerWallets(ctx, relayer)
s.Require().NoError(err)
})

chainARelayerWallet, chainBRelayerWallet, err := s.GetRelayerWallets(relayer)
t.Run("relayer wallets fetched", func(t *testing.T) {
s.Require().NoError(err)
})

s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks")

_, chainBRelayerUser := s.GetRelayerUsers(ctx)

t.Run("register counter party payee", func(t *testing.T) {
resp, err := s.RegisterCounterPartyPayee(ctx, chainB, chainBRelayerUser, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, chainBRelayerWallet.Address, chainARelayerWallet.Address)
s.Require().NoError(err)
s.AssertValidTxResponse(resp)
})

t.Run("verify counter party payee", func(t *testing.T) {
address, err := s.QueryCounterPartyPayee(ctx, chainB, chainBRelayerWallet.Address, channelA.Counterparty.ChannelID)
s.Require().NoError(err)
s.Require().Equal(chainARelayerWallet.Address, address)
})

walletAmount := ibc.WalletAmount{
Address: chainAWallet.Bech32Address(chainB.Config().Bech32Prefix), // destination address
Denom: chainADenom,
Amount: testvalues.IBCTransferAmount,
}

t.Run("send IBC transfer", func(t *testing.T) {
chainATx, err = chainA.SendIBCTransfer(ctx, channelA.ChannelID, chainAWallet.KeyName, walletAmount, nil)
s.Require().NoError(err)
s.Require().NoError(chainATx.Validate(), "chain-a ibc transfer tx is invalid")
})

t.Run("tokens are escrowed", func(t *testing.T) {
actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet)
s.Require().NoError(err)

expected := testvalues.StartingTokenAmount - walletAmount.Amount - chainA.GetGasFeesInNativeDenom(chainATx.GasSpent)
s.Require().Equal(expected, actualBalance)
})

t.Run("pay packet fee", func(t *testing.T) {
t.Run("no incentivized packets", func(t *testing.T) {
packets, err := s.QueryIncentivizedPacketsForChannel(ctx, chainA, channelA.PortID, channelA.ChannelID)
s.Require().NoError(err)
s.Require().Empty(packets)
})

packetId := channeltypes.NewPacketId(channelA.PortID, channelA.ChannelID, 1)
packetFee := feetypes.NewPacketFee(testFee, chainAWallet.Bech32Address(chainA.Config().Bech32Prefix), nil)

t.Run("should succeed", func(t *testing.T) {
payPacketFeeTxResp, err = s.PayPacketFeeAsync(ctx, chainA, chainAWallet, packetId, packetFee)
s.Require().NoError(err)
s.AssertValidTxResponse(payPacketFeeTxResp)
})

t.Run("there should be incentivized packets", func(t *testing.T) {
packets, err := s.QueryIncentivizedPacketsForChannel(ctx, chainA, channelA.PortID, channelA.ChannelID)
s.Require().NoError(err)
s.Require().Len(packets, 1)
actualFee := packets[0].PacketFees[0].Fee

s.Require().True(actualFee.RecvFee.IsEqual(testFee.RecvFee))
s.Require().True(actualFee.AckFee.IsEqual(testFee.AckFee))
s.Require().True(actualFee.TimeoutFee.IsEqual(testFee.TimeoutFee))
})

t.Run("balance should be lowered by sum of recv ack and timeout", func(t *testing.T) {
// The balance should be lowered by the sum of the recv, ack and timeout fees.
actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet)
s.Require().NoError(err)

gasFees := chainA.GetGasFeesInNativeDenom(chainATx.GasSpent) + chainA.GetGasFeesInNativeDenom(payPacketFeeTxResp.GasWanted)
expected := testvalues.StartingTokenAmount - walletAmount.Amount - gasFees - testFee.Total().AmountOf(chainADenom).Int64()
s.Require().Equal(expected, actualBalance)
})
})

t.Run("start relayer", func(t *testing.T) {
s.StartRelayer(relayer)
})

t.Run("packets are relayed", func(t *testing.T) {
packets, err := s.QueryIncentivizedPacketsForChannel(ctx, chainA, channelA.PortID, channelA.ChannelID)
s.Require().NoError(err)
s.Require().Empty(packets)
})

t.Run("timeout fee is refunded", func(t *testing.T) {
actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet)
s.Require().NoError(err)

gasFees := chainA.GetGasFeesInNativeDenom(chainATx.GasSpent) + chainA.GetGasFeesInNativeDenom(payPacketFeeTxResp.GasWanted)
// once the relayer has relayed the packets, the timeout fee should be refunded.
expected := testvalues.StartingTokenAmount - walletAmount.Amount - gasFees - testFee.AckFee.AmountOf(chainADenom).Int64() - testFee.RecvFee.AmountOf(chainADenom).Int64()
s.Require().Equal(expected, actualBalance)
})
}

Expand Down
6 changes: 3 additions & 3 deletions e2e/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ go 1.18
replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1

require (
github.com/cosmos/cosmos-sdk v0.45.6
github.com/cosmos/ibc-go/v4 v4.0.0-rc0
github.com/docker/docker v20.10.17+incompatible
github.com/strangelove-ventures/ibctest v0.0.0-20220713213153-930886d8db30
github.com/stretchr/testify v1.8.0
go.uber.org/zap v1.21.0
google.golang.org/grpc v1.47.0
)

require (
Expand All @@ -27,10 +30,8 @@ require (
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/confio/ics23/go v0.7.0 // indirect
github.com/cosmos/btcutil v1.0.4 // indirect
github.com/cosmos/cosmos-sdk v0.45.6 // indirect
github.com/cosmos/go-bip39 v1.0.0 // indirect
github.com/cosmos/iavl v0.17.3 // indirect
github.com/cosmos/ibc-go/v4 v4.0.0-rc0 // indirect
github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect
github.com/cosmos/ledger-go v0.9.2 // indirect
github.com/danieljoos/wincred v1.0.2 // indirect
Expand Down Expand Up @@ -124,7 +125,6 @@ require (
golang.org/x/tools v0.1.10 // indirect
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect
google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd // indirect
google.golang.org/grpc v1.47.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/ini.v1 v1.66.4 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
Expand Down
38 changes: 36 additions & 2 deletions e2e/testsuite/testsuite.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,33 @@ func newPath(chainA, chainB *cosmos.CosmosChain) path {
}
}

// GetRelayerUsers returns two ibctest.User instances which can be used for the relayer users
// on the two chains.
func (s *E2ETestSuite) GetRelayerUsers(ctx context.Context, chainOpts ...testconfig.ChainOptionConfiguration) (*ibctest.User, *ibctest.User) {
chainA, chainB := s.GetChains(chainOpts...)
chainAAccountBytes, err := chainA.GetAddress(ctx, ChainARelayerName)
s.Require().NoError(err)

chainBAccountBytes, err := chainB.GetAddress(ctx, ChainBRelayerName)
s.Require().NoError(err)

chainARelayerUser := ibctest.User{
Address: chainAAccountBytes,
KeyName: ChainARelayerName,
}

chainBRelayerUser := ibctest.User{
Address: chainBAccountBytes,
KeyName: ChainBRelayerName,
}
return &chainARelayerUser, &chainBRelayerUser
}

// SetupChainsRelayerAndChannel create two chains, a relayer, establishes a connection and creates a channel
// using the given channel options. The relayer returned by this function has not yet started. It should be started
// with E2ETestSuite.StartRelayer if needed.
// This should be called at the start of every test, unless fine grained control is required.
func (s *E2ETestSuite) SetupChainsRelayerAndChannel(ctx context.Context, channelOpts ...func(*ibc.CreateChannelOptions)) ibc.Relayer {
func (s *E2ETestSuite) SetupChainsRelayerAndChannel(ctx context.Context, channelOpts ...func(*ibc.CreateChannelOptions)) (ibc.Relayer, ibc.ChannelOutput) {
chainA, chainB := s.GetChains()
home, err := ioutil.TempDir("", "")
s.Require().NoError(err)
Expand Down Expand Up @@ -121,7 +143,9 @@ func (s *E2ETestSuite) SetupChainsRelayerAndChannel(ctx context.Context, channel
s.initGRPCClients(chainA)
s.initGRPCClients(chainB)

return r
chainAChannels, err := r.GetChannels(ctx, eRep, chainA.Config().ChainID)
s.Require().NoError(err)
return r, chainAChannels[len(chainAChannels)-1]
}

// GetChains returns two chains that can be used in a test. The pair returned
Expand Down Expand Up @@ -260,6 +284,16 @@ func (s *E2ETestSuite) initGRPCClients(chain *cosmos.CosmosChain) {
}
}

// AssertValidTxResponse verifies that an sdk.TxResponse
// has non-empty values.
func (s *E2ETestSuite) AssertValidTxResponse(resp sdk.TxResponse) {
respLogsMsg := resp.Logs.String()
s.Require().NotEqual(int64(0), resp.GasUsed, respLogsMsg)
s.Require().NotEqual(int64(0), resp.GasWanted, respLogsMsg)
s.Require().NotEmpty(resp.Events, respLogsMsg)
s.Require().NotEmpty(resp.Data, respLogsMsg)
}

// createCosmosChains creates two separate chains in docker containers.
// test and can be retrieved with GetChains.
func (s *E2ETestSuite) createCosmosChains(chainOptions testconfig.ChainOptions) (*cosmos.CosmosChain, *cosmos.CosmosChain) {
Expand Down
20 changes: 20 additions & 0 deletions e2e/testvalues/values.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package testvalues

import (
sdk "github.com/cosmos/cosmos-sdk/types"

feetypes "github.com/cosmos/ibc-go/v4/modules/apps/29-fee/types"
)

const (
StartingTokenAmount int64 = 10_000_000
IBCTransferAmount int64 = 10_000
)

func DefaultFee(denom string) feetypes.Fee {
return feetypes.Fee{
RecvFee: sdk.NewCoins(sdk.NewCoin(denom, sdk.NewInt(50))),
AckFee: sdk.NewCoins(sdk.NewCoin(denom, sdk.NewInt(25))),
TimeoutFee: sdk.NewCoins(sdk.NewCoin(denom, sdk.NewInt(10))),
}
}

0 comments on commit 8987888

Please sign in to comment.