From c98ab97cf996c3c77e123a925e3ca65869c883d4 Mon Sep 17 00:00:00 2001 From: ylg Date: Mon, 7 Jul 2025 09:05:23 -0400 Subject: [PATCH 1/4] reuse network --- scripts/e2e_test.sh | 18 ++ tests/network/network.go | 98 +++++++-- .../governance/governance_suite_test.go | 8 +- tests/suites/ictt/ictt_suite_test.go | 141 +++++++----- .../teleporter/teleporter_suite_test.go | 205 +++++++++--------- 5 files changed, 287 insertions(+), 183 deletions(-) diff --git a/scripts/e2e_test.sh b/scripts/e2e_test.sh index 984f96ac0..6565a173b 100755 --- a/scripts/e2e_test.sh +++ b/scripts/e2e_test.sh @@ -21,6 +21,7 @@ Arguments: --components component1,component2 Comma separated list of test suites to run. Valid components are: $(echo $valid_components | tr ' ' '\n' | sort | tr '\n' ' ') (default: all) + --network-dir path Path to the network directory to reuse. If not provided, a new network will be created. Options: --help Print this help message EOF @@ -28,6 +29,8 @@ EOF valid_components=$(ls -d $ICM_CONTRACTS_PATH/tests/suites/*/ | xargs -n 1 basename) components= +network_dir= +reuse_network=false while [ $# -gt 0 ]; do case "$1" in @@ -38,6 +41,13 @@ while [ $# -gt 0 ]; do echo "Invalid components $2" && printHelp && exit 1 fi shift;; + --network-dir) + if [[ $2 != --* ]]; then + network_dir=$2 + else + echo "Invalid network directory $2" && printHelp && exit 1 + fi + shift;; --help) printHelp && exit 0 ;; *) @@ -58,6 +68,12 @@ for component in $(echo $components | tr ',' ' '); do fi done +# If network_dir is set, set reuse-network flag +if [ -n "$network_dir" ]; then + reuse_network=true + echo "Using network directory: $network_dir" +fi + source "$ICM_CONTRACTS_PATH"/scripts/constants.sh source "$ICM_CONTRACTS_PATH"/scripts/versions.sh @@ -100,6 +116,8 @@ for component in $(echo $components | tr ',' ' '); do echo "Running e2e tests for $component" RUN_E2E=true SIG_AGG_PATH=$ICM_SERVICES_BUILD_PATH/signature-aggregator ./tests/suites/$component/$component.test \ + --reuse-network=${reuse_network} \ + --network-dir=${network_dir} \ --ginkgo.vv \ --ginkgo.label-filter=${GINKGO_LABEL_FILTER:-""} \ --ginkgo.focus=${GINKGO_FOCUS:-""} \ diff --git a/tests/network/network.go b/tests/network/network.go index f6b898ebf..9235b968d 100644 --- a/tests/network/network.go +++ b/tests/network/network.go @@ -75,31 +75,17 @@ type L1Spec struct { RequirePrimaryNetworkSigners bool } -func NewLocalNetwork( - ctx context.Context, +func newTmpnetNetwork( name string, + extraNodes []*tmpnet.Node, + globalFundedKey *secp256k1.PrivateKey, warpGenesisTemplateFile string, - l1Specs []L1Spec, numPrimaryNetworkValidators int, - extraNodeCount int, // for use by tests, eg to add new L1 validators + l1Specs []L1Spec, flagVars *e2e.FlagVars, -) *LocalNetwork { - // There must be at least one primary network validator per L1 - Expect(numPrimaryNetworkValidators).Should(BeNumerically(">=", len(l1Specs))) - - // Create extra nodes to be used to add more validators later - extraNodes := subnetEvmTestUtils.NewTmpnetNodes(extraNodeCount) - - fundedKey, err := hex.DecodeString(fundedKeyStr) - Expect(err).Should(BeNil()) - globalFundedKey, err := secp256k1.ToPrivateKey(fundedKey) - Expect(err).Should(BeNil()) - - globalFundedECDSAKey := globalFundedKey.ToECDSA() - Expect(err).Should(BeNil()) - +) *tmpnet.Network { var l1s []*tmpnet.Subnet - deployedL1Specs := make(map[string]L1Spec) + bootstrapNodes := subnetEvmTestUtils.NewTmpnetNodes(numPrimaryNetworkValidators) for i, l1Spec := range l1Specs { // Create a single bootstrap node. This will be removed from the L1 validator set after it is converted, @@ -123,16 +109,18 @@ func NewLocalNetwork( utils.WarpEnabledChainConfig, initialL1Bootstrapper, ) - deployedL1Specs[l1Spec.Name] = l1Spec l1.OwningKey = globalFundedKey l1s = append(l1s, l1) } + + // Create new network network := subnetEvmTestUtils.NewTmpnetNetwork( name, bootstrapNodes, tmpnet.FlagsMap{}, l1s..., ) + Expect(network).ShouldNot(BeNil()) // Specify only a subset of the nodes to be bootstrapped @@ -147,11 +135,71 @@ func NewLocalNetwork( network.Genesis = genesis network.PreFundedKeys = keysToFund - tc := e2e.NewTestContext() runtimeCfg, err := flagVars.NodeRuntimeConfig() Expect(err).Should(BeNil()) runtimeCfg.Process.ReuseDynamicPorts = true network.DefaultRuntimeConfig = *runtimeCfg + + return network +} + +func NewLocalNetwork( + ctx context.Context, + name string, + warpGenesisTemplateFile string, + l1Specs []L1Spec, + numPrimaryNetworkValidators int, + extraNodeCount int, // for use by tests, eg to add new L1 validators + flagVars *e2e.FlagVars, +) *LocalNetwork { + // There must be at least one primary network validator per L1 + Expect(numPrimaryNetworkValidators).Should(BeNumerically(">=", len(l1Specs))) + + // Create extra nodes to be used to add more validators later + extraNodes := subnetEvmTestUtils.NewTmpnetNodes(extraNodeCount) + + fundedKey, err := hex.DecodeString(fundedKeyStr) + Expect(err).Should(BeNil()) + globalFundedKey, err := secp256k1.ToPrivateKey(fundedKey) + Expect(err).Should(BeNil()) + + globalFundedECDSAKey := globalFundedKey.ToECDSA() + Expect(err).Should(BeNil()) + + deployedL1Specs := make(map[string]L1Spec) + for _, l1Spec := range l1Specs { + deployedL1Specs[l1Spec.Name] = l1Spec + } + + isReuseNetwork := flagVars != nil && flagVars.NetworkDir() != "" + + var network *tmpnet.Network + if isReuseNetwork { + // Load existing network and restart nodes + network, err = tmpnet.ReadNetwork(context.Background(), logging.NoLog{}, flagVars.NetworkDir()) + Expect(err).Should(BeNil()) + Expect(network).ShouldNot(BeNil()) + + for _, node := range network.Nodes { + err := node.Restart(ctx) + Expect(err).Should(BeNil(), "Failed to restart node %s: %v", node.NodeID, err) + } + + err := tmpnet.WaitForHealthyNodes(ctx, logging.NoLog{}, network.Nodes) + Expect(err).Should(BeNil()) + } else { + network = newTmpnetNetwork( + name, + extraNodes, + globalFundedKey, + warpGenesisTemplateFile, + numPrimaryNetworkValidators, + l1Specs, + flagVars, + ) + } + + tc := e2e.NewTestContext() env := e2e.NewTestEnvironment(tc, flagVars, network) Expect(env).ShouldNot(BeNil()) @@ -162,8 +210,10 @@ func NewLocalNetwork( goLog.Println("Network bootstrapped") // Issue transactions to activate the proposerVM fork on the chains - for _, l1 := range network.Subnets { - utils.SetupProposerVM(ctx, globalFundedECDSAKey, network, l1.SubnetID) + if !isReuseNetwork { + for _, l1 := range network.Subnets { + utils.SetupProposerVM(ctx, globalFundedECDSAKey, network, l1.SubnetID) + } } // All nodes are specified as bootstrap validators diff --git a/tests/suites/governance/governance_suite_test.go b/tests/suites/governance/governance_suite_test.go index fd196cc0b..080457a76 100644 --- a/tests/suites/governance/governance_suite_test.go +++ b/tests/suites/governance/governance_suite_test.go @@ -2,6 +2,7 @@ package governance_test import ( "context" + "flag" "os" "testing" "time" @@ -24,12 +25,17 @@ var ( e2eFlags *e2e.FlagVars ) +func TestMain(m *testing.M) { + e2eFlags = e2e.RegisterFlags() + flag.Parse() + os.Exit(m.Run()) +} + func TestGovernance(t *testing.T) { if os.Getenv("RUN_E2E") == "" { t.Skip("Environment variable RUN_E2E not set; skipping E2E tests") } - e2eFlags = e2e.RegisterFlags() RegisterFailHandler(ginkgo.Fail) ginkgo.RunSpecs(t, "Governance e2e test") } diff --git a/tests/suites/ictt/ictt_suite_test.go b/tests/suites/ictt/ictt_suite_test.go index 3edab6175..becce550d 100644 --- a/tests/suites/ictt/ictt_suite_test.go +++ b/tests/suites/ictt/ictt_suite_test.go @@ -2,6 +2,9 @@ package ictt_test import ( "context" + "flag" + "fmt" + "math/big" "os" "testing" "time" @@ -37,12 +40,17 @@ var ( e2eFlags *e2e.FlagVars ) +func TestMain(m *testing.M) { + e2eFlags = e2e.RegisterFlags() + flag.Parse() + os.Exit(m.Run()) +} + func TestValidatorManager(t *testing.T) { if os.Getenv("RUN_E2E") == "" { t.Skip("Environment variable RUN_E2E not set; skipping E2E tests") } - e2eFlags = e2e.RegisterFlags() RegisterFailHandler(ginkgo.Fail) ginkgo.RunSpecs(t, "Teleporter e2e test") } @@ -95,14 +103,26 @@ var _ = ginkgo.BeforeSuite(func() { // Only need to deploy Teleporter on the C-Chain since it is included in the genesis of the L1 chains. _, fundedKey := LocalNetworkInstance.GetFundedAccountInfo() - TeleporterInfo.DeployTeleporterMessenger( - ctx, - LocalNetworkInstance.GetPrimaryNetworkInfo(), - teleporterDeployerTransaction, - teleporterDeployerAddress, - teleporterContractAddress, - fundedKey, - ) + + if e2eFlags.NetworkDir() == "" { + // Only deploy Teleporter if we are not reusing an existing network + TeleporterInfo.DeployTeleporterMessenger( + ctx, + LocalNetworkInstance.GetPrimaryNetworkInfo(), + teleporterDeployerTransaction, + teleporterDeployerAddress, + teleporterContractAddress, + fundedKey, + ) + } else { + fundAmount := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(15)) // 11 AVAX + fundDeployerTx := utils.CreateNativeTransferTransaction( + ctx, LocalNetworkInstance.GetPrimaryNetworkInfo(), fundedKey, teleporterDeployerAddress, fundAmount, + ) + utils.SendTransactionAndWaitForSuccess(ctx, LocalNetworkInstance.GetPrimaryNetworkInfo(), fundDeployerTx) + fmt.Println("Deployer funded with", fundAmount, "AVAX") + } + for _, l1 := range LocalNetworkInstance.GetAllL1Infos() { TeleporterInfo.SetTeleporter(teleporterContractAddress, l1) TeleporterInfo.InitializeBlockchainID(l1, fundedKey) @@ -118,59 +138,62 @@ var _ = ginkgo.AfterSuite(func() { var _ = ginkgo.Describe("[Validator manager integration tests]", func() { // ICTT tests - ginkgo.It("Transfer an ERC20 token between two L1s", - ginkgo.Label(icttLabel, erc20TokenHomeLabel, erc20TokenRemoteLabel), - func() { - icttFlows.ERC20TokenHomeERC20TokenRemote(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Transfer a native token to an ERC20 token", - ginkgo.Label(icttLabel, nativeTokenHomeLabel, erc20TokenRemoteLabel), - func() { - icttFlows.NativeTokenHomeERC20TokenRemote(LocalNetworkInstance, TeleporterInfo) - }) + // ginkgo.It("Transfer an ERC20 token between two L1s", + // ginkgo.Label(icttLabel, erc20TokenHomeLabel, erc20TokenRemoteLabel), + // func() { + // icttFlows.ERC20TokenHomeERC20TokenRemote(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Transfer a native token to an ERC20 token", + // ginkgo.Label(icttLabel, nativeTokenHomeLabel, erc20TokenRemoteLabel), + // func() { + // icttFlows.NativeTokenHomeERC20TokenRemote(LocalNetworkInstance, TeleporterInfo) + // }) + + // TODO: failed ginkgo.It("Transfer a native token to a native token", ginkgo.Label(icttLabel, nativeTokenHomeLabel, nativeTokenRemoteLabel), func() { icttFlows.NativeTokenHomeNativeDestination(LocalNetworkInstance, TeleporterInfo) }) - ginkgo.It("Transfer an ERC20 token with ERC20TokenHome multi-hop", - ginkgo.Label(icttLabel, erc20TokenHomeLabel, erc20TokenRemoteLabel, multiHopLabel), - func() { - icttFlows.ERC20TokenHomeERC20TokenRemoteMultiHop(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Transfer a native token with NativeTokenHome multi-hop", - ginkgo.Label(icttLabel, nativeTokenHomeLabel, erc20TokenRemoteLabel, multiHopLabel), - func() { - icttFlows.NativeTokenHomeERC20TokenRemoteMultiHop(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Transfer an ERC20 token to a native token", - ginkgo.Label(icttLabel, erc20TokenHomeLabel, nativeTokenRemoteLabel), - func() { - icttFlows.ERC20TokenHomeNativeTokenRemote(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Transfer a native token with ERC20TokenHome multi-hop", - ginkgo.Label(icttLabel, erc20TokenHomeLabel, nativeTokenRemoteLabel, multiHopLabel), - func() { - icttFlows.ERC20TokenHomeNativeTokenRemoteMultiHop(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Transfer a native token to a native token multi-hop", - ginkgo.Label(icttLabel, nativeTokenHomeLabel, nativeTokenRemoteLabel, multiHopLabel), - func() { - icttFlows.NativeTokenHomeNativeTokenRemoteMultiHop(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Transfer an ERC20 token using sendAndCall", - ginkgo.Label(icttLabel, erc20TokenHomeLabel, erc20TokenRemoteLabel, sendAndCallLabel), - func() { - icttFlows.ERC20TokenHomeERC20TokenRemoteSendAndCall(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Registration and collateral checks", - ginkgo.Label(icttLabel, erc20TokenHomeLabel, nativeTokenRemoteLabel, registrationLabel), - func() { - icttFlows.RegistrationAndCollateralCheck(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Transparent proxy upgrade", - ginkgo.Label(icttLabel, erc20TokenHomeLabel, erc20TokenRemoteLabel, upgradabilityLabel), - func() { - icttFlows.TransparentUpgradeableProxy(LocalNetworkInstance, TeleporterInfo) - }) + + // ginkgo.It("Transfer an ERC20 token with ERC20TokenHome multi-hop", + // ginkgo.Label(icttLabel, erc20TokenHomeLabel, erc20TokenRemoteLabel, multiHopLabel), + // func() { + // icttFlows.ERC20TokenHomeERC20TokenRemoteMultiHop(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Transfer a native token with NativeTokenHome multi-hop", + // ginkgo.Label(icttLabel, nativeTokenHomeLabel, erc20TokenRemoteLabel, multiHopLabel), + // func() { + // icttFlows.NativeTokenHomeERC20TokenRemoteMultiHop(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Transfer an ERC20 token to a native token", + // ginkgo.Label(icttLabel, erc20TokenHomeLabel, nativeTokenRemoteLabel), + // func() { + // icttFlows.ERC20TokenHomeNativeTokenRemote(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Transfer a native token with ERC20TokenHome multi-hop", + // ginkgo.Label(icttLabel, erc20TokenHomeLabel, nativeTokenRemoteLabel, multiHopLabel), + // func() { + // icttFlows.ERC20TokenHomeNativeTokenRemoteMultiHop(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Transfer a native token to a native token multi-hop", + // ginkgo.Label(icttLabel, nativeTokenHomeLabel, nativeTokenRemoteLabel, multiHopLabel), + // func() { + // icttFlows.NativeTokenHomeNativeTokenRemoteMultiHop(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Transfer an ERC20 token using sendAndCall", + // ginkgo.Label(icttLabel, erc20TokenHomeLabel, erc20TokenRemoteLabel, sendAndCallLabel), + // func() { + // icttFlows.ERC20TokenHomeERC20TokenRemoteSendAndCall(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Registration and collateral checks", + // ginkgo.Label(icttLabel, erc20TokenHomeLabel, nativeTokenRemoteLabel, registrationLabel), + // func() { + // icttFlows.RegistrationAndCollateralCheck(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Transparent proxy upgrade", + // ginkgo.Label(icttLabel, erc20TokenHomeLabel, erc20TokenRemoteLabel, upgradabilityLabel), + // func() { + // icttFlows.TransparentUpgradeableProxy(LocalNetworkInstance, TeleporterInfo) + // }) }) diff --git a/tests/suites/teleporter/teleporter_suite_test.go b/tests/suites/teleporter/teleporter_suite_test.go index cdbdadf60..4034c0c94 100644 --- a/tests/suites/teleporter/teleporter_suite_test.go +++ b/tests/suites/teleporter/teleporter_suite_test.go @@ -5,6 +5,7 @@ package teleporter_test import ( "context" + "flag" "os" "testing" "time" @@ -12,7 +13,6 @@ import ( "github.com/ava-labs/avalanchego/tests/fixture/e2e" "github.com/ava-labs/avalanchego/utils/units" teleporterFlows "github.com/ava-labs/icm-contracts/tests/flows/teleporter" - registryFlows "github.com/ava-labs/icm-contracts/tests/flows/teleporter/registry" "github.com/ava-labs/icm-contracts/tests/network" "github.com/ava-labs/icm-contracts/tests/utils" deploymentUtils "github.com/ava-labs/icm-contracts/utils/deployment-utils" @@ -36,12 +36,17 @@ var ( e2eFlags *e2e.FlagVars ) +func TestMain(m *testing.M) { + e2eFlags = e2e.RegisterFlags() + flag.Parse() + os.Exit(m.Run()) +} + func TestTeleporter(t *testing.T) { if os.Getenv("RUN_E2E") == "" { t.Skip("Environment variable RUN_E2E not set; skipping E2E tests") } - e2eFlags = e2e.RegisterFlags() RegisterFailHandler(ginkgo.Fail) ginkgo.RunSpecs(t, "Teleporter e2e test") } @@ -97,14 +102,28 @@ var _ = ginkgo.BeforeSuite(func() { // Only need to deploy Teleporter on the C-Chain since it is included in the genesis of the l1 chains. _, fundedKey := LocalNetworkInstance.GetFundedAccountInfo() - TeleporterInfo.DeployTeleporterMessenger( - ctx, - LocalNetworkInstance.GetPrimaryNetworkInfo(), - teleporterDeployerTransaction, - teleporterDeployerAddress, - teleporterContractAddress, - fundedKey, - ) + if e2eFlags.NetworkDir() == "" { + TeleporterInfo.DeployTeleporterMessenger( + ctx, + LocalNetworkInstance.GetPrimaryNetworkInfo(), + teleporterDeployerTransaction, + teleporterDeployerAddress, + teleporterContractAddress, + fundedKey, + ) + + for _, subnet := range LocalNetworkInstance.GetL1Infos() { + // Choose weights such that we can test validator churn + LocalNetworkInstance.ConvertSubnet( + ctx, + subnet, + utils.PoAValidatorManager, + []uint64{units.Schmeckle, units.Schmeckle, units.Schmeckle, units.Schmeckle, units.Schmeckle}, + fundedKey, + false, + ) + } + } for _, l1 := range LocalNetworkInstance.GetAllL1Infos() { TeleporterInfo.SetTeleporter(teleporterContractAddress, l1) @@ -112,18 +131,6 @@ var _ = ginkgo.BeforeSuite(func() { TeleporterInfo.DeployTeleporterRegistry(l1, fundedKey) } - for _, subnet := range LocalNetworkInstance.GetL1Infos() { - // Choose weights such that we can test validator churn - LocalNetworkInstance.ConvertSubnet( - ctx, - subnet, - utils.PoAValidatorManager, - []uint64{units.Schmeckle, units.Schmeckle, units.Schmeckle, units.Schmeckle, units.Schmeckle}, - fundedKey, - false, - ) - } - log.Info("Set up ginkgo before suite") }) @@ -139,81 +146,81 @@ var _ = ginkgo.Describe("[Teleporter integration tests]", func() { func() { teleporterFlows.BasicSendReceive(LocalNetworkInstance, TeleporterInfo) }) - ginkgo.It("Deliver to the wrong chain", - ginkgo.Label(teleporterMessengerLabel), - func() { - teleporterFlows.DeliverToWrongChain(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Deliver to non-existent contract", - ginkgo.Label(teleporterMessengerLabel), - func() { - teleporterFlows.DeliverToNonExistentContract(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Retry successful execution", - ginkgo.Label(teleporterMessengerLabel), - func() { - teleporterFlows.RetrySuccessfulExecution(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Unallowed relayer", - ginkgo.Label(teleporterMessengerLabel), - func() { - teleporterFlows.UnallowedRelayer(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Relay message twice", - ginkgo.Label(teleporterMessengerLabel), - func() { - teleporterFlows.RelayMessageTwice(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Add additional fee amount", - ginkgo.Label(teleporterMessengerLabel), - func() { - teleporterFlows.AddFeeAmount(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Send specific receipts", - ginkgo.Label(teleporterMessengerLabel), - func() { - teleporterFlows.SendSpecificReceipts(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Insufficient gas", - ginkgo.Label(teleporterMessengerLabel), - func() { - teleporterFlows.InsufficientGas(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Resubmit altered message", - ginkgo.Label(teleporterMessengerLabel), - func() { - teleporterFlows.ResubmitAlteredMessage(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Calculate Teleporter message IDs", - ginkgo.Label(utilsLabel), - func() { - teleporterFlows.CalculateMessageID(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Relayer modifies message", - ginkgo.Label(teleporterMessengerLabel), - func() { - teleporterFlows.RelayerModifiesMessage(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Validator churn", - ginkgo.Label(teleporterMessengerLabel), - func() { - teleporterFlows.ValidatorChurn(LocalNetworkInstance, TeleporterInfo) - }) - - // Teleporter Registry tests - ginkgo.It("Teleporter registry", - ginkgo.Label(upgradabilityLabel), - func() { - registryFlows.TeleporterRegistry(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Check upgrade access", - ginkgo.Label(upgradabilityLabel), - func() { - registryFlows.CheckUpgradeAccess(LocalNetworkInstance, TeleporterInfo) - }) - ginkgo.It("Pause and Unpause Teleporter", - ginkgo.Label(upgradabilityLabel), - func() { - registryFlows.PauseTeleporter(LocalNetworkInstance, TeleporterInfo) - }) + // ginkgo.It("Deliver to the wrong chain", + // ginkgo.Label(teleporterMessengerLabel), + // func() { + // teleporterFlows.DeliverToWrongChain(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Deliver to non-existent contract", + // ginkgo.Label(teleporterMessengerLabel), + // func() { + // teleporterFlows.DeliverToNonExistentContract(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Retry successful execution", + // ginkgo.Label(teleporterMessengerLabel), + // func() { + // teleporterFlows.RetrySuccessfulExecution(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Unallowed relayer", + // ginkgo.Label(teleporterMessengerLabel), + // func() { + // teleporterFlows.UnallowedRelayer(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Relay message twice", + // ginkgo.Label(teleporterMessengerLabel), + // func() { + // teleporterFlows.RelayMessageTwice(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Add additional fee amount", + // ginkgo.Label(teleporterMessengerLabel), + // func() { + // teleporterFlows.AddFeeAmount(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Send specific receipts", + // ginkgo.Label(teleporterMessengerLabel), + // func() { + // teleporterFlows.SendSpecificReceipts(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Insufficient gas", + // ginkgo.Label(teleporterMessengerLabel), + // func() { + // teleporterFlows.InsufficientGas(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Resubmit altered message", + // ginkgo.Label(teleporterMessengerLabel), + // func() { + // teleporterFlows.ResubmitAlteredMessage(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Calculate Teleporter message IDs", + // ginkgo.Label(utilsLabel), + // func() { + // teleporterFlows.CalculateMessageID(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Relayer modifies message", + // ginkgo.Label(teleporterMessengerLabel), + // func() { + // teleporterFlows.RelayerModifiesMessage(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Validator churn", + // ginkgo.Label(teleporterMessengerLabel), + // func() { + // teleporterFlows.ValidatorChurn(LocalNetworkInstance, TeleporterInfo) + // }) + + // // Teleporter Registry tests + // ginkgo.It("Teleporter registry", + // ginkgo.Label(upgradabilityLabel), + // func() { + // registryFlows.TeleporterRegistry(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Check upgrade access", + // ginkgo.Label(upgradabilityLabel), + // func() { + // registryFlows.CheckUpgradeAccess(LocalNetworkInstance, TeleporterInfo) + // }) + // ginkgo.It("Pause and Unpause Teleporter", + // ginkgo.Label(upgradabilityLabel), + // func() { + // registryFlows.PauseTeleporter(LocalNetworkInstance, TeleporterInfo) + // }) }) From c0e9a11fff7b425ca6a142c30fa4441540945a88 Mon Sep 17 00:00:00 2001 From: ylg Date: Thu, 10 Jul 2025 09:58:09 -0400 Subject: [PATCH 2/4] reuse network --- .gitignore | 4 + go.mod | 2 + go.sum | 4 + tests/network/network.go | 66 ++++++- tests/suites/ictt/ictt_suite_test.go | 146 ++++++++------ .../teleporter/teleporter_suite_test.go | 184 ++++++++++-------- tests/utils/teleporter.go | 53 +++++ 7 files changed, 308 insertions(+), 151 deletions(-) diff --git a/.gitignore b/.gitignore index 6ec26aeca..93809f7ce 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,7 @@ server.log # Forge documentation docs/ coverage/ + +TeleporterRegistryAddress.json +ValidatorAddresses.json + diff --git a/go.mod b/go.mod index 3616d0759..ca5ead9a8 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/onsi/ginkgo/v2 v2.23.4 github.com/onsi/gomega v1.37.0 github.com/pkg/errors v0.9.1 + github.com/segmentio/encoding v0.5.1 github.com/spf13/cobra v1.9.1 github.com/stretchr/testify v1.10.0 go.uber.org/zap v1.27.0 @@ -118,6 +119,7 @@ require ( github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/cors v1.7.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/segmentio/asm v1.1.3 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/spf13/afero v1.9.5 // indirect github.com/spf13/cast v1.5.1 // indirect diff --git a/go.sum b/go.sum index c775cd6c8..ab23db633 100644 --- a/go.sum +++ b/go.sum @@ -541,6 +541,10 @@ github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFo github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/segmentio/asm v1.1.3 h1:WM03sfUOENvvKexOLp+pCqgb/WDjsi7EK8gIsICtzhc= +github.com/segmentio/asm v1.1.3/go.mod h1:Ld3L4ZXGNcSLRg4JBsZ3//1+f/TjYl0Mzen/DQy1EJg= +github.com/segmentio/encoding v0.5.1 h1:LhmgXA5/alniiqfc4cYYrxF6DbUQ3m8MVz4/LQIU1mg= +github.com/segmentio/encoding v0.5.1/go.mod h1:HS1ZKa3kSN32ZHVZ7ZLPLXWvOVIiZtyJnO1gPH1sKt0= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= diff --git a/tests/network/network.go b/tests/network/network.go index 9235b968d..5bd9da838 100644 --- a/tests/network/network.go +++ b/tests/network/network.go @@ -5,7 +5,9 @@ import ( "crypto/ecdsa" "encoding/hex" "encoding/json" + "io/fs" goLog "log" + "os" "sort" "time" @@ -77,7 +79,6 @@ type L1Spec struct { func newTmpnetNetwork( name string, - extraNodes []*tmpnet.Node, globalFundedKey *secp256k1.PrivateKey, warpGenesisTemplateFile string, numPrimaryNetworkValidators int, @@ -92,10 +93,6 @@ func newTmpnetNetwork( // but will remain a primary network validator initialL1Bootstrapper := bootstrapNodes[i] // One bootstrap node per L1 - // Create validators to specify as the initial vdr set in the L1 conversion, and store them as extra nodes - initialVdrNodes := subnetEvmTestUtils.NewTmpnetNodes(l1Spec.NodeCount) - extraNodes = append(extraNodes, initialVdrNodes...) - l1 := subnetEvmTestUtils.NewTmpnetSubnet( l1Spec.Name, utils.InstantiateGenesisTemplate( @@ -158,6 +155,11 @@ func NewLocalNetwork( // Create extra nodes to be used to add more validators later extraNodes := subnetEvmTestUtils.NewTmpnetNodes(extraNodeCount) + for _, l1Spec := range l1Specs { + initialVdrNodes := subnetEvmTestUtils.NewTmpnetNodes(l1Spec.NodeCount) + extraNodes = append(extraNodes, initialVdrNodes...) + } + fundedKey, err := hex.DecodeString(fundedKeyStr) Expect(err).Should(BeNil()) globalFundedKey, err := secp256k1.ToPrivateKey(fundedKey) @@ -174,15 +176,24 @@ func NewLocalNetwork( isReuseNetwork := flagVars != nil && flagVars.NetworkDir() != "" var network *tmpnet.Network + // All nodes are specified as bootstrap validators + var primaryNetworkValidators []*tmpnet.Node if isReuseNetwork { // Load existing network and restart nodes network, err = tmpnet.ReadNetwork(context.Background(), logging.NoLog{}, flagVars.NetworkDir()) Expect(err).Should(BeNil()) Expect(network).ShouldNot(BeNil()) + extraNodes = make([]*tmpnet.Node, 0) for _, node := range network.Nodes { err := node.Restart(ctx) Expect(err).Should(BeNil(), "Failed to restart node %s: %v", node.NodeID, err) + + if node.Flags[config.PartialSyncPrimaryNetworkKey] == "true" { + extraNodes = append(extraNodes, node) + } else { + primaryNetworkValidators = append(primaryNetworkValidators, node) + } } err := tmpnet.WaitForHealthyNodes(ctx, logging.NoLog{}, network.Nodes) @@ -190,13 +201,14 @@ func NewLocalNetwork( } else { network = newTmpnetNetwork( name, - extraNodes, globalFundedKey, warpGenesisTemplateFile, numPrimaryNetworkValidators, l1Specs, flagVars, ) + + primaryNetworkValidators = append(primaryNetworkValidators, network.Nodes...) } tc := e2e.NewTestContext() @@ -216,10 +228,6 @@ func NewLocalNetwork( } } - // All nodes are specified as bootstrap validators - var primaryNetworkValidators []*tmpnet.Node - primaryNetworkValidators = append(primaryNetworkValidators, network.Nodes...) - localNetwork := &LocalNetwork{ Network: network, extraNodes: extraNodes, @@ -646,3 +654,41 @@ func (n *LocalNetwork) GetTwoL1s() ( Expect(len(l1s)).Should(BeNumerically(">=", 2)) return l1s[0], l1s[1] } + +func (n *LocalNetwork) SaveValidatorAddress( + fileName string, +) { + validatorAddresses := make(map[string]map[string]string) + for _, subnet := range n.GetL1Infos() { + validator, validatorSpec := n.GetValidatorManager(subnet.SubnetID) + validatorAddresses[subnet.BlockchainID.Hex()] = make(map[string]string) + validatorAddresses[subnet.BlockchainID.Hex()]["validator"] = validator.Address.Hex() + validatorAddresses[subnet.BlockchainID.Hex()]["spec"] = validatorSpec.Address.Hex() + } + + jsonData, err := json.Marshal(validatorAddresses) + Expect(err).Should(BeNil()) + err = os.WriteFile(fileName, jsonData, fs.ModePerm) + Expect(err).Should(BeNil()) +} + +func (n *LocalNetwork) SetValidatorAddressFromFile(fileName string) { + validatorAddresses := make(map[string]map[string]string) + data, err := os.ReadFile(fileName) + Expect(err).Should(BeNil()) + err = json.Unmarshal(data, &validatorAddresses) + Expect(err).Should(BeNil()) + + // Set the validator manager for each L1 + for _, subnet := range n.GetL1Infos() { + validatorAddress := common.HexToAddress(validatorAddresses[subnet.BlockchainID.Hex()]["validator"]) + validatorSpecAddress := common.HexToAddress(validatorAddresses[subnet.BlockchainID.Hex()]["spec"]) + + n.validatorManagers[subnet.SubnetID] = ProxyAddress{ + Address: validatorAddress, + } + n.validatorManagerSpecializations[subnet.SubnetID] = ProxyAddress{ + Address: validatorSpecAddress, + } + } +} diff --git a/tests/suites/ictt/ictt_suite_test.go b/tests/suites/ictt/ictt_suite_test.go index becce550d..fffd31cad 100644 --- a/tests/suites/ictt/ictt_suite_test.go +++ b/tests/suites/ictt/ictt_suite_test.go @@ -4,6 +4,7 @@ import ( "context" "flag" "fmt" + "io/fs" "math/big" "os" "testing" @@ -14,9 +15,11 @@ import ( localnetwork "github.com/ava-labs/icm-contracts/tests/network" "github.com/ava-labs/icm-contracts/tests/utils" deploymentUtils "github.com/ava-labs/icm-contracts/utils/deployment-utils" + "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/log" "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + "github.com/segmentio/encoding/json" ) const ( @@ -32,6 +35,8 @@ const ( sendAndCallLabel = "SendAndCall" registrationLabel = "Registration" upgradabilityLabel = "upgradability" + + teleporterRegistryAddressFile = "TeleporterRegistryAddress.json" ) var ( @@ -114,6 +119,23 @@ var _ = ginkgo.BeforeSuite(func() { teleporterContractAddress, fundedKey, ) + + for _, l1 := range LocalNetworkInstance.GetAllL1Infos() { + TeleporterInfo.SetTeleporter(teleporterContractAddress, l1) + TeleporterInfo.InitializeBlockchainID(l1, fundedKey) + TeleporterInfo.DeployTeleporterRegistry(l1, fundedKey) + } + + registryAddresseses := make(map[string]string) + for l1, teleporterInfo := range TeleporterInfo { + registryAddresseses[l1.Hex()] = teleporterInfo.TeleporterRegistryAddress.Hex() + } + + jsonData, err := json.Marshal(registryAddresseses) + Expect(err).Should(BeNil()) + err = os.WriteFile(teleporterRegistryAddressFile, jsonData, fs.ModePerm) + Expect(err).Should(BeNil()) + } else { fundAmount := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(15)) // 11 AVAX fundDeployerTx := utils.CreateNativeTransferTransaction( @@ -121,13 +143,23 @@ var _ = ginkgo.BeforeSuite(func() { ) utils.SendTransactionAndWaitForSuccess(ctx, LocalNetworkInstance.GetPrimaryNetworkInfo(), fundDeployerTx) fmt.Println("Deployer funded with", fundAmount, "AVAX") - } - for _, l1 := range LocalNetworkInstance.GetAllL1Infos() { - TeleporterInfo.SetTeleporter(teleporterContractAddress, l1) - TeleporterInfo.InitializeBlockchainID(l1, fundedKey) - TeleporterInfo.DeployTeleporterRegistry(l1, fundedKey) + // Read the Teleporter registry address from the file + registryAddresseses := make(map[string]string) + data, err := os.ReadFile(teleporterRegistryAddressFile) + Expect(err).Should(BeNil()) + err = json.Unmarshal(data, ®istryAddresseses) + Expect(err).Should(BeNil()) + + for _, l1 := range LocalNetworkInstance.GetAllL1Infos() { + TeleporterInfo.SetTeleporter(teleporterContractAddress, l1) + TeleporterInfo.SetTeleporterRegistry( + common.HexToAddress(registryAddresseses[l1.BlockchainID.Hex()]), + l1, + ) + } } + }) var _ = ginkgo.AfterSuite(func() { @@ -137,63 +169,59 @@ var _ = ginkgo.AfterSuite(func() { var _ = ginkgo.Describe("[Validator manager integration tests]", func() { // ICTT tests - - // ginkgo.It("Transfer an ERC20 token between two L1s", - // ginkgo.Label(icttLabel, erc20TokenHomeLabel, erc20TokenRemoteLabel), - // func() { - // icttFlows.ERC20TokenHomeERC20TokenRemote(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Transfer a native token to an ERC20 token", - // ginkgo.Label(icttLabel, nativeTokenHomeLabel, erc20TokenRemoteLabel), - // func() { - // icttFlows.NativeTokenHomeERC20TokenRemote(LocalNetworkInstance, TeleporterInfo) - // }) - - // TODO: failed + ginkgo.It("Transfer an ERC20 token between two L1s", + ginkgo.Label(icttLabel, erc20TokenHomeLabel, erc20TokenRemoteLabel), + func() { + icttFlows.ERC20TokenHomeERC20TokenRemote(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Transfer a native token to an ERC20 token", + ginkgo.Label(icttLabel, nativeTokenHomeLabel, erc20TokenRemoteLabel), + func() { + icttFlows.NativeTokenHomeERC20TokenRemote(LocalNetworkInstance, TeleporterInfo) + }) ginkgo.It("Transfer a native token to a native token", ginkgo.Label(icttLabel, nativeTokenHomeLabel, nativeTokenRemoteLabel), func() { icttFlows.NativeTokenHomeNativeDestination(LocalNetworkInstance, TeleporterInfo) }) - - // ginkgo.It("Transfer an ERC20 token with ERC20TokenHome multi-hop", - // ginkgo.Label(icttLabel, erc20TokenHomeLabel, erc20TokenRemoteLabel, multiHopLabel), - // func() { - // icttFlows.ERC20TokenHomeERC20TokenRemoteMultiHop(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Transfer a native token with NativeTokenHome multi-hop", - // ginkgo.Label(icttLabel, nativeTokenHomeLabel, erc20TokenRemoteLabel, multiHopLabel), - // func() { - // icttFlows.NativeTokenHomeERC20TokenRemoteMultiHop(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Transfer an ERC20 token to a native token", - // ginkgo.Label(icttLabel, erc20TokenHomeLabel, nativeTokenRemoteLabel), - // func() { - // icttFlows.ERC20TokenHomeNativeTokenRemote(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Transfer a native token with ERC20TokenHome multi-hop", - // ginkgo.Label(icttLabel, erc20TokenHomeLabel, nativeTokenRemoteLabel, multiHopLabel), - // func() { - // icttFlows.ERC20TokenHomeNativeTokenRemoteMultiHop(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Transfer a native token to a native token multi-hop", - // ginkgo.Label(icttLabel, nativeTokenHomeLabel, nativeTokenRemoteLabel, multiHopLabel), - // func() { - // icttFlows.NativeTokenHomeNativeTokenRemoteMultiHop(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Transfer an ERC20 token using sendAndCall", - // ginkgo.Label(icttLabel, erc20TokenHomeLabel, erc20TokenRemoteLabel, sendAndCallLabel), - // func() { - // icttFlows.ERC20TokenHomeERC20TokenRemoteSendAndCall(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Registration and collateral checks", - // ginkgo.Label(icttLabel, erc20TokenHomeLabel, nativeTokenRemoteLabel, registrationLabel), - // func() { - // icttFlows.RegistrationAndCollateralCheck(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Transparent proxy upgrade", - // ginkgo.Label(icttLabel, erc20TokenHomeLabel, erc20TokenRemoteLabel, upgradabilityLabel), - // func() { - // icttFlows.TransparentUpgradeableProxy(LocalNetworkInstance, TeleporterInfo) - // }) + ginkgo.It("Transfer an ERC20 token with ERC20TokenHome multi-hop", + ginkgo.Label(icttLabel, erc20TokenHomeLabel, erc20TokenRemoteLabel, multiHopLabel), + func() { + icttFlows.ERC20TokenHomeERC20TokenRemoteMultiHop(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Transfer a native token with NativeTokenHome multi-hop", + ginkgo.Label(icttLabel, nativeTokenHomeLabel, erc20TokenRemoteLabel, multiHopLabel), + func() { + icttFlows.NativeTokenHomeERC20TokenRemoteMultiHop(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Transfer an ERC20 token to a native token", + ginkgo.Label(icttLabel, erc20TokenHomeLabel, nativeTokenRemoteLabel), + func() { + icttFlows.ERC20TokenHomeNativeTokenRemote(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Transfer a native token with ERC20TokenHome multi-hop", + ginkgo.Label(icttLabel, erc20TokenHomeLabel, nativeTokenRemoteLabel, multiHopLabel), + func() { + icttFlows.ERC20TokenHomeNativeTokenRemoteMultiHop(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Transfer a native token to a native token multi-hop", + ginkgo.Label(icttLabel, nativeTokenHomeLabel, nativeTokenRemoteLabel, multiHopLabel), + func() { + icttFlows.NativeTokenHomeNativeTokenRemoteMultiHop(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Transfer an ERC20 token using sendAndCall", + ginkgo.Label(icttLabel, erc20TokenHomeLabel, erc20TokenRemoteLabel, sendAndCallLabel), + func() { + icttFlows.ERC20TokenHomeERC20TokenRemoteSendAndCall(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Registration and collateral checks", + ginkgo.Label(icttLabel, erc20TokenHomeLabel, nativeTokenRemoteLabel, registrationLabel), + func() { + icttFlows.RegistrationAndCollateralCheck(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Transparent proxy upgrade", + ginkgo.Label(icttLabel, erc20TokenHomeLabel, erc20TokenRemoteLabel, upgradabilityLabel), + func() { + icttFlows.TransparentUpgradeableProxy(LocalNetworkInstance, TeleporterInfo) + }) }) diff --git a/tests/suites/teleporter/teleporter_suite_test.go b/tests/suites/teleporter/teleporter_suite_test.go index 4034c0c94..cbba19ebd 100644 --- a/tests/suites/teleporter/teleporter_suite_test.go +++ b/tests/suites/teleporter/teleporter_suite_test.go @@ -13,6 +13,7 @@ import ( "github.com/ava-labs/avalanchego/tests/fixture/e2e" "github.com/ava-labs/avalanchego/utils/units" teleporterFlows "github.com/ava-labs/icm-contracts/tests/flows/teleporter" + registryFlows "github.com/ava-labs/icm-contracts/tests/flows/teleporter/registry" "github.com/ava-labs/icm-contracts/tests/network" "github.com/ava-labs/icm-contracts/tests/utils" deploymentUtils "github.com/ava-labs/icm-contracts/utils/deployment-utils" @@ -28,6 +29,9 @@ const ( teleporterMessengerLabel = "TeleporterMessenger" upgradabilityLabel = "upgradability" utilsLabel = "utils" + + teleporterRegistryAddressFile = "TeleporterRegistryAddress.json" + validatorAddressesFile = "ValidatorAddresses.json" ) var ( @@ -123,12 +127,28 @@ var _ = ginkgo.BeforeSuite(func() { false, ) } - } - for _, l1 := range LocalNetworkInstance.GetAllL1Infos() { - TeleporterInfo.SetTeleporter(teleporterContractAddress, l1) - TeleporterInfo.InitializeBlockchainID(l1, fundedKey) - TeleporterInfo.DeployTeleporterRegistry(l1, fundedKey) + for _, l1 := range LocalNetworkInstance.GetAllL1Infos() { + TeleporterInfo.SetTeleporter(teleporterContractAddress, l1) + TeleporterInfo.InitializeBlockchainID(l1, fundedKey) + TeleporterInfo.DeployTeleporterRegistry(l1, fundedKey) + } + + // Save the Teleporter registry address and validator addresses to files + utils.SaveRegistyAddress(TeleporterInfo, teleporterRegistryAddressFile) + + LocalNetworkInstance.SaveValidatorAddress(validatorAddressesFile) + } else { + // Read the Teleporter registry address from the file + utils.SetTeleporterInfoFromFile( + teleporterRegistryAddressFile, + teleporterContractAddress, + TeleporterInfo, + LocalNetworkInstance.GetAllL1Infos(), + ) + + // Read the validator addresses from the file + LocalNetworkInstance.SetValidatorAddressFromFile(validatorAddressesFile) } log.Info("Set up ginkgo before suite") @@ -146,81 +166,81 @@ var _ = ginkgo.Describe("[Teleporter integration tests]", func() { func() { teleporterFlows.BasicSendReceive(LocalNetworkInstance, TeleporterInfo) }) - // ginkgo.It("Deliver to the wrong chain", - // ginkgo.Label(teleporterMessengerLabel), - // func() { - // teleporterFlows.DeliverToWrongChain(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Deliver to non-existent contract", - // ginkgo.Label(teleporterMessengerLabel), - // func() { - // teleporterFlows.DeliverToNonExistentContract(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Retry successful execution", - // ginkgo.Label(teleporterMessengerLabel), - // func() { - // teleporterFlows.RetrySuccessfulExecution(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Unallowed relayer", - // ginkgo.Label(teleporterMessengerLabel), - // func() { - // teleporterFlows.UnallowedRelayer(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Relay message twice", - // ginkgo.Label(teleporterMessengerLabel), - // func() { - // teleporterFlows.RelayMessageTwice(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Add additional fee amount", - // ginkgo.Label(teleporterMessengerLabel), - // func() { - // teleporterFlows.AddFeeAmount(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Send specific receipts", - // ginkgo.Label(teleporterMessengerLabel), - // func() { - // teleporterFlows.SendSpecificReceipts(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Insufficient gas", - // ginkgo.Label(teleporterMessengerLabel), - // func() { - // teleporterFlows.InsufficientGas(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Resubmit altered message", - // ginkgo.Label(teleporterMessengerLabel), - // func() { - // teleporterFlows.ResubmitAlteredMessage(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Calculate Teleporter message IDs", - // ginkgo.Label(utilsLabel), - // func() { - // teleporterFlows.CalculateMessageID(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Relayer modifies message", - // ginkgo.Label(teleporterMessengerLabel), - // func() { - // teleporterFlows.RelayerModifiesMessage(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Validator churn", - // ginkgo.Label(teleporterMessengerLabel), - // func() { - // teleporterFlows.ValidatorChurn(LocalNetworkInstance, TeleporterInfo) - // }) - - // // Teleporter Registry tests - // ginkgo.It("Teleporter registry", - // ginkgo.Label(upgradabilityLabel), - // func() { - // registryFlows.TeleporterRegistry(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Check upgrade access", - // ginkgo.Label(upgradabilityLabel), - // func() { - // registryFlows.CheckUpgradeAccess(LocalNetworkInstance, TeleporterInfo) - // }) - // ginkgo.It("Pause and Unpause Teleporter", - // ginkgo.Label(upgradabilityLabel), - // func() { - // registryFlows.PauseTeleporter(LocalNetworkInstance, TeleporterInfo) - // }) + ginkgo.It("Deliver to the wrong chain", + ginkgo.Label(teleporterMessengerLabel), + func() { + teleporterFlows.DeliverToWrongChain(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Deliver to non-existent contract", + ginkgo.Label(teleporterMessengerLabel), + func() { + teleporterFlows.DeliverToNonExistentContract(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Retry successful execution", + ginkgo.Label(teleporterMessengerLabel), + func() { + teleporterFlows.RetrySuccessfulExecution(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Unallowed relayer", + ginkgo.Label(teleporterMessengerLabel), + func() { + teleporterFlows.UnallowedRelayer(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Relay message twice", + ginkgo.Label(teleporterMessengerLabel), + func() { + teleporterFlows.RelayMessageTwice(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Add additional fee amount", + ginkgo.Label(teleporterMessengerLabel), + func() { + teleporterFlows.AddFeeAmount(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Send specific receipts", + ginkgo.Label(teleporterMessengerLabel), + func() { + teleporterFlows.SendSpecificReceipts(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Insufficient gas", + ginkgo.Label(teleporterMessengerLabel), + func() { + teleporterFlows.InsufficientGas(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Resubmit altered message", + ginkgo.Label(teleporterMessengerLabel), + func() { + teleporterFlows.ResubmitAlteredMessage(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Calculate Teleporter message IDs", + ginkgo.Label(utilsLabel), + func() { + teleporterFlows.CalculateMessageID(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Relayer modifies message", + ginkgo.Label(teleporterMessengerLabel), + func() { + teleporterFlows.RelayerModifiesMessage(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Validator churn", + ginkgo.Label(teleporterMessengerLabel), + func() { + teleporterFlows.ValidatorChurn(LocalNetworkInstance, TeleporterInfo) + }) + + // Teleporter Registry tests + ginkgo.It("Teleporter registry", + ginkgo.Label(upgradabilityLabel), + func() { + registryFlows.TeleporterRegistry(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Check upgrade access", + ginkgo.Label(upgradabilityLabel), + func() { + registryFlows.CheckUpgradeAccess(LocalNetworkInstance, TeleporterInfo) + }) + ginkgo.It("Pause and Unpause Teleporter", + ginkgo.Label(upgradabilityLabel), + func() { + registryFlows.PauseTeleporter(LocalNetworkInstance, TeleporterInfo) + }) }) diff --git a/tests/utils/teleporter.go b/tests/utils/teleporter.go index 48bde37ec..547f02c6f 100644 --- a/tests/utils/teleporter.go +++ b/tests/utils/teleporter.go @@ -4,7 +4,11 @@ import ( "bytes" "context" "crypto/ecdsa" + "encoding/json" + "fmt" + "io/fs" "math/big" + "os" "github.com/ava-labs/avalanchego/ids" avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" @@ -82,6 +86,16 @@ func (t TeleporterTestInfo) SetTeleporter(address common.Address, l1 interfaces. info.TeleporterMessenger = teleporterMessenger } +func (t TeleporterTestInfo) SetTeleporterRegistry(address common.Address, l1 interfaces.L1TestInfo) { + teleporterRegistry, err := teleporterregistry.NewTeleporterRegistry( + address, l1.RPCClient, + ) + Expect(err).Should(BeNil()) + info := t[l1.BlockchainID] + info.TeleporterRegistryAddress = address + info.TeleporterRegistry = teleporterRegistry +} + func (t TeleporterTestInfo) InitializeBlockchainID(l1 interfaces.L1TestInfo, fundedKey *ecdsa.PrivateKey) { opts, err := bind.NewKeyedTransactorWithChainID(fundedKey, l1.EVMChainID) Expect(err).Should(BeNil()) @@ -192,6 +206,7 @@ func (t TeleporterTestInfo) RelayTeleporterMessage( receipt.Logs, t.TeleporterMessenger(destination).ParseReceiveCrossChainMessage, ) + fmt.Println("receiveEvent", receiveEvent) Expect(err).Should(BeNil()) Expect(receiveEvent.SourceBlockchainID[:]).Should(Equal(source.BlockchainID[:])) return receipt @@ -832,3 +847,41 @@ func CreateOffChainRegistryMessage( return unsignedMessage } + +func SaveRegistyAddress( + teleporterInfo TeleporterTestInfo, + fileName string, +) { + // Save the Teleporter registry address and validator addresses to files + registryAddresseses := make(map[string]string) + for l1, teleporterInfo := range teleporterInfo { + registryAddresseses[l1.Hex()] = teleporterInfo.TeleporterRegistryAddress.Hex() + } + + jsonData, err := json.Marshal(registryAddresseses) + Expect(err).Should(BeNil()) + err = os.WriteFile(fileName, jsonData, fs.ModePerm) + Expect(err).Should(BeNil()) +} + +func SetTeleporterInfoFromFile( + fileName string, + teleporterContractAddress common.Address, + teleporterInfo TeleporterTestInfo, + l1s []interfaces.L1TestInfo, +) { + // Read the Teleporter registry address from the file + registryAddresseses := make(map[string]string) + data, err := os.ReadFile(fileName) + Expect(err).Should(BeNil()) + err = json.Unmarshal(data, ®istryAddresseses) + Expect(err).Should(BeNil()) + + for _, l1 := range l1s { + teleporterInfo.SetTeleporter(teleporterContractAddress, l1) + teleporterInfo.SetTeleporterRegistry( + common.HexToAddress(registryAddresseses[l1.BlockchainID.Hex()]), + l1, + ) + } +} From 095d1bbc59ee597c6c693d49ac1b87cd1d6da0ae Mon Sep 17 00:00:00 2001 From: ylg Date: Mon, 14 Jul 2025 00:03:21 -0400 Subject: [PATCH 3/4] add TestMain --- .../validator-manager/validator_manager_suite_test.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/suites/validator-manager/validator_manager_suite_test.go b/tests/suites/validator-manager/validator_manager_suite_test.go index 4f2691ae3..8fdd5e5e0 100644 --- a/tests/suites/validator-manager/validator_manager_suite_test.go +++ b/tests/suites/validator-manager/validator_manager_suite_test.go @@ -2,6 +2,7 @@ package validator_manager_test import ( "context" + "flag" "os" "testing" "time" @@ -24,12 +25,17 @@ var ( e2eFlags *e2e.FlagVars ) +func TestMain(m *testing.M) { + e2eFlags = e2e.RegisterFlags() + flag.Parse() + os.Exit(m.Run()) +} + func TestValidatorManager(t *testing.T) { if os.Getenv("RUN_E2E") == "" { t.Skip("Environment variable RUN_E2E not set; skipping E2E tests") } - e2eFlags = e2e.RegisterFlags() RegisterFailHandler(ginkgo.Fail) ginkgo.RunSpecs(t, "Validator Manager e2e test") } From beb9da2bb13f0469a70b0f817439f0cbcb471dfb Mon Sep 17 00:00:00 2001 From: ylg Date: Wed, 30 Jul 2025 15:41:19 -0400 Subject: [PATCH 4/4] set the root network dir --- scripts/e2e_test.sh | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/scripts/e2e_test.sh b/scripts/e2e_test.sh index 6565a173b..4bd671fbe 100755 --- a/scripts/e2e_test.sh +++ b/scripts/e2e_test.sh @@ -21,7 +21,10 @@ Arguments: --components component1,component2 Comma separated list of test suites to run. Valid components are: $(echo $valid_components | tr ' ' '\n' | sort | tr '\n' ' ') (default: all) - --network-dir path Path to the network directory to reuse. If not provided, a new network will be created. + --network-dir path Path to the network directory. + If the directory does not exist or is empty, it will be used as the root network directory for a new network. + If the directory exists and is non-empty, the network will be reused. + If not set, a new network will be created at the default root network directory. Options: --help Print this help message EOF @@ -29,6 +32,8 @@ EOF valid_components=$(ls -d $ICM_CONTRACTS_PATH/tests/suites/*/ | xargs -n 1 basename) components= +reuse_network_dir= +root_dir= network_dir= reuse_network=false @@ -43,7 +48,7 @@ while [ $# -gt 0 ]; do shift;; --network-dir) if [[ $2 != --* ]]; then - network_dir=$2 + reuse_network_dir=$2 else echo "Invalid network directory $2" && printHelp && exit 1 fi @@ -68,10 +73,16 @@ for component in $(echo $components | tr ',' ' '); do fi done -# If network_dir is set, set reuse-network flag -if [ -n "$network_dir" ]; then - reuse_network=true - echo "Using network directory: $network_dir" +if [ -n "$reuse_network_dir" ]; then + if [ -d "$reuse_network_dir" ] && [ "$(ls -A "$reuse_network_dir")" ]; then + network_dir=$reuse_network_dir + reuse_network=true + echo "Reuse network directory: $network_dir" + else + echo "Network directory $reuse_network_dir does not exist or is empty. Creating a new network at root $reuse_network_dir." + mkdir -p "$reuse_network_dir" + root_dir=$reuse_network_dir + fi fi source "$ICM_CONTRACTS_PATH"/scripts/constants.sh @@ -116,6 +127,7 @@ for component in $(echo $components | tr ',' ' '); do echo "Running e2e tests for $component" RUN_E2E=true SIG_AGG_PATH=$ICM_SERVICES_BUILD_PATH/signature-aggregator ./tests/suites/$component/$component.test \ + --root-network-dir=${root_dir} \ --reuse-network=${reuse_network} \ --network-dir=${network_dir} \ --ginkgo.vv \