diff --git a/changelog.md b/changelog.md index d71bded0a0..59e544fad6 100644 --- a/changelog.md +++ b/changelog.md @@ -8,7 +8,9 @@ * [3124](https://github.com/zeta-chain/node/pull/3124) - integrate SPL deposits ### Tests + * [3075](https://github.com/zeta-chain/node/pull/3075) - ton: withdraw concurrent, deposit & revert. +* [3105](https://github.com/zeta-chain/node/pull/3105) - split Bitcoin E2E tests into two runners for deposit and withdraw ### Refactor * [3118](https://github.com/zeta-chain/node/pull/3118) - zetaclient: remove hsm signer diff --git a/cmd/zetae2e/bitcoin_address.go b/cmd/zetae2e/bitcoin_address.go index 70d64ab582..be1251d1d2 100644 --- a/cmd/zetae2e/bitcoin_address.go +++ b/cmd/zetae2e/bitcoin_address.go @@ -66,14 +66,11 @@ func runBitcoinAddress(cmd *cobra.Command, args []string) error { return err } - addr, privKey, err := r.GetBtcAddress() - if err != nil { - return err - } + addr, privKey := r.GetBtcAddress() - logger.Print("* BTC address: %s", addr) + logger.Print("* BTC address: %s", addr.EncodeAddress()) if showPrivKey { - logger.Print("* BTC privkey: %s", privKey) + logger.Print("* BTC privkey: %s", privKey.String()) } return nil diff --git a/cmd/zetae2e/config/local.yml b/cmd/zetae2e/config/local.yml index 2481ab31fa..5cc87be394 100644 --- a/cmd/zetae2e/config/local.yml +++ b/cmd/zetae2e/config/local.yml @@ -16,10 +16,14 @@ additional_accounts: bech32_address: "zeta13t3zjxvwec7g38q8mdjga37rpes9zkfvv7tkn2" evm_address: "0x8Ae229198eCE3c889C07DB648Ec7C30E6051592c" private_key: "105460aebf71b10bfdb710ef5aa6d2932ee6ff6fc317ac9c24e0979903b10a5d" - user_bitcoin: + user_bitcoin_deposit: bech32_address: "zeta19q7czqysah6qg0n4y3l2a08gfzqxydla492v80" evm_address: "0x283d810090EdF4043E75247eAeBcE848806237fD" private_key: "7bb523963ee2c78570fb6113d886a4184d42565e8847f1cb639f5f5e2ef5b37a" + user_bitcoin_withdraw: + bech32_address: "zeta17e77anpmzhuuam67hg6x3mtqrulqh80z9chv70" + evm_address: "0xf67deecc3B15F9CEeF5eba3468ed601f3e0B9de2" + private_key: "2b3306a8ac43dbf0e350b87876c131e7e12bd49563a16de9ce8aeb664b94d559" user_solana: bech32_address: "zeta1zqlajgj0qr8rqylf2c572t0ux8vqt45d4zngpm" evm_address: "0x103FD9224F00ce3013e95629e52DFc31D805D68d" diff --git a/cmd/zetae2e/config/localnet.yml b/cmd/zetae2e/config/localnet.yml index 5bd207a020..24e51223ef 100644 --- a/cmd/zetae2e/config/localnet.yml +++ b/cmd/zetae2e/config/localnet.yml @@ -16,10 +16,14 @@ additional_accounts: bech32_address: "zeta13t3zjxvwec7g38q8mdjga37rpes9zkfvv7tkn2" evm_address: "0x8Ae229198eCE3c889C07DB648Ec7C30E6051592c" private_key: "105460aebf71b10bfdb710ef5aa6d2932ee6ff6fc317ac9c24e0979903b10a5d" - user_bitcoin: + user_bitcoin_deposit: bech32_address: "zeta19q7czqysah6qg0n4y3l2a08gfzqxydla492v80" evm_address: "0x283d810090EdF4043E75247eAeBcE848806237fD" private_key: "7bb523963ee2c78570fb6113d886a4184d42565e8847f1cb639f5f5e2ef5b37a" + user_bitcoin_withdraw: + bech32_address: "zeta17e77anpmzhuuam67hg6x3mtqrulqh80z9chv70" + evm_address: "0xf67deecc3B15F9CEeF5eba3468ed601f3e0B9de2" + private_key: "2b3306a8ac43dbf0e350b87876c131e7e12bd49563a16de9ce8aeb664b94d559" user_solana: bech32_address: "zeta1zqlajgj0qr8rqylf2c572t0ux8vqt45d4zngpm" evm_address: "0x103FD9224F00ce3013e95629e52DFc31D805D68d" diff --git a/cmd/zetae2e/local/bitcoin.go b/cmd/zetae2e/local/bitcoin.go index f28f182877..900c9c3792 100644 --- a/cmd/zetae2e/local/bitcoin.go +++ b/cmd/zetae2e/local/bitcoin.go @@ -5,55 +5,116 @@ import ( "time" "github.com/fatih/color" + "github.com/stretchr/testify/require" "github.com/zeta-chain/node/e2e/config" "github.com/zeta-chain/node/e2e/e2etests" "github.com/zeta-chain/node/e2e/runner" + "github.com/zeta-chain/node/testutil" ) -// bitcoinTestRoutine runs Bitcoin related e2e tests -func bitcoinTestRoutine( +// initBitcoinTestRunners initializes Bitcoin deposit and withdraw test runners +func initBitcoinTestRunners( conf config.Config, deployerRunner *runner.E2ERunner, verbose bool, - initBitcoinNetwork bool, - testNames ...string, -) func() error { - return func() (err error) { - account := conf.AdditionalAccounts.UserBitcoin - // initialize runner for bitcoin test - bitcoinRunner, err := initTestRunner( - "bitcoin", - conf, - deployerRunner, - account, - runner.NewLogger(verbose, color.FgYellow, "bitcoin"), - ) - if err != nil { - return err - } + initNetwork bool, + depositTests []string, + withdrawTests []string, +) (func() error, func() error) { + // initialize runner for deposit tests + // deposit tests need Bitcoin node wallet to handle UTXOs + account := conf.AdditionalAccounts.UserBitcoinDeposit + runnerDeposit := initBitcoinRunner( + "btc_deposit", + account, + conf, + deployerRunner, + color.FgYellow, + verbose, + initNetwork, + true, + ) - bitcoinRunner.Logger.Print("🏃 starting Bitcoin tests") - startTime := time.Now() + // initialize runner for withdraw tests + // withdraw tests DON'T use Bitcoin node wallet + account = conf.AdditionalAccounts.UserBitcoinWithdraw + runnerWithdraw := initBitcoinRunner( + "btc_withdraw", + account, + conf, + deployerRunner, + color.FgHiYellow, + verbose, + initNetwork, + false, + ) + + // initialize funds + // send BTC to TSS for gas fees and to tester ZEVM address + if initNetwork { + // mine 101 blocks to ensure the BTC rewards are spendable + // Note: the block rewards can be sent to any address in here + _, err := runnerDeposit.GenerateToAddressIfLocalBitcoin(101, runnerDeposit.BTCDeployerAddress) + require.NoError(runnerDeposit, err) - // funding the account + // send BTC to ZEVM addresses + runnerDeposit.DepositBTC(runnerDeposit.EVMAddress()) + runnerDeposit.DepositBTC(runnerWithdraw.EVMAddress()) + } + + // create test routines + routineDeposit := createBitcoinTestRoutine(runnerDeposit, depositTests) + routineWithdraw := createBitcoinTestRoutine(runnerWithdraw, withdrawTests) + + return routineDeposit, routineWithdraw +} + +// initBitcoinRunner initializes the Bitcoin runner for given test name and account +func initBitcoinRunner( + name string, + account config.Account, + conf config.Config, + deployerRunner *runner.E2ERunner, + printColor color.Attribute, + verbose, initNetwork, createWallet bool, +) *runner.E2ERunner { + // initialize runner for bitcoin test + runner, err := initTestRunner(name, conf, deployerRunner, account, runner.NewLogger(verbose, printColor, name)) + testutil.NoError(err) + + // setup TSS address and setup deployer wallet + runner.SetupBitcoinAccounts(createWallet) + + // initialize funds + if initNetwork { + // send some BTC block rewards to the deployer address + _, err = runner.GenerateToAddressIfLocalBitcoin(4, runner.BTCDeployerAddress) + require.NoError(runner, err) + + // send ERC20 token on EVM txERC20Send := deployerRunner.SendERC20OnEvm(account.EVMAddress(), 1000) - bitcoinRunner.WaitForTxReceiptOnEvm(txERC20Send) + runner.WaitForTxReceiptOnEvm(txERC20Send) - // depositing the necessary tokens on ZetaChain - txEtherDeposit := bitcoinRunner.DepositEther() - txERC20Deposit := bitcoinRunner.DepositERC20() + // deposit ETH and ERC20 tokens on ZetaChain + txEtherDeposit := runner.DepositEther() + txERC20Deposit := runner.DepositERC20() - bitcoinRunner.WaitForMinedCCTX(txEtherDeposit) - bitcoinRunner.WaitForMinedCCTX(txERC20Deposit) + runner.WaitForMinedCCTX(txEtherDeposit) + runner.WaitForMinedCCTX(txERC20Deposit) + } - bitcoinRunner.SetupBitcoinAccount(initBitcoinNetwork) - bitcoinRunner.DepositBTC() + return runner +} - // run bitcoin test - // Note: due to the extensive block generation in Bitcoin localnet, block header test is run first - // to make it faster to catch up with the latest block header - testsToRun, err := bitcoinRunner.GetE2ETestsToRunByName( +// createBitcoinTestRoutine creates a test routine for given test names +func createBitcoinTestRoutine(r *runner.E2ERunner, testNames []string) func() error { + return func() (err error) { + r.Logger.Print("🏃 starting bitcoin tests") + startTime := time.Now() + + // run bitcoin tests + testsToRun, err := r.GetE2ETestsToRunByName( e2etests.AllE2ETests, testNames..., ) @@ -61,15 +122,11 @@ func bitcoinTestRoutine( return fmt.Errorf("bitcoin tests failed: %v", err) } - if err := bitcoinRunner.RunE2ETests(testsToRun); err != nil { + if err := r.RunE2ETests(testsToRun); err != nil { return fmt.Errorf("bitcoin tests failed: %v", err) } - if err := bitcoinRunner.CheckBtcTSSBalance(); err != nil { - return err - } - - bitcoinRunner.Logger.Print("🍾 Bitcoin tests completed in %s", time.Since(startTime).String()) + r.Logger.Print("🍾 bitcoin tests completed in %s", time.Since(startTime).String()) return err } diff --git a/cmd/zetae2e/local/local.go b/cmd/zetae2e/local/local.go index 9b818ea8c0..9858ac6382 100644 --- a/cmd/zetae2e/local/local.go +++ b/cmd/zetae2e/local/local.go @@ -313,7 +313,8 @@ func localE2ETest(cmd *cobra.Command, _ []string) { e2etests.TestMessagePassingEVMtoZEVMRevertFailName, } - bitcoinTests := []string{ + // btc withdraw tests are those that need a Bitcoin node wallet to send UTXOs + bitcoinDepositTests := []string{ e2etests.TestBitcoinDonationName, e2etests.TestBitcoinDepositName, e2etests.TestBitcoinDepositAndCallName, @@ -323,17 +324,19 @@ func localE2ETest(cmd *cobra.Command, _ []string) { e2etests.TestBitcoinStdMemoDepositAndCallRevertName, e2etests.TestBitcoinStdMemoDepositAndCallRevertOtherAddressName, e2etests.TestBitcoinStdMemoInscribedDepositAndCallName, + e2etests.TestCrosschainSwapName, + } + bitcoinWithdrawTests := []string{ e2etests.TestBitcoinWithdrawSegWitName, e2etests.TestBitcoinWithdrawInvalidAddressName, e2etests.TestZetaWithdrawBTCRevertName, - e2etests.TestCrosschainSwapName, } - bitcoinAdvancedTests := []string{ + bitcoinWithdrawTestsAdvanced := []string{ e2etests.TestBitcoinWithdrawTaprootName, e2etests.TestBitcoinWithdrawLegacyName, - e2etests.TestBitcoinWithdrawMultipleName, e2etests.TestBitcoinWithdrawP2SHName, e2etests.TestBitcoinWithdrawP2WSHName, + e2etests.TestBitcoinWithdrawMultipleName, e2etests.TestBitcoinWithdrawRestrictedName, } ethereumTests := []string{ @@ -367,7 +370,7 @@ func localE2ETest(cmd *cobra.Command, _ []string) { erc20Tests = append(erc20Tests, erc20AdvancedTests...) zetaTests = append(zetaTests, zetaAdvancedTests...) zevmMPTests = append(zevmMPTests, zevmMPAdvancedTests...) - bitcoinTests = append(bitcoinTests, bitcoinAdvancedTests...) + bitcoinWithdrawTests = append(bitcoinWithdrawTests, bitcoinWithdrawTestsAdvanced...) ethereumTests = append(ethereumTests, ethereumAdvancedTests...) } @@ -375,7 +378,16 @@ func localE2ETest(cmd *cobra.Command, _ []string) { eg.Go(erc20TestRoutine(conf, deployerRunner, verbose, erc20Tests...)) eg.Go(zetaTestRoutine(conf, deployerRunner, verbose, zetaTests...)) eg.Go(zevmMPTestRoutine(conf, deployerRunner, verbose, zevmMPTests...)) - eg.Go(bitcoinTestRoutine(conf, deployerRunner, verbose, !skipBitcoinSetup, bitcoinTests...)) + runnerDeposit, runnerWithdraw := initBitcoinTestRunners( + conf, + deployerRunner, + verbose, + !skipBitcoinSetup, + bitcoinDepositTests, + bitcoinWithdrawTests, + ) + eg.Go(runnerDeposit) + eg.Go(runnerWithdraw) eg.Go(ethereumTestRoutine(conf, deployerRunner, verbose, ethereumTests...)) } @@ -470,7 +482,7 @@ func localE2ETest(cmd *cobra.Command, _ []string) { } // if all tests pass, cancel txs priority monitoring and check if tx priority is not correct in some blocks - logger.Print("⏳ e2e tests passed,checking tx priority") + logger.Print("⏳ e2e tests passed, checking tx priority") monitorPriorityCancel() if err := <-txPriorityErrCh; err != nil && errors.Is(err, errWrongTxPriority) { logger.Print("❌ %v", err) @@ -483,10 +495,15 @@ func localE2ETest(cmd *cobra.Command, _ []string) { if testTSSMigration { TSSMigration(deployerRunner, logger, verbose, conf) } + // Verify that there are no trackers left over after tests complete if !skipTrackerCheck { deployerRunner.EnsureNoTrackers() } + + // Verify that the balance of restricted address is zero + deployerRunner.EnsureZeroBalanceOnRestrictedAddressZEVM() + // print and validate report networkReport, err := deployerRunner.GenerateNetworkReport() if err != nil { diff --git a/cmd/zetae2e/setup_bitcoin.go b/cmd/zetae2e/setup_bitcoin.go index 622855a027..a51d8880b0 100644 --- a/cmd/zetae2e/setup_bitcoin.go +++ b/cmd/zetae2e/setup_bitcoin.go @@ -58,7 +58,7 @@ func runSetupBitcoin(_ *cobra.Command, args []string) error { return err } - r.SetupBitcoinAccount(true) + r.SetupBitcoinAccounts(true) logger.Print("* BTC setup done") diff --git a/contrib/localnet/orchestrator/start-zetae2e.sh b/contrib/localnet/orchestrator/start-zetae2e.sh index 33f0d4e956..5d8c9c5586 100644 --- a/contrib/localnet/orchestrator/start-zetae2e.sh +++ b/contrib/localnet/orchestrator/start-zetae2e.sh @@ -98,8 +98,11 @@ fund_eth_from_config '.additional_accounts.user_zeta_test.evm_address' 10000 "ze # unlock zevm message passing tester accounts fund_eth_from_config '.additional_accounts.user_zevm_mp_test.evm_address' 10000 "zevm mp tester" -# unlock bitcoin tester accounts -fund_eth_from_config '.additional_accounts.user_bitcoin.evm_address' 10000 "bitcoin tester" +# unlock bitcoin deposit tester accounts +fund_eth_from_config '.additional_accounts.user_bitcoin_deposit.evm_address' 10000 "bitcoin deposit tester" + +# unlock bitcoin withdraw tester accounts +fund_eth_from_config '.additional_accounts.user_bitcoin_withdraw.evm_address' 10000 "bitcoin withdraw tester" # unlock solana tester accounts fund_eth_from_config '.additional_accounts.user_solana.evm_address' 10000 "solana tester" diff --git a/contrib/localnet/scripts/start-zetacored.sh b/contrib/localnet/scripts/start-zetacored.sh index c0e8424738..38047a6b46 100755 --- a/contrib/localnet/scripts/start-zetacored.sh +++ b/contrib/localnet/scripts/start-zetacored.sh @@ -242,8 +242,11 @@ then # zeta tester address=$(yq -r '.additional_accounts.user_zeta_test.bech32_address' /root/config.yml) zetacored add-genesis-account "$address" 100000000000000000000000000azeta -# bitcoin tester - address=$(yq -r '.additional_accounts.user_bitcoin.bech32_address' /root/config.yml) +# bitcoin deposit tester + address=$(yq -r '.additional_accounts.user_bitcoin_deposit.bech32_address' /root/config.yml) + zetacored add-genesis-account "$address" 100000000000000000000000000azeta +# bitcoin withdraw tester + address=$(yq -r '.additional_accounts.user_bitcoin_withdraw.bech32_address' /root/config.yml) zetacored add-genesis-account "$address" 100000000000000000000000000azeta # solana tester address=$(yq -r '.additional_accounts.user_solana.bech32_address' /root/config.yml) diff --git a/e2e/config/config.go b/e2e/config/config.go index 15ca4a1f2c..33a8c2bea8 100644 --- a/e2e/config/config.go +++ b/e2e/config/config.go @@ -61,20 +61,21 @@ type Account struct { // AdditionalAccounts are extra accounts required to run specific tests type AdditionalAccounts struct { - UserERC20 Account `yaml:"user_erc20"` - UserZetaTest Account `yaml:"user_zeta_test"` - UserZEVMMPTest Account `yaml:"user_zevm_mp_test"` - UserBitcoin Account `yaml:"user_bitcoin"` - UserSolana Account `yaml:"user_solana"` - UserEther Account `yaml:"user_ether"` - UserMisc Account `yaml:"user_misc"` - UserAdmin Account `yaml:"user_admin"` - UserMigration Account `yaml:"user_migration"` // used for TSS migration, TODO: rename (https://github.com/zeta-chain/node/issues/2780) - UserPrecompile Account `yaml:"user_precompile"` - UserV2Ether Account `yaml:"user_v2_ether"` - UserV2ERC20 Account `yaml:"user_v2_erc20"` - UserV2EtherRevert Account `yaml:"user_v2_ether_revert"` - UserV2ERC20Revert Account `yaml:"user_v2_erc20_revert"` + UserERC20 Account `yaml:"user_erc20"` + UserZetaTest Account `yaml:"user_zeta_test"` + UserZEVMMPTest Account `yaml:"user_zevm_mp_test"` + UserBitcoinDeposit Account `yaml:"user_bitcoin_deposit"` + UserBitcoinWithdraw Account `yaml:"user_bitcoin_withdraw"` + UserSolana Account `yaml:"user_solana"` + UserEther Account `yaml:"user_ether"` + UserMisc Account `yaml:"user_misc"` + UserAdmin Account `yaml:"user_admin"` + UserMigration Account `yaml:"user_migration"` // used for TSS migration, TODO: rename (https://github.com/zeta-chain/node/issues/2780) + UserPrecompile Account `yaml:"user_precompile"` + UserV2Ether Account `yaml:"user_v2_ether"` + UserV2ERC20 Account `yaml:"user_v2_erc20"` + UserV2EtherRevert Account `yaml:"user_v2_ether_revert"` + UserV2ERC20Revert Account `yaml:"user_v2_erc20_revert"` } type PolicyAccounts struct { @@ -235,7 +236,8 @@ func (a AdditionalAccounts) AsSlice() []Account { a.UserERC20, a.UserZetaTest, a.UserZEVMMPTest, - a.UserBitcoin, + a.UserBitcoinDeposit, + a.UserBitcoinWithdraw, a.UserSolana, a.UserEther, a.UserMisc, @@ -314,7 +316,11 @@ func (c *Config) GenerateKeys() error { if err != nil { return err } - c.AdditionalAccounts.UserBitcoin, err = generateAccount() + c.AdditionalAccounts.UserBitcoinDeposit, err = generateAccount() + if err != nil { + return err + } + c.AdditionalAccounts.UserBitcoinWithdraw, err = generateAccount() if err != nil { return err } diff --git a/e2e/e2etests/test_bitcoin_deposit.go b/e2e/e2etests/test_bitcoin_deposit.go index 590a5c81d8..59df40f9b6 100644 --- a/e2e/e2etests/test_bitcoin_deposit.go +++ b/e2e/e2etests/test_bitcoin_deposit.go @@ -13,8 +13,6 @@ func TestBitcoinDeposit(r *runner.E2ERunner, args []string) { depositAmount := parseFloat(r, args[0]) - r.SetBtcAddress(r.Name, false) - txHash := r.DepositBTCWithAmount(depositAmount, nil) // wait for the cctx to be mined diff --git a/e2e/e2etests/test_bitcoin_deposit_and_call_revert.go b/e2e/e2etests/test_bitcoin_deposit_and_call_revert.go index eed10485bf..0c0e45c77f 100644 --- a/e2e/e2etests/test_bitcoin_deposit_and_call_revert.go +++ b/e2e/e2etests/test_bitcoin_deposit_and_call_revert.go @@ -11,10 +11,6 @@ import ( ) func TestBitcoinDepositAndCallRevert(r *runner.E2ERunner, args []string) { - // ARRANGE - // Given BTC address - r.SetBtcAddress(r.Name, false) - // Given "Live" BTC network stop := r.MineBlocksIfLocalBitcoin() defer stop() diff --git a/e2e/e2etests/test_bitcoin_deposit_call.go b/e2e/e2etests/test_bitcoin_deposit_call.go index d3d6917c59..0ddbcb0b27 100644 --- a/e2e/e2etests/test_bitcoin_deposit_call.go +++ b/e2e/e2etests/test_bitcoin_deposit_call.go @@ -13,10 +13,6 @@ import ( ) func TestBitcoinDepositAndCall(r *runner.E2ERunner, args []string) { - // ARRANGE - // Given BTC address - r.SetBtcAddress(r.Name, false) - // Given "Live" BTC network stop := r.MineBlocksIfLocalBitcoin() defer stop() diff --git a/e2e/e2etests/test_bitcoin_donation.go b/e2e/e2etests/test_bitcoin_donation.go index 1dd5a34859..91b39ebff3 100644 --- a/e2e/e2etests/test_bitcoin_donation.go +++ b/e2e/e2etests/test_bitcoin_donation.go @@ -12,10 +12,6 @@ import ( ) func TestBitcoinDonation(r *runner.E2ERunner, args []string) { - // ARRANGE - // Given BTC address - r.SetBtcAddress(r.Name, false) - // Given "Live" BTC network stop := r.MineBlocksIfLocalBitcoin() defer stop() diff --git a/e2e/e2etests/test_bitcoin_std_deposit.go b/e2e/e2etests/test_bitcoin_std_deposit.go index e90b23d64a..b822487f21 100644 --- a/e2e/e2etests/test_bitcoin_std_deposit.go +++ b/e2e/e2etests/test_bitcoin_std_deposit.go @@ -14,9 +14,6 @@ import ( ) func TestBitcoinStdMemoDeposit(r *runner.E2ERunner, args []string) { - // setup deployer BTC address - r.SetBtcAddress(r.Name, false) - // start mining blocks if local bitcoin stop := r.MineBlocksIfLocalBitcoin() defer stop() diff --git a/e2e/e2etests/test_bitcoin_std_deposit_and_call.go b/e2e/e2etests/test_bitcoin_std_deposit_and_call.go index 7a9c6ca255..2cdd7caa3d 100644 --- a/e2e/e2etests/test_bitcoin_std_deposit_and_call.go +++ b/e2e/e2etests/test_bitcoin_std_deposit_and_call.go @@ -14,9 +14,6 @@ import ( ) func TestBitcoinStdMemoDepositAndCall(r *runner.E2ERunner, args []string) { - // setup deployer BTC address - r.SetBtcAddress(r.Name, false) - // start mining blocks if local bitcoin stop := r.MineBlocksIfLocalBitcoin() defer stop() diff --git a/e2e/e2etests/test_bitcoin_std_deposit_and_call_revert.go b/e2e/e2etests/test_bitcoin_std_deposit_and_call_revert.go index 76bf128aad..96b4186d8f 100644 --- a/e2e/e2etests/test_bitcoin_std_deposit_and_call_revert.go +++ b/e2e/e2etests/test_bitcoin_std_deposit_and_call_revert.go @@ -11,10 +11,6 @@ import ( ) func TestBitcoinStdMemoDepositAndCallRevert(r *runner.E2ERunner, args []string) { - // ARRANGE - // Given BTC address - r.SetBtcAddress(r.Name, false) - // Start mining blocks stop := r.MineBlocksIfLocalBitcoin() defer stop() diff --git a/e2e/e2etests/test_bitcoin_std_deposit_and_call_revert_other_address.go b/e2e/e2etests/test_bitcoin_std_deposit_and_call_revert_other_address.go index c6da1b1696..8ecb3b0d5f 100644 --- a/e2e/e2etests/test_bitcoin_std_deposit_and_call_revert_other_address.go +++ b/e2e/e2etests/test_bitcoin_std_deposit_and_call_revert_other_address.go @@ -12,10 +12,6 @@ import ( ) func TestBitcoinStdMemoDepositAndCallRevertOtherAddress(r *runner.E2ERunner, args []string) { - // ARRANGE - // Given BTC address - r.SetBtcAddress(r.Name, false) - // Start mining blocks stop := r.MineBlocksIfLocalBitcoin() defer stop() diff --git a/e2e/e2etests/test_bitcoin_std_memo_inscribed_deposit_and_call.go b/e2e/e2etests/test_bitcoin_std_memo_inscribed_deposit_and_call.go index c9a5d7af31..df23ae8383 100644 --- a/e2e/e2etests/test_bitcoin_std_memo_inscribed_deposit_and_call.go +++ b/e2e/e2etests/test_bitcoin_std_memo_inscribed_deposit_and_call.go @@ -14,10 +14,6 @@ import ( ) func TestBitcoinStdMemoInscribedDepositAndCall(r *runner.E2ERunner, args []string) { - // ARRANGE - // Given BTC address - r.SetBtcAddress(r.Name, false) - // Start mining blocks stop := r.MineBlocksIfLocalBitcoin() defer stop() diff --git a/e2e/e2etests/test_bitcoin_withdraw_invalid_address.go b/e2e/e2etests/test_bitcoin_withdraw_invalid_address.go index 5c7254a3a1..aae4b4a446 100644 --- a/e2e/e2etests/test_bitcoin_withdraw_invalid_address.go +++ b/e2e/e2etests/test_bitcoin_withdraw_invalid_address.go @@ -15,8 +15,6 @@ func TestBitcoinWithdrawToInvalidAddress(r *runner.E2ERunner, args []string) { withdrawalAmount := parseFloat(r, args[0]) amount := btcAmountFromFloat64(r, withdrawalAmount) - r.SetBtcAddress(r.Name, false) - withdrawToInvalidAddress(r, amount) } diff --git a/e2e/e2etests/test_bitcoin_withdraw_legacy.go b/e2e/e2etests/test_bitcoin_withdraw_legacy.go index 091bb63531..ba33c8b24d 100644 --- a/e2e/e2etests/test_bitcoin_withdraw_legacy.go +++ b/e2e/e2etests/test_bitcoin_withdraw_legacy.go @@ -11,8 +11,6 @@ func TestBitcoinWithdrawLegacy(r *runner.E2ERunner, args []string) { // check length of arguments require.Len(r, args, 2) - r.SetBtcAddress(r.Name, false) - // parse arguments and withdraw BTC receiver, amount := parseBitcoinWithdrawArgs(r, args, defaultReceiver) diff --git a/e2e/e2etests/test_bitcoin_withdraw_multiple.go b/e2e/e2etests/test_bitcoin_withdraw_multiple.go index 09d77fde80..642f1d49dd 100644 --- a/e2e/e2etests/test_bitcoin_withdraw_multiple.go +++ b/e2e/e2etests/test_bitcoin_withdraw_multiple.go @@ -18,9 +18,6 @@ func WithdrawBitcoinMultipleTimes(r *runner.E2ERunner, args []string) { times = parseInt(r, args[1]) ) - // Given BTC address set - r.SetBtcAddress(r.Name, false) - // Given a receiver receiver, err := chains.DecodeBtcAddress(defaultReceiver, r.GetBitcoinChainID()) require.NoError(r, err) diff --git a/e2e/e2etests/test_bitcoin_withdraw_p2sh.go b/e2e/e2etests/test_bitcoin_withdraw_p2sh.go index 248ce14ec5..e3eda5f9d5 100644 --- a/e2e/e2etests/test_bitcoin_withdraw_p2sh.go +++ b/e2e/e2etests/test_bitcoin_withdraw_p2sh.go @@ -11,8 +11,6 @@ func TestBitcoinWithdrawP2SH(r *runner.E2ERunner, args []string) { // check length of arguments require.Len(r, args, 2) - r.SetBtcAddress(r.Name, false) - // parse arguments and withdraw BTC defaultReceiver := "2N6AoUj3KPS7wNGZXuCckh8YEWcSYNsGbqd" receiver, amount := parseBitcoinWithdrawArgs(r, args, defaultReceiver) diff --git a/e2e/e2etests/test_bitcoin_withdraw_p2wsh.go b/e2e/e2etests/test_bitcoin_withdraw_p2wsh.go index 1865018628..41b65824bc 100644 --- a/e2e/e2etests/test_bitcoin_withdraw_p2wsh.go +++ b/e2e/e2etests/test_bitcoin_withdraw_p2wsh.go @@ -10,8 +10,6 @@ import ( func TestBitcoinWithdrawP2WSH(r *runner.E2ERunner, args []string) { require.Len(r, args, 2) - r.SetBtcAddress(r.Name, false) - // parse arguments and withdraw BTC defaultReceiver := "bcrt1qm9mzhyky4w853ft2ms6dtqdyyu3z2tmrq8jg8xglhyuv0dsxzmgs2f0sqy" receiver, amount := parseBitcoinWithdrawArgs(r, args, defaultReceiver) diff --git a/e2e/e2etests/test_bitcoin_withdraw_restricted_address.go b/e2e/e2etests/test_bitcoin_withdraw_restricted_address.go index 84bd11b8de..87610cac09 100644 --- a/e2e/e2etests/test_bitcoin_withdraw_restricted_address.go +++ b/e2e/e2etests/test_bitcoin_withdraw_restricted_address.go @@ -16,8 +16,6 @@ func TestBitcoinWithdrawRestricted(r *runner.E2ERunner, args []string) { withdrawalAmount := parseFloat(r, args[0]) amount := btcAmountFromFloat64(r, withdrawalAmount) - r.SetBtcAddress(r.Name, false) - withdrawBitcoinRestricted(r, amount) } diff --git a/e2e/e2etests/test_bitcoin_withdraw_segwit.go b/e2e/e2etests/test_bitcoin_withdraw_segwit.go index fe30c118f8..6d5c7d4516 100644 --- a/e2e/e2etests/test_bitcoin_withdraw_segwit.go +++ b/e2e/e2etests/test_bitcoin_withdraw_segwit.go @@ -10,8 +10,6 @@ import ( func TestBitcoinWithdrawSegWit(r *runner.E2ERunner, args []string) { require.Len(r, args, 2) - r.SetBtcAddress(r.Name, false) - // parse arguments defaultReceiver := r.BTCDeployerAddress.EncodeAddress() receiver, amount := parseBitcoinWithdrawArgs(r, args, defaultReceiver) diff --git a/e2e/e2etests/test_bitcoin_withdraw_taproot.go b/e2e/e2etests/test_bitcoin_withdraw_taproot.go index f675a88c43..5935bb1986 100644 --- a/e2e/e2etests/test_bitcoin_withdraw_taproot.go +++ b/e2e/e2etests/test_bitcoin_withdraw_taproot.go @@ -10,8 +10,6 @@ import ( func TestBitcoinWithdrawTaproot(r *runner.E2ERunner, args []string) { require.Len(r, args, 2) - r.SetBtcAddress(r.Name, false) - // parse arguments and withdraw BTC defaultReceiver := "bcrt1pqqqsyqcyq5rqwzqfpg9scrgwpugpzysnzs23v9ccrydpk8qarc0sj9hjuh" receiver, amount := parseBitcoinWithdrawArgs(r, args, defaultReceiver) diff --git a/e2e/e2etests/test_migrate_tss.go b/e2e/e2etests/test_migrate_tss.go index 3825228c14..067623a325 100644 --- a/e2e/e2etests/test_migrate_tss.go +++ b/e2e/e2etests/test_migrate_tss.go @@ -20,7 +20,6 @@ import ( ) func TestMigrateTSS(r *runner.E2ERunner, _ []string) { - r.SetBtcAddress(r.Name, false) stop := r.MineBlocksIfLocalBitcoin() defer stop() diff --git a/e2e/e2etests/test_stress_btc_deposit.go b/e2e/e2etests/test_stress_btc_deposit.go index bedf004bdf..ea15d4fa9b 100644 --- a/e2e/e2etests/test_stress_btc_deposit.go +++ b/e2e/e2etests/test_stress_btc_deposit.go @@ -20,8 +20,6 @@ func TestStressBTCDeposit(r *runner.E2ERunner, args []string) { depositAmount := parseFloat(r, args[0]) numDeposits := parseInt(r, args[1]) - r.SetBtcAddress(r.Name, false) - r.Logger.Print("starting stress test of %d deposits", numDeposits) // create a wait group to wait for all the deposits to complete diff --git a/e2e/e2etests/test_stress_btc_withdraw.go b/e2e/e2etests/test_stress_btc_withdraw.go index 52d60430d2..1c02d17bf0 100644 --- a/e2e/e2etests/test_stress_btc_withdraw.go +++ b/e2e/e2etests/test_stress_btc_withdraw.go @@ -22,8 +22,6 @@ func TestStressBTCWithdraw(r *runner.E2ERunner, args []string) { withdrawalAmount := parseFloat(r, args[0]) numWithdraws := parseInt(r, args[1]) - r.SetBtcAddress(r.Name, false) - r.Logger.Print("starting stress test of %d withdraws", numWithdraws) // create a wait group to wait for all the withdraws to complete diff --git a/e2e/runner/accounting.go b/e2e/runner/accounting.go index c47883c3f0..223ca9c8c4 100644 --- a/e2e/runner/accounting.go +++ b/e2e/runner/accounting.go @@ -33,15 +33,20 @@ type Response struct { Amount Amount `json:"amount"` } -func (r *E2ERunner) CheckZRC20ReserveAndSupply() error { - r.Logger.Info("Checking ZRC20 Reserve and Supply") - if err := r.checkEthTSSBalance(); err != nil { - return err - } - if err := r.checkERC20TSSBalance(); err != nil { - return err - } - return r.checkZetaTSSBalance() +func (r *E2ERunner) CheckZRC20BalanceAndSupply() { + r.Logger.Info("Checking ZRC20 Balance vs. Supply") + + err := r.checkEthTSSBalance() + require.NoError(r, err, "ETH balance check failed") + + err = r.checkERC20TSSBalance() + require.NoError(r, err, "ERC20 balance check failed") + + err = r.checkZetaTSSBalance() + require.NoError(r, err, "ZETA balance check failed") + + err = r.CheckBtcTSSBalance() + require.NoError(r, err, "BTC balance check failed") } func (r *E2ERunner) checkEthTSSBalance() error { diff --git a/e2e/runner/balances.go b/e2e/runner/balances.go index 5def04090f..38ac61d70c 100644 --- a/e2e/runner/balances.go +++ b/e2e/runner/balances.go @@ -107,16 +107,7 @@ func (r *E2ERunner) GetAccountBalances(skipBTC bool) (AccountBalances, error) { // GetBitcoinBalance returns the spendable BTC balance of the BTC address func (r *E2ERunner) GetBitcoinBalance() (string, error) { - addr, _, err := r.GetBtcAddress() - if err != nil { - return "", fmt.Errorf("failed to get BTC address: %w", err) - } - - address, err := btcutil.DecodeAddress(addr, r.BitcoinParams) - if err != nil { - return "", fmt.Errorf("failed to decode BTC address: %w", err) - } - + address, _ := r.GetBtcAddress() total, err := r.GetBitcoinBalanceByAddress(address) if err != nil { return "", err diff --git a/e2e/runner/bitcoin.go b/e2e/runner/bitcoin.go index 047e97139b..bec7a1e907 100644 --- a/e2e/runner/bitcoin.go +++ b/e2e/runner/bitcoin.go @@ -14,6 +14,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog/log" "github.com/stretchr/testify/require" @@ -106,7 +107,7 @@ func (r *E2ERunner) DepositBTCWithAmount(amount float64, memo *memo.InboundMemo) if memo != nil { txHash, err = r.DepositBTCWithStandardMemo(amount, utxos, memo) } else { - txHash, err = r.DepositBTCWithLegacyMemo(amount, utxos) + txHash, err = r.DepositBTCWithLegacyMemo(amount, utxos, r.EVMAddress()) } require.NoError(r, err) @@ -115,8 +116,9 @@ func (r *E2ERunner) DepositBTCWithAmount(amount float64, memo *memo.InboundMemo) return txHash } -// DepositBTC deposits BTC on ZetaChain -func (r *E2ERunner) DepositBTC() { +// DepositBTC deposits BTC from the Bitcoin node wallet into ZetaChain. +// Note: This function only works for node wallet based deployer account. +func (r *E2ERunner) DepositBTC(receiver common.Address) { r.Logger.Print("⏳ depositing BTC into ZEVM") startTime := time.Now() defer func() { @@ -130,6 +132,7 @@ func (r *E2ERunner) DepositBTC() { spendableAmount := 0.0 spendableUTXOs := 0 for _, utxo := range utxos { + // 'Spendable' indicates whether we have the private keys to spend this output if utxo.Spendable { spendableAmount += utxo.Amount spendableUTXOs++ @@ -142,27 +145,24 @@ func (r *E2ERunner) DepositBTC() { r.Logger.Info("ListUnspent:") r.Logger.Info(" spendableAmount: %f", spendableAmount) r.Logger.Info(" spendableUTXOs: %d", spendableUTXOs) - r.Logger.Info("Now sending two txs to TSS address...") - - // send two transactions to the TSS address - amount1 := 1.1 + zetabitcoin.DefaultDepositorFee - _, err = r.DepositBTCWithLegacyMemo(amount1, utxos[:2]) - require.NoError(r, err) + r.Logger.Info("Now sending two txs to TSS address and tester ZEVM address...") - amount2 := 0.05 + zetabitcoin.DefaultDepositorFee - txHash2, err := r.DepositBTCWithLegacyMemo(amount2, utxos[2:4]) + // send initial BTC to the tester ZEVM address + amount := 1.15 + zetabitcoin.DefaultDepositorFee + txHash, err := r.DepositBTCWithLegacyMemo(amount, utxos[:2], receiver) require.NoError(r, err) // send a donation to the TSS address to compensate for the funds minted automatically during pool creation // and prevent accounting errors - _, err = r.SendToTSSFromDeployerWithMemo(0.11, utxos[4:5], []byte(constant.DonationMessage)) + // it also serves as gas fee for the TSS to send BTC to other addresses + _, err = r.SendToTSSFromDeployerWithMemo(0.11, utxos[2:4], []byte(constant.DonationMessage)) require.NoError(r, err) r.Logger.Info("testing if the deposit into BTC ZRC20 is successful...") cctx := utils.WaitCctxMinedByInboundHash( r.Ctx, - txHash2.String(), + txHash.String(), r.CctxClient, r.Logger, r.CctxTimeout, @@ -180,11 +180,12 @@ func (r *E2ERunner) DepositBTC() { func (r *E2ERunner) DepositBTCWithLegacyMemo( amount float64, inputUTXOs []btcjson.ListUnspentResult, + receiver common.Address, ) (*chainhash.Hash, error) { r.Logger.Info("⏳ depositing BTC into ZEVM with legacy memo") // payload is not needed for pure deposit - memoBytes := r.EVMAddress().Bytes() + memoBytes := receiver.Bytes() return r.SendToTSSFromDeployerWithMemo(amount, inputUTXOs, memoBytes) } @@ -431,7 +432,7 @@ func (r *E2ERunner) MineBlocksIfLocalBitcoin() func() { _, err := r.GenerateToAddressIfLocalBitcoin(1, r.BTCDeployerAddress) require.NoError(r, err) - time.Sleep(3 * time.Second) + time.Sleep(6 * time.Second) } } }() diff --git a/e2e/runner/logger.go b/e2e/runner/logger.go index 24f9c8f7bc..ba8053de60 100644 --- a/e2e/runner/logger.go +++ b/e2e/runner/logger.go @@ -15,7 +15,7 @@ import ( const ( loggerSeparator = " | " - padding = 10 + padding = 12 ) // Logger is a wrapper around log.Logger that adds verbosity diff --git a/e2e/runner/require.go b/e2e/runner/require.go index 9e296bf748..98496c5f25 100644 --- a/e2e/runner/require.go +++ b/e2e/runner/require.go @@ -24,8 +24,8 @@ func (r *E2ERunner) EnsureNoTrackers() { require.Empty(r, res.OutboundTracker, "there should be no trackers at the end of the test") } -// EnsureZeroBalanceAddressZEVM ensures that the balance of the address is zero in the ZEVM -func (r *E2ERunner) EnsureZeroBalanceAddressZEVM() { +// EnsureZeroBalanceAddressZEVM ensures that the balance of the restricted address is zero in the ZEVM +func (r *E2ERunner) EnsureZeroBalanceOnRestrictedAddressZEVM() { restrictedAddress := ethcommon.HexToAddress(sample.RestrictedEVMAddressTest) // ensure ZETA balance is zero diff --git a/e2e/runner/run.go b/e2e/runner/run.go index c05129b775..fde3de2277 100644 --- a/e2e/runner/run.go +++ b/e2e/runner/run.go @@ -26,11 +26,9 @@ func (r *E2ERunner) RunE2ETest(e2eTest E2ETest, checkAccounting bool) error { } e2eTest.E2ETest(r, args) - //check supplies + // check zrc20 balance vs. supply if checkAccounting { - if err := r.CheckZRC20ReserveAndSupply(); err != nil { - return err - } + r.CheckZRC20BalanceAndSupply() } r.Logger.Print("✅ completed in %s - %s", time.Since(startTime), e2eTest.Description) diff --git a/e2e/runner/setup_bitcoin.go b/e2e/runner/setup_bitcoin.go index 7b4d794f87..88d516e1b7 100644 --- a/e2e/runner/setup_bitcoin.go +++ b/e2e/runner/setup_bitcoin.go @@ -26,78 +26,65 @@ func (r *E2ERunner) AddTSSToNode() { require.NoError(r, err) } -func (r *E2ERunner) SetupBitcoinAccount(initNetwork bool) { - r.Logger.Print("⚙️ setting up Bitcoin account") +// SetupBitcoinAccounts sets up the TSS account and deployer account +func (r *E2ERunner) SetupBitcoinAccounts(createWallet bool) { + r.Logger.Info("⚙️ setting up Bitcoin account") startTime := time.Now() defer func() { r.Logger.Print("✅ Bitcoin account setup in %s", time.Since(startTime)) }() - _, err := r.BtcRPCClient.CreateWallet(r.Name, rpcclient.WithCreateWalletBlank()) - if err != nil { - require.ErrorContains(r, err, "Database already exists") - } - - r.SetBtcAddress(r.Name, true) - - if initNetwork { - // import the TSS address - err = r.BtcRPCClient.ImportAddress(r.BTCTSSAddress.EncodeAddress()) - require.NoError(r, err) + // setup deployer address + r.SetupBtcAddress(r.Name, createWallet) - // mine some blocks to get some BTC into the deployer address - _, err = r.GenerateToAddressIfLocalBitcoin(101, r.BTCDeployerAddress) - require.NoError(r, err) + // import the TSS address to index TSS utxos and transactions + err := r.BtcRPCClient.ImportAddress(r.BTCTSSAddress.EncodeAddress()) + require.NoError(r, err) + r.Logger.Info("⚙️ imported BTC TSSAddress: %s", r.BTCTSSAddress.EncodeAddress()) - _, err = r.GenerateToAddressIfLocalBitcoin(4, r.BTCDeployerAddress) - require.NoError(r, err) - } + // import deployer address to index deployer utxos and transactions + err = r.BtcRPCClient.ImportAddress(r.BTCDeployerAddress.EncodeAddress()) + require.NoError(r, err) + r.Logger.Info("⚙️ imported BTCDeployerAddress: %s", r.BTCDeployerAddress.EncodeAddress()) } -// GetBtcAddress returns the BTC address of the deployer from its EVM private key -func (r *E2ERunner) GetBtcAddress() (string, string, error) { +// GetBtcAddress returns the BTC address of the deployer and private key in WIF format +func (r *E2ERunner) GetBtcAddress() (*btcutil.AddressWitnessPubKeyHash, *btcutil.WIF) { + // load configured private key skBytes, err := hex.DecodeString(r.Account.RawPrivateKey.String()) - if err != nil { - return "", "", err - } + require.NoError(r, err) + // create private key in WIF format sk, _ := btcec.PrivKeyFromBytes(skBytes) privkeyWIF, err := btcutil.NewWIF(sk, r.BitcoinParams, true) - if err != nil { - return "", "", err - } + require.NoError(r, err) + // derive address from private key address, err := btcutil.NewAddressWitnessPubKeyHash( btcutil.Hash160(privkeyWIF.SerializePubKey()), r.BitcoinParams, ) - if err != nil { - return "", "", err - } + require.NoError(r, err) - // return the string representation of the address - return address.EncodeAddress(), privkeyWIF.String(), nil + return address, privkeyWIF } -// SetBtcAddress imports the deployer's private key into the Bitcoin node -func (r *E2ERunner) SetBtcAddress(name string, rescan bool) { - skBytes, err := hex.DecodeString(r.Account.RawPrivateKey.String()) - require.NoError(r, err) +// SetupBtcAddress setups the deployer Bitcoin address +func (r *E2ERunner) SetupBtcAddress(name string, setupWallet bool) { + // set the deployer address + address, privkeyWIF := r.GetBtcAddress() + r.BTCDeployerAddress = address - sk, _ := btcec.PrivKeyFromBytes(skBytes) - privkeyWIF, err := btcutil.NewWIF(sk, r.BitcoinParams, true) - require.NoError(r, err) + r.Logger.Info("BTCDeployerAddress: %s, %v", r.BTCDeployerAddress.EncodeAddress(), setupWallet) - if rescan { - err := r.BtcRPCClient.ImportPrivKeyRescan(privkeyWIF, name, true) + // import the deployer private key as a Bitcoin node wallet + if setupWallet { + _, err := r.BtcRPCClient.CreateWallet(r.Name, rpcclient.WithCreateWalletBlank()) + if err != nil { + require.ErrorContains(r, err, "Database already exists") + } + + err = r.BtcRPCClient.ImportPrivKeyRescan(privkeyWIF, name, true) require.NoError(r, err, "failed to execute ImportPrivKeyRescan") } - - r.BTCDeployerAddress, err = btcutil.NewAddressWitnessPubKeyHash( - btcutil.Hash160(privkeyWIF.PrivKey.PubKey().SerializeCompressed()), - r.BitcoinParams, - ) - require.NoError(r, err) - - r.Logger.Info("BTCDeployerAddress: %s", r.BTCDeployerAddress.EncodeAddress()) } diff --git a/x/observer/types/chain_params.go b/x/observer/types/chain_params.go index b1a5335e58..b76af2da49 100644 --- a/x/observer/types/chain_params.go +++ b/x/observer/types/chain_params.go @@ -290,7 +290,7 @@ func GetDefaultBtcRegtestChainParams() *ChainParams { WatchUtxoTicker: 1, InboundTicker: 1, OutboundTicker: 2, - OutboundScheduleInterval: 2, + OutboundScheduleInterval: 1, OutboundScheduleLookahead: 5, BallotThreshold: DefaultBallotThreshold, MinObserverDelegation: DefaultMinObserverDelegation,