Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(e2e): TestBitcoinDepositRefund, WithdrawBitcoinMultipleTimes #2349

Merged
merged 22 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -248,11 +248,13 @@ start-upgrade-test-light: zetanode-upgrade
@echo "--> Starting light upgrade test (no ZetaChain state populating before upgrade)"
cd contrib/localnet/ && $(DOCKER) compose -f docker-compose.yml -f docker-compose-upgrade.yml -f docker-compose-upgrade-light.yml up -d

start-localnet: zetanode
start-localnet: zetanode start-localnet-skip-build

start-localnet-skip-build:
@echo "--> Starting localnet"
cd contrib/localnet/ && $(DOCKER) compose -f docker-compose.yml -f docker-compose-setup-only.yml up -d

stop-test:
stop-localnet:
cd contrib/localnet/ && $(DOCKER) compose down --remove-orphans

###############################################################################
Expand Down
23 changes: 19 additions & 4 deletions cmd/zetae2e/stress.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"math/big"
"os"
"sort"
"sync"
"time"

sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -225,11 +226,25 @@ func StressTest(cmd *cobra.Command, _ []string) {
fmt.Println(" 1. Periodically Withdraw ETH from ZEVM to EVM")
fmt.Println(" 2. Display Network metrics to monitor performance [Num Pending outbound tx], [Num Trackers]")

e2eTest.WG.Add(2)
go WithdrawCCtx(e2eTest) // Withdraw from ZEVM to EVM
go EchoNetworkMetrics(e2eTest) // Display Network metrics periodically to monitor performance
var wg sync.WaitGroup

e2eTest.WG.Wait()
wg.Add(2)

go func() {
defer wg.Done()

// Withdraw from ZEVM to EVM
WithdrawCCtx(e2eTest)
}()

go func() {
defer wg.Done()

// Display Network metrics periodically to monitor performance
EchoNetworkMetrics(e2eTest)
}()

wg.Wait()
}

// WithdrawCCtx withdraw ETHZRC20 from ZEVM to EVM
Expand Down
2 changes: 1 addition & 1 deletion docs/development/LOCAL_TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ $ docker logs -f orchestrator

To stop the tests,
```bash
make stop-test
make stop-localnet
```

### Run monitoring setup
Expand Down
37 changes: 31 additions & 6 deletions e2e/README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
# `e2e`

`e2e` is a comprehensive suite of E2E tests designed to validate the integration and functionality of the ZetaChain network, particularly its interactions with Bitcoin and EVM (Ethereum Virtual Machine) networks. This tool is essential for ensuring the robustness and reliability of ZetaChain's cross-chain functionalities.
`e2e` is a comprehensive suite of E2E tests designed to validate the integration and functionality of the ZetaChain
swift1337 marked this conversation as resolved.
Show resolved Hide resolved
network, particularly its interactions with Bitcoin and EVM (Ethereum Virtual Machine) networks. This tool is essential
for ensuring the robustness and reliability of ZetaChain's cross-chain functionalities.

## Packages

The E2E testing project is organized into several packages, each with a specific role:

- `config`: Provides general configuration for E2E tests, including RPC addresses for connected networks, addresses of deployed smart contracts, and account details for test transactions.
- `config`: Provides general configuration for E2E tests, including RPC addresses for connected networks, addresses of
deployed smart contracts, and account details for test transactions.
- `contracts`: Includes sample Solidity smart contracts used in testing scenarios.
- `runner`: Responsible for executing E2E tests, handling interactions with various network clients.
- `e2etests`: Houses a collection of E2E tests that can be run against the ZetaChain network. Each test is implemented as a separate Go file prefixed with `test_`.
- `e2etests`: Houses a collection of E2E tests that can be run against the ZetaChain network. Each test is implemented
as a separate Go file prefixed with `test_`.
- `txserver`: A minimalistic client for interacting with the ZetaChain RPC interface.
- `utils`: Offers utility functions to facilitate interactions with the different blockchain networks involved in testing.
- `utils`: Offers utility functions to facilitate interactions with the different blockchain networks involved in
testing.

## Config

The E2E testing suite utilizes a flexible and comprehensive configuration system defined in the config package, which is central to setting up and customizing your test environments. The configuration is structured as follows:
The E2E testing suite utilizes a flexible and comprehensive configuration system defined in the config package, which is
central to setting up and customizing your test environments. The configuration is structured as follows:

A config YAML file can be provided to the E2E test tool via the `--config` flag. If no config file is provided, the tool will use default values for all configuration parameters.
A config YAML file can be provided to the E2E test tool via the `--config` flag. If no config file is provided, the tool
will use default values for all configuration parameters.

### Config Structure

- `RPCs`: Defines the RPC endpoints for various networks involved in the testing.
- `Contracts`: Specifies the addresses of pre-deployed smart contracts relevant to the tests.
- `ZetaChainID`: The specific chain ID of the ZetaChain network being tested.
Expand All @@ -34,6 +43,7 @@ A config YAML file can be provided to the E2E test tool via the `--config` flag.
### Contracts Configuration:

**EVM Contracts**

- `ZetaEthAddress`: Address of Zeta token contract on EVM chain.
- `ConnectorEthAddr`: Address of a connector contract on EVM chain.
- `ERC20`: Address of the ERC20 token contract on EVM chain.
Expand All @@ -56,3 +66,18 @@ zeta_chain_id: "zetachain-1"
```

NOTE: config is in progress, contracts on the zEVM must be added

## Debugging

It's possible to debug a single test using Delve debugger.

1. Make sure delve is installed. `go install github.com/go-delve/delve/cmd/dlv@latest`
2. Configure your IDE to use Delve as the debugger. For Goland, you can do the following:
- Go to "Run" > "Edit Run Configurations"
- Hit "+" > "Go Remote". Keep port as default (`2345`). Toggle "On Disconnect" > "Stop Delve process"
3. Make sure that localnet is running. For a quick start, you can use `make start-localnet-skip-build`.
Networks need some time to generate blocks.
4. Run test as following: `./e2e/scripts/debug.sh my_test_name arg1 arg2 arg_n`.
Example: `./e2e/scripts/debug.sh bitcoin_withdraw_restricted 0.001`
5. Place a breakpoint in the code.
6. Go to the editor's debug panel and hit "Debug" button.
8 changes: 8 additions & 0 deletions e2e/e2etests/e2etests.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package e2etests

import (
"github.com/zeta-chain/zetacore/e2e/runner"

Check failure on line 4 in e2e/e2etests/e2etests.go

View workflow job for this annotation

GitHub Actions / lint

could not import github.com/zeta-chain/zetacore/e2e/runner (-: # github.com/zeta-chain/zetacore/e2e/runner
)

// List of all e2e test names to be used in zetae2e
Expand Down Expand Up @@ -56,6 +56,7 @@
Test transfer of Bitcoin asset across chains
*/
TestBitcoinDepositName = "bitcoin_deposit"
TestBitcoinDepositRefund = "bitcoin_deposit_refund"
lumtis marked this conversation as resolved.
Show resolved Hide resolved
TestBitcoinWithdrawSegWitName = "bitcoin_withdraw_segwit"
TestBitcoinWithdrawTaprootName = "bitcoin_withdraw_taproot"
TestBitcoinWithdrawLegacyName = "bitcoin_withdraw_legacy"
Expand Down Expand Up @@ -332,6 +333,13 @@
},
TestBitcoinDeposit,
),
runner.NewE2ETest(
TestBitcoinDepositRefund,
lumtis marked this conversation as resolved.
Show resolved Hide resolved
"deposit Bitcoin into ZEVM; expect refund", []runner.ArgDefinition{
{Description: "amount in btc", DefaultValue: "0.001"},
},
TestDepositBTCRefund,
lumtis marked this conversation as resolved.
Show resolved Hide resolved
),
runner.NewE2ETest(
TestBitcoinWithdrawSegWitName,
"withdraw BTC from ZEVM to a SegWit address",
Expand Down
38 changes: 12 additions & 26 deletions e2e/e2etests/helper_bitcoin.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package e2etests

import (
"fmt"
"math/big"
"strconv"

"github.com/btcsuite/btcd/btcjson"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcutil"
"github.com/stretchr/testify/require"

"github.com/zeta-chain/zetacore/e2e/runner"
"github.com/zeta-chain/zetacore/e2e/utils"
Expand Down Expand Up @@ -55,50 +55,36 @@ func withdrawBTCZRC20(r *runner.E2ERunner, to btcutil.Address, amount *big.Int)
r.BTCZRC20Addr,
big.NewInt(amount.Int64()*2),
) // approve more to cover withdraw fee
if err != nil {
panic(err)
}
require.NoError(r, err)

receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout)
if receipt.Status != 1 {
panic(fmt.Errorf("approve receipt status is not 1"))
}
require.Equal(r, uint64(1), receipt.Status, "approve receipt status is not 1")
swift1337 marked this conversation as resolved.
Show resolved Hide resolved

// mine blocks if testing on regnet
stop := r.MineBlocksIfLocalBitcoin()

// withdraw 'amount' of BTC from ZRC20 to BTC address
tx, err = r.BTCZRC20.Withdraw(r.ZEVMAuth, []byte(to.EncodeAddress()), amount)
if err != nil {
panic(err)
}
require.NoError(r, err)

receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout)
if receipt.Status != 1 {
panic(fmt.Errorf("withdraw receipt status is not 1"))
}
require.Equal(r, uint64(1), receipt.Status, "withdraw receipt status is not 1")

// mine 10 blocks to confirm the withdraw tx
// mine 10 blocks to confirm the withdrawal tx
_, err = r.GenerateToAddressIfLocalBitcoin(10, to)
if err != nil {
panic(err)
}
require.NoError(r, err)

// get cctx and check status
cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, receipt.TxHash.Hex(), r.CctxClient, r.Logger, r.CctxTimeout)
if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_OutboundMined {
panic(fmt.Errorf("cctx status is not OutboundMined"))
}
require.Equal(r, crosschaintypes.CctxStatus_OutboundMined, cctx.CctxStatus.Status, "cctx status is not OutboundMined")

// get bitcoin tx according to the outTxHash in cctx
outTxHash := cctx.GetCurrentOutboundParam().Hash
hash, err := chainhash.NewHashFromStr(outTxHash)
if err != nil {
panic(err)
}
require.NoError(r, err)

rawTx, err := r.BtcRPCClient.GetRawTransactionVerbose(hash)
if err != nil {
panic(err)
}
require.NoError(r, err)
r.Logger.Info("raw tx:")
r.Logger.Info(" TxIn: %d", len(rawTx.Vin))
for idx, txIn := range rawTx.Vin {
Expand Down
93 changes: 39 additions & 54 deletions e2e/e2etests/test_bitcoin_deposit_refund.go
Original file line number Diff line number Diff line change
@@ -1,56 +1,41 @@
package e2etests

// DepositBTCRefund ...
// TODO: define e2e test
// https://github.com/zeta-chain/node-private/issues/79
//func DepositBTCRefund(r *runner.E2ERunner) {
// r.Logger.InfoLoud("Deposit BTC with invalid memo; should be refunded")
// btc := r.BtcRPCClient
// utxos, err := r.BtcRPCClient.ListUnspent()
// if err != nil {
// panic(err)
// }
// spendableAmount := 0.0
// spendableUTXOs := 0
// for _, utxo := range utxos {
// if utxo.Spendable {
// spendableAmount += utxo.Amount
// spendableUTXOs++
// }
// }
// 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...")
// _, err = r.SendToTSSFromDeployerToDeposit(r.BTCTSSAddress, 1.1, utxos[:2], btc, r.BTCDeployerAddress)
// if err != nil {
// panic(err)
// }
// _, err = r.SendToTSSFromDeployerToDeposit(r.BTCTSSAddress, 0.05, utxos[2:4], btc, r.BTCDeployerAddress)
// if err != nil {
// panic(err)
// }
//
// r.Logger.Info("testing if the deposit into BTC ZRC20 is successful...")
//
// // check if the deposit is successful
// initialBalance, err := r.BTCZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress)
// if err != nil {
// panic(err)
// }
// for {
// time.Sleep(3 * time.Second)
// balance, err := r.BTCZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress)
// if err != nil {
// panic(err)
// }
// diff := big.NewInt(0)
// diff.Sub(balance, initialBalance)
// if diff.Cmp(big.NewInt(1.15*btcutil.SatoshiPerBitcoin)) != 0 {
// r.Logger.Info("waiting for BTC balance to show up in ZRC contract... current bal %d", balance)
// } else {
// r.Logger.Info("BTC balance is in ZRC contract! Success")
// break
// }
// }
//}
import (
"strconv"

"github.com/stretchr/testify/require"
"github.com/zeta-chain/zetacore/e2e/runner"
"github.com/zeta-chain/zetacore/e2e/utils"
)

func TestDepositBTCRefund(r *runner.E2ERunner, args []string) {
swift1337 marked this conversation as resolved.
Show resolved Hide resolved
// ARRANGE
swift1337 marked this conversation as resolved.
Show resolved Hide resolved
// Given amount to send
require.Len(r, args, 1)
swift1337 marked this conversation as resolved.
Show resolved Hide resolved
amount := parseFloat(r, args[0])

// Given BTC address
r.SetBtcAddress(r.Name, false)

// Given a list of UTXOs
utxos, err := r.BtcRPCClient.ListUnspent()
require.NoError(r, err)
require.NotEmpty(r, utxos)

// ACT
// Send a single UTXO to TSS address
txHash, err := r.SendToTSSFromDeployerWithMemo(amount, utxos, []byte("gibberish-memo"))
require.NotEmpty(r, err)

// Wait for processing in zetaclient
utils.WaitCctxMinedByInboundHash(r.Ctx, txHash.String(), r.CctxClient, r.Logger, r.CctxTimeout)

// ASSERT
// todo...
}

func parseFloat(t require.TestingT, s string) float64 {
swift1337 marked this conversation as resolved.
Show resolved Hide resolved
f, err := strconv.ParseFloat(s, 64)
require.NoError(t, err, "unable to parse float %q", s)
return f
}
14 changes: 11 additions & 3 deletions e2e/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@
Ctx context.Context
CtxCancel context.CancelFunc
Logger *Logger
WG sync.WaitGroup
BitcoinParams *chaincfg.Params
mutex sync.Mutex
}
Expand Down Expand Up @@ -158,8 +157,6 @@
BtcRPCClient: btcRPCClient,

Logger: logger,

WG: sync.WaitGroup{},
}
}

Expand Down Expand Up @@ -285,3 +282,14 @@
runner.Logger.Print("ERC20: %s", runner.ERC20Addr.Hex())
runner.Logger.Print("TestDappEVM: %s", runner.EvmTestDAppAddr.Hex())
}

// Errorf logs an error message. Mimics the behavior of testing.T.Errorf
func (runner *E2ERunner) Errorf(format string, args ...any) {
swift1337 marked this conversation as resolved.
Show resolved Hide resolved
runner.Logger.Error(format, args...)
}

// FailNow implemented to mimic the behavior of testing.T.FailNow
func (runner *E2ERunner) FailNow() {
runner.Logger.Error("Test failed")
os.Exit(1)

Check failure on line 294 in e2e/runner/runner.go

View workflow job for this annotation

GitHub Actions / lint

undefined: os (typecheck)

Check failure on line 294 in e2e/runner/runner.go

View workflow job for this annotation

GitHub Actions / lint

undefined: os) (typecheck)

Check failure on line 294 in e2e/runner/runner.go

View workflow job for this annotation

GitHub Actions / lint

undefined: os) (typecheck)

Check failure on line 294 in e2e/runner/runner.go

View workflow job for this annotation

GitHub Actions / lint

undefined: os) (typecheck)

Check failure on line 294 in e2e/runner/runner.go

View workflow job for this annotation

GitHub Actions / gosec-cosmos

undefined: os

Check failure on line 294 in e2e/runner/runner.go

View workflow job for this annotation

GitHub Actions / gosec

undefined: os

Check failure on line 294 in e2e/runner/runner.go

View workflow job for this annotation

GitHub Actions / build-and-test

undefined: os

Check failure on line 294 in e2e/runner/runner.go

View workflow job for this annotation

GitHub Actions / build-and-test

undefined: os
}
7 changes: 3 additions & 4 deletions e2e/runner/setup_bitcoin.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/rpcclient"
"github.com/btcsuite/btcutil"
"github.com/stretchr/testify/require"
)

func (runner *E2ERunner) SetupBitcoinAccount(initNetwork bool) {
Expand Down Expand Up @@ -85,10 +86,8 @@ func (runner *E2ERunner) SetBtcAddress(name string, rescan bool) {
}

if rescan {
err = runner.BtcRPCClient.ImportPrivKeyRescan(privkeyWIF, name, true)
if err != nil {
panic(err)
}
err := runner.BtcRPCClient.ImportPrivKeyRescan(privkeyWIF, name, true)
require.NoError(runner, err, "failed to execute ImportPrivKeyRescan")
}

runner.BTCDeployerAddress, err = btcutil.NewAddressWitnessPubKeyHash(
Expand Down
Loading
Loading