Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

test: backport solana performance tests and performance improvements #3298

Open
wants to merge 6 commits into
base: release/v23
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ start-e2e-admin-test: e2e-images
export E2E_ARGS="--skip-regular --test-admin" && \
cd contrib/localnet/ && $(DOCKER_COMPOSE) --profile eth2 up -d

start-e2e-performance-test: e2e-images
start-e2e-performance-test: e2e-images solana
@echo "--> Starting e2e performance test"
export E2E_ARGS="--test-performance" && \
cd contrib/localnet/ && $(DOCKER_COMPOSE) --profile stress up -d
Expand Down
5 changes: 5 additions & 0 deletions cmd/zetae2e/config/local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ additional_accounts:
evm_address: "0x103FD9224F00ce3013e95629e52DFc31D805D68d"
private_key: "dd53f191113d18e57bd4a5494a64a020ba7919c815d0a6d34a42ebb2839e9d95"
solana_private_key: "4yqSQxDeTBvn86BuxcN5jmZb2gaobFXrBqu8kiE9rZxNkVMe3LfXmFigRsU4sRp7vk4vVP1ZCFiejDKiXBNWvs2C"
user_spl:
bech32_address: "zeta17e77anpmzhuuam67hg6x3mtqrulqh80z9chv70"
evm_address: "0xf67deecc3B15F9CEeF5eba3468ed601f3e0B9de2"
private_key: "2b3306a8ac43dbf0e350b87876c131e7e12bd49563a16de9ce8aeb664b94d559"
solana_private_key: "4yqSQxDeTBvn86BuxcN5jmZb2gaobFXrBqu8kiE9rZxNkVMe3LfXmFigRsU4sRp7vk4vVP1ZCFiejDKiXBNWvs2C"
user_ether:
bech32_address: "zeta134rakuus43xn63yucgxhn88ywj8ewcv6ezn2ga"
evm_address: "0x8D47Db7390AC4D3D449Cc20D799ce4748F97619A"
Expand Down
5 changes: 5 additions & 0 deletions cmd/zetae2e/config/localnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ additional_accounts:
evm_address: "0x103FD9224F00ce3013e95629e52DFc31D805D68d"
private_key: "dd53f191113d18e57bd4a5494a64a020ba7919c815d0a6d34a42ebb2839e9d95"
solana_private_key: "4yqSQxDeTBvn86BuxcN5jmZb2gaobFXrBqu8kiE9rZxNkVMe3LfXmFigRsU4sRp7vk4vVP1ZCFiejDKiXBNWvs2C"
user_spl:
bech32_address: "zeta17e77anpmzhuuam67hg6x3mtqrulqh80z9chv70"
evm_address: "0xf67deecc3B15F9CEeF5eba3468ed601f3e0B9de2"
private_key: "2b3306a8ac43dbf0e350b87876c131e7e12bd49563a16de9ce8aeb664b94d559"
solana_private_key: "4yqSQxDeTBvn86BuxcN5jmZb2gaobFXrBqu8kiE9rZxNkVMe3LfXmFigRsU4sRp7vk4vVP1ZCFiejDKiXBNWvs2C"
user_ether:
bech32_address: "zeta134rakuus43xn63yucgxhn88ywj8ewcv6ezn2ga"
evm_address: "0x8D47Db7390AC4D3D449Cc20D799ce4748F97619A"
Expand Down
118 changes: 118 additions & 0 deletions cmd/zetae2e/local/get_zetaclient_bootstrap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package local

import (
"fmt"
"net"
"strings"

sdk "github.com/cosmos/cosmos-sdk/types"
legacybech32 "github.com/cosmos/cosmos-sdk/types/bech32/legacybech32"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
crypto2 "github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/spf13/cobra"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

"github.com/zeta-chain/node/pkg/rpc"
"github.com/zeta-chain/node/pkg/sdkconfig"
observertypes "github.com/zeta-chain/node/x/observer/types"
)

const grpcURLFlag = "grpc-url"

func NewGetZetaclientBootstrap() *cobra.Command {
var cmd = &cobra.Command{
Use: "get-zetaclient-bootstrap",
Short: "get bootstrap address book entries for zetaclient",
RunE: getZetaclientBootstrap,
}

cmd.Flags().
String(grpcURLFlag, "zetacore0:9090", "--grpc-url zetacore0:9090")

return cmd
}

func bech32PubkeyToPeerID(pubKey string) (peer.ID, error) {
bech32PubKey, err := legacybech32.UnmarshalPubKey(legacybech32.AccPK, pubKey)
if err != nil {
return "", err
}
secp256k1PubKey, err := crypto2.UnmarshalSecp256k1PublicKey(bech32PubKey.Bytes())
if err != nil {
return "", err
}
return peer.IDFromPublicKey(secp256k1PubKey)
}

func getZetaclientBootstrap(cmd *cobra.Command, _ []string) error {
sdkconfig.SetDefault(true)
grpcURL, _ := cmd.Flags().GetString(grpcURLFlag)
rpcClient, err := rpc.NewGRPCClients(
grpcURL,
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithBlock(),
)
if err != nil {
return fmt.Errorf("get zetacore rpc client: %w", err)
}
var res *observertypes.QueryAllNodeAccountResponse
for {
res, err = rpcClient.Observer.NodeAccountAll(cmd.Context(), &observertypes.QueryAllNodeAccountRequest{})
if err != nil {
return fmt.Errorf("get all node accounts: %w", err)
}
if len(res.NodeAccount) > 1 {
break
}
fmt.Fprintln(cmd.OutOrStderr(), "waiting for node accounts")
}

// note that we deliberately do not filter ourselfs/localhost
// to mirror the production configuration
for _, account := range res.NodeAccount {
accAddr, err := sdk.AccAddressFromBech32(account.Operator)
if err != nil {
return err
}
valAddr := sdk.ValAddress(accAddr).String()
validatorRes, err := rpcClient.Staking.Validator(cmd.Context(), &stakingtypes.QueryValidatorRequest{
ValidatorAddr: valAddr,
})
if err != nil {
return fmt.Errorf("getting validator info for %s: %w", account.Operator, err)
}
// in localnet, moniker is also the hostname
moniker := validatorRes.Validator.Description.Moniker

peerID, err := bech32PubkeyToPeerID(account.GranteePubkey.Secp256k1.String())
if err != nil {
return fmt.Errorf("converting pubkey to peerID: %w", err)
}
zetaclientHostname := strings.ReplaceAll(moniker, "zetacore", "zetaclient")

// resolve the hostname
// something in libp2p/go-tss requires /ip4/<ip> and doesn't tolerate /dns4/<hostname>
ipAddresses, err := net.LookupIP(zetaclientHostname)
if err != nil {
return fmt.Errorf("failed to resolve hostname %s: %w", zetaclientHostname, err)
}
if len(ipAddresses) == 0 {
return fmt.Errorf("no IP addresses found for hostname %s", zetaclientHostname)
}
ipv4Address := ""
for _, ip := range ipAddresses {
if ip.To4() != nil {
ipv4Address = ip.String()
break
}
}
if ipv4Address == "" {
return fmt.Errorf("no IPv4 address found for hostname %s", zetaclientHostname)
}
fmt.Printf("/ip4/%s/tcp/6668/p2p/%s\n", ipv4Address, peerID.String())
}

return nil
}
47 changes: 45 additions & 2 deletions cmd/zetae2e/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ func NewLocalCmd() *cobra.Command {
cmd.Flags().
Bool(flagUpgradeContracts, false, "set to true to upgrade Gateways and ERC20Custody contracts during setup for ZEVM and EVM")

cmd.AddCommand(NewGetZetaclientBootstrap())

return cmd
}

Expand Down Expand Up @@ -116,6 +118,7 @@ func localE2ETest(cmd *cobra.Command, _ []string) {
testV2Migration = must(cmd.Flags().GetBool(flagTestV2Migration))
skipPrecompiles = must(cmd.Flags().GetBool(flagSkipPrecompiles))
upgradeContracts = must(cmd.Flags().GetBool(flagUpgradeContracts))
setupSolana = testSolana || testPerformance
)

logger := runner.NewLogger(verbose, color.FgWhite, "setup")
Expand Down Expand Up @@ -230,7 +233,7 @@ func localE2ETest(cmd *cobra.Command, _ []string) {

deployerRunner.SetupEVMV2()

if testSolana {
if setupSolana {
deployerRunner.SetupSolana(
conf.Contracts.Solana.GatewayProgramID.String(),
conf.AdditionalAccounts.UserSolana.SolanaPrivateKey.String(),
Expand All @@ -246,7 +249,7 @@ func localE2ETest(cmd *cobra.Command, _ []string) {
ERC20Addr: deployerRunner.ERC20Addr,
SPLAddr: nil,
}
if testSolana {
if setupSolana {
zrc20Deployment.SPLAddr = deployerRunner.SPLAddr.ToPointer()
}

Expand Down Expand Up @@ -433,6 +436,46 @@ func localE2ETest(cmd *cobra.Command, _ []string) {
if testPerformance {
eg.Go(ethereumDepositPerformanceRoutine(conf, deployerRunner, verbose, e2etests.TestStressEtherDepositName))
eg.Go(ethereumWithdrawPerformanceRoutine(conf, deployerRunner, verbose, e2etests.TestStressEtherWithdrawName))
eg.Go(
solanaDepositPerformanceRoutine(
conf,
"perf_sol_deposit",
deployerRunner,
verbose,
conf.AdditionalAccounts.UserSolana,
e2etests.TestStressSolanaDepositName,
),
)
eg.Go(
solanaDepositPerformanceRoutine(
conf,
"perf_spl_deposit",
deployerRunner,
verbose,
conf.AdditionalAccounts.UserSPL,
e2etests.TestStressSPLDepositName,
),
)
eg.Go(
solanaWithdrawPerformanceRoutine(
conf,
"perf_sol_withdraw",
deployerRunner,
verbose,
conf.AdditionalAccounts.UserSolana,
e2etests.TestStressSolanaWithdrawName,
),
)
eg.Go(
solanaWithdrawPerformanceRoutine(
conf,
"perf_spl_withdraw",
deployerRunner,
verbose,
conf.AdditionalAccounts.UserSPL,
e2etests.TestStressSPLWithdrawName,
),
)
}
if testCustom {
eg.Go(miscTestRoutine(conf, deployerRunner, verbose, e2etests.TestMyTestName))
Expand Down
2 changes: 1 addition & 1 deletion cmd/zetae2e/local/monitor_block_production.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func monitorBlockProduction(ctx context.Context, conf config.Config) error {
return fmt.Errorf("expecting new block event, got %T", event.Data)
}
latestNewBlockEvent = newBlockEvent
case <-time.After(4 * time.Second):
case <-time.After(5 * time.Second):
return fmt.Errorf("timed out waiting for new block (last block %d)", latestNewBlockEvent.Block.Height)
case <-ctx.Done():
return nil
Expand Down
125 changes: 125 additions & 0 deletions cmd/zetae2e/local/performance.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ package local

import (
"fmt"
"math/big"
"time"

"github.com/fatih/color"

"github.com/zeta-chain/node/e2e/config"
"github.com/zeta-chain/node/e2e/e2etests"
"github.com/zeta-chain/node/e2e/runner"
"github.com/zeta-chain/node/e2e/utils"
"github.com/zeta-chain/node/x/crosschain/types"
)

// ethereumDepositPerformanceRoutine runs performance tests for Ether deposit
Expand Down Expand Up @@ -106,3 +109,125 @@ func ethereumWithdrawPerformanceRoutine(
return err
}
}

// solanaDepositPerformanceRoutine runs performance tests for solana deposits
func solanaDepositPerformanceRoutine(
conf config.Config,
name string,
deployerRunner *runner.E2ERunner,
verbose bool,
account config.Account,
testNames ...string,
) func() error {
return func() (err error) {
// initialize runner for solana test
r, err := initTestRunner(
"solana",
conf,
deployerRunner,
account,
runner.NewLogger(verbose, color.FgHiMagenta, name),
runner.WithZetaTxServer(deployerRunner.ZetaTxServer),
)
if err != nil {
return err
}

if r.ReceiptTimeout == 0 {
r.ReceiptTimeout = 15 * time.Minute
}
if r.CctxTimeout == 0 {
r.CctxTimeout = 15 * time.Minute
}

r.Logger.Print("🏃 starting solana deposit performance tests")
startTime := time.Now()

tests, err := r.GetE2ETestsToRunByName(
e2etests.AllE2ETests,
testNames...,
)
if err != nil {
return fmt.Errorf("solana deposit performance test failed: %v", err)
}

if err := r.RunE2ETests(tests); err != nil {
return fmt.Errorf("solana deposit performance test failed: %v", err)
}

r.Logger.Print("🍾 solana deposit performance test completed in %s", time.Since(startTime).String())

return err
}
}

// solanaWithdrawPerformanceRoutine runs performance tests for solana withdrawals
func solanaWithdrawPerformanceRoutine(
conf config.Config,
name string,
deployerRunner *runner.E2ERunner,
verbose bool,
account config.Account,
testNames ...string,
) func() error {
return func() (err error) {
// initialize runner for solana test
r, err := initTestRunner(
"solana",
conf,
deployerRunner,
account,
runner.NewLogger(verbose, color.FgHiGreen, name),
runner.WithZetaTxServer(deployerRunner.ZetaTxServer),
)
if err != nil {
return err
}

if r.ReceiptTimeout == 0 {
r.ReceiptTimeout = 15 * time.Minute
}
if r.CctxTimeout == 0 {
r.CctxTimeout = 15 * time.Minute
}

r.Logger.Print("🏃 starting solana withdraw performance tests")
startTime := time.Now()

// load deployer private key
privKey := r.GetSolanaPrivKey()

// execute the deposit sol transaction
amount := big.NewInt(0).Mul(big.NewInt(1e9), big.NewInt(100)) // 100 sol in lamports
sig := r.SOLDepositAndCall(nil, r.EVMAddress(), amount, nil)

// wait for the cctx to be mined
cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, sig.String(), r.CctxClient, r.Logger, r.CctxTimeout)
r.Logger.CCTX(*cctx, "solana_deposit")
utils.RequireCCTXStatus(r, cctx, types.CctxStatus_OutboundMined)

// same amount for spl
sig = r.SPLDepositAndCall(&privKey, amount.Uint64(), r.SPLAddr, r.EVMAddress(), nil)

// wait for the cctx to be mined
cctx = utils.WaitCctxMinedByInboundHash(r.Ctx, sig.String(), r.CctxClient, r.Logger, r.CctxTimeout)
r.Logger.CCTX(*cctx, "solana_deposit_spl")
utils.RequireCCTXStatus(r, cctx, types.CctxStatus_OutboundMined)

tests, err := r.GetE2ETestsToRunByName(
e2etests.AllE2ETests,
testNames...,
)
if err != nil {
return fmt.Errorf("solana withdraw performance test failed: %v", err)
}

if err := r.RunE2ETests(tests); err != nil {
return fmt.Errorf("solana withdraw performance test failed: %v", err)
}

r.Logger.Print("🍾 solana withdraw performance test completed in %s", time.Since(startTime).String())

return err
}
}
2 changes: 2 additions & 0 deletions contrib/localnet/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ services:
profiles:
- solana
- all
- stress
restart: always
ports:
- "8899:8899"
networks:
Expand Down
Loading
Loading