diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 905366de7..ae3f61dd5 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -19,6 +19,7 @@ jobs: "\\[Error handling\\]", "\\[Key\\]", "\\[ICM\\]", + "\\[Relayer\\]", "\\[Local Network\\]", "\\[Network\\]", "\\[Blockchain Configure\\]", diff --git a/cmd/interchaincmd/relayercmd/deploy.go b/cmd/interchaincmd/relayercmd/deploy.go index 25de7cec5..e69b45b04 100644 --- a/cmd/interchaincmd/relayercmd/deploy.go +++ b/cmd/interchaincmd/relayercmd/deploy.go @@ -72,7 +72,7 @@ func newDeployCmd() *cobra.Command { cmd.Flags().Float64Var(&deployFlags.CChainAmount, "cchain-amount", 0, "automatically fund cchain fee payments with the given amount") cmd.Flags().StringVar(&deployFlags.BlockchainFundingKey, "blockchain-funding-key", "", "key to be used to fund relayer account on all l1s") cmd.Flags().StringVar(&deployFlags.CChainFundingKey, "cchain-funding-key", "", "key to be used to fund relayer account on cchain") - cmd.Flags().BoolVar(&deployFlags.AllowPrivateIPs, "allow-private-ips", true, "allow relayer to connec to private ips") + cmd.Flags().BoolVar(&deployFlags.AllowPrivateIPs, "allow-private-ips", true, "allow relayer to connect to private ips") return cmd } @@ -134,25 +134,30 @@ func CallDeploy(_ []string, flags DeployFlags, network models.Network) error { } } + logLevelOptions := []string{ + logging.Info.LowerString(), + logging.Warn.LowerString(), + logging.Error.LowerString(), + logging.Off.LowerString(), + logging.Fatal.LowerString(), + logging.Debug.LowerString(), + logging.Trace.LowerString(), + logging.Verbo.LowerString(), + } if flags.LogLevel == "" { prompt := "Which log level do you prefer for your relayer?" - options := []string{ - logging.Info.LowerString(), - logging.Warn.LowerString(), - logging.Error.LowerString(), - logging.Off.LowerString(), - logging.Fatal.LowerString(), - logging.Debug.LowerString(), - logging.Trace.LowerString(), - logging.Verbo.LowerString(), - } + flags.LogLevel, err = app.Prompt.CaptureList( prompt, - options, + logLevelOptions, ) if err != nil { return err } + } else { + if _, err := logging.ToLevel(flags.LogLevel); err != nil { + return fmt.Errorf("invalid log level %s: %w", flags.LogLevel, err) + } } networkUP := true @@ -375,7 +380,7 @@ func CallDeploy(_ []string, flags DeployFlags, network models.Network) error { return err } if balance.Cmp(big.NewInt(0)) == 0 { - return fmt.Errorf("destination %s funding key as no balance", destination.blockchainDesc) + return fmt.Errorf("destination %s funding key has no balance", destination.blockchainDesc) } balanceBigFlt := new(big.Float).SetInt(balance) balanceBigFlt = balanceBigFlt.Quo(balanceBigFlt, new(big.Float).SetInt(vm.OneAvax)) @@ -415,9 +420,13 @@ func CallDeploy(_ []string, flags DeployFlags, network models.Network) error { amountBigFlt := new(big.Float).SetFloat64(amountFlt) amountBigFlt = amountBigFlt.Mul(amountBigFlt, new(big.Float).SetInt(vm.OneAvax)) amount, _ := amountBigFlt.Int(nil) - if _, err := client.FundAddress(privateKey, addr.Hex(), amount); err != nil { + receipt, err := client.FundAddress(privateKey, addr.Hex(), amount) + if err != nil { return err } + ux.Logger.PrintToUser("%s Paid fee: %.9f AVAX", + destination.blockchainDesc, + evm.CalculateEvmFeeInAvax(receipt.GasUsed, receipt.EffectiveGasPrice)) } } } diff --git a/cmd/keycmd/list.go b/cmd/keycmd/list.go index d477a6b60..1d2cdd597 100644 --- a/cmd/keycmd/list.go +++ b/cmd/keycmd/list.go @@ -14,6 +14,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/networkoptions" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" + "github.com/ava-labs/avalanche-cli/sdk/evm" sdkUtils "github.com/ava-labs/avalanche-cli/sdk/utils" "github.com/ava-labs/avalanchego/ids" ledger "github.com/ava-labs/avalanchego/utils/crypto/ledger" @@ -653,7 +654,7 @@ func formatCChainBalance(balance *big.Int) (string, error) { return fmt.Sprintf("%d", balance), nil } - result := utils.ConvertToNanoAvax(balance) + result := evm.ConvertToNanoAvax(balance) if result.Cmp(big.NewInt(0)) == 0 { return "0", nil } diff --git a/cmd/keycmd/transfer.go b/cmd/keycmd/transfer.go index 109212716..c2a215482 100644 --- a/cmd/keycmd/transfer.go +++ b/cmd/keycmd/transfer.go @@ -455,7 +455,7 @@ func intraEvmSend( } ux.Logger.PrintToUser("%s Paid fee: %.9f AVAX", chainName, - calculateEvmFeeInAvax(receipt.GasUsed, receipt.EffectiveGasPrice)) + evm.CalculateEvmFeeInAvax(receipt.GasUsed, receipt.EffectiveGasPrice)) return err } @@ -597,7 +597,7 @@ func interEvmSend( } ux.Logger.PrintToUser("%s Paid fee: %.9f AVAX", chainName, - calculateEvmFeeInAvax(receipt.GasUsed, receipt.EffectiveGasPrice)) + evm.CalculateEvmFeeInAvax(receipt.GasUsed, receipt.EffectiveGasPrice)) if receipt2 != nil { chainName, err := contract.GetBlockchainDesc(receiverChain) @@ -606,7 +606,7 @@ func interEvmSend( } ux.Logger.PrintToUser("%s Paid fee: %.9f AVAX", chainName, - calculateEvmFeeInAvax(receipt2.GasUsed, receipt2.EffectiveGasPrice)) + evm.CalculateEvmFeeInAvax(receipt2.GasUsed, receipt2.EffectiveGasPrice)) } return nil @@ -1091,13 +1091,3 @@ func getBuilderContext(wallet *primary.Wallet) *builder.Context { } return wallet.P().Builder().Context() } - -func calculateEvmFeeInAvax(gasUsed uint64, gasPrice *big.Int) float64 { - gasUsedBig := new(big.Int).SetUint64(gasUsed) - totalCost := new(big.Int).Mul(gasUsedBig, gasPrice) - - totalCostInNanoAvax := utils.ConvertToNanoAvax(totalCost) - - result, _ := new(big.Float).SetInt(totalCostInNanoAvax).Float64() - return result / float64(units.Avax) -} diff --git a/pkg/utils/common.go b/pkg/utils/common.go index 6d80e7e8d..c80fdaa61 100644 --- a/pkg/utils/common.go +++ b/pkg/utils/common.go @@ -10,7 +10,6 @@ import ( "encoding/json" "fmt" "io" - "math/big" "math/rand" "net" "net/http" @@ -31,7 +30,6 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" "github.com/ava-labs/avalanchego/vms/platformvm" "github.com/ava-labs/avalanchego/vms/platformvm/txs" "github.com/ava-labs/subnet-evm/core" @@ -655,13 +653,3 @@ func PointersSlice[T any](input []T) []*T { } return output } - -// ConvertToNanoAvax converts a balance in Avax to NanoAvax. -// It adds 0.5 to the balance before dividing by 1e9 to round -// it to the nearest whole number. -func ConvertToNanoAvax(balance *big.Int) *big.Int { - divisor := big.NewInt(int64(units.Avax)) - half := new(big.Int).Div(divisor, big.NewInt(2)) - adjusted := new(big.Int).Add(balance, half) - return new(big.Int).Div(adjusted, divisor) -} diff --git a/sdk/evm/helpers.go b/sdk/evm/helpers.go index f6c90d59c..0fc424aa4 100644 --- a/sdk/evm/helpers.go +++ b/sdk/evm/helpers.go @@ -5,7 +5,9 @@ package evm import ( "encoding/hex" "fmt" + "math/big" + "github.com/ava-labs/avalanchego/utils/units" "github.com/ava-labs/subnet-evm/core/types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -76,3 +78,23 @@ func PrivateKeyToAddress(privateKey string) (common.Address, error) { } return crypto.PubkeyToAddress(pk.PublicKey), nil } + +// ConvertToNanoAvax converts a balance in Avax to NanoAvax. +// It adds 0.5 to the balance before dividing by 1e9 to round +// it to the nearest whole number. +func ConvertToNanoAvax(balance *big.Int) *big.Int { + divisor := big.NewInt(int64(units.Avax)) + half := new(big.Int).Div(divisor, big.NewInt(2)) + adjusted := new(big.Int).Add(balance, half) + return new(big.Int).Div(adjusted, divisor) +} + +func CalculateEvmFeeInAvax(gasUsed uint64, gasPrice *big.Int) float64 { + gasUsedBig := new(big.Int).SetUint64(gasUsed) + totalCost := new(big.Int).Mul(gasUsedBig, gasPrice) + + totalCostInNanoAvax := ConvertToNanoAvax(totalCost) + + result, _ := new(big.Float).SetInt(totalCostInNanoAvax).Float64() + return result / float64(units.Avax) +} diff --git a/tests/e2e/commands/icm.go b/tests/e2e/commands/icm.go index c3c993fef..651994ba0 100644 --- a/tests/e2e/commands/icm.go +++ b/tests/e2e/commands/icm.go @@ -12,7 +12,7 @@ const ( /* #nosec G204 */ func SendICMMessage(args []string, testFlags utils.TestFlags) (string, error) { - return utils.TestCommand(utils.ICMCmd, "sendMsg", args, utils.GlobalFlags{ + return utils.TestCommand(ICMCmd, "sendMsg", args, utils.GlobalFlags{ "local": true, "skip-update-check": true, }, testFlags) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 98b10cd9d..1eed517bc 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -26,6 +26,10 @@ import ( _ "github.com/ava-labs/avalanche-cli/tests/e2e/testcases/node/devnet" _ "github.com/ava-labs/avalanche-cli/tests/e2e/testcases/node/monitoring" _ "github.com/ava-labs/avalanche-cli/tests/e2e/testcases/packageman" + _ "github.com/ava-labs/avalanche-cli/tests/e2e/testcases/relayer/deploy" + _ "github.com/ava-labs/avalanche-cli/tests/e2e/testcases/relayer/logs_cmd" + _ "github.com/ava-labs/avalanche-cli/tests/e2e/testcases/relayer/start" + _ "github.com/ava-labs/avalanche-cli/tests/e2e/testcases/relayer/stop" _ "github.com/ava-labs/avalanche-cli/tests/e2e/testcases/root" _ "github.com/ava-labs/avalanche-cli/tests/e2e/testcases/subnet" _ "github.com/ava-labs/avalanche-cli/tests/e2e/testcases/subnet/non-sov/local" diff --git a/tests/e2e/testcases/relayer/deploy/suite.go b/tests/e2e/testcases/relayer/deploy/suite.go new file mode 100644 index 000000000..dd920641b --- /dev/null +++ b/tests/e2e/testcases/relayer/deploy/suite.go @@ -0,0 +1,950 @@ +package deploy + +import ( + "fmt" + + "github.com/ava-labs/avalanche-cli/tests/e2e/commands" + "github.com/ava-labs/avalanche-cli/tests/e2e/utils" + "github.com/ava-labs/avalanchego/utils/units" + ginkgo "github.com/onsi/ginkgo/v2" + "github.com/onsi/gomega" +) + +const ( + ewoqKeyName = "ewoq" + keyName = "e2eKey" + key2Name = "e2eKey2" + subnetName = "testSubnet" + subnet2Name = "testSubnet2" + cChain = "cchain" + message = "Hello World" +) + +var _ = ginkgo.Describe("[Relayer] deploy", func() { + ginkgo.BeforeEach(func() { + _, err := commands.CreateKey(keyName) + gomega.Expect(err).Should(gomega.BeNil()) + _, err = commands.CreateKey(key2Name) + gomega.Expect(err).Should(gomega.BeNil()) + commands.StartNetwork() + }) + + ginkgo.AfterEach(func() { + commands.CleanNetwork() + _, err := commands.DeleteKey(keyName) + gomega.Expect(err).Should(gomega.BeNil()) + _, err = commands.DeleteKey(key2Name) + gomega.Expect(err).Should(gomega.BeNil()) + }) + + ginkgo.Context("With valid input", func() { + ginkgo.Context("With non SOV subnet", func() { + ginkgo.BeforeEach(func() { + commands.CreateSubnetEvmConfigNonSOV(subnetName, utils.SubnetEvmGenesisPath, false) + commands.DeploySubnetLocallyNonSOV(subnetName) + }) + + ginkgo.AfterEach(func() { + err := utils.DeleteConfigs(subnetName) + gomega.Expect(err).Should(gomega.BeNil()) + utils.DeleteCustomBinary(subnetName) + + err = utils.DeleteConfigs(subnet2Name) + gomega.Expect(err).Should(gomega.BeNil()) + utils.DeleteCustomBinary(subnet2Name) + }) + + ginkgo.It("should deploy the relayer between c-chain and subnet in both directions", func() { + // Deploy ICM contracts + _, err := commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnetName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy relayer + deployFlags := utils.TestFlags{ + "key": keyName, + "blockchains": subnetName, + "amount": 10000, + "cchain-amount": 10000, + "log-level": "info", + } + + deployArgs := []string{ + "deploy", + "--cchain", + } + + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", deployArgs, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, deployFlags) + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(output).Should(gomega.ContainSubstring("Executing Relayer")) + + // Send message from c-chain to subnet + _, err = commands.SendICMMessage( + []string{ + cChain, + subnetName, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Send message from subnet to c-chain + _, err = commands.SendICMMessage( + []string{ + subnetName, + cChain, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + }) + + ginkgo.It("should deploy the relayer between subnet and subnet in both directions", func() { + commands.CreateSubnetEvmConfigNonSOV(subnet2Name, utils.SubnetEvmGenesisPath, false) + commands.DeploySubnetLocallyNonSOV(subnet2Name) + + // Deploy ICM contracts + _, err := commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnetName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + _, err = commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnet2Name, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy relayer + deployFlags := utils.TestFlags{ + "key": keyName, + "blockchains": fmt.Sprintf("%s,%s", subnetName, subnet2Name), + "amount": 10000, + "log-level": "info", + } + + deployArgs := []string{ + "deploy", + } + + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", deployArgs, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, deployFlags) + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(output).Should(gomega.ContainSubstring("Executing Relayer")) + + // Send message from subnet to subnet2 + _, err = commands.SendICMMessage( + []string{ + subnetName, + subnet2Name, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Send message from subnet2 to subnet + _, err = commands.SendICMMessage( + []string{ + subnet2Name, + subnetName, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + }) + + ginkgo.It("should deploy the relayer between subnet, subnet and c-chain in all directions", func() { + commands.CreateSubnetEvmConfigNonSOV(subnet2Name, utils.SubnetEvmGenesisPath, false) + commands.DeploySubnetLocallyNonSOV(subnet2Name) + + // Deploy ICM contracts + _, err := commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnetName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + _, err = commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnet2Name, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy relayer + deployFlags := utils.TestFlags{ + "key": keyName, + "blockchains": fmt.Sprintf("%s,%s", subnetName, subnet2Name), + "amount": 10000, + "cchain-amount": 10000, + "log-level": "info", + } + + deployArgs := []string{ + "deploy", + "--cchain", + } + + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", deployArgs, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, deployFlags) + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(output).Should(gomega.ContainSubstring("Executing Relayer")) + + // Send message from subnet to c-chain + _, err = commands.SendICMMessage( + []string{ + subnetName, + cChain, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Send message from subnet2 to c-chain + _, err = commands.SendICMMessage( + []string{ + subnet2Name, + cChain, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Send message from c-chain to subnet + _, err = commands.SendICMMessage( + []string{ + cChain, + subnetName, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Send message from c-chain to subnet2 + _, err = commands.SendICMMessage( + []string{ + cChain, + subnet2Name, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Send message from subnet to subnet2 + _, err = commands.SendICMMessage( + []string{ + subnetName, + subnet2Name, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Send message from subnet2 to subnet + _, err = commands.SendICMMessage( + []string{ + subnet2Name, + subnetName, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + }) + + ginkgo.It("should deploy the relayer on c-chain and subnet with funding it from another key", func() { + // Fund key on subnet + commandArguments := []string{ + "--local", + "--key", + ewoqKeyName, + "--destination-key", + keyName, + "--sender-blockchain", + subnetName, + "--receiver-blockchain", + subnetName, + "--amount", + "100", + } + _, err := commands.KeyTransferSend(commandArguments) + gomega.Expect(err).Should(gomega.BeNil()) + + // Fund key on c-chain + commandArguments = []string{ + "--local", + "--key", + ewoqKeyName, + "--destination-key", + keyName, + "--c-chain-sender", + "--c-chain-receiver", + "--amount", + "100", + } + _, err = commands.KeyTransferSend(commandArguments) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy ICM contracts + _, err = commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnetName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy relayer + deployFlags := utils.TestFlags{ + "key": key2Name, + "cchain-amount": 90, + "blockchains": subnetName, + "amount": 50, + "log-level": "info", + "cchain-funding-key": keyName, + "blockchain-funding-key": keyName, + } + + deployArgs := []string{ + "deploy", + "--cchain", + } + + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", deployArgs, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, deployFlags) + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(output).Should(gomega.ContainSubstring("Executing Relayer")) + + subnetFee, err := utils.GetKeyTransferFee(output, subnetName) + gomega.Expect(err).Should(gomega.BeNil()) + + cchainFee, err := utils.GetKeyTransferFee(output, "C-Chain") + gomega.Expect(err).Should(gomega.BeNil()) + fmt.Println("output", output) + + // Key2 balance on c-chain + output, err = commands.ListKeys("local", true, "", "") + gomega.Expect(err).Should(gomega.BeNil()) + _, key2BalanceCchain, err := utils.ParseAddrBalanceFromKeyListOutput(output, key2Name, "C-Chain") + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(key2BalanceCchain).Should(gomega.Equal(90 * units.Avax)) + + // Key2 balance on subnet + output, err = commands.ListKeys("local", true, "c,"+subnetName, "") + gomega.Expect(err).Should(gomega.BeNil()) + _, key2BalanceSubnet, err := utils.ParseAddrBalanceFromKeyListOutput(output, key2Name, subnetName) + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(key2BalanceSubnet).Should(gomega.Equal(50 * units.Avax)) + + // Key balance on c-chain + output, err = commands.ListKeys("local", true, "", "") + gomega.Expect(err).Should(gomega.BeNil()) + _, keyBalanceCchain, err := utils.ParseAddrBalanceFromKeyListOutput(output, keyName, "C-Chain") + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(keyBalanceCchain).Should(gomega.Equal(10*units.Avax - cchainFee)) + + // Key balance on c-chain + output, err = commands.ListKeys("local", true, "c,"+subnetName, "") + gomega.Expect(err).Should(gomega.BeNil()) + _, keyBalanceSubnet, err := utils.ParseAddrBalanceFromKeyListOutput(output, keyName, subnetName) + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(keyBalanceSubnet).Should(gomega.Equal(50*units.Avax - subnetFee)) + }) + }) + + ginkgo.Context("With SOV subnet", func() { + ginkgo.BeforeEach(func() { + commands.CreateSubnetEvmConfigSOV(subnet2Name, utils.SubnetEvmGenesisPoaPath) + commands.DeploySubnetLocallyNonSOV(subnet2Name) + }) + + ginkgo.AfterEach(func() { + commands.CleanNetwork() + err := utils.DeleteConfigs(subnetName) + gomega.Expect(err).Should(gomega.BeNil()) + utils.DeleteCustomBinary(subnetName) + + err = utils.DeleteConfigs(subnet2Name) + gomega.Expect(err).Should(gomega.BeNil()) + utils.DeleteCustomBinary(subnet2Name) + }) + + ginkgo.It("should deploy the relayer between c-chain and subnet (sov) in both directions", func() { + // Deploy ICM contracts + _, err := commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnet2Name, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy relayer + deployFlags := utils.TestFlags{ + "key": keyName, + "blockchains": subnet2Name, + "amount": 10000, + "cchain-amount": 10000, + "log-level": "info", + } + + deployArgs := []string{ + "deploy", + "--cchain", + } + + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", deployArgs, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, deployFlags) + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(output).Should(gomega.ContainSubstring("Executing Relayer")) + + // Send message from c-chain to subnet + _, err = commands.SendICMMessage( + []string{ + cChain, + subnet2Name, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Send message from subnet to c-chain + _, err = commands.SendICMMessage( + []string{ + subnet2Name, + cChain, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + }) + + ginkgo.It("should deploy the relayer between subnet (sov) and subnet (non-sov) in both directions", func() { + commands.CreateSubnetEvmConfigNonSOV(subnetName, utils.SubnetEvmGenesisPath, false) + commands.DeploySubnetLocallyNonSOV(subnetName) + + // Deploy ICM contracts + _, err := commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnetName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + _, err = commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnet2Name, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy relayer + deployFlags := utils.TestFlags{ + "key": keyName, + "blockchains": fmt.Sprintf("%s,%s", subnetName, subnet2Name), + "amount": 10000, + "log-level": "info", + } + + deployArgs := []string{ + "deploy", + } + + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", deployArgs, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, deployFlags) + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(output).Should(gomega.ContainSubstring("Executing Relayer")) + + // Send message from subnet to subnet2 + _, err = commands.SendICMMessage( + []string{ + subnetName, + subnet2Name, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Send message from subnet2 to subnet + _, err = commands.SendICMMessage( + []string{ + subnet2Name, + subnetName, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + }) + + ginkgo.It("should deploy the relayer between subnet (sov), subnet (sov) and c-chain in all directions", func() { + commands.CreateSubnetEvmConfigSOV(subnetName, utils.SubnetEvmGenesisPoaPath) + commands.DeploySubnetLocallyNonSOV(subnetName) + + // Deploy ICM contracts + _, err := commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnetName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + _, err = commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnet2Name, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy relayer + deployFlags := utils.TestFlags{ + "key": keyName, + "blockchains": fmt.Sprintf("%s,%s", subnetName, subnet2Name), + "amount": 10000, + "cchain-amount": 10000, + "log-level": "info", + } + + deployArgs := []string{ + "deploy", + "--cchain", + } + + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", deployArgs, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, deployFlags) + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(output).Should(gomega.ContainSubstring("Executing Relayer")) + + // Send message from subnet to c-chain + _, err = commands.SendICMMessage( + []string{ + subnetName, + cChain, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Send message from subnet2 to c-chain + _, err = commands.SendICMMessage( + []string{ + subnet2Name, + cChain, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Send message from c-chain to subnet + _, err = commands.SendICMMessage( + []string{ + cChain, + subnetName, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Send message from c-chain to subnet2 + _, err = commands.SendICMMessage( + []string{ + cChain, + subnet2Name, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Send message from subnet to subnet2 + _, err = commands.SendICMMessage( + []string{ + subnetName, + subnet2Name, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Send message from subnet2 to subnet + _, err = commands.SendICMMessage( + []string{ + subnet2Name, + subnetName, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + }) + + ginkgo.It("should deploy the relayer on c-chain and subnet (sov) with funding it from another key", func() { + // Fund key on subnet + commandArguments := []string{ + "--local", + "--key", + ewoqKeyName, + "--destination-key", + keyName, + "--sender-blockchain", + subnet2Name, + "--receiver-blockchain", + subnet2Name, + "--amount", + "100", + } + _, err := commands.KeyTransferSend(commandArguments) + gomega.Expect(err).Should(gomega.BeNil()) + + // Fund key on c-chain + commandArguments = []string{ + "--local", + "--key", + ewoqKeyName, + "--destination-key", + keyName, + "--c-chain-sender", + "--c-chain-receiver", + "--amount", + "100", + } + _, err = commands.KeyTransferSend(commandArguments) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy ICM contracts + _, err = commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnet2Name, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy relayer + deployFlags := utils.TestFlags{ + "key": key2Name, + "cchain-amount": 90, + "blockchains": subnet2Name, + "amount": 50, + "log-level": "info", + "cchain-funding-key": keyName, + "blockchain-funding-key": keyName, + } + + deployArgs := []string{ + "deploy", + "--cchain", + } + + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", deployArgs, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, deployFlags) + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(output).Should(gomega.ContainSubstring("Executing Relayer")) + + subnetFee, err := utils.GetKeyTransferFee(output, subnet2Name) + gomega.Expect(err).Should(gomega.BeNil()) + + cchainFee, err := utils.GetKeyTransferFee(output, "C-Chain") + gomega.Expect(err).Should(gomega.BeNil()) + fmt.Println("output", output) + + // Key2 balance on c-chain + output, err = commands.ListKeys("local", true, "", "") + gomega.Expect(err).Should(gomega.BeNil()) + _, key2BalanceCchain, err := utils.ParseAddrBalanceFromKeyListOutput(output, key2Name, "C-Chain") + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(key2BalanceCchain).Should(gomega.Equal(90 * units.Avax)) + + // Key2 balance on subnet + output, err = commands.ListKeys("local", true, "c,"+subnet2Name, "") + gomega.Expect(err).Should(gomega.BeNil()) + _, key2BalanceSubnet, err := utils.ParseAddrBalanceFromKeyListOutput(output, key2Name, subnet2Name) + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(key2BalanceSubnet).Should(gomega.Equal(50 * units.Avax)) + + // Key balance on c-chain + output, err = commands.ListKeys("local", true, "", "") + gomega.Expect(err).Should(gomega.BeNil()) + _, keyBalanceCchain, err := utils.ParseAddrBalanceFromKeyListOutput(output, keyName, "C-Chain") + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(keyBalanceCchain).Should(gomega.Equal(10*units.Avax - cchainFee)) + + // Key balance on c-chain + output, err = commands.ListKeys("local", true, "c,"+subnet2Name, "") + gomega.Expect(err).Should(gomega.BeNil()) + _, keyBalanceSubnet, err := utils.ParseAddrBalanceFromKeyListOutput(output, keyName, subnet2Name) + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(keyBalanceSubnet).Should(gomega.Equal(50*units.Avax - subnetFee)) + }) + }) + }) + + ginkgo.Context("With invalid input", func() { + ginkgo.BeforeEach(func() { + commands.CreateSubnetEvmConfigNonSOV(subnetName, utils.SubnetEvmGenesisPath, false) + commands.DeploySubnetLocallyNonSOV(subnetName) + }) + + ginkgo.AfterEach(func() { + err := utils.DeleteConfigs(subnetName) + gomega.Expect(err).Should(gomega.BeNil()) + utils.DeleteCustomBinary(subnetName) + }) + + ginkgo.It("should fail if relayer is already deployed", func() { + // Deploy ICM contracts + _, err := commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnetName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy relayer + deployFlags := utils.TestFlags{ + "key": keyName, + "blockchains": subnetName, + "amount": 10000, + "cchain-amount": 10000, + "log-level": "info", + } + + deployArgs := []string{ + "deploy", + "--cchain", + } + + _, err = utils.TestCommand(utils.InterchainCmd, "relayer", deployArgs, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, deployFlags) + gomega.Expect(err).Should(gomega.BeNil()) + + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", deployArgs, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, deployFlags) + gomega.Expect(err).Should(gomega.HaveOccurred()) + gomega.Expect(output).Should(gomega.ContainSubstring("there is already a local relayer deployed")) + }) + + ginkgo.It("should fail if log level is invalid", func() { + // Deploy relayer + deployFlags := utils.TestFlags{ + "key": keyName, + "log-level": "test", + } + + deployArgs := []string{ + "deploy", + "--cchain", + } + + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", deployArgs, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, deployFlags) + gomega.Expect(err).Should(gomega.HaveOccurred()) + gomega.Expect(output).Should(gomega.ContainSubstring("invalid log level test")) + }) + + ginkgo.It("should fail if funding key has no balance on C-Chain", func() { + // Deploy ICM contracts + _, err := commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnetName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy relayer + deployFlags := utils.TestFlags{ + "key": keyName, + "blockchains": subnetName, + "amount": 10000, + "cchain-amount": 10000, + "log-level": "info", + "cchain-funding-key": key2Name, + } + + deployArgs := []string{ + "deploy", + "--cchain", + } + + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", deployArgs, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, deployFlags) + gomega.Expect(err).Should(gomega.HaveOccurred()) + gomega.Expect(output).Should(gomega.ContainSubstring("destination C-Chain funding key has no balance")) + }) + + ginkgo.It("should fail if funding key on c-chain has not enough funds", func() { + // Fund key on c-chain + commandArguments := []string{ + "--local", + "--key", + ewoqKeyName, + "--destination-key", + key2Name, + "--c-chain-sender", + "--c-chain-receiver", + "--amount", + "100", + } + _, err := commands.KeyTransferSend(commandArguments) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy ICM contracts + _, err = commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnetName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy relayer + deployFlags := utils.TestFlags{ + "key": keyName, + "blockchains": subnetName, + "amount": 10000, + "cchain-amount": 10000, + "log-level": "info", + "cchain-funding-key": key2Name, + } + + deployArgs := []string{ + "deploy", + "--cchain", + } + + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", deployArgs, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, deployFlags) + gomega.Expect(err).Should(gomega.HaveOccurred()) + gomega.Expect(output).Should(gomega.ContainSubstring("desired balance 10000.000000 for destination C-Chain exceeds available funding balance of 99.990000")) + }) + + ginkgo.It("should fail if funding key on subnet has not enough funds", func() { + // Deploy ICM contracts + _, err := commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnetName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy relayer + deployFlags := utils.TestFlags{ + "key": keyName, + "blockchains": subnetName, + "amount": 10000, + "cchain-amount": 10000, + "log-level": "info", + "blockchain-funding-key": key2Name, + } + + deployArgs := []string{ + "deploy", + "--cchain", + } + + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", deployArgs, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, deployFlags) + gomega.Expect(err).Should(gomega.HaveOccurred()) + gomega.Expect(output).Should(gomega.ContainSubstring(fmt.Sprintf("destination %s funding key has no balance", subnetName))) + }) + + ginkgo.It("should fail if funding key has no balance on subnet", func() { + commandArguments := []string{ + "--local", + "--key", + ewoqKeyName, + "--destination-key", + key2Name, + "--sender-blockchain", + subnetName, + "--receiver-blockchain", + subnetName, + "--amount", + "100", + } + _, err := commands.KeyTransferSend(commandArguments) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy ICM contracts + _, err = commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnetName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy relayer + deployFlags := utils.TestFlags{ + "key": keyName, + "blockchains": subnetName, + "amount": 10000, + "cchain-amount": 10000, + "log-level": "info", + "blockchain-funding-key": key2Name, + } + + deployArgs := []string{ + "deploy", + "--cchain", + } + + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", deployArgs, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, deployFlags) + gomega.Expect(err).Should(gomega.HaveOccurred()) + gomega.Expect(output).Should(gomega.ContainSubstring(fmt.Sprintf("desired balance 10000.000000 for destination %s exceeds available funding balance of 99.990000", subnetName))) + }) + }) +}) diff --git a/tests/e2e/testcases/relayer/logs_cmd/suite.go b/tests/e2e/testcases/relayer/logs_cmd/suite.go new file mode 100644 index 000000000..58c6a979d --- /dev/null +++ b/tests/e2e/testcases/relayer/logs_cmd/suite.go @@ -0,0 +1,188 @@ +package logs + +import ( + "github.com/ava-labs/avalanche-cli/tests/e2e/commands" + "github.com/ava-labs/avalanche-cli/tests/e2e/utils" + ginkgo "github.com/onsi/ginkgo/v2" + "github.com/onsi/gomega" +) + +const ( + ewoqKeyName = "ewoq" + keyName = "e2eKey" + subnetName = "testSubnet" + cChain = "cchain" +) + +var _ = ginkgo.Describe("[Relayer] stop", func() { + ginkgo.BeforeEach(func() { + _, err := commands.CreateKey(keyName) + gomega.Expect(err).Should(gomega.BeNil()) + commands.StartNetwork() + commands.CreateSubnetEvmConfigNonSOV(subnetName, utils.SubnetEvmGenesisPath, false) + commands.DeploySubnetLocallyNonSOV(subnetName) + }) + + ginkgo.AfterEach(func() { + commands.CleanNetwork() + _, err := commands.DeleteKey(keyName) + gomega.Expect(err).Should(gomega.BeNil()) + err = utils.DeleteConfigs(subnetName) + gomega.Expect(err).Should(gomega.BeNil()) + utils.DeleteCustomBinary(subnetName) + }) + + ginkgo.Context("With valid input", func() { + ginkgo.It("should display logs", func() { + // Deploy ICM contracts + _, err := commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnetName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy the relayer + _, err = commands.DeployRelayer( + []string{ + "deploy", + "--cchain", + }, + utils.TestFlags{ + "key": ewoqKeyName, + "blockchains": subnetName, + "amount": 10000, + "cchain-amount": 10000, + "log-level": "info", + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Display relayer logs + logsArgs := []string{ + "logs", + } + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", logsArgs, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, utils.TestFlags{}) + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(output).Should(gomega.ContainSubstring("Initializing icm-relayer")) + }) + + ginkgo.It("should display raw logs", func() { + // Deploy ICM contracts + _, err := commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnetName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy the relayer + _, err = commands.DeployRelayer( + []string{ + "deploy", + "--cchain", + }, + utils.TestFlags{ + "key": ewoqKeyName, + "blockchains": subnetName, + "amount": 10000, + "cchain-amount": 10000, + "log-level": "info", + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Display relayer logs + logsArgs := []string{ + "logs", + "--raw", + } + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", logsArgs, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, utils.TestFlags{}) + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(output).Should(gomega.ContainSubstring("Initializing icm-relayer")) + }) + + ginkgo.It("should display first logs", func() { + // Deploy ICM contracts + _, err := commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnetName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy the relayer + _, err = commands.DeployRelayer( + []string{ + "deploy", + "--cchain", + }, + utils.TestFlags{ + "key": ewoqKeyName, + "blockchains": subnetName, + "amount": 10000, + "cchain-amount": 10000, + "log-level": "info", + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Display relayer logs + logsFlags := utils.TestFlags{ + "first": 3, + } + logsArgs := []string{ + "logs", + "--raw", + } + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", logsArgs, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, logsFlags) + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(output).Should(gomega.ContainSubstring("Initializing icm-relayer")) + gomega.Expect(output).Should(gomega.ContainSubstring("Initializing destination clients")) + gomega.Expect(output).ShouldNot(gomega.ContainSubstring("Initializing source clients")) + }) + + ginkgo.It("should display last logs", func() { + // Deploy ICM contracts + _, err := commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnetName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy the relayer + _, err = commands.DeployRelayer( + []string{ + "deploy", + "--cchain", + }, + utils.TestFlags{ + "key": ewoqKeyName, + "blockchains": subnetName, + "amount": 10000, + "cchain-amount": 10000, + "log-level": "info", + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Display relayer logs + logsFlags := utils.TestFlags{ + "last": 3, + } + logsArgs := []string{ + "logs", + "--raw", + } + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", logsArgs, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, logsFlags) + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(output).ShouldNot(gomega.ContainSubstring("Initializing icm-relayer")) + gomega.Expect(output).Should(gomega.ContainSubstring("Listener initialized. Listening for messages to relay.")) + }) + }) +}) diff --git a/tests/e2e/testcases/relayer/start/suite.go b/tests/e2e/testcases/relayer/start/suite.go new file mode 100644 index 000000000..499c9dbf8 --- /dev/null +++ b/tests/e2e/testcases/relayer/start/suite.go @@ -0,0 +1,137 @@ +package start + +import ( + "github.com/ava-labs/avalanche-cli/tests/e2e/commands" + "github.com/ava-labs/avalanche-cli/tests/e2e/utils" + ginkgo "github.com/onsi/ginkgo/v2" + "github.com/onsi/gomega" +) + +const ( + ewoqKeyName = "ewoq" + keyName = "e2eKey" + subnetName = "testSubnet" + cChain = "cchain" +) + +var _ = ginkgo.Describe("[Relayer] start", func() { + ginkgo.BeforeEach(func() { + _, err := commands.CreateKey(keyName) + gomega.Expect(err).Should(gomega.BeNil()) + commands.StartNetwork() + commands.CreateSubnetEvmConfigNonSOV(subnetName, utils.SubnetEvmGenesisPath, false) + commands.DeploySubnetLocallyNonSOV(subnetName) + }) + + ginkgo.AfterEach(func() { + commands.CleanNetwork() + _, err := commands.DeleteKey(keyName) + gomega.Expect(err).Should(gomega.BeNil()) + err = utils.DeleteConfigs(subnetName) + gomega.Expect(err).Should(gomega.BeNil()) + utils.DeleteCustomBinary(subnetName) + }) + + ginkgo.Context("With valid input", func() { + ginkgo.It("should start the relayer", func() { + // Deploy ICM contracts + _, err := commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnetName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy the relayer + _, err = commands.DeployRelayer( + []string{ + "deploy", + "--cchain", + }, + utils.TestFlags{ + "key": ewoqKeyName, + "blockchains": subnetName, + "amount": 10000, + "cchain-amount": 10000, + "log-level": "info", + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Stop the relayer + _, err = commands.StopRelayer() + gomega.Expect(err).Should(gomega.BeNil()) + + // Start the relayer + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", []string{ + "start", + }, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, utils.TestFlags{}) + + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(output).Should(gomega.ContainSubstring("Local AWM Relayer successfully started for Local Network")) + + // Send message from c-chain to subnet + _, err = commands.SendICMMessage( + []string{ + cChain, + subnetName, + "hello world", + }, + utils.TestFlags{ + "key": ewoqKeyName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + }) + }) + + ginkgo.Context("With invalid input", func() { + ginkgo.It("should fail to start the relayer when there is no relayer config", func() { + // Start the relayer + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", []string{ + "start", + }, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, utils.TestFlags{}) + + gomega.Expect(err).Should(gomega.HaveOccurred()) + gomega.Expect(output).Should(gomega.ContainSubstring("there is no relayer configuration available")) + }) + + ginkgo.It("should fail to start the relayer when it is already running", func() { + // Deploy ICM contracts + _, err := commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnetName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy the relayer + _, err = commands.DeployRelayer( + []string{ + "deploy", + "--cchain", + }, + utils.TestFlags{ + "key": ewoqKeyName, + "blockchains": subnetName, + "amount": 10000, + "cchain-amount": 10000, + "log-level": "info", + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Start the relayer + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", []string{ + "start", + }, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, utils.TestFlags{}) + + gomega.Expect(err).Should(gomega.HaveOccurred()) + gomega.Expect(output).Should(gomega.ContainSubstring("local AWM relayer is already running for Local Network")) + }) + }) +}) diff --git a/tests/e2e/testcases/relayer/stop/suite.go b/tests/e2e/testcases/relayer/stop/suite.go new file mode 100644 index 000000000..09bb610cf --- /dev/null +++ b/tests/e2e/testcases/relayer/stop/suite.go @@ -0,0 +1,127 @@ +package stop + +import ( + "github.com/ava-labs/avalanche-cli/pkg/interchain/relayer" + "github.com/ava-labs/avalanche-cli/pkg/models" + "github.com/ava-labs/avalanche-cli/tests/e2e/commands" + "github.com/ava-labs/avalanche-cli/tests/e2e/utils" + ginkgo "github.com/onsi/ginkgo/v2" + "github.com/onsi/gomega" +) + +const ( + ewoqKeyName = "ewoq" + keyName = "e2eKey" + subnetName = "testSubnet" + cChain = "cchain" +) + +var _ = ginkgo.Describe("[Relayer] stop", func() { + ginkgo.BeforeEach(func() { + _, err := commands.CreateKey(keyName) + gomega.Expect(err).Should(gomega.BeNil()) + commands.StartNetwork() + commands.CreateSubnetEvmConfigNonSOV(subnetName, utils.SubnetEvmGenesisPath, false) + commands.DeploySubnetLocallyNonSOV(subnetName) + }) + + ginkgo.AfterEach(func() { + commands.CleanNetwork() + _, err := commands.DeleteKey(keyName) + gomega.Expect(err).Should(gomega.BeNil()) + err = utils.DeleteConfigs(subnetName) + gomega.Expect(err).Should(gomega.BeNil()) + utils.DeleteCustomBinary(subnetName) + }) + + ginkgo.Context("With valid input", func() { + ginkgo.It("should stop the relayer", func() { + // Deploy ICM contracts + _, err := commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnetName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy the relayer + _, err = commands.DeployRelayer( + []string{ + "deploy", + "--cchain", + }, + utils.TestFlags{ + "key": ewoqKeyName, + "blockchains": subnetName, + "amount": 10000, + "cchain-amount": 10000, + "log-level": "info", + }) + gomega.Expect(err).Should(gomega.BeNil()) + + app := utils.GetApp() + configPath := app.GetLocalRelayerRunPath(models.Local) + isUp, _, _, err := relayer.RelayerIsUp(configPath) + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(isUp).Should(gomega.BeTrue()) + + // Stop the relayer + output, err := commands.StopRelayer() + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(output).Should(gomega.ContainSubstring("Local AWM Relayer successfully stopped for Local Network")) + + isUp, _, _, err = relayer.RelayerIsUp(configPath) + gomega.Expect(err).Should(gomega.BeNil()) + gomega.Expect(isUp).Should(gomega.BeFalse()) + }) + }) + + ginkgo.Context("With invalid input", func() { + ginkgo.It("should fail to start the relayer when there is no relayer config", func() { + // Start the relayer + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", []string{ + "start", + }, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, utils.TestFlags{}) + + gomega.Expect(err).Should(gomega.HaveOccurred()) + gomega.Expect(output).Should(gomega.ContainSubstring("there is no relayer configuration available")) + }) + + ginkgo.It("should fail to start the relayer when it is already running", func() { + // Deploy ICM contracts + _, err := commands.DeployICMContracts([]string{}, utils.TestFlags{ + "key": ewoqKeyName, + "blockchain": subnetName, + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Deploy the relayer + _, err = commands.DeployRelayer( + []string{ + "deploy", + "--cchain", + }, + utils.TestFlags{ + "key": ewoqKeyName, + "blockchains": subnetName, + "amount": 10000, + "cchain-amount": 10000, + "log-level": "info", + }) + gomega.Expect(err).Should(gomega.BeNil()) + + // Start the relayer + output, err := utils.TestCommand(utils.InterchainCmd, "relayer", []string{ + "start", + }, utils.GlobalFlags{ + "local": true, + "skip-update-check": true, + }, utils.TestFlags{}) + + gomega.Expect(err).Should(gomega.HaveOccurred()) + gomega.Expect(output).Should(gomega.ContainSubstring("local AWM relayer is already running for Local Network")) + }) + }) +})