Skip to content

Commit

Permalink
test: e2e for pfm
Browse files Browse the repository at this point in the history
  • Loading branch information
javiersuweijie committed Aug 30, 2023
1 parent 9220bc5 commit 6ada68d
Show file tree
Hide file tree
Showing 3 changed files with 342 additions and 54 deletions.
60 changes: 60 additions & 0 deletions interchaintest/config.go
Original file line number Diff line number Diff line change
@@ -1 +1,61 @@
package interchaintest

import (
"fmt"

"github.com/strangelove-ventures/interchaintest/v7/chain/cosmos"
"github.com/strangelove-ventures/interchaintest/v7/ibc"

"github.com/cosmos/cosmos-sdk/types/module/testutil"
)

var (
Denom = "uluna"
VotingPeriod = "15s"
MaxDepositPeriod = "10s"
Image = ibc.DockerImage{
Repository: "terramoneycore",
Version: "latest",
UidGid: "1025:1025",
}
IBCRelayerImage = "ghcr.io/cosmos/relayer"
IBCRelayerVersion = "main"
config = ibc.ChainConfig{
Type: "cosmos",
Name: "terra",
ChainID: "phoenix-1",
Images: []ibc.DockerImage{Image},
Bin: "terrad",
Bech32Prefix: "terra",
Denom: Denom,
CoinType: "330",
GasPrices: fmt.Sprintf("0%s", Denom),
GasAdjustment: 2.0,
TrustingPeriod: "112h",
NoHostMount: false,
ConfigFileOverrides: nil,
EncodingConfig: encoding(),
UsingNewGenesisCommand: true,
ModifyGenesis: cosmos.ModifyGenesis(defaultGenesisKV),
}
// SDK v47 Genesis
defaultGenesisKV = []cosmos.GenesisKV{
{
Key: "app_state.gov.params.voting_period",
Value: VotingPeriod,
},
{
Key: "app_state.gov.params.max_deposit_period",
Value: MaxDepositPeriod,
},
{
Key: "app_state.gov.params.min_deposit.0.denom",
Value: Denom,
},
}
)

func encoding() *testutil.TestEncodingConfig {
cfg := cosmos.DefaultEncoding()
return &cfg
}
276 changes: 276 additions & 0 deletions interchaintest/pmf_test.go
Original file line number Diff line number Diff line change
@@ -1 +1,277 @@
package interchaintest

import (
"context"
"encoding/json"
"testing"
"time"

"github.com/strangelove-ventures/interchaintest/v7"
"github.com/strangelove-ventures/interchaintest/v7/chain/cosmos"
"github.com/strangelove-ventures/interchaintest/v7/ibc"
interchaintestrelayer "github.com/strangelove-ventures/interchaintest/v7/relayer"
"github.com/strangelove-ventures/interchaintest/v7/testreporter"
"github.com/strangelove-ventures/interchaintest/v7/testutil"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"

transfertypes "github.com/cosmos/ibc-go/v7/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"`
}

// TestPacketForwardMiddlewareRouter ensures the PFM module is set up properly and works as expected.
func TestPMF(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, chainID_D = "chain-a", "chain-b", "chain-c", "chain-d"
chainA, chainB, chainC, chainD *cosmos.CosmosChain
)

baseCfg := config

// 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

baseCfg.ChainID = chainID_D
configD := baseCfg

// Create chain factory with multiple Juno individual networks.
numVals := 1
numFullNodes := 0

cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
{
Name: "juno",
ChainConfig: configA,
NumValidators: &numVals,
NumFullNodes: &numFullNodes,
},
{
Name: "juno",
ChainConfig: configB,
NumValidators: &numVals,
NumFullNodes: &numFullNodes,
},
{
Name: "juno",
ChainConfig: configC,
NumValidators: &numVals,
NumFullNodes: &numFullNodes,
},
{
Name: "juno",
ChainConfig: configD,
NumValidators: &numVals,
NumFullNodes: &numFullNodes,
},
})

// Get chains from the chain factory
chains, err := cf.Chains(t.Name())
require.NoError(t, err)

chainA, chainB, chainC, chainD = chains[0].(*cosmos.CosmosChain), chains[1].(*cosmos.CosmosChain), chains[2].(*cosmos.CosmosChain), chains[3].(*cosmos.CosmosChain)

r := interchaintest.NewBuiltinRelayerFactory(
ibc.CosmosRly,
zaptest.NewLogger(t),
interchaintestrelayer.CustomDockerImage(IBCRelayerImage, IBCRelayerVersion, "100:1000"),
interchaintestrelayer.StartupFlags("--processor", "events", "--block-history", "100"),
).Build(t, client, network)

const pathAB = "ab"
const pathBC = "bc"
const pathCD = "cd"

ic := interchaintest.NewInterchain().
AddChain(chainA).
AddChain(chainB).
AddChain(chainC).
AddChain(chainD).
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,
}).
AddLink(interchaintest.InterchainLink{
Chain1: chainC,
Chain2: chainD,
Relayer: r,
Path: pathCD,
})

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()
})

const userFunds = int64(10_000_000_000)
users := interchaintest.GetAndFundTestUsers(t, ctx, t.Name(), userFunds, chainA, chainB, chainC, chainD)

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

dcChan, err := ibc.GetTransferChannel(ctx, r, eRep, chainID_D, chainID_C)
require.NoError(t, err)

cdChan := dcChan.Counterparty

// Start the relayer on all paths
err = r.StartRelayer(ctx, eRep, pathAB, pathBC, pathCD)
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, userD := users[0], users[1], users[2], users[3]

const transferAmount int64 = 100000

// 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)
thirdHopDenom := transfertypes.GetPrefixedDenom(dcChan.PortID, dcChan.ChannelID, secondHopDenom)

firstHopDenomTrace := transfertypes.ParseDenomTrace(firstHopDenom)
secondHopDenomTrace := transfertypes.ParseDenomTrace(secondHopDenom)
thirdHopDenomTrace := transfertypes.ParseDenomTrace(thirdHopDenom)

firstHopIBCDenom := firstHopDenomTrace.IBCDenom()
secondHopIBCDenom := secondHopDenomTrace.IBCDenom()
thirdHopIBCDenom := thirdHopDenomTrace.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))
thirdHopEscrowAccount := sdk.MustBech32ifyAddressBytes(chainC.Config().Bech32Prefix, transfertypes.GetEscrowAddress(cdChan.PortID, abChan.ChannelID))

t.Run("multi-hop a->b->c->d", func(t *testing.T) {
// Send packet from Chain A->Chain B->Chain C->Chain D

transfer := ibc.WalletAmount{
Address: userB.FormattedAddress(),
Denom: chainA.Config().Denom,
Amount: transferAmount,
}

secondHopMetadata := &PacketMetadata{
Forward: &ForwardMetadata{
Receiver: userD.FormattedAddress(),
Channel: cdChan.ChannelID,
Port: cdChan.PortID,
},
}
nextBz, err := json.Marshal(secondHopMetadata)
require.NoError(t, err)
next := string(nextBz)

firstHopMetadata := &PacketMetadata{
Forward: &ForwardMetadata{
Receiver: userC.FormattedAddress(),
Channel: bcChan.ChannelID,
Port: bcChan.PortID,
Next: &next,
},
}

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)

chainDBalance, err := chainD.GetBalance(ctx, userD.FormattedAddress(), thirdHopIBCDenom)
require.NoError(t, err)

require.Equal(t, userFunds-transferAmount, chainABalance)
require.Equal(t, int64(0), chainBBalance)
require.Equal(t, int64(0), chainCBalance)
require.Equal(t, transferAmount, chainDBalance)

firstHopEscrowBalance, err := chainA.GetBalance(ctx, firstHopEscrowAccount, chainA.Config().Denom)
require.NoError(t, err)

secondHopEscrowBalance, err := chainB.GetBalance(ctx, secondHopEscrowAccount, firstHopIBCDenom)
require.NoError(t, err)

thirdHopEscrowBalance, err := chainC.GetBalance(ctx, thirdHopEscrowAccount, secondHopIBCDenom)
require.NoError(t, err)

require.Equal(t, transferAmount, firstHopEscrowBalance)
require.Equal(t, transferAmount, secondHopEscrowBalance)
require.Equal(t, transferAmount, thirdHopEscrowBalance)
})
}
Loading

0 comments on commit 6ada68d

Please sign in to comment.