From 98c63b92cd3ef20d90afdb8093a7b24adb84ad03 Mon Sep 17 00:00:00 2001 From: Alex Gartner Date: Thu, 27 Jun 2024 09:39:17 -0700 Subject: [PATCH 1/7] refactor(e2e): move addresses and private keys to config (#2308) * refactor(e2e): move all addresses and private keys to config * localnet config and inject into orchestrator * zetacored from config * generate keys in init * fmt * docs * more lint fixes * s/deployer/default_account/ * trim prefix --- Dockerfile-localnet | 3 +- cmd/zetae2e/README.md | 8 +- cmd/zetae2e/balances.go | 12 +- cmd/zetae2e/bitcoin_address.go | 12 +- cmd/zetae2e/config/clients.go | 17 +- cmd/zetae2e/config/config.go | 42 ++-- cmd/zetae2e/config/config_test.go | 40 +++ cmd/zetae2e/config/contracts.go | 125 +++++----- cmd/zetae2e/config/example.yml | 4 +- cmd/zetae2e/config/local.yml | 5 +- cmd/zetae2e/config/localnet.yml | 51 ++++ cmd/zetae2e/init.go | 13 +- cmd/zetae2e/local/accounts.go | 44 ---- cmd/zetae2e/local/admin.go | 8 +- cmd/zetae2e/local/bitcoin.go | 6 +- cmd/zetae2e/local/config.go | 8 +- cmd/zetae2e/local/erc20.go | 6 +- cmd/zetae2e/local/ethereum.go | 3 +- cmd/zetae2e/local/local.go | 5 +- cmd/zetae2e/local/misc.go | 6 +- cmd/zetae2e/local/performance.go | 6 +- cmd/zetae2e/local/test_runner.go | 8 +- cmd/zetae2e/local/zeta.go | 6 +- cmd/zetae2e/local/zevm_mp.go | 6 +- cmd/zetae2e/run.go | 10 +- cmd/zetae2e/setup_bitcoin.go | 11 +- cmd/zetae2e/show_tss.go | 12 +- cmd/zetae2e/stress.go | 32 +-- .../orchestrator/Dockerfile.fastbuild | 3 +- .../localnet/orchestrator/start-zetae2e.sh | 50 ++-- contrib/localnet/scripts/start-zetacored.sh | 27 +- e2e/config/config.go | 230 ++++++++++++++++-- e2e/config/config_test.go | 39 +++ e2e/e2etests/test_context_upgrade.go | 2 +- e2e/e2etests/test_crosschain_swap.go | 8 +- e2e/e2etests/test_erc20_deposit.go | 2 +- e2e/e2etests/test_erc20_deposit_refund.go | 16 +- e2e/e2etests/test_erc20_multiple_deposits.go | 6 +- e2e/e2etests/test_erc20_multiple_withdraws.go | 4 +- e2e/e2etests/test_eth_deposit_call.go | 7 +- .../test_eth_deposit_liquidity_cap.go | 8 +- e2e/e2etests/test_eth_deposit_refund.go | 7 +- .../test_message_passing_external_chains.go | 2 +- ...age_passing_external_chains_revert_fail.go | 2 +- e2e/e2etests/test_migrate_chain_support.go | 19 +- e2e/e2etests/test_rate_limiter.go | 2 +- e2e/e2etests/test_stress_eth_withdraw.go | 2 +- e2e/e2etests/test_update_bytecode_zrc20.go | 8 +- e2e/e2etests/test_zeta_deposit.go | 2 +- .../test_zeta_withdraw_bitcoin_revert.go | 2 +- e2e/e2etests/test_zrc20_swap.go | 8 +- e2e/runner/balances.go | 18 +- e2e/runner/bitcoin.go | 4 +- e2e/runner/evm.go | 7 +- e2e/runner/runner.go | 15 +- e2e/runner/setup_bitcoin.go | 4 +- e2e/runner/setup_evm.go | 18 +- e2e/runner/zeta.go | 8 +- 58 files changed, 631 insertions(+), 408 deletions(-) create mode 100644 cmd/zetae2e/config/config_test.go create mode 100644 cmd/zetae2e/config/localnet.yml delete mode 100644 cmd/zetae2e/local/accounts.go create mode 100644 e2e/config/config_test.go diff --git a/Dockerfile-localnet b/Dockerfile-localnet index bacf8c19a4..1ed82c6b98 100644 --- a/Dockerfile-localnet +++ b/Dockerfile-localnet @@ -28,7 +28,7 @@ RUN go install cosmossdk.io/tools/cosmovisor/cmd/cosmovisor@v1.5.0 FROM golang:1.20.14-bookworm AS base-runtime RUN apt update && \ - apt install -yq jq curl tmux python3 openssh-server iputils-ping iproute2 && \ + apt install -yq jq yq curl tmux python3 openssh-server iputils-ping iproute2 && \ rm -rf /var/lib/apt/lists/* RUN ssh-keygen -A && \ @@ -46,6 +46,7 @@ ENV PATH /root/.zetacored/cosmovisor/current/bin/:/root/.zetaclientd/upgrades/cu COPY contrib/localnet/scripts /root COPY contrib/localnet/ssh_config /etc/ssh/ssh_config.d/localnet.conf COPY contrib/localnet/zetacored /root/zetacored +COPY cmd/zetae2e/config/localnet.yml /root/config.yml RUN chmod 755 /root/*.sh && \ chmod 644 /etc/ssh/ssh_config.d/localnet.conf diff --git a/cmd/zetae2e/README.md b/cmd/zetae2e/README.md index c57863e7cf..bdc043f7d2 100644 --- a/cmd/zetae2e/README.md +++ b/cmd/zetae2e/README.md @@ -24,9 +24,9 @@ This is an example of config for interaction with Athens3: ```go zeta_chain_id: "athens_7001-1" -accounts: +default_account: evm_address: "" - evm_priv_key: "" + private_key: "" rpcs: zevm: ", generally using port 8545" evm: ", generally using port 8545" @@ -101,9 +101,9 @@ Testing a gas token requires the following values to be defined in the config: ```go zeta_chain_id -accounts: +default_account: evm_address - evm_priv_key + private_key rpcs: zevm evm diff --git a/cmd/zetae2e/balances.go b/cmd/zetae2e/balances.go index bf1b543227..13df89430a 100644 --- a/cmd/zetae2e/balances.go +++ b/cmd/zetae2e/balances.go @@ -2,9 +2,7 @@ package main import ( "context" - "errors" - ethcommon "github.com/ethereum/go-ethereum/common" "github.com/fatih/color" "github.com/spf13/cobra" @@ -54,21 +52,13 @@ func runBalances(cmd *cobra.Command, args []string) error { // initialize context ctx, cancel := context.WithCancel(context.Background()) - // get EVM address from config - evmAddr := conf.Accounts.EVMAddress - if !ethcommon.IsHexAddress(evmAddr) { - cancel() - return errors.New("invalid EVM address") - } - // initialize deployer runner with config r, err := zetae2econfig.RunnerFromConfig( ctx, "e2e", cancel, conf, - ethcommon.HexToAddress(evmAddr), - conf.Accounts.EVMPrivKey, + conf.DefaultAccount, logger, ) if err != nil { diff --git a/cmd/zetae2e/bitcoin_address.go b/cmd/zetae2e/bitcoin_address.go index 63eb26d386..6c9c5c3f4a 100644 --- a/cmd/zetae2e/bitcoin_address.go +++ b/cmd/zetae2e/bitcoin_address.go @@ -2,9 +2,7 @@ package main import ( "context" - "errors" - ethcommon "github.com/ethereum/go-ethereum/common" "github.com/fatih/color" "github.com/spf13/cobra" @@ -54,21 +52,13 @@ func runBitcoinAddress(cmd *cobra.Command, args []string) error { // initialize context ctx, cancel := context.WithCancel(context.Background()) - // get EVM address from config - evmAddr := conf.Accounts.EVMAddress - if !ethcommon.IsHexAddress(evmAddr) { - cancel() - return errors.New("invalid EVM address") - } - // initialize deployer runner with config r, err := zetae2econfig.RunnerFromConfig( ctx, "e2e", cancel, conf, - ethcommon.HexToAddress(evmAddr), - conf.Accounts.EVMPrivKey, + conf.DefaultAccount, logger, ) if err != nil { diff --git a/cmd/zetae2e/config/clients.go b/cmd/zetae2e/config/clients.go index ae56eaa9dd..8c6bb37106 100644 --- a/cmd/zetae2e/config/clients.go +++ b/cmd/zetae2e/config/clients.go @@ -8,7 +8,6 @@ import ( 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" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "google.golang.org/grpc" @@ -20,7 +19,7 @@ import ( ) // getClientsFromConfig get clients from config -func getClientsFromConfig(ctx context.Context, conf config.Config, evmPrivKey string) ( +func getClientsFromConfig(ctx context.Context, conf config.Config, account config.Account) ( *rpcclient.Client, *ethclient.Client, *bind.TransactOpts, @@ -38,7 +37,7 @@ func getClientsFromConfig(ctx context.Context, conf config.Config, evmPrivKey st if err != nil { return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get btc client: %w", err) } - evmClient, evmAuth, err := getEVMClient(ctx, conf.RPCs.EVM, evmPrivKey) + evmClient, evmAuth, err := getEVMClient(ctx, conf.RPCs.EVM, account) if err != nil { return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get evm client: %w", err) } @@ -48,7 +47,7 @@ func getClientsFromConfig(ctx context.Context, conf config.Config, evmPrivKey st if err != nil { return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get zeta clients: %w", err) } - zevmClient, zevmAuth, err := getEVMClient(ctx, conf.RPCs.Zevm, evmPrivKey) + zevmClient, zevmAuth, err := getEVMClient(ctx, conf.RPCs.Zevm, account) if err != nil { return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get zevm client: %w", err) } @@ -91,7 +90,11 @@ func getBtcClient(rpcConf config.BitcoinRPC) (*rpcclient.Client, error) { } // getEVMClient get evm client -func getEVMClient(ctx context.Context, rpc, privKey string) (*ethclient.Client, *bind.TransactOpts, error) { +func getEVMClient( + ctx context.Context, + rpc string, + account config.Account, +) (*ethclient.Client, *bind.TransactOpts, error) { evmClient, err := ethclient.Dial(rpc) if err != nil { return nil, nil, fmt.Errorf("failed to dial evm client: %w", err) @@ -101,11 +104,11 @@ func getEVMClient(ctx context.Context, rpc, privKey string) (*ethclient.Client, if err != nil { return nil, nil, fmt.Errorf("failed to get chain id: %w", err) } - deployerPrivkey, err := crypto.HexToECDSA(privKey) + privKey, err := account.PrivateKey() if err != nil { return nil, nil, fmt.Errorf("failed to get deployer privkey: %w", err) } - evmAuth, err := bind.NewKeyedTransactorWithChainID(deployerPrivkey, chainid) + evmAuth, err := bind.NewKeyedTransactorWithChainID(privKey, chainid) if err != nil { return nil, nil, fmt.Errorf("failed to get keyed transactor: %w", err) } diff --git a/cmd/zetae2e/config/config.go b/cmd/zetae2e/config/config.go index 7918a9a9ae..a0aedef1a6 100644 --- a/cmd/zetae2e/config/config.go +++ b/cmd/zetae2e/config/config.go @@ -4,8 +4,6 @@ import ( "context" "fmt" - ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/zeta-chain/zetacore/e2e/config" "github.com/zeta-chain/zetacore/e2e/runner" ) @@ -16,8 +14,7 @@ func RunnerFromConfig( name string, ctxCancel context.CancelFunc, conf config.Config, - evmUserAddr ethcommon.Address, - evmUserPrivKey string, + account config.Account, logger *runner.Logger, opts ...runner.E2ERunnerOption, ) (*runner.E2ERunner, error) { @@ -33,7 +30,7 @@ func RunnerFromConfig( lightClient, zevmClient, zevmAuth, - err := getClientsFromConfig(ctx, conf, evmUserPrivKey) + err := getClientsFromConfig(ctx, conf, account) if err != nil { return nil, fmt.Errorf("failed to get clients from config: %w", err) } @@ -43,8 +40,7 @@ func RunnerFromConfig( ctx, name, ctxCancel, - evmUserAddr, - evmUserPrivKey, + account, evmClient, zevmClient, cctxClient, @@ -79,23 +75,23 @@ func RunnerFromConfig( // ExportContractsFromRunner export contracts from the runner to config using a source config func ExportContractsFromRunner(r *runner.E2ERunner, conf config.Config) config.Config { // copy contracts from deployer runner - conf.Contracts.EVM.ZetaEthAddress = r.ZetaEthAddr.Hex() - conf.Contracts.EVM.ConnectorEthAddr = r.ConnectorEthAddr.Hex() - conf.Contracts.EVM.CustodyAddr = r.ERC20CustodyAddr.Hex() - conf.Contracts.EVM.ERC20 = r.ERC20Addr.Hex() - conf.Contracts.EVM.TestDappAddr = r.EvmTestDAppAddr.Hex() + conf.Contracts.EVM.ZetaEthAddr = config.DoubleQuotedString(r.ZetaEthAddr.Hex()) + conf.Contracts.EVM.ConnectorEthAddr = config.DoubleQuotedString(r.ConnectorEthAddr.Hex()) + conf.Contracts.EVM.CustodyAddr = config.DoubleQuotedString(r.ERC20CustodyAddr.Hex()) + conf.Contracts.EVM.ERC20 = config.DoubleQuotedString(r.ERC20Addr.Hex()) + conf.Contracts.EVM.TestDappAddr = config.DoubleQuotedString(r.EvmTestDAppAddr.Hex()) - conf.Contracts.ZEVM.SystemContractAddr = r.SystemContractAddr.Hex() - conf.Contracts.ZEVM.ETHZRC20Addr = r.ETHZRC20Addr.Hex() - conf.Contracts.ZEVM.ERC20ZRC20Addr = r.ERC20ZRC20Addr.Hex() - conf.Contracts.ZEVM.BTCZRC20Addr = r.BTCZRC20Addr.Hex() - conf.Contracts.ZEVM.UniswapFactoryAddr = r.UniswapV2FactoryAddr.Hex() - conf.Contracts.ZEVM.UniswapRouterAddr = r.UniswapV2RouterAddr.Hex() - conf.Contracts.ZEVM.ConnectorZEVMAddr = r.ConnectorZEVMAddr.Hex() - conf.Contracts.ZEVM.WZetaAddr = r.WZetaAddr.Hex() - conf.Contracts.ZEVM.ZEVMSwapAppAddr = r.ZEVMSwapAppAddr.Hex() - conf.Contracts.ZEVM.ContextAppAddr = r.ContextAppAddr.Hex() - conf.Contracts.ZEVM.TestDappAddr = r.ZevmTestDAppAddr.Hex() + conf.Contracts.ZEVM.SystemContractAddr = config.DoubleQuotedString(r.SystemContractAddr.Hex()) + conf.Contracts.ZEVM.ETHZRC20Addr = config.DoubleQuotedString(r.ETHZRC20Addr.Hex()) + conf.Contracts.ZEVM.ERC20ZRC20Addr = config.DoubleQuotedString(r.ERC20ZRC20Addr.Hex()) + conf.Contracts.ZEVM.BTCZRC20Addr = config.DoubleQuotedString(r.BTCZRC20Addr.Hex()) + conf.Contracts.ZEVM.UniswapFactoryAddr = config.DoubleQuotedString(r.UniswapV2FactoryAddr.Hex()) + conf.Contracts.ZEVM.UniswapRouterAddr = config.DoubleQuotedString(r.UniswapV2RouterAddr.Hex()) + conf.Contracts.ZEVM.ConnectorZEVMAddr = config.DoubleQuotedString(r.ConnectorZEVMAddr.Hex()) + conf.Contracts.ZEVM.WZetaAddr = config.DoubleQuotedString(r.WZetaAddr.Hex()) + conf.Contracts.ZEVM.ZEVMSwapAppAddr = config.DoubleQuotedString(r.ZEVMSwapAppAddr.Hex()) + conf.Contracts.ZEVM.ContextAppAddr = config.DoubleQuotedString(r.ContextAppAddr.Hex()) + conf.Contracts.ZEVM.TestDappAddr = config.DoubleQuotedString(r.ZevmTestDAppAddr.Hex()) return conf } diff --git a/cmd/zetae2e/config/config_test.go b/cmd/zetae2e/config/config_test.go new file mode 100644 index 0000000000..f8eb98a01e --- /dev/null +++ b/cmd/zetae2e/config/config_test.go @@ -0,0 +1,40 @@ +package config + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/zeta-chain/zetacore/e2e/config" +) + +func TestReadConfig(t *testing.T) { + tests := []struct { + name string + filePath string + expectNoError bool + expectNotEmpty bool + }{ + { + name: "ReadLocalnetConfig", + filePath: "localnet.yml", + expectNoError: true, + expectNotEmpty: true, + }, + { + name: "ReadLocalConfig", + filePath: "local.yml", + expectNoError: true, + expectNotEmpty: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + conf, err := config.ReadConfig(tt.filePath) + require.NoError(t, err) + require.NotEmpty(t, conf.DefaultAccount.RawEVMAddress) + require.NotEmpty(t, conf.DefaultAccount.RawPrivateKey) + }) + } +} diff --git a/cmd/zetae2e/config/contracts.go b/cmd/zetae2e/config/contracts.go index a47b39ef4e..110038298a 100644 --- a/cmd/zetae2e/config/contracts.go +++ b/cmd/zetae2e/config/contracts.go @@ -3,7 +3,6 @@ package config import ( "fmt" - ethcommon "github.com/ethereum/go-ethereum/common" "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/erc20custody.sol" zetaeth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zeta.eth.sol" zetaconnectoreth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zetaconnector.eth.sol" @@ -26,169 +25,173 @@ func setContractsFromConfig(r *runner.E2ERunner, conf config.Config) error { var err error // set EVM contracts - if c := conf.Contracts.EVM.ZetaEthAddress; c != "" { - if !ethcommon.IsHexAddress(c) { - return fmt.Errorf("invalid ZetaEthAddress: %s", c) + if c := conf.Contracts.EVM.ZetaEthAddr; c != "" { + r.ZetaEthAddr, err = c.AsEVMAddress() + if err != nil { + return fmt.Errorf("invalid ZetaEthAddr: %w", err) } - r.ZetaEthAddr = ethcommon.HexToAddress(c) r.ZetaEth, err = zetaeth.NewZetaEth(r.ZetaEthAddr, r.EVMClient) if err != nil { return err } } + if c := conf.Contracts.EVM.ConnectorEthAddr; c != "" { - if !ethcommon.IsHexAddress(c) { - return fmt.Errorf("invalid ConnectorEthAddr: %s", c) + r.ConnectorEthAddr, err = c.AsEVMAddress() + if err != nil { + return fmt.Errorf("invalid ConnectorEthAddr: %w", err) } - r.ConnectorEthAddr = ethcommon.HexToAddress(c) r.ConnectorEth, err = zetaconnectoreth.NewZetaConnectorEth(r.ConnectorEthAddr, r.EVMClient) if err != nil { return err } } + if c := conf.Contracts.EVM.CustodyAddr; c != "" { - if !ethcommon.IsHexAddress(c) { - return fmt.Errorf("invalid CustodyAddr: %s", c) + r.ERC20CustodyAddr, err = c.AsEVMAddress() + if err != nil { + return fmt.Errorf("invalid CustodyAddr: %w", err) } - r.ERC20CustodyAddr = ethcommon.HexToAddress(c) r.ERC20Custody, err = erc20custody.NewERC20Custody(r.ERC20CustodyAddr, r.EVMClient) if err != nil { return err } } + if c := conf.Contracts.EVM.ERC20; c != "" { - if !ethcommon.IsHexAddress(c) { - return fmt.Errorf("invalid ERC20: %s", c) + r.ERC20Addr, err = c.AsEVMAddress() + if err != nil { + return fmt.Errorf("invalid ERC20: %w", err) } - r.ERC20Addr = ethcommon.HexToAddress(c) r.ERC20, err = erc20.NewERC20(r.ERC20Addr, r.EVMClient) if err != nil { return err } } - // set Zevm contracts + // set ZEVM contracts if c := conf.Contracts.ZEVM.SystemContractAddr; c != "" { - if !ethcommon.IsHexAddress(c) { - return fmt.Errorf("invalid SystemContractAddr: %s", c) + r.SystemContractAddr, err = c.AsEVMAddress() + if err != nil { + return fmt.Errorf("invalid SystemContractAddr: %w", err) } - r.SystemContractAddr = ethcommon.HexToAddress(c) r.SystemContract, err = systemcontract.NewSystemContract(r.SystemContractAddr, r.ZEVMClient) if err != nil { return err } } + if c := conf.Contracts.ZEVM.ETHZRC20Addr; c != "" { - if !ethcommon.IsHexAddress(c) { - return fmt.Errorf("invalid ETHZRC20Addr: %s", c) + r.ETHZRC20Addr, err = c.AsEVMAddress() + if err != nil { + return fmt.Errorf("invalid ETHZRC20Addr: %w", err) } - r.ETHZRC20Addr = ethcommon.HexToAddress(c) r.ETHZRC20, err = zrc20.NewZRC20(r.ETHZRC20Addr, r.ZEVMClient) if err != nil { return err } } + if c := conf.Contracts.ZEVM.ERC20ZRC20Addr; c != "" { - if !ethcommon.IsHexAddress(c) { - return fmt.Errorf("invalid ERC20ZRC20Addr: %s", c) + r.ERC20ZRC20Addr, err = c.AsEVMAddress() + if err != nil { + return fmt.Errorf("invalid ERC20ZRC20Addr: %w", err) } - r.ERC20ZRC20Addr = ethcommon.HexToAddress(c) r.ERC20ZRC20, err = zrc20.NewZRC20(r.ERC20ZRC20Addr, r.ZEVMClient) if err != nil { return err } } + if c := conf.Contracts.ZEVM.BTCZRC20Addr; c != "" { - if !ethcommon.IsHexAddress(c) { - return fmt.Errorf("invalid BTCZRC20Addr: %s", c) - } - r.BTCZRC20Addr = ethcommon.HexToAddress(c) - r.BTCZRC20, err = zrc20.NewZRC20(r.BTCZRC20Addr, r.ZEVMClient) + r.BTCZRC20Addr, err = c.AsEVMAddress() if err != nil { - return err - } - } - if c := conf.Contracts.ZEVM.ERC20ZRC20Addr; c != "" { - if !ethcommon.IsHexAddress(c) { - return fmt.Errorf("invalid ERC20ZRC20Addr: %s", c) + return fmt.Errorf("invalid BTCZRC20Addr: %w", err) } - r.ERC20ZRC20Addr = ethcommon.HexToAddress(c) - r.ERC20ZRC20, err = zrc20.NewZRC20(r.ERC20ZRC20Addr, r.ZEVMClient) + r.BTCZRC20, err = zrc20.NewZRC20(r.BTCZRC20Addr, r.ZEVMClient) if err != nil { return err } } + if c := conf.Contracts.ZEVM.UniswapFactoryAddr; c != "" { - if !ethcommon.IsHexAddress(c) { - return fmt.Errorf("invalid UniswapFactoryAddr: %s", c) + r.UniswapV2FactoryAddr, err = c.AsEVMAddress() + if err != nil { + return fmt.Errorf("invalid UniswapFactoryAddr: %w", err) } - r.UniswapV2FactoryAddr = ethcommon.HexToAddress(c) r.UniswapV2Factory, err = uniswapv2factory.NewUniswapV2Factory(r.UniswapV2FactoryAddr, r.ZEVMClient) if err != nil { return err } } + if c := conf.Contracts.ZEVM.UniswapRouterAddr; c != "" { - if !ethcommon.IsHexAddress(c) { - return fmt.Errorf("invalid UniswapRouterAddr: %s", c) + r.UniswapV2RouterAddr, err = c.AsEVMAddress() + if err != nil { + return fmt.Errorf("invalid UniswapRouterAddr: %w", err) } - r.UniswapV2RouterAddr = ethcommon.HexToAddress(c) r.UniswapV2Router, err = uniswapv2router.NewUniswapV2Router02(r.UniswapV2RouterAddr, r.ZEVMClient) if err != nil { return err } } + if c := conf.Contracts.ZEVM.ConnectorZEVMAddr; c != "" { - if !ethcommon.IsHexAddress(c) { - return fmt.Errorf("invalid ConnectorZEVMAddr: %s", c) + r.ConnectorZEVMAddr, err = c.AsEVMAddress() + if err != nil { + return fmt.Errorf("invalid ConnectorZEVMAddr: %w", err) } - r.ConnectorZEVMAddr = ethcommon.HexToAddress(c) r.ConnectorZEVM, err = connectorzevm.NewZetaConnectorZEVM(r.ConnectorZEVMAddr, r.ZEVMClient) if err != nil { return err } } + if c := conf.Contracts.ZEVM.WZetaAddr; c != "" { - if !ethcommon.IsHexAddress(c) { - return fmt.Errorf("invalid WZetaAddr: %s", c) + r.WZetaAddr, err = c.AsEVMAddress() + if err != nil { + return fmt.Errorf("invalid WZetaAddr: %w", err) } - r.WZetaAddr = ethcommon.HexToAddress(c) r.WZeta, err = wzeta.NewWETH9(r.WZetaAddr, r.ZEVMClient) if err != nil { return err } } + if c := conf.Contracts.ZEVM.ZEVMSwapAppAddr; c != "" { - if !ethcommon.IsHexAddress(c) { - return fmt.Errorf("invalid ZEVMSwapAppAddr: %s", c) + r.ZEVMSwapAppAddr, err = c.AsEVMAddress() + if err != nil { + return fmt.Errorf("invalid ZEVMSwapAppAddr: %w", err) } - r.ZEVMSwapAppAddr = ethcommon.HexToAddress(c) r.ZEVMSwapApp, err = zevmswap.NewZEVMSwapApp(r.ZEVMSwapAppAddr, r.ZEVMClient) if err != nil { return err } } + if c := conf.Contracts.ZEVM.ContextAppAddr; c != "" { - if !ethcommon.IsHexAddress(c) { - return fmt.Errorf("invalid ContextAppAddr: %s", c) + r.ContextAppAddr, err = c.AsEVMAddress() + if err != nil { + return fmt.Errorf("invalid ContextAppAddr: %w", err) } - r.ContextAppAddr = ethcommon.HexToAddress(c) r.ContextApp, err = contextapp.NewContextApp(r.ContextAppAddr, r.ZEVMClient) if err != nil { return err } } + if c := conf.Contracts.ZEVM.TestDappAddr; c != "" { - if !ethcommon.IsHexAddress(c) { - return fmt.Errorf("invalid ZevmTestDappAddr: %s", c) + r.ZevmTestDAppAddr, err = c.AsEVMAddress() + if err != nil { + return fmt.Errorf("invalid ZevmTestDappAddr: %w", err) } - r.ZevmTestDAppAddr = ethcommon.HexToAddress(c) } + if c := conf.Contracts.EVM.TestDappAddr; c != "" { - if !ethcommon.IsHexAddress(c) { - return fmt.Errorf("invalid EvmTestDappAddr: %s", c) + r.EvmTestDAppAddr, err = c.AsEVMAddress() + if err != nil { + return fmt.Errorf("invalid EvmTestDappAddr: %w", err) } - r.EvmTestDAppAddr = ethcommon.HexToAddress(c) } return nil diff --git a/cmd/zetae2e/config/example.yml b/cmd/zetae2e/config/example.yml index be692b9d4c..21cdd6de36 100644 --- a/cmd/zetae2e/config/example.yml +++ b/cmd/zetae2e/config/example.yml @@ -1,7 +1,7 @@ zeta_chain_id: "athens_7001-1" -accounts: +default_account: evm_address: "" - evm_priv_key: "" + private_key: "" rpcs: zevm: ", generally using port 8545" evm: ", generally using port 8545" diff --git a/cmd/zetae2e/config/local.yml b/cmd/zetae2e/config/local.yml index ae2638ace7..ee5e171ccc 100644 --- a/cmd/zetae2e/config/local.yml +++ b/cmd/zetae2e/config/local.yml @@ -1,7 +1,8 @@ zeta_chain_id: "athens_7001-1" -accounts: +default_account: + bech32_address: zeta1uhznv7uzyjq84s3q056suc8pkme85lkvhrz3dd evm_address: "0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC" - evm_priv_key: "d87baf7bf6dc560a252596678c12e41f7d1682837f05b29d411bc3f78ae2c263" + private_key: "d87baf7bf6dc560a252596678c12e41f7d1682837f05b29d411bc3f78ae2c263" rpcs: zevm: "http://0.0.0.0:9545" evm: "http://0.0.0.0:8545" diff --git a/cmd/zetae2e/config/localnet.yml b/cmd/zetae2e/config/localnet.yml new file mode 100644 index 0000000000..abb780db39 --- /dev/null +++ b/cmd/zetae2e/config/localnet.yml @@ -0,0 +1,51 @@ +zeta_chain_id: "athens_101-1" +default_account: + bech32_address: "zeta1uhznv7uzyjq84s3q056suc8pkme85lkvhrz3dd" + evm_address: "0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC" + private_key: "d87baf7bf6dc560a252596678c12e41f7d1682837f05b29d411bc3f78ae2c263" +additional_accounts: + user_erc20: + bech32_address: "zeta1datate7xmwm4uk032f9rmcu0cwy7ch7kg6y6zv" + evm_address: "0x6F57D5E7c6DBb75e59F1524a3dE38Fc389ec5Fd6" + private_key: "fda3be1b1517bdf48615bdadacc1e6463d2865868dc8077d2cdcfa4709a16894" + user_zeta_test: + bech32_address: "zeta1tnp0hvsq4y5mxuhrq9h3jfwulxywpq0ads0rer" + evm_address: "0x5cC2fBb200A929B372e3016F1925DcF988E081fd" + private_key: "729a6cdc5c925242e7df92fdeeb94dadbf2d0b9950d4db8f034ab27a3b114ba7" + user_zevm_mp_test: + bech32_address: "zeta13t3zjxvwec7g38q8mdjga37rpes9zkfvv7tkn2" + evm_address: "0x8Ae229198eCE3c889C07DB648Ec7C30E6051592c" + private_key: "105460aebf71b10bfdb710ef5aa6d2932ee6ff6fc317ac9c24e0979903b10a5d" + user_bitcoin: + bech32_address: "zeta19q7czqysah6qg0n4y3l2a08gfzqxydla492v80" + evm_address: "0x283d810090EdF4043E75247eAeBcE848806237fD" + private_key: "7bb523963ee2c78570fb6113d886a4184d42565e8847f1cb639f5f5e2ef5b37a" + user_ether: + bech32_address: "zeta134rakuus43xn63yucgxhn88ywj8ewcv6ezn2ga" + evm_address: "0x8D47Db7390AC4D3D449Cc20D799ce4748F97619A" + private_key: "098e74a1c2261fa3c1b8cfca8ef2b4ff96c73ce36710d208d1f6535aef42545d" + user_misc: + bech32_address: "zeta1jqfx6qhyrj0t9ggvl3p64vaax3s9y0xldt020w" + evm_address: "0x90126d02E41c9eB2a10cfc43aAb3BD3460523Cdf" + private_key: "853c0945b8035a501b1161df65a17a0a20fc848bda8975a8b4e9222cc6f84cd4" + user_admin: + bech32_address: "zeta17w0adeg64ky0daxwd2ugyuneellmjgnx4e483s" + evm_address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + private_key: "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" + user_fungible_admin: + bech32_address: "zeta1svzuz982w09vf2y08xsh8qplj36phyz466krj3" + evm_address: "0x8305C114Ea73cAc4A88f39A173803F94741b9055" + private_key: "d88d09a7d6849c15a36eb6931f9dd616091a63e9849a2cc86f309ba11fb8fec5" +rpcs: + zevm: "http://zetacore0:8545" + evm: "http://eth:8545" + bitcoin: + host: "bitcoin:18443" + user: "smoketest" + pass: "123" + http_post_mode: true + disable_tls: true + params: regnet + zetacore_grpc: "zetacore0:9090" + zetacore_rpc: "http://zetacore0:26657" +# contracts will be populated on first run \ No newline at end of file diff --git a/cmd/zetae2e/init.go b/cmd/zetae2e/init.go index b35f42ff97..742b3ebd96 100644 --- a/cmd/zetae2e/init.go +++ b/cmd/zetae2e/init.go @@ -16,7 +16,7 @@ func NewInitCmd() *cobra.Command { var InitCmd = &cobra.Command{ Use: "init", Short: "initialize config file for e2e tests", - Run: initConfig, + RunE: initConfig, } InitCmd.Flags().StringVar(&initConf.RPCs.EVM, "ethURL", "http://eth:8545", "--ethURL http://eth:8545") @@ -33,9 +33,14 @@ func NewInitCmd() *cobra.Command { return InitCmd } -func initConfig(_ *cobra.Command, _ []string) { - err := config.WriteConfig(configFile, initConf) +func initConfig(_ *cobra.Command, _ []string) error { + err := initConf.GenerateKeys() if err != nil { - fmt.Printf("error writing config file: %s", err.Error()) + return fmt.Errorf("generating keys: %w", err) } + err = config.WriteConfig(configFile, initConf) + if err != nil { + return fmt.Errorf("writing config: %w", err) + } + return nil } diff --git a/cmd/zetae2e/local/accounts.go b/cmd/zetae2e/local/accounts.go deleted file mode 100644 index 16ab7d97a4..0000000000 --- a/cmd/zetae2e/local/accounts.go +++ /dev/null @@ -1,44 +0,0 @@ -package local - -import ( - ethcommon "github.com/ethereum/go-ethereum/common" -) - -var ( - // DeployerAddress is the address of the account for deploying networks - DeployerAddress = ethcommon.HexToAddress("0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC") - DeployerPrivateKey = "d87baf7bf6dc560a252596678c12e41f7d1682837f05b29d411bc3f78ae2c263" // #nosec G101 - used for testing - - // UserERC20Address is the address of the account for testing ERC20 - UserERC20Address = ethcommon.HexToAddress("0x6F57D5E7c6DBb75e59F1524a3dE38Fc389ec5Fd6") - UserERC20PrivateKey = "fda3be1b1517bdf48615bdadacc1e6463d2865868dc8077d2cdcfa4709a16894" // #nosec G101 - used for testing - - // UserZetaTestAddress is the address of the account for testing Zeta transfers - UserZetaTestAddress = ethcommon.HexToAddress("0x5cC2fBb200A929B372e3016F1925DcF988E081fd") - UserZetaTestPrivateKey = "729a6cdc5c925242e7df92fdeeb94dadbf2d0b9950d4db8f034ab27a3b114ba7" // #nosec G101 - used for testing - - // UserZEVMMPTestAddress is the address of the account for testing ZEVM Message Passing - UserZEVMMPTestAddress = ethcommon.HexToAddress("0x8Ae229198eCE3c889C07DB648Ec7C30E6051592c") - UserZEVMMPTestPrivateKey = "105460aebf71b10bfdb710ef5aa6d2932ee6ff6fc317ac9c24e0979903b10a5d" // #nosec G101 - used for testing - - // UserBitcoinAddress is the address of the account for testing Bitcoin - UserBitcoinAddress = ethcommon.HexToAddress("0x283d810090EdF4043E75247eAeBcE848806237fD") - UserBitcoinPrivateKey = "7bb523963ee2c78570fb6113d886a4184d42565e8847f1cb639f5f5e2ef5b37a" // #nosec G101 - used for testing - - // UserEtherAddress is the address of the account for testing Ether - UserEtherAddress = ethcommon.HexToAddress("0x8D47Db7390AC4D3D449Cc20D799ce4748F97619A") - UserEtherPrivateKey = "098e74a1c2261fa3c1b8cfca8ef2b4ff96c73ce36710d208d1f6535aef42545d" // #nosec G101 - used for testing - - // UserMiscAddress is the address of the account for miscellaneous tests - UserMiscAddress = ethcommon.HexToAddress("0x90126d02E41c9eB2a10cfc43aAb3BD3460523Cdf") - UserMiscPrivateKey = "853c0945b8035a501b1161df65a17a0a20fc848bda8975a8b4e9222cc6f84cd4" // #nosec G101 - used for testing - - // UserAdminAddress is the address of the account for testing admin function features - // NOTE: this is the default account using Anvil - UserAdminAddress = ethcommon.HexToAddress("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266") - UserAdminPrivateKey = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" // #nosec G101 - used for testing - - // FungibleAdminAddress is the address of the account for testing the fungible admin functions - UserFungibleAdminAddress = ethcommon.HexToAddress("0x8305C114Ea73cAc4A88f39A173803F94741b9055") - UserFungibleAdminPrivateKey = "d88d09a7d6849c15a36eb6931f9dd616091a63e9849a2cc86f309ba11fb8fec5" // #nosec G101 - used for testing -) diff --git a/cmd/zetae2e/local/admin.go b/cmd/zetae2e/local/admin.go index 63cff6fe23..bc76aeeedc 100644 --- a/cmd/zetae2e/local/admin.go +++ b/cmd/zetae2e/local/admin.go @@ -19,13 +19,13 @@ func adminTestRoutine( testNames ...string, ) func() error { return func() (err error) { + account := conf.AdditionalAccounts.UserAdmin // initialize runner for erc20 advanced test adminRunner, err := initTestRunner( "admin", conf, deployerRunner, - UserAdminAddress, - UserAdminPrivateKey, + account, runner.NewLogger(verbose, color.FgHiGreen, "admin"), runner.WithZetaTxServer(deployerRunner.ZetaTxServer), ) @@ -38,8 +38,8 @@ func adminTestRoutine( // funding the account // we transfer around the total supply of Zeta to the admin for the chain migration test - txZetaSend := deployerRunner.SendZetaOnEvm(UserAdminAddress, 20_500_000_000) - txERC20Send := deployerRunner.SendERC20OnEvm(UserAdminAddress, 1000) + txZetaSend := deployerRunner.SendZetaOnEvm(account.EVMAddress(), 20_500_000_000) + txERC20Send := deployerRunner.SendERC20OnEvm(account.EVMAddress(), 1000) adminRunner.WaitForTxReceiptOnEvm(txZetaSend) adminRunner.WaitForTxReceiptOnEvm(txERC20Send) diff --git a/cmd/zetae2e/local/bitcoin.go b/cmd/zetae2e/local/bitcoin.go index cfb0501a8c..05098fd5a9 100644 --- a/cmd/zetae2e/local/bitcoin.go +++ b/cmd/zetae2e/local/bitcoin.go @@ -21,13 +21,13 @@ func bitcoinTestRoutine( testNames ...string, ) func() error { return func() (err error) { + account := conf.AdditionalAccounts.UserBitcoin // initialize runner for bitcoin test bitcoinRunner, err := initTestRunner( "bitcoin", conf, deployerRunner, - UserBitcoinAddress, - UserBitcoinPrivateKey, + account, runner.NewLogger(verbose, color.FgYellow, "bitcoin"), ) if err != nil { @@ -38,7 +38,7 @@ func bitcoinTestRoutine( startTime := time.Now() // funding the account - txERC20Send := deployerRunner.SendERC20OnEvm(UserBitcoinAddress, 1000) + txERC20Send := deployerRunner.SendERC20OnEvm(account.EVMAddress(), 1000) bitcoinRunner.WaitForTxReceiptOnEvm(txERC20Send) // depositing the necessary tokens on ZetaChain diff --git a/cmd/zetae2e/local/config.go b/cmd/zetae2e/local/config.go index 98ece83ac0..8788024b7d 100644 --- a/cmd/zetae2e/local/config.go +++ b/cmd/zetae2e/local/config.go @@ -1,6 +1,7 @@ package local import ( + "fmt" "path/filepath" sdk "github.com/cosmos/cosmos-sdk/types" @@ -14,12 +15,7 @@ import ( func GetConfig(cmd *cobra.Command) (config.Config, error) { configFile, err := cmd.Flags().GetString(FlagConfigFile) if err != nil { - return config.Config{}, err - } - - // use default config if no config file is specified - if configFile == "" { - return config.DefaultConfig(), nil + return config.Config{}, fmt.Errorf("--config is a required parameter") } configFile, err = filepath.Abs(configFile) diff --git a/cmd/zetae2e/local/erc20.go b/cmd/zetae2e/local/erc20.go index fe0fa8bb8a..8b0d21e564 100644 --- a/cmd/zetae2e/local/erc20.go +++ b/cmd/zetae2e/local/erc20.go @@ -19,13 +19,13 @@ func erc20TestRoutine( testNames ...string, ) func() error { return func() (err error) { + account := conf.AdditionalAccounts.UserERC20 // initialize runner for erc20 test erc20Runner, err := initTestRunner( "erc20", conf, deployerRunner, - UserERC20Address, - UserERC20PrivateKey, + account, runner.NewLogger(verbose, color.FgGreen, "erc20"), runner.WithZetaTxServer(deployerRunner.ZetaTxServer), ) @@ -37,7 +37,7 @@ func erc20TestRoutine( startTime := time.Now() // funding the account - txERC20Send := deployerRunner.SendERC20OnEvm(UserERC20Address, 10) + txERC20Send := deployerRunner.SendERC20OnEvm(account.EVMAddress(), 10) erc20Runner.WaitForTxReceiptOnEvm(txERC20Send) // depositing the necessary tokens on ZetaChain diff --git a/cmd/zetae2e/local/ethereum.go b/cmd/zetae2e/local/ethereum.go index fa9e7754e2..ae2eebc268 100644 --- a/cmd/zetae2e/local/ethereum.go +++ b/cmd/zetae2e/local/ethereum.go @@ -25,8 +25,7 @@ func ethereumTestRoutine( "ether", conf, deployerRunner, - UserEtherAddress, - UserEtherPrivateKey, + conf.AdditionalAccounts.UserEther, runner.NewLogger(verbose, color.FgMagenta, "ether"), ) if err != nil { diff --git a/cmd/zetae2e/local/local.go b/cmd/zetae2e/local/local.go index bd9dd654a2..7e00f9ba5b 100644 --- a/cmd/zetae2e/local/local.go +++ b/cmd/zetae2e/local/local.go @@ -127,7 +127,7 @@ func localE2ETest(cmd *cobra.Command, _ []string) { zetaTxServer, err := txserver.NewZetaTxServer( conf.RPCs.ZetaCoreRPC, []string{utils.FungibleAdminName}, - []string{UserFungibleAdminPrivateKey}, + []string{conf.AdditionalAccounts.UserFungibleAdmin.RawPrivateKey.String()}, conf.ZetaChainID, ) noError(err) @@ -138,8 +138,7 @@ func localE2ETest(cmd *cobra.Command, _ []string) { "deployer", cancel, conf, - DeployerAddress, - DeployerPrivateKey, + conf.DefaultAccount, logger, runner.WithZetaTxServer(zetaTxServer), ) diff --git a/cmd/zetae2e/local/misc.go b/cmd/zetae2e/local/misc.go index 65467ec9e5..a27c93c932 100644 --- a/cmd/zetae2e/local/misc.go +++ b/cmd/zetae2e/local/misc.go @@ -19,13 +19,13 @@ func miscTestRoutine( testNames ...string, ) func() error { return func() (err error) { + account := conf.AdditionalAccounts.UserMisc // initialize runner for misc test miscRunner, err := initTestRunner( "misc", conf, deployerRunner, - UserMiscAddress, - UserMiscPrivateKey, + account, runner.NewLogger(verbose, color.FgCyan, "misc"), ) if err != nil { @@ -36,7 +36,7 @@ func miscTestRoutine( startTime := time.Now() // funding the account - txZetaSend := deployerRunner.SendZetaOnEvm(UserMiscAddress, 1000) + txZetaSend := deployerRunner.SendZetaOnEvm(account.EVMAddress(), 1000) miscRunner.WaitForTxReceiptOnEvm(txZetaSend) // depositing the necessary tokens on ZetaChain diff --git a/cmd/zetae2e/local/performance.go b/cmd/zetae2e/local/performance.go index 7d289c4e90..4039084550 100644 --- a/cmd/zetae2e/local/performance.go +++ b/cmd/zetae2e/local/performance.go @@ -27,8 +27,7 @@ func ethereumDepositPerformanceRoutine( "ether", conf, deployerRunner, - UserERC20Address, - UserERC20PrivateKey, + conf.AdditionalAccounts.UserERC20, runner.NewLogger(verbose, color.FgHiMagenta, "perf_eth_deposit"), ) if err != nil { @@ -69,8 +68,7 @@ func ethereumWithdrawPerformanceRoutine( "ether", conf, deployerRunner, - UserEtherAddress, - UserEtherPrivateKey, + conf.AdditionalAccounts.UserEther, runner.NewLogger(verbose, color.FgHiBlue, "perf_eth_withdraw"), ) if err != nil { diff --git a/cmd/zetae2e/local/test_runner.go b/cmd/zetae2e/local/test_runner.go index f2fe0ae811..198260c05c 100644 --- a/cmd/zetae2e/local/test_runner.go +++ b/cmd/zetae2e/local/test_runner.go @@ -1,8 +1,6 @@ package local import ( - ethcommon "github.com/ethereum/go-ethereum/common" - zetae2econfig "github.com/zeta-chain/zetacore/cmd/zetae2e/config" "github.com/zeta-chain/zetacore/e2e/config" "github.com/zeta-chain/zetacore/e2e/runner" @@ -14,8 +12,7 @@ func initTestRunner( name string, conf config.Config, deployerRunner *runner.E2ERunner, - userAddress ethcommon.Address, - userPrivKey string, + account config.Account, logger *runner.Logger, opts ...runner.E2ERunnerOption, ) (*runner.E2ERunner, error) { @@ -25,8 +22,7 @@ func initTestRunner( name, deployerRunner.CtxCancel, conf, - userAddress, - userPrivKey, + account, logger, opts..., ) diff --git a/cmd/zetae2e/local/zeta.go b/cmd/zetae2e/local/zeta.go index 6f5039b63f..3fdb4f48cc 100644 --- a/cmd/zetae2e/local/zeta.go +++ b/cmd/zetae2e/local/zeta.go @@ -19,13 +19,13 @@ func zetaTestRoutine( testNames ...string, ) func() error { return func() (err error) { + account := conf.AdditionalAccounts.UserZetaTest // initialize runner for zeta test zetaRunner, err := initTestRunner( "zeta", conf, deployerRunner, - UserZetaTestAddress, - UserZetaTestPrivateKey, + account, runner.NewLogger(verbose, color.FgBlue, "zeta"), ) if err != nil { @@ -36,7 +36,7 @@ func zetaTestRoutine( startTime := time.Now() // funding the account - txZetaSend := deployerRunner.SendZetaOnEvm(UserZetaTestAddress, 1000) + txZetaSend := deployerRunner.SendZetaOnEvm(account.EVMAddress(), 1000) zetaRunner.WaitForTxReceiptOnEvm(txZetaSend) // depositing the necessary tokens on ZetaChain diff --git a/cmd/zetae2e/local/zevm_mp.go b/cmd/zetae2e/local/zevm_mp.go index f95fa24390..bc97c45e29 100644 --- a/cmd/zetae2e/local/zevm_mp.go +++ b/cmd/zetae2e/local/zevm_mp.go @@ -19,13 +19,13 @@ func zevmMPTestRoutine( testNames ...string, ) func() error { return func() (err error) { + account := conf.AdditionalAccounts.UserZEVMMPTest // initialize runner for zevm mp test zevmMPRunner, err := initTestRunner( "zevm_mp", conf, deployerRunner, - UserZEVMMPTestAddress, - UserZEVMMPTestPrivateKey, + account, runner.NewLogger(verbose, color.FgHiRed, "zevm_mp"), ) if err != nil { @@ -36,7 +36,7 @@ func zevmMPTestRoutine( startTime := time.Now() // funding the account - txZetaSend := deployerRunner.SendZetaOnEvm(UserZEVMMPTestAddress, 1000) + txZetaSend := deployerRunner.SendZetaOnEvm(account.EVMAddress(), 1000) zevmMPRunner.WaitForTxReceiptOnEvm(txZetaSend) // depositing the necessary tokens on ZetaChain diff --git a/cmd/zetae2e/run.go b/cmd/zetae2e/run.go index 7d57500823..9c36d8e3d2 100644 --- a/cmd/zetae2e/run.go +++ b/cmd/zetae2e/run.go @@ -8,7 +8,6 @@ import ( "strings" "time" - ethcommon "github.com/ethereum/go-ethereum/common" "github.com/fatih/color" "github.com/spf13/cobra" @@ -75,20 +74,13 @@ func runE2ETest(cmd *cobra.Command, args []string) error { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - // get EVM address from config - evmAddr := conf.Accounts.EVMAddress - if !ethcommon.IsHexAddress(evmAddr) { - return errors.New("invalid EVM address") - } - // initialize deployer runner with config testRunner, err := zetae2econfig.RunnerFromConfig( ctx, "e2e", cancel, conf, - ethcommon.HexToAddress(evmAddr), - conf.Accounts.EVMPrivKey, + conf.DefaultAccount, logger, ) if err != nil { diff --git a/cmd/zetae2e/setup_bitcoin.go b/cmd/zetae2e/setup_bitcoin.go index f77924e768..99a5365adc 100644 --- a/cmd/zetae2e/setup_bitcoin.go +++ b/cmd/zetae2e/setup_bitcoin.go @@ -2,9 +2,7 @@ package main import ( "context" - "errors" - ethcommon "github.com/ethereum/go-ethereum/common" "github.com/fatih/color" "github.com/spf13/cobra" @@ -42,20 +40,13 @@ func runSetupBitcoin(_ *cobra.Command, args []string) error { // initialize context ctx, cancel := context.WithCancel(context.Background()) - // get EVM address from config - evmAddr := conf.Accounts.EVMAddress - if !ethcommon.IsHexAddress(evmAddr) { - cancel() - return errors.New("invalid EVM address") - } // initialize deployer runner with config r, err := zetae2econfig.RunnerFromConfig( ctx, "e2e", cancel, conf, - ethcommon.HexToAddress(evmAddr), - conf.Accounts.EVMPrivKey, + conf.DefaultAccount, logger, ) if err != nil { diff --git a/cmd/zetae2e/show_tss.go b/cmd/zetae2e/show_tss.go index 780a525b19..01b61317a1 100644 --- a/cmd/zetae2e/show_tss.go +++ b/cmd/zetae2e/show_tss.go @@ -2,9 +2,7 @@ package main import ( "context" - "errors" - ethcommon "github.com/ethereum/go-ethereum/common" "github.com/fatih/color" "github.com/spf13/cobra" @@ -42,21 +40,13 @@ func runShowTSS(_ *cobra.Command, args []string) error { // initialize context ctx, cancel := context.WithCancel(context.Background()) - // get EVM address from config - evmAddr := conf.Accounts.EVMAddress - if !ethcommon.IsHexAddress(evmAddr) { - cancel() - return errors.New("invalid EVM address") - } - // initialize deployer runner with config testRunner, err := zetae2econfig.RunnerFromConfig( ctx, "tss", cancel, conf, - ethcommon.HexToAddress(evmAddr), - conf.Accounts.EVMPrivKey, + conf.DefaultAccount, logger, ) if err != nil { diff --git a/cmd/zetae2e/stress.go b/cmd/zetae2e/stress.go index ca0446cbc9..30b2faf924 100644 --- a/cmd/zetae2e/stress.go +++ b/cmd/zetae2e/stress.go @@ -12,7 +12,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/accounts/abi/bind" - ethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/fatih/color" "github.com/spf13/cobra" @@ -38,12 +37,10 @@ var ( ) type stressArguments struct { - deployerAddress string - deployerPrivateKey string - network string - txnInterval int64 - contractsDeployed bool - config string + network string + txnInterval int64 + contractsDeployed bool + config string } var stressTestArgs = stressArguments{} @@ -57,10 +54,6 @@ func NewStressTestCmd() *cobra.Command { Run: StressTest, } - StressCmd.Flags(). - StringVar(&stressTestArgs.deployerAddress, "addr", "0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC", "--addr ") - StressCmd.Flags(). - StringVar(&stressTestArgs.deployerPrivateKey, "privKey", "d87baf7bf6dc560a252596678c12e41f7d1682837f05b29d411bc3f78ae2c263", "--privKey ") StressCmd.Flags().StringVar(&stressTestArgs.network, "network", "LOCAL", "--network TESTNET") StressCmd.Flags(). Int64Var(&stressTestArgs.txnInterval, "tx-interval", 500, "--tx-interval [TIME_INTERVAL_MILLISECONDS]") @@ -69,8 +62,6 @@ func NewStressTestCmd() *cobra.Command { StressCmd.Flags().StringVar(&stressTestArgs.config, local.FlagConfigFile, "", "config file to use for the E2E test") StressCmd.Flags().Bool(flagVerbose, false, "set to true to enable verbose logging") - local.DeployerAddress = ethcommon.HexToAddress(stressTestArgs.deployerAddress) - return StressCmd } @@ -93,11 +84,13 @@ func StressTest(cmd *cobra.Command, _ []string) { // initialize E2E tests config conf := must(local.GetConfig(cmd)) + deployerAccount := conf.DefaultAccount + // Initialize clients ---------------------------------------------------------------- evmClient := must(ethclient.Dial(conf.RPCs.EVM)) - bal := must(evmClient.BalanceAt(context.TODO(), local.DeployerAddress, nil)) + bal := must(evmClient.BalanceAt(context.TODO(), deployerAccount.EVMAddress(), nil)) - fmt.Printf("Deployer address: %s, balance: %d Wei\n", local.DeployerAddress.Hex(), bal) + fmt.Printf("Deployer address: %s, balance: %d Wei\n", deployerAccount.EVMAddress().Hex(), bal) grpcConn := must(grpc.Dial(conf.RPCs.ZetaCoreGRPC, grpc.WithInsecure())) @@ -136,8 +129,7 @@ func StressTest(cmd *cobra.Command, _ []string) { "deployer", cancel, conf, - local.DeployerAddress, - local.DeployerPrivateKey, + conf.DefaultAccount, logger, )) @@ -164,7 +156,7 @@ func StressTest(cmd *cobra.Command, _ []string) { } // Check zrc20 balance of Deployer address - ethZRC20Balance := must(e2eTest.ETHZRC20.BalanceOf(nil, local.DeployerAddress)) + ethZRC20Balance := must(e2eTest.ETHZRC20.BalanceOf(nil, deployerAccount.EVMAddress())) fmt.Printf("eth zrc20 balance: %s Wei \n", ethZRC20Balance.String()) //Pre-approve ETH withdraw on ZEVM @@ -179,7 +171,7 @@ func StressTest(cmd *cobra.Command, _ []string) { blockNum := must(e2eTest.ZEVMClient.BlockNumber(ctx)) // #nosec G701 e2eTest - always in range - nonce := must(e2eTest.ZEVMClient.NonceAt(ctx, local.DeployerAddress, big.NewInt(int64(blockNum)))) + nonce := must(e2eTest.ZEVMClient.NonceAt(ctx, deployerAccount.EVMAddress(), big.NewInt(int64(blockNum)))) // #nosec G701 e2e - always in range zevmNonce = big.NewInt(int64(nonce)) @@ -309,7 +301,7 @@ func WithdrawETHZRC20(r *runner.E2ERunner) { ethZRC20 := r.ETHZRC20 r.ZEVMAuth.Nonce = zevmNonce - must(ethZRC20.Withdraw(r.ZEVMAuth, local.DeployerAddress.Bytes(), big.NewInt(100))) + must(ethZRC20.Withdraw(r.ZEVMAuth, r.EVMAddress().Bytes(), big.NewInt(100))) } // Get ETH based chain ID diff --git a/contrib/localnet/orchestrator/Dockerfile.fastbuild b/contrib/localnet/orchestrator/Dockerfile.fastbuild index 2ef5520c64..96f437ed30 100644 --- a/contrib/localnet/orchestrator/Dockerfile.fastbuild +++ b/contrib/localnet/orchestrator/Dockerfile.fastbuild @@ -3,13 +3,14 @@ FROM ethereum/client-go:v1.10.26 as geth FROM golang:1.20.14-bookworm as orchestrator RUN apt update && \ - apt install -yq jq curl tmux python3 openssh-server iputils-ping iproute2 && \ + apt install -yq jq yq curl tmux python3 openssh-server iputils-ping iproute2 && \ rm -rf /var/lib/apt/lists/* COPY --from=geth /usr/local/bin/geth /usr/local/bin/ COPY --from=zeta /usr/local/bin/zetacored /usr/local/bin/zetaclientd /usr/local/bin/zetae2e /usr/local/bin/ COPY contrib/localnet/orchestrator/start-zetae2e.sh /work/ +COPY cmd/zetae2e/config/localnet.yml /work/config.yml RUN chmod +x /work/*.sh WORKDIR /work diff --git a/contrib/localnet/orchestrator/start-zetae2e.sh b/contrib/localnet/orchestrator/start-zetae2e.sh index 791f0a6074..676d55e26e 100644 --- a/contrib/localnet/orchestrator/start-zetae2e.sh +++ b/contrib/localnet/orchestrator/start-zetae2e.sh @@ -37,41 +37,45 @@ sleep 2 ### Create the accounts and fund them with Ether on local Ethereum network -# unlock the deployer account -echo "funding deployer address 0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC with 10000 Ether" -geth --exec 'eth.sendTransaction({from: eth.coinbase, to: "0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC", value: web3.toWei(10000,"ether")})' attach http://eth:8545 +# unlock the default account account +address=$(yq -r '.default_account.evm_address' config.yml) +echo "funding deployer address ${address} with 10000 Ether" +geth --exec "eth.sendTransaction({from: eth.coinbase, to: '${address}', value: web3.toWei(10000,'ether')})" attach http://eth:8545 # unlock erc20 tester accounts -echo "funding deployer address 0x6F57D5E7c6DBb75e59F1524a3dE38Fc389ec5Fd6 with 10000 Ether" -geth --exec 'eth.sendTransaction({from: eth.coinbase, to: "0x6F57D5E7c6DBb75e59F1524a3dE38Fc389ec5Fd6", value: web3.toWei(10000,"ether")})' attach http://eth:8545 +address=$(yq -r '.additional_accounts.user_erc20.evm_address' config.yml) +echo "funding erc20 address ${address} with 10000 Ether" +geth --exec "eth.sendTransaction({from: eth.coinbase, to: '${address}', value: web3.toWei(10000,'ether')})" attach http://eth:8545 # unlock zeta tester accounts -echo "funding deployer address 0x5cC2fBb200A929B372e3016F1925DcF988E081fd with 10000 Ether" -geth --exec 'eth.sendTransaction({from: eth.coinbase, to: "0x5cC2fBb200A929B372e3016F1925DcF988E081fd", value: web3.toWei(10000,"ether")})' attach http://eth:8545 +address=$(yq -r '.additional_accounts.user_zeta_test.evm_address' config.yml) +echo "funding zeta tester address ${address} with 10000 Ether" +geth --exec "eth.sendTransaction({from: eth.coinbase, to: '${address}', value: web3.toWei(10000,'ether')})" attach http://eth:8545 # unlock zevm message passing tester accounts -echo "funding deployer address 0x8Ae229198eCE3c889C07DB648Ec7C30E6051592c with 10000 Ether" -geth --exec 'eth.sendTransaction({from: eth.coinbase, to: "0x8Ae229198eCE3c889C07DB648Ec7C30E6051592c", value: web3.toWei(10000,"ether")})' attach http://eth:8545 +address=$(yq -r '.additional_accounts.user_zevm_mp_test.evm_address' config.yml) +echo "funding zevm mp tester address ${address} with 10000 Ether" +geth --exec "eth.sendTransaction({from: eth.coinbase, to: '${address}', value: web3.toWei(10000,'ether')})" attach http://eth:8545 # unlock bitcoin tester accounts -echo "funding deployer address 0x283d810090EdF4043E75247eAeBcE848806237fD with 10000 Ether" -geth --exec 'eth.sendTransaction({from: eth.coinbase, to: "0x283d810090EdF4043E75247eAeBcE848806237fD", value: web3.toWei(10000,"ether")})' attach http://eth:8545 +address=$(yq -r '.additional_accounts.user_bitcoin.evm_address' config.yml) +echo "funding bitcoin tester address ${address} with 10000 Ether" +geth --exec "eth.sendTransaction({from: eth.coinbase, to: '${address}', value: web3.toWei(10000,'ether')})" attach http://eth:8545 # unlock ethers tester accounts -echo "funding deployer address 0x8D47Db7390AC4D3D449Cc20D799ce4748F97619A with 10000 Ether" -geth --exec 'eth.sendTransaction({from: eth.coinbase, to: "0x8D47Db7390AC4D3D449Cc20D799ce4748F97619A", value: web3.toWei(10000,"ether")})' attach http://eth:8545 +address=$(yq -r '.additional_accounts.user_ether.evm_address' config.yml) +echo "funding ether tester address ${address} with 10000 Ether" +geth --exec "eth.sendTransaction({from: eth.coinbase, to: '${address}', value: web3.toWei(10000,'ether')})" attach http://eth:8545 # unlock miscellaneous tests accounts -echo "funding deployer address 0x90126d02E41c9eB2a10cfc43aAb3BD3460523Cdf with 10000 Ether" -geth --exec 'eth.sendTransaction({from: eth.coinbase, to: "0x90126d02E41c9eB2a10cfc43aAb3BD3460523Cdf", value: web3.toWei(10000,"ether")})' attach http://eth:8545 +address=$(yq -r '.additional_accounts.user_misc.evm_address' config.yml) +echo "funding misc tester address ${address} with 10000 Ether" +geth --exec "eth.sendTransaction({from: eth.coinbase, to: '${address}', value: web3.toWei(10000,'ether')})" attach http://eth:8545 # unlock admin erc20 tests accounts -echo "funding deployer address 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 with 10000 Ether" -geth --exec 'eth.sendTransaction({from: eth.coinbase, to: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", value: web3.toWei(10000,"ether")})' attach http://eth:8545 - -# unlock the TSS account -echo "funding TSS address 0xF421292cb0d3c97b90EEEADfcD660B893592c6A2 with 10000 Ether" -geth --exec 'eth.sendTransaction({from: eth.coinbase, to: "0xF421292cb0d3c97b90EEEADfcD660B893592c6A2", value: web3.toWei(10000,"ether")})' attach http://eth:8545 +address=$(yq -r '.additional_accounts.user_admin.evm_address' config.yml) +echo "funding admin tester address ${address} with 10000 Ether" +geth --exec "eth.sendTransaction({from: eth.coinbase, to: '${address}', value: web3.toWei(10000,'ether')})" attach http://eth:8545 ### Run zetae2e command depending on the option passed @@ -83,7 +87,7 @@ if [ "$LOCALNET_MODE" == "upgrade" ]; then UPGRADE_HEIGHT=${UPGRADE_HEIGHT:=225} if [[ ! -f deployed.yml ]]; then - zetae2e local $E2E_ARGS --setup-only --config-out deployed.yml --skip-header-proof + zetae2e local $E2E_ARGS --setup-only --config config.yml --config-out deployed.yml --skip-header-proof if [ $? -ne 0 ]; then echo "e2e setup failed" exit 1 @@ -159,7 +163,7 @@ else echo "running e2e setup..." if [[ ! -f deployed.yml ]]; then - zetae2e local $E2E_ARGS --setup-only --config-out deployed.yml + zetae2e local $E2E_ARGS --config config.yml --setup-only --config-out deployed.yml if [ $? -ne 0 ]; then echo "e2e setup failed" exit 1 diff --git a/contrib/localnet/scripts/start-zetacored.sh b/contrib/localnet/scripts/start-zetacored.sh index 29be9fb1ad..aba9538c5e 100755 --- a/contrib/localnet/scripts/start-zetacored.sh +++ b/contrib/localnet/scripts/start-zetacored.sh @@ -213,23 +213,30 @@ then fi # set admin account - zetacored add-genesis-account zeta1svzuz982w09vf2y08xsh8qplj36phyz466krj3 100000000000000000000000000azeta zetacored add-genesis-account zeta1n0rn6sne54hv7w2uu93fl48ncyqz97d3kty6sh 100000000000000000000000000azeta # Funds the localnet_gov_admin account - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["authority"]["policies"]["items"][0]["address"]="zeta1svzuz982w09vf2y08xsh8qplj36phyz466krj3"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["authority"]["policies"]["items"][1]["address"]="zeta1svzuz982w09vf2y08xsh8qplj36phyz466krj3"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["authority"]["policies"]["items"][2]["address"]="zeta1svzuz982w09vf2y08xsh8qplj36phyz466krj3"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json + + address=$(yq -r '.additional_accounts.user_fungible_admin.bech32_address' /root/config.yml) + zetacored add-genesis-account "$address" 100000000000000000000000000azeta + cat $HOME/.zetacored/config/genesis.json | jq --arg address "$address" '.app_state["authority"]["policies"]["items"][0]["address"] = $address' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json + cat $HOME/.zetacored/config/genesis.json | jq --arg address "$address" '.app_state["authority"]["policies"]["items"][1]["address"] = $address' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json + cat $HOME/.zetacored/config/genesis.json | jq --arg address "$address" '.app_state["authority"]["policies"]["items"][2]["address"] = $address' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json # give balance to runner accounts to deploy contracts directly on zEVM -# deployer - zetacored add-genesis-account zeta1uhznv7uzyjq84s3q056suc8pkme85lkvhrz3dd 100000000000000000000000000azeta +# default account + address=$(yq -r '.default_account.bech32_address' /root/config.yml) + zetacored add-genesis-account "$address" 100000000000000000000000000azeta # erc20 tester - zetacored add-genesis-account zeta1datate7xmwm4uk032f9rmcu0cwy7ch7kg6y6zv 100000000000000000000000000azeta + address=$(yq -r '.additional_accounts.user_erc20.bech32_address' /root/config.yml) + zetacored add-genesis-account "$address" 100000000000000000000000000azeta # zeta tester - zetacored add-genesis-account zeta1tnp0hvsq4y5mxuhrq9h3jfwulxywpq0ads0rer 100000000000000000000000000azeta + address=$(yq -r '.additional_accounts.user_zeta_test.bech32_address' /root/config.yml) + zetacored add-genesis-account "$address" 100000000000000000000000000azeta # bitcoin tester - zetacored add-genesis-account zeta19q7czqysah6qg0n4y3l2a08gfzqxydla492v80 100000000000000000000000000azeta + address=$(yq -r '.additional_accounts.user_bitcoin.bech32_address' /root/config.yml) + zetacored add-genesis-account "$address" 100000000000000000000000000azeta # ethers tester - zetacored add-genesis-account zeta134rakuus43xn63yucgxhn88ywj8ewcv6ezn2ga 100000000000000000000000000azeta + address=$(yq -r '.additional_accounts.user_ether.bech32_address' /root/config.yml) + zetacored add-genesis-account "$address" 100000000000000000000000000azeta # 3. Copy the genesis.json to all the nodes .And use it to create a gentx for every node zetacored gentx operator 1000000000000000000000azeta --chain-id=$CHAINID --keyring-backend=$KEYRING --gas-prices 20000000000azeta diff --git a/e2e/config/config.go b/e2e/config/config.go index 450b02c5a3..66409ee339 100644 --- a/e2e/config/config.go +++ b/e2e/config/config.go @@ -1,26 +1,70 @@ package config import ( + "crypto/ecdsa" "errors" "fmt" "os" + "strings" "github.com/btcsuite/btcd/chaincfg" - "gopkg.in/yaml.v2" + "github.com/cosmos/cosmos-sdk/types/bech32" + ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" + "gopkg.in/yaml.v3" ) +// DoubleQuotedString forces a string to be double quoted when marshaling to yaml. +// This is required because of https://github.com/go-yaml/yaml/issues/847 +type DoubleQuotedString string + +func (s DoubleQuotedString) MarshalYAML() (interface{}, error) { + return yaml.Node{ + Value: string(s), + Kind: yaml.ScalarNode, + Style: yaml.DoubleQuotedStyle, + }, nil +} + +func (s DoubleQuotedString) String() string { + return string(s) +} + +func (s DoubleQuotedString) AsEVMAddress() (ethcommon.Address, error) { + if !ethcommon.IsHexAddress(string(s)) { + return ethcommon.Address{}, fmt.Errorf("invalid evm address: %s", string(s)) + } + return ethcommon.HexToAddress(string(s)), nil +} + // Config contains the configuration for the e2e test type Config struct { - Accounts Accounts `yaml:"accounts"` - RPCs RPCs `yaml:"rpcs"` - Contracts Contracts `yaml:"contracts"` - ZetaChainID string `yaml:"zeta_chain_id"` + // Default account to use when running tests and running setup + DefaultAccount Account `yaml:"default_account"` + AdditionalAccounts AdditionalAccounts `yaml:"additional_accounts"` + RPCs RPCs `yaml:"rpcs"` + Contracts Contracts `yaml:"contracts"` + ZetaChainID string `yaml:"zeta_chain_id"` +} + +// Account contains configuration for an account +type Account struct { + RawBech32Address DoubleQuotedString `yaml:"bech32_address"` + RawEVMAddress DoubleQuotedString `yaml:"evm_address"` + RawPrivateKey DoubleQuotedString `yaml:"private_key"` } -// Accounts contains the configuration for the accounts -type Accounts struct { - EVMAddress string `yaml:"evm_address"` - EVMPrivKey string `yaml:"evm_priv_key"` +// 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"` + UserEther Account `yaml:"user_ether"` + UserMisc Account `yaml:"user_misc"` + UserAdmin Account `yaml:"user_admin"` + UserFungibleAdmin Account `yaml:"user_fungible_admin"` } // RPCs contains the configuration for the RPC endpoints @@ -50,26 +94,26 @@ type Contracts struct { // EVM contains the addresses of predeployed contracts on the EVM chain type EVM struct { - ZetaEthAddress string `yaml:"zeta_eth"` - ConnectorEthAddr string `yaml:"connector_eth"` - CustodyAddr string `yaml:"custody"` - ERC20 string `yaml:"erc20"` - TestDappAddr string `yaml:"test_dapp"` + ZetaEthAddr DoubleQuotedString `yaml:"zeta_eth"` + ConnectorEthAddr DoubleQuotedString `yaml:"connector_eth"` + CustodyAddr DoubleQuotedString `yaml:"custody"` + ERC20 DoubleQuotedString `yaml:"erc20"` + TestDappAddr DoubleQuotedString `yaml:"test_dapp"` } // ZEVM contains the addresses of predeployed contracts on the zEVM chain type ZEVM struct { - SystemContractAddr string `yaml:"system_contract"` - ETHZRC20Addr string `yaml:"eth_zrc20"` - ERC20ZRC20Addr string `yaml:"erc20_zrc20"` - BTCZRC20Addr string `yaml:"btc_zrc20"` - UniswapFactoryAddr string `yaml:"uniswap_factory"` - UniswapRouterAddr string `yaml:"uniswap_router"` - ConnectorZEVMAddr string `yaml:"connector_zevm"` - WZetaAddr string `yaml:"wzeta"` - ZEVMSwapAppAddr string `yaml:"zevm_swap_app"` - ContextAppAddr string `yaml:"context_app"` - TestDappAddr string `yaml:"test_dapp"` + SystemContractAddr DoubleQuotedString `yaml:"system_contract"` + ETHZRC20Addr DoubleQuotedString `yaml:"eth_zrc20"` + ERC20ZRC20Addr DoubleQuotedString `yaml:"erc20_zrc20"` + BTCZRC20Addr DoubleQuotedString `yaml:"btc_zrc20"` + UniswapFactoryAddr DoubleQuotedString `yaml:"uniswap_factory"` + UniswapRouterAddr DoubleQuotedString `yaml:"uniswap_router"` + ConnectorZEVMAddr DoubleQuotedString `yaml:"connector_zevm"` + WZetaAddr DoubleQuotedString `yaml:"wzeta"` + ZEVMSwapAppAddr DoubleQuotedString `yaml:"zevm_swap_app"` + ContextAppAddr DoubleQuotedString `yaml:"context_app"` + TestDappAddr DoubleQuotedString `yaml:"test_dapp"` } // DefaultConfig returns the default config using values for localnet testing @@ -137,6 +181,21 @@ func WriteConfig(file string, config Config) error { return nil } +// AsSlice gets all accounts as a slice rather than a +// struct +func (a AdditionalAccounts) AsSlice() []Account { + return []Account{ + a.UserERC20, + a.UserZetaTest, + a.UserZEVMMPTest, + a.UserBitcoin, + a.UserEther, + a.UserMisc, + a.UserAdmin, + a.UserFungibleAdmin, + } +} + // Validate validates the config func (c Config) Validate() error { if c.RPCs.Bitcoin.Params != Mainnet && @@ -144,6 +203,105 @@ func (c Config) Validate() error { c.RPCs.Bitcoin.Params != Regnet { return errors.New("invalid bitcoin params") } + + err := c.DefaultAccount.Validate() + if err != nil { + return fmt.Errorf("validating deployer account: %w", err) + } + + accounts := c.AdditionalAccounts.AsSlice() + for i, account := range accounts { + if account.RawEVMAddress == "" { + continue + } + err := account.Validate() + if err != nil { + return fmt.Errorf("validating account %d: %w", i, err) + } + } + return nil +} + +// GenerateKeys generates new key pairs for all accounts +func (c *Config) GenerateKeys() error { + var err error + c.DefaultAccount, err = generateAccount() + if err != nil { + return err + } + c.AdditionalAccounts.UserERC20, err = generateAccount() + if err != nil { + return err + } + c.AdditionalAccounts.UserZetaTest, err = generateAccount() + if err != nil { + return err + } + c.AdditionalAccounts.UserZEVMMPTest, err = generateAccount() + if err != nil { + return err + } + c.AdditionalAccounts.UserBitcoin, err = generateAccount() + if err != nil { + return err + } + c.AdditionalAccounts.UserEther, err = generateAccount() + if err != nil { + return err + } + c.AdditionalAccounts.UserMisc, err = generateAccount() + if err != nil { + return err + } + c.AdditionalAccounts.UserAdmin, err = generateAccount() + if err != nil { + return err + } + c.AdditionalAccounts.UserFungibleAdmin, err = generateAccount() + if err != nil { + return err + } + return nil +} + +func (a Account) EVMAddress() ethcommon.Address { + return ethcommon.HexToAddress(a.RawEVMAddress.String()) +} + +func (a Account) PrivateKey() (*ecdsa.PrivateKey, error) { + return crypto.HexToECDSA(a.RawPrivateKey.String()) +} + +// Validate that the address and the private key specified in the +// config actually match +func (a Account) Validate() error { + privateKey, err := a.PrivateKey() + if err != nil { + return fmt.Errorf("invalid private key: %w", err) + } + privateKeyAddress := crypto.PubkeyToAddress(privateKey.PublicKey) + if a.RawEVMAddress.String() != privateKeyAddress.Hex() { + return fmt.Errorf( + "address derived from private key (%s) does not match configured address (%s)", + privateKeyAddress, + a.RawEVMAddress, + ) + } + _, _, err = bech32.DecodeAndConvert(a.RawBech32Address.String()) + if err != nil { + return fmt.Errorf("decoding bech32 address: %w", err) + } + bech32PrivateKeyAddress, err := bech32.ConvertAndEncode("zeta", privateKeyAddress.Bytes()) + if err != nil { + return fmt.Errorf("encoding private key to bech32: %w", err) + } + if a.RawBech32Address.String() != bech32PrivateKeyAddress { + return fmt.Errorf( + "address derived from private key (%s) does not match configured address (%s)", + bech32PrivateKeyAddress, + a.RawBech32Address, + ) + } return nil } @@ -170,3 +328,25 @@ func (bnt BitcoinNetworkType) GetParams() (chaincfg.Params, error) { return chaincfg.Params{}, fmt.Errorf("invalid bitcoin params %s", bnt) } } + +func generateAccount() (Account, error) { + privateKey, err := crypto.GenerateKey() + if err != nil { + return Account{}, fmt.Errorf("generating private key: %w", err) + } + // encode private key and strip 0x prefix + encodedPrivateKey := hexutil.Encode(crypto.FromECDSA(privateKey)) + encodedPrivateKey = strings.TrimPrefix(encodedPrivateKey, "0x") + + evmAddress := crypto.PubkeyToAddress(privateKey.PublicKey) + bech32Address, err := bech32.ConvertAndEncode("zeta", evmAddress.Bytes()) + if err != nil { + return Account{}, fmt.Errorf("bech32 convert and encode: %w", err) + } + + return Account{ + RawEVMAddress: DoubleQuotedString(evmAddress.String()), + RawPrivateKey: DoubleQuotedString(encodedPrivateKey), + RawBech32Address: DoubleQuotedString(bech32Address), + }, nil +} diff --git a/e2e/config/config_test.go b/e2e/config/config_test.go new file mode 100644 index 0000000000..033efb81b6 --- /dev/null +++ b/e2e/config/config_test.go @@ -0,0 +1,39 @@ +package config + +import ( + "reflect" + "testing" + + "github.com/stretchr/testify/require" +) + +// TestAdditionalAccountsSlicesSynced ensures than if any new accounts are added the +// AccountsSlice() function is updated +func TestConfigAdditionalAccountsSliceSynced(t *testing.T) { + additionalAccountsType := reflect.TypeOf(AdditionalAccounts{}) + numberOfAdditionalAccounts := additionalAccountsType.NumField() + + require.Greater(t, numberOfAdditionalAccounts, 0) + + conf := Config{} + err := conf.GenerateKeys() + require.NoError(t, err) + + additionalAccountsSlice := conf.AdditionalAccounts.AsSlice() + require.Len(t, additionalAccountsSlice, numberOfAdditionalAccounts) + + for _, account := range additionalAccountsSlice { + require.NoError(t, account.Validate()) + } +} + +func TestConfigInvalidAccount(t *testing.T) { + conf := Config{ + DefaultAccount: Account{ + RawEVMAddress: "asdf", + RawPrivateKey: "asdf", + }, + } + err := conf.Validate() + require.Error(t, err) +} diff --git a/e2e/e2etests/test_context_upgrade.go b/e2e/e2etests/test_context_upgrade.go index 4d06ee84d1..4a71b07428 100644 --- a/e2e/e2etests/test_context_upgrade.go +++ b/e2e/e2etests/test_context_upgrade.go @@ -57,7 +57,7 @@ func TestContextUpgrade(r *runner.E2ERunner, args []string) { r.Logger.Info(" msgsender: %s", eventIter.Event.MsgSender.Hex()) found = true - require.Equal(r, 0, bytes.Compare(eventIter.Event.Origin, r.DeployerAddress.Bytes()), "origin mismatch") + require.Equal(r, 0, bytes.Compare(eventIter.Event.Origin, r.EVMAddress().Bytes()), "origin mismatch") chainID, err := r.EVMClient.ChainID(r.Ctx) require.NoError(r, err) diff --git a/e2e/e2etests/test_crosschain_swap.go b/e2e/e2etests/test_crosschain_swap.go index f1fe6f54aa..798958a652 100644 --- a/e2e/e2etests/test_crosschain_swap.go +++ b/e2e/e2etests/test_crosschain_swap.go @@ -58,7 +58,7 @@ func TestCrosschainSwap(r *runner.E2ERunner, _ []string) { big.NewInt(1e8), big.NewInt(1e8), big.NewInt(1e5), - r.DeployerAddress, + r.EVMAddress(), big.NewInt(time.Now().Add(10*time.Minute).Unix()), ) require.NoError(r, err) @@ -80,7 +80,7 @@ func TestCrosschainSwap(r *runner.E2ERunner, _ []string) { r.Logger.Info("***** First test: ERC20 -> BTC") // Should deposit ERC20 for swap, swap for BTC and withdraw BTC - txHash := r.DepositERC20WithAmountAndMessage(r.DeployerAddress, big.NewInt(8e7), msg) + txHash := r.DepositERC20WithAmountAndMessage(r.EVMAddress(), big.NewInt(8e7), msg) cctx1 := utils.WaitCctxMinedByInboundHash(r.Ctx, txHash.Hex(), r.CctxClient, r.Logger, r.CctxTimeout) // check the cctx status @@ -110,7 +110,7 @@ func TestCrosschainSwap(r *runner.E2ERunner, _ []string) { r.Logger.Info("#utxos %d", len(utxos)) r.Logger.Info("memo address %s", r.ERC20ZRC20Addr) - memo, err := r.ZEVMSwapApp.EncodeMemo(&bind.CallOpts{}, r.ERC20ZRC20Addr, r.DeployerAddress.Bytes()) + memo, err := r.ZEVMSwapApp.EncodeMemo(&bind.CallOpts{}, r.ERC20ZRC20Addr, r.EVMAddress().Bytes()) require.NoError(r, err) memo = append(r.ZEVMSwapAppAddr.Bytes(), memo...) @@ -138,7 +138,7 @@ func TestCrosschainSwap(r *runner.E2ERunner, _ []string) { r.Logger.Info("******* Third test: BTC -> ETH with contract call reverted; should refund BTC") // the following memo will result in a revert in the contract call as targetZRC20 is set to DeployerAddress // which is apparently not a ZRC20 contract; the UNISWAP call will revert - memo, err := r.ZEVMSwapApp.EncodeMemo(&bind.CallOpts{}, r.DeployerAddress, r.DeployerAddress.Bytes()) + memo, err := r.ZEVMSwapApp.EncodeMemo(&bind.CallOpts{}, r.EVMAddress(), r.EVMAddress().Bytes()) require.NoError(r, err) memo = append(r.ZEVMSwapAppAddr.Bytes(), memo...) diff --git a/e2e/e2etests/test_erc20_deposit.go b/e2e/e2etests/test_erc20_deposit.go index 2f763f34b0..c7f1d4fc5f 100644 --- a/e2e/e2etests/test_erc20_deposit.go +++ b/e2e/e2etests/test_erc20_deposit.go @@ -15,7 +15,7 @@ func TestERC20Deposit(r *runner.E2ERunner, args []string) { amount, ok := big.NewInt(0).SetString(args[0], 10) require.True(r, ok, "Invalid amount specified for TestERC20Deposit.") - hash := r.DepositERC20WithAmountAndMessage(r.DeployerAddress, amount, []byte{}) + hash := r.DepositERC20WithAmountAndMessage(r.EVMAddress(), amount, []byte{}) // wait for the cctx to be mined cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, hash.Hex(), r.CctxClient, r.Logger, r.CctxTimeout) diff --git a/e2e/e2etests/test_erc20_deposit_refund.go b/e2e/e2etests/test_erc20_deposit_refund.go index ad0a962507..5e8d1173ef 100644 --- a/e2e/e2etests/test_erc20_deposit_refund.go +++ b/e2e/e2etests/test_erc20_deposit_refund.go @@ -17,7 +17,7 @@ import ( func TestERC20DepositAndCallRefund(r *runner.E2ERunner, _ []string) { // Get the initial balance of the deployer - initialBal, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + initialBal, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) require.NoError(r, err) r.Logger.Info("Sending a deposit that should revert without a liquidity pool makes the cctx aborted") @@ -36,13 +36,13 @@ func TestERC20DepositAndCallRefund(r *runner.E2ERunner, _ []string) { r.Logger.CCTX(*cctx, "deposit") r.Logger.Info("Refunding the cctx via admin") - msg := types.NewMsgRefundAbortedCCTX(r.ZetaTxServer.GetAccountAddress(0), cctx.Index, r.DeployerAddress.String()) + msg := types.NewMsgRefundAbortedCCTX(r.ZetaTxServer.GetAccountAddress(0), cctx.Index, r.EVMAddress().String()) _, err = r.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msg) require.NoError(r, err) // Check that the erc20 in the aborted cctx was refunded on ZetaChain - newBalance, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + newBalance, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) require.NoError(r, err) expectedBalance := initialBal.Add(initialBal, amount) @@ -65,7 +65,7 @@ func TestERC20DepositAndCallRefund(r *runner.E2ERunner, _ []string) { r.Logger.Info("Liquidity pool created") - erc20Balance, err := r.ERC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + erc20Balance, err := r.ERC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) require.NoError(r, err) // send the deposit @@ -87,7 +87,7 @@ func TestERC20DepositAndCallRefund(r *runner.E2ERunner, _ []string) { utils.RequireTxSuccessful(r, receipt) // check that the erc20 in the reverted cctx was refunded on EVM - erc20BalanceAfterRefund, err := r.ERC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + erc20BalanceAfterRefund, err := r.ERC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) require.NoError(r, err) // the new balance must be higher than the previous one because of the revert refund @@ -118,7 +118,7 @@ func TestERC20DepositAndCallRefund(r *runner.E2ERunner, _ []string) { func createZetaERC20LiquidityPool(r *runner.E2ERunner) error { amount := big.NewInt(1e10) - txHash := r.DepositERC20WithAmountAndMessage(r.DeployerAddress, amount, []byte{}) + txHash := r.DepositERC20WithAmountAndMessage(r.EVMAddress(), amount, []byte{}) utils.WaitCctxMinedByInboundHash(r.Ctx, txHash.Hex(), r.CctxClient, r.Logger, r.CctxTimeout) tx, err := r.ERC20ZRC20.Approve(r.ZEVMAuth, r.UniswapV2RouterAddr, big.NewInt(1e10)) @@ -138,7 +138,7 @@ func createZetaERC20LiquidityPool(r *runner.E2ERunner) error { amount, big.NewInt(0), big.NewInt(0), - r.DeployerAddress, + r.EVMAddress(), big.NewInt(time.Now().Add(10*time.Minute).Unix()), ) r.ZEVMAuth.Value = previousValue @@ -163,7 +163,7 @@ func sendInvalidERC20Deposit(r *runner.E2ERunner, amount *big.Int) (string, erro tx, err = r.ERC20Custody.Deposit( r.EVMAuth, - r.DeployerAddress.Bytes(), + r.EVMAddress().Bytes(), r.ERC20Addr, amount, []byte("this is an invalid msg that will cause the contract to revert"), diff --git a/e2e/e2etests/test_erc20_multiple_deposits.go b/e2e/e2etests/test_erc20_multiple_deposits.go index a99642f356..87b8309924 100644 --- a/e2e/e2etests/test_erc20_multiple_deposits.go +++ b/e2e/e2etests/test_erc20_multiple_deposits.go @@ -22,7 +22,7 @@ func TestMultipleERC20Deposit(r *runner.E2ERunner, args []string) { require.True(r, ok) require.NotZero(r, numberOfDeposits.Int64()) - initialBal, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + initialBal, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) require.NoError(r, err) txhash := multipleDeposits(r, depositAmount, numberOfDeposits) @@ -37,7 +37,7 @@ func TestMultipleERC20Deposit(r *runner.E2ERunner, args []string) { require.Len(r, cctxs, 3) // check new balance is increased by amount * count - bal, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + bal, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) require.NoError(r, err) diff := big.NewInt(0).Sub(bal, initialBal) @@ -61,7 +61,7 @@ func multipleDeposits(r *runner.E2ERunner, amount, count *big.Int) ethcommon.Has r.Logger.Info("ERC20 Approve receipt tx hash: %s", tx.Hash().Hex()) // deposit - tx, err = depositor.RunDeposits(r.EVMAuth, r.DeployerAddress.Bytes(), r.ERC20Addr, amount, []byte{}, count) + tx, err = depositor.RunDeposits(r.EVMAuth, r.EVMAddress().Bytes(), r.ERC20Addr, amount, []byte{}, count) require.NoError(r, err) receipt = utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) diff --git a/e2e/e2etests/test_erc20_multiple_withdraws.go b/e2e/e2etests/test_erc20_multiple_withdraws.go index 14bbb176ca..53a45d1b41 100644 --- a/e2e/e2etests/test_erc20_multiple_withdraws.go +++ b/e2e/e2etests/test_erc20_multiple_withdraws.go @@ -56,7 +56,7 @@ func TestMultipleERC20Withdraws(r *runner.E2ERunner, args []string) { r.Logger.Info("eth zrc20 approve receipt: status %d", receipt.Status) // check the balance - bal, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + bal, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) require.NoError(r, err) r.Logger.Info("balance of deployer on ERC20 ZRC20: %d", bal) @@ -65,7 +65,7 @@ func TestMultipleERC20Withdraws(r *runner.E2ERunner, args []string) { // withdraw tx, err = withdrawer.RunWithdraws( r.ZEVMAuth, - r.DeployerAddress.Bytes(), + r.EVMAddress().Bytes(), r.ERC20ZRC20Addr, withdrawalAmount, numberOfWithdrawals, diff --git a/e2e/e2etests/test_eth_deposit_call.go b/e2e/e2etests/test_eth_deposit_call.go index 0d7734fbdb..7fd928266d 100644 --- a/e2e/e2etests/test_eth_deposit_call.go +++ b/e2e/e2etests/test_eth_deposit_call.go @@ -5,7 +5,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" @@ -33,7 +32,7 @@ func TestEtherDepositAndCall(r *runner.E2ERunner, args []string) { gasPrice, err := evmClient.SuggestGasPrice(r.Ctx) require.NoError(r, err) - nonce, err := evmClient.PendingNonceAt(r.Ctx, r.DeployerAddress) + nonce, err := evmClient.PendingNonceAt(r.Ctx, r.EVMAddress()) require.NoError(r, err) data := append(exampleAddr.Bytes(), []byte("hello sailors")...) @@ -41,7 +40,7 @@ func TestEtherDepositAndCall(r *runner.E2ERunner, args []string) { chainID, err := evmClient.NetworkID(r.Ctx) require.NoError(r, err) - deployerPrivkey, err := crypto.HexToECDSA(r.DeployerPrivateKey) + deployerPrivkey, err := r.Account.PrivateKey() require.NoError(r, err) signedTx, err := ethtypes.SignTx(tx, ethtypes.NewEIP155Signer(chainID), deployerPrivkey) @@ -80,7 +79,7 @@ func TestEtherDepositAndCall(r *runner.E2ERunner, args []string) { gasPrice, err = evmClient.SuggestGasPrice(r.Ctx) require.NoError(r, err) - nonce, err = evmClient.PendingNonceAt(r.Ctx, r.DeployerAddress) + nonce, err = evmClient.PendingNonceAt(r.Ctx, r.EVMAddress()) require.NoError(r, err) data = append(reverterAddr.Bytes(), []byte("hello sailors")...) diff --git a/e2e/e2etests/test_eth_deposit_liquidity_cap.go b/e2e/e2etests/test_eth_deposit_liquidity_cap.go index f64b041478..2f03c7a568 100644 --- a/e2e/e2etests/test_eth_deposit_liquidity_cap.go +++ b/e2e/e2etests/test_eth_deposit_liquidity_cap.go @@ -47,7 +47,7 @@ func TestDepositEtherLiquidityCap(r *runner.E2ERunner, args []string) { r.Logger.Info("CCTX has been reverted") r.Logger.Info("Depositing less than liquidity cap should still succeed") - initialBal, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + initialBal, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) require.NoError(r, err) signedTx, err = r.SendEther(r.TSSAddress, amountLessThanCap, nil) @@ -61,7 +61,7 @@ func TestDepositEtherLiquidityCap(r *runner.E2ERunner, args []string) { expectedBalance := big.NewInt(0).Add(initialBal, amountLessThanCap) - bal, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + bal, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) require.NoError(r, err) require.Equal(r, 0, bal.Cmp(expectedBalance)) @@ -79,7 +79,7 @@ func TestDepositEtherLiquidityCap(r *runner.E2ERunner, args []string) { r.Logger.Info("remove liquidity cap tx hash: %s", res.TxHash) - initialBal, err = r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + initialBal, err = r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) require.NoError(r, err) signedTx, err = r.SendEther(r.TSSAddress, amountMoreThanCap, nil) @@ -91,7 +91,7 @@ func TestDepositEtherLiquidityCap(r *runner.E2ERunner, args []string) { utils.WaitCctxMinedByInboundHash(r.Ctx, signedTx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) expectedBalance = big.NewInt(0).Add(initialBal, amountMoreThanCap) - bal, err = r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + bal, err = r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) require.NoError(r, err) require.Equal(r, 0, diff --git a/e2e/e2etests/test_eth_deposit_refund.go b/e2e/e2etests/test_eth_deposit_refund.go index 394ffdd8e4..946c457927 100644 --- a/e2e/e2etests/test_eth_deposit_refund.go +++ b/e2e/e2etests/test_eth_deposit_refund.go @@ -5,7 +5,6 @@ import ( ethcommon "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" @@ -21,7 +20,7 @@ func TestEtherDepositAndCallRefund(r *runner.E2ERunner, args []string) { evmClient := r.EVMClient - nonce, err := evmClient.PendingNonceAt(r.Ctx, r.DeployerAddress) + nonce, err := evmClient.PendingNonceAt(r.Ctx, r.EVMAddress()) require.NoError(r, err) gasLimit := uint64(23000) // in units @@ -33,7 +32,7 @@ func TestEtherDepositAndCallRefund(r *runner.E2ERunner, args []string) { chainID, err := evmClient.NetworkID(r.Ctx) require.NoError(r, err) - deployerPrivkey, err := crypto.HexToECDSA(r.DeployerPrivateKey) + deployerPrivkey, err := r.Account.PrivateKey() require.NoError(r, err) signedTx, err := ethtypes.SignTx(tx, ethtypes.NewEIP155Signer(chainID), deployerPrivkey) @@ -66,7 +65,7 @@ func TestEtherDepositAndCallRefund(r *runner.E2ERunner, args []string) { utils.RequireCCTXStatus(r, cctx, types.CctxStatus_Reverted) utils.RequireTxSuccessful(r, receipt) - require.Equal(r, r.DeployerAddress, *tx.To(), "expected tx to %s; got %s", r.DeployerAddress.Hex(), tx.To().Hex()) + require.Equal(r, r.EVMAddress(), *tx.To(), "expected tx to %s; got %s", r.EVMAddress().Hex(), tx.To().Hex()) // the received value must be lower than the original value because of the paid fees for the revert tx // we check that the value is still greater than 0 diff --git a/e2e/e2etests/test_message_passing_external_chains.go b/e2e/e2etests/test_message_passing_external_chains.go index 317665920b..2c2ed65997 100644 --- a/e2e/e2etests/test_message_passing_external_chains.go +++ b/e2e/e2etests/test_message_passing_external_chains.go @@ -39,7 +39,7 @@ func TestMessagePassingExternalChains(r *runner.E2ERunner, args []string) { r.Logger.Info("Calling ConnectorEth.Send") tx, err = r.ConnectorEth.Send(auth, zetaconnectoreth.ZetaInterfacesSendInput{ DestinationChainId: chainID, - DestinationAddress: r.DeployerAddress.Bytes(), + DestinationAddress: r.EVMAddress().Bytes(), DestinationGasLimit: big.NewInt(400_000), Message: nil, ZetaValueAndGas: amount, diff --git a/e2e/e2etests/test_message_passing_external_chains_revert_fail.go b/e2e/e2etests/test_message_passing_external_chains_revert_fail.go index 3950a8cdd5..9cc1ee8d8f 100644 --- a/e2e/e2etests/test_message_passing_external_chains_revert_fail.go +++ b/e2e/e2etests/test_message_passing_external_chains_revert_fail.go @@ -39,7 +39,7 @@ func TestMessagePassingRevertFailExternalChains(r *runner.E2ERunner, args []stri tx, err = r.ConnectorEth.Send(auth, zetaconnectoreth.ZetaInterfacesSendInput{ DestinationChainId: chainID, - DestinationAddress: r.DeployerAddress.Bytes(), + DestinationAddress: r.EVMAddress().Bytes(), DestinationGasLimit: big.NewInt(400_000), Message: []byte( "revert", diff --git a/e2e/e2etests/test_migrate_chain_support.go b/e2e/e2etests/test_migrate_chain_support.go index 848335ddef..07f49a5815 100644 --- a/e2e/e2etests/test_migrate_chain_support.go +++ b/e2e/e2etests/test_migrate_chain_support.go @@ -9,12 +9,12 @@ import ( "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/fatih/color" "github.com/stretchr/testify/require" "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zrc20.sol" + "github.com/zeta-chain/zetacore/e2e/config" "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/txserver" "github.com/zeta-chain/zetacore/e2e/utils" @@ -38,7 +38,7 @@ func TestMigrateChainSupport(r *runner.E2ERunner, _ []string) { // deposit most of the ZETA supply on ZetaChain zetaAmount := big.NewInt(1e18) zetaAmount = zetaAmount.Mul(zetaAmount, big.NewInt(20_000_000_000)) // 20B Zeta - r.DepositZetaWithAmount(r.DeployerAddress, zetaAmount) + r.DepositZetaWithAmount(r.EVMAddress(), zetaAmount) // do an ethers withdraw on the previous chain (0.01eth) for some interaction TestEtherWithdraw(r, []string{"10000000000000000"}) @@ -120,7 +120,7 @@ func TestMigrateChainSupport(r *runner.E2ERunner, _ []string) { time.Sleep(10 * time.Second) // emitting a withdraw with the previous chain should fail - txWithdraw, err := r.ETHZRC20.Withdraw(r.ZEVMAuth, r.DeployerAddress.Bytes(), big.NewInt(10000000000000000)) + txWithdraw, err := r.ETHZRC20.Withdraw(r.ZEVMAuth, r.EVMAddress().Bytes(), big.NewInt(10000000000000000)) if err == nil { receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, txWithdraw, r.Logger, r.ReceiptTimeout) utils.RequiredTxFailed(r, receipt) @@ -199,8 +199,7 @@ func configureEVM2(r *runner.E2ERunner) (*runner.E2ERunner, error) { r.Ctx, "admin-evm2", r.CtxCancel, - r.DeployerAddress, - r.DeployerPrivateKey, + r.Account, r.EVMClient, r.ZEVMClient, r.CctxClient, @@ -217,7 +216,7 @@ func configureEVM2(r *runner.E2ERunner) (*runner.E2ERunner, error) { ) // All existing fields of the runner are the same except for the RPC URL and client for EVM - ewvmClient, evmAuth, err := getEVMClient(newRunner.Ctx, EVM2RPCURL, r.DeployerPrivateKey) + ewvmClient, evmAuth, err := getEVMClient(newRunner.Ctx, EVM2RPCURL, r.Account) if err != nil { return nil, err } @@ -243,7 +242,11 @@ func configureEVM2(r *runner.E2ERunner) (*runner.E2ERunner, error) { } // getEVMClient get evm client from rpc and private key -func getEVMClient(ctx context.Context, rpc, privKey string) (*ethclient.Client, *bind.TransactOpts, error) { +func getEVMClient( + ctx context.Context, + rpc string, + account config.Account, +) (*ethclient.Client, *bind.TransactOpts, error) { evmClient, err := ethclient.Dial(rpc) if err != nil { return nil, nil, err @@ -253,7 +256,7 @@ func getEVMClient(ctx context.Context, rpc, privKey string) (*ethclient.Client, if err != nil { return nil, nil, err } - deployerPrivkey, err := crypto.HexToECDSA(privKey) + deployerPrivkey, err := account.PrivateKey() if err != nil { return nil, nil, err } diff --git a/e2e/e2etests/test_rate_limiter.go b/e2e/e2etests/test_rate_limiter.go index 446d49a6b2..739d7821dc 100644 --- a/e2e/e2etests/test_rate_limiter.go +++ b/e2e/e2etests/test_rate_limiter.go @@ -221,7 +221,7 @@ func addZetaGasLiquidity(r *runner.E2ERunner) error { amount, big.NewInt(1e18), big.NewInt(1e18), - r.DeployerAddress, + r.EVMAddress(), big.NewInt(time.Now().Add(10*time.Minute).Unix()), ) if err != nil { diff --git a/e2e/e2etests/test_stress_eth_withdraw.go b/e2e/e2etests/test_stress_eth_withdraw.go index 3a67ca8f94..2abd036a25 100644 --- a/e2e/e2etests/test_stress_eth_withdraw.go +++ b/e2e/e2etests/test_stress_eth_withdraw.go @@ -40,7 +40,7 @@ func TestStressEtherWithdraw(r *runner.E2ERunner, args []string) { for i := 0; i < numWithdraws; i++ { i := i - tx, err := r.ETHZRC20.Withdraw(r.ZEVMAuth, r.DeployerAddress.Bytes(), withdrawalAmount) + tx, err := r.ETHZRC20.Withdraw(r.ZEVMAuth, r.EVMAddress().Bytes(), withdrawalAmount) require.NoError(r, err) receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) diff --git a/e2e/e2etests/test_update_bytecode_zrc20.go b/e2e/e2etests/test_update_bytecode_zrc20.go index ba914655d1..8205b88d9c 100644 --- a/e2e/e2etests/test_update_bytecode_zrc20.go +++ b/e2e/e2etests/test_update_bytecode_zrc20.go @@ -60,10 +60,10 @@ func TestUpdateBytecodeZRC20(r *runner.E2ERunner, _ []string) { totalSupply, err := r.ETHZRC20.TotalSupply(&bind.CallOpts{}) require.NoError(r, err) - balance, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + balance, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) require.NoError(r, err) - approval, err := r.ETHZRC20.Allowance(&bind.CallOpts{}, r.DeployerAddress, approved) + approval, err := r.ETHZRC20.Allowance(&bind.CallOpts{}, r.EVMAddress(), approved) require.NoError(r, err) r.Logger.Info("Updating the bytecode of the ZRC20") @@ -95,11 +95,11 @@ func TestUpdateBytecodeZRC20(r *runner.E2ERunner, _ []string) { require.NoError(r, err) require.Equal(r, 0, totalSupply.Cmp(newTotalSupply)) - newBalance, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + newBalance, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) require.NoError(r, err) require.Equal(r, 0, balance.Cmp(newBalance)) - newApproval, err := r.ETHZRC20.Allowance(&bind.CallOpts{}, r.DeployerAddress, approved) + newApproval, err := r.ETHZRC20.Allowance(&bind.CallOpts{}, r.EVMAddress(), approved) require.NoError(r, err) require.Equal(r, 0, approval.Cmp(newApproval)) diff --git a/e2e/e2etests/test_zeta_deposit.go b/e2e/e2etests/test_zeta_deposit.go index 056ee5709f..eb8021876d 100644 --- a/e2e/e2etests/test_zeta_deposit.go +++ b/e2e/e2etests/test_zeta_deposit.go @@ -15,7 +15,7 @@ func TestZetaDeposit(r *runner.E2ERunner, args []string) { amount, ok := big.NewInt(0).SetString(args[0], 10) require.True(r, ok, "Invalid amount specified for TestZetaDeposit.") - hash := r.DepositZetaWithAmount(r.DeployerAddress, amount) + hash := r.DepositZetaWithAmount(r.EVMAddress(), amount) // wait for the cctx to be mined cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, hash.Hex(), r.CctxClient, r.Logger, r.CctxTimeout) diff --git a/e2e/e2etests/test_zeta_withdraw_bitcoin_revert.go b/e2e/e2etests/test_zeta_withdraw_bitcoin_revert.go index ae34058c94..3685dccfb3 100644 --- a/e2e/e2etests/test_zeta_withdraw_bitcoin_revert.go +++ b/e2e/e2etests/test_zeta_withdraw_bitcoin_revert.go @@ -41,7 +41,7 @@ func TestZetaWithdrawBTCRevert(r *runner.E2ERunner, args []string) { lessThanAmount := amount.Div(amount, big.NewInt(10)) // 1/10 of amount tx, err = r.ConnectorZEVM.Send(r.ZEVMAuth, connectorzevm.ZetaInterfacesSendInput{ DestinationChainId: big.NewInt(chains.BitcoinRegtest.ChainId), - DestinationAddress: r.DeployerAddress.Bytes(), + DestinationAddress: r.EVMAddress().Bytes(), DestinationGasLimit: big.NewInt(400_000), Message: nil, ZetaValueAndGas: lessThanAmount, diff --git a/e2e/e2etests/test_zrc20_swap.go b/e2e/e2etests/test_zrc20_swap.go index 661d2fc40f..14febbe800 100644 --- a/e2e/e2etests/test_zrc20_swap.go +++ b/e2e/e2etests/test_zrc20_swap.go @@ -56,7 +56,7 @@ func TestZRC20Swap(r *runner.E2ERunner, _ []string) { big.NewInt(1000), big.NewInt(90000), big.NewInt(1000), - r.DeployerAddress, + r.EVMAddress(), big.NewInt(time.Now().Add(10*time.Minute).Unix()), ) require.NoError(r, err) @@ -64,7 +64,7 @@ func TestZRC20Swap(r *runner.E2ERunner, _ []string) { receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) r.Logger.Info("Add liquidity receipt txhash %s status %d", receipt.TxHash, receipt.Status) - balETHBefore, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + balETHBefore, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) require.NoError(r, err) ethOutAmout := big.NewInt(1) @@ -73,7 +73,7 @@ func TestZRC20Swap(r *runner.E2ERunner, _ []string) { big.NewInt(1000), ethOutAmout, []ethcommon.Address{r.ERC20ZRC20Addr, r.ETHZRC20Addr}, - r.DeployerAddress, + r.EVMAddress(), big.NewInt(time.Now().Add(10*time.Minute).Unix()), ) require.NoError(r, err) @@ -81,7 +81,7 @@ func TestZRC20Swap(r *runner.E2ERunner, _ []string) { receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) r.Logger.Info("Swap ERC20 ZRC20 for ETH ZRC20 %s status %d", receipt.TxHash, receipt.Status) - balETHAfter, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + balETHAfter, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) require.NoError(r, err) ethDiff := big.NewInt(0).Sub(balETHAfter, balETHBefore) diff --git a/e2e/runner/balances.go b/e2e/runner/balances.go index 8a0c37782a..d1e19d4c61 100644 --- a/e2e/runner/balances.go +++ b/e2e/runner/balances.go @@ -33,37 +33,37 @@ type AccountBalancesDiff struct { // GetAccountBalances returns the account balances of the accounts used in the E2E test func (r *E2ERunner) GetAccountBalances(skipBTC bool) (AccountBalances, error) { // zevm - zetaZeta, err := r.ZEVMClient.BalanceAt(r.Ctx, r.DeployerAddress, nil) + zetaZeta, err := r.ZEVMClient.BalanceAt(r.Ctx, r.EVMAddress(), nil) if err != nil { return AccountBalances{}, err } - zetaWZeta, err := r.WZeta.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + zetaWZeta, err := r.WZeta.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) if err != nil { return AccountBalances{}, err } - zetaEth, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + zetaEth, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) if err != nil { return AccountBalances{}, err } - zetaErc20, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + zetaErc20, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) if err != nil { return AccountBalances{}, err } - zetaBtc, err := r.BTCZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + zetaBtc, err := r.BTCZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) if err != nil { return AccountBalances{}, err } // evm - evmEth, err := r.EVMClient.BalanceAt(r.Ctx, r.DeployerAddress, nil) + evmEth, err := r.EVMClient.BalanceAt(r.Ctx, r.EVMAddress(), nil) if err != nil { return AccountBalances{}, err } - evmZeta, err := r.ZetaEth.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + evmZeta, err := r.ZetaEth.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) if err != nil { return AccountBalances{}, err } - evmErc20, err := r.ERC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + evmErc20, err := r.ERC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) if err != nil { return AccountBalances{}, err } @@ -129,7 +129,7 @@ func (r *E2ERunner) GetBitcoinBalanceByAddress(address btcutil.Address) (btcutil // PrintAccountBalances shows the account balances of the accounts used in the E2E test // Note: USDT is mentioned as erc20 here because we want to show the balance of any erc20 contract func (r *E2ERunner) PrintAccountBalances(balances AccountBalances) { - r.Logger.Print(" ---💰 Account info %s ---", r.DeployerAddress.Hex()) + r.Logger.Print(" ---💰 Account info %s ---", r.EVMAddress().Hex()) // zevm r.Logger.Print("ZetaChain:") diff --git a/e2e/runner/bitcoin.go b/e2e/runner/bitcoin.go index c096bfc748..3165d745ca 100644 --- a/e2e/runner/bitcoin.go +++ b/e2e/runner/bitcoin.go @@ -141,7 +141,7 @@ func (r *E2ERunner) DepositBTC(testHeader bool) { ) utils.RequireCCTXStatus(r, cctx, crosschaintypes.CctxStatus_OutboundMined) - balance, err := r.BTCZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + balance, err := r.BTCZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) require.NoError(r, err) require.Equal(r, 1, balance.Sign(), "balance should be positive") @@ -156,7 +156,7 @@ func (r *E2ERunner) SendToTSSFromDeployerToDeposit(amount float64, inputUTXOs [] *chainhash.Hash, error, ) { - return r.SendToTSSFromDeployerWithMemo(amount, inputUTXOs, r.DeployerAddress.Bytes()) + return r.SendToTSSFromDeployerWithMemo(amount, inputUTXOs, r.EVMAddress().Bytes()) } func (r *E2ERunner) SendToTSSFromDeployerWithMemo( diff --git a/e2e/runner/evm.go b/e2e/runner/evm.go index 523e01e207..88c1e100bf 100644 --- a/e2e/runner/evm.go +++ b/e2e/runner/evm.go @@ -7,7 +7,6 @@ import ( ethcommon "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rpc" "github.com/stretchr/testify/require" @@ -66,7 +65,7 @@ func (r *E2ERunner) SendERC20OnEvm(address ethcommon.Address, amountERC20 int64) func (r *E2ERunner) DepositERC20() ethcommon.Hash { r.Logger.Print("⏳ depositing ERC20 into ZEVM") - return r.DepositERC20WithAmountAndMessage(r.DeployerAddress, big.NewInt(1e18), []byte{}) + return r.DepositERC20WithAmountAndMessage(r.EVMAddress(), big.NewInt(1e18), []byte{}) } func (r *E2ERunner) DepositERC20WithAmountAndMessage(to ethcommon.Address, amount *big.Int, msg []byte) ethcommon.Hash { @@ -143,7 +142,7 @@ func (r *E2ERunner) DepositEtherWithAmount(testHeader bool, amount *big.Int) eth func (r *E2ERunner) SendEther(_ ethcommon.Address, value *big.Int, data []byte) (*ethtypes.Transaction, error) { evmClient := r.EVMClient - nonce, err := evmClient.PendingNonceAt(r.Ctx, r.DeployerAddress) + nonce, err := evmClient.PendingNonceAt(r.Ctx, r.EVMAddress()) if err != nil { return nil, err } @@ -160,7 +159,7 @@ func (r *E2ERunner) SendEther(_ ethcommon.Address, value *big.Int, data []byte) return nil, err } - deployerPrivkey, err := crypto.HexToECDSA(r.DeployerPrivateKey) + deployerPrivkey, err := r.Account.PrivateKey() if err != nil { return nil, err } diff --git a/e2e/runner/runner.go b/e2e/runner/runner.go index e27de63247..a9c5c11d00 100644 --- a/e2e/runner/runner.go +++ b/e2e/runner/runner.go @@ -25,6 +25,7 @@ import ( "github.com/zeta-chain/protocol-contracts/pkg/uniswap/v2-core/contracts/uniswapv2factory.sol" uniswapv2router "github.com/zeta-chain/protocol-contracts/pkg/uniswap/v2-periphery/contracts/uniswapv2router02.sol" + "github.com/zeta-chain/zetacore/e2e/config" "github.com/zeta-chain/zetacore/e2e/contracts/contextapp" "github.com/zeta-chain/zetacore/e2e/contracts/erc20" "github.com/zeta-chain/zetacore/e2e/contracts/zevmswap" @@ -49,8 +50,7 @@ func WithZetaTxServer(txServer *txserver.ZetaTxServer) E2ERunnerOption { // It also provides some helper functions type E2ERunner struct { // accounts - DeployerAddress ethcommon.Address - DeployerPrivateKey string + Account config.Account TSSAddress ethcommon.Address BTCTSSAddress btcutil.Address BTCDeployerAddress *btcutil.AddressWitnessPubKeyHash @@ -128,8 +128,7 @@ func NewE2ERunner( ctx context.Context, name string, ctxCancel context.CancelFunc, - deployerAddress ethcommon.Address, - deployerPrivateKey string, + account config.Account, evmClient *ethclient.Client, zevmClient *ethclient.Client, cctxClient crosschaintypes.QueryClient, @@ -148,8 +147,7 @@ func NewE2ERunner( Name: name, CtxCancel: ctxCancel, - DeployerAddress: deployerAddress, - DeployerPrivateKey: deployerPrivateKey, + Account: account, ZEVMClient: zevmClient, EVMClient: evmClient, @@ -314,3 +312,8 @@ func (r *E2ERunner) FailNow() { func (r *E2ERunner) requireTxSuccessful(receipt *ethtypes.Receipt, msgAndArgs ...any) { utils.RequireTxSuccessful(r, receipt, msgAndArgs...) } + +// EVMAddress is shorthand to get the EVM address of the account +func (r *E2ERunner) EVMAddress() ethcommon.Address { + return r.Account.EVMAddress() +} diff --git a/e2e/runner/setup_bitcoin.go b/e2e/runner/setup_bitcoin.go index 92a7eac428..15b6d4a11d 100644 --- a/e2e/runner/setup_bitcoin.go +++ b/e2e/runner/setup_bitcoin.go @@ -40,7 +40,7 @@ func (r *E2ERunner) SetupBitcoinAccount(initNetwork bool) { // GetBtcAddress returns the BTC address of the deployer from its EVM private key func (r *E2ERunner) GetBtcAddress() (string, string, error) { - skBytes, err := hex.DecodeString(r.DeployerPrivateKey) + skBytes, err := hex.DecodeString(r.Account.RawPrivateKey.String()) if err != nil { return "", "", err } @@ -65,7 +65,7 @@ func (r *E2ERunner) GetBtcAddress() (string, string, error) { // SetBtcAddress imports the deployer's private key into the Bitcoin node func (r *E2ERunner) SetBtcAddress(name string, rescan bool) { - skBytes, err := hex.DecodeString(r.DeployerPrivateKey) + skBytes, err := hex.DecodeString(r.Account.RawPrivateKey.String()) require.NoError(r, err) sk, _ := btcec.PrivKeyFromBytes(btcec.S256(), skBytes) diff --git a/e2e/runner/setup_evm.go b/e2e/runner/setup_evm.go index ff5b2e0ddc..7b61d43163 100644 --- a/e2e/runner/setup_evm.go +++ b/e2e/runner/setup_evm.go @@ -28,12 +28,12 @@ func (r *E2ERunner) SetEVMContractsFromConfig() { require.NoError(r, err) // Set ZetaEthAddr - r.ZetaEthAddr = ethcommon.HexToAddress(conf.Contracts.EVM.ZetaEthAddress) + r.ZetaEthAddr = ethcommon.HexToAddress(conf.Contracts.EVM.ZetaEthAddr.String()) r.ZetaEth, err = zetaeth.NewZetaEth(r.ZetaEthAddr, r.EVMClient) require.NoError(r, err) // Set ConnectorEthAddr - r.ConnectorEthAddr = ethcommon.HexToAddress(conf.Contracts.EVM.ConnectorEthAddr) + r.ConnectorEthAddr = ethcommon.HexToAddress(conf.Contracts.EVM.ConnectorEthAddr.String()) r.ConnectorEth, err = zetaconnectoreth.NewZetaConnectorEth(r.ConnectorEthAddr, r.EVMClient) require.NoError(r, err) } @@ -66,14 +66,14 @@ func (r *E2ERunner) SetupEVM(contractsDeployed bool, whitelistERC20 bool) { zetaEthAddr, txZetaEth, ZetaEth, err := zetaeth.DeployZetaEth( r.EVMAuth, r.EVMClient, - r.DeployerAddress, + r.EVMAddress(), big.NewInt(21_000_000_000), ) require.NoError(r, err) r.ZetaEth = ZetaEth r.ZetaEthAddr = zetaEthAddr - conf.Contracts.EVM.ZetaEthAddress = zetaEthAddr.String() + conf.Contracts.EVM.ZetaEthAddr = config.DoubleQuotedString(zetaEthAddr.String()) r.Logger.Info("ZetaEth contract address: %s, tx hash: %s", zetaEthAddr.Hex(), zetaEthAddr.Hash().Hex()) r.Logger.Info("Deploying ZetaConnectorEth contract") @@ -82,14 +82,14 @@ func (r *E2ERunner) SetupEVM(contractsDeployed bool, whitelistERC20 bool) { r.EVMClient, zetaEthAddr, r.TSSAddress, - r.DeployerAddress, - r.DeployerAddress, + r.EVMAddress(), + r.EVMAddress(), ) require.NoError(r, err) r.ConnectorEth = ConnectorEth r.ConnectorEthAddr = connectorEthAddr - conf.Contracts.EVM.ConnectorEthAddr = connectorEthAddr.String() + conf.Contracts.EVM.ConnectorEthAddr = config.DoubleQuotedString(connectorEthAddr.String()) r.Logger.Info( "ZetaConnectorEth contract address: %s, tx hash: %s", @@ -101,8 +101,8 @@ func (r *E2ERunner) SetupEVM(contractsDeployed bool, whitelistERC20 bool) { erc20CustodyAddr, txCustody, ERC20Custody, err := erc20custody.DeployERC20Custody( r.EVMAuth, r.EVMClient, - r.DeployerAddress, - r.DeployerAddress, + r.EVMAddress(), + r.EVMAddress(), big.NewInt(0), big.NewInt(1e18), ethcommon.HexToAddress("0x"), diff --git a/e2e/runner/zeta.go b/e2e/runner/zeta.go index 726f3f5cb6..732104afe1 100644 --- a/e2e/runner/zeta.go +++ b/e2e/runner/zeta.go @@ -66,7 +66,7 @@ func (r *E2ERunner) DepositZeta() ethcommon.Hash { amount := big.NewInt(1e18) amount = amount.Mul(amount, big.NewInt(100)) // 100 Zeta - return r.DepositZetaWithAmount(r.DeployerAddress, amount) + return r.DepositZetaWithAmount(r.EVMAddress(), amount) } // DepositZetaWithAmount deposits ZETA on ZetaChain from the ZETA smart contract on EVM with the specified amount @@ -149,7 +149,7 @@ func (r *E2ERunner) WithdrawZeta(amount *big.Int, waitReceipt bool) *ethtypes.Tr tx, err := r.ConnectorZEVM.Send(r.ZEVMAuth, connectorzevm.ZetaInterfacesSendInput{ DestinationChainId: chainID, - DestinationAddress: r.DeployerAddress.Bytes(), + DestinationAddress: r.EVMAddress().Bytes(), DestinationGasLimit: big.NewInt(400_000), Message: nil, ZetaValueAndGas: amount, @@ -182,7 +182,7 @@ func (r *E2ERunner) WithdrawZeta(amount *big.Int, waitReceipt bool) *ethtypes.Tr // WithdrawEther withdraws Ether from ZetaChain to the ZETA smart contract on EVM func (r *E2ERunner) WithdrawEther(amount *big.Int) *ethtypes.Transaction { // withdraw - tx, err := r.ETHZRC20.Withdraw(r.ZEVMAuth, r.DeployerAddress.Bytes(), amount) + tx, err := r.ETHZRC20.Withdraw(r.ZEVMAuth, r.EVMAddress().Bytes(), amount) require.NoError(r, err) r.Logger.EVMTransaction(*tx, "withdraw") @@ -198,7 +198,7 @@ func (r *E2ERunner) WithdrawEther(amount *big.Int) *ethtypes.Transaction { // WithdrawERC20 withdraws an ERC20 token from ZetaChain to the ZETA smart contract on EVM func (r *E2ERunner) WithdrawERC20(amount *big.Int) *ethtypes.Transaction { - tx, err := r.ERC20ZRC20.Withdraw(r.ZEVMAuth, r.DeployerAddress.Bytes(), amount) + tx, err := r.ERC20ZRC20.Withdraw(r.ZEVMAuth, r.EVMAddress().Bytes(), amount) require.NoError(r, err) r.Logger.EVMTransaction(*tx, "withdraw") From ef8470cf66b10ca09a2a14570c986e8069295012 Mon Sep 17 00:00:00 2001 From: Charlie <31941002+CharlieMc0@users.noreply.github.com> Date: Thu, 27 Jun 2024 12:08:15 -0500 Subject: [PATCH 2/7] ci: enable artifact attenstations (#2388) * updated * Testing * Testing * Testing * Testing * Testing * Testing * Testing * Testing * Testing * Testing * Testing * enable all binaries * enable all binaries * Testing * Testing * Testing * Testing * Testing * enable all binaries * cleanup from testing * cleanup from testing * test default token * test default token * changed back to default token * updated changelog --------- Co-authored-by: Grant Zukel Co-authored-by: Alex Gartner --- .github/workflows/docker-build-and-push.yml | 4 ++-- .github/workflows/publish-release.yml | 24 +++++++++++++++++++-- .goreleaser.yaml | 1 - changelog.md | 2 +- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/.github/workflows/docker-build-and-push.yml b/.github/workflows/docker-build-and-push.yml index 95ca015953..c2def3200d 100644 --- a/.github/workflows/docker-build-and-push.yml +++ b/.github/workflows/docker-build-and-push.yml @@ -30,7 +30,7 @@ jobs: fetch-depth: 0 - name: Set Version from the release title. - if: github.event_name != 'workflow_dispatch' + if: github.event_name == 'workflow_dispatch' run: | echo "GITHUB_TAG_MAJOR_VERSION=${{ github.event.release.name }}" >> $GITHUB_ENV @@ -62,7 +62,7 @@ jobs: fetch-depth: 0 - name: Set Version from the release title. - if: github.event_name != 'workflow_dispatch' + if: github.event_name == 'workflow_dispatch' run: | echo "GITHUB_TAG_MAJOR_VERSION=${{ github.event.release.name }}" >> $GITHUB_ENV diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 7eded17252..97dc97aa9a 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -425,6 +425,10 @@ jobs: echo "continue" publish-release: + permissions: + id-token: write + contents: write + attestations: write if: ${{ github.event.inputs.skip_release == 'false' }} needs: - gosec @@ -495,18 +499,34 @@ jobs: uses: softprops/action-gh-release@v1 with: prerelease: true - token: ${{ secrets.PAT_GITHUB_SERVICE_ACCT }} + token: ${{ secrets.GITHUB_TOKEN }} body_path: ${{ github.workspace }}-CHANGELOG.txt tag_name: ${{ env.GITHUB_TAG_MAJOR_VERSION }} - name: Publish Release Files env: - GITHUB_TOKEN: ${{ secrets.PAT_GITHUB_SERVICE_ACCT }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GORELEASER_CURRENT_TAG: ${{ env.GITHUB_TAG_MAJOR_VERSION }} run: | touch .release-env make release + - name: Artifact Attestations + id: attestation + uses: actions/attest-build-provenance@v1 + with: + subject-path: | + dist/zetacored_**/* + dist/zetaclientd_**/* + dist/checksums.txt + + - name: Upload Attestation Bundle + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash + run: | + gh release upload ${{ env.GITHUB_TAG_MAJOR_VERSION }} ${{ steps.attestation.outputs.bundle-path }} + - name: Clean Up Workspace if: always() shell: bash diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 16541f2291..7291e57a08 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -6,7 +6,6 @@ # - Add SBOMs # - Add Docker Builds # - SLSA - https://github.com/goreleaser/goreleaser-example-slsa-provenance -# - Add Code Signing env: - CGO_ENABLED=1 diff --git a/changelog.md b/changelog.md index 1a7d568bd3..a16cd90d2d 100644 --- a/changelog.md +++ b/changelog.md @@ -88,7 +88,7 @@ * [2382](https://github.com/zeta-chain/node/pull/2382) - add tx input and gas in rpc methods for synthetic eth txs ### CI - +* [2388](https://github.com/zeta-chain/node/pull/2388) - added GitHub attestations of binaries produced in the release workflow. * [2285](https://github.com/zeta-chain/node/pull/2285) - added nightly EVM performance testing pipeline, modified localnet testing docker image to utilitze debian:bookworm, removed build-jet runners where applicable, removed deprecated/removed upgrade path testing pipeline * [2268](https://github.com/zeta-chain/node/pull/2268) - updated the publish-release pipeline to utilize the Github Actions Ubuntu 20.04 Runners * [2070](https://github.com/zeta-chain/node/pull/2070) - Added commands to build binaries from the working branch as a live full node rpc to test non-governance changes From 0660e73614aec34f15515a378557b046c6b07346 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jun 2024 10:13:41 +0200 Subject: [PATCH 3/7] chore(deps): bump github.com/hashicorp/go-getter from 1.7.4 to 1.7.5 (#2392) Bumps [github.com/hashicorp/go-getter](https://github.com/hashicorp/go-getter) from 1.7.4 to 1.7.5. - [Release notes](https://github.com/hashicorp/go-getter/releases) - [Changelog](https://github.com/hashicorp/go-getter/blob/main/.goreleaser.yml) - [Commits](https://github.com/hashicorp/go-getter/compare/v1.7.4...v1.7.5) --- updated-dependencies: - dependency-name: github.com/hashicorp/go-getter dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alex Gartner --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 60a7598f16..43584e6b4e 100644 --- a/go.mod +++ b/go.mod @@ -215,7 +215,7 @@ require ( github.com/gtank/ristretto255 v0.1.2 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-getter v1.7.4 + github.com/hashicorp/go-getter v1.7.5 github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect github.com/hashicorp/go-version v1.6.0 // indirect diff --git a/go.sum b/go.sum index a5bbf02ee3..ad13862826 100644 --- a/go.sum +++ b/go.sum @@ -921,8 +921,8 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-getter v1.7.4 h1:3yQjWuxICvSpYwqSayAdKRFcvBl1y/vogCxczWSmix0= -github.com/hashicorp/go-getter v1.7.4/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-getter v1.7.5 h1:dT58k9hQ/vbxNMwoI5+xFYAJuv6152UNvdHokfI5wE4= +github.com/hashicorp/go-getter v1.7.5/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= From 86298f28d8a4e6ea00f316840f409bcd4186dafa Mon Sep 17 00:00:00 2001 From: Alex Gartner Date: Fri, 28 Jun 2024 09:09:49 -0700 Subject: [PATCH 4/7] chore: update PR template (#2394) * chore: update PR template * remove checklist --- .github/pull_request_template.md | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 09a533c5d6..7abe7810e0 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,26 +1,13 @@ # Description -Please include a summary of the changes and the related issue. Please also include relevant motivation and context. List any dependencies that are required for this change. - -Closes: - -## Type of change - -- [ ] Bug fix (non-breaking change which fixes an issue) -- [ ] New feature (non-breaking change which adds functionality) -- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) -- [ ] This change requires a documentation update + # How Has This Been Tested? -Please describe the tests that you ran to verify your changes. Include instructions and any relevant details so others can reproduce. + - [ ] Tested CCTX in localnet - [ ] Tested in development environment - [ ] Go unit tests - [ ] Go integration tests -- [ ] Tested via GitHub Actions - -# Checklist: - -- [ ] I have added unit tests that prove my fix feature works +- [ ] Tested via GitHub Actions From 0bcb422e614c3e1b2c565de83017c93538ff668c Mon Sep 17 00:00:00 2001 From: Francisco de Borja Aranda Castillejo Date: Mon, 1 Jul 2024 19:11:00 +0200 Subject: [PATCH 5/7] chore: add fbac as codeowner (#2410) Signed-off-by: Francisco de Borja Aranda Castillejo Co-authored-by: Francisco de Borja Aranda Castillejo --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 65567bd2ab..084809afa5 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,3 @@ -* @brewmaster012 @kingpinXD @lumtis @ws4charlie @skosito @swift1337 +* @brewmaster012 @kingpinXD @lumtis @ws4charlie @skosito @swift1337 @fbac .github/** @zeta-chain/devops From 2d5519f4d64bb05b64e6f2c7ec9ef6a87e97610f Mon Sep 17 00:00:00 2001 From: Dmitry S <11892559+swift1337@users.noreply.github.com> Date: Mon, 1 Jul 2024 21:04:06 +0200 Subject: [PATCH 6/7] feat(zetaclient): converge AppContext with ZetaCoreContext (#2395) * Converge AppContext and ZetaCoreContext * Embed AppContext into context.Context * Fix code after converging AppContext with ZetaCoreContext * Update changelog * Address PR comments * Add more test cases for AppContext --- changelog.md | 1 + cmd/zetaclientd/debug.go | 282 +++++++-------- cmd/zetaclientd/keygen_tss.go | 2 +- cmd/zetaclientd/start.go | 8 +- cmd/zetaclientd/utils.go | 16 +- zetaclient/chains/base/observer.go | 20 +- zetaclient/chains/base/observer_test.go | 25 +- zetaclient/chains/base/signer.go | 25 +- zetaclient/chains/base/signer_test.go | 13 +- zetaclient/chains/bitcoin/observer/inbound.go | 7 +- .../chains/bitcoin/observer/observer.go | 4 +- .../chains/bitcoin/observer/observer_test.go | 10 +- .../chains/bitcoin/observer/outbound.go | 3 +- zetaclient/chains/bitcoin/signer/signer.go | 6 +- zetaclient/chains/evm/observer/inbound.go | 9 +- zetaclient/chains/evm/observer/observer.go | 4 +- .../chains/evm/observer/observer_test.go | 9 +- zetaclient/chains/evm/observer/outbound.go | 3 +- zetaclient/chains/evm/signer/signer.go | 6 +- zetaclient/chains/evm/signer/signer_test.go | 6 +- zetaclient/config/config_chain.go | 7 +- zetaclient/context/app.go | 287 +++++++++++++++ zetaclient/context/app_context.go | 46 --- zetaclient/context/app_context_test.go | 1 - .../{zetacore_context_test.go => app_test.go} | 331 ++++++++++++------ zetaclient/context/context.go | 26 ++ zetaclient/context/context_test.go | 40 +++ zetaclient/context/zetacore_context.go | 253 ------------- zetaclient/orchestrator/orchestrator.go | 19 +- zetaclient/orchestrator/orchestrator_test.go | 23 +- .../supplychecker/zeta_supply_checker.go | 10 +- zetaclient/tss/tss_signer.go | 2 +- zetaclient/zetacore/client.go | 7 +- zetaclient/zetacore/tx.go | 2 +- zetaclient/zetacore/tx_test.go | 4 +- 35 files changed, 835 insertions(+), 682 deletions(-) create mode 100644 zetaclient/context/app.go delete mode 100644 zetaclient/context/app_context.go delete mode 100644 zetaclient/context/app_context_test.go rename zetaclient/context/{zetacore_context_test.go => app_test.go} (55%) create mode 100644 zetaclient/context/context.go create mode 100644 zetaclient/context/context_test.go delete mode 100644 zetaclient/context/zetacore_context.go diff --git a/changelog.md b/changelog.md index a16cd90d2d..4e7cd838a0 100644 --- a/changelog.md +++ b/changelog.md @@ -55,6 +55,7 @@ * [2357](https://github.com/zeta-chain/node/pull/2357) - integrate base Signer structure into EVM/Bitcoin Signer * [2359](https://github.com/zeta-chain/node/pull/2359) - integrate base Observer structure into EVM/Bitcoin Observer * [2375](https://github.com/zeta-chain/node/pull/2375) - improve & speedup code formatting +* [2395](https://github.com/zeta-chain/node/pull/2395) - converge AppContext with ZetaCoreContext in zetaclient ### Tests diff --git a/cmd/zetaclientd/debug.go b/cmd/zetaclientd/debug.go index 8aaeb6384e..08aadbe8a4 100644 --- a/cmd/zetaclientd/debug.go +++ b/cmd/zetaclientd/debug.go @@ -11,6 +11,7 @@ import ( ethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/onrik/ethrpc" + "github.com/rs/zerolog" "github.com/spf13/cobra" "github.com/zeta-chain/zetacore/pkg/chains" @@ -42,163 +43,166 @@ func init() { } func DebugCmd() *cobra.Command { - cmd := &cobra.Command{ + return &cobra.Command{ Use: "get-inbound-ballot [inboundHash] [chainID]", Short: "provide txHash and chainID to get the ballot status for the txHash", - RunE: func(_ *cobra.Command, args []string) error { - cobra.ExactArgs(2) - cfg, err := config.Load(debugArgs.zetaCoreHome) - if err != nil { - return err - } - coreContext := clientcontext.NewZetacoreContext(cfg) - chainID, err := strconv.ParseInt(args[1], 10, 64) - if err != nil { - return err - } - inboundHash := args[0] - var ballotIdentifier string - - // create a new zetacore client - client, err := zetacore.NewClient( - &keys.Keys{OperatorAddress: sdk.MustAccAddressFromBech32(sample.AccAddress())}, - debugArgs.zetaNode, - "", - debugArgs.zetaChainID, - false, - nil) - if err != nil { - return err - } - chainParams, err := client.GetChainParams() - if err != nil { - return err - } - tssEthAddress, err := client.GetEthTssAddress() - if err != nil { - return err - } - chain := chains.GetChainFromChainID(chainID) - if chain == nil { - return fmt.Errorf("invalid chain id") - } + RunE: debugCmd, + } +} - // get ballot identifier according to the chain type - if chains.IsEVMChain(chain.ChainId) { - evmObserver := evmobserver.Observer{} - evmObserver.WithZetacoreClient(client) - var ethRPC *ethrpc.EthRPC - var client *ethclient.Client - coinType := coin.CoinType_Cmd - for chain, evmConfig := range cfg.GetAllEVMConfigs() { - if chainID == chain { - ethRPC = ethrpc.NewEthRPC(evmConfig.Endpoint) - client, err = ethclient.Dial(evmConfig.Endpoint) - if err != nil { - return err - } - evmObserver.WithEvmClient(client) - evmObserver.WithEvmJSONRPC(ethRPC) - evmObserver.WithChain(*chains.GetChainFromChainID(chainID)) - } - } - hash := ethcommon.HexToHash(inboundHash) - tx, isPending, err := evmObserver.TransactionByHash(inboundHash) - if err != nil { - return fmt.Errorf("tx not found on chain %s , %d", err.Error(), chain.ChainId) - } - if isPending { - return fmt.Errorf("tx is still pending") - } - receipt, err := client.TransactionReceipt(context.Background(), hash) - if err != nil { - return fmt.Errorf("tx receipt not found on chain %s, %d", err.Error(), chain.ChainId) - } +func debugCmd(_ *cobra.Command, args []string) error { + cobra.ExactArgs(2) + cfg, err := config.Load(debugArgs.zetaCoreHome) + if err != nil { + return err + } - for _, chainParams := range chainParams { - if chainParams.ChainId == chainID { - evmObserver.SetChainParams(observertypes.ChainParams{ - ChainId: chainID, - ConnectorContractAddress: chainParams.ConnectorContractAddress, - ZetaTokenContractAddress: chainParams.ZetaTokenContractAddress, - Erc20CustodyContractAddress: chainParams.Erc20CustodyContractAddress, - }) - evmChainParams, found := coreContext.GetEVMChainParams(chainID) - if !found { - return fmt.Errorf("missing chain params for chain %d", chainID) - } - evmChainParams.ZetaTokenContractAddress = chainParams.ZetaTokenContractAddress - if strings.EqualFold(tx.To, chainParams.ConnectorContractAddress) { - coinType = coin.CoinType_Zeta - } else if strings.EqualFold(tx.To, chainParams.Erc20CustodyContractAddress) { - coinType = coin.CoinType_ERC20 - } else if strings.EqualFold(tx.To, tssEthAddress) { - coinType = coin.CoinType_Gas - } - } - } + appContext := clientcontext.New(cfg, zerolog.Nop()) - switch coinType { - case coin.CoinType_Zeta: - ballotIdentifier, err = evmObserver.CheckAndVoteInboundTokenZeta(tx, receipt, false) - if err != nil { - return err - } - - case coin.CoinType_ERC20: - ballotIdentifier, err = evmObserver.CheckAndVoteInboundTokenERC20(tx, receipt, false) - if err != nil { - return err - } - - case coin.CoinType_Gas: - ballotIdentifier, err = evmObserver.CheckAndVoteInboundTokenGas(tx, receipt, false) - if err != nil { - return err - } - default: - fmt.Println("CoinType not detected") - } - fmt.Println("CoinType : ", coinType) - } else if chains.IsBitcoinChain(chain.ChainId) { - btcObserver := btcobserver.Observer{} - btcObserver.WithZetacoreClient(client) - btcObserver.WithChain(*chains.GetChainFromChainID(chainID)) - connCfg := &rpcclient.ConnConfig{ - Host: cfg.BitcoinConfig.RPCHost, - User: cfg.BitcoinConfig.RPCUsername, - Pass: cfg.BitcoinConfig.RPCPassword, - HTTPPostMode: true, - DisableTLS: true, - Params: cfg.BitcoinConfig.RPCParams, - } + chainID, err := strconv.ParseInt(args[1], 10, 64) + if err != nil { + return err + } + + inboundHash := args[0] + var ballotIdentifier string + + // create a new zetacore client + client, err := zetacore.NewClient( + &keys.Keys{OperatorAddress: sdk.MustAccAddressFromBech32(sample.AccAddress())}, + debugArgs.zetaNode, + "", + debugArgs.zetaChainID, + false, + nil) + if err != nil { + return err + } + chainParams, err := client.GetChainParams() + if err != nil { + return err + } + tssEthAddress, err := client.GetEthTssAddress() + if err != nil { + return err + } + chain := chains.GetChainFromChainID(chainID) + if chain == nil { + return fmt.Errorf("invalid chain id") + } - btcClient, err := rpcclient.New(connCfg, nil) + // get ballot identifier according to the chain type + if chains.IsEVMChain(chain.ChainId) { + evmObserver := evmobserver.Observer{} + evmObserver.WithZetacoreClient(client) + var ethRPC *ethrpc.EthRPC + var client *ethclient.Client + coinType := coin.CoinType_Cmd + for chain, evmConfig := range cfg.GetAllEVMConfigs() { + if chainID == chain { + ethRPC = ethrpc.NewEthRPC(evmConfig.Endpoint) + client, err = ethclient.Dial(evmConfig.Endpoint) if err != nil { return err } - btcObserver.WithBtcClient(btcClient) - ballotIdentifier, err = btcObserver.CheckReceiptForBtcTxHash(inboundHash, false) - if err != nil { - return err + evmObserver.WithEvmClient(client) + evmObserver.WithEvmJSONRPC(ethRPC) + evmObserver.WithChain(*chains.GetChainFromChainID(chainID)) + } + } + hash := ethcommon.HexToHash(inboundHash) + tx, isPending, err := evmObserver.TransactionByHash(inboundHash) + if err != nil { + return fmt.Errorf("tx not found on chain %s , %d", err.Error(), chain.ChainId) + } + if isPending { + return fmt.Errorf("tx is still pending") + } + receipt, err := client.TransactionReceipt(context.Background(), hash) + if err != nil { + return fmt.Errorf("tx receipt not found on chain %s, %d", err.Error(), chain.ChainId) + } + + for _, chainParams := range chainParams { + if chainParams.ChainId == chainID { + evmObserver.SetChainParams(observertypes.ChainParams{ + ChainId: chainID, + ConnectorContractAddress: chainParams.ConnectorContractAddress, + ZetaTokenContractAddress: chainParams.ZetaTokenContractAddress, + Erc20CustodyContractAddress: chainParams.Erc20CustodyContractAddress, + }) + evmChainParams, found := appContext.GetEVMChainParams(chainID) + if !found { + return fmt.Errorf("missing chain params for chain %d", chainID) + } + evmChainParams.ZetaTokenContractAddress = chainParams.ZetaTokenContractAddress + if strings.EqualFold(tx.To, chainParams.ConnectorContractAddress) { + coinType = coin.CoinType_Zeta + } else if strings.EqualFold(tx.To, chainParams.Erc20CustodyContractAddress) { + coinType = coin.CoinType_ERC20 + } else if strings.EqualFold(tx.To, tssEthAddress) { + coinType = coin.CoinType_Gas } } - fmt.Println("BallotIdentifier : ", ballotIdentifier) + } - // query ballot - ballot, err := client.GetBallot(ballotIdentifier) + switch coinType { + case coin.CoinType_Zeta: + ballotIdentifier, err = evmObserver.CheckAndVoteInboundTokenZeta(tx, receipt, false) if err != nil { return err } - for _, vote := range ballot.Voters { - fmt.Printf("%s : %s \n", vote.VoterAddress, vote.VoteType) + case coin.CoinType_ERC20: + ballotIdentifier, err = evmObserver.CheckAndVoteInboundTokenERC20(tx, receipt, false) + if err != nil { + return err } - fmt.Println("BallotStatus : ", ballot.BallotStatus) - return nil - }, + case coin.CoinType_Gas: + ballotIdentifier, err = evmObserver.CheckAndVoteInboundTokenGas(tx, receipt, false) + if err != nil { + return err + } + default: + fmt.Println("CoinType not detected") + } + fmt.Println("CoinType : ", coinType) + } else if chains.IsBitcoinChain(chain.ChainId) { + btcObserver := btcobserver.Observer{} + btcObserver.WithZetacoreClient(client) + btcObserver.WithChain(*chains.GetChainFromChainID(chainID)) + connCfg := &rpcclient.ConnConfig{ + Host: cfg.BitcoinConfig.RPCHost, + User: cfg.BitcoinConfig.RPCUsername, + Pass: cfg.BitcoinConfig.RPCPassword, + HTTPPostMode: true, + DisableTLS: true, + Params: cfg.BitcoinConfig.RPCParams, + } + + btcClient, err := rpcclient.New(connCfg, nil) + if err != nil { + return err + } + btcObserver.WithBtcClient(btcClient) + ballotIdentifier, err = btcObserver.CheckReceiptForBtcTxHash(inboundHash, false) + if err != nil { + return err + } + } + fmt.Println("BallotIdentifier : ", ballotIdentifier) + + // query ballot + ballot, err := client.GetBallot(ballotIdentifier) + if err != nil { + return err + } + + for _, vote := range ballot.Voters { + fmt.Printf("%s : %s \n", vote.VoterAddress, vote.VoteType) } + fmt.Println("BallotStatus : ", ballot.BallotStatus) - return cmd + return nil } diff --git a/cmd/zetaclientd/keygen_tss.go b/cmd/zetaclientd/keygen_tss.go index 007ce9ec8c..63b5d98041 100644 --- a/cmd/zetaclientd/keygen_tss.go +++ b/cmd/zetaclientd/keygen_tss.go @@ -74,7 +74,7 @@ func GenerateTss( // This loop will try keygen at the keygen block and then wait for keygen to be successfully reported by all nodes before breaking out of the loop. // If keygen is unsuccessful, it will reset the triedKeygenAtBlock flag and try again at a new keygen block. - keyGen := appContext.ZetacoreContext().GetKeygen() + keyGen := appContext.GetKeygen() if keyGen.Status == observertypes.KeygenStatus_KeyGenSuccess { return tss, nil } diff --git a/cmd/zetaclientd/start.go b/cmd/zetaclientd/start.go index c815b616c0..3546cec8ad 100644 --- a/cmd/zetaclientd/start.go +++ b/cmd/zetaclientd/start.go @@ -144,8 +144,8 @@ func start(_ *cobra.Command, _ []string) error { startLogger.Debug().Msgf("CreateAuthzSigner is ready") // Initialize core parameters from zetacore - appContext := context.NewAppContext(context.NewZetacoreContext(cfg), cfg) - err = zetacoreClient.UpdateZetacoreContext(appContext.ZetacoreContext(), true, startLogger) + appContext := context.New(cfg, masterLogger) + err = zetacoreClient.UpdateZetacoreContext(appContext, true, startLogger) if err != nil { startLogger.Error().Err(err).Msg("Error getting core parameters") return err @@ -226,7 +226,7 @@ func start(_ *cobra.Command, _ []string) error { // For existing keygen, this should directly proceed to the next step ticker := time.NewTicker(time.Second * 1) for range ticker.C { - keyGen := appContext.ZetacoreContext().GetKeygen() + keyGen := appContext.GetKeygen() if keyGen.Status != observerTypes.KeygenStatus_KeyGenSuccess { startLogger.Info().Msgf("Waiting for TSS Keygen to be a success, current status %s", keyGen.Status) continue @@ -250,7 +250,7 @@ func start(_ *cobra.Command, _ []string) error { } startLogger.Info(). Msgf("Current TSS address \n ETH : %s \n BTC : %s \n PubKey : %s ", tss.EVMAddress(), tss.BTCAddress(), tss.CurrentPubkey) - if len(appContext.ZetacoreContext().GetEnabledChains()) == 0 { + if len(appContext.GetEnabledChains()) == 0 { startLogger.Error().Msgf("No chains enabled in updated config %s ", cfg.String()) } diff --git a/cmd/zetaclientd/utils.go b/cmd/zetaclientd/utils.go index 99dd26c487..99f6e03e59 100644 --- a/cmd/zetaclientd/utils.go +++ b/cmd/zetaclientd/utils.go @@ -65,7 +65,6 @@ func CreateSignerMap( logger base.Logger, ts *metrics.TelemetryServer, ) (map[int64]interfaces.ChainSigner, error) { - zetacoreContext := appContext.ZetacoreContext() signerMap := make(map[int64]interfaces.ChainSigner) // EVM signers @@ -73,7 +72,7 @@ func CreateSignerMap( if evmConfig.Chain.IsZetaChain() { continue } - evmChainParams, found := zetacoreContext.GetEVMChainParams(evmConfig.Chain.ChainId) + evmChainParams, found := appContext.GetEVMChainParams(evmConfig.Chain.ChainId) if !found { logger.Std.Error().Msgf("ChainParam not found for chain %s", evmConfig.Chain.String()) continue @@ -82,7 +81,7 @@ func CreateSignerMap( erc20CustodyAddress := ethcommon.HexToAddress(evmChainParams.Erc20CustodyContractAddress) signer, err := evmsigner.NewSigner( evmConfig.Chain, - zetacoreContext, + appContext, tss, ts, logger, @@ -100,7 +99,7 @@ func CreateSignerMap( // BTC signer btcChain, btcConfig, enabled := appContext.GetBTCChainAndConfig() if enabled { - signer, err := btcsigner.NewSigner(btcChain, zetacoreContext, tss, ts, logger, btcConfig) + signer, err := btcsigner.NewSigner(btcChain, appContext, tss, ts, logger, btcConfig) if err != nil { logger.Std.Error().Err(err).Msgf("NewBTCSigner error for chain %s", btcChain.String()) } else { @@ -120,14 +119,13 @@ func CreateChainObserverMap( logger base.Logger, ts *metrics.TelemetryServer, ) (map[int64]interfaces.ChainObserver, error) { - zetacoreContext := appContext.ZetacoreContext() observerMap := make(map[int64]interfaces.ChainObserver) // EVM observers for _, evmConfig := range appContext.Config().GetAllEVMConfigs() { if evmConfig.Chain.IsZetaChain() { continue } - chainParams, found := zetacoreContext.GetEVMChainParams(evmConfig.Chain.ChainId) + chainParams, found := appContext.GetEVMChainParams(evmConfig.Chain.ChainId) if !found { logger.Std.Error().Msgf("ChainParam not found for chain %s", evmConfig.Chain.String()) continue @@ -145,7 +143,7 @@ func CreateChainObserverMap( evmConfig, evmClient, *chainParams, - zetacoreContext, + appContext, zetacoreClient, tss, dbpath, @@ -160,7 +158,7 @@ func CreateChainObserverMap( } // BTC observer - _, chainParams, found := zetacoreContext.GetBTCChainParams() + _, chainParams, found := appContext.GetBTCChainParams() if !found { return nil, fmt.Errorf("bitcoin chains params not found") } @@ -177,7 +175,7 @@ func CreateChainObserverMap( btcChain, btcClient, *chainParams, - zetacoreContext, + appContext, zetacoreClient, tss, dbpath, diff --git a/zetaclient/chains/base/observer.go b/zetaclient/chains/base/observer.go index 1f3fc2d0ca..edfef83629 100644 --- a/zetaclient/chains/base/observer.go +++ b/zetaclient/chains/base/observer.go @@ -45,8 +45,8 @@ type Observer struct { // chainParams contains the dynamic chain parameters of the observed chain chainParams observertypes.ChainParams - // coreContext contains context data of ZetaChain - zetacoreContext *context.ZetacoreContext + // appContext contains context data for zetaclient & zetacore (e.g. supported chains) + appContext *context.AppContext // zetacoreClient is the client to interact with ZetaChain zetacoreClient interfaces.ZetacoreClient @@ -87,7 +87,7 @@ type Observer struct { func NewObserver( chain chains.Chain, chainParams observertypes.ChainParams, - zetacoreContext *context.ZetacoreContext, + appContext *context.AppContext, zetacoreClient interfaces.ZetacoreClient, tss interfaces.TSSSigner, blockCacheSize int, @@ -98,7 +98,7 @@ func NewObserver( ob := Observer{ chain: chain, chainParams: chainParams, - zetacoreContext: zetacoreContext, + appContext: appContext, zetacoreClient: zetacoreClient, tss: tss, lastBlock: 0, @@ -164,15 +164,9 @@ func (ob *Observer) WithChainParams(params observertypes.ChainParams) *Observer return ob } -// ZetacoreContext returns the zetacore context for the observer. -func (ob *Observer) ZetacoreContext() *context.ZetacoreContext { - return ob.zetacoreContext -} - -// WithZetacoreContext attaches a new zetacore context to the observer. -func (ob *Observer) WithZetacoreContext(context *context.ZetacoreContext) *Observer { - ob.zetacoreContext = context - return ob +// AppContext returns the zetacore context for the observer. +func (ob *Observer) AppContext() *context.AppContext { + return ob.appContext } // ZetacoreClient returns the zetacore client for the observer. diff --git a/zetaclient/chains/base/observer_test.go b/zetaclient/chains/base/observer_test.go index a04a48fcc3..e6d5a088a9 100644 --- a/zetaclient/chains/base/observer_test.go +++ b/zetaclient/chains/base/observer_test.go @@ -5,6 +5,7 @@ import ( "testing" lru "github.com/hashicorp/golang-lru" + "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/zetaclient/testutils" @@ -25,7 +26,7 @@ func createObserver(t *testing.T) *base.Observer { // constructor parameters chain := chains.Ethereum chainParams := *sample.ChainParams(chain.ChainId) - zetacoreContext := context.NewZetacoreContext(config.NewConfig()) + appContext := context.New(config.NewConfig(), zerolog.Nop()) zetacoreClient := mocks.NewMockZetacoreClient() tss := mocks.NewTSSMainnet() @@ -34,7 +35,7 @@ func createObserver(t *testing.T) *base.Observer { ob, err := base.NewObserver( chain, chainParams, - zetacoreContext, + appContext, zetacoreClient, tss, base.DefaultBlockCacheSize, @@ -51,7 +52,7 @@ func TestNewObserver(t *testing.T) { // constructor parameters chain := chains.Ethereum chainParams := *sample.ChainParams(chain.ChainId) - zetacoreContext := context.NewZetacoreContext(config.NewConfig()) + appContext := context.New(config.NewConfig(), zerolog.Nop()) zetacoreClient := mocks.NewMockZetacoreClient() tss := mocks.NewTSSMainnet() blockCacheSize := base.DefaultBlockCacheSize @@ -62,7 +63,7 @@ func TestNewObserver(t *testing.T) { name string chain chains.Chain chainParams observertypes.ChainParams - zetacoreContext *context.ZetacoreContext + appContext *context.AppContext zetacoreClient interfaces.ZetacoreClient tss interfaces.TSSSigner blockCacheSize int @@ -74,7 +75,7 @@ func TestNewObserver(t *testing.T) { name: "should be able to create new observer", chain: chain, chainParams: chainParams, - zetacoreContext: zetacoreContext, + appContext: appContext, zetacoreClient: zetacoreClient, tss: tss, blockCacheSize: blockCacheSize, @@ -85,7 +86,7 @@ func TestNewObserver(t *testing.T) { name: "should return error on invalid block cache size", chain: chain, chainParams: chainParams, - zetacoreContext: zetacoreContext, + appContext: appContext, zetacoreClient: zetacoreClient, tss: tss, blockCacheSize: 0, @@ -97,7 +98,7 @@ func TestNewObserver(t *testing.T) { name: "should return error on invalid header cache size", chain: chain, chainParams: chainParams, - zetacoreContext: zetacoreContext, + appContext: appContext, zetacoreClient: zetacoreClient, tss: tss, blockCacheSize: blockCacheSize, @@ -113,7 +114,7 @@ func TestNewObserver(t *testing.T) { ob, err := base.NewObserver( tt.chain, tt.chainParams, - tt.zetacoreContext, + tt.appContext, tt.zetacoreClient, tt.tss, tt.blockCacheSize, @@ -161,14 +162,6 @@ func TestObserverGetterAndSetter(t *testing.T) { ob = ob.WithChainParams(newChainParams) require.True(t, observertypes.ChainParamsEqual(newChainParams, ob.ChainParams())) }) - t.Run("should be able to update zetacore context", func(t *testing.T) { - ob := createObserver(t) - - // update zetacore context - newZetacoreContext := context.NewZetacoreContext(config.NewConfig()) - ob = ob.WithZetacoreContext(newZetacoreContext) - require.Equal(t, newZetacoreContext, ob.ZetacoreContext()) - }) t.Run("should be able to update zetacore client", func(t *testing.T) { ob := createObserver(t) diff --git a/zetaclient/chains/base/signer.go b/zetaclient/chains/base/signer.go index bc5ad7934f..0fc9ca4837 100644 --- a/zetaclient/chains/base/signer.go +++ b/zetaclient/chains/base/signer.go @@ -15,8 +15,7 @@ type Signer struct { // chain contains static information about the external chain chain chains.Chain - // zetacoreContext is the Zetacore client to interact with ZetaChain - zetacoreContext *context.ZetacoreContext + appContext *context.AppContext // tss is the TSS signer tss interfaces.TSSSigner @@ -35,16 +34,16 @@ type Signer struct { // NewSigner creates a new base signer func NewSigner( chain chains.Chain, - zetacoreContext *context.ZetacoreContext, + zetacoreContext *context.AppContext, tss interfaces.TSSSigner, ts *metrics.TelemetryServer, logger Logger, ) *Signer { return &Signer{ - chain: chain, - zetacoreContext: zetacoreContext, - tss: tss, - ts: ts, + chain: chain, + appContext: zetacoreContext, + tss: tss, + ts: ts, logger: Logger{ Std: logger.Std.With().Int64("chain", chain.ChainId).Str("module", "signer").Logger(), Compliance: logger.Compliance, @@ -63,15 +62,9 @@ func (s *Signer) WithChain(chain chains.Chain) *Signer { return s } -// ZetacoreContext returns the zetacore context for the signer -func (s *Signer) ZetacoreContext() *context.ZetacoreContext { - return s.zetacoreContext -} - -// WithZetacoreContext attaches a new zetacore context to the signer -func (s *Signer) WithZetacoreContext(context *context.ZetacoreContext) *Signer { - s.zetacoreContext = context - return s +// AppContext returns the zetacore context for the signer +func (s *Signer) AppContext() *context.AppContext { + return s.appContext } // Tss returns the tss signer for the signer diff --git a/zetaclient/chains/base/signer_test.go b/zetaclient/chains/base/signer_test.go index 960c508d6e..a0e2696b92 100644 --- a/zetaclient/chains/base/signer_test.go +++ b/zetaclient/chains/base/signer_test.go @@ -3,6 +3,7 @@ package base_test import ( "testing" + "github.com/rs/zerolog" "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/pkg/chains" @@ -17,12 +18,12 @@ import ( func createSigner(_ *testing.T) *base.Signer { // constructor parameters chain := chains.Ethereum - zetacoreContext := context.NewZetacoreContext(config.NewConfig()) + appContext := context.New(config.NewConfig(), zerolog.Nop()) tss := mocks.NewTSSMainnet() logger := base.DefaultLogger() // create signer - return base.NewSigner(chain, zetacoreContext, tss, nil, logger) + return base.NewSigner(chain, appContext, tss, nil, logger) } func TestNewSigner(t *testing.T) { @@ -39,14 +40,6 @@ func TestSignerGetterAndSetter(t *testing.T) { signer = signer.WithChain(chains.BscMainnet) require.Equal(t, newChain, signer.Chain()) }) - t.Run("should be able to update zetacore context", func(t *testing.T) { - signer := createSigner(t) - - // update zetacore context - newZetacoreContext := context.NewZetacoreContext(config.NewConfig()) - signer = signer.WithZetacoreContext(newZetacoreContext) - require.Equal(t, newZetacoreContext, signer.ZetacoreContext()) - }) t.Run("should be able to update tss", func(t *testing.T) { signer := createSigner(t) diff --git a/zetaclient/chains/bitcoin/observer/inbound.go b/zetaclient/chains/bitcoin/observer/inbound.go index 037fd11cd1..1d528a7c62 100644 --- a/zetaclient/chains/bitcoin/observer/inbound.go +++ b/zetaclient/chains/bitcoin/observer/inbound.go @@ -20,7 +20,6 @@ import ( "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" "github.com/zeta-chain/zetacore/zetaclient/compliance" "github.com/zeta-chain/zetacore/zetaclient/config" - "github.com/zeta-chain/zetacore/zetaclient/context" "github.com/zeta-chain/zetacore/zetaclient/types" "github.com/zeta-chain/zetacore/zetaclient/zetacore" ) @@ -43,7 +42,7 @@ func (ob *Observer) WatchInbound() { for { select { case <-ticker.C(): - if !context.IsInboundObservationEnabled(ob.ZetacoreContext(), ob.GetChainParams()) { + if !ob.AppContext().IsInboundObservationEnabled(ob.GetChainParams()) { sampledLogger.Info(). Msgf("WatchInbound: inbound observation is disabled for chain %d", ob.Chain().ChainId) continue @@ -109,7 +108,7 @@ func (ob *Observer) ObserveInbound() error { // https://github.com/zeta-chain/node/issues/1847 // TODO: move this logic in its own routine // https://github.com/zeta-chain/node/issues/2204 - blockHeaderVerification, found := ob.ZetacoreContext().GetBlockHeaderEnabledChains(ob.Chain().ChainId) + blockHeaderVerification, found := ob.AppContext().GetBlockHeaderEnabledChains(ob.Chain().ChainId) if found && blockHeaderVerification.Enabled { // #nosec G701 always in range err = ob.postBlockHeader(int64(blockNumber)) @@ -187,7 +186,7 @@ func (ob *Observer) WatchInboundTracker() { for { select { case <-ticker.C(): - if !context.IsInboundObservationEnabled(ob.ZetacoreContext(), ob.GetChainParams()) { + if !ob.AppContext().IsInboundObservationEnabled(ob.GetChainParams()) { continue } err := ob.ProcessInboundTrackers() diff --git a/zetaclient/chains/bitcoin/observer/observer.go b/zetaclient/chains/bitcoin/observer/observer.go index 11ccc5460a..a04188da80 100644 --- a/zetaclient/chains/bitcoin/observer/observer.go +++ b/zetaclient/chains/bitcoin/observer/observer.go @@ -112,7 +112,7 @@ func NewObserver( chain chains.Chain, btcClient interfaces.BTCRPCClient, chainParams observertypes.ChainParams, - zetacoreContext *context.ZetacoreContext, + appContext *context.AppContext, zetacoreClient interfaces.ZetacoreClient, tss interfaces.TSSSigner, dbpath string, @@ -123,7 +123,7 @@ func NewObserver( baseObserver, err := base.NewObserver( chain, chainParams, - zetacoreContext, + appContext, zetacoreClient, tss, btcBlocksPerDay, diff --git a/zetaclient/chains/bitcoin/observer/observer_test.go b/zetaclient/chains/bitcoin/observer/observer_test.go index c79209e3fc..8fb8838ae3 100644 --- a/zetaclient/chains/bitcoin/observer/observer_test.go +++ b/zetaclient/chains/bitcoin/observer/observer_test.go @@ -113,7 +113,7 @@ func Test_NewObserver(t *testing.T) { chain chains.Chain btcClient interfaces.BTCRPCClient chainParams observertypes.ChainParams - coreContext *context.ZetacoreContext + appContext *context.AppContext coreClient interfaces.ZetacoreClient tss interfaces.TSSSigner dbpath string @@ -127,7 +127,7 @@ func Test_NewObserver(t *testing.T) { chain: chain, btcClient: mocks.NewMockBTCRPCClient().WithBlockCount(100), chainParams: params, - coreContext: nil, + appContext: nil, coreClient: nil, tss: mocks.NewTSSMainnet(), dbpath: sample.CreateTempDir(t), @@ -140,7 +140,7 @@ func Test_NewObserver(t *testing.T) { chain: chains.Chain{ChainId: 111}, // invalid chain id btcClient: mocks.NewMockBTCRPCClient().WithBlockCount(100), chainParams: params, - coreContext: nil, + appContext: nil, coreClient: nil, tss: mocks.NewTSSMainnet(), dbpath: sample.CreateTempDir(t), @@ -153,7 +153,7 @@ func Test_NewObserver(t *testing.T) { name: "should fail on invalid dbpath", chain: chain, chainParams: params, - coreContext: nil, + appContext: nil, coreClient: nil, btcClient: mocks.NewMockBTCRPCClient().WithBlockCount(100), tss: mocks.NewTSSMainnet(), @@ -173,7 +173,7 @@ func Test_NewObserver(t *testing.T) { tt.chain, tt.btcClient, tt.chainParams, - tt.coreContext, + tt.appContext, tt.coreClient, tt.tss, tt.dbpath, diff --git a/zetaclient/chains/bitcoin/observer/outbound.go b/zetaclient/chains/bitcoin/observer/outbound.go index 5f4684f50f..681604d48b 100644 --- a/zetaclient/chains/bitcoin/observer/outbound.go +++ b/zetaclient/chains/bitcoin/observer/outbound.go @@ -16,7 +16,6 @@ import ( "github.com/zeta-chain/zetacore/zetaclient/chains/bitcoin/rpc" "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" "github.com/zeta-chain/zetacore/zetaclient/compliance" - "github.com/zeta-chain/zetacore/zetaclient/context" "github.com/zeta-chain/zetacore/zetaclient/types" ) @@ -44,7 +43,7 @@ func (ob *Observer) WatchOutbound() { for { select { case <-ticker.C(): - if !context.IsOutboundObservationEnabled(ob.ZetacoreContext(), ob.GetChainParams()) { + if !ob.AppContext().IsOutboundObservationEnabled(ob.GetChainParams()) { sampledLogger.Info(). Msgf("WatchOutbound: outbound observation is disabled for chain %d", chainID) continue diff --git a/zetaclient/chains/bitcoin/signer/signer.go b/zetaclient/chains/bitcoin/signer/signer.go index eae11a68ce..259f55bc53 100644 --- a/zetaclient/chains/bitcoin/signer/signer.go +++ b/zetaclient/chains/bitcoin/signer/signer.go @@ -58,13 +58,13 @@ type Signer struct { // NewSigner creates a new Bitcoin signer func NewSigner( chain chains.Chain, - zetacoreContext *context.ZetacoreContext, + appContext *context.AppContext, tss interfaces.TSSSigner, ts *metrics.TelemetryServer, logger base.Logger, cfg config.BTCConfig) (*Signer, error) { // create base signer - baseSigner := base.NewSigner(chain, zetacoreContext, tss, ts, logger) + baseSigner := base.NewSigner(chain, appContext, tss, ts, logger) // create the bitcoin rpc client using the provided config connCfg := &rpcclient.ConnConfig{ @@ -350,7 +350,7 @@ func (signer *Signer) TryProcessOutbound( logger.Error().Msgf("chain observer is not a bitcoin observer") return } - flags := signer.ZetacoreContext().GetCrossChainFlags() + flags := signer.AppContext().GetCrossChainFlags() if !flags.IsOutboundEnabled { logger.Info().Msgf("outbound is disabled") return diff --git a/zetaclient/chains/evm/observer/inbound.go b/zetaclient/chains/evm/observer/inbound.go index 40844ddbd7..20823f533b 100644 --- a/zetaclient/chains/evm/observer/inbound.go +++ b/zetaclient/chains/evm/observer/inbound.go @@ -27,7 +27,6 @@ import ( "github.com/zeta-chain/zetacore/zetaclient/chains/evm" "github.com/zeta-chain/zetacore/zetaclient/compliance" "github.com/zeta-chain/zetacore/zetaclient/config" - clientcontext "github.com/zeta-chain/zetacore/zetaclient/context" "github.com/zeta-chain/zetacore/zetaclient/metrics" clienttypes "github.com/zeta-chain/zetacore/zetaclient/types" "github.com/zeta-chain/zetacore/zetaclient/zetacore" @@ -52,7 +51,7 @@ func (ob *Observer) WatchInbound() { for { select { case <-ticker.C(): - if !clientcontext.IsInboundObservationEnabled(ob.ZetacoreContext(), ob.GetChainParams()) { + if !ob.AppContext().IsInboundObservationEnabled(ob.GetChainParams()) { sampledLogger.Info(). Msgf("WatchInbound: inbound observation is disabled for chain %d", ob.Chain().ChainId) continue @@ -87,7 +86,7 @@ func (ob *Observer) WatchInboundTracker() { for { select { case <-ticker.C(): - if !clientcontext.IsInboundObservationEnabled(ob.ZetacoreContext(), ob.GetChainParams()) { + if !ob.AppContext().IsInboundObservationEnabled(ob.GetChainParams()) { continue } err := ob.ProcessInboundTrackers() @@ -395,7 +394,7 @@ func (ob *Observer) ObserverTSSReceive(startBlock, toBlock uint64) uint64 { // post new block header (if any) to zetacore and ignore error // TODO: consider having a independent ticker(from TSS scaning) for posting block headers // https://github.com/zeta-chain/node/issues/1847 - blockHeaderVerification, found := ob.ZetacoreContext().GetBlockHeaderEnabledChains(ob.Chain().ChainId) + blockHeaderVerification, found := ob.AppContext().GetBlockHeaderEnabledChains(ob.Chain().ChainId) if found && blockHeaderVerification.Enabled { // post block header for supported chains // TODO: move this logic in its own routine @@ -659,7 +658,7 @@ func (ob *Observer) BuildInboundVoteMsgForZetaSentEvent( } if !destChain.IsZetaChain() { - paramsDest, found := ob.ZetacoreContext().GetEVMChainParams(destChain.ChainId) + paramsDest, found := ob.AppContext().GetEVMChainParams(destChain.ChainId) if !found { ob.Logger().Inbound.Warn(). Msgf("chain id not present in EVMChainParams %d", event.DestinationChainId.Int64()) diff --git a/zetaclient/chains/evm/observer/observer.go b/zetaclient/chains/evm/observer/observer.go index 0a33603196..3a60b16e40 100644 --- a/zetaclient/chains/evm/observer/observer.go +++ b/zetaclient/chains/evm/observer/observer.go @@ -58,7 +58,7 @@ func NewObserver( evmCfg config.EVMConfig, evmClient interfaces.EVMRPCClient, chainParams observertypes.ChainParams, - zetacoreContext *clientcontext.ZetacoreContext, + appClient *clientcontext.AppContext, zetacoreClient interfaces.ZetacoreClient, tss interfaces.TSSSigner, dbpath string, @@ -69,7 +69,7 @@ func NewObserver( baseObserver, err := base.NewObserver( evmCfg.Chain, chainParams, - zetacoreContext, + appClient, zetacoreClient, tss, base.DefaultBlockCacheSize, diff --git a/zetaclient/chains/evm/observer/observer_test.go b/zetaclient/chains/evm/observer/observer_test.go index f149d1bae2..6cb97dd65d 100644 --- a/zetaclient/chains/evm/observer/observer_test.go +++ b/zetaclient/chains/evm/observer/observer_test.go @@ -37,7 +37,7 @@ func getZetacoreContext( evmChain chains.Chain, endpoint string, evmChainParams *observertypes.ChainParams, -) (*context.ZetacoreContext, config.EVMConfig) { +) (*context.AppContext, config.EVMConfig) { // use default endpoint if not provided if endpoint == "" { endpoint = "http://localhost:8545" @@ -51,12 +51,12 @@ func getZetacoreContext( } // create zetacore context - coreCtx := context.NewZetacoreContext(cfg) + appContext := context.New(cfg, zerolog.Nop()) evmChainParamsMap := make(map[int64]*observertypes.ChainParams) evmChainParamsMap[evmChain.ChainId] = evmChainParams // feed chain params - coreCtx.Update( + appContext.Update( &observertypes.Keygen{}, []chains.Chain{evmChain}, evmChainParamsMap, @@ -65,10 +65,9 @@ func getZetacoreContext( *sample.CrosschainFlags(), sample.HeaderSupportedChains(), true, - zerolog.Logger{}, ) // create app context - return coreCtx, cfg.EVMChainConfigs[evmChain.ChainId] + return appContext, cfg.EVMChainConfigs[evmChain.ChainId] } // MockEVMObserver creates a mock ChainObserver with custom chain, TSS, params etc diff --git a/zetaclient/chains/evm/observer/outbound.go b/zetaclient/chains/evm/observer/outbound.go index 2f3d3c136f..84103620dd 100644 --- a/zetaclient/chains/evm/observer/outbound.go +++ b/zetaclient/chains/evm/observer/outbound.go @@ -23,7 +23,6 @@ import ( "github.com/zeta-chain/zetacore/zetaclient/chains/evm" "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" "github.com/zeta-chain/zetacore/zetaclient/compliance" - clientcontext "github.com/zeta-chain/zetacore/zetaclient/context" clienttypes "github.com/zeta-chain/zetacore/zetaclient/types" ) @@ -52,7 +51,7 @@ func (ob *Observer) WatchOutbound() { for { select { case <-ticker.C(): - if !clientcontext.IsOutboundObservationEnabled(ob.ZetacoreContext(), ob.GetChainParams()) { + if !ob.AppContext().IsOutboundObservationEnabled(ob.GetChainParams()) { sampledLogger.Info(). Msgf("WatchOutbound: outbound observation is disabled for chain %d", ob.Chain().ChainId) continue diff --git a/zetaclient/chains/evm/signer/signer.go b/zetaclient/chains/evm/signer/signer.go index 3ea7852766..8bba72d777 100644 --- a/zetaclient/chains/evm/signer/signer.go +++ b/zetaclient/chains/evm/signer/signer.go @@ -82,7 +82,7 @@ type Signer struct { // NewSigner creates a new EVM signer func NewSigner( chain chains.Chain, - zetacoreContext *clientcontext.ZetacoreContext, + appContext *clientcontext.AppContext, tss interfaces.TSSSigner, ts *metrics.TelemetryServer, logger base.Logger, @@ -93,7 +93,7 @@ func NewSigner( erc20CustodyAddress ethcommon.Address, ) (*Signer, error) { // create base signer - baseSigner := base.NewSigner(chain, zetacoreContext, tss, ts, logger) + baseSigner := base.NewSigner(chain, appContext, tss, ts, logger) // create EVM client client, ethSigner, err := getEVMRPC(endpoint) @@ -376,7 +376,7 @@ func (signer *Signer) TryProcessOutbound( toChain := chains.GetChainFromChainID(txData.toChainID.Int64()) // Get cross-chain flags - crossChainflags := signer.ZetacoreContext().GetCrossChainFlags() + crossChainflags := signer.AppContext().GetCrossChainFlags() // https://github.com/zeta-chain/node/issues/2050 var tx *ethtypes.Transaction // compliance check goes first diff --git a/zetaclient/chains/evm/signer/signer_test.go b/zetaclient/chains/evm/signer/signer_test.go index ea27152b97..13aaac87b1 100644 --- a/zetaclient/chains/evm/signer/signer_test.go +++ b/zetaclient/chains/evm/signer/signer_test.go @@ -47,7 +47,7 @@ func getNewEvmSigner(tss interfaces.TSSSigner) (*Signer, error) { return NewSigner( chains.BscMainnet, - context.NewZetacoreContext(cfg), + context.New(cfg, zerolog.Nop()), tss, nil, logger, @@ -71,7 +71,7 @@ func getNewEvmChainObserver(t *testing.T, tss interfaces.TSSSigner) (*observer.O evmClient := mocks.NewMockEvmClient().WithBlockNumber(1000) params := mocks.MockChainParams(evmcfg.Chain.ChainId, 10) cfg.EVMChainConfigs[chains.BscMainnet.ChainId] = evmcfg - coreCTX := context.NewZetacoreContext(cfg) + appContext := context.New(cfg, zerolog.Nop()) dbpath := sample.CreateTempDir(t) logger := base.Logger{} ts := &metrics.TelemetryServer{} @@ -80,7 +80,7 @@ func getNewEvmChainObserver(t *testing.T, tss interfaces.TSSSigner) (*observer.O evmcfg, evmClient, params, - coreCTX, + appContext, mocks.NewMockZetacoreClient(), tss, dbpath, diff --git a/zetaclient/config/config_chain.go b/zetaclient/config/config_chain.go index 5c2ed1d077..5946c4ca62 100644 --- a/zetaclient/config/config_chain.go +++ b/zetaclient/config/config_chain.go @@ -1,6 +1,10 @@ package config -import "github.com/zeta-chain/zetacore/pkg/chains" +import ( + "sync" + + "github.com/zeta-chain/zetacore/pkg/chains" +) const ( MaxBlocksPerPeriod = 100 @@ -32,6 +36,7 @@ func GetERC20CustodyABI() string { // It is initialize with default chain configs func New() Config { return Config{ + cfgLock: &sync.RWMutex{}, EVMChainConfigs: evmChainsConfigs, BitcoinConfig: bitcoinConfigRegnet, } diff --git a/zetaclient/context/app.go b/zetaclient/context/app.go new file mode 100644 index 0000000000..c40e769492 --- /dev/null +++ b/zetaclient/context/app.go @@ -0,0 +1,287 @@ +// Package context provides global app context for ZetaClient +package context + +import ( + "sort" + "sync" + + "github.com/rs/zerolog" + + "github.com/zeta-chain/zetacore/pkg/chains" + lightclienttypes "github.com/zeta-chain/zetacore/x/lightclient/types" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" + "github.com/zeta-chain/zetacore/zetaclient/config" +) + +// AppContext represents application context. +type AppContext struct { + config config.Config + logger zerolog.Logger + + keygen observertypes.Keygen + chainsEnabled []chains.Chain + evmChainParams map[int64]*observertypes.ChainParams + bitcoinChainParams *observertypes.ChainParams + currentTssPubkey string + crosschainFlags observertypes.CrosschainFlags + + // blockHeaderEnabledChains is used to store the list of chains that have block header verification enabled + // All chains in this list will have Enabled flag set to true + blockHeaderEnabledChains []lightclienttypes.HeaderSupportedChain + + mu sync.RWMutex +} + +// New creates and returns new AppContext +func New(cfg config.Config, logger zerolog.Logger) *AppContext { + evmChainParams := make(map[int64]*observertypes.ChainParams) + for _, e := range cfg.EVMChainConfigs { + evmChainParams[e.Chain.ChainId] = &observertypes.ChainParams{} + } + + var bitcoinChainParams *observertypes.ChainParams + _, found := cfg.GetBTCConfig() + if found { + bitcoinChainParams = &observertypes.ChainParams{} + } + + return &AppContext{ + config: cfg, + logger: logger.With().Str("module", "appcontext").Logger(), + + chainsEnabled: []chains.Chain{}, + evmChainParams: evmChainParams, + bitcoinChainParams: bitcoinChainParams, + crosschainFlags: observertypes.CrosschainFlags{}, + blockHeaderEnabledChains: []lightclienttypes.HeaderSupportedChain{}, + + currentTssPubkey: "", + keygen: observertypes.Keygen{}, + mu: sync.RWMutex{}, + } +} + +// Config returns the config of the app +func (a *AppContext) Config() config.Config { + return a.config +} + +// GetBTCChainAndConfig returns btc chain and config if enabled +func (a *AppContext) GetBTCChainAndConfig() (chains.Chain, config.BTCConfig, bool) { + btcConfig, configEnabled := a.Config().GetBTCConfig() + btcChain, _, paramsEnabled := a.GetBTCChainParams() + + if !configEnabled || !paramsEnabled { + return chains.Chain{}, config.BTCConfig{}, false + } + + return btcChain, btcConfig, true +} + +// IsOutboundObservationEnabled returns true if the chain is supported and outbound flag is enabled +func (a *AppContext) IsOutboundObservationEnabled(chainParams observertypes.ChainParams) bool { + flags := a.GetCrossChainFlags() + return chainParams.IsSupported && flags.IsOutboundEnabled +} + +// IsInboundObservationEnabled returns true if the chain is supported and inbound flag is enabled +func (a *AppContext) IsInboundObservationEnabled(chainParams observertypes.ChainParams) bool { + flags := a.GetCrossChainFlags() + return chainParams.IsSupported && flags.IsInboundEnabled +} + +// GetKeygen returns the current keygen +func (a *AppContext) GetKeygen() observertypes.Keygen { + a.mu.RLock() + defer a.mu.RUnlock() + + var copiedPubkeys []string + if a.keygen.GranteePubkeys != nil { + copiedPubkeys = make([]string, len(a.keygen.GranteePubkeys)) + copy(copiedPubkeys, a.keygen.GranteePubkeys) + } + + return observertypes.Keygen{ + Status: a.keygen.Status, + GranteePubkeys: copiedPubkeys, + BlockNumber: a.keygen.BlockNumber, + } +} + +// GetCurrentTssPubKey returns the current tss pubkey +func (a *AppContext) GetCurrentTssPubKey() string { + a.mu.RLock() + defer a.mu.RUnlock() + + return a.currentTssPubkey +} + +// GetEnabledChains returns all enabled chains including zetachain +func (a *AppContext) GetEnabledChains() []chains.Chain { + a.mu.RLock() + defer a.mu.RUnlock() + + copiedChains := make([]chains.Chain, len(a.chainsEnabled)) + copy(copiedChains, a.chainsEnabled) + + return copiedChains +} + +// GetEnabledExternalChains returns all enabled external chains +func (a *AppContext) GetEnabledExternalChains() []chains.Chain { + a.mu.RLock() + defer a.mu.RUnlock() + + externalChains := make([]chains.Chain, 0) + for _, chain := range a.chainsEnabled { + if chain.IsExternal { + externalChains = append(externalChains, chain) + } + } + return externalChains +} + +// GetEVMChainParams returns chain params for a specific EVM chain +func (a *AppContext) GetEVMChainParams(chainID int64) (*observertypes.ChainParams, bool) { + a.mu.RLock() + defer a.mu.RUnlock() + + evmChainParams, found := a.evmChainParams[chainID] + return evmChainParams, found +} + +// GetAllEVMChainParams returns all chain params for EVM chains +func (a *AppContext) GetAllEVMChainParams() map[int64]*observertypes.ChainParams { + a.mu.RLock() + defer a.mu.RUnlock() + + // deep copy evm chain params + copied := make(map[int64]*observertypes.ChainParams, len(a.evmChainParams)) + for chainID, evmConfig := range a.evmChainParams { + copied[chainID] = &observertypes.ChainParams{} + *copied[chainID] = *evmConfig + } + return copied +} + +// GetBTCChainParams returns (chain, chain params, found) for bitcoin chain +func (a *AppContext) GetBTCChainParams() (chains.Chain, *observertypes.ChainParams, bool) { + a.mu.RLock() + defer a.mu.RUnlock() + + if a.bitcoinChainParams == nil { // bitcoin is not enabled + return chains.Chain{}, nil, false + } + + chain := chains.GetChainFromChainID(a.bitcoinChainParams.ChainId) + if chain == nil { + return chains.Chain{}, nil, false + } + + return *chain, a.bitcoinChainParams, true +} + +// GetCrossChainFlags returns crosschain flags +func (a *AppContext) GetCrossChainFlags() observertypes.CrosschainFlags { + a.mu.RLock() + defer a.mu.RUnlock() + + return a.crosschainFlags +} + +// GetAllHeaderEnabledChains returns all verification flags +func (a *AppContext) GetAllHeaderEnabledChains() []lightclienttypes.HeaderSupportedChain { + a.mu.RLock() + defer a.mu.RUnlock() + + return a.blockHeaderEnabledChains +} + +// GetBlockHeaderEnabledChains checks if block header verification is enabled for a specific chain +func (a *AppContext) GetBlockHeaderEnabledChains(chainID int64) (lightclienttypes.HeaderSupportedChain, bool) { + a.mu.RLock() + defer a.mu.RUnlock() + + for _, flags := range a.blockHeaderEnabledChains { + if flags.ChainId == chainID { + return flags, true + } + } + + return lightclienttypes.HeaderSupportedChain{}, false +} + +// Update updates zetacore context and params for all chains +// this must be the ONLY function that writes to zetacore context +func (a *AppContext) Update( + keygen *observertypes.Keygen, + newChains []chains.Chain, + evmChainParams map[int64]*observertypes.ChainParams, + btcChainParams *observertypes.ChainParams, + tssPubKey string, + crosschainFlags observertypes.CrosschainFlags, + blockHeaderEnabledChains []lightclienttypes.HeaderSupportedChain, + init bool, +) { + // Ignore whatever order zetacore organizes chain list in state + sort.SliceStable(newChains, func(i, j int) bool { + return newChains[i].ChainId < newChains[j].ChainId + }) + + if len(newChains) == 0 { + a.logger.Warn().Msg("UpdateChainParams: No chains enabled in ZeroCore") + } + + a.mu.Lock() + defer a.mu.Unlock() + + // Add some warnings if chain list changes at runtime + if !init && !chainsEqual(a.chainsEnabled, newChains) { + a.logger.Warn(). + Interface("chains.current", a.chainsEnabled). + Interface("chains.new", newChains). + Msg("UpdateChainParams: ChainsEnabled changed at runtime!") + } + + if keygen != nil { + a.keygen = *keygen + } + + a.chainsEnabled = newChains + a.crosschainFlags = crosschainFlags + a.blockHeaderEnabledChains = blockHeaderEnabledChains + + // update chain params for bitcoin if it has config in file + if a.bitcoinChainParams != nil && btcChainParams != nil { + a.bitcoinChainParams = btcChainParams + } + + // update core params for evm chains we have configs in file + for _, params := range evmChainParams { + _, found := a.evmChainParams[params.ChainId] + if !found { + continue + } + a.evmChainParams[params.ChainId] = params + } + + if tssPubKey != "" { + a.currentTssPubkey = tssPubKey + } +} + +func chainsEqual(a []chains.Chain, b []chains.Chain) bool { + if len(a) != len(b) { + return false + } + + for i, left := range a { + right := b[i] + + if left.ChainId != right.ChainId || left.ChainName != right.ChainName { + return false + } + } + + return true +} diff --git a/zetaclient/context/app_context.go b/zetaclient/context/app_context.go deleted file mode 100644 index ffdfa05604..0000000000 --- a/zetaclient/context/app_context.go +++ /dev/null @@ -1,46 +0,0 @@ -// Package context provides global app context for ZetaClient -package context - -import ( - "github.com/zeta-chain/zetacore/pkg/chains" - "github.com/zeta-chain/zetacore/zetaclient/config" -) - -// AppContext contains global app structs like config, zetacore context and logger -type AppContext struct { - coreContext *ZetacoreContext - config config.Config -} - -// NewAppContext creates and returns new AppContext -func NewAppContext( - coreContext *ZetacoreContext, - config config.Config, -) *AppContext { - return &AppContext{ - coreContext: coreContext, - config: config, - } -} - -// Config returns the config of the app -func (a AppContext) Config() config.Config { - return a.config -} - -// ZetacoreContext returns the context for ZetaChain -func (a AppContext) ZetacoreContext() *ZetacoreContext { - return a.coreContext -} - -// GetBTCChainAndConfig returns btc chain and config if enabled -func (a AppContext) GetBTCChainAndConfig() (chains.Chain, config.BTCConfig, bool) { - btcConfig, configEnabled := a.Config().GetBTCConfig() - btcChain, _, paramsEnabled := a.coreContext.GetBTCChainParams() - - if !configEnabled || !paramsEnabled { - return chains.Chain{}, config.BTCConfig{}, false - } - - return btcChain, btcConfig, true -} diff --git a/zetaclient/context/app_context_test.go b/zetaclient/context/app_context_test.go deleted file mode 100644 index 960b2b7c5a..0000000000 --- a/zetaclient/context/app_context_test.go +++ /dev/null @@ -1 +0,0 @@ -package context_test diff --git a/zetaclient/context/zetacore_context_test.go b/zetaclient/context/app_test.go similarity index 55% rename from zetaclient/context/zetacore_context_test.go rename to zetaclient/context/app_test.go index d8117e124b..99b56c7d88 100644 --- a/zetaclient/context/zetacore_context_test.go +++ b/zetaclient/context/app_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/rs/zerolog" - "github.com/rs/zerolog/log" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/pkg/chains" @@ -12,68 +12,40 @@ import ( lightclienttypes "github.com/zeta-chain/zetacore/x/lightclient/types" observertypes "github.com/zeta-chain/zetacore/x/observer/types" "github.com/zeta-chain/zetacore/zetaclient/config" - context "github.com/zeta-chain/zetacore/zetaclient/context" + "github.com/zeta-chain/zetacore/zetaclient/context" ) -func getTestCoreContext( - evmChain chains.Chain, - evmChainParams *observertypes.ChainParams, - ccFlags observertypes.CrosschainFlags, - headerSupportedChains []lightclienttypes.HeaderSupportedChain, -) *context.ZetacoreContext { - // create config - cfg := config.NewConfig() - cfg.EVMChainConfigs[evmChain.ChainId] = config.EVMConfig{ - Chain: evmChain, - } - // create zetacore context - coreContext := context.NewZetacoreContext(cfg) - evmChainParamsMap := make(map[int64]*observertypes.ChainParams) - evmChainParamsMap[evmChain.ChainId] = evmChainParams - - // feed chain params - coreContext.Update( - &observertypes.Keygen{}, - []chains.Chain{evmChain}, - evmChainParamsMap, - nil, - "", - ccFlags, - headerSupportedChains, - true, - zerolog.Logger{}, +func TestNew(t *testing.T) { + var ( + testCfg = config.NewConfig() + logger = zerolog.Nop() ) - return coreContext -} -func TestNewZetaCoreContext(t *testing.T) { t.Run("should create new zetacore context with empty config", func(t *testing.T) { - testCfg := config.NewConfig() - - zetaContext := context.NewZetacoreContext(testCfg) - require.NotNil(t, zetaContext) + appContext := context.New(testCfg, logger) + require.NotNil(t, appContext) // assert keygen - keyGen := zetaContext.GetKeygen() + keyGen := appContext.GetKeygen() require.Equal(t, observertypes.Keygen{}, keyGen) // assert enabled chains - require.Empty(t, len(zetaContext.GetEnabledChains())) + require.Empty(t, len(appContext.GetEnabledChains())) // assert external chains - require.Empty(t, len(zetaContext.GetEnabledExternalChains())) + require.Empty(t, len(appContext.GetEnabledExternalChains())) // assert current tss pubkey - require.Equal(t, "", zetaContext.GetCurrentTssPubkey()) + require.Equal(t, "", appContext.GetCurrentTssPubKey()) // assert btc chain params - chain, btcChainParams, btcChainParamsFound := zetaContext.GetBTCChainParams() + chain, btcChainParams, btcChainParamsFound := appContext.GetBTCChainParams() require.Equal(t, chains.Chain{}, chain) require.False(t, btcChainParamsFound) require.Nil(t, btcChainParams) // assert evm chain params - allEVMChainParams := zetaContext.GetAllEVMChainParams() + allEVMChainParams := appContext.GetAllEVMChainParams() require.Empty(t, allEVMChainParams) }) @@ -86,11 +58,11 @@ func TestNewZetaCoreContext(t *testing.T) { } // create zetacore context with 0 chain id - zetaContext := context.NewZetacoreContext(testCfg) - require.NotNil(t, zetaContext) + appContext := context.New(testCfg, logger) + require.NotNil(t, appContext) // assert btc chain params - chain, btcChainParams, btcChainParamsFound := zetaContext.GetBTCChainParams() + chain, btcChainParams, btcChainParamsFound := appContext.GetBTCChainParams() require.Equal(t, chains.Chain{}, chain) require.False(t, btcChainParamsFound) require.Nil(t, btcChainParams) @@ -112,20 +84,20 @@ func TestNewZetaCoreContext(t *testing.T) { }, }, } - zetaContext := context.NewZetacoreContext(testCfg) - require.NotNil(t, zetaContext) + appContext := context.New(testCfg, logger) + require.NotNil(t, appContext) // assert evm chain params - allEVMChainParams := zetaContext.GetAllEVMChainParams() + allEVMChainParams := appContext.GetAllEVMChainParams() require.Equal(t, 2, len(allEVMChainParams)) require.Equal(t, &observertypes.ChainParams{}, allEVMChainParams[1]) require.Equal(t, &observertypes.ChainParams{}, allEVMChainParams[2]) - evmChainParams1, found := zetaContext.GetEVMChainParams(1) + evmChainParams1, found := appContext.GetEVMChainParams(1) require.True(t, found) require.Equal(t, &observertypes.ChainParams{}, evmChainParams1) - evmChainParams2, found := zetaContext.GetEVMChainParams(2) + evmChainParams2, found := appContext.GetEVMChainParams(2) require.True(t, found) require.Equal(t, &observertypes.ChainParams{}, evmChainParams2) }) @@ -138,17 +110,20 @@ func TestNewZetaCoreContext(t *testing.T) { RPCHost: "test host", RPCParams: "test params", } - zetaContext := context.NewZetacoreContext(testCfg) - require.NotNil(t, zetaContext) + appContext := context.New(testCfg, logger) + require.NotNil(t, appContext) }) } -func TestUpdateZetacoreContext(t *testing.T) { - t.Run("should update zetacore context after being created from empty config", func(t *testing.T) { - testCfg := config.NewConfig() +func TestAppContextUpdate(t *testing.T) { + var ( + testCfg = config.NewConfig() + logger = zerolog.Nop() + ) - zetaContext := context.NewZetacoreContext(testCfg) - require.NotNil(t, zetaContext) + t.Run("should update zetacore context after being created from empty config", func(t *testing.T) { + appContext := context.New(testCfg, logger) + require.NotNil(t, appContext) keyGenToUpdate := observertypes.Keygen{ Status: observertypes.KeygenStatus_KeyGenSuccess, @@ -183,7 +158,7 @@ func TestUpdateZetacoreContext(t *testing.T) { verificationFlags := sample.HeaderSupportedChains() require.NotNil(t, crosschainFlags) - zetaContext.Update( + appContext.Update( &keyGenToUpdate, enabledChainsToUpdate, evmChainParamsToUpdate, @@ -192,36 +167,35 @@ func TestUpdateZetacoreContext(t *testing.T) { *crosschainFlags, verificationFlags, false, - log.Logger, ) // assert keygen updated - keyGen := zetaContext.GetKeygen() + keyGen := appContext.GetKeygen() require.Equal(t, keyGenToUpdate, keyGen) // assert enabled chains updated - require.Equal(t, enabledChainsToUpdate, zetaContext.GetEnabledChains()) + require.Equal(t, enabledChainsToUpdate, appContext.GetEnabledChains()) // assert enabled external chains - require.Equal(t, enabledChainsToUpdate[0:2], zetaContext.GetEnabledExternalChains()) + require.Equal(t, enabledChainsToUpdate[0:2], appContext.GetEnabledExternalChains()) // assert current tss pubkey updated - require.Equal(t, tssPubKeyToUpdate, zetaContext.GetCurrentTssPubkey()) + require.Equal(t, tssPubKeyToUpdate, appContext.GetCurrentTssPubKey()) // assert btc chain params still empty because they were not specified in config - chain, btcChainParams, btcChainParamsFound := zetaContext.GetBTCChainParams() + chain, btcChainParams, btcChainParamsFound := appContext.GetBTCChainParams() require.Equal(t, chains.Chain{}, chain) require.False(t, btcChainParamsFound) require.Nil(t, btcChainParams) // assert evm chain params still empty because they were not specified in config - allEVMChainParams := zetaContext.GetAllEVMChainParams() + allEVMChainParams := appContext.GetAllEVMChainParams() require.Empty(t, allEVMChainParams) - ccFlags := zetaContext.GetCrossChainFlags() + ccFlags := appContext.GetCrossChainFlags() require.Equal(t, *crosschainFlags, ccFlags) - verFlags := zetaContext.GetAllHeaderEnabledChains() + verFlags := appContext.GetAllHeaderEnabledChains() require.Equal(t, verificationFlags, verFlags) }) @@ -250,8 +224,8 @@ func TestUpdateZetacoreContext(t *testing.T) { RPCParams: "test params", } - zetaContext := context.NewZetacoreContext(testCfg) - require.NotNil(t, zetaContext) + appContext := context.New(testCfg, logger) + require.NotNil(t, appContext) keyGenToUpdate := observertypes.Keygen{ Status: observertypes.KeygenStatus_KeyGenSuccess, @@ -284,7 +258,7 @@ func TestUpdateZetacoreContext(t *testing.T) { crosschainFlags := sample.CrosschainFlags() verificationFlags := sample.HeaderSupportedChains() require.NotNil(t, crosschainFlags) - zetaContext.Update( + appContext.Update( &keyGenToUpdate, enabledChainsToUpdate, evmChainParamsToUpdate, @@ -293,41 +267,40 @@ func TestUpdateZetacoreContext(t *testing.T) { *crosschainFlags, verificationFlags, false, - log.Logger, ) // assert keygen updated - keyGen := zetaContext.GetKeygen() + keyGen := appContext.GetKeygen() require.Equal(t, keyGenToUpdate, keyGen) // assert enabled chains updated - require.Equal(t, enabledChainsToUpdate, zetaContext.GetEnabledChains()) + require.Equal(t, enabledChainsToUpdate, appContext.GetEnabledChains()) // assert current tss pubkey updated - require.Equal(t, tssPubKeyToUpdate, zetaContext.GetCurrentTssPubkey()) + require.Equal(t, tssPubKeyToUpdate, appContext.GetCurrentTssPubKey()) // assert btc chain params - chain, btcChainParams, btcChainParamsFound := zetaContext.GetBTCChainParams() + chain, btcChainParams, btcChainParamsFound := appContext.GetBTCChainParams() require.Equal(t, testBtcChain, chain) require.True(t, btcChainParamsFound) require.Equal(t, btcChainParamsToUpdate, btcChainParams) // assert evm chain params - allEVMChainParams := zetaContext.GetAllEVMChainParams() + allEVMChainParams := appContext.GetAllEVMChainParams() require.Equal(t, evmChainParamsToUpdate, allEVMChainParams) - evmChainParams1, found := zetaContext.GetEVMChainParams(1) + evmChainParams1, found := appContext.GetEVMChainParams(1) require.True(t, found) require.Equal(t, evmChainParamsToUpdate[1], evmChainParams1) - evmChainParams2, found := zetaContext.GetEVMChainParams(2) + evmChainParams2, found := appContext.GetEVMChainParams(2) require.True(t, found) require.Equal(t, evmChainParamsToUpdate[2], evmChainParams2) - ccFlags := zetaContext.GetCrossChainFlags() + ccFlags := appContext.GetCrossChainFlags() require.Equal(t, ccFlags, *crosschainFlags) - verFlags := zetaContext.GetAllHeaderEnabledChains() + verFlags := appContext.GetAllHeaderEnabledChains() require.Equal(t, verFlags, verificationFlags) }, ) @@ -344,22 +317,22 @@ func TestIsOutboundObservationEnabled(t *testing.T) { } t.Run("should return true if chain is supported and outbound flag is enabled", func(t *testing.T) { - coreCTX := getTestCoreContext(evmChain, chainParams, ccFlags, verificationFlags) - require.True(t, context.IsOutboundObservationEnabled(coreCTX, *chainParams)) + appContext := makeAppContext(evmChain, chainParams, ccFlags, verificationFlags) + + require.True(t, appContext.IsOutboundObservationEnabled(*chainParams)) }) t.Run("should return false if chain is not supported yet", func(t *testing.T) { - paramsUnsupported := &observertypes.ChainParams{ - ChainId: evmChain.ChainId, - IsSupported: false, - } - coreCTXUnsupported := getTestCoreContext(evmChain, paramsUnsupported, ccFlags, verificationFlags) - require.False(t, context.IsOutboundObservationEnabled(coreCTXUnsupported, *paramsUnsupported)) + paramsUnsupported := &observertypes.ChainParams{ChainId: evmChain.ChainId, IsSupported: false} + appContextUnsupported := makeAppContext(evmChain, paramsUnsupported, ccFlags, verificationFlags) + + require.False(t, appContextUnsupported.IsOutboundObservationEnabled(*paramsUnsupported)) }) t.Run("should return false if outbound flag is disabled", func(t *testing.T) { flagsDisabled := ccFlags flagsDisabled.IsOutboundEnabled = false - coreCTXDisabled := getTestCoreContext(evmChain, chainParams, flagsDisabled, verificationFlags) - require.False(t, context.IsOutboundObservationEnabled(coreCTXDisabled, *chainParams)) + coreContextDisabled := makeAppContext(evmChain, chainParams, flagsDisabled, verificationFlags) + + require.False(t, coreContextDisabled.IsOutboundObservationEnabled(*chainParams)) }) } @@ -374,21 +347,179 @@ func TestIsInboundObservationEnabled(t *testing.T) { } t.Run("should return true if chain is supported and inbound flag is enabled", func(t *testing.T) { - coreCTX := getTestCoreContext(evmChain, chainParams, ccFlags, verificationFlags) - require.True(t, context.IsInboundObservationEnabled(coreCTX, *chainParams)) + appContext := makeAppContext(evmChain, chainParams, ccFlags, verificationFlags) + + require.True(t, appContext.IsInboundObservationEnabled(*chainParams)) }) + t.Run("should return false if chain is not supported yet", func(t *testing.T) { - paramsUnsupported := &observertypes.ChainParams{ - ChainId: evmChain.ChainId, - IsSupported: false, - } - coreCTXUnsupported := getTestCoreContext(evmChain, paramsUnsupported, ccFlags, verificationFlags) - require.False(t, context.IsInboundObservationEnabled(coreCTXUnsupported, *paramsUnsupported)) + paramsUnsupported := &observertypes.ChainParams{ChainId: evmChain.ChainId, IsSupported: false} + appContextUnsupported := makeAppContext(evmChain, paramsUnsupported, ccFlags, verificationFlags) + + require.False(t, appContextUnsupported.IsInboundObservationEnabled(*paramsUnsupported)) }) + t.Run("should return false if inbound flag is disabled", func(t *testing.T) { flagsDisabled := ccFlags flagsDisabled.IsInboundEnabled = false - coreCTXDisabled := getTestCoreContext(evmChain, chainParams, flagsDisabled, verificationFlags) - require.False(t, context.IsInboundObservationEnabled(coreCTXDisabled, *chainParams)) + appContextDisabled := makeAppContext(evmChain, chainParams, flagsDisabled, verificationFlags) + + require.False(t, appContextDisabled.IsInboundObservationEnabled(*chainParams)) }) } + +func TestGetBTCChainAndConfig(t *testing.T) { + logger := zerolog.Nop() + + emptyConfig := config.NewConfig() + nonEmptyConfig := config.New() + + assertEmpty := func(t *testing.T, chain chains.Chain, btcConfig config.BTCConfig, enabled bool) { + assert.Empty(t, chain) + assert.Empty(t, btcConfig) + assert.False(t, enabled) + } + + for _, tt := range []struct { + name string + cfg config.Config + setup func(app *context.AppContext) + assert func(t *testing.T, chain chains.Chain, btcConfig config.BTCConfig, enabled bool) + }{ + { + name: "no btc config", + cfg: emptyConfig, + setup: nil, + assert: assertEmpty, + }, + { + name: "btc config exists, but not chain params are set", + cfg: nonEmptyConfig, + setup: nil, + assert: assertEmpty, + }, + { + name: "btc config exists but chain is invalid", + cfg: nonEmptyConfig, + setup: func(app *context.AppContext) { + app.Update( + &observertypes.Keygen{}, + []chains.Chain{}, + nil, + &observertypes.ChainParams{ChainId: 123}, + "", + observertypes.CrosschainFlags{}, + nil, + true, + ) + }, + assert: assertEmpty, + }, + { + name: "btc config exists and chain params are set", + cfg: nonEmptyConfig, + setup: func(app *context.AppContext) { + app.Update( + &observertypes.Keygen{}, + []chains.Chain{}, + nil, + &observertypes.ChainParams{ChainId: chains.BitcoinMainnet.ChainId}, + "", + observertypes.CrosschainFlags{}, + nil, + true, + ) + }, + assert: func(t *testing.T, chain chains.Chain, btcConfig config.BTCConfig, enabled bool) { + assert.Equal(t, chains.BitcoinMainnet.ChainId, chain.ChainId) + assert.Equal(t, "smoketest", btcConfig.RPCUsername) + assert.True(t, enabled) + }, + }, + } { + t.Run(tt.name, func(t *testing.T) { + // ARRANGE + // Given app context + appContext := context.New(tt.cfg, logger) + + // And optional setup + if tt.setup != nil { + tt.setup(appContext) + } + + // ACT + chain, btcConfig, enabled := appContext.GetBTCChainAndConfig() + + // ASSERT + tt.assert(t, chain, btcConfig, enabled) + }) + } +} + +func TestGetBlockHeaderEnabledChains(t *testing.T) { + // ARRANGE + // Given app config + appContext := context.New(config.New(), zerolog.Nop()) + + // That was eventually updated + appContext.Update( + &observertypes.Keygen{}, + []chains.Chain{}, + nil, + &observertypes.ChainParams{ChainId: chains.BitcoinMainnet.ChainId}, + "", + observertypes.CrosschainFlags{}, + []lightclienttypes.HeaderSupportedChain{ + {ChainId: 1, Enabled: true}, + }, + true, + ) + + // ACT #1 (found) + chain, found := appContext.GetBlockHeaderEnabledChains(1) + + // ASSERT #1 + assert.True(t, found) + assert.Equal(t, int64(1), chain.ChainId) + assert.True(t, chain.Enabled) + + // ACT #2 (not found) + chain, found = appContext.GetBlockHeaderEnabledChains(2) + + // ASSERT #2 + assert.False(t, found) + assert.Empty(t, chain) +} + +func makeAppContext( + evmChain chains.Chain, + evmChainParams *observertypes.ChainParams, + ccFlags observertypes.CrosschainFlags, + headerSupportedChains []lightclienttypes.HeaderSupportedChain, +) *context.AppContext { + // create config + cfg := config.NewConfig() + logger := zerolog.Nop() + cfg.EVMChainConfigs[evmChain.ChainId] = config.EVMConfig{ + Chain: evmChain, + } + + // create zetacore context + coreContext := context.New(cfg, logger) + evmChainParamsMap := make(map[int64]*observertypes.ChainParams) + evmChainParamsMap[evmChain.ChainId] = evmChainParams + + // feed chain params + coreContext.Update( + &observertypes.Keygen{}, + []chains.Chain{evmChain}, + evmChainParamsMap, + nil, + "", + ccFlags, + headerSupportedChains, + true, + ) + + return coreContext +} diff --git a/zetaclient/context/context.go b/zetaclient/context/context.go new file mode 100644 index 0000000000..3f8b6177fa --- /dev/null +++ b/zetaclient/context/context.go @@ -0,0 +1,26 @@ +package context + +import ( + goctx "context" + + "github.com/pkg/errors" +) + +type appContextKey struct{} + +var ErrNotSet = errors.New("AppContext is not set in the context.Context") + +// WithAppContext applied AppContext to standard Go context.Context. +func WithAppContext(ctx goctx.Context, app *AppContext) goctx.Context { + return goctx.WithValue(ctx, appContextKey{}, app) +} + +// FromContext extracts AppContext from context.Context +func FromContext(ctx goctx.Context) (*AppContext, error) { + app, ok := ctx.Value(appContextKey{}).(*AppContext) + if !ok || app == nil { + return nil, ErrNotSet + } + + return app, nil +} diff --git a/zetaclient/context/context_test.go b/zetaclient/context/context_test.go new file mode 100644 index 0000000000..5bde4596d6 --- /dev/null +++ b/zetaclient/context/context_test.go @@ -0,0 +1,40 @@ +package context_test + +import ( + goctx "context" + "testing" + + "github.com/rs/zerolog" + "github.com/stretchr/testify/assert" + "github.com/zeta-chain/zetacore/zetaclient/config" + "github.com/zeta-chain/zetacore/zetaclient/context" +) + +func TestFromContext(t *testing.T) { + // ARRANGE #1 + // Given default go ctx + ctx := goctx.Background() + + // ACT #1 + // Extract App + _, err := context.FromContext(ctx) + + // ASSERT #1 + assert.ErrorIs(t, err, context.ErrNotSet) + + // ARRANGE #2 + // Given basic app + app := context.New(config.NewConfig(), zerolog.Nop()) + + // That is included in the ctx + ctx = context.WithAppContext(ctx, app) + + // ACT #2 + app2, err := context.FromContext(ctx) + + // ASSERT #2 + assert.NoError(t, err) + assert.NotNil(t, app2) + assert.Equal(t, app, app2) + assert.NotEmpty(t, app.Config()) +} diff --git a/zetaclient/context/zetacore_context.go b/zetaclient/context/zetacore_context.go deleted file mode 100644 index 17d4cc5c3d..0000000000 --- a/zetaclient/context/zetacore_context.go +++ /dev/null @@ -1,253 +0,0 @@ -package context - -import ( - "sort" - "sync" - - "github.com/rs/zerolog" - - "github.com/zeta-chain/zetacore/pkg/chains" - lightclienttypes "github.com/zeta-chain/zetacore/x/lightclient/types" - observertypes "github.com/zeta-chain/zetacore/x/observer/types" - "github.com/zeta-chain/zetacore/zetaclient/config" -) - -// ZetacoreContext contains zetacore context params -// these are initialized and updated at runtime at every height -type ZetacoreContext struct { - coreContextLock *sync.RWMutex - keygen observertypes.Keygen - chainsEnabled []chains.Chain - evmChainParams map[int64]*observertypes.ChainParams - bitcoinChainParams *observertypes.ChainParams - currentTssPubkey string - crosschainFlags observertypes.CrosschainFlags - - // blockHeaderEnabledChains is used to store the list of chains that have block header verification enabled - // All chains in this list will have Enabled flag set to true - blockHeaderEnabledChains []lightclienttypes.HeaderSupportedChain -} - -// NewZetacoreContext creates and returns new ZetacoreContext -// it is initializing chain params from provided config -func NewZetacoreContext(cfg config.Config) *ZetacoreContext { - evmChainParams := make(map[int64]*observertypes.ChainParams) - for _, e := range cfg.EVMChainConfigs { - evmChainParams[e.Chain.ChainId] = &observertypes.ChainParams{} - } - - var bitcoinChainParams *observertypes.ChainParams - _, found := cfg.GetBTCConfig() - if found { - bitcoinChainParams = &observertypes.ChainParams{} - } - - return &ZetacoreContext{ - coreContextLock: new(sync.RWMutex), - chainsEnabled: []chains.Chain{}, - evmChainParams: evmChainParams, - bitcoinChainParams: bitcoinChainParams, - crosschainFlags: observertypes.CrosschainFlags{}, - blockHeaderEnabledChains: []lightclienttypes.HeaderSupportedChain{}, - } -} - -// GetKeygen returns the current keygen -func (c *ZetacoreContext) GetKeygen() observertypes.Keygen { - c.coreContextLock.RLock() - defer c.coreContextLock.RUnlock() - - var copiedPubkeys []string - if c.keygen.GranteePubkeys != nil { - copiedPubkeys = make([]string, len(c.keygen.GranteePubkeys)) - copy(copiedPubkeys, c.keygen.GranteePubkeys) - } - - return observertypes.Keygen{ - Status: c.keygen.Status, - GranteePubkeys: copiedPubkeys, - BlockNumber: c.keygen.BlockNumber, - } -} - -// GetCurrentTssPubkey returns the current tss pubkey -func (c *ZetacoreContext) GetCurrentTssPubkey() string { - c.coreContextLock.RLock() - defer c.coreContextLock.RUnlock() - return c.currentTssPubkey -} - -// GetEnabledChains returns all enabled chains including zetachain -func (c *ZetacoreContext) GetEnabledChains() []chains.Chain { - c.coreContextLock.RLock() - defer c.coreContextLock.RUnlock() - - copiedChains := make([]chains.Chain, len(c.chainsEnabled)) - copy(copiedChains, c.chainsEnabled) - return copiedChains -} - -// GetEnabledExternalChains returns all enabled external chains -func (c *ZetacoreContext) GetEnabledExternalChains() []chains.Chain { - c.coreContextLock.RLock() - defer c.coreContextLock.RUnlock() - - externalChains := make([]chains.Chain, 0) - for _, chain := range c.chainsEnabled { - if chain.IsExternal { - externalChains = append(externalChains, chain) - } - } - return externalChains -} - -// GetEVMChainParams returns chain params for a specific EVM chain -func (c *ZetacoreContext) GetEVMChainParams(chainID int64) (*observertypes.ChainParams, bool) { - c.coreContextLock.RLock() - defer c.coreContextLock.RUnlock() - - evmChainParams, found := c.evmChainParams[chainID] - return evmChainParams, found -} - -// GetAllEVMChainParams returns all chain params for EVM chains -func (c *ZetacoreContext) GetAllEVMChainParams() map[int64]*observertypes.ChainParams { - c.coreContextLock.RLock() - defer c.coreContextLock.RUnlock() - - // deep copy evm chain params - copied := make(map[int64]*observertypes.ChainParams, len(c.evmChainParams)) - for chainID, evmConfig := range c.evmChainParams { - copied[chainID] = &observertypes.ChainParams{} - *copied[chainID] = *evmConfig - } - return copied -} - -// GetBTCChainParams returns (chain, chain params, found) for bitcoin chain -func (c *ZetacoreContext) GetBTCChainParams() (chains.Chain, *observertypes.ChainParams, bool) { - c.coreContextLock.RLock() - defer c.coreContextLock.RUnlock() - - if c.bitcoinChainParams == nil { // bitcoin is not enabled - return chains.Chain{}, nil, false - } - - chain := chains.GetChainFromChainID(c.bitcoinChainParams.ChainId) - if chain == nil { - return chains.Chain{}, nil, false - } - - return *chain, c.bitcoinChainParams, true -} - -// GetCrossChainFlags returns crosschain flags -func (c *ZetacoreContext) GetCrossChainFlags() observertypes.CrosschainFlags { - c.coreContextLock.RLock() - defer c.coreContextLock.RUnlock() - return c.crosschainFlags -} - -// GetAllHeaderEnabledChains returns all verification flags -func (c *ZetacoreContext) GetAllHeaderEnabledChains() []lightclienttypes.HeaderSupportedChain { - c.coreContextLock.RLock() - defer c.coreContextLock.RUnlock() - return c.blockHeaderEnabledChains -} - -// GetBlockHeaderEnabledChains checks if block header verification is enabled for a specific chain -func (c *ZetacoreContext) GetBlockHeaderEnabledChains(chainID int64) (lightclienttypes.HeaderSupportedChain, bool) { - c.coreContextLock.RLock() - defer c.coreContextLock.RUnlock() - for _, flags := range c.blockHeaderEnabledChains { - if flags.ChainId == chainID { - return flags, true - } - } - return lightclienttypes.HeaderSupportedChain{}, false -} - -// Update updates zetacore context and params for all chains -// this must be the ONLY function that writes to zetacore context -func (c *ZetacoreContext) Update( - keygen *observertypes.Keygen, - newChains []chains.Chain, - evmChainParams map[int64]*observertypes.ChainParams, - btcChainParams *observertypes.ChainParams, - tssPubKey string, - crosschainFlags observertypes.CrosschainFlags, - blockHeaderEnabledChains []lightclienttypes.HeaderSupportedChain, - init bool, - logger zerolog.Logger, -) { - c.coreContextLock.Lock() - defer c.coreContextLock.Unlock() - - // Ignore whatever order zetacore organizes chain list in state - sort.SliceStable(newChains, func(i, j int) bool { - return newChains[i].ChainId < newChains[j].ChainId - }) - - if len(newChains) == 0 { - logger.Warn().Msg("UpdateChainParams: No chains enabled in ZeroCore") - } - - // Add some warnings if chain list changes at runtime - if !init { - if len(c.chainsEnabled) != len(newChains) { - logger.Warn().Msgf( - "UpdateChainParams: ChainsEnabled changed at runtime!! current: %v, new: %v", - c.chainsEnabled, - newChains, - ) - } else { - for i, chain := range newChains { - if chain != c.chainsEnabled[i] { - logger.Warn().Msgf( - "UpdateChainParams: ChainsEnabled changed at runtime!! current: %v, new: %v", - c.chainsEnabled, - newChains, - ) - } - } - } - } - - if keygen != nil { - c.keygen = *keygen - } - - c.chainsEnabled = newChains - c.crosschainFlags = crosschainFlags - c.blockHeaderEnabledChains = blockHeaderEnabledChains - - // update chain params for bitcoin if it has config in file - if c.bitcoinChainParams != nil && btcChainParams != nil { - c.bitcoinChainParams = btcChainParams - } - - // update core params for evm chains we have configs in file - for _, params := range evmChainParams { - _, found := c.evmChainParams[params.ChainId] - if !found { - continue - } - c.evmChainParams[params.ChainId] = params - } - - if tssPubKey != "" { - c.currentTssPubkey = tssPubKey - } -} - -// IsOutboundObservationEnabled returns true if the chain is supported and outbound flag is enabled -func IsOutboundObservationEnabled(c *ZetacoreContext, chainParams observertypes.ChainParams) bool { - flags := c.GetCrossChainFlags() - return chainParams.IsSupported && flags.IsOutboundEnabled -} - -// IsInboundObservationEnabled returns true if the chain is supported and inbound flag is enabled -func IsInboundObservationEnabled(c *ZetacoreContext, chainParams observertypes.ChainParams) bool { - flags := c.GetCrossChainFlags() - return chainParams.IsSupported && flags.IsInboundEnabled -} diff --git a/zetaclient/orchestrator/orchestrator.go b/zetaclient/orchestrator/orchestrator.go index 2c5ea2d2de..348baac514 100644 --- a/zetaclient/orchestrator/orchestrator.go +++ b/zetaclient/orchestrator/orchestrator.go @@ -127,7 +127,7 @@ func (oc *Orchestrator) MonitorCore(appContext *context.AppContext) error { // GetUpdatedSigner returns signer with updated chain parameters func (oc *Orchestrator) GetUpdatedSigner( - coreContext *context.ZetacoreContext, + appContext *context.AppContext, chainID int64, ) (interfaces.ChainSigner, error) { signer, found := oc.signerMap[chainID] @@ -136,7 +136,7 @@ func (oc *Orchestrator) GetUpdatedSigner( } // update EVM signer parameters only. BTC signer doesn't use chain parameters for now. if chains.IsEVMChain(chainID) { - evmParams, found := coreContext.GetEVMChainParams(chainID) + evmParams, found := appContext.GetEVMChainParams(chainID) if found { // update zeta connector and ERC20 custody addresses zetaConnectorAddress := ethcommon.HexToAddress(evmParams.GetConnectorContractAddress()) @@ -158,7 +158,7 @@ func (oc *Orchestrator) GetUpdatedSigner( // GetUpdatedChainObserver returns chain observer with updated chain parameters func (oc *Orchestrator) GetUpdatedChainObserver( - coreContext *context.ZetacoreContext, + appContext *context.AppContext, chainID int64, ) (interfaces.ChainObserver, error) { observer, found := oc.observerMap[chainID] @@ -168,14 +168,14 @@ func (oc *Orchestrator) GetUpdatedChainObserver( // update chain observer chain parameters curParams := observer.GetChainParams() if chains.IsEVMChain(chainID) { - evmParams, found := coreContext.GetEVMChainParams(chainID) + evmParams, found := appContext.GetEVMChainParams(chainID) if found && !observertypes.ChainParamsEqual(curParams, *evmParams) { observer.SetChainParams(*evmParams) oc.logger.Std.Info().Msgf( "updated chain params for chainID %d, new params: %v", chainID, *evmParams) } } else if chains.IsBitcoinChain(chainID) { - _, btcParams, found := coreContext.GetBTCChainParams() + _, btcParams, found := appContext.GetBTCChainParams() if found && !observertypes.ChainParamsEqual(curParams, *btcParams) { observer.SetChainParams(*btcParams) @@ -281,8 +281,7 @@ func (oc *Orchestrator) StartCctxScheduler(appContext *context.AppContext) { metrics.HotKeyBurnRate.Set(float64(oc.ts.HotKeyBurnRate.GetBurnRate().Int64())) // get supported external chains - coreContext := appContext.ZetacoreContext() - externalChains := coreContext.GetEnabledExternalChains() + externalChains := appContext.GetEnabledExternalChains() // query pending cctxs across all external chains within rate limit cctxMap, err := oc.GetPendingCctxsWithinRatelimit(externalChains) @@ -300,21 +299,21 @@ func (oc *Orchestrator) StartCctxScheduler(appContext *context.AppContext) { } // update chain parameters for signer and chain observer - signer, err := oc.GetUpdatedSigner(coreContext, c.ChainId) + signer, err := oc.GetUpdatedSigner(appContext, c.ChainId) if err != nil { oc.logger.Std.Error(). Err(err). Msgf("StartCctxScheduler: GetUpdatedSigner failed for chain %d", c.ChainId) continue } - ob, err := oc.GetUpdatedChainObserver(coreContext, c.ChainId) + ob, err := oc.GetUpdatedChainObserver(appContext, c.ChainId) if err != nil { oc.logger.Std.Error(). Err(err). Msgf("StartCctxScheduler: GetUpdatedChainObserver failed for chain %d", c.ChainId) continue } - if !context.IsOutboundObservationEnabled(coreContext, ob.GetChainParams()) { + if !appContext.IsOutboundObservationEnabled(ob.GetChainParams()) { continue } diff --git a/zetaclient/orchestrator/orchestrator_test.go b/zetaclient/orchestrator/orchestrator_test.go index 131dc29656..69930bdbcf 100644 --- a/zetaclient/orchestrator/orchestrator_test.go +++ b/zetaclient/orchestrator/orchestrator_test.go @@ -53,10 +53,10 @@ func MockOrchestrator( return orchestrator } -func CreateCoreContext( +func CreateAppContext( evmChain, btcChain chains.Chain, evmChainParams, btcChainParams *observertypes.ChainParams, -) *context.ZetacoreContext { +) *context.AppContext { // new config cfg := config.NewConfig() cfg.EVMChainConfigs[evmChain.ChainId] = config.EVMConfig{ @@ -66,14 +66,14 @@ func CreateCoreContext( RPCHost: "localhost", } // new zetacore context - coreContext := context.NewZetacoreContext(cfg) + appContext := context.New(cfg, zerolog.Nop()) evmChainParamsMap := make(map[int64]*observertypes.ChainParams) evmChainParamsMap[evmChain.ChainId] = evmChainParams ccFlags := sample.CrosschainFlags() verificationFlags := sample.HeaderSupportedChains() // feed chain params - coreContext.Update( + appContext.Update( &observertypes.Keygen{}, []chains.Chain{evmChain, btcChain}, evmChainParamsMap, @@ -82,9 +82,8 @@ func CreateCoreContext( *ccFlags, verificationFlags, true, - zerolog.Logger{}, ) - return coreContext + return appContext } func Test_GetUpdatedSigner(t *testing.T) { @@ -107,14 +106,14 @@ func Test_GetUpdatedSigner(t *testing.T) { t.Run("signer should not be found", func(t *testing.T) { orchestrator := MockOrchestrator(t, nil, evmChain, btcChain, evmChainParams, btcChainParams) - context := CreateCoreContext(evmChain, btcChain, evmChainParamsNew, btcChainParams) + context := CreateAppContext(evmChain, btcChain, evmChainParamsNew, btcChainParams) // BSC signer should not be found _, err := orchestrator.GetUpdatedSigner(context, chains.BscMainnet.ChainId) require.ErrorContains(t, err, "signer not found") }) t.Run("should be able to update connector and erc20 custody address", func(t *testing.T) { orchestrator := MockOrchestrator(t, nil, evmChain, btcChain, evmChainParams, btcChainParams) - context := CreateCoreContext(evmChain, btcChain, evmChainParamsNew, btcChainParams) + context := CreateAppContext(evmChain, btcChain, evmChainParamsNew, btcChainParams) // update signer with new connector and erc20 custody address signer, err := orchestrator.GetUpdatedSigner(context, evmChain.ChainId) require.NoError(t, err) @@ -172,14 +171,14 @@ func Test_GetUpdatedChainObserver(t *testing.T) { t.Run("evm chain observer should not be found", func(t *testing.T) { orchestrator := MockOrchestrator(t, nil, evmChain, btcChain, evmChainParams, btcChainParams) - coreContext := CreateCoreContext(evmChain, btcChain, evmChainParamsNew, btcChainParams) + coreContext := CreateAppContext(evmChain, btcChain, evmChainParamsNew, btcChainParams) // BSC chain observer should not be found _, err := orchestrator.GetUpdatedChainObserver(coreContext, chains.BscMainnet.ChainId) require.ErrorContains(t, err, "chain observer not found") }) t.Run("chain params in evm chain observer should be updated successfully", func(t *testing.T) { orchestrator := MockOrchestrator(t, nil, evmChain, btcChain, evmChainParams, btcChainParams) - coreContext := CreateCoreContext(evmChain, btcChain, evmChainParamsNew, btcChainParams) + coreContext := CreateAppContext(evmChain, btcChain, evmChainParamsNew, btcChainParams) // update evm chain observer with new chain params chainOb, err := orchestrator.GetUpdatedChainObserver(coreContext, evmChain.ChainId) require.NoError(t, err) @@ -188,14 +187,14 @@ func Test_GetUpdatedChainObserver(t *testing.T) { }) t.Run("btc chain observer should not be found", func(t *testing.T) { orchestrator := MockOrchestrator(t, nil, evmChain, btcChain, evmChainParams, btcChainParams) - coreContext := CreateCoreContext(btcChain, btcChain, evmChainParams, btcChainParamsNew) + coreContext := CreateAppContext(btcChain, btcChain, evmChainParams, btcChainParamsNew) // BTC testnet chain observer should not be found _, err := orchestrator.GetUpdatedChainObserver(coreContext, chains.BitcoinTestnet.ChainId) require.ErrorContains(t, err, "chain observer not found") }) t.Run("chain params in btc chain observer should be updated successfully", func(t *testing.T) { orchestrator := MockOrchestrator(t, nil, evmChain, btcChain, evmChainParams, btcChainParams) - coreContext := CreateCoreContext(btcChain, btcChain, evmChainParams, btcChainParamsNew) + coreContext := CreateAppContext(btcChain, btcChain, evmChainParams, btcChainParamsNew) // update btc chain observer with new chain params chainOb, err := orchestrator.GetUpdatedChainObserver(coreContext, btcChain.ChainId) require.NoError(t, err) diff --git a/zetaclient/supplychecker/zeta_supply_checker.go b/zetaclient/supplychecker/zeta_supply_checker.go index 10ad1d5db1..4c16ffd203 100644 --- a/zetaclient/supplychecker/zeta_supply_checker.go +++ b/zetaclient/supplychecker/zeta_supply_checker.go @@ -23,7 +23,7 @@ import ( // ZetaSupplyChecker is a utility to check the total supply of Zeta tokens type ZetaSupplyChecker struct { - coreContext *context.ZetacoreContext + appContext *context.AppContext evmClient map[int64]*ethclient.Client zetaClient *zetacore.Client ticker *clienttypes.DynamicTicker @@ -52,8 +52,8 @@ func NewZetaSupplyChecker( logger: logger.With(). Str("module", "ZetaSupplyChecker"). Logger(), - coreContext: appContext.ZetacoreContext(), - zetaClient: zetaClient, + appContext: appContext, + zetaClient: zetaClient, } for _, evmConfig := range appContext.Config().GetAllEVMConfigs() { @@ -120,7 +120,7 @@ func (zs *ZetaSupplyChecker) Stop() { func (zs *ZetaSupplyChecker) CheckZetaTokenSupply() error { externalChainTotalSupply := sdkmath.ZeroInt() for _, chain := range zs.externalEvmChain { - externalEvmChainParams, ok := zs.coreContext.GetEVMChainParams(chain.ChainId) + externalEvmChainParams, ok := zs.appContext.GetEVMChainParams(chain.ChainId) if !ok { return fmt.Errorf("externalEvmChainParams not found for chain id %d", chain.ChainId) } @@ -146,7 +146,7 @@ func (zs *ZetaSupplyChecker) CheckZetaTokenSupply() error { externalChainTotalSupply = externalChainTotalSupply.Add(totalSupplyInt) } - evmChainParams, ok := zs.coreContext.GetEVMChainParams(zs.ethereumChain.ChainId) + evmChainParams, ok := zs.appContext.GetEVMChainParams(zs.ethereumChain.ChainId) if !ok { return fmt.Errorf("eth config not found for chain id %d", zs.ethereumChain.ChainId) } diff --git a/zetaclient/tss/tss_signer.go b/zetaclient/tss/tss_signer.go index 08d48833db..e00252db55 100644 --- a/zetaclient/tss/tss_signer.go +++ b/zetaclient/tss/tss_signer.go @@ -109,7 +109,7 @@ func NewTSS( newTss := TSS{ Server: server, Keys: make(map[string]*Key), - CurrentPubkey: appContext.ZetacoreContext().GetCurrentTssPubkey(), + CurrentPubkey: appContext.GetCurrentTssPubKey(), logger: logger, ZetacoreClient: client, KeysignsTracker: NewKeysignsTracker(logger), diff --git a/zetaclient/zetacore/client.go b/zetaclient/zetacore/client.go index 4443316a4a..140520fe11 100644 --- a/zetaclient/zetacore/client.go +++ b/zetaclient/zetacore/client.go @@ -193,11 +193,7 @@ func (c *Client) WaitForZetacoreToCreateBlocks() error { // UpdateZetacoreContext updates zetacore context // zetacore stores zetacore context for all clients -func (c *Client) UpdateZetacoreContext( - coreContext *context.ZetacoreContext, - init bool, - sampledLogger zerolog.Logger, -) error { +func (c *Client) UpdateZetacoreContext(coreContext *context.AppContext, init bool, sampledLogger zerolog.Logger) error { bn, err := c.GetBlockHeight() if err != nil { return fmt.Errorf("failed to get zetablock height: %w", err) @@ -278,7 +274,6 @@ func (c *Client) UpdateZetacoreContext( crosschainFlags, blockHeaderEnabledChains, init, - c.logger, ) return nil diff --git a/zetaclient/zetacore/tx.go b/zetaclient/zetacore/tx.go index 0a28336b04..1cf1c5c40e 100644 --- a/zetaclient/zetacore/tx.go +++ b/zetaclient/zetacore/tx.go @@ -185,7 +185,7 @@ func (c *Client) ZetacoreContextUpdater(appContext *appcontext.AppContext) { select { case <-ticker.C: c.logger.Debug().Msg("Running Updater") - err := c.UpdateZetacoreContext(appContext.ZetacoreContext(), false, sampledLogger) + err := c.UpdateZetacoreContext(appContext, false, sampledLogger) if err != nil { c.logger.Err(err).Msg("ZetacoreContextUpdater failed to update config") } diff --git a/zetaclient/zetacore/tx_test.go b/zetaclient/zetacore/tx_test.go index 1d00f33d1a..fbf9a10e7d 100644 --- a/zetaclient/zetacore/tx_test.go +++ b/zetaclient/zetacore/tx_test.go @@ -333,9 +333,9 @@ func TestZetacore_UpdateZetacoreContext(t *testing.T) { t.Run("zetacore update success", func(t *testing.T) { cfg := config.NewConfig() - coreCtx := context.NewZetacoreContext(cfg) + appContext := context.New(cfg, zerolog.Nop()) zetacoreBroadcast = MockBroadcast - err := client.UpdateZetacoreContext(coreCtx, false, zerolog.Logger{}) + err := client.UpdateZetacoreContext(appContext, false, zerolog.Logger{}) require.NoError(t, err) }) } From ba6bc6fe7bc610e078b7c8b8cc51dc7578867105 Mon Sep 17 00:00:00 2001 From: Grant Zukel <80433392+gzukel@users.noreply.github.com> Date: Mon, 1 Jul 2024 16:43:07 -0600 Subject: [PATCH 7/7] ci: expand performance testing to catch errors, fixed connection refused errors, added performance testing with state. (#2400) * fixed bugs in the performance testing. * added command to start a network from the latest state-export from mainnet. * added additional test validation to display correctly in cloud reports. * added failure alerting and conditional outcome checking for the test reports to fail when there are issues and notify the team. --- .github/actions/performance-tests/art.yaml | 233 +++++++++++++++++- .../ci-nightly-performance-testing.yaml | 56 ++++- changelog.md | 1 + 3 files changed, 276 insertions(+), 14 deletions(-) diff --git a/.github/actions/performance-tests/art.yaml b/.github/actions/performance-tests/art.yaml index 71c1b3a15e..70d2ba1f85 100644 --- a/.github/actions/performance-tests/art.yaml +++ b/.github/actions/performance-tests/art.yaml @@ -1,7 +1,5 @@ -# artillery run art.yaml --output results.json -# artillery report results.json --output artillery_report.html config: - target: "http://127.0.0.1:8545" + target: "http://localhost:9545" phases: - duration: 60 arrivalRate: 10 @@ -13,10 +11,14 @@ config: plugins: metrics-by-endpoint: useOnlyRequestNames: true + ensure: + - type: "failure" + threshold: 1 summary: true reports: - type: "html" filename: "artillery_report.html" + logLevel: debug scenarios: - name: web3_clientVersion @@ -28,6 +30,15 @@ scenarios: jsonrpc: "2.0" method: "web3_clientVersion" params: [] + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: web3_sha3 flow: @@ -39,6 +50,15 @@ scenarios: method: "web3_sha3" params: - "0x68656c6c6f20776f726c64" + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: net_version flow: @@ -49,6 +69,15 @@ scenarios: jsonrpc: "2.0" method: "net_version" params: [] + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: net_listening flow: @@ -59,6 +88,15 @@ scenarios: jsonrpc: "2.0" method: "net_listening" params: [] + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: net_peerCount flow: @@ -69,6 +107,15 @@ scenarios: jsonrpc: "2.0" method: "net_peerCount" params: [] + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_chainId flow: @@ -79,6 +126,15 @@ scenarios: jsonrpc: "2.0" method: "eth_chainId" params: [] + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_getStorageAt flow: @@ -90,6 +146,15 @@ scenarios: method: "eth_getStorageAt" params: - "latest" + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_getTransactionByBlockHashAndIndex flow: @@ -101,6 +166,15 @@ scenarios: method: "eth_getTransactionByBlockHashAndIndex" params: - "0x0" + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_getTransactionByBlockNumberAndIndex flow: @@ -113,6 +187,15 @@ scenarios: params: - "latest" - "0x0" + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_getUncleByBlockHashAndIndex flow: @@ -124,6 +207,15 @@ scenarios: method: "eth_getUncleByBlockHashAndIndex" params: - "0x0" + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_getUncleByBlockNumberAndIndex flow: @@ -136,6 +228,15 @@ scenarios: params: - "latest" - "0x0" + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_newFilter flow: @@ -152,6 +253,15 @@ scenarios: address: "0x0", topics: [] } + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_getFilterChanges flow: @@ -163,6 +273,15 @@ scenarios: method: "eth_getFilterChanges" params: - "0x0" + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_getFilterLogs flow: @@ -174,6 +293,15 @@ scenarios: method: "eth_getFilterLogs" params: - "0x0" + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_blockNumber flow: @@ -184,6 +312,15 @@ scenarios: jsonrpc: "2.0" method: "eth_blockNumber" params: [] + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_getBlockByHash flow: @@ -196,6 +333,15 @@ scenarios: params: - "0x0" - true + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_getBlockByNumber flow: @@ -208,6 +354,15 @@ scenarios: params: - "latest" - true + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_getBlockTransactionCountByHash flow: @@ -219,6 +374,15 @@ scenarios: method: "eth_getBlockTransactionCountByHash" params: - "0x0" + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_getBlockTransactionCountByNumber flow: @@ -230,6 +394,15 @@ scenarios: method: "eth_getBlockTransactionCountByNumber" params: - "latest" + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_getCode flow: @@ -242,6 +415,15 @@ scenarios: params: - "0x0" - "latest" + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_getTransactionByHash flow: @@ -253,6 +435,15 @@ scenarios: method: "eth_getTransactionByHash" params: - "0x0" + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_getTransactionReceipt flow: @@ -264,6 +455,15 @@ scenarios: method: "eth_getTransactionReceipt" params: - "0x0" + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_getLogs flow: @@ -278,6 +478,15 @@ scenarios: toBlock: "latest" address: "0x0" topics: ["0x0"] + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_getBalance flow: @@ -290,6 +499,15 @@ scenarios: params: - "0x0" - "latest" + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null - name: eth_estimateGas flow: @@ -301,3 +519,12 @@ scenarios: method: "eth_estimateGas" params: - from: "0x0" + capture: + - json: "$" + as: "response" + ensure: + - statusCode: 200 + - statusCode: 201 + assert: + - subject: response.error + equals: null diff --git a/.github/workflows/ci-nightly-performance-testing.yaml b/.github/workflows/ci-nightly-performance-testing.yaml index 30116f743f..a6a566f4aa 100644 --- a/.github/workflows/ci-nightly-performance-testing.yaml +++ b/.github/workflows/ci-nightly-performance-testing.yaml @@ -12,23 +12,57 @@ jobs: steps: - uses: actions/checkout@v4 - - name: "START:LOCAL:NET" + - name: "INSTALL:NODEJS" + uses: actions/setup-node@v4 + with: + node-version: 16 + + - name: "START:LOCAL:NET:WITH:STATE" run: | - make start-e2e-test + make start-e2e-import-mainnet-test - - name: "EXECUTE:LOADTESTS" - uses: artilleryio/action-cli@v1 - with: - command: run .github/actions/performance-tests/art.yaml --record --key ${{ secrets.ARTILLERY_KEY }} --output ./report.json + - name: "INSTALL:ARTILLERY" + run: | + npm install -g artillery@latest + + - name: "EXECUTE:PERFORMANCE:TESTS" + run: | + artillery run .github/actions/performance-tests/art.yaml --record --key ${{ secrets.ARTILLERY_KEY }} --output ./report.json + # Check Artillery exit status + if [ $? -ne 0 ]; then + echo "Artillery command failed to execute." + exit 1 + fi + + # Parse the results.json file to check for failed vusers and http response codes + failed_vusers=$(jq '.aggregate.counters["vusers.failed"] // 0' ./report.json) + http_codes_200=$(jq '.aggregate.counters["http.codes.200"] // 0' ./report.json) + http_responses=$(jq '.aggregate.counters["http.responses"] // 0' ./report.json) + + if [ "$failed_vusers" -gt 1 ] || [ "$http_codes_200" -ne "$http_responses" ]; then + echo "Performance Testing had Failed Tests." + exit 1 + else + echo "EVM Performance Testing Successful" + fi - name: "GENERATE:REPORT" - uses: artilleryio/action-cli@v1 - with: - command: report report.json --output artillery_report.html + if: always() + run: | + artillery report report.json --output artillery_report.html - name: "UPLOAD:REPORT" uses: actions/upload-artifact@v3 - if: success() + if: always() with: name: artillery-report - path: ./artillery_report.html \ No newline at end of file + path: ./artillery_report.html + + - name: "NOTIFY:SLACK:FAILURE" + if: failure() && github.event_name == 'schedule' + uses: 8398a7/action-slack@v3 + with: + status: ${{ job.status }} + fields: repo,message,commit,author,action,eventName,ref,workflow,job,took + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_CI_ALERTS }} \ No newline at end of file diff --git a/changelog.md b/changelog.md index 4e7cd838a0..1506dee6ee 100644 --- a/changelog.md +++ b/changelog.md @@ -99,6 +99,7 @@ * [2192](https://github.com/zeta-chain/node/pull/2192) - Added release status checker and updater pipeline that will update release statuses when they go live on network * [2335](https://github.com/zeta-chain/node/pull/2335) - ci: updated the artillery report to publish to artillery cloud * [2377](https://github.com/zeta-chain/node/pull/2377) - ci: adjusted sast-linters.yml to not scan itself, nor alert on removal of nosec. +* [2400](https://github.com/zeta-chain/node/pull/2400) - ci: adjusted the performance test to pass or fail pipeline based on test results, alert slack, and launch network with state. Fixed connection issues as well. ### Documentation