mirror of
https://github.com/onsonr/sonr.git
synced 2025-03-10 21:09:11 +00:00
232 lines
7.1 KiB
Go
232 lines
7.1 KiB
Go
|
package e2e
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"encoding/json"
|
||
|
"testing"
|
||
|
"time"
|
||
|
|
||
|
"cosmossdk.io/math"
|
||
|
"github.com/strangelove-ventures/interchaintest/v8"
|
||
|
"github.com/strangelove-ventures/interchaintest/v8/chain/cosmos"
|
||
|
"github.com/strangelove-ventures/interchaintest/v8/ibc"
|
||
|
interchaintestrelayer "github.com/strangelove-ventures/interchaintest/v8/relayer"
|
||
|
"github.com/strangelove-ventures/interchaintest/v8/testreporter"
|
||
|
"github.com/strangelove-ventures/interchaintest/v8/testutil"
|
||
|
"github.com/stretchr/testify/require"
|
||
|
"go.uber.org/zap/zaptest"
|
||
|
|
||
|
transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types"
|
||
|
|
||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||
|
)
|
||
|
|
||
|
type PacketMetadata struct {
|
||
|
Forward *ForwardMetadata `json:"forward"`
|
||
|
}
|
||
|
|
||
|
type ForwardMetadata struct {
|
||
|
Receiver string `json:"receiver"`
|
||
|
Port string `json:"port"`
|
||
|
Channel string `json:"channel"`
|
||
|
Timeout time.Duration `json:"timeout"`
|
||
|
Retries *uint8 `json:"retries,omitempty"`
|
||
|
Next *string `json:"next,omitempty"`
|
||
|
RefundSequence *uint64 `json:"refund_sequence,omitempty"`
|
||
|
}
|
||
|
|
||
|
func TestPacketForwardMiddleware(t *testing.T) {
|
||
|
if testing.Short() {
|
||
|
t.Skip()
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
ctx = context.Background()
|
||
|
client, network = interchaintest.DockerSetup(t)
|
||
|
rep = testreporter.NewNopReporter()
|
||
|
eRep = rep.RelayerExecReporter(t)
|
||
|
chainID_A, chainID_B, chainID_C = "chain-a", "chain-b", "chain-c"
|
||
|
chainA, chainB, chainC *cosmos.CosmosChain
|
||
|
)
|
||
|
|
||
|
// base config which all networks will use as defaults.
|
||
|
baseCfg := DefaultChainConfig
|
||
|
|
||
|
// Set specific chain ids for each so they are their own unique networks
|
||
|
baseCfg.ChainID = chainID_A
|
||
|
configA := baseCfg
|
||
|
|
||
|
baseCfg.ChainID = chainID_B
|
||
|
configB := baseCfg
|
||
|
|
||
|
baseCfg.ChainID = chainID_C
|
||
|
configC := baseCfg
|
||
|
|
||
|
// Create chain factory with multiple individual networks.
|
||
|
numVals := 1
|
||
|
numFullNodes := 0
|
||
|
|
||
|
cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
|
||
|
{
|
||
|
Name: configA.Name,
|
||
|
ChainConfig: configA,
|
||
|
NumValidators: &numVals,
|
||
|
NumFullNodes: &numFullNodes,
|
||
|
},
|
||
|
{
|
||
|
Name: configA.Name,
|
||
|
ChainConfig: configB,
|
||
|
NumValidators: &numVals,
|
||
|
NumFullNodes: &numFullNodes,
|
||
|
},
|
||
|
{
|
||
|
Name: configA.Name,
|
||
|
ChainConfig: configC,
|
||
|
NumValidators: &numVals,
|
||
|
NumFullNodes: &numFullNodes,
|
||
|
},
|
||
|
})
|
||
|
|
||
|
// Get chains from the chain factory
|
||
|
chains, err := cf.Chains(t.Name())
|
||
|
require.NoError(t, err)
|
||
|
|
||
|
chainA, chainB, chainC = chains[0].(*cosmos.CosmosChain), chains[1].(*cosmos.CosmosChain), chains[2].(*cosmos.CosmosChain)
|
||
|
|
||
|
r := interchaintest.NewBuiltinRelayerFactory(
|
||
|
ibc.CosmosRly,
|
||
|
zaptest.NewLogger(t),
|
||
|
interchaintestrelayer.CustomDockerImage(RelayerRepo, RelayerVersion, "100:1000"),
|
||
|
interchaintestrelayer.StartupFlags("--processor", "events", "--block-history", "100"),
|
||
|
).Build(t, client, network)
|
||
|
|
||
|
const pathAB = "ab"
|
||
|
const pathBC = "bc"
|
||
|
|
||
|
ic := interchaintest.NewInterchain().
|
||
|
AddChain(chainA).
|
||
|
AddChain(chainB).
|
||
|
AddChain(chainC).
|
||
|
AddRelayer(r, "relayer").
|
||
|
AddLink(interchaintest.InterchainLink{
|
||
|
Chain1: chainA,
|
||
|
Chain2: chainB,
|
||
|
Relayer: r,
|
||
|
Path: pathAB,
|
||
|
}).
|
||
|
AddLink(interchaintest.InterchainLink{
|
||
|
Chain1: chainB,
|
||
|
Chain2: chainC,
|
||
|
Relayer: r,
|
||
|
Path: pathBC,
|
||
|
})
|
||
|
|
||
|
require.NoError(t, ic.Build(ctx, eRep, interchaintest.InterchainBuildOptions{
|
||
|
TestName: t.Name(),
|
||
|
Client: client,
|
||
|
NetworkID: network,
|
||
|
BlockDatabaseFile: interchaintest.DefaultBlockDatabaseFilepath(),
|
||
|
|
||
|
SkipPathCreation: false,
|
||
|
}))
|
||
|
t.Cleanup(func() {
|
||
|
_ = ic.Close()
|
||
|
})
|
||
|
|
||
|
users := interchaintest.GetAndFundTestUsers(t, ctx, t.Name(), GenesisFundsAmount, chainA, chainB, chainC)
|
||
|
|
||
|
abChan, err := ibc.GetTransferChannel(ctx, r, eRep, chainID_A, chainID_B)
|
||
|
require.NoError(t, err)
|
||
|
|
||
|
baChan := abChan.Counterparty
|
||
|
|
||
|
cbChan, err := ibc.GetTransferChannel(ctx, r, eRep, chainID_C, chainID_B)
|
||
|
require.NoError(t, err)
|
||
|
|
||
|
bcChan := cbChan.Counterparty
|
||
|
|
||
|
// Start the relayer on all paths
|
||
|
err = r.StartRelayer(ctx, eRep, pathAB, pathBC)
|
||
|
require.NoError(t, err)
|
||
|
|
||
|
t.Cleanup(
|
||
|
func() {
|
||
|
err := r.StopRelayer(ctx, eRep)
|
||
|
if err != nil {
|
||
|
t.Logf("an error occurred while stopping the relayer: %s", err)
|
||
|
}
|
||
|
},
|
||
|
)
|
||
|
|
||
|
// Get original account balances
|
||
|
userA, userB, userC := users[0], users[1], users[2]
|
||
|
|
||
|
var transferAmount math.Int = math.NewInt(100_000)
|
||
|
|
||
|
// Compose the prefixed denoms and ibc denom for asserting balances
|
||
|
firstHopDenom := transfertypes.GetPrefixedDenom(baChan.PortID, baChan.ChannelID, chainA.Config().Denom)
|
||
|
secondHopDenom := transfertypes.GetPrefixedDenom(cbChan.PortID, cbChan.ChannelID, firstHopDenom)
|
||
|
|
||
|
firstHopDenomTrace := transfertypes.ParseDenomTrace(firstHopDenom)
|
||
|
secondHopDenomTrace := transfertypes.ParseDenomTrace(secondHopDenom)
|
||
|
|
||
|
firstHopIBCDenom := firstHopDenomTrace.IBCDenom()
|
||
|
secondHopIBCDenom := secondHopDenomTrace.IBCDenom()
|
||
|
|
||
|
firstHopEscrowAccount := sdk.MustBech32ifyAddressBytes(chainA.Config().Bech32Prefix, transfertypes.GetEscrowAddress(abChan.PortID, abChan.ChannelID))
|
||
|
secondHopEscrowAccount := sdk.MustBech32ifyAddressBytes(chainB.Config().Bech32Prefix, transfertypes.GetEscrowAddress(bcChan.PortID, bcChan.ChannelID))
|
||
|
|
||
|
t.Run("multi-hop a->b->c", func(t *testing.T) {
|
||
|
// Send packet from Chain A->Chain B->Chain C
|
||
|
|
||
|
transfer := ibc.WalletAmount{
|
||
|
Address: userB.FormattedAddress(),
|
||
|
Denom: chainA.Config().Denom,
|
||
|
Amount: transferAmount,
|
||
|
}
|
||
|
|
||
|
firstHopMetadata := &PacketMetadata{
|
||
|
Forward: &ForwardMetadata{
|
||
|
Receiver: userC.FormattedAddress(),
|
||
|
Channel: bcChan.ChannelID,
|
||
|
Port: bcChan.PortID,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
memo, err := json.Marshal(firstHopMetadata)
|
||
|
require.NoError(t, err)
|
||
|
|
||
|
chainAHeight, err := chainA.Height(ctx)
|
||
|
require.NoError(t, err)
|
||
|
|
||
|
transferTx, err := chainA.SendIBCTransfer(ctx, abChan.ChannelID, userA.KeyName(), transfer, ibc.TransferOptions{Memo: string(memo)})
|
||
|
require.NoError(t, err)
|
||
|
_, err = testutil.PollForAck(ctx, chainA, chainAHeight, chainAHeight+30, transferTx.Packet)
|
||
|
require.NoError(t, err)
|
||
|
err = testutil.WaitForBlocks(ctx, 1, chainA)
|
||
|
require.NoError(t, err)
|
||
|
|
||
|
chainABalance, err := chainA.GetBalance(ctx, userA.FormattedAddress(), chainA.Config().Denom)
|
||
|
require.NoError(t, err)
|
||
|
|
||
|
chainBBalance, err := chainB.GetBalance(ctx, userB.FormattedAddress(), firstHopIBCDenom)
|
||
|
require.NoError(t, err)
|
||
|
|
||
|
chainCBalance, err := chainC.GetBalance(ctx, userC.FormattedAddress(), secondHopIBCDenom)
|
||
|
require.NoError(t, err)
|
||
|
|
||
|
require.Equal(t, GenesisFundsAmount.Sub(transferAmount).Int64(), chainABalance.Int64())
|
||
|
require.Equal(t, int64(0), chainBBalance.Int64())
|
||
|
require.Equal(t, int64(100000), chainCBalance.Int64())
|
||
|
|
||
|
firstHopEscrowBalance, err := chainA.GetBalance(ctx, firstHopEscrowAccount, chainA.Config().Denom)
|
||
|
require.NoError(t, err)
|
||
|
|
||
|
secondHopEscrowBalance, err := chainB.GetBalance(ctx, secondHopEscrowAccount, firstHopIBCDenom)
|
||
|
require.NoError(t, err)
|
||
|
|
||
|
require.Equal(t, transferAmount.Int64(), firstHopEscrowBalance.Int64())
|
||
|
require.Equal(t, transferAmount.Int64(), secondHopEscrowBalance.Int64())
|
||
|
})
|
||
|
}
|