Skip to content

Commit 83e2078

Browse files
committed
e2e: Ensure interchain workflow coverage equivalent to kurtosis testing
1 parent ff08965 commit 83e2078

File tree

6 files changed

+308
-4
lines changed

6 files changed

+308
-4
lines changed

tests/e2e/c/interchain_workflow.go

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved.
2+
// See the file LICENSE for licensing terms.
3+
4+
package c
5+
6+
import (
7+
ginkgo "github.com/onsi/ginkgo/v2"
8+
9+
"github.com/stretchr/testify/require"
10+
11+
"github.com/ava-labs/avalanchego/ids"
12+
"github.com/ava-labs/avalanchego/tests/e2e"
13+
"github.com/ava-labs/avalanchego/utils/constants"
14+
"github.com/ava-labs/avalanchego/utils/crypto/secp256k1"
15+
"github.com/ava-labs/avalanchego/utils/set"
16+
"github.com/ava-labs/avalanchego/utils/units"
17+
"github.com/ava-labs/avalanchego/vms/secp256k1fx"
18+
"github.com/ava-labs/avalanchego/wallet/subnet/primary/common"
19+
)
20+
21+
var _ = e2e.DescribeCChain("[Interchain Workflow]", func() {
22+
require := require.New(ginkgo.GinkgoT())
23+
24+
const transferAmount = 10 * units.Avax
25+
26+
ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() {
27+
ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to")
28+
factory := secp256k1.Factory{}
29+
recipientKey, err := factory.NewPrivateKey()
30+
require.NoError(err)
31+
keychain := e2e.Env.NewKeychain(1)
32+
keychain.Add(recipientKey)
33+
baseWallet := e2e.Env.NewWallet(keychain)
34+
xWallet := baseWallet.X()
35+
cWallet := baseWallet.C()
36+
pWallet := baseWallet.P()
37+
38+
ginkgo.By("defining common configuration")
39+
avaxAssetID := xWallet.AVAXAssetID()
40+
// Use the same owner for import funds to X-Chain and P-Chain
41+
recipientOwner := secp256k1fx.OutputOwners{
42+
Threshold: 1,
43+
Addrs: []ids.ShortID{
44+
recipientKey.Address(),
45+
},
46+
}
47+
// Use the same outputs for both X-Chain and P-Chain exports
48+
exportOutputs := []*secp256k1fx.TransferOutput{
49+
{
50+
Amt: transferAmount,
51+
OutputOwners: secp256k1fx.OutputOwners{
52+
Threshold: 1,
53+
Addrs: []ids.ShortID{
54+
keychain.Keys[0].Address(),
55+
},
56+
},
57+
},
58+
}
59+
60+
ginkgo.By("sending funds from one address to another on the C-Chain", func() {
61+
// TODO(marun)
62+
})
63+
64+
ginkgo.By("checking that the recipient address received funds on the C-Chain", func() {
65+
// TODO(marun)
66+
})
67+
68+
ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() {
69+
_, err := cWallet.IssueExportTx(
70+
xWallet.BlockchainID(),
71+
exportOutputs,
72+
e2e.WithDefaultContext(),
73+
)
74+
require.NoError(err)
75+
})
76+
77+
ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() {
78+
_, err := xWallet.IssueImportTx(
79+
cWallet.BlockchainID(),
80+
&recipientOwner,
81+
e2e.WithDefaultContext(),
82+
)
83+
require.NoError(err)
84+
})
85+
86+
ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() {
87+
balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of(
88+
recipientKey.Address(),
89+
)))
90+
require.NoError(err)
91+
require.Greater(balances[avaxAssetID], uint64(0))
92+
})
93+
94+
ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() {
95+
_, err := cWallet.IssueExportTx(
96+
constants.PlatformChainID,
97+
exportOutputs,
98+
e2e.WithDefaultContext(),
99+
)
100+
require.NoError(err)
101+
})
102+
103+
ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() {
104+
_, err := pWallet.IssueImportTx(
105+
cWallet.BlockchainID(),
106+
&recipientOwner,
107+
e2e.WithDefaultContext(),
108+
)
109+
require.NoError(err)
110+
})
111+
112+
ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() {
113+
balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of(
114+
recipientKey.Address(),
115+
)))
116+
require.NoError(err)
117+
require.Greater(balances[avaxAssetID], uint64(0))
118+
})
119+
})
120+
})

tests/e2e/describe.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,9 @@ func DescribeXChainSerial(text string, body func()) bool {
2424
func DescribePChain(text string, body func()) bool {
2525
return ginkgo.Describe("[P-Chain] "+text, body)
2626
}
27+
28+
// DescribeCChain annotates the tests for C-Chain.
29+
// Can run with any type of cluster (e.g., local, fuji, mainnet).
30+
func DescribeCChain(text string, body func()) bool {
31+
return ginkgo.Describe("[C-Chain] "+text, body)
32+
}

tests/e2e/e2e.go

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,25 @@ package e2e
77
import (
88
"context"
99
"encoding/json"
10+
"fmt"
1011
"math/rand"
12+
"strings"
1113
"time"
1214

1315
ginkgo "github.com/onsi/ginkgo/v2"
1416

1517
"github.com/stretchr/testify/require"
1618

19+
"github.com/ava-labs/coreth/ethclient"
20+
1721
"github.com/ava-labs/avalanchego/tests"
1822
"github.com/ava-labs/avalanchego/tests/fixture"
1923
"github.com/ava-labs/avalanchego/tests/fixture/testnet"
2024
"github.com/ava-labs/avalanchego/tests/fixture/testnet/local"
2125
"github.com/ava-labs/avalanchego/utils/crypto/secp256k1"
2226
"github.com/ava-labs/avalanchego/vms/secp256k1fx"
2327
"github.com/ava-labs/avalanchego/wallet/subnet/primary"
28+
"github.com/ava-labs/avalanchego/wallet/subnet/primary/common"
2429
)
2530

2631
const (
@@ -101,13 +106,38 @@ func (te *TestEnvironment) NewKeychain(count int) *secp256k1fx.Keychain {
101106
// Create a new wallet for the provided keychain.
102107
func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain) primary.Wallet {
103108
tests.Outf("{{blue}} initializing a new wallet {{/}}\n")
104-
ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout)
105-
defer cancel()
106-
wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{
109+
wallet, err := primary.MakeWallet(DefaultContext(), &primary.WalletConfig{
107110
URI: te.GetRandomNodeURI(),
108111
AVAXKeychain: keychain,
109112
EthKeychain: keychain,
110113
})
111114
te.require.NoError(err)
112115
return wallet
113116
}
117+
118+
// Create a new eth client targeting a random node.
119+
func (te *TestEnvironment) NewEthClient() ethclient.Client {
120+
nodeURI := te.GetRandomNodeURI()
121+
nodeAddress := strings.Split(nodeURI, "//")[1]
122+
uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress)
123+
client, err := ethclient.Dial(uri)
124+
te.require.NoError(err)
125+
return client
126+
}
127+
128+
// Helper simplifying use of a timed context by canceling the context on ginkgo teardown.
129+
func ContextWithTimeout(duration time.Duration) context.Context {
130+
ctx, cancel := context.WithTimeout(context.Background(), duration)
131+
ginkgo.DeferCleanup(cancel)
132+
return ctx
133+
}
134+
135+
// Helper simplifying use of a timed context configured with the default timeout.
136+
func DefaultContext() context.Context {
137+
return ContextWithTimeout(DefaultTimeout)
138+
}
139+
140+
// Helper simplifying use via an option of a timed context configured with the default timeout.
141+
func WithDefaultContext() common.Option {
142+
return common.WithContext(DefaultContext())
143+
}

tests/e2e/e2e_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ import (
2525

2626
// ensure test packages are scanned by ginkgo
2727
_ "github.com/ava-labs/avalanchego/tests/e2e/banff"
28+
_ "github.com/ava-labs/avalanchego/tests/e2e/c"
2829
_ "github.com/ava-labs/avalanchego/tests/e2e/p"
2930
_ "github.com/ava-labs/avalanchego/tests/e2e/static-handlers"
31+
_ "github.com/ava-labs/avalanchego/tests/e2e/x"
3032
_ "github.com/ava-labs/avalanchego/tests/e2e/x/transfer"
3133
)
3234

tests/e2e/x/interchain_workflow.go

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved.
2+
// See the file LICENSE for licensing terms.
3+
4+
package x
5+
6+
import (
7+
"math/big"
8+
9+
ginkgo "github.com/onsi/ginkgo/v2"
10+
11+
"github.com/stretchr/testify/require"
12+
13+
"github.com/ava-labs/coreth/plugin/evm"
14+
15+
"github.com/ava-labs/avalanchego/ids"
16+
"github.com/ava-labs/avalanchego/tests/e2e"
17+
"github.com/ava-labs/avalanchego/utils/constants"
18+
"github.com/ava-labs/avalanchego/utils/crypto/secp256k1"
19+
"github.com/ava-labs/avalanchego/utils/set"
20+
"github.com/ava-labs/avalanchego/utils/units"
21+
"github.com/ava-labs/avalanchego/vms/components/avax"
22+
"github.com/ava-labs/avalanchego/vms/secp256k1fx"
23+
"github.com/ava-labs/avalanchego/wallet/subnet/primary/common"
24+
)
25+
26+
var _ = e2e.DescribeXChain("[Interchain Workflow]", func() {
27+
require := require.New(ginkgo.GinkgoT())
28+
29+
const transferAmount = 10 * units.Avax
30+
31+
ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() {
32+
ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to")
33+
factory := secp256k1.Factory{}
34+
recipientKey, err := factory.NewPrivateKey()
35+
require.NoError(err)
36+
keychain := e2e.Env.NewKeychain(1)
37+
keychain.Add(recipientKey)
38+
baseWallet := e2e.Env.NewWallet(keychain)
39+
xWallet := baseWallet.X()
40+
cWallet := baseWallet.C()
41+
pWallet := baseWallet.P()
42+
43+
ginkgo.By("defining common configuration")
44+
recipientEthAddress := evm.GetEthAddress(recipientKey)
45+
avaxAssetID := xWallet.AVAXAssetID()
46+
// Use the same owner for sending to X-Chain and importing funds to P-Chain
47+
recipientOwner := secp256k1fx.OutputOwners{
48+
Threshold: 1,
49+
Addrs: []ids.ShortID{
50+
recipientKey.Address(),
51+
},
52+
}
53+
// Use the same outputs for both C-Chain and P-Chain exports
54+
exportOutputs := []*avax.TransferableOutput{
55+
{
56+
Asset: avax.Asset{
57+
ID: avaxAssetID,
58+
},
59+
Out: &secp256k1fx.TransferOutput{
60+
Amt: transferAmount,
61+
OutputOwners: secp256k1fx.OutputOwners{
62+
Threshold: 1,
63+
Addrs: []ids.ShortID{
64+
keychain.Keys[0].Address(),
65+
},
66+
},
67+
},
68+
},
69+
}
70+
71+
ginkgo.By("sending funds from one address to another on the X-Chain", func() {
72+
_, err = xWallet.IssueBaseTx(
73+
[]*avax.TransferableOutput{{
74+
Asset: avax.Asset{
75+
ID: avaxAssetID,
76+
},
77+
Out: &secp256k1fx.TransferOutput{
78+
Amt: transferAmount,
79+
OutputOwners: recipientOwner,
80+
},
81+
}},
82+
e2e.WithDefaultContext(),
83+
)
84+
require.NoError(err)
85+
})
86+
87+
ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() {
88+
balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of(
89+
recipientKey.Address(),
90+
)))
91+
require.NoError(err)
92+
require.Greater(balances[avaxAssetID], uint64(0))
93+
})
94+
95+
ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() {
96+
_, err := xWallet.IssueExportTx(
97+
cWallet.BlockchainID(),
98+
exportOutputs,
99+
e2e.WithDefaultContext(),
100+
)
101+
require.NoError(err)
102+
})
103+
104+
ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() {
105+
_, err := cWallet.IssueImportTx(
106+
xWallet.BlockchainID(),
107+
recipientEthAddress,
108+
e2e.WithDefaultContext(),
109+
)
110+
require.NoError(err)
111+
})
112+
113+
ginkgo.By("checking that the recipient address has received imported funds on the C-Chain", func() {
114+
ethClient := e2e.Env.NewEthClient()
115+
balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil)
116+
require.NoError(err)
117+
require.Greater(balance.Cmp(big.NewInt(0)), 0)
118+
})
119+
120+
ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() {
121+
_, err := xWallet.IssueExportTx(
122+
constants.PlatformChainID,
123+
exportOutputs,
124+
e2e.WithDefaultContext(),
125+
)
126+
require.NoError(err)
127+
})
128+
129+
ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() {
130+
_, err := pWallet.IssueImportTx(
131+
xWallet.BlockchainID(),
132+
&recipientOwner,
133+
e2e.WithDefaultContext(),
134+
)
135+
require.NoError(err)
136+
})
137+
138+
ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() {
139+
balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of(
140+
recipientKey.Address(),
141+
)))
142+
require.NoError(err)
143+
require.Greater(balances[avaxAssetID], uint64(0))
144+
})
145+
})
146+
})

tests/e2e/x/transfer/virtuous.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ var _ = e2e.DescribeXChainSerial("[Virtuous Transfer Tx AVAX]", func() {
6868
metricBlksAccepted,
6969
}
7070

71-
// Ensure the same set of 10 keys are used for all tests
71+
// Ensure the same set of 10 keys is used for all tests
7272
// by retrieving them outside of runFunc.
7373
testKeys := e2e.Env.AllocateFundedKeys(10)
7474

0 commit comments

Comments
 (0)