From e3963d3d49fac24d87d1bedd5b8a9dc5d91f83bc Mon Sep 17 00:00:00 2001 From: kevinssgh Date: Tue, 19 Dec 2023 16:39:39 -0400 Subject: [PATCH 1/8] fixed local stress test --- .../smoketest/cmd/smoketest/root.go | 1 + .../smoketest/cmd/smoketest/stress.go | 683 ++++++++++-------- 2 files changed, 365 insertions(+), 319 deletions(-) diff --git a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/root.go b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/root.go index 7f0d513e2a..b8964b4675 100644 --- a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/root.go +++ b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/root.go @@ -8,6 +8,7 @@ func NewRootCmd() *cobra.Command { Short: "Smoke Test CLI", } cmd.AddCommand(NewLocalCmd()) + cmd.AddCommand(NewStressTestCmd()) return cmd } diff --git a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go index 670922056f..beedb16b2d 100644 --- a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go +++ b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go @@ -1,321 +1,366 @@ package main -//import ( -// "context" -// "errors" -// "fmt" -// "math/big" -// "os" -// "sort" -// "time" -// -// authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" -// banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" -// "github.com/ethereum/go-ethereum/accounts/abi/bind" -// ethcommon "github.com/ethereum/go-ethereum/common" -// "github.com/ethereum/go-ethereum/crypto" -// "github.com/ethereum/go-ethereum/ethclient" -// "github.com/spf13/cobra" -// "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zrc20.sol" -// crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" -// fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" -// observertypes "github.com/zeta-chain/zetacore/x/observer/types" -// "google.golang.org/grpc" -//) -// -//const ( -// StatInterval = 5 -// StressTestTimeout = 100 * time.Minute -//) -// -//var ( -// zevmNonce = big.NewInt(1) -//) -// -//var StressCmd = &cobra.Command{ -// Use: "stress", -// Short: "Run Local Stress Test", -// Run: StressTest, -//} -// -//type stressArguments struct { -// ethURL string -// grpcURL string -// zevmURL string -// deployerAddress string -// deployerPrivateKey string -// network string -// txnInterval int64 -//} -// -//var stressTestArgs = stressArguments{} -// -//func init() { -// RootCmd.AddCommand(StressCmd) -// StressCmd.Flags().StringVar(&stressTestArgs.ethURL, "ethURL", "http://eth:8545", "--ethURL http://eth:8545") -// StressCmd.Flags().StringVar(&stressTestArgs.grpcURL, "grpcURL", "zetacore0:9090", "--grpcURL zetacore0:9090") -// StressCmd.Flags().StringVar(&stressTestArgs.zevmURL, "zevmURL", zevmRPC, "--zevmURL http://zetacore0:8545") -// StressCmd.Flags().StringVar(&stressTestArgs.deployerAddress, "addr", "0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC", "--addr ") -// StressCmd.Flags().StringVar(&stressTestArgs.deployerPrivateKey, "privKey", "d87baf7bf6dc560a252596678c12e41f7d1682837f05b29d411bc3f78ae2c263", "--privKey ") -// StressCmd.Flags().StringVar(&stressTestArgs.network, "network", "PRIVNET", "--network PRIVNET") -// StressCmd.Flags().Int64Var(&stressTestArgs.txnInterval, "tx-interval", 500, "--tx-interval [TIME_INTERVAL_MILLISECONDS]") -// -// DeployerAddress = ethcommon.HexToAddress(stressTestArgs.deployerAddress) -//} -// -//func StressTest(_ *cobra.Command, _ []string) { -// testStartTime := time.Now() -// defer func() { -// fmt.Println("Smoke test took", time.Since(testStartTime)) -// }() -// go func() { -// time.Sleep(StressTestTimeout) -// fmt.Println("Smoke test timed out after", StressTestTimeout) -// os.Exit(1) -// }() -// -// goerliClient, err := ethclient.Dial(stressTestArgs.ethURL) -// if err != nil { -// panic(err) -// } -// -// bal, err := goerliClient.BalanceAt(context.TODO(), DeployerAddress, nil) -// if err != nil { -// panic(err) -// } -// fmt.Printf("Deployer address: %s, balance: %d Wei\n", DeployerAddress.Hex(), bal) -// -// chainid, err := goerliClient.ChainID(context.Background()) -// if err != nil { -// panic(err) -// } -// deployerPrivkey, err := crypto.HexToECDSA(stressTestArgs.deployerPrivateKey) -// if err != nil { -// panic(err) -// } -// goerliAuth, err := bind.NewKeyedTransactorWithChainID(deployerPrivkey, chainid) -// if err != nil { -// panic(err) -// } -// -// grpcConn, err := grpc.Dial(stressTestArgs.grpcURL, grpc.WithInsecure()) -// if err != nil { -// panic(err) -// } -// -// cctxClient := crosschaintypes.NewQueryClient(grpcConn) -// fungibleClient := fungibletypes.NewQueryClient(grpcConn) -// bankClient := banktypes.NewQueryClient(grpcConn) -// authClient := authtypes.NewQueryClient(grpcConn) -// observerClient := observertypes.NewQueryClient(grpcConn) -// -// // Wait for Genesis and keygen to be completed. ~ height 30 -// time.Sleep(20 * time.Second) -// for { -// time.Sleep(5 * time.Second) -// response, err := cctxClient.LastZetaHeight(context.Background(), &crosschaintypes.QueryLastZetaHeightRequest{}) -// if err != nil { -// fmt.Printf("cctxClient.LastZetaHeight error: %s", err) -// continue -// } -// if response.Height >= 30 { -// break -// } -// fmt.Printf("Last ZetaHeight: %d\n", response.Height) -// } -// -// // get the clients for tests -// var zevmClient *ethclient.Client -// for { -// time.Sleep(5 * time.Second) -// fmt.Printf("dialing zevm client: %s\n", stressTestArgs.zevmURL) -// zevmClient, err = ethclient.Dial(stressTestArgs.zevmURL) -// if err != nil { -// continue -// } -// break -// } -// chainid, err = zevmClient.ChainID(context.Background()) -// if err != nil { -// panic(err) -// } -// zevmAuth, err := bind.NewKeyedTransactorWithChainID(deployerPrivkey, chainid) -// if err != nil { -// panic(err) -// } -// -// smokeTest := NewSmokeTest( -// goerliClient, -// zevmClient, -// cctxClient, -// ZetaTxServer{}, // not used in stress test -// fungibleClient, -// authClient, -// bankClient, -// observerClient, -// goerliAuth, -// zevmAuth, -// nil, -// ) -// -// // If stress test is running on local docker environment -// if stressTestArgs.network == "PRIVNET" { -// smokeTest.TestSetupZetaTokenAndConnectorAndZEVMContracts() -// smokeTest.TestDepositEtherIntoZRC20() -// smokeTest.TestSendZetaIn() -// } else if stressTestArgs.network == "TESTNET" { -// ethZRC20Addr, err := smokeTest.SystemContract.GasCoinZRC20ByChainId(&bind.CallOpts{}, big.NewInt(5)) -// if err != nil { -// panic(err) -// } -// smokeTest.ETHZRC20Addr = ethZRC20Addr -// smokeTest.ETHZRC20, err = zrc20.NewZRC20(smokeTest.ETHZRC20Addr, smokeTest.zevmClient) -// if err != nil { -// panic(err) -// } -// } else { -// err := errors.New("invalid network argument: " + stressTestArgs.network) -// panic(err) -// } -// -// // Check zrc20 balance of Deployer address -// ethZRC20Balance, err := smokeTest.ETHZRC20.BalanceOf(nil, DeployerAddress) -// if err != nil { -// panic(err) -// } -// fmt.Printf("eth zrc20 balance: %s Wei \n", ethZRC20Balance.String()) -// -// //Pre-approve ETH withdraw on ZEVM -// fmt.Printf("approving ETH ZRC20...\n") -// ethZRC20 := smokeTest.ETHZRC20 -// tx, err := ethZRC20.Approve(smokeTest.zevmAuth, smokeTest.ETHZRC20Addr, big.NewInt(1e18)) -// if err != nil { -// panic(err) -// } -// receipt := MustWaitForTxReceipt(smokeTest.zevmClient, tx) -// fmt.Printf("eth zrc20 approve receipt: status %d\n", receipt.Status) -// -// // Get current nonce on zevm for DeployerAddress - Need to keep track of nonce at client level -// blockNum, err := smokeTest.zevmClient.BlockNumber(context.Background()) -// if err != nil { -// panic(err) -// } -// -// // #nosec G701 smoketest - always in range -// nonce, err := smokeTest.zevmClient.NonceAt(context.Background(), DeployerAddress, big.NewInt(int64(blockNum))) -// if err != nil { -// panic(err) -// } -// -// // #nosec G701 smoketest - always in range -// zevmNonce = big.NewInt(int64(nonce)) -// -// // -------------- TEST BEGINS ------------------ -// -// fmt.Println("**** STRESS TEST BEGINS ****") -// fmt.Println(" 1. Periodically Withdraw ETH from ZEVM to EVM - goerli") -// fmt.Println(" 2. Display Network metrics to monitor performance [Num Pending outbound tx], [Num Trackers]") -// -// smokeTest.wg.Add(2) -// go smokeTest.WithdrawCCtx() // Withdraw USDT from ZEVM to EVM - goerli -// go smokeTest.EchoNetworkMetrics() // Display Network metrics periodically to monitor performance -// -// smokeTest.wg.Wait() -//} -// -//// WithdrawCCtx withdraw USDT from ZEVM to EVM -//func (sm *SmokeTest) WithdrawCCtx() { -// ticker := time.NewTicker(time.Millisecond * time.Duration(stressTestArgs.txnInterval)) -// for { -// select { -// case <-ticker.C: -// sm.WithdrawETHZRC20() -// } -// } -//} -// -//func (sm *SmokeTest) EchoNetworkMetrics() { -// ticker := time.NewTicker(time.Second * StatInterval) -// var queue = make([]uint64, 0) -// var numTicks = 0 -// var totalMinedTxns = uint64(0) -// var previousMinedTxns = uint64(0) -// -// for { -// select { -// case <-ticker.C: -// numTicks++ -// // Get all pending outbound transactions -// cctxResp, err := sm.cctxClient.CctxListPending(context.Background(), &crosschaintypes.QueryListCctxPendingRequest{ -// ChainId: getChainID(), -// }) -// if err != nil { -// continue -// } -// sends := cctxResp.CrossChainTx -// sort.Slice(sends, func(i, j int) bool { -// return sends[i].GetCurrentOutTxParam().OutboundTxTssNonce < sends[j].GetCurrentOutTxParam().OutboundTxTssNonce -// }) -// if len(sends) > 0 { -// fmt.Printf("pending nonces %d to %d\n", sends[0].GetCurrentOutTxParam().OutboundTxTssNonce, sends[len(sends)-1].GetCurrentOutTxParam().OutboundTxTssNonce) -// } else { -// continue -// } -// // -// // Get all trackers -// trackerResp, err := sm.cctxClient.OutTxTrackerAll(context.Background(), &crosschaintypes.QueryAllOutTxTrackerRequest{}) -// if err != nil { -// continue -// } -// -// currentMinedTxns := sends[0].GetCurrentOutTxParam().OutboundTxTssNonce -// newMinedTxCnt := currentMinedTxns - previousMinedTxns -// previousMinedTxns = currentMinedTxns -// -// // Add new mined txn count to queue and remove the oldest entry -// queue = append(queue, newMinedTxCnt) -// if numTicks > 60/StatInterval { -// totalMinedTxns -= queue[0] -// queue = queue[1:] -// numTicks = 60/StatInterval + 1 //prevent overflow -// } -// -// //Calculate rate -> tx/min -// totalMinedTxns += queue[len(queue)-1] -// rate := totalMinedTxns -// -// numPending := len(cctxResp.CrossChainTx) -// numTrackers := len(trackerResp.OutTxTracker) -// -// fmt.Println("Network Stat => Num of Pending cctx: ", numPending, "Num active trackers: ", numTrackers, "Tx Rate: ", rate, " tx/min") -// } -// } -//} -// -//func (sm *SmokeTest) WithdrawETHZRC20() { -// defer func() { -// zevmNonce.Add(zevmNonce, big.NewInt(1)) -// }() -// -// ethZRC20 := sm.ETHZRC20 -// -// sm.zevmAuth.Nonce = zevmNonce -// _, err := ethZRC20.Withdraw(sm.zevmAuth, DeployerAddress.Bytes(), big.NewInt(100)) -// if err != nil { -// panic(err) -// } -//} -// -//// Get ETH based chain ID - Build flags are conflicting with current lib, need to do this manually -//func getChainID() int64 { -// switch stressTestArgs.network { -// case "PRIVNET": -// return 1337 -// case "TESTNET": -// return 5 -// case "MAINNET": -// return 1 -// default: -// return 1337 -// } -//} +import ( + "context" + "errors" + "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/zeta-chain/zetacore/app" + "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" + "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/txserver" + "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" + "math/big" + "os" + "sort" + "time" + + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/spf13/cobra" + "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zrc20.sol" + crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" + fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" + "google.golang.org/grpc" +) + +const ( + StatInterval = 5 + StressTestTimeout = 100 * time.Minute +) + +var ( + zevmNonce = big.NewInt(1) +) + +type stressArguments struct { + ethURL string + grpcURL string + zevmURL string + deployerAddress string + deployerPrivateKey string + network string + txnInterval int64 + contractsDeployed bool + config string +} + +var stressTestArgs = stressArguments{} + +func NewStressTestCmd() *cobra.Command { + var StressCmd = &cobra.Command{ + Use: "stress", + Short: "Run Local Stress Test", + Run: StressTest, + } + + StressCmd.Flags().StringVar(&stressTestArgs.ethURL, "ethURL", "http://eth:8545", "--ethURL http://eth:8545") + StressCmd.Flags().StringVar(&stressTestArgs.grpcURL, "grpcURL", "zetacore0:9090", "--grpcURL zetacore0:9090") + StressCmd.Flags().StringVar(&stressTestArgs.deployerAddress, "addr", "0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC", "--addr ") + StressCmd.Flags().StringVar(&stressTestArgs.deployerPrivateKey, "privKey", "d87baf7bf6dc560a252596678c12e41f7d1682837f05b29d411bc3f78ae2c263", "--privKey ") + StressCmd.Flags().StringVar(&stressTestArgs.network, "network", "", "--network TESTNET") + StressCmd.Flags().Int64Var(&stressTestArgs.txnInterval, "tx-interval", 500, "--tx-interval [TIME_INTERVAL_MILLISECONDS]") + StressCmd.Flags().BoolVar(&stressTestArgs.contractsDeployed, "contracts-deployed", false, "--contracts-deployed=false") + StressCmd.Flags().StringVar(&stressTestArgs.network, flagConfigFile, "", "config file to use for the smoketest") + + DeployerAddress = ethcommon.HexToAddress(stressTestArgs.deployerAddress) + + return StressCmd +} + +func StressTest(cmd *cobra.Command, _ []string) { + testStartTime := time.Now() + defer func() { + fmt.Println("Smoke test took", time.Since(testStartTime)) + }() + go func() { + time.Sleep(StressTestTimeout) + fmt.Println("Smoke test timed out after", StressTestTimeout) + os.Exit(1) + }() + + // set account prefix to zeta + cosmosConf := sdk.GetConfig() + cosmosConf.SetBech32PrefixForAccount(app.Bech32PrefixAccAddr, app.Bech32PrefixAccPub) + cosmosConf.Seal() + + // initialize smoke tests config + conf, err := getConfig(cmd) + if err != nil { + panic(err) + } + + goerliClient, err := ethclient.Dial(stressTestArgs.ethURL) + if err != nil { + panic(err) + } + + bal, err := goerliClient.BalanceAt(context.TODO(), DeployerAddress, nil) + if err != nil { + panic(err) + } + fmt.Printf("Deployer address: %s, balance: %d Wei\n", DeployerAddress.Hex(), bal) + + chainid, err := goerliClient.ChainID(context.Background()) + if err != nil { + panic(err) + } + deployerPrivkey, err := crypto.HexToECDSA(stressTestArgs.deployerPrivateKey) + if err != nil { + panic(err) + } + goerliAuth, err := bind.NewKeyedTransactorWithChainID(deployerPrivkey, chainid) + if err != nil { + panic(err) + } + + grpcConn, err := grpc.Dial(stressTestArgs.grpcURL, grpc.WithInsecure()) + if err != nil { + panic(err) + } + + cctxClient := crosschaintypes.NewQueryClient(grpcConn) + fungibleClient := fungibletypes.NewQueryClient(grpcConn) + bankClient := banktypes.NewQueryClient(grpcConn) + authClient := authtypes.NewQueryClient(grpcConn) + observerClient := observertypes.NewQueryClient(grpcConn) + + // Wait for Genesis and keygen to be completed. ~ height 30 + time.Sleep(20 * time.Second) + for { + time.Sleep(5 * time.Second) + response, err := cctxClient.LastZetaHeight(context.Background(), &crosschaintypes.QueryLastZetaHeightRequest{}) + if err != nil { + fmt.Printf("cctxClient.LastZetaHeight error: %s", err) + continue + } + if response.Height >= 30 { + break + } + fmt.Printf("Last ZetaHeight: %d\n", response.Height) + } + + // initialize client to send messages to ZetaChain + zetaTxServer, err := txserver.NewZetaTxServer( + conf.RPCs.ZetaCoreRPC, + []string{utils.FungibleAdminName}, + []string{FungibleAdminMnemonic}, + conf.ZetaChainID, + ) + if err != nil { + panic(err) + } + + // get the clients for tests + var zevmClient *ethclient.Client + for { + time.Sleep(5 * time.Second) + fmt.Printf("dialing zevm client: %s\n", conf.RPCs.Zevm) + zevmClient, err = ethclient.Dial(conf.RPCs.Zevm) + if err != nil { + continue + } + break + } + chainid, err = zevmClient.ChainID(context.Background()) + if err != nil { + panic(err) + } + zevmAuth, err := bind.NewKeyedTransactorWithChainID(deployerPrivkey, chainid) + if err != nil { + panic(err) + } + + // initialize smoke test runner + smokeTest := runner.NewSmokeTestRunner( + DeployerAddress, + DeployerPrivateKey, + FungibleAdminMnemonic, + goerliClient, + zevmClient, + cctxClient, + zetaTxServer, + fungibleClient, + authClient, + bankClient, + observerClient, + goerliAuth, + zevmAuth, + nil, + ) + + // setup TSS addresses + smokeTest.SetTSSAddresses() + + smokeTest.SetupEVM(stressTestArgs.contractsDeployed) + + fmt.Printf("Stress test arguments: %+v", stressTestArgs) + + // If stress test is running on local docker environment + if stressTestArgs.network == "" { + // deploy and set zevm contract + smokeTest.SetZEVMContracts() + + // deposit on ZetaChain + smokeTest.DepositEtherIntoZRC20() + smokeTest.SendZetaIn() + } else if stressTestArgs.network == "TESTNET" { + ethZRC20Addr, err := smokeTest.SystemContract.GasCoinZRC20ByChainId(&bind.CallOpts{}, big.NewInt(5)) + if err != nil { + panic(err) + } + smokeTest.ETHZRC20Addr = ethZRC20Addr + smokeTest.ETHZRC20, err = zrc20.NewZRC20(smokeTest.ETHZRC20Addr, smokeTest.ZevmClient) + if err != nil { + panic(err) + } + } else { + err := errors.New("invalid network argument: " + stressTestArgs.network) + panic(err) + } + + // Check zrc20 balance of Deployer address + ethZRC20Balance, err := smokeTest.ETHZRC20.BalanceOf(nil, DeployerAddress) + if err != nil { + panic(err) + } + fmt.Printf("eth zrc20 balance: %s Wei \n", ethZRC20Balance.String()) + + //Pre-approve ETH withdraw on ZEVM + fmt.Printf("approving ETH ZRC20...\n") + ethZRC20 := smokeTest.ETHZRC20 + tx, err := ethZRC20.Approve(smokeTest.ZevmAuth, smokeTest.ETHZRC20Addr, big.NewInt(1e18)) + if err != nil { + panic(err) + } + receipt := utils.MustWaitForTxReceipt(smokeTest.ZevmClient, tx) + fmt.Printf("eth zrc20 approve receipt: status %d\n", receipt.Status) + + // Get current nonce on zevm for DeployerAddress - Need to keep track of nonce at client level + blockNum, err := smokeTest.ZevmClient.BlockNumber(context.Background()) + if err != nil { + panic(err) + } + + // #nosec G701 smoketest - always in range + nonce, err := smokeTest.ZevmClient.NonceAt(context.Background(), DeployerAddress, big.NewInt(int64(blockNum))) + if err != nil { + panic(err) + } + + // #nosec G701 smoketest - always in range + zevmNonce = big.NewInt(int64(nonce)) + + // -------------- TEST BEGINS ------------------ + + fmt.Println("**** STRESS TEST BEGINS ****") + fmt.Println(" 1. Periodically Withdraw ETH from ZEVM to EVM - goerli") + fmt.Println(" 2. Display Network metrics to monitor performance [Num Pending outbound tx], [Num Trackers]") + + smokeTest.WG.Add(2) + go WithdrawCCtx(smokeTest) // Withdraw USDT from ZEVM to EVM - goerli + go EchoNetworkMetrics(smokeTest) // Display Network metrics periodically to monitor performance + + smokeTest.WG.Wait() +} + +// WithdrawCCtx withdraw USDT from ZEVM to EVM +func WithdrawCCtx(sm *runner.SmokeTestRunner) { + ticker := time.NewTicker(time.Millisecond * time.Duration(stressTestArgs.txnInterval)) + for { + select { + case <-ticker.C: + WithdrawETHZRC20(sm) + } + } +} + +func EchoNetworkMetrics(sm *runner.SmokeTestRunner) { + ticker := time.NewTicker(time.Second * StatInterval) + var queue = make([]uint64, 0) + var numTicks = 0 + var totalMinedTxns = uint64(0) + var previousMinedTxns = uint64(0) + + for { + select { + case <-ticker.C: + numTicks++ + // Get all pending outbound transactions + cctxResp, err := sm.CctxClient.CctxListPending(context.Background(), &crosschaintypes.QueryListCctxPendingRequest{ + ChainId: getChainID(), + }) + if err != nil { + continue + } + sends := cctxResp.CrossChainTx + sort.Slice(sends, func(i, j int) bool { + return sends[i].GetCurrentOutTxParam().OutboundTxTssNonce < sends[j].GetCurrentOutTxParam().OutboundTxTssNonce + }) + if len(sends) > 0 { + fmt.Printf("pending nonces %d to %d\n", sends[0].GetCurrentOutTxParam().OutboundTxTssNonce, sends[len(sends)-1].GetCurrentOutTxParam().OutboundTxTssNonce) + } else { + continue + } + // + // Get all trackers + trackerResp, err := sm.CctxClient.OutTxTrackerAll(context.Background(), &crosschaintypes.QueryAllOutTxTrackerRequest{}) + if err != nil { + continue + } + + currentMinedTxns := sends[0].GetCurrentOutTxParam().OutboundTxTssNonce + newMinedTxCnt := currentMinedTxns - previousMinedTxns + previousMinedTxns = currentMinedTxns + + // Add new mined txn count to queue and remove the oldest entry + queue = append(queue, newMinedTxCnt) + if numTicks > 60/StatInterval { + totalMinedTxns -= queue[0] + queue = queue[1:] + numTicks = 60/StatInterval + 1 //prevent overflow + } + + //Calculate rate -> tx/min + totalMinedTxns += queue[len(queue)-1] + rate := totalMinedTxns + + numPending := len(cctxResp.CrossChainTx) + numTrackers := len(trackerResp.OutTxTracker) + + fmt.Println("Network Stat => Num of Pending cctx: ", numPending, "Num active trackers: ", numTrackers, "Tx Rate: ", rate, " tx/min") + } + } +} + +func WithdrawETHZRC20(sm *runner.SmokeTestRunner) { + defer func() { + zevmNonce.Add(zevmNonce, big.NewInt(1)) + }() + + ethZRC20 := sm.ETHZRC20 + + sm.ZevmAuth.Nonce = zevmNonce + _, err := ethZRC20.Withdraw(sm.ZevmAuth, DeployerAddress.Bytes(), big.NewInt(100)) + if err != nil { + panic(err) + } +} + +// Get ETH based chain ID - Build flags are conflicting with current lib, need to do this manually +func getChainID() int64 { + switch stressTestArgs.network { + case "PRIVNET": + return 1337 + case "TESTNET": + return 5 + case "MAINNET": + return 1 + default: + return 1337 + } +} From c7c6d53c9ab82aaa1d6e4d01ab147caf9e51eedb Mon Sep 17 00:00:00 2001 From: kevinssgh Date: Fri, 22 Dec 2023 12:17:21 -0400 Subject: [PATCH 2/8] added new cmd to initialize config file. --- .../smoketest/cmd/smoketest/init.go | 40 +++++++++++++++++++ .../smoketest/cmd/smoketest/root.go | 1 + .../smoketest/cmd/smoketest/stress.go | 4 +- 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 contrib/localnet/orchestrator/smoketest/cmd/smoketest/init.go diff --git a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/init.go b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/init.go new file mode 100644 index 0000000000..feff605f68 --- /dev/null +++ b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/init.go @@ -0,0 +1,40 @@ +package main + +import ( + "fmt" + "github.com/spf13/cobra" + "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" +) + +const ( + InitCmdId = "init" +) + +var initConf = config.Config{} +var configFile = "" + +func NewInitCmd() *cobra.Command { + var InitCmd = &cobra.Command{ + Use: InitCmdId, + Short: "Run Local Stress Test", + Run: initConfig, + } + + InitCmd.Flags().StringVar(&initConf.RPCs.EVM, "ethURL", "http://eth:8545", "--ethURL http://eth:8545") + InitCmd.Flags().StringVar(&initConf.RPCs.ZetaCoreGRPC, "grpcURL", "zetacore0:9090", "--grpcURL zetacore0:9090") + InitCmd.Flags().StringVar(&initConf.RPCs.ZetaCoreRPC, "rpcURL", "http://zetacore0:26657", "--rpcURL http://zetacore0:26657") + InitCmd.Flags().StringVar(&initConf.RPCs.Zevm, "zevmURL", "http://zetacore0:8545", "--zevmURL http://zetacore0:8545") + InitCmd.Flags().StringVar(&initConf.RPCs.Bitcoin, "btcURL", "bitcoin:18443", "--grpcURL bitcoin:18443") + + InitCmd.Flags().StringVar(&initConf.ZetaChainID, "chainID", "athens_101-1", "--chainID athens_101-1") + InitCmd.Flags().StringVar(&configFile, "cfg", "smoketest.config", "--cfg ./smoketest.config") + + return InitCmd +} + +func initConfig(_ *cobra.Command, _ []string) { + err := config.WriteConfig(configFile, initConf) + if err != nil { + fmt.Printf("error writing config file: %s", err.Error()) + } +} diff --git a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/root.go b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/root.go index b8964b4675..83fbbeab14 100644 --- a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/root.go +++ b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/root.go @@ -9,6 +9,7 @@ func NewRootCmd() *cobra.Command { } cmd.AddCommand(NewLocalCmd()) cmd.AddCommand(NewStressTestCmd()) + cmd.AddCommand(NewInitCmd()) return cmd } diff --git a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go index beedb16b2d..e77062c6bd 100644 --- a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go +++ b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go @@ -65,7 +65,7 @@ func NewStressTestCmd() *cobra.Command { StressCmd.Flags().StringVar(&stressTestArgs.network, "network", "", "--network TESTNET") StressCmd.Flags().Int64Var(&stressTestArgs.txnInterval, "tx-interval", 500, "--tx-interval [TIME_INTERVAL_MILLISECONDS]") StressCmd.Flags().BoolVar(&stressTestArgs.contractsDeployed, "contracts-deployed", false, "--contracts-deployed=false") - StressCmd.Flags().StringVar(&stressTestArgs.network, flagConfigFile, "", "config file to use for the smoketest") + StressCmd.Flags().StringVar(&stressTestArgs.config, flagConfigFile, "", "config file to use for the smoketest") DeployerAddress = ethcommon.HexToAddress(stressTestArgs.deployerAddress) @@ -94,6 +94,7 @@ func StressTest(cmd *cobra.Command, _ []string) { panic(err) } + // Initialize clients ---------------------------------------------------------------- goerliClient, err := ethclient.Dial(stressTestArgs.ethURL) if err != nil { panic(err) @@ -128,6 +129,7 @@ func StressTest(cmd *cobra.Command, _ []string) { bankClient := banktypes.NewQueryClient(grpcConn) authClient := authtypes.NewQueryClient(grpcConn) observerClient := observertypes.NewQueryClient(grpcConn) + // ----------------------------------------------------------------------------------- // Wait for Genesis and keygen to be completed. ~ height 30 time.Sleep(20 * time.Second) From 02c03a4adb461256f1dce021d18fb4a9da09ac7c Mon Sep 17 00:00:00 2001 From: kevinssgh Date: Fri, 22 Dec 2023 15:42:54 -0400 Subject: [PATCH 3/8] cleaned up stress test cmd by using config file --- .../smoketest/cmd/smoketest/stress.go | 27 +++++-------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go index e77062c6bd..8fe75605e5 100644 --- a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go +++ b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go @@ -38,9 +38,6 @@ var ( ) type stressArguments struct { - ethURL string - grpcURL string - zevmURL string deployerAddress string deployerPrivateKey string network string @@ -58,8 +55,6 @@ func NewStressTestCmd() *cobra.Command { Run: StressTest, } - StressCmd.Flags().StringVar(&stressTestArgs.ethURL, "ethURL", "http://eth:8545", "--ethURL http://eth:8545") - StressCmd.Flags().StringVar(&stressTestArgs.grpcURL, "grpcURL", "zetacore0:9090", "--grpcURL zetacore0:9090") StressCmd.Flags().StringVar(&stressTestArgs.deployerAddress, "addr", "0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC", "--addr ") StressCmd.Flags().StringVar(&stressTestArgs.deployerPrivateKey, "privKey", "d87baf7bf6dc560a252596678c12e41f7d1682837f05b29d411bc3f78ae2c263", "--privKey ") StressCmd.Flags().StringVar(&stressTestArgs.network, "network", "", "--network TESTNET") @@ -95,7 +90,7 @@ func StressTest(cmd *cobra.Command, _ []string) { } // Initialize clients ---------------------------------------------------------------- - goerliClient, err := ethclient.Dial(stressTestArgs.ethURL) + goerliClient, err := ethclient.Dial(conf.RPCs.EVM) if err != nil { panic(err) } @@ -119,7 +114,7 @@ func StressTest(cmd *cobra.Command, _ []string) { panic(err) } - grpcConn, err := grpc.Dial(stressTestArgs.grpcURL, grpc.WithInsecure()) + grpcConn, err := grpc.Dial(conf.RPCs.ZetaCoreGRPC, grpc.WithInsecure()) if err != nil { panic(err) } @@ -287,6 +282,7 @@ func EchoNetworkMetrics(sm *runner.SmokeTestRunner) { var numTicks = 0 var totalMinedTxns = uint64(0) var previousMinedTxns = uint64(0) + chainID, _ := getChainID(sm.GoerliClient) for { select { @@ -294,7 +290,7 @@ func EchoNetworkMetrics(sm *runner.SmokeTestRunner) { numTicks++ // Get all pending outbound transactions cctxResp, err := sm.CctxClient.CctxListPending(context.Background(), &crosschaintypes.QueryListCctxPendingRequest{ - ChainId: getChainID(), + ChainId: chainID.Int64(), }) if err != nil { continue @@ -353,16 +349,7 @@ func WithdrawETHZRC20(sm *runner.SmokeTestRunner) { } } -// Get ETH based chain ID - Build flags are conflicting with current lib, need to do this manually -func getChainID() int64 { - switch stressTestArgs.network { - case "PRIVNET": - return 1337 - case "TESTNET": - return 5 - case "MAINNET": - return 1 - default: - return 1337 - } +// Get ETH based chain ID +func getChainID(client *ethclient.Client) (*big.Int, error) { + return client.ChainID(context.Background()) } From 6d8c35eb5cc49967a66870f7da7000c60d0738f5 Mon Sep 17 00:00:00 2001 From: kevinssgh Date: Fri, 22 Dec 2023 15:46:28 -0400 Subject: [PATCH 4/8] add changelog --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index a1706d308e..d742875b34 100644 --- a/changelog.md +++ b/changelog.md @@ -30,6 +30,7 @@ * add check to verify new tss has been produced when triggering tss funds migration * fix Athens-3 log print issue - avoid posting uncessary outtx confirmation * fix docker build issues with version: golang:1.20-alpine3.18 +* fix stress test - use new refactored config file and smoketest runner ### Refactoring * [1211](https://github.com/zeta-chain/node/issues/1211) - use `grpc` and `msg` for query and message files From eb80b694ff5fb5e239b9bca1c89e1ab9f257edc7 Mon Sep 17 00:00:00 2001 From: kevinssgh Date: Fri, 22 Dec 2023 15:54:00 -0400 Subject: [PATCH 5/8] ran make generate --- .../orchestrator/smoketest/cmd/smoketest/init.go | 7 ++----- .../orchestrator/smoketest/cmd/smoketest/stress.go | 9 +++++---- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/init.go b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/init.go index feff605f68..171fcfcc18 100644 --- a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/init.go +++ b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/init.go @@ -2,20 +2,17 @@ package main import ( "fmt" + "github.com/spf13/cobra" "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" ) -const ( - InitCmdId = "init" -) - var initConf = config.Config{} var configFile = "" func NewInitCmd() *cobra.Command { var InitCmd = &cobra.Command{ - Use: InitCmdId, + Use: "init", Short: "Run Local Stress Test", Run: initConfig, } diff --git a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go index 8fe75605e5..821415954f 100644 --- a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go +++ b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go @@ -4,15 +4,16 @@ import ( "context" "errors" "fmt" + "math/big" + "os" + "sort" + "time" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/zeta-chain/zetacore/app" "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/txserver" "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" - "math/big" - "os" - "sort" - "time" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" From b9124b554b5b2101c89dcb3cc22dee39f447f01b Mon Sep 17 00:00:00 2001 From: kevinssgh Date: Fri, 22 Dec 2023 16:01:41 -0400 Subject: [PATCH 6/8] fix gosec error --- .../localnet/orchestrator/smoketest/cmd/smoketest/stress.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go index 821415954f..2bb4e043a7 100644 --- a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go +++ b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go @@ -283,7 +283,11 @@ func EchoNetworkMetrics(sm *runner.SmokeTestRunner) { var numTicks = 0 var totalMinedTxns = uint64(0) var previousMinedTxns = uint64(0) - chainID, _ := getChainID(sm.GoerliClient) + chainID, err := getChainID(sm.GoerliClient) + + if err != nil { + panic(err) + } for { select { From 5b05cc63b4f463eccf5bcd40d14a831dc82a19e7 Mon Sep 17 00:00:00 2001 From: kevinssgh Date: Wed, 17 Jan 2024 13:17:34 -0500 Subject: [PATCH 7/8] update refactor, can remove the cmd from orchestrator later. --- cmd/zetae2e/init.go | 37 + cmd/zetae2e/local/local.go | 6 +- cmd/zetae2e/local/utils.go | 6 +- cmd/zetae2e/root.go | 2 + cmd/zetae2e/stress.go | 693 ++++++++++-------- .../smoketest/cmd/smoketest/local/local.go | 2 +- .../smoketest/cmd/smoketest/local/utils.go | 4 +- .../smoketest/cmd/smoketest/stress.go | 47 +- 8 files changed, 454 insertions(+), 343 deletions(-) create mode 100644 cmd/zetae2e/init.go diff --git a/cmd/zetae2e/init.go b/cmd/zetae2e/init.go new file mode 100644 index 0000000000..171fcfcc18 --- /dev/null +++ b/cmd/zetae2e/init.go @@ -0,0 +1,37 @@ +package main + +import ( + "fmt" + + "github.com/spf13/cobra" + "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" +) + +var initConf = config.Config{} +var configFile = "" + +func NewInitCmd() *cobra.Command { + var InitCmd = &cobra.Command{ + Use: "init", + Short: "Run Local Stress Test", + Run: initConfig, + } + + InitCmd.Flags().StringVar(&initConf.RPCs.EVM, "ethURL", "http://eth:8545", "--ethURL http://eth:8545") + InitCmd.Flags().StringVar(&initConf.RPCs.ZetaCoreGRPC, "grpcURL", "zetacore0:9090", "--grpcURL zetacore0:9090") + InitCmd.Flags().StringVar(&initConf.RPCs.ZetaCoreRPC, "rpcURL", "http://zetacore0:26657", "--rpcURL http://zetacore0:26657") + InitCmd.Flags().StringVar(&initConf.RPCs.Zevm, "zevmURL", "http://zetacore0:8545", "--zevmURL http://zetacore0:8545") + InitCmd.Flags().StringVar(&initConf.RPCs.Bitcoin, "btcURL", "bitcoin:18443", "--grpcURL bitcoin:18443") + + InitCmd.Flags().StringVar(&initConf.ZetaChainID, "chainID", "athens_101-1", "--chainID athens_101-1") + InitCmd.Flags().StringVar(&configFile, "cfg", "smoketest.config", "--cfg ./smoketest.config") + + return InitCmd +} + +func initConfig(_ *cobra.Command, _ []string) { + err := config.WriteConfig(configFile, initConf) + if err != nil { + fmt.Printf("error writing config file: %s", err.Error()) + } +} diff --git a/cmd/zetae2e/local/local.go b/cmd/zetae2e/local/local.go index f1a723f26e..7597811885 100644 --- a/cmd/zetae2e/local/local.go +++ b/cmd/zetae2e/local/local.go @@ -18,7 +18,7 @@ import ( const ( flagContractsDeployed = "deployed" flagWaitForHeight = "wait-for" - flagConfigFile = "config" + FlagConfigFile = "config" flagVerbose = "verbose" flagTestAdmin = "test-admin" flagTestCustom = "test-custom" @@ -51,7 +51,7 @@ func NewLocalCmd() *cobra.Command { "block height for tests to begin, ex. --wait-for 100", ) cmd.Flags().String( - flagConfigFile, + FlagConfigFile, "", "config file to use for the tests", ) @@ -145,7 +145,7 @@ func localE2ETest(cmd *cobra.Command, _ []string) { }() // initialize tests config - conf, err := getConfig(cmd) + conf, err := GetConfig(cmd) if err != nil { panic(err) } diff --git a/cmd/zetae2e/local/utils.go b/cmd/zetae2e/local/utils.go index 8e1ab210c1..e190b45df1 100644 --- a/cmd/zetae2e/local/utils.go +++ b/cmd/zetae2e/local/utils.go @@ -16,9 +16,9 @@ import ( crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" ) -// getConfig returns config from file from the command line flag -func getConfig(cmd *cobra.Command) (config.Config, error) { - configFile, err := cmd.Flags().GetString(flagConfigFile) +// GetConfig returns config from file from the command line flag +func GetConfig(cmd *cobra.Command) (config.Config, error) { + configFile, err := cmd.Flags().GetString(FlagConfigFile) if err != nil { return config.Config{}, err } diff --git a/cmd/zetae2e/root.go b/cmd/zetae2e/root.go index 8f514a6584..fb93caa131 100644 --- a/cmd/zetae2e/root.go +++ b/cmd/zetae2e/root.go @@ -13,6 +13,8 @@ func NewRootCmd() *cobra.Command { cmd.AddCommand( NewRunCmd(), local.NewLocalCmd(), + NewStressTestCmd(), + NewInitCmd(), ) return cmd diff --git a/cmd/zetae2e/stress.go b/cmd/zetae2e/stress.go index 670922056f..fbde30a3ef 100644 --- a/cmd/zetae2e/stress.go +++ b/cmd/zetae2e/stress.go @@ -1,321 +1,376 @@ package main -//import ( -// "context" -// "errors" -// "fmt" -// "math/big" -// "os" -// "sort" -// "time" -// -// authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" -// banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" -// "github.com/ethereum/go-ethereum/accounts/abi/bind" -// ethcommon "github.com/ethereum/go-ethereum/common" -// "github.com/ethereum/go-ethereum/crypto" -// "github.com/ethereum/go-ethereum/ethclient" -// "github.com/spf13/cobra" -// "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zrc20.sol" -// crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" -// fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" -// observertypes "github.com/zeta-chain/zetacore/x/observer/types" -// "google.golang.org/grpc" -//) -// -//const ( -// StatInterval = 5 -// StressTestTimeout = 100 * time.Minute -//) -// -//var ( -// zevmNonce = big.NewInt(1) -//) -// -//var StressCmd = &cobra.Command{ -// Use: "stress", -// Short: "Run Local Stress Test", -// Run: StressTest, -//} -// -//type stressArguments struct { -// ethURL string -// grpcURL string -// zevmURL string -// deployerAddress string -// deployerPrivateKey string -// network string -// txnInterval int64 -//} -// -//var stressTestArgs = stressArguments{} -// -//func init() { -// RootCmd.AddCommand(StressCmd) -// StressCmd.Flags().StringVar(&stressTestArgs.ethURL, "ethURL", "http://eth:8545", "--ethURL http://eth:8545") -// StressCmd.Flags().StringVar(&stressTestArgs.grpcURL, "grpcURL", "zetacore0:9090", "--grpcURL zetacore0:9090") -// StressCmd.Flags().StringVar(&stressTestArgs.zevmURL, "zevmURL", zevmRPC, "--zevmURL http://zetacore0:8545") -// StressCmd.Flags().StringVar(&stressTestArgs.deployerAddress, "addr", "0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC", "--addr ") -// StressCmd.Flags().StringVar(&stressTestArgs.deployerPrivateKey, "privKey", "d87baf7bf6dc560a252596678c12e41f7d1682837f05b29d411bc3f78ae2c263", "--privKey ") -// StressCmd.Flags().StringVar(&stressTestArgs.network, "network", "PRIVNET", "--network PRIVNET") -// StressCmd.Flags().Int64Var(&stressTestArgs.txnInterval, "tx-interval", 500, "--tx-interval [TIME_INTERVAL_MILLISECONDS]") -// -// DeployerAddress = ethcommon.HexToAddress(stressTestArgs.deployerAddress) -//} -// -//func StressTest(_ *cobra.Command, _ []string) { -// testStartTime := time.Now() -// defer func() { -// fmt.Println("Smoke test took", time.Since(testStartTime)) -// }() -// go func() { -// time.Sleep(StressTestTimeout) -// fmt.Println("Smoke test timed out after", StressTestTimeout) -// os.Exit(1) -// }() -// -// goerliClient, err := ethclient.Dial(stressTestArgs.ethURL) -// if err != nil { -// panic(err) -// } -// -// bal, err := goerliClient.BalanceAt(context.TODO(), DeployerAddress, nil) -// if err != nil { -// panic(err) -// } -// fmt.Printf("Deployer address: %s, balance: %d Wei\n", DeployerAddress.Hex(), bal) -// -// chainid, err := goerliClient.ChainID(context.Background()) -// if err != nil { -// panic(err) -// } -// deployerPrivkey, err := crypto.HexToECDSA(stressTestArgs.deployerPrivateKey) -// if err != nil { -// panic(err) -// } -// goerliAuth, err := bind.NewKeyedTransactorWithChainID(deployerPrivkey, chainid) -// if err != nil { -// panic(err) -// } -// -// grpcConn, err := grpc.Dial(stressTestArgs.grpcURL, grpc.WithInsecure()) -// if err != nil { -// panic(err) -// } -// -// cctxClient := crosschaintypes.NewQueryClient(grpcConn) -// fungibleClient := fungibletypes.NewQueryClient(grpcConn) -// bankClient := banktypes.NewQueryClient(grpcConn) -// authClient := authtypes.NewQueryClient(grpcConn) -// observerClient := observertypes.NewQueryClient(grpcConn) -// -// // Wait for Genesis and keygen to be completed. ~ height 30 -// time.Sleep(20 * time.Second) -// for { -// time.Sleep(5 * time.Second) -// response, err := cctxClient.LastZetaHeight(context.Background(), &crosschaintypes.QueryLastZetaHeightRequest{}) -// if err != nil { -// fmt.Printf("cctxClient.LastZetaHeight error: %s", err) -// continue -// } -// if response.Height >= 30 { -// break -// } -// fmt.Printf("Last ZetaHeight: %d\n", response.Height) -// } -// -// // get the clients for tests -// var zevmClient *ethclient.Client -// for { -// time.Sleep(5 * time.Second) -// fmt.Printf("dialing zevm client: %s\n", stressTestArgs.zevmURL) -// zevmClient, err = ethclient.Dial(stressTestArgs.zevmURL) -// if err != nil { -// continue -// } -// break -// } -// chainid, err = zevmClient.ChainID(context.Background()) -// if err != nil { -// panic(err) -// } -// zevmAuth, err := bind.NewKeyedTransactorWithChainID(deployerPrivkey, chainid) -// if err != nil { -// panic(err) -// } -// -// smokeTest := NewSmokeTest( -// goerliClient, -// zevmClient, -// cctxClient, -// ZetaTxServer{}, // not used in stress test -// fungibleClient, -// authClient, -// bankClient, -// observerClient, -// goerliAuth, -// zevmAuth, -// nil, -// ) -// -// // If stress test is running on local docker environment -// if stressTestArgs.network == "PRIVNET" { -// smokeTest.TestSetupZetaTokenAndConnectorAndZEVMContracts() -// smokeTest.TestDepositEtherIntoZRC20() -// smokeTest.TestSendZetaIn() -// } else if stressTestArgs.network == "TESTNET" { -// ethZRC20Addr, err := smokeTest.SystemContract.GasCoinZRC20ByChainId(&bind.CallOpts{}, big.NewInt(5)) -// if err != nil { -// panic(err) -// } -// smokeTest.ETHZRC20Addr = ethZRC20Addr -// smokeTest.ETHZRC20, err = zrc20.NewZRC20(smokeTest.ETHZRC20Addr, smokeTest.zevmClient) -// if err != nil { -// panic(err) -// } -// } else { -// err := errors.New("invalid network argument: " + stressTestArgs.network) -// panic(err) -// } -// -// // Check zrc20 balance of Deployer address -// ethZRC20Balance, err := smokeTest.ETHZRC20.BalanceOf(nil, DeployerAddress) -// if err != nil { -// panic(err) -// } -// fmt.Printf("eth zrc20 balance: %s Wei \n", ethZRC20Balance.String()) -// -// //Pre-approve ETH withdraw on ZEVM -// fmt.Printf("approving ETH ZRC20...\n") -// ethZRC20 := smokeTest.ETHZRC20 -// tx, err := ethZRC20.Approve(smokeTest.zevmAuth, smokeTest.ETHZRC20Addr, big.NewInt(1e18)) -// if err != nil { -// panic(err) -// } -// receipt := MustWaitForTxReceipt(smokeTest.zevmClient, tx) -// fmt.Printf("eth zrc20 approve receipt: status %d\n", receipt.Status) -// -// // Get current nonce on zevm for DeployerAddress - Need to keep track of nonce at client level -// blockNum, err := smokeTest.zevmClient.BlockNumber(context.Background()) -// if err != nil { -// panic(err) -// } -// -// // #nosec G701 smoketest - always in range -// nonce, err := smokeTest.zevmClient.NonceAt(context.Background(), DeployerAddress, big.NewInt(int64(blockNum))) -// if err != nil { -// panic(err) -// } -// -// // #nosec G701 smoketest - always in range -// zevmNonce = big.NewInt(int64(nonce)) -// -// // -------------- TEST BEGINS ------------------ -// -// fmt.Println("**** STRESS TEST BEGINS ****") -// fmt.Println(" 1. Periodically Withdraw ETH from ZEVM to EVM - goerli") -// fmt.Println(" 2. Display Network metrics to monitor performance [Num Pending outbound tx], [Num Trackers]") -// -// smokeTest.wg.Add(2) -// go smokeTest.WithdrawCCtx() // Withdraw USDT from ZEVM to EVM - goerli -// go smokeTest.EchoNetworkMetrics() // Display Network metrics periodically to monitor performance -// -// smokeTest.wg.Wait() -//} -// -//// WithdrawCCtx withdraw USDT from ZEVM to EVM -//func (sm *SmokeTest) WithdrawCCtx() { -// ticker := time.NewTicker(time.Millisecond * time.Duration(stressTestArgs.txnInterval)) -// for { -// select { -// case <-ticker.C: -// sm.WithdrawETHZRC20() -// } -// } -//} -// -//func (sm *SmokeTest) EchoNetworkMetrics() { -// ticker := time.NewTicker(time.Second * StatInterval) -// var queue = make([]uint64, 0) -// var numTicks = 0 -// var totalMinedTxns = uint64(0) -// var previousMinedTxns = uint64(0) -// -// for { -// select { -// case <-ticker.C: -// numTicks++ -// // Get all pending outbound transactions -// cctxResp, err := sm.cctxClient.CctxListPending(context.Background(), &crosschaintypes.QueryListCctxPendingRequest{ -// ChainId: getChainID(), -// }) -// if err != nil { -// continue -// } -// sends := cctxResp.CrossChainTx -// sort.Slice(sends, func(i, j int) bool { -// return sends[i].GetCurrentOutTxParam().OutboundTxTssNonce < sends[j].GetCurrentOutTxParam().OutboundTxTssNonce -// }) -// if len(sends) > 0 { -// fmt.Printf("pending nonces %d to %d\n", sends[0].GetCurrentOutTxParam().OutboundTxTssNonce, sends[len(sends)-1].GetCurrentOutTxParam().OutboundTxTssNonce) -// } else { -// continue -// } -// // -// // Get all trackers -// trackerResp, err := sm.cctxClient.OutTxTrackerAll(context.Background(), &crosschaintypes.QueryAllOutTxTrackerRequest{}) -// if err != nil { -// continue -// } -// -// currentMinedTxns := sends[0].GetCurrentOutTxParam().OutboundTxTssNonce -// newMinedTxCnt := currentMinedTxns - previousMinedTxns -// previousMinedTxns = currentMinedTxns -// -// // Add new mined txn count to queue and remove the oldest entry -// queue = append(queue, newMinedTxCnt) -// if numTicks > 60/StatInterval { -// totalMinedTxns -= queue[0] -// queue = queue[1:] -// numTicks = 60/StatInterval + 1 //prevent overflow -// } -// -// //Calculate rate -> tx/min -// totalMinedTxns += queue[len(queue)-1] -// rate := totalMinedTxns -// -// numPending := len(cctxResp.CrossChainTx) -// numTrackers := len(trackerResp.OutTxTracker) -// -// fmt.Println("Network Stat => Num of Pending cctx: ", numPending, "Num active trackers: ", numTrackers, "Tx Rate: ", rate, " tx/min") -// } -// } -//} -// -//func (sm *SmokeTest) WithdrawETHZRC20() { -// defer func() { -// zevmNonce.Add(zevmNonce, big.NewInt(1)) -// }() -// -// ethZRC20 := sm.ETHZRC20 -// -// sm.zevmAuth.Nonce = zevmNonce -// _, err := ethZRC20.Withdraw(sm.zevmAuth, DeployerAddress.Bytes(), big.NewInt(100)) -// if err != nil { -// panic(err) -// } -//} -// -//// Get ETH based chain ID - Build flags are conflicting with current lib, need to do this manually -//func getChainID() int64 { -// switch stressTestArgs.network { -// case "PRIVNET": -// return 1337 -// case "TESTNET": -// return 5 -// case "MAINNET": -// return 1 -// default: -// return 1337 -// } -//} +import ( + "context" + "errors" + "fmt" + "github.com/fatih/color" + "github.com/zeta-chain/zetacore/cmd/zetae2e/local" + "math/big" + "os" + "sort" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/zeta-chain/zetacore/app" + "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" + "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/txserver" + "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" + + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/spf13/cobra" + "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zrc20.sol" + crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" + fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" + "google.golang.org/grpc" +) + +const ( + StatInterval = 5 + StressTestTimeout = 100 * time.Minute +) + +var ( + zevmNonce = big.NewInt(1) +) + +type stressArguments struct { + deployerAddress string + deployerPrivateKey string + network string + txnInterval int64 + contractsDeployed bool + config string +} + +var stressTestArgs = stressArguments{} + +func NewStressTestCmd() *cobra.Command { + var StressCmd = &cobra.Command{ + Use: "stress", + Short: "Run Local Stress Test", + Run: StressTest, + } + + StressCmd.Flags().StringVar(&stressTestArgs.deployerAddress, "addr", "0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC", "--addr ") + StressCmd.Flags().StringVar(&stressTestArgs.deployerPrivateKey, "privKey", "d87baf7bf6dc560a252596678c12e41f7d1682837f05b29d411bc3f78ae2c263", "--privKey ") + StressCmd.Flags().StringVar(&stressTestArgs.network, "network", "", "--network TESTNET") + StressCmd.Flags().Int64Var(&stressTestArgs.txnInterval, "tx-interval", 500, "--tx-interval [TIME_INTERVAL_MILLISECONDS]") + StressCmd.Flags().BoolVar(&stressTestArgs.contractsDeployed, "contracts-deployed", false, "--contracts-deployed=false") + StressCmd.Flags().StringVar(&stressTestArgs.config, local.FlagConfigFile, "", "config file to use for the smoketest") + StressCmd.Flags().Bool(flagVerbose, false, "set to true to enable verbose logging") + + local.DeployerAddress = ethcommon.HexToAddress(stressTestArgs.deployerAddress) + + return StressCmd +} + +func StressTest(cmd *cobra.Command, _ []string) { + testStartTime := time.Now() + defer func() { + fmt.Println("Smoke test took", time.Since(testStartTime)) + }() + go func() { + time.Sleep(StressTestTimeout) + fmt.Println("Smoke test timed out after", StressTestTimeout) + os.Exit(1) + }() + + // set account prefix to zeta + cosmosConf := sdk.GetConfig() + cosmosConf.SetBech32PrefixForAccount(app.Bech32PrefixAccAddr, app.Bech32PrefixAccPub) + cosmosConf.Seal() + + // initialize smoke tests config + conf, err := local.GetConfig(cmd) + if err != nil { + panic(err) + } + + // Initialize clients ---------------------------------------------------------------- + goerliClient, err := ethclient.Dial(conf.RPCs.EVM) + if err != nil { + panic(err) + } + + bal, err := goerliClient.BalanceAt(context.TODO(), local.DeployerAddress, nil) + if err != nil { + panic(err) + } + fmt.Printf("Deployer address: %s, balance: %d Wei\n", local.DeployerAddress.Hex(), bal) + + chainid, err := goerliClient.ChainID(context.Background()) + if err != nil { + panic(err) + } + deployerPrivkey, err := crypto.HexToECDSA(stressTestArgs.deployerPrivateKey) + if err != nil { + panic(err) + } + goerliAuth, err := bind.NewKeyedTransactorWithChainID(deployerPrivkey, chainid) + if err != nil { + panic(err) + } + + grpcConn, err := grpc.Dial(conf.RPCs.ZetaCoreGRPC, grpc.WithInsecure()) + if err != nil { + panic(err) + } + + cctxClient := crosschaintypes.NewQueryClient(grpcConn) + fungibleClient := fungibletypes.NewQueryClient(grpcConn) + bankClient := banktypes.NewQueryClient(grpcConn) + authClient := authtypes.NewQueryClient(grpcConn) + observerClient := observertypes.NewQueryClient(grpcConn) + // ----------------------------------------------------------------------------------- + + // Wait for Genesis and keygen to be completed. ~ height 30 + time.Sleep(20 * time.Second) + for { + time.Sleep(5 * time.Second) + response, err := cctxClient.LastZetaHeight(context.Background(), &crosschaintypes.QueryLastZetaHeightRequest{}) + if err != nil { + fmt.Printf("cctxClient.LastZetaHeight error: %s", err) + continue + } + if response.Height >= 30 { + break + } + fmt.Printf("Last ZetaHeight: %d\n", response.Height) + } + + // initialize client to send messages to ZetaChain + zetaTxServer, err := txserver.NewZetaTxServer( + conf.RPCs.ZetaCoreRPC, + []string{utils.FungibleAdminName}, + []string{local.FungibleAdminMnemonic}, + conf.ZetaChainID, + ) + if err != nil { + panic(err) + } + + // get the clients for tests + var zevmClient *ethclient.Client + for { + time.Sleep(5 * time.Second) + fmt.Printf("dialing zevm client: %s\n", conf.RPCs.Zevm) + zevmClient, err = ethclient.Dial(conf.RPCs.Zevm) + if err != nil { + continue + } + break + } + chainid, err = zevmClient.ChainID(context.Background()) + if err != nil { + panic(err) + } + zevmAuth, err := bind.NewKeyedTransactorWithChainID(deployerPrivkey, chainid) + if err != nil { + panic(err) + } + + // initialize context + ctx, cancel := context.WithCancel(context.Background()) + + verbose, err := cmd.Flags().GetBool(flagVerbose) + if err != nil { + panic(err) + } + logger := runner.NewLogger(verbose, color.FgWhite, "setup") + + // initialize smoke test runner + smokeTest := runner.NewSmokeTestRunner( + ctx, + "deployer", + cancel, + local.DeployerAddress, + local.DeployerPrivateKey, + local.FungibleAdminMnemonic, + goerliClient, + zevmClient, + cctxClient, + zetaTxServer, + fungibleClient, + authClient, + bankClient, + observerClient, + goerliAuth, + zevmAuth, + nil, + logger, + ) + + // setup TSS addresses + smokeTest.SetTSSAddresses() + + smokeTest.SetupEVM(stressTestArgs.contractsDeployed) + + fmt.Printf("Stress test arguments: %+v", stressTestArgs) + + // If stress test is running on local docker environment + if stressTestArgs.network == "" { + // deploy and set zevm contract + smokeTest.SetZEVMContracts() + + // deposit on ZetaChain + smokeTest.DepositEther(false) + smokeTest.DepositZeta() + } else if stressTestArgs.network == "TESTNET" { + ethZRC20Addr, err := smokeTest.SystemContract.GasCoinZRC20ByChainId(&bind.CallOpts{}, big.NewInt(5)) + if err != nil { + panic(err) + } + smokeTest.ETHZRC20Addr = ethZRC20Addr + smokeTest.ETHZRC20, err = zrc20.NewZRC20(smokeTest.ETHZRC20Addr, smokeTest.ZevmClient) + if err != nil { + panic(err) + } + } else { + err := errors.New("invalid network argument: " + stressTestArgs.network) + panic(err) + } + + // Check zrc20 balance of Deployer address + ethZRC20Balance, err := smokeTest.ETHZRC20.BalanceOf(nil, local.DeployerAddress) + if err != nil { + panic(err) + } + fmt.Printf("eth zrc20 balance: %s Wei \n", ethZRC20Balance.String()) + + //Pre-approve ETH withdraw on ZEVM + fmt.Printf("approving ETH ZRC20...\n") + ethZRC20 := smokeTest.ETHZRC20 + tx, err := ethZRC20.Approve(smokeTest.ZevmAuth, smokeTest.ETHZRC20Addr, big.NewInt(1e18)) + if err != nil { + panic(err) + } + receipt := utils.MustWaitForTxReceipt(ctx, smokeTest.ZevmClient, tx, logger, smokeTest.ReceiptTimeout) + fmt.Printf("eth zrc20 approve receipt: status %d\n", receipt.Status) + + // Get current nonce on zevm for DeployerAddress - Need to keep track of nonce at client level + blockNum, err := smokeTest.ZevmClient.BlockNumber(context.Background()) + if err != nil { + panic(err) + } + + // #nosec G701 smoketest - always in range + nonce, err := smokeTest.ZevmClient.NonceAt(context.Background(), local.DeployerAddress, big.NewInt(int64(blockNum))) + if err != nil { + panic(err) + } + + // #nosec G701 smoketest - always in range + zevmNonce = big.NewInt(int64(nonce)) + + // -------------- TEST BEGINS ------------------ + + fmt.Println("**** STRESS TEST BEGINS ****") + fmt.Println(" 1. Periodically Withdraw ETH from ZEVM to EVM - goerli") + fmt.Println(" 2. Display Network metrics to monitor performance [Num Pending outbound tx], [Num Trackers]") + + smokeTest.WG.Add(2) + go WithdrawCCtx(smokeTest) // Withdraw USDT from ZEVM to EVM - goerli + go EchoNetworkMetrics(smokeTest) // Display Network metrics periodically to monitor performance + + smokeTest.WG.Wait() +} + +// WithdrawCCtx withdraw USDT from ZEVM to EVM +func WithdrawCCtx(sm *runner.SmokeTestRunner) { + ticker := time.NewTicker(time.Millisecond * time.Duration(stressTestArgs.txnInterval)) + for { + select { + case <-ticker.C: + WithdrawETHZRC20(sm) + } + } +} + +func EchoNetworkMetrics(sm *runner.SmokeTestRunner) { + ticker := time.NewTicker(time.Second * StatInterval) + var queue = make([]uint64, 0) + var numTicks = 0 + var totalMinedTxns = uint64(0) + var previousMinedTxns = uint64(0) + chainID, err := getChainID(sm.GoerliClient) + + if err != nil { + panic(err) + } + + for { + select { + case <-ticker.C: + numTicks++ + // Get all pending outbound transactions + cctxResp, err := sm.CctxClient.CctxListPending(context.Background(), &crosschaintypes.QueryListCctxPendingRequest{ + ChainId: chainID.Int64(), + }) + if err != nil { + continue + } + sends := cctxResp.CrossChainTx + sort.Slice(sends, func(i, j int) bool { + return sends[i].GetCurrentOutTxParam().OutboundTxTssNonce < sends[j].GetCurrentOutTxParam().OutboundTxTssNonce + }) + if len(sends) > 0 { + fmt.Printf("pending nonces %d to %d\n", sends[0].GetCurrentOutTxParam().OutboundTxTssNonce, sends[len(sends)-1].GetCurrentOutTxParam().OutboundTxTssNonce) + } else { + continue + } + // + // Get all trackers + trackerResp, err := sm.CctxClient.OutTxTrackerAll(context.Background(), &crosschaintypes.QueryAllOutTxTrackerRequest{}) + if err != nil { + continue + } + + currentMinedTxns := sends[0].GetCurrentOutTxParam().OutboundTxTssNonce + newMinedTxCnt := currentMinedTxns - previousMinedTxns + previousMinedTxns = currentMinedTxns + + // Add new mined txn count to queue and remove the oldest entry + queue = append(queue, newMinedTxCnt) + if numTicks > 60/StatInterval { + totalMinedTxns -= queue[0] + queue = queue[1:] + numTicks = 60/StatInterval + 1 //prevent overflow + } + + //Calculate rate -> tx/min + totalMinedTxns += queue[len(queue)-1] + rate := totalMinedTxns + + numPending := len(cctxResp.CrossChainTx) + numTrackers := len(trackerResp.OutTxTracker) + + fmt.Println("Network Stat => Num of Pending cctx: ", numPending, "Num active trackers: ", numTrackers, "Tx Rate: ", rate, " tx/min") + } + } +} + +func WithdrawETHZRC20(sm *runner.SmokeTestRunner) { + defer func() { + zevmNonce.Add(zevmNonce, big.NewInt(1)) + }() + + ethZRC20 := sm.ETHZRC20 + + sm.ZevmAuth.Nonce = zevmNonce + _, err := ethZRC20.Withdraw(sm.ZevmAuth, local.DeployerAddress.Bytes(), big.NewInt(100)) + if err != nil { + panic(err) + } +} + +// Get ETH based chain ID +func getChainID(client *ethclient.Client) (*big.Int, error) { + return client.ChainID(context.Background()) +} diff --git a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/local/local.go b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/local/local.go index f4aabbcf8b..170e8a644c 100644 --- a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/local/local.go +++ b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/local/local.go @@ -112,7 +112,7 @@ func localSmokeTest(cmd *cobra.Command, _ []string) { }() // initialize smoke tests config - conf, err := getConfig(cmd) + conf, err := GetConfig(cmd) if err != nil { panic(err) } diff --git a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/local/utils.go b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/local/utils.go index 4ca541a406..3cc27582dc 100644 --- a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/local/utils.go +++ b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/local/utils.go @@ -24,8 +24,8 @@ import ( "google.golang.org/grpc" ) -// getConfig returns config from file from the command line flag -func getConfig(cmd *cobra.Command) (config.Config, error) { +// GetConfig returns config from file from the command line flag +func GetConfig(cmd *cobra.Command) (config.Config, error) { configFile, err := cmd.Flags().GetString(flagConfigFile) if err != nil { return config.Config{}, err diff --git a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go index 2bb4e043a7..9c18124f05 100644 --- a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go +++ b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go @@ -4,6 +4,8 @@ import ( "context" "errors" "fmt" + "github.com/fatih/color" + "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/cmd/smoketest/local" "math/big" "os" "sort" @@ -32,6 +34,7 @@ import ( const ( StatInterval = 5 StressTestTimeout = 100 * time.Minute + flagVerbose = "verbose" ) var ( @@ -61,9 +64,10 @@ func NewStressTestCmd() *cobra.Command { StressCmd.Flags().StringVar(&stressTestArgs.network, "network", "", "--network TESTNET") StressCmd.Flags().Int64Var(&stressTestArgs.txnInterval, "tx-interval", 500, "--tx-interval [TIME_INTERVAL_MILLISECONDS]") StressCmd.Flags().BoolVar(&stressTestArgs.contractsDeployed, "contracts-deployed", false, "--contracts-deployed=false") - StressCmd.Flags().StringVar(&stressTestArgs.config, flagConfigFile, "", "config file to use for the smoketest") + StressCmd.Flags().StringVar(&stressTestArgs.config, "cfg", "", "config file to use for the smoketest") + StressCmd.Flags().Bool(flagVerbose, false, "set to true to enable verbose logging") - DeployerAddress = ethcommon.HexToAddress(stressTestArgs.deployerAddress) + local.DeployerAddress = ethcommon.HexToAddress(stressTestArgs.deployerAddress) return StressCmd } @@ -85,7 +89,7 @@ func StressTest(cmd *cobra.Command, _ []string) { cosmosConf.Seal() // initialize smoke tests config - conf, err := getConfig(cmd) + conf, err := local.GetConfig(cmd) if err != nil { panic(err) } @@ -96,11 +100,11 @@ func StressTest(cmd *cobra.Command, _ []string) { panic(err) } - bal, err := goerliClient.BalanceAt(context.TODO(), DeployerAddress, nil) + bal, err := goerliClient.BalanceAt(context.TODO(), local.DeployerAddress, nil) if err != nil { panic(err) } - fmt.Printf("Deployer address: %s, balance: %d Wei\n", DeployerAddress.Hex(), bal) + fmt.Printf("Deployer address: %s, balance: %d Wei\n", local.DeployerAddress.Hex(), bal) chainid, err := goerliClient.ChainID(context.Background()) if err != nil { @@ -146,7 +150,7 @@ func StressTest(cmd *cobra.Command, _ []string) { zetaTxServer, err := txserver.NewZetaTxServer( conf.RPCs.ZetaCoreRPC, []string{utils.FungibleAdminName}, - []string{FungibleAdminMnemonic}, + []string{local.FungibleAdminMnemonic}, conf.ZetaChainID, ) if err != nil { @@ -173,11 +177,23 @@ func StressTest(cmd *cobra.Command, _ []string) { panic(err) } + // initialize context + ctx, cancel := context.WithCancel(context.Background()) + + verbose, err := cmd.Flags().GetBool(flagVerbose) + if err != nil { + panic(err) + } + logger := runner.NewLogger(verbose, color.FgWhite, "setup") + // initialize smoke test runner smokeTest := runner.NewSmokeTestRunner( - DeployerAddress, - DeployerPrivateKey, - FungibleAdminMnemonic, + ctx, + "deployer", + cancel, + local.DeployerAddress, + local.DeployerPrivateKey, + local.FungibleAdminMnemonic, goerliClient, zevmClient, cctxClient, @@ -189,6 +205,7 @@ func StressTest(cmd *cobra.Command, _ []string) { goerliAuth, zevmAuth, nil, + logger, ) // setup TSS addresses @@ -204,8 +221,8 @@ func StressTest(cmd *cobra.Command, _ []string) { smokeTest.SetZEVMContracts() // deposit on ZetaChain - smokeTest.DepositEtherIntoZRC20() - smokeTest.SendZetaIn() + smokeTest.DepositEther(false) + smokeTest.DepositZeta() } else if stressTestArgs.network == "TESTNET" { ethZRC20Addr, err := smokeTest.SystemContract.GasCoinZRC20ByChainId(&bind.CallOpts{}, big.NewInt(5)) if err != nil { @@ -222,7 +239,7 @@ func StressTest(cmd *cobra.Command, _ []string) { } // Check zrc20 balance of Deployer address - ethZRC20Balance, err := smokeTest.ETHZRC20.BalanceOf(nil, DeployerAddress) + ethZRC20Balance, err := smokeTest.ETHZRC20.BalanceOf(nil, local.DeployerAddress) if err != nil { panic(err) } @@ -235,7 +252,7 @@ func StressTest(cmd *cobra.Command, _ []string) { if err != nil { panic(err) } - receipt := utils.MustWaitForTxReceipt(smokeTest.ZevmClient, tx) + receipt := utils.MustWaitForTxReceipt(ctx, smokeTest.ZevmClient, tx, logger, smokeTest.ReceiptTimeout) fmt.Printf("eth zrc20 approve receipt: status %d\n", receipt.Status) // Get current nonce on zevm for DeployerAddress - Need to keep track of nonce at client level @@ -245,7 +262,7 @@ func StressTest(cmd *cobra.Command, _ []string) { } // #nosec G701 smoketest - always in range - nonce, err := smokeTest.ZevmClient.NonceAt(context.Background(), DeployerAddress, big.NewInt(int64(blockNum))) + nonce, err := smokeTest.ZevmClient.NonceAt(context.Background(), local.DeployerAddress, big.NewInt(int64(blockNum))) if err != nil { panic(err) } @@ -348,7 +365,7 @@ func WithdrawETHZRC20(sm *runner.SmokeTestRunner) { ethZRC20 := sm.ETHZRC20 sm.ZevmAuth.Nonce = zevmNonce - _, err := ethZRC20.Withdraw(sm.ZevmAuth, DeployerAddress.Bytes(), big.NewInt(100)) + _, err := ethZRC20.Withdraw(sm.ZevmAuth, local.DeployerAddress.Bytes(), big.NewInt(100)) if err != nil { panic(err) } From a707ddeaa10c8079ce4d6f2752c9e3af04fc037b Mon Sep 17 00:00:00 2001 From: kevinssgh Date: Wed, 17 Jan 2024 15:23:03 -0500 Subject: [PATCH 8/8] update refactor --- changelog.md | 2 +- cmd/zetae2e/init.go | 6 +- cmd/zetae2e/stress.go | 114 ++---- .../smoketest/cmd/smoketest/init.go | 37 -- .../smoketest/cmd/smoketest/root.go | 2 - .../smoketest/cmd/smoketest/stress.go | 377 ------------------ 6 files changed, 33 insertions(+), 505 deletions(-) delete mode 100644 contrib/localnet/orchestrator/smoketest/cmd/smoketest/init.go delete mode 100644 contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go diff --git a/changelog.md b/changelog.md index 3e4e7eaae6..3738a0fa15 100644 --- a/changelog.md +++ b/changelog.md @@ -68,7 +68,7 @@ Getting the correct TSS address for Bitcoin now requires proviidng the Bitcoin c * [1546](https://github.com/zeta-chain/node/pull/1546) - fix reset of pending nonces on genesis import * [1555](https://github.com/zeta-chain/node/pull/1555) - Reduce websocket message limit to 10MB * [1567](https://github.com/zeta-chain/node/pull/1567) - add bitcoin chain id to fetch the tss address rpc endpoint -* fix stress test - use new refactored config file and smoketest runner +* [1501](https://github.com/zeta-chain/node/pull/1501) - fix stress test - use new refactored config file and smoketest runner ### Refactoring diff --git a/cmd/zetae2e/init.go b/cmd/zetae2e/init.go index 171fcfcc18..66d7e4fd3f 100644 --- a/cmd/zetae2e/init.go +++ b/cmd/zetae2e/init.go @@ -3,6 +3,8 @@ package main import ( "fmt" + "github.com/zeta-chain/zetacore/cmd/zetae2e/local" + "github.com/spf13/cobra" "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" ) @@ -13,7 +15,7 @@ var configFile = "" func NewInitCmd() *cobra.Command { var InitCmd = &cobra.Command{ Use: "init", - Short: "Run Local Stress Test", + Short: "initialize config file for e2e tests", Run: initConfig, } @@ -24,7 +26,7 @@ func NewInitCmd() *cobra.Command { InitCmd.Flags().StringVar(&initConf.RPCs.Bitcoin, "btcURL", "bitcoin:18443", "--grpcURL bitcoin:18443") InitCmd.Flags().StringVar(&initConf.ZetaChainID, "chainID", "athens_101-1", "--chainID athens_101-1") - InitCmd.Flags().StringVar(&configFile, "cfg", "smoketest.config", "--cfg ./smoketest.config") + InitCmd.Flags().StringVar(&configFile, local.FlagConfigFile, "smoketest.config", "--cfg ./smoketest.config") return InitCmd } diff --git a/cmd/zetae2e/stress.go b/cmd/zetae2e/stress.go index fbde30a3ef..26a2169b95 100644 --- a/cmd/zetae2e/stress.go +++ b/cmd/zetae2e/stress.go @@ -4,30 +4,26 @@ import ( "context" "errors" "fmt" - "github.com/fatih/color" - "github.com/zeta-chain/zetacore/cmd/zetae2e/local" "math/big" "os" "sort" "time" + "github.com/fatih/color" + zetae2econfig "github.com/zeta-chain/zetacore/cmd/zetae2e/config" + "github.com/zeta-chain/zetacore/cmd/zetae2e/local" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/zeta-chain/zetacore/app" "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/txserver" "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/ethereum/go-ethereum/accounts/abi/bind" ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/spf13/cobra" "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zrc20.sol" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" - fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" - observertypes "github.com/zeta-chain/zetacore/x/observer/types" "google.golang.org/grpc" ) @@ -54,13 +50,13 @@ var stressTestArgs = stressArguments{} func NewStressTestCmd() *cobra.Command { var StressCmd = &cobra.Command{ Use: "stress", - Short: "Run Local Stress Test", + Short: "Run Stress Test", Run: StressTest, } StressCmd.Flags().StringVar(&stressTestArgs.deployerAddress, "addr", "0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC", "--addr ") StressCmd.Flags().StringVar(&stressTestArgs.deployerPrivateKey, "privKey", "d87baf7bf6dc560a252596678c12e41f7d1682837f05b29d411bc3f78ae2c263", "--privKey ") - StressCmd.Flags().StringVar(&stressTestArgs.network, "network", "", "--network TESTNET") + StressCmd.Flags().StringVar(&stressTestArgs.network, "network", "LOCAL", "--network TESTNET") StressCmd.Flags().Int64Var(&stressTestArgs.txnInterval, "tx-interval", 500, "--tx-interval [TIME_INTERVAL_MILLISECONDS]") StressCmd.Flags().BoolVar(&stressTestArgs.contractsDeployed, "contracts-deployed", false, "--contracts-deployed=false") StressCmd.Flags().StringVar(&stressTestArgs.config, local.FlagConfigFile, "", "config file to use for the smoketest") @@ -105,75 +101,29 @@ func StressTest(cmd *cobra.Command, _ []string) { } fmt.Printf("Deployer address: %s, balance: %d Wei\n", local.DeployerAddress.Hex(), bal) - chainid, err := goerliClient.ChainID(context.Background()) - if err != nil { - panic(err) - } - deployerPrivkey, err := crypto.HexToECDSA(stressTestArgs.deployerPrivateKey) - if err != nil { - panic(err) - } - goerliAuth, err := bind.NewKeyedTransactorWithChainID(deployerPrivkey, chainid) - if err != nil { - panic(err) - } - grpcConn, err := grpc.Dial(conf.RPCs.ZetaCoreGRPC, grpc.WithInsecure()) if err != nil { panic(err) } cctxClient := crosschaintypes.NewQueryClient(grpcConn) - fungibleClient := fungibletypes.NewQueryClient(grpcConn) - bankClient := banktypes.NewQueryClient(grpcConn) - authClient := authtypes.NewQueryClient(grpcConn) - observerClient := observertypes.NewQueryClient(grpcConn) // ----------------------------------------------------------------------------------- - // Wait for Genesis and keygen to be completed. ~ height 30 - time.Sleep(20 * time.Second) - for { - time.Sleep(5 * time.Second) - response, err := cctxClient.LastZetaHeight(context.Background(), &crosschaintypes.QueryLastZetaHeightRequest{}) - if err != nil { - fmt.Printf("cctxClient.LastZetaHeight error: %s", err) - continue - } - if response.Height >= 30 { - break - } - fmt.Printf("Last ZetaHeight: %d\n", response.Height) - } - - // initialize client to send messages to ZetaChain - zetaTxServer, err := txserver.NewZetaTxServer( - conf.RPCs.ZetaCoreRPC, - []string{utils.FungibleAdminName}, - []string{local.FungibleAdminMnemonic}, - conf.ZetaChainID, - ) - if err != nil { - panic(err) - } - - // get the clients for tests - var zevmClient *ethclient.Client - for { - time.Sleep(5 * time.Second) - fmt.Printf("dialing zevm client: %s\n", conf.RPCs.Zevm) - zevmClient, err = ethclient.Dial(conf.RPCs.Zevm) - if err != nil { - continue + // Wait for Genesis and keygen to be completed if network is local. ~ height 30 + if stressTestArgs.network == "LOCAL" { + time.Sleep(20 * time.Second) + for { + time.Sleep(5 * time.Second) + response, err := cctxClient.LastZetaHeight(context.Background(), &crosschaintypes.QueryLastZetaHeightRequest{}) + if err != nil { + fmt.Printf("cctxClient.LastZetaHeight error: %s", err) + continue + } + if response.Height >= 30 { + break + } + fmt.Printf("Last ZetaHeight: %d\n", response.Height) } - break - } - chainid, err = zevmClient.ChainID(context.Background()) - if err != nil { - panic(err) - } - zevmAuth, err := bind.NewKeyedTransactorWithChainID(deployerPrivkey, chainid) - if err != nil { - panic(err) } // initialize context @@ -186,36 +136,28 @@ func StressTest(cmd *cobra.Command, _ []string) { logger := runner.NewLogger(verbose, color.FgWhite, "setup") // initialize smoke test runner - smokeTest := runner.NewSmokeTestRunner( + smokeTest, err := zetae2econfig.RunnerFromConfig( ctx, "deployer", cancel, + conf, local.DeployerAddress, local.DeployerPrivateKey, - local.FungibleAdminMnemonic, - goerliClient, - zevmClient, - cctxClient, - zetaTxServer, - fungibleClient, - authClient, - bankClient, - observerClient, - goerliAuth, - zevmAuth, - nil, + utils.FungibleAdminName, + FungibleAdminMnemonic, logger, ) + if err != nil { + panic(err) + } // setup TSS addresses smokeTest.SetTSSAddresses() smokeTest.SetupEVM(stressTestArgs.contractsDeployed) - fmt.Printf("Stress test arguments: %+v", stressTestArgs) - // If stress test is running on local docker environment - if stressTestArgs.network == "" { + if stressTestArgs.network == "LOCAL" { // deploy and set zevm contract smokeTest.SetZEVMContracts() diff --git a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/init.go b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/init.go deleted file mode 100644 index 171fcfcc18..0000000000 --- a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/init.go +++ /dev/null @@ -1,37 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/spf13/cobra" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" -) - -var initConf = config.Config{} -var configFile = "" - -func NewInitCmd() *cobra.Command { - var InitCmd = &cobra.Command{ - Use: "init", - Short: "Run Local Stress Test", - Run: initConfig, - } - - InitCmd.Flags().StringVar(&initConf.RPCs.EVM, "ethURL", "http://eth:8545", "--ethURL http://eth:8545") - InitCmd.Flags().StringVar(&initConf.RPCs.ZetaCoreGRPC, "grpcURL", "zetacore0:9090", "--grpcURL zetacore0:9090") - InitCmd.Flags().StringVar(&initConf.RPCs.ZetaCoreRPC, "rpcURL", "http://zetacore0:26657", "--rpcURL http://zetacore0:26657") - InitCmd.Flags().StringVar(&initConf.RPCs.Zevm, "zevmURL", "http://zetacore0:8545", "--zevmURL http://zetacore0:8545") - InitCmd.Flags().StringVar(&initConf.RPCs.Bitcoin, "btcURL", "bitcoin:18443", "--grpcURL bitcoin:18443") - - InitCmd.Flags().StringVar(&initConf.ZetaChainID, "chainID", "athens_101-1", "--chainID athens_101-1") - InitCmd.Flags().StringVar(&configFile, "cfg", "smoketest.config", "--cfg ./smoketest.config") - - return InitCmd -} - -func initConfig(_ *cobra.Command, _ []string) { - err := config.WriteConfig(configFile, initConf) - if err != nil { - fmt.Printf("error writing config file: %s", err.Error()) - } -} diff --git a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/root.go b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/root.go index f746ea6914..512f235df5 100644 --- a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/root.go +++ b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/root.go @@ -11,8 +11,6 @@ func NewRootCmd() *cobra.Command { Short: "Smoke Test CLI", } cmd.AddCommand(local.NewLocalCmd()) - cmd.AddCommand(NewStressTestCmd()) - cmd.AddCommand(NewInitCmd()) return cmd } diff --git a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go b/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go deleted file mode 100644 index 9c18124f05..0000000000 --- a/contrib/localnet/orchestrator/smoketest/cmd/smoketest/stress.go +++ /dev/null @@ -1,377 +0,0 @@ -package main - -import ( - "context" - "errors" - "fmt" - "github.com/fatih/color" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/cmd/smoketest/local" - "math/big" - "os" - "sort" - "time" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/zeta-chain/zetacore/app" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/txserver" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" - - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/spf13/cobra" - "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zrc20.sol" - crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" - fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" - observertypes "github.com/zeta-chain/zetacore/x/observer/types" - "google.golang.org/grpc" -) - -const ( - StatInterval = 5 - StressTestTimeout = 100 * time.Minute - flagVerbose = "verbose" -) - -var ( - zevmNonce = big.NewInt(1) -) - -type stressArguments struct { - deployerAddress string - deployerPrivateKey string - network string - txnInterval int64 - contractsDeployed bool - config string -} - -var stressTestArgs = stressArguments{} - -func NewStressTestCmd() *cobra.Command { - var StressCmd = &cobra.Command{ - Use: "stress", - Short: "Run Local Stress Test", - Run: StressTest, - } - - StressCmd.Flags().StringVar(&stressTestArgs.deployerAddress, "addr", "0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC", "--addr ") - StressCmd.Flags().StringVar(&stressTestArgs.deployerPrivateKey, "privKey", "d87baf7bf6dc560a252596678c12e41f7d1682837f05b29d411bc3f78ae2c263", "--privKey ") - StressCmd.Flags().StringVar(&stressTestArgs.network, "network", "", "--network TESTNET") - StressCmd.Flags().Int64Var(&stressTestArgs.txnInterval, "tx-interval", 500, "--tx-interval [TIME_INTERVAL_MILLISECONDS]") - StressCmd.Flags().BoolVar(&stressTestArgs.contractsDeployed, "contracts-deployed", false, "--contracts-deployed=false") - StressCmd.Flags().StringVar(&stressTestArgs.config, "cfg", "", "config file to use for the smoketest") - StressCmd.Flags().Bool(flagVerbose, false, "set to true to enable verbose logging") - - local.DeployerAddress = ethcommon.HexToAddress(stressTestArgs.deployerAddress) - - return StressCmd -} - -func StressTest(cmd *cobra.Command, _ []string) { - testStartTime := time.Now() - defer func() { - fmt.Println("Smoke test took", time.Since(testStartTime)) - }() - go func() { - time.Sleep(StressTestTimeout) - fmt.Println("Smoke test timed out after", StressTestTimeout) - os.Exit(1) - }() - - // set account prefix to zeta - cosmosConf := sdk.GetConfig() - cosmosConf.SetBech32PrefixForAccount(app.Bech32PrefixAccAddr, app.Bech32PrefixAccPub) - cosmosConf.Seal() - - // initialize smoke tests config - conf, err := local.GetConfig(cmd) - if err != nil { - panic(err) - } - - // Initialize clients ---------------------------------------------------------------- - goerliClient, err := ethclient.Dial(conf.RPCs.EVM) - if err != nil { - panic(err) - } - - bal, err := goerliClient.BalanceAt(context.TODO(), local.DeployerAddress, nil) - if err != nil { - panic(err) - } - fmt.Printf("Deployer address: %s, balance: %d Wei\n", local.DeployerAddress.Hex(), bal) - - chainid, err := goerliClient.ChainID(context.Background()) - if err != nil { - panic(err) - } - deployerPrivkey, err := crypto.HexToECDSA(stressTestArgs.deployerPrivateKey) - if err != nil { - panic(err) - } - goerliAuth, err := bind.NewKeyedTransactorWithChainID(deployerPrivkey, chainid) - if err != nil { - panic(err) - } - - grpcConn, err := grpc.Dial(conf.RPCs.ZetaCoreGRPC, grpc.WithInsecure()) - if err != nil { - panic(err) - } - - cctxClient := crosschaintypes.NewQueryClient(grpcConn) - fungibleClient := fungibletypes.NewQueryClient(grpcConn) - bankClient := banktypes.NewQueryClient(grpcConn) - authClient := authtypes.NewQueryClient(grpcConn) - observerClient := observertypes.NewQueryClient(grpcConn) - // ----------------------------------------------------------------------------------- - - // Wait for Genesis and keygen to be completed. ~ height 30 - time.Sleep(20 * time.Second) - for { - time.Sleep(5 * time.Second) - response, err := cctxClient.LastZetaHeight(context.Background(), &crosschaintypes.QueryLastZetaHeightRequest{}) - if err != nil { - fmt.Printf("cctxClient.LastZetaHeight error: %s", err) - continue - } - if response.Height >= 30 { - break - } - fmt.Printf("Last ZetaHeight: %d\n", response.Height) - } - - // initialize client to send messages to ZetaChain - zetaTxServer, err := txserver.NewZetaTxServer( - conf.RPCs.ZetaCoreRPC, - []string{utils.FungibleAdminName}, - []string{local.FungibleAdminMnemonic}, - conf.ZetaChainID, - ) - if err != nil { - panic(err) - } - - // get the clients for tests - var zevmClient *ethclient.Client - for { - time.Sleep(5 * time.Second) - fmt.Printf("dialing zevm client: %s\n", conf.RPCs.Zevm) - zevmClient, err = ethclient.Dial(conf.RPCs.Zevm) - if err != nil { - continue - } - break - } - chainid, err = zevmClient.ChainID(context.Background()) - if err != nil { - panic(err) - } - zevmAuth, err := bind.NewKeyedTransactorWithChainID(deployerPrivkey, chainid) - if err != nil { - panic(err) - } - - // initialize context - ctx, cancel := context.WithCancel(context.Background()) - - verbose, err := cmd.Flags().GetBool(flagVerbose) - if err != nil { - panic(err) - } - logger := runner.NewLogger(verbose, color.FgWhite, "setup") - - // initialize smoke test runner - smokeTest := runner.NewSmokeTestRunner( - ctx, - "deployer", - cancel, - local.DeployerAddress, - local.DeployerPrivateKey, - local.FungibleAdminMnemonic, - goerliClient, - zevmClient, - cctxClient, - zetaTxServer, - fungibleClient, - authClient, - bankClient, - observerClient, - goerliAuth, - zevmAuth, - nil, - logger, - ) - - // setup TSS addresses - smokeTest.SetTSSAddresses() - - smokeTest.SetupEVM(stressTestArgs.contractsDeployed) - - fmt.Printf("Stress test arguments: %+v", stressTestArgs) - - // If stress test is running on local docker environment - if stressTestArgs.network == "" { - // deploy and set zevm contract - smokeTest.SetZEVMContracts() - - // deposit on ZetaChain - smokeTest.DepositEther(false) - smokeTest.DepositZeta() - } else if stressTestArgs.network == "TESTNET" { - ethZRC20Addr, err := smokeTest.SystemContract.GasCoinZRC20ByChainId(&bind.CallOpts{}, big.NewInt(5)) - if err != nil { - panic(err) - } - smokeTest.ETHZRC20Addr = ethZRC20Addr - smokeTest.ETHZRC20, err = zrc20.NewZRC20(smokeTest.ETHZRC20Addr, smokeTest.ZevmClient) - if err != nil { - panic(err) - } - } else { - err := errors.New("invalid network argument: " + stressTestArgs.network) - panic(err) - } - - // Check zrc20 balance of Deployer address - ethZRC20Balance, err := smokeTest.ETHZRC20.BalanceOf(nil, local.DeployerAddress) - if err != nil { - panic(err) - } - fmt.Printf("eth zrc20 balance: %s Wei \n", ethZRC20Balance.String()) - - //Pre-approve ETH withdraw on ZEVM - fmt.Printf("approving ETH ZRC20...\n") - ethZRC20 := smokeTest.ETHZRC20 - tx, err := ethZRC20.Approve(smokeTest.ZevmAuth, smokeTest.ETHZRC20Addr, big.NewInt(1e18)) - if err != nil { - panic(err) - } - receipt := utils.MustWaitForTxReceipt(ctx, smokeTest.ZevmClient, tx, logger, smokeTest.ReceiptTimeout) - fmt.Printf("eth zrc20 approve receipt: status %d\n", receipt.Status) - - // Get current nonce on zevm for DeployerAddress - Need to keep track of nonce at client level - blockNum, err := smokeTest.ZevmClient.BlockNumber(context.Background()) - if err != nil { - panic(err) - } - - // #nosec G701 smoketest - always in range - nonce, err := smokeTest.ZevmClient.NonceAt(context.Background(), local.DeployerAddress, big.NewInt(int64(blockNum))) - if err != nil { - panic(err) - } - - // #nosec G701 smoketest - always in range - zevmNonce = big.NewInt(int64(nonce)) - - // -------------- TEST BEGINS ------------------ - - fmt.Println("**** STRESS TEST BEGINS ****") - fmt.Println(" 1. Periodically Withdraw ETH from ZEVM to EVM - goerli") - fmt.Println(" 2. Display Network metrics to monitor performance [Num Pending outbound tx], [Num Trackers]") - - smokeTest.WG.Add(2) - go WithdrawCCtx(smokeTest) // Withdraw USDT from ZEVM to EVM - goerli - go EchoNetworkMetrics(smokeTest) // Display Network metrics periodically to monitor performance - - smokeTest.WG.Wait() -} - -// WithdrawCCtx withdraw USDT from ZEVM to EVM -func WithdrawCCtx(sm *runner.SmokeTestRunner) { - ticker := time.NewTicker(time.Millisecond * time.Duration(stressTestArgs.txnInterval)) - for { - select { - case <-ticker.C: - WithdrawETHZRC20(sm) - } - } -} - -func EchoNetworkMetrics(sm *runner.SmokeTestRunner) { - ticker := time.NewTicker(time.Second * StatInterval) - var queue = make([]uint64, 0) - var numTicks = 0 - var totalMinedTxns = uint64(0) - var previousMinedTxns = uint64(0) - chainID, err := getChainID(sm.GoerliClient) - - if err != nil { - panic(err) - } - - for { - select { - case <-ticker.C: - numTicks++ - // Get all pending outbound transactions - cctxResp, err := sm.CctxClient.CctxListPending(context.Background(), &crosschaintypes.QueryListCctxPendingRequest{ - ChainId: chainID.Int64(), - }) - if err != nil { - continue - } - sends := cctxResp.CrossChainTx - sort.Slice(sends, func(i, j int) bool { - return sends[i].GetCurrentOutTxParam().OutboundTxTssNonce < sends[j].GetCurrentOutTxParam().OutboundTxTssNonce - }) - if len(sends) > 0 { - fmt.Printf("pending nonces %d to %d\n", sends[0].GetCurrentOutTxParam().OutboundTxTssNonce, sends[len(sends)-1].GetCurrentOutTxParam().OutboundTxTssNonce) - } else { - continue - } - // - // Get all trackers - trackerResp, err := sm.CctxClient.OutTxTrackerAll(context.Background(), &crosschaintypes.QueryAllOutTxTrackerRequest{}) - if err != nil { - continue - } - - currentMinedTxns := sends[0].GetCurrentOutTxParam().OutboundTxTssNonce - newMinedTxCnt := currentMinedTxns - previousMinedTxns - previousMinedTxns = currentMinedTxns - - // Add new mined txn count to queue and remove the oldest entry - queue = append(queue, newMinedTxCnt) - if numTicks > 60/StatInterval { - totalMinedTxns -= queue[0] - queue = queue[1:] - numTicks = 60/StatInterval + 1 //prevent overflow - } - - //Calculate rate -> tx/min - totalMinedTxns += queue[len(queue)-1] - rate := totalMinedTxns - - numPending := len(cctxResp.CrossChainTx) - numTrackers := len(trackerResp.OutTxTracker) - - fmt.Println("Network Stat => Num of Pending cctx: ", numPending, "Num active trackers: ", numTrackers, "Tx Rate: ", rate, " tx/min") - } - } -} - -func WithdrawETHZRC20(sm *runner.SmokeTestRunner) { - defer func() { - zevmNonce.Add(zevmNonce, big.NewInt(1)) - }() - - ethZRC20 := sm.ETHZRC20 - - sm.ZevmAuth.Nonce = zevmNonce - _, err := ethZRC20.Withdraw(sm.ZevmAuth, local.DeployerAddress.Bytes(), big.NewInt(100)) - if err != nil { - panic(err) - } -} - -// Get ETH based chain ID -func getChainID(client *ethclient.Client) (*big.Int, error) { - return client.ChainID(context.Background()) -}