From ace34cbcd09a9eebdfbe70b4931426f328839312 Mon Sep 17 00:00:00 2001 From: Alex Gartner Date: Wed, 28 Aug 2024 13:16:11 -0700 Subject: [PATCH 1/8] feat: add common rpc package --- pkg/rpc/rpc.go | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 pkg/rpc/rpc.go diff --git a/pkg/rpc/rpc.go b/pkg/rpc/rpc.go new file mode 100644 index 0000000000..c090e33f0b --- /dev/null +++ b/pkg/rpc/rpc.go @@ -0,0 +1,61 @@ +package rpc + +import ( + "fmt" + + rpcclient "github.com/cometbft/cometbft/rpc/client/http" + "github.com/cosmos/cosmos-sdk/client" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "google.golang.org/grpc" + + authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" + crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" + fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" + lightclienttypes "github.com/zeta-chain/zetacore/x/lightclient/types" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" +) + +// Clients contains RPC client interfaces to interact with zetacored +type Clients struct { + AuthorityClient authoritytypes.QueryClient + CctxClient crosschaintypes.QueryClient + FungibleClient fungibletypes.QueryClient + AuthClient authtypes.QueryClient + BankClient banktypes.QueryClient + ObserverClient observertypes.QueryClient + LightClient lightclienttypes.QueryClient +} + +func newClients(ctx client.Context) (Clients, error) { + return Clients{ + AuthorityClient: authoritytypes.NewQueryClient(ctx), + CctxClient: crosschaintypes.NewQueryClient(ctx), + FungibleClient: fungibletypes.NewQueryClient(ctx), + AuthClient: authtypes.NewQueryClient(ctx), + BankClient: banktypes.NewQueryClient(ctx), + ObserverClient: observertypes.NewQueryClient(ctx), + LightClient: lightclienttypes.NewQueryClient(ctx), + }, nil +} + +// NewCometBFTClients creates a Clients which uses cometbft abci_query as the transport +func NewCometBFTClients(url string) (Clients, error) { + cometRPCClient, err := rpcclient.New(url, "/websocket") + if err != nil { + return Clients{}, fmt.Errorf("create cometbft rpc client: %w", err) + } + clientCtx := client.Context{}.WithClient(cometRPCClient) + + return newClients(clientCtx) +} + +// NewGRPCClient creates a Clients which uses gRPC as the transport +func NewGRPCClients(url string, opts ...grpc.DialOption) (Clients, error) { + grpcConn, err := grpc.Dial(url, opts...) + if err != nil { + return Clients{}, err + } + clientCtx := client.Context{}.WithGRPCClient(grpcConn) + return newClients(clientCtx) +} From 83ee6d71bab082167b4131325b90e5cc7e4063d6 Mon Sep 17 00:00:00 2001 From: Alex Gartner Date: Thu, 29 Aug 2024 10:15:25 -0700 Subject: [PATCH 2/8] review feedback --- pkg/rpc/rpc.go | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/pkg/rpc/rpc.go b/pkg/rpc/rpc.go index c090e33f0b..6ba1ec2ca2 100644 --- a/pkg/rpc/rpc.go +++ b/pkg/rpc/rpc.go @@ -9,6 +9,7 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "google.golang.org/grpc" + etherminttypes "github.com/zeta-chain/zetacore/rpc/types" authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" @@ -18,24 +19,42 @@ import ( // Clients contains RPC client interfaces to interact with zetacored type Clients struct { - AuthorityClient authoritytypes.QueryClient - CctxClient crosschaintypes.QueryClient - FungibleClient fungibletypes.QueryClient - AuthClient authtypes.QueryClient - BankClient banktypes.QueryClient - ObserverClient observertypes.QueryClient - LightClient lightclienttypes.QueryClient + // Cosmos SDK clients + + // Auth is a github.com/cosmos/cosmos-sdk/x/auth/types QueryClient + Auth authtypes.QueryClient + // Bank is a github.com/cosmos/cosmos-sdk/x/bank/types QueryClient + Bank banktypes.QueryClient + + // ZetaCore specific clients + + // Authority is a github.com/zeta-chain/zetacore/x/authority/types QueryClient + Authority authoritytypes.QueryClient + // Crosschain is a github.com/zeta-chain/zetacore/x/crosschain/types QueryClient + Crosschain crosschaintypes.QueryClient + // Fungible is a github.com/zeta-chain/zetacore/x/fungible/types QueryClient + Fungible fungibletypes.QueryClient + // Observer is a github.com/zeta-chain/zetacore/x/observer/types QueryClient + Observer observertypes.QueryClient + // Light is a github.com/zeta-chain/zetacore/x/lightclient/types QueryClient + Light lightclienttypes.QueryClient + + // Ethermint specific clients + + // Ethermint is a github.com/zeta-chain/zetacore/rpc/types QueryClient + Ethermint *etherminttypes.QueryClient } func newClients(ctx client.Context) (Clients, error) { return Clients{ - AuthorityClient: authoritytypes.NewQueryClient(ctx), - CctxClient: crosschaintypes.NewQueryClient(ctx), - FungibleClient: fungibletypes.NewQueryClient(ctx), - AuthClient: authtypes.NewQueryClient(ctx), - BankClient: banktypes.NewQueryClient(ctx), - ObserverClient: observertypes.NewQueryClient(ctx), - LightClient: lightclienttypes.NewQueryClient(ctx), + Authority: authoritytypes.NewQueryClient(ctx), + Crosschain: crosschaintypes.NewQueryClient(ctx), + Fungible: fungibletypes.NewQueryClient(ctx), + Auth: authtypes.NewQueryClient(ctx), + Bank: banktypes.NewQueryClient(ctx), + Observer: observertypes.NewQueryClient(ctx), + Light: lightclienttypes.NewQueryClient(ctx), + Ethermint: etherminttypes.NewQueryClient(ctx), }, nil } From 8ec1a6a87059fe8910839775cf71ddec0866cd69 Mon Sep 17 00:00:00 2001 From: Alex Gartner Date: Thu, 29 Aug 2024 11:25:53 -0700 Subject: [PATCH 3/8] update e2e --- cmd/zetae2e/config/clients.go | 113 +++++---------------- cmd/zetae2e/config/config.go | 14 +-- cmd/zetae2e/local/local.go | 2 +- cmd/zetae2e/run.go | 10 +- e2e/e2etests/test_migrate_chain_support.go | 14 +-- e2e/runner/clients.go | 24 +++++ e2e/runner/runner.go | 52 +++++----- pkg/rpc/rpc.go | 27 +++-- 8 files changed, 96 insertions(+), 160 deletions(-) create mode 100644 e2e/runner/clients.go diff --git a/cmd/zetae2e/config/clients.go b/cmd/zetae2e/config/clients.go index 4bdf8a6d3d..dc4751e6b1 100644 --- a/cmd/zetae2e/config/clients.go +++ b/cmd/zetae2e/config/clients.go @@ -5,99 +5,53 @@ import ( "fmt" "github.com/btcsuite/btcd/rpcclient" - 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/ethclient" "github.com/gagliardetto/solana-go/rpc" + zetacore_rpc "github.com/zeta-chain/zetacore/pkg/rpc" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "github.com/zeta-chain/zetacore/e2e/config" - authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" - crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" - fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" - lightclienttypes "github.com/zeta-chain/zetacore/x/lightclient/types" - observertypes "github.com/zeta-chain/zetacore/x/observer/types" + "github.com/zeta-chain/zetacore/e2e/runner" ) -// E2EClients contains all the RPC clients and gRPC clients for E2E tests -type E2EClients struct { - // the RPC clients for external chains in the localnet - BtcRPCClient *rpcclient.Client - SolanaClient *rpc.Client - EvmClient *ethclient.Client - EvmAuth *bind.TransactOpts - - // the gRPC clients for ZetaChain - AuthorityClient authoritytypes.QueryClient - CctxClient crosschaintypes.QueryClient - FungibleClient fungibletypes.QueryClient - AuthClient authtypes.QueryClient - BankClient banktypes.QueryClient - ObserverClient observertypes.QueryClient - LightClient lightclienttypes.QueryClient - - // the RPC clients for ZetaChain - ZevmClient *ethclient.Client - ZevmAuth *bind.TransactOpts -} - -// ZetaChainClients contains all the RPC clients and gRPC clients for ZetaChain -type ZetaChainClients struct { - AuthorityClient authoritytypes.QueryClient - CctxClient crosschaintypes.QueryClient - FungibleClient fungibletypes.QueryClient - AuthClient authtypes.QueryClient - BankClient banktypes.QueryClient - ObserverClient observertypes.QueryClient - LightClient lightclienttypes.QueryClient -} - // getClientsFromConfig get clients from config func getClientsFromConfig(ctx context.Context, conf config.Config, account config.Account) ( - E2EClients, + runner.Clients, error, ) { var solanaClient *rpc.Client if conf.RPCs.Solana != "" { if solanaClient = rpc.New(conf.RPCs.Solana); solanaClient == nil { - return E2EClients{}, fmt.Errorf("failed to get solana client") + return runner.Clients{}, fmt.Errorf("failed to get solana client") } } btcRPCClient, err := getBtcClient(conf.RPCs.Bitcoin) if err != nil { - return E2EClients{}, fmt.Errorf("failed to get btc client: %w", err) + return runner.Clients{}, fmt.Errorf("failed to get btc client: %w", err) } evmClient, evmAuth, err := getEVMClient(ctx, conf.RPCs.EVM, account) if err != nil { - return E2EClients{}, fmt.Errorf("failed to get evm client: %w", err) + return runner.Clients{}, fmt.Errorf("failed to get evm client: %w", err) } - zetaChainClients, err := GetZetaClients( - conf.RPCs.ZetaCoreGRPC, - ) + zetaCoreClients, err := GetZetacoreClient(ctx, conf) if err != nil { - return E2EClients{}, fmt.Errorf("failed to get zeta clients: %w", err) + return runner.Clients{}, fmt.Errorf("failed to get zetacore client: %w", err) } zevmClient, zevmAuth, err := getEVMClient(ctx, conf.RPCs.Zevm, account) if err != nil { - return E2EClients{}, fmt.Errorf("failed to get zevm client: %w", err) + return runner.Clients{}, fmt.Errorf("failed to get zevm client: %w", err) } - return E2EClients{ - BtcRPCClient: btcRPCClient, - SolanaClient: solanaClient, - EvmClient: evmClient, - EvmAuth: evmAuth, - AuthorityClient: zetaChainClients.AuthorityClient, - CctxClient: zetaChainClients.CctxClient, - FungibleClient: zetaChainClients.FungibleClient, - AuthClient: zetaChainClients.AuthClient, - BankClient: zetaChainClients.BankClient, - ObserverClient: zetaChainClients.ObserverClient, - LightClient: zetaChainClients.LightClient, - ZevmClient: zevmClient, - ZevmAuth: zevmAuth, + return runner.Clients{ + Zetacore: zetaCoreClients, + BtcRPC: btcRPCClient, + Solana: solanaClient, + Evm: evmClient, + EvmAuth: evmAuth, + Zevm: zevmClient, + ZevmAuth: zevmAuth, }, nil } @@ -152,31 +106,12 @@ func getEVMClient( return evmClient, evmAuth, nil } -// GetZetaClients get zeta clients -func GetZetaClients(rpc string) ( - ZetaChainClients, - error, -) { - grpcConn, err := grpc.Dial(rpc, grpc.WithTransportCredentials(insecure.NewCredentials())) - if err != nil { - return ZetaChainClients{}, err +func GetZetacoreClient(ctx context.Context, conf config.Config) (zetacore_rpc.Clients, error) { + if conf.RPCs.ZetaCoreGRPC != "" { + return zetacore_rpc.NewGRPCClients(conf.RPCs.ZetaCoreGRPC, grpc.WithTransportCredentials(insecure.NewCredentials())) } - - authorityClient := authoritytypes.NewQueryClient(grpcConn) - cctxClient := crosschaintypes.NewQueryClient(grpcConn) - fungibleClient := fungibletypes.NewQueryClient(grpcConn) - authClient := authtypes.NewQueryClient(grpcConn) - bankClient := banktypes.NewQueryClient(grpcConn) - observerClient := observertypes.NewQueryClient(grpcConn) - lightclientClient := lightclienttypes.NewQueryClient(grpcConn) - - return ZetaChainClients{ - AuthorityClient: authorityClient, - CctxClient: cctxClient, - FungibleClient: fungibleClient, - AuthClient: authClient, - BankClient: bankClient, - ObserverClient: observerClient, - LightClient: lightclientClient, - }, nil + if conf.RPCs.ZetaCoreRPC != "" { + return zetacore_rpc.NewCometBFTClients(conf.RPCs.ZetaCoreRPC) + } + return zetacore_rpc.Clients{}, fmt.Errorf("no ZetaCore gRPC or RPC specified") } diff --git a/cmd/zetae2e/config/config.go b/cmd/zetae2e/config/config.go index ce1b03717b..7cf2afb461 100644 --- a/cmd/zetae2e/config/config.go +++ b/cmd/zetae2e/config/config.go @@ -30,19 +30,7 @@ func RunnerFromConfig( name, ctxCancel, account, - e2eClients.EvmClient, - e2eClients.ZevmClient, - e2eClients.AuthorityClient, - e2eClients.CctxClient, - e2eClients.FungibleClient, - e2eClients.AuthClient, - e2eClients.BankClient, - e2eClients.ObserverClient, - e2eClients.LightClient, - e2eClients.EvmAuth, - e2eClients.ZevmAuth, - e2eClients.BtcRPCClient, - e2eClients.SolanaClient, + e2eClients, logger, opts..., diff --git a/cmd/zetae2e/local/local.go b/cmd/zetae2e/local/local.go index dd00666e25..c8d92fce28 100644 --- a/cmd/zetae2e/local/local.go +++ b/cmd/zetae2e/local/local.go @@ -166,7 +166,7 @@ func localE2ETest(cmd *cobra.Command, _ []string) { noError(err) // set the authority client to the zeta tx server to be able to query message permissions - deployerRunner.ZetaTxServer.SetAuthorityClient(deployerRunner.AutorithyClient) + deployerRunner.ZetaTxServer.SetAuthorityClient(deployerRunner.AuthorityClient) // wait for keygen to be completed // if setup is skipped, we assume that the keygen is already completed diff --git a/cmd/zetae2e/run.go b/cmd/zetae2e/run.go index fe0ef1b4ff..a710e98504 100644 --- a/cmd/zetae2e/run.go +++ b/cmd/zetae2e/run.go @@ -86,7 +86,7 @@ func runE2ETest(cmd *cobra.Command, args []string) error { if erc20ChainName != "" && erc20Symbol != "" { erc20Asset, zrc20ContractAddress, err := findERC20( cmd.Context(), - conf.RPCs.ZetaCoreGRPC, + conf, erc20ChainName, erc20Symbol, ) @@ -178,13 +178,13 @@ func parseCmdArgsToE2ETestRunConfig(args []string) ([]runner.E2ETestRunConfig, e } // findERC20 loads ERC20 addresses via gRPC given CLI flags -func findERC20(ctx context.Context, zetaCoreGRPCURL, erc20ChainName, erc20Symbol string) (string, string, error) { - clients, err := zetae2econfig.GetZetaClients(zetaCoreGRPCURL) +func findERC20(ctx context.Context, conf config.Config, erc20ChainName, erc20Symbol string) (string, string, error) { + clients, err := zetae2econfig.GetZetacoreClient(ctx, conf) if err != nil { return "", "", fmt.Errorf("get zeta clients: %w", err) } - supportedChainsRes, err := clients.ObserverClient.SupportedChains(ctx, &observertypes.QuerySupportedChains{}) + supportedChainsRes, err := clients.Observer.SupportedChains(ctx, &observertypes.QuerySupportedChains{}) if err != nil { return "", "", fmt.Errorf("get chain params: %w", err) } @@ -200,7 +200,7 @@ func findERC20(ctx context.Context, zetaCoreGRPCURL, erc20ChainName, erc20Symbol return "", "", fmt.Errorf("chain %s not found", erc20ChainName) } - foreignCoinsRes, err := clients.FungibleClient.ForeignCoinsAll(ctx, &fungibletypes.QueryAllForeignCoinsRequest{}) + foreignCoinsRes, err := clients.Fungible.ForeignCoinsAll(ctx, &fungibletypes.QueryAllForeignCoinsRequest{}) if err != nil { return "", "", fmt.Errorf("get foreign coins: %w", err) } diff --git a/e2e/e2etests/test_migrate_chain_support.go b/e2e/e2etests/test_migrate_chain_support.go index 62c9bac84f..b5222a81d7 100644 --- a/e2e/e2etests/test_migrate_chain_support.go +++ b/e2e/e2etests/test_migrate_chain_support.go @@ -201,19 +201,7 @@ func configureEVM2(r *runner.E2ERunner) (*runner.E2ERunner, error) { "admin-evm2", r.CtxCancel, r.Account, - r.EVMClient, - r.ZEVMClient, - r.AutorithyClient, - r.CctxClient, - r.FungibleClient, - r.AuthClient, - r.BankClient, - r.ObserverClient, - r.LightclientClient, - r.EVMAuth, - r.ZEVMAuth, - r.BtcRPCClient, - r.SolanaClient, + r.Clients, runner.NewLogger(true, color.FgHiYellow, "admin-evm2"), runner.WithZetaTxServer(r.ZetaTxServer), ) diff --git a/e2e/runner/clients.go b/e2e/runner/clients.go new file mode 100644 index 0000000000..6e08a8aae2 --- /dev/null +++ b/e2e/runner/clients.go @@ -0,0 +1,24 @@ +package runner + +import ( + "github.com/btcsuite/btcd/rpcclient" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/gagliardetto/solana-go/rpc" + zetacore_rpc "github.com/zeta-chain/zetacore/pkg/rpc" +) + +// Clients contains all the RPC clients and gRPC clients for E2E tests +type Clients struct { + Zetacore zetacore_rpc.Clients + + // the RPC clients for external chains in the localnet + BtcRPC *rpcclient.Client + Solana *rpc.Client + Evm *ethclient.Client + EvmAuth *bind.TransactOpts + + // the RPC clients for ZetaChain + Zevm *ethclient.Client + ZevmAuth *bind.TransactOpts +} diff --git a/e2e/runner/runner.go b/e2e/runner/runner.go index 77d068c398..90bffd1ed1 100644 --- a/e2e/runner/runner.go +++ b/e2e/runner/runner.go @@ -70,14 +70,18 @@ type E2ERunner struct { BTCDeployerAddress *btcutil.AddressWitnessPubKeyHash SolanaDeployerAddress solana.PublicKey + // all clients. + // a reference to this type is required to enable creating a new E2ERunner. + Clients Clients + // rpc clients ZEVMClient *ethclient.Client EVMClient *ethclient.Client BtcRPCClient *rpcclient.Client SolanaClient *rpc.Client - // grpc clients - AutorithyClient authoritytypes.QueryClient + // zetacored grpc clients + AuthorityClient authoritytypes.QueryClient CctxClient crosschaintypes.QueryClient FungibleClient fungibletypes.QueryClient AuthClient authtypes.QueryClient @@ -165,19 +169,7 @@ func NewE2ERunner( name string, ctxCancel context.CancelFunc, account config.Account, - evmClient *ethclient.Client, - zevmClient *ethclient.Client, - authorityClient authoritytypes.QueryClient, - cctxClient crosschaintypes.QueryClient, - fungibleClient fungibletypes.QueryClient, - authClient authtypes.QueryClient, - bankClient banktypes.QueryClient, - observerClient observertypes.QueryClient, - lightclientClient lightclienttypes.QueryClient, - evmAuth *bind.TransactOpts, - zevmAuth *bind.TransactOpts, - btcRPCClient *rpcclient.Client, - solanaClient *rpc.Client, + clients Clients, logger *Logger, opts ...E2ERunnerOption, ) *E2ERunner { @@ -187,20 +179,22 @@ func NewE2ERunner( Account: account, - ZEVMClient: zevmClient, - EVMClient: evmClient, - AutorithyClient: authorityClient, - CctxClient: cctxClient, - FungibleClient: fungibleClient, - AuthClient: authClient, - BankClient: bankClient, - ObserverClient: observerClient, - LightclientClient: lightclientClient, - - EVMAuth: evmAuth, - ZEVMAuth: zevmAuth, - BtcRPCClient: btcRPCClient, - SolanaClient: solanaClient, + Clients: clients, + + ZEVMClient: clients.Zevm, + EVMClient: clients.Evm, + AuthorityClient: clients.Zetacore.Authority, + CctxClient: clients.Zetacore.Crosschain, + FungibleClient: clients.Zetacore.Fungible, + AuthClient: clients.Zetacore.Auth, + BankClient: clients.Zetacore.Bank, + ObserverClient: clients.Zetacore.Observer, + LightclientClient: clients.Zetacore.Lightclient, + + EVMAuth: clients.EvmAuth, + ZEVMAuth: clients.ZevmAuth, + BtcRPCClient: clients.BtcRPC, + SolanaClient: clients.Solana, Logger: logger, } diff --git a/pkg/rpc/rpc.go b/pkg/rpc/rpc.go index 6ba1ec2ca2..401062611c 100644 --- a/pkg/rpc/rpc.go +++ b/pkg/rpc/rpc.go @@ -5,6 +5,7 @@ import ( rpcclient "github.com/cometbft/cometbft/rpc/client/http" "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "google.golang.org/grpc" @@ -36,25 +37,31 @@ type Clients struct { Fungible fungibletypes.QueryClient // Observer is a github.com/zeta-chain/zetacore/x/observer/types QueryClient Observer observertypes.QueryClient - // Light is a github.com/zeta-chain/zetacore/x/lightclient/types QueryClient - Light lightclienttypes.QueryClient + // Lightclient is a github.com/zeta-chain/zetacore/x/lightclient/types QueryClient + Lightclient lightclienttypes.QueryClient // Ethermint specific clients // Ethermint is a github.com/zeta-chain/zetacore/rpc/types QueryClient Ethermint *etherminttypes.QueryClient + + // Tendermint specific clients + + // Tendermint is a github.com/cosmos/cosmos-sdk/client/grpc/tmservice QueryClient + Tendermint tmservice.ServiceClient } func newClients(ctx client.Context) (Clients, error) { return Clients{ - Authority: authoritytypes.NewQueryClient(ctx), - Crosschain: crosschaintypes.NewQueryClient(ctx), - Fungible: fungibletypes.NewQueryClient(ctx), - Auth: authtypes.NewQueryClient(ctx), - Bank: banktypes.NewQueryClient(ctx), - Observer: observertypes.NewQueryClient(ctx), - Light: lightclienttypes.NewQueryClient(ctx), - Ethermint: etherminttypes.NewQueryClient(ctx), + Authority: authoritytypes.NewQueryClient(ctx), + Crosschain: crosschaintypes.NewQueryClient(ctx), + Fungible: fungibletypes.NewQueryClient(ctx), + Auth: authtypes.NewQueryClient(ctx), + Bank: banktypes.NewQueryClient(ctx), + Observer: observertypes.NewQueryClient(ctx), + Lightclient: lightclienttypes.NewQueryClient(ctx), + Ethermint: etherminttypes.NewQueryClient(ctx), + Tendermint: tmservice.NewServiceClient(ctx), }, nil } From c93c75d97a9464bc844cee6e4ded12c7587c7e60 Mon Sep 17 00:00:00 2001 From: Alex Gartner Date: Thu, 29 Aug 2024 12:11:48 -0700 Subject: [PATCH 4/8] port zetacore high level helpers and tests --- pkg/rpc/{rpc.go => clients.go} | 22 +- pkg/rpc/clients_authority.go | 18 + pkg/rpc/clients_cosmos.go | 37 ++ pkg/rpc/clients_crosschain.go | 194 +++++++ pkg/rpc/clients_ethermint.go | 23 + pkg/rpc/clients_lightclient.go | 57 ++ pkg/rpc/clients_observer.go | 216 ++++++++ pkg/rpc/clients_tendermint.go | 35 ++ pkg/rpc/clients_test.go | 923 +++++++++++++++++++++++++++++++++ 9 files changed, 1520 insertions(+), 5 deletions(-) rename pkg/rpc/{rpc.go => clients.go} (77%) create mode 100644 pkg/rpc/clients_authority.go create mode 100644 pkg/rpc/clients_cosmos.go create mode 100644 pkg/rpc/clients_crosschain.go create mode 100644 pkg/rpc/clients_ethermint.go create mode 100644 pkg/rpc/clients_lightclient.go create mode 100644 pkg/rpc/clients_observer.go create mode 100644 pkg/rpc/clients_tendermint.go create mode 100644 pkg/rpc/clients_test.go diff --git a/pkg/rpc/rpc.go b/pkg/rpc/clients.go similarity index 77% rename from pkg/rpc/rpc.go rename to pkg/rpc/clients.go index 401062611c..59fa329f81 100644 --- a/pkg/rpc/rpc.go +++ b/pkg/rpc/clients.go @@ -8,8 +8,10 @@ import ( "github.com/cosmos/cosmos-sdk/client/grpc/tmservice" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" "google.golang.org/grpc" + feemarkettypes "github.com/zeta-chain/ethermint/x/feemarket/types" etherminttypes "github.com/zeta-chain/zetacore/rpc/types" authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" @@ -26,6 +28,8 @@ type Clients struct { Auth authtypes.QueryClient // Bank is a github.com/cosmos/cosmos-sdk/x/bank/types QueryClient Bank banktypes.QueryClient + // Upgrade is a github.com/cosmos/cosmos-sdk/x/upgrade/types QueryClient + Upgrade upgradetypes.QueryClient // ZetaCore specific clients @@ -44,6 +48,8 @@ type Clients struct { // Ethermint is a github.com/zeta-chain/zetacore/rpc/types QueryClient Ethermint *etherminttypes.QueryClient + // EthermintFeeMarket is a github.com/zeta-chain/ethermint/x/feemarket/types QueryClient + EthermintFeeMarket feemarkettypes.QueryClient // Tendermint specific clients @@ -53,15 +59,21 @@ type Clients struct { func newClients(ctx client.Context) (Clients, error) { return Clients{ - Authority: authoritytypes.NewQueryClient(ctx), + // Cosmos SDK clients + Auth: authtypes.NewQueryClient(ctx), + Bank: banktypes.NewQueryClient(ctx), + Upgrade: upgradetypes.NewQueryClient(ctx), + Authority: authoritytypes.NewQueryClient(ctx), + // ZetaCore specific clients Crosschain: crosschaintypes.NewQueryClient(ctx), Fungible: fungibletypes.NewQueryClient(ctx), - Auth: authtypes.NewQueryClient(ctx), - Bank: banktypes.NewQueryClient(ctx), Observer: observertypes.NewQueryClient(ctx), Lightclient: lightclienttypes.NewQueryClient(ctx), - Ethermint: etherminttypes.NewQueryClient(ctx), - Tendermint: tmservice.NewServiceClient(ctx), + // Ethermint specific clients + Ethermint: etherminttypes.NewQueryClient(ctx), + EthermintFeeMarket: feemarkettypes.NewQueryClient(ctx), + // Tendermint specific clients + Tendermint: tmservice.NewServiceClient(ctx), }, nil } diff --git a/pkg/rpc/clients_authority.go b/pkg/rpc/clients_authority.go new file mode 100644 index 0000000000..68baa01271 --- /dev/null +++ b/pkg/rpc/clients_authority.go @@ -0,0 +1,18 @@ +package rpc + +import ( + "context" + + "github.com/zeta-chain/zetacore/pkg/chains" + authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" +) + +// GetAdditionalChains returns the additional chains +func (c *Clients) GetAdditionalChains(ctx context.Context) ([]chains.Chain, error) { + resp, err := c.Authority.ChainInfo(ctx, &authoritytypes.QueryGetChainInfoRequest{}) + if err != nil { + return nil, err + } + + return resp.GetChainInfo().Chains, nil +} diff --git a/pkg/rpc/clients_cosmos.go b/pkg/rpc/clients_cosmos.go new file mode 100644 index 0000000000..36d41acea2 --- /dev/null +++ b/pkg/rpc/clients_cosmos.go @@ -0,0 +1,37 @@ +package rpc + +import ( + "context" + + sdkmath "cosmossdk.io/math" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + "github.com/pkg/errors" + + "github.com/zeta-chain/zetacore/cmd/zetacored/config" +) + +// GetUpgradePlan returns the current upgrade plan. +// if there is no active upgrade plan, plan will be nil, err will be nil as well. +func (c *Clients) GetUpgradePlan(ctx context.Context) (*upgradetypes.Plan, error) { + in := &upgradetypes.QueryCurrentPlanRequest{} + + resp, err := c.Upgrade.CurrentPlan(ctx, in) + if err != nil { + return nil, errors.Wrap(err, "failed to get current upgrade plan") + } + + return resp.Plan, nil +} + +// GetZetaTokenSupplyOnNode returns the zeta token supply on the node +func (c *Clients) GetZetaTokenSupplyOnNode(ctx context.Context) (sdkmath.Int, error) { + in := &banktypes.QuerySupplyOfRequest{Denom: config.BaseDenom} + + resp, err := c.Bank.SupplyOf(ctx, in) + if err != nil { + return sdkmath.ZeroInt(), errors.Wrap(err, "failed to get zeta token supply") + } + + return resp.GetAmount().Amount, nil +} diff --git a/pkg/rpc/clients_crosschain.go b/pkg/rpc/clients_crosschain.go new file mode 100644 index 0000000000..3fa5b06675 --- /dev/null +++ b/pkg/rpc/clients_crosschain.go @@ -0,0 +1,194 @@ +package rpc + +import ( + "context" + "sort" + + "cosmossdk.io/errors" + "github.com/cosmos/cosmos-sdk/types/query" + "google.golang.org/grpc" + + "github.com/zeta-chain/zetacore/pkg/chains" + "github.com/zeta-chain/zetacore/x/crosschain/types" + "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" +) + +// 32MB +var maxSizeOption = grpc.MaxCallRecvMsgSize(32 * 1024 * 1024) + +// GetLastBlockHeight returns the zetachain block height +func (c *Clients) GetLastBlockHeight(ctx context.Context) (uint64, error) { + resp, err := c.Crosschain.LastBlockHeight(ctx, &types.QueryGetLastBlockHeightRequest{}) + if err != nil { + return 0, errors.Wrap(err, "failed to get block height") + } + + return resp.GetLastBlockHeight().LastInboundHeight, nil +} + +// GetBlockHeight returns the zetachain block height +func (c *Clients) GetBlockHeight(ctx context.Context) (int64, error) { + resp, err := c.Crosschain.LastZetaHeight(ctx, &types.QueryLastZetaHeightRequest{}) + if err != nil { + return 0, err + } + + return resp.Height, nil +} + +// GetAbortedZetaAmount returns the amount of zeta that has been aborted +func (c *Clients) GetAbortedZetaAmount(ctx context.Context) (string, error) { + resp, err := c.Crosschain.ZetaAccounting(ctx, &types.QueryZetaAccountingRequest{}) + if err != nil { + return "", errors.Wrap(err, "failed to get aborted zeta amount") + } + + return resp.AbortedZetaAmount, nil +} + +// GetRateLimiterFlags returns the rate limiter flags +func (c *Clients) GetRateLimiterFlags(ctx context.Context) (types.RateLimiterFlags, error) { + resp, err := c.Crosschain.RateLimiterFlags(ctx, &types.QueryRateLimiterFlagsRequest{}) + if err != nil { + return types.RateLimiterFlags{}, errors.Wrap(err, "failed to get rate limiter flags") + } + + return resp.RateLimiterFlags, nil +} + +// GetRateLimiterInput returns input data for the rate limit checker +func (c *Clients) GetRateLimiterInput(ctx context.Context, window int64) (*types.QueryRateLimiterInputResponse, error) { + in := &types.QueryRateLimiterInputRequest{Window: window} + + resp, err := c.Crosschain.RateLimiterInput(ctx, in, maxSizeOption) + if err != nil { + return nil, errors.Wrap(err, "failed to get rate limiter input") + } + + return resp, nil +} + +// GetAllCctx returns all cross chain transactions +func (c *Clients) GetAllCctx(ctx context.Context) ([]*types.CrossChainTx, error) { + resp, err := c.Crosschain.CctxAll(ctx, &types.QueryAllCctxRequest{}) + if err != nil { + return nil, errors.Wrap(err, "failed to get all cross chain transactions") + } + + return resp.CrossChainTx, nil +} + +func (c *Clients) GetCctxByHash(ctx context.Context, sendHash string) (*types.CrossChainTx, error) { + in := &types.QueryGetCctxRequest{Index: sendHash} + resp, err := c.Crosschain.Cctx(ctx, in) + if err != nil { + return nil, errors.Wrap(err, "failed to get cctx by hash") + } + + return resp.CrossChainTx, nil +} + +// GetCctxByNonce returns a cross chain transaction by nonce +func (c *Clients) GetCctxByNonce(ctx context.Context, chainID int64, nonce uint64) (*types.CrossChainTx, error) { + resp, err := c.Crosschain.CctxByNonce(ctx, &types.QueryGetCctxByNonceRequest{ + ChainID: chainID, + Nonce: nonce, + }) + if err != nil { + return nil, errors.Wrap(err, "failed to get cctx by nonce") + } + + return resp.CrossChainTx, nil +} + +// ListPendingCCTXWithinRateLimit returns a list of pending cctxs that do not exceed the outbound rate limit +// - The max size of the list is crosschainkeeper.MaxPendingCctxs +// - The returned `rateLimitExceeded` flag indicates if the rate limit is exceeded or not +func (c *Clients) ListPendingCCTXWithinRateLimit( + ctx context.Context, +) (*types.QueryListPendingCctxWithinRateLimitResponse, error) { + in := &types.QueryListPendingCctxWithinRateLimitRequest{} + + resp, err := c.Crosschain.ListPendingCctxWithinRateLimit(ctx, in, maxSizeOption) + if err != nil { + return nil, errors.Wrap(err, "failed to get pending cctxs within rate limit") + } + + return resp, nil +} + +// ListPendingCCTX returns a list of pending cctxs for a given chainID +// - The max size of the list is crosschainkeeper.MaxPendingCctxs +func (c *Clients) ListPendingCCTX(ctx context.Context, chainID int64) ([]*types.CrossChainTx, uint64, error) { + in := &types.QueryListPendingCctxRequest{ChainId: chainID} + + resp, err := c.Crosschain.ListPendingCctx(ctx, in, maxSizeOption) + if err != nil { + return nil, 0, errors.Wrap(err, "failed to get pending cctxs") + } + + return resp.CrossChainTx, resp.TotalPending, nil +} + +// GetOutboundTracker returns the outbound tracker for a chain and nonce +func (c *Clients) GetOutboundTracker( + ctx context.Context, + chain chains.Chain, + nonce uint64, +) (*types.OutboundTracker, error) { + in := &types.QueryGetOutboundTrackerRequest{ChainID: chain.ChainId, Nonce: nonce} + + resp, err := c.Crosschain.OutboundTracker(ctx, in) + if err != nil { + return nil, err + } + + return &resp.OutboundTracker, nil +} + +// GetInboundTrackersForChain returns the inbound trackers for a chain +func (c *Clients) GetInboundTrackersForChain(ctx context.Context, chainID int64) ([]types.InboundTracker, error) { + in := &types.QueryAllInboundTrackerByChainRequest{ChainId: chainID} + + resp, err := c.Crosschain.InboundTrackerAllByChain(ctx, in) + if err != nil { + return nil, err + } + + return resp.InboundTracker, nil +} + +// GetAllOutboundTrackerByChain returns all outbound trackers for a chain +func (c *Clients) GetAllOutboundTrackerByChain( + ctx context.Context, + chainID int64, + order interfaces.Order, +) ([]types.OutboundTracker, error) { + in := &types.QueryAllOutboundTrackerByChainRequest{ + Chain: chainID, + Pagination: &query.PageRequest{ + Key: nil, + Offset: 0, + Limit: 2000, + CountTotal: false, + Reverse: false, + }, + } + + resp, err := c.Crosschain.OutboundTrackerAllByChain(ctx, in) + if err != nil { + return nil, errors.Wrap(err, "failed to get all outbound trackers") + } + + if order == interfaces.Ascending { + sort.SliceStable(resp.OutboundTracker, func(i, j int) bool { + return resp.OutboundTracker[i].Nonce < resp.OutboundTracker[j].Nonce + }) + } else if order == interfaces.Descending { + sort.SliceStable(resp.OutboundTracker, func(i, j int) bool { + return resp.OutboundTracker[i].Nonce > resp.OutboundTracker[j].Nonce + }) + } + + return resp.OutboundTracker, nil +} diff --git a/pkg/rpc/clients_ethermint.go b/pkg/rpc/clients_ethermint.go new file mode 100644 index 0000000000..0a559fbf7f --- /dev/null +++ b/pkg/rpc/clients_ethermint.go @@ -0,0 +1,23 @@ +package rpc + +import ( + "context" + "fmt" + + "cosmossdk.io/errors" + feemarkettypes "github.com/zeta-chain/ethermint/x/feemarket/types" +) + +// GetBaseGasPrice returns the base gas price +func (c *Clients) GetBaseGasPrice(ctx context.Context) (int64, error) { + resp, err := c.EthermintFeeMarket.Params(ctx, &feemarkettypes.QueryParamsRequest{}) + if err != nil { + return 0, errors.Wrap(err, "failed to get base gas price") + } + + if resp.Params.BaseFee.IsNil() { + return 0, fmt.Errorf("base fee is nil") + } + + return resp.Params.BaseFee.Int64(), nil +} diff --git a/pkg/rpc/clients_lightclient.go b/pkg/rpc/clients_lightclient.go new file mode 100644 index 0000000000..cb3e0e0c3c --- /dev/null +++ b/pkg/rpc/clients_lightclient.go @@ -0,0 +1,57 @@ +package rpc + +import ( + "context" + + "cosmossdk.io/errors" + + "github.com/zeta-chain/zetacore/pkg/proofs" + "github.com/zeta-chain/zetacore/x/lightclient/types" +) + +// GetBlockHeaderEnabledChains returns the enabled chains for block headers +func (c *Clients) GetBlockHeaderEnabledChains(ctx context.Context) ([]types.HeaderSupportedChain, error) { + resp, err := c.Lightclient.HeaderEnabledChains(ctx, &types.QueryHeaderEnabledChainsRequest{}) + if err != nil { + return []types.HeaderSupportedChain{}, err + } + + return resp.HeaderEnabledChains, nil +} + +// GetBlockHeaderChainState returns the block header chain state +func (c *Clients) GetBlockHeaderChainState(ctx context.Context, chainID int64) (*types.ChainState, error) { + in := &types.QueryGetChainStateRequest{ChainId: chainID} + + resp, err := c.Lightclient.ChainState(ctx, in) + if err != nil { + return nil, errors.Wrap(err, "failed to get chain state") + } + + return resp.ChainState, nil +} + +// Prove returns whether a proof is valid +func (c *Clients) Prove( + ctx context.Context, + blockHash string, + txHash string, + txIndex int64, + proof *proofs.Proof, + chainID int64, +) (bool, error) { + in := &types.QueryProveRequest{ + BlockHash: blockHash, + TxIndex: txIndex, + Proof: proof, + ChainId: chainID, + TxHash: txHash, + } + + resp, err := c.Lightclient.Prove(ctx, in) + if err != nil { + return false, errors.Wrap(err, "failed to prove") + } + + return resp.Valid, nil +} diff --git a/pkg/rpc/clients_observer.go b/pkg/rpc/clients_observer.go new file mode 100644 index 0000000000..a5c7455e91 --- /dev/null +++ b/pkg/rpc/clients_observer.go @@ -0,0 +1,216 @@ +package rpc + +import ( + "context" + "fmt" + + "cosmossdk.io/errors" + + "github.com/zeta-chain/zetacore/pkg/chains" + "github.com/zeta-chain/zetacore/pkg/retry" + "github.com/zeta-chain/zetacore/x/observer/types" +) + +// GetCrosschainFlags returns the crosschain flags +func (c *Clients) GetCrosschainFlags(ctx context.Context) (types.CrosschainFlags, error) { + resp, err := c.Observer.CrosschainFlags(ctx, &types.QueryGetCrosschainFlagsRequest{}) + if err != nil { + return types.CrosschainFlags{}, err + } + + return resp.CrosschainFlags, nil +} + +// GetSupportedChains returns the supported chains +func (c *Clients) GetSupportedChains(ctx context.Context) ([]chains.Chain, error) { + resp, err := c.Observer.SupportedChains(ctx, &types.QuerySupportedChains{}) + if err != nil { + return nil, errors.Wrap(err, "failed to get supported chains") + } + + return resp.GetChains(), nil +} + +// GetChainParams returns all the chain params +func (c *Clients) GetChainParams(ctx context.Context) ([]*types.ChainParams, error) { + in := &types.QueryGetChainParamsRequest{} + + resp, err := retry.DoTypedWithRetry(func() (*types.QueryGetChainParamsResponse, error) { + return c.Observer.GetChainParams(ctx, in) + }) + + if err != nil { + return nil, errors.Wrap(err, "failed to get chain params") + } + + return resp.ChainParams.ChainParams, nil +} + +// GetChainParamsForChainID returns the chain params for a given chain ID +func (c *Clients) GetChainParamsForChainID( + ctx context.Context, + externalChainID int64, +) (*types.ChainParams, error) { + in := &types.QueryGetChainParamsForChainRequest{ChainId: externalChainID} + + resp, err := c.Observer.GetChainParamsForChain(ctx, in) + if err != nil { + return &types.ChainParams{}, err + } + + return resp.ChainParams, nil +} + +// GetObserverList returns the list of observers +func (c *Clients) GetObserverList(ctx context.Context) ([]string, error) { + in := &types.QueryObserverSet{} + + resp, err := retry.DoTypedWithRetry(func() (*types.QueryObserverSetResponse, error) { + return c.Observer.ObserverSet(ctx, in) + }) + + if err != nil { + return nil, errors.Wrap(err, "failed to get observer list") + } + + return resp.Observers, nil +} + +// GetBallotByID returns a ballot by ID +func (c *Clients) GetBallotByID(ctx context.Context, id string) (*types.QueryBallotByIdentifierResponse, error) { + in := &types.QueryBallotByIdentifierRequest{BallotIdentifier: id} + + return c.Observer.BallotByIdentifier(ctx, in) +} + +// GetNonceByChain returns the nonce by chain +func (c *Clients) GetNonceByChain(ctx context.Context, chain chains.Chain) (types.ChainNonces, error) { + in := &types.QueryGetChainNoncesRequest{ChainId: chain.ChainId} + + resp, err := c.Observer.ChainNonces(ctx, in) + if err != nil { + return types.ChainNonces{}, errors.Wrap(err, "failed to get nonce by chain") + } + + return resp.ChainNonces, nil +} + +// GetKeyGen returns the keygen +func (c *Clients) GetKeyGen(ctx context.Context) (types.Keygen, error) { + in := &types.QueryGetKeygenRequest{} + + resp, err := retry.DoTypedWithRetry(func() (*types.QueryGetKeygenResponse, error) { + return c.Observer.Keygen(ctx, in) + }) + + switch { + case err != nil: + return types.Keygen{}, errors.Wrap(err, "failed to get keygen") + case resp.Keygen == nil: + return types.Keygen{}, fmt.Errorf("keygen is nil") + } + + return *resp.Keygen, nil +} + +// GetAllNodeAccounts returns all node accounts +func (c *Clients) GetAllNodeAccounts(ctx context.Context) ([]*types.NodeAccount, error) { + resp, err := c.Observer.NodeAccountAll(ctx, &types.QueryAllNodeAccountRequest{}) + if err != nil { + return nil, errors.Wrap(err, "failed to get all node accounts") + } + + return resp.NodeAccount, nil +} + +// GetBallot returns a ballot by ID +func (c *Clients) GetBallot( + ctx context.Context, + ballotIdentifier string, +) (*types.QueryBallotByIdentifierResponse, error) { + in := &types.QueryBallotByIdentifierRequest{BallotIdentifier: ballotIdentifier} + + resp, err := c.Observer.BallotByIdentifier(ctx, in) + if err != nil { + return nil, errors.Wrap(err, "failed to get ballot") + } + + return resp, nil +} + +// GetEVMTSSAddress returns the current EVM TSS address. +func (c *Clients) GetEVMTSSAddress(ctx context.Context) (string, error) { + resp, err := c.Observer.GetTssAddress(ctx, &types.QueryGetTssAddressRequest{}) + if err != nil { + return "", errors.Wrap(err, "failed to get eth tss address") + } + + return resp.Eth, nil +} + +// GetBTCTSSAddress returns the current BTC TSS address +func (c *Clients) GetBTCTSSAddress(ctx context.Context, chainID int64) (string, error) { + in := &types.QueryGetTssAddressRequest{BitcoinChainId: chainID} + + resp, err := c.Observer.GetTssAddress(ctx, in) + if err != nil { + return "", errors.Wrap(err, "failed to get btc tss address") + } + return resp.Btc, nil +} + +// GetTSS returns the current TSS +func (c *Clients) GetTSS(ctx context.Context) (types.TSS, error) { + resp, err := c.Observer.TSS(ctx, &types.QueryGetTSSRequest{}) + if err != nil { + return types.TSS{}, errors.Wrap(err, "failed to get tss") + } + return resp.TSS, nil +} + +// GetTSSHistory returns the historical list of TSS +func (c *Clients) GetTSSHistory(ctx context.Context) ([]types.TSS, error) { + resp, err := c.Observer.TssHistory(ctx, &types.QueryTssHistoryRequest{}) + if err != nil { + return nil, errors.Wrap(err, "failed to get tss history") + } + + return resp.TssList, nil +} + +// GetPendingNonces returns the pending nonces +func (c *Clients) GetPendingNonces(ctx context.Context) (*types.QueryAllPendingNoncesResponse, error) { + resp, err := c.Observer.PendingNoncesAll(ctx, &types.QueryAllPendingNoncesRequest{}) + if err != nil { + return nil, errors.Wrap(err, "failed to get pending nonces") + } + + return resp, nil +} + +// GetPendingNoncesByChain returns the pending nonces for a chain and current tss address +func (c *Clients) GetPendingNoncesByChain(ctx context.Context, chainID int64) (types.PendingNonces, error) { + in := &types.QueryPendingNoncesByChainRequest{ChainId: chainID} + + resp, err := c.Observer.PendingNoncesByChain(ctx, in) + if err != nil { + return types.PendingNonces{}, errors.Wrap(err, "failed to get pending nonces by chain") + } + + return resp.PendingNonces, nil +} + +// HasVoted returns whether an observer has voted +func (c *Clients) HasVoted(ctx context.Context, ballotIndex string, voterAddress string) (bool, error) { + in := &types.QueryHasVotedRequest{ + BallotIdentifier: ballotIndex, + VoterAddress: voterAddress, + } + + resp, err := c.Observer.HasVoted(ctx, in) + if err != nil { + return false, errors.Wrap(err, "failed to check if observer has voted") + } + + return resp.HasVoted, nil +} diff --git a/pkg/rpc/clients_tendermint.go b/pkg/rpc/clients_tendermint.go new file mode 100644 index 0000000000..e1df340a71 --- /dev/null +++ b/pkg/rpc/clients_tendermint.go @@ -0,0 +1,35 @@ +package rpc + +import ( + "context" + + "cosmossdk.io/errors" + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice" + + "github.com/zeta-chain/zetacore/pkg/retry" +) + +// GetLatestZetaBlock returns the latest zeta block +func (c *Clients) GetLatestZetaBlock(ctx context.Context) (*tmservice.Block, error) { + res, err := c.Tendermint.GetLatestBlock(ctx, &tmservice.GetLatestBlockRequest{}) + if err != nil { + return nil, errors.Wrap(err, "failed to get latest zeta block") + } + + return res.SdkBlock, nil +} + +// GetNodeInfo returns the node info +func (c *Clients) GetNodeInfo(ctx context.Context) (*tmservice.GetNodeInfoResponse, error) { + var err error + + res, err := retry.DoTypedWithRetry(func() (*tmservice.GetNodeInfoResponse, error) { + return c.Tendermint.GetNodeInfo(ctx, &tmservice.GetNodeInfoRequest{}) + }) + + if err != nil { + return nil, errors.Wrap(err, "failed to get node info") + } + + return res, nil +} diff --git a/pkg/rpc/clients_test.go b/pkg/rpc/clients_test.go new file mode 100644 index 0000000000..8b61f8335d --- /dev/null +++ b/pkg/rpc/clients_test.go @@ -0,0 +1,923 @@ +package rpc + +import ( + "context" + "net" + "testing" + + authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + + abci "github.com/cometbft/cometbft/abci/types" + tmtypes "github.com/cometbft/cometbft/proto/tendermint/types" + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice" + "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + "github.com/stretchr/testify/require" + feemarkettypes "github.com/zeta-chain/ethermint/x/feemarket/types" + "go.nhat.io/grpcmock" + "go.nhat.io/grpcmock/planner" + + "github.com/zeta-chain/zetacore/cmd/zetacored/config" + "github.com/zeta-chain/zetacore/pkg/chains" + "github.com/zeta-chain/zetacore/pkg/coin" + "github.com/zeta-chain/zetacore/testutil/sample" + crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" + lightclienttypes "github.com/zeta-chain/zetacore/x/lightclient/types" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" + "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" +) + +const skipMethod = "skip" +const gRPCListenPath = "127.0.0.1:47392" + +// setupMockServer setup mock zetacore GRPC server +func setupMockServer( + t *testing.T, + serviceFunc any, method string, input any, expectedOutput any, + extra ...grpcmock.ServerOption, +) *grpcmock.Server { + listener, err := net.Listen("tcp", gRPCListenPath) + require.NoError(t, err) + + opts := []grpcmock.ServerOption{ + grpcmock.RegisterService(serviceFunc), + grpcmock.WithPlanner(planner.FirstMatch()), + grpcmock.WithListener(listener), + } + + opts = append(opts, extra...) + + if method != skipMethod { + opts = append(opts, func(s *grpcmock.Server) { + s.ExpectUnary(method). + UnlimitedTimes(). + WithPayload(input). + Return(expectedOutput) + }) + } + + server := grpcmock.MockUnstartedServer(opts...)(t) + + server.Serve() + + t.Cleanup(func() { + require.NoError(t, server.Close()) + }) + + return server +} + +func withDummyServer(zetaBlockHeight int64) []grpcmock.ServerOption { + return []grpcmock.ServerOption{ + grpcmock.RegisterService(crosschaintypes.RegisterQueryServer), + grpcmock.RegisterService(crosschaintypes.RegisterMsgServer), + grpcmock.RegisterService(feemarkettypes.RegisterQueryServer), + grpcmock.RegisterService(authtypes.RegisterQueryServer), + grpcmock.RegisterService(abci.RegisterABCIApplicationServer), + func(s *grpcmock.Server) { + // Block Height + s.ExpectUnary("/zetachain.zetacore.crosschain.Query/LastZetaHeight"). + UnlimitedTimes(). + Return(crosschaintypes.QueryLastZetaHeightResponse{Height: zetaBlockHeight}) + + // London Base Fee + s.ExpectUnary("/ethermint.feemarket.v1.Query/Params"). + UnlimitedTimes(). + Return(feemarkettypes.QueryParamsResponse{ + Params: feemarkettypes.Params{BaseFee: types.NewInt(100)}, + }) + }, + } +} + +func setupZetacoreClients(t *testing.T) Clients { + c, err := NewGRPCClients(gRPCListenPath, grpc.WithTransportCredentials(insecure.NewCredentials())) + + require.NoError(t, err) + + return c +} + +func TestZetacore_GetBallot(t *testing.T) { + ctx := context.Background() + + expectedOutput := observertypes.QueryBallotByIdentifierResponse{ + BallotIdentifier: "123", + Voters: nil, + ObservationType: 0, + BallotStatus: 0, + } + input := observertypes.QueryBallotByIdentifierRequest{BallotIdentifier: "123"} + method := "/zetachain.zetacore.observer.Query/BallotByIdentifier" + setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetBallotByID(ctx, "123") + require.NoError(t, err) + require.Equal(t, expectedOutput, *resp) +} + +func TestZetacore_GetCrosschainFlags(t *testing.T) { + ctx := context.Background() + + expectedOutput := observertypes.QueryGetCrosschainFlagsResponse{CrosschainFlags: observertypes.CrosschainFlags{ + IsInboundEnabled: true, + IsOutboundEnabled: false, + GasPriceIncreaseFlags: nil, + }} + input := observertypes.QueryGetCrosschainFlagsRequest{} + method := "/zetachain.zetacore.observer.Query/CrosschainFlags" + setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetCrosschainFlags(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput.CrosschainFlags, resp) +} + +func TestZetacore_GetRateLimiterFlags(t *testing.T) { + ctx := context.Background() + + // create sample flags + rateLimiterFlags := sample.RateLimiterFlags() + expectedOutput := crosschaintypes.QueryRateLimiterFlagsResponse{ + RateLimiterFlags: rateLimiterFlags, + } + + // setup mock server + input := crosschaintypes.QueryRateLimiterFlagsRequest{} + method := "/zetachain.zetacore.crosschain.Query/RateLimiterFlags" + setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + // query + resp, err := client.GetRateLimiterFlags(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput.RateLimiterFlags, resp) +} + +func TestZetacore_HeaderEnabledChains(t *testing.T) { + ctx := context.Background() + + expectedOutput := lightclienttypes.QueryHeaderEnabledChainsResponse{ + HeaderEnabledChains: []lightclienttypes.HeaderSupportedChain{ + { + ChainId: chains.Ethereum.ChainId, + Enabled: true, + }, + { + ChainId: chains.BitcoinMainnet.ChainId, + Enabled: true, + }, + }, + } + input := lightclienttypes.QueryHeaderEnabledChainsRequest{} + method := "/zetachain.zetacore.lightclient.Query/HeaderEnabledChains" + setupMockServer(t, lightclienttypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetBlockHeaderEnabledChains(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput.HeaderEnabledChains, resp) +} + +func TestZetacore_GetChainParamsForChainID(t *testing.T) { + ctx := context.Background() + + expectedOutput := observertypes.QueryGetChainParamsForChainResponse{ChainParams: &observertypes.ChainParams{ + ChainId: 123, + BallotThreshold: types.ZeroDec(), + MinObserverDelegation: types.ZeroDec(), + }} + input := observertypes.QueryGetChainParamsForChainRequest{ChainId: 123} + method := "/zetachain.zetacore.observer.Query/GetChainParamsForChain" + setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetChainParamsForChainID(ctx, 123) + require.NoError(t, err) + require.Equal(t, expectedOutput.ChainParams, resp) +} + +func TestZetacore_GetChainParams(t *testing.T) { + ctx := context.Background() + + expectedOutput := observertypes.QueryGetChainParamsResponse{ChainParams: &observertypes.ChainParamsList{ + ChainParams: []*observertypes.ChainParams{ + { + ChainId: 123, + MinObserverDelegation: types.ZeroDec(), + BallotThreshold: types.ZeroDec(), + }, + }, + }} + input := observertypes.QueryGetChainParamsRequest{} + method := "/zetachain.zetacore.observer.Query/GetChainParams" + setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetChainParams(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput.ChainParams.ChainParams, resp) +} + +func TestZetacore_GetUpgradePlan(t *testing.T) { + ctx := context.Background() + + expectedOutput := upgradetypes.QueryCurrentPlanResponse{ + Plan: &upgradetypes.Plan{ + Name: "big upgrade", + Height: 100, + }, + } + input := upgradetypes.QueryCurrentPlanRequest{} + method := "/cosmos.upgrade.v1beta1.Query/CurrentPlan" + setupMockServer(t, upgradetypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetUpgradePlan(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput.Plan, resp) +} + +func TestZetacore_GetAllCctx(t *testing.T) { + ctx := context.Background() + + expectedOutput := crosschaintypes.QueryAllCctxResponse{ + CrossChainTx: []*crosschaintypes.CrossChainTx{ + { + Index: "cross-chain4456", + }, + }, + Pagination: nil, + } + input := crosschaintypes.QueryAllCctxRequest{} + method := "/zetachain.zetacore.crosschain.Query/CctxAll" + setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetAllCctx(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput.CrossChainTx, resp) +} + +func TestZetacore_GetCctxByHash(t *testing.T) { + ctx := context.Background() + + expectedOutput := crosschaintypes.QueryGetCctxResponse{CrossChainTx: &crosschaintypes.CrossChainTx{ + Index: "9c8d02b6956b9c78ecb6090a8160faaa48e7aecfd0026fcdf533721d861436a3", + }} + input := crosschaintypes.QueryGetCctxRequest{ + Index: "9c8d02b6956b9c78ecb6090a8160faaa48e7aecfd0026fcdf533721d861436a3", + } + method := "/zetachain.zetacore.crosschain.Query/Cctx" + setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetCctxByHash(ctx, "9c8d02b6956b9c78ecb6090a8160faaa48e7aecfd0026fcdf533721d861436a3") + require.NoError(t, err) + require.Equal(t, expectedOutput.CrossChainTx, resp) +} + +func TestZetacore_GetCctxByNonce(t *testing.T) { + ctx := context.Background() + + expectedOutput := crosschaintypes.QueryGetCctxResponse{CrossChainTx: &crosschaintypes.CrossChainTx{ + Index: "9c8d02b6956b9c78ecb6090a8160faaa48e7aecfd0026fcdf533721d861436a3", + }} + input := crosschaintypes.QueryGetCctxByNonceRequest{ + ChainID: 7000, + Nonce: 55, + } + method := "/zetachain.zetacore.crosschain.Query/CctxByNonce" + setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetCctxByNonce(ctx, 7000, 55) + require.NoError(t, err) + require.Equal(t, expectedOutput.CrossChainTx, resp) +} + +func TestZetacore_GetObserverList(t *testing.T) { + ctx := context.Background() + + expectedOutput := observertypes.QueryObserverSetResponse{ + Observers: []string{ + "zeta19jr7nl82lrktge35f52x9g5y5prmvchmk40zhg", + "zeta1cxj07f3ju484ry2cnnhxl5tryyex7gev0yzxtj", + "zeta1hjct6q7npsspsg3dgvzk3sdf89spmlpf7rqmnw", + }, + } + input := observertypes.QueryObserverSet{} + method := "/zetachain.zetacore.observer.Query/ObserverSet" + setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetObserverList(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput.Observers, resp) +} + +func TestZetacore_GetRateLimiterInput(t *testing.T) { + ctx := context.Background() + + expectedOutput := &crosschaintypes.QueryRateLimiterInputResponse{ + Height: 10, + CctxsMissed: []*crosschaintypes.CrossChainTx{sample.CrossChainTx(t, "1-1")}, + CctxsPending: []*crosschaintypes.CrossChainTx{sample.CrossChainTx(t, "1-2")}, + TotalPending: 1, + PastCctxsValue: "123456", + PendingCctxsValue: "1234", + LowestPendingCctxHeight: 2, + } + input := crosschaintypes.QueryRateLimiterInputRequest{Window: 10} + method := "/zetachain.zetacore.crosschain.Query/RateLimiterInput" + setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetRateLimiterInput(ctx, 10) + require.NoError(t, err) + require.Equal(t, expectedOutput, resp) +} + +func TestZetacore_ListPendingCctx(t *testing.T) { + ctx := context.Background() + + expectedOutput := crosschaintypes.QueryListPendingCctxResponse{ + CrossChainTx: []*crosschaintypes.CrossChainTx{ + { + Index: "cross-chain4456", + }, + }, + TotalPending: 1, + } + input := crosschaintypes.QueryListPendingCctxRequest{ChainId: 7000} + method := "/zetachain.zetacore.crosschain.Query/ListPendingCctx" + setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, totalPending, err := client.ListPendingCCTX(ctx, 7000) + require.NoError(t, err) + require.Equal(t, expectedOutput.CrossChainTx, resp) + require.Equal(t, expectedOutput.TotalPending, totalPending) +} + +func TestZetacore_GetAbortedZetaAmount(t *testing.T) { + ctx := context.Background() + + expectedOutput := crosschaintypes.QueryZetaAccountingResponse{AbortedZetaAmount: "1080999"} + input := crosschaintypes.QueryZetaAccountingRequest{} + method := "/zetachain.zetacore.crosschain.Query/ZetaAccounting" + setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetAbortedZetaAmount(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput.AbortedZetaAmount, resp) +} + +// Need to test after refactor +func TestZetacore_GetGenesisSupply(t *testing.T) { +} + +func TestZetacore_GetZetaTokenSupplyOnNode(t *testing.T) { + ctx := context.Background() + + expectedOutput := banktypes.QuerySupplyOfResponse{ + Amount: types.Coin{ + Denom: config.BaseDenom, + Amount: types.NewInt(329438), + }} + input := banktypes.QuerySupplyOfRequest{Denom: config.BaseDenom} + method := "/cosmos.bank.v1beta1.Query/SupplyOf" + setupMockServer(t, banktypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetZetaTokenSupplyOnNode(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput.GetAmount().Amount, resp) +} + +func TestZetacore_GetBlockHeight(t *testing.T) { + ctx := context.Background() + + method := "/zetachain.zetacore.crosschain.Query/LastZetaHeight" + input := &crosschaintypes.QueryLastZetaHeightRequest{} + output := &crosschaintypes.QueryLastZetaHeightResponse{Height: 12345} + + setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, output) + + client := setupZetacoreClients(t) + + t.Run("last block height", func(t *testing.T) { + height, err := client.GetBlockHeight(ctx) + require.NoError(t, err) + require.Equal(t, int64(12345), height) + }) +} + +func TestZetacore_GetLatestZetaBlock(t *testing.T) { + ctx := context.Background() + + expectedOutput := tmservice.GetLatestBlockResponse{ + SdkBlock: &tmservice.Block{ + Header: tmservice.Header{}, + Data: tmtypes.Data{}, + Evidence: tmtypes.EvidenceList{}, + LastCommit: nil, + }, + } + input := tmservice.GetLatestBlockRequest{} + method := "/cosmos.base.tendermint.v1beta1.Service/GetLatestBlock" + setupMockServer(t, tmservice.RegisterServiceServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetLatestZetaBlock(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput.SdkBlock, resp) +} + +func TestZetacore_GetNodeInfo(t *testing.T) { + ctx := context.Background() + + expectedOutput := tmservice.GetNodeInfoResponse{ + DefaultNodeInfo: nil, + ApplicationVersion: &tmservice.VersionInfo{}, + } + input := tmservice.GetNodeInfoRequest{} + method := "/cosmos.base.tendermint.v1beta1.Service/GetNodeInfo" + setupMockServer(t, tmservice.RegisterServiceServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetNodeInfo(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput, *resp) +} + +func TestZetacore_GetBaseGasPrice(t *testing.T) { + ctx := context.Background() + + expectedOutput := feemarkettypes.QueryParamsResponse{ + Params: feemarkettypes.Params{ + BaseFee: types.NewInt(23455), + }, + } + input := feemarkettypes.QueryParamsRequest{} + method := "/ethermint.feemarket.v1.Query/Params" + setupMockServer(t, feemarkettypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetBaseGasPrice(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput.Params.BaseFee.Int64(), resp) +} + +func TestZetacore_GetNonceByChain(t *testing.T) { + ctx := context.Background() + + chain := chains.BscMainnet + expectedOutput := observertypes.QueryGetChainNoncesResponse{ + ChainNonces: observertypes.ChainNonces{ + Creator: "", + ChainId: chain.ChainId, + Nonce: 8446, + Signers: nil, + FinalizedHeight: 0, + }, + } + input := observertypes.QueryGetChainNoncesRequest{ChainId: chain.ChainId} + method := "/zetachain.zetacore.observer.Query/ChainNonces" + setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetNonceByChain(ctx, chain) + require.NoError(t, err) + require.Equal(t, expectedOutput.ChainNonces, resp) +} + +func TestZetacore_GetAllNodeAccounts(t *testing.T) { + ctx := context.Background() + + expectedOutput := observertypes.QueryAllNodeAccountResponse{ + NodeAccount: []*observertypes.NodeAccount{ + { + Operator: "zeta19jr7nl82lrktge35f52x9g5y5prmvchmk40zhg", + GranteeAddress: "zeta1kxhesgcvl6j5upupd9m3d3g3gfz4l3pcpqfnw6", + GranteePubkey: nil, + NodeStatus: 0, + }, + }, + } + input := observertypes.QueryAllNodeAccountRequest{} + method := "/zetachain.zetacore.observer.Query/NodeAccountAll" + setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetAllNodeAccounts(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput.NodeAccount, resp) +} + +func TestZetacore_GetKeyGen(t *testing.T) { + ctx := context.Background() + + expectedOutput := observertypes.QueryGetKeygenResponse{ + Keygen: &observertypes.Keygen{ + Status: observertypes.KeygenStatus_KeyGenSuccess, + GranteePubkeys: nil, + BlockNumber: 5646, + }} + input := observertypes.QueryGetKeygenRequest{} + method := "/zetachain.zetacore.observer.Query/Keygen" + setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetKeyGen(ctx) + require.NoError(t, err) + require.Equal(t, *expectedOutput.Keygen, resp) +} + +func TestZetacore_GetBallotByID(t *testing.T) { + ctx := context.Background() + + expectedOutput := observertypes.QueryBallotByIdentifierResponse{ + BallotIdentifier: "ballot1235", + } + input := observertypes.QueryBallotByIdentifierRequest{BallotIdentifier: "ballot1235"} + method := "/zetachain.zetacore.observer.Query/BallotByIdentifier" + setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetBallot(ctx, "ballot1235") + require.NoError(t, err) + require.Equal(t, expectedOutput, *resp) +} + +func TestZetacore_GetInboundTrackersForChain(t *testing.T) { + ctx := context.Background() + + chainID := chains.BscMainnet.ChainId + expectedOutput := crosschaintypes.QueryAllInboundTrackerByChainResponse{ + InboundTracker: []crosschaintypes.InboundTracker{ + { + ChainId: chainID, + TxHash: "DC76A6DCCC3AA62E89E69042ADC44557C50D59E4D3210C37D78DC8AE49B3B27F", + CoinType: coin.CoinType_Gas, + }, + }, + } + input := crosschaintypes.QueryAllInboundTrackerByChainRequest{ChainId: chainID} + method := "/zetachain.zetacore.crosschain.Query/InboundTrackerAllByChain" + setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetInboundTrackersForChain(ctx, chainID) + require.NoError(t, err) + require.Equal(t, expectedOutput.InboundTracker, resp) +} + +func TestZetacore_GetTss(t *testing.T) { + ctx := context.Background() + + expectedOutput := observertypes.QueryGetTSSResponse{ + TSS: observertypes.TSS{ + TssPubkey: "zetapub1addwnpepqtadxdyt037h86z60nl98t6zk56mw5zpnm79tsmvspln3hgt5phdc79kvfc", + TssParticipantList: nil, + OperatorAddressList: nil, + FinalizedZetaHeight: 1000, + KeyGenZetaHeight: 900, + }, + } + input := observertypes.QueryGetTSSRequest{} + method := "/zetachain.zetacore.observer.Query/TSS" + setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetTSS(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput.TSS, resp) +} + +func TestZetacore_GetEthTssAddress(t *testing.T) { + ctx := context.Background() + + expectedOutput := observertypes.QueryGetTssAddressResponse{ + Eth: "0x70e967acfcc17c3941e87562161406d41676fd83", + Btc: "bc1qm24wp577nk8aacckv8np465z3dvmu7ry45el6y", + } + input := observertypes.QueryGetTssAddressRequest{} + method := "/zetachain.zetacore.observer.Query/GetTssAddress" + setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetEVMTSSAddress(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput.Eth, resp) +} + +func TestZetacore_GetBtcTssAddress(t *testing.T) { + ctx := context.Background() + + expectedOutput := observertypes.QueryGetTssAddressResponse{ + Eth: "0x70e967acfcc17c3941e87562161406d41676fd83", + Btc: "bc1qm24wp577nk8aacckv8np465z3dvmu7ry45el6y", + } + input := observertypes.QueryGetTssAddressRequest{BitcoinChainId: 8332} + method := "/zetachain.zetacore.observer.Query/GetTssAddress" + setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetBTCTSSAddress(ctx, 8332) + require.NoError(t, err) + require.Equal(t, expectedOutput.Btc, resp) +} + +func TestZetacore_GetTssHistory(t *testing.T) { + ctx := context.Background() + + expectedOutput := observertypes.QueryTssHistoryResponse{ + TssList: []observertypes.TSS{ + { + TssPubkey: "zetapub1addwnpepqtadxdyt037h86z60nl98t6zk56mw5zpnm79tsmvspln3hgt5phdc79kvfc", + TssParticipantList: nil, + OperatorAddressList: nil, + FinalizedZetaHeight: 46546, + KeyGenZetaHeight: 6897, + }, + }, + } + input := observertypes.QueryTssHistoryRequest{} + method := "/zetachain.zetacore.observer.Query/TssHistory" + setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetTSSHistory(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput.TssList, resp) +} + +func TestZetacore_GetOutboundTracker(t *testing.T) { + chain := chains.BscMainnet + expectedOutput := crosschaintypes.QueryGetOutboundTrackerResponse{ + OutboundTracker: crosschaintypes.OutboundTracker{ + Index: "tracker12345", + ChainId: chain.ChainId, + Nonce: 456, + HashList: nil, + }, + } + input := crosschaintypes.QueryGetOutboundTrackerRequest{ + ChainID: chain.ChainId, + Nonce: 456, + } + method := "/zetachain.zetacore.crosschain.Query/OutboundTracker" + setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + ctx := context.Background() + resp, err := client.GetOutboundTracker(ctx, chain, 456) + require.NoError(t, err) + require.Equal(t, expectedOutput.OutboundTracker, *resp) +} + +func TestZetacore_GetAllOutboundTrackerByChain(t *testing.T) { + ctx := context.Background() + + chain := chains.BscMainnet + expectedOutput := crosschaintypes.QueryAllOutboundTrackerByChainResponse{ + OutboundTracker: []crosschaintypes.OutboundTracker{ + { + Index: "tracker23456", + ChainId: chain.ChainId, + Nonce: 123456, + HashList: nil, + }, + }, + } + input := crosschaintypes.QueryAllOutboundTrackerByChainRequest{ + Chain: chain.ChainId, + Pagination: &query.PageRequest{ + Key: nil, + Offset: 0, + Limit: 2000, + CountTotal: false, + Reverse: false, + }, + } + method := "/zetachain.zetacore.crosschain.Query/OutboundTrackerAllByChain" + setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetAllOutboundTrackerByChain(ctx, chain.ChainId, interfaces.Ascending) + require.NoError(t, err) + require.Equal(t, expectedOutput.OutboundTracker, resp) + + resp, err = client.GetAllOutboundTrackerByChain(ctx, chain.ChainId, interfaces.Descending) + require.NoError(t, err) + require.Equal(t, expectedOutput.OutboundTracker, resp) +} + +func TestZetacore_GetPendingNoncesByChain(t *testing.T) { + ctx := context.Background() + + expectedOutput := observertypes.QueryPendingNoncesByChainResponse{ + PendingNonces: observertypes.PendingNonces{ + NonceLow: 0, + NonceHigh: 0, + ChainId: chains.Ethereum.ChainId, + Tss: "", + }, + } + input := observertypes.QueryPendingNoncesByChainRequest{ChainId: chains.Ethereum.ChainId} + method := "/zetachain.zetacore.observer.Query/PendingNoncesByChain" + setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetPendingNoncesByChain(ctx, chains.Ethereum.ChainId) + require.NoError(t, err) + require.Equal(t, expectedOutput.PendingNonces, resp) +} + +func TestZetacore_GetBlockHeaderChainState(t *testing.T) { + ctx := context.Background() + + chainID := chains.BscMainnet.ChainId + expectedOutput := lightclienttypes.QueryGetChainStateResponse{ChainState: &lightclienttypes.ChainState{ + ChainId: chainID, + LatestHeight: 5566654, + EarliestHeight: 4454445, + LatestBlockHash: nil, + }} + input := lightclienttypes.QueryGetChainStateRequest{ChainId: chainID} + method := "/zetachain.zetacore.lightclient.Query/ChainState" + setupMockServer(t, lightclienttypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetBlockHeaderChainState(ctx, chainID) + require.NoError(t, err) + require.Equal(t, expectedOutput.ChainState, resp) +} + +func TestZetacore_GetSupportedChains(t *testing.T) { + ctx := context.Background() + + expectedOutput := observertypes.QuerySupportedChainsResponse{ + Chains: []chains.Chain{ + { + ChainId: chains.BitcoinMainnet.ChainId, + Network: chains.BscMainnet.Network, + NetworkType: chains.BscMainnet.NetworkType, + Vm: chains.BscMainnet.Vm, + Consensus: chains.BscMainnet.Consensus, + IsExternal: chains.BscMainnet.IsExternal, + Name: chains.BscMainnet.Name, + }, + { + ChainId: chains.Ethereum.ChainId, + Network: chains.Ethereum.Network, + NetworkType: chains.Ethereum.NetworkType, + Vm: chains.Ethereum.Vm, + Consensus: chains.Ethereum.Consensus, + IsExternal: chains.Ethereum.IsExternal, + Name: chains.Ethereum.Name, + }, + }, + } + input := observertypes.QuerySupportedChains{} + method := "/zetachain.zetacore.observer.Query/SupportedChains" + setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetSupportedChains(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput.Chains, resp) +} + +func TestZetacore_GetAdditionalChains(t *testing.T) { + ctx := context.Background() + + expectedOutput := authoritytypes.QueryGetChainInfoResponse{ + ChainInfo: authoritytypes.ChainInfo{ + Chains: []chains.Chain{ + chains.BitcoinMainnet, + chains.Ethereum, + }, + }, + } + input := observertypes.QuerySupportedChains{} + method := "/zetachain.zetacore.authority.Query/ChainInfo" + + setupMockServer(t, authoritytypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetAdditionalChains(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput.ChainInfo.Chains, resp) +} + +func TestZetacore_GetPendingNonces(t *testing.T) { + ctx := context.Background() + + expectedOutput := observertypes.QueryAllPendingNoncesResponse{ + PendingNonces: []observertypes.PendingNonces{ + { + NonceLow: 225, + NonceHigh: 226, + ChainId: 8332, + Tss: "bc1qm24wp577nk8aacckv8np465z3dvmu7ry45el6y", + }, + }, + } + input := observertypes.QueryAllPendingNoncesRequest{} + method := "/zetachain.zetacore.observer.Query/PendingNoncesAll" + setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.GetPendingNonces(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput, *resp) +} + +func TestZetacore_Prove(t *testing.T) { + ctx := context.Background() + + chainId := chains.BscMainnet.ChainId + txHash := "9c8d02b6956b9c78ecb6090a8160faaa48e7aecfd0026fcdf533721d861436a3" + blockHash := "0000000000000000000172c9a64f86f208b867a84dc7a0b7c75be51e750ed8eb" + txIndex := 555 + expectedOutput := lightclienttypes.QueryProveResponse{ + Valid: true, + } + input := lightclienttypes.QueryProveRequest{ + ChainId: chainId, + TxHash: txHash, + Proof: nil, + BlockHash: blockHash, + TxIndex: int64(txIndex), + } + method := "/zetachain.zetacore.lightclient.Query/Prove" + setupMockServer(t, lightclienttypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.Prove(ctx, blockHash, txHash, int64(txIndex), nil, chainId) + require.NoError(t, err) + require.Equal(t, expectedOutput.Valid, resp) +} + +func TestZetacore_HasVoted(t *testing.T) { + ctx := context.Background() + + expectedOutput := observertypes.QueryHasVotedResponse{HasVoted: true} + input := observertypes.QueryHasVotedRequest{ + BallotIdentifier: "123456asdf", + VoterAddress: "zeta1l40mm7meacx03r4lp87s9gkxfan32xnznp42u6", + } + method := "/zetachain.zetacore.observer.Query/HasVoted" + setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClients(t) + + resp, err := client.HasVoted(ctx, "123456asdf", "zeta1l40mm7meacx03r4lp87s9gkxfan32xnznp42u6") + require.NoError(t, err) + require.Equal(t, expectedOutput.HasVoted, resp) +} From 3025cde9b29458a460e64520bb8fd0fbbb2c36bc Mon Sep 17 00:00:00 2001 From: Alex Gartner Date: Thu, 29 Aug 2024 12:20:46 -0700 Subject: [PATCH 5/8] embed rpc.Clients in zetaclient/zetacored.Client --- pkg/rpc/clients.go | 2 +- zetaclient/zetacore/client.go | 39 +- ...lient_query_cosmos.go => client_cosmos.go} | 28 +- zetaclient/zetacore/client_query_authority.go | 18 - .../zetacore/client_query_crosschain.go | 194 ---- zetaclient/zetacore/client_query_ethermint.go | 23 - .../zetacore/client_query_lightclient.go | 57 - zetaclient/zetacore/client_query_observer.go | 218 ---- .../zetacore/client_query_tendermint.go | 35 - zetaclient/zetacore/client_query_test.go | 1024 ----------------- zetaclient/zetacore/client_test.go | 191 +++ 11 files changed, 200 insertions(+), 1629 deletions(-) rename zetaclient/zetacore/{client_query_cosmos.go => client_cosmos.go} (64%) delete mode 100644 zetaclient/zetacore/client_query_authority.go delete mode 100644 zetaclient/zetacore/client_query_crosschain.go delete mode 100644 zetaclient/zetacore/client_query_ethermint.go delete mode 100644 zetaclient/zetacore/client_query_lightclient.go delete mode 100644 zetaclient/zetacore/client_query_observer.go delete mode 100644 zetaclient/zetacore/client_query_tendermint.go delete mode 100644 zetaclient/zetacore/client_query_test.go create mode 100644 zetaclient/zetacore/client_test.go diff --git a/pkg/rpc/clients.go b/pkg/rpc/clients.go index 59fa329f81..2e36e84021 100644 --- a/pkg/rpc/clients.go +++ b/pkg/rpc/clients.go @@ -20,7 +20,7 @@ import ( observertypes "github.com/zeta-chain/zetacore/x/observer/types" ) -// Clients contains RPC client interfaces to interact with zetacored +// Clients contains RPC client interfaces to interact with ZetaCore type Clients struct { // Cosmos SDK clients diff --git a/zetaclient/zetacore/client.go b/zetaclient/zetacore/client.go index aee2e51784..dc5a888678 100644 --- a/zetaclient/zetacore/client.go +++ b/zetaclient/zetacore/client.go @@ -10,23 +10,17 @@ import ( rpchttp "github.com/cometbft/cometbft/rpc/client/http" cosmosclient "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/grpc/tmservice" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" "github.com/pkg/errors" "github.com/rs/zerolog" etherminttypes "github.com/zeta-chain/ethermint/types" - feemarkettypes "github.com/zeta-chain/ethermint/x/feemarket/types" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "github.com/zeta-chain/zetacore/app" "github.com/zeta-chain/zetacore/pkg/authz" "github.com/zeta-chain/zetacore/pkg/chains" - authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" - crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" - lightclienttypes "github.com/zeta-chain/zetacore/x/lightclient/types" + zetacore_rpc "github.com/zeta-chain/zetacore/pkg/rpc" observertypes "github.com/zeta-chain/zetacore/x/observer/types" "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" "github.com/zeta-chain/zetacore/zetaclient/config" @@ -38,10 +32,11 @@ var _ interfaces.ZetacoreClient = &Client{} // Client is the client to send tx to zetacore type Client struct { + zetacore_rpc.Clients + logger zerolog.Logger config config.ClientConfiguration - client clients cosmosClientContext cosmosclient.Context blockHeight int64 @@ -58,17 +53,6 @@ type Client struct { mu sync.RWMutex } -type clients struct { - observer observertypes.QueryClient - light lightclienttypes.QueryClient - crosschain crosschaintypes.QueryClient - bank banktypes.QueryClient - upgrade upgradetypes.QueryClient - fees feemarkettypes.QueryClient - authority authoritytypes.QueryClient - tendermint tmservice.ServiceClient -} - var unsecureGRPC = grpc.WithTransportCredentials(insecure.NewCredentials()) type constructOpts struct { @@ -129,7 +113,7 @@ func NewClient( encodingCfg := app.MakeEncodingConfig() - grpcConn, err := grpc.Dial(cosmosGRPC(chainIP), unsecureGRPC) + zetacoreClients, err := zetacore_rpc.NewGRPCClients(cosmosGRPC(chainIP), unsecureGRPC) if err != nil { return nil, errors.Wrap(err, "grpc dial fail") } @@ -147,20 +131,11 @@ func NewClient( } return &Client{ - logger: log, - config: cfg, + Clients: zetacoreClients, + logger: log, + config: cfg, cosmosClientContext: cosmosContext, - client: clients{ - observer: observertypes.NewQueryClient(grpcConn), - light: lightclienttypes.NewQueryClient(grpcConn), - crosschain: crosschaintypes.NewQueryClient(grpcConn), - bank: banktypes.NewQueryClient(grpcConn), - upgrade: upgradetypes.NewQueryClient(grpcConn), - fees: feemarkettypes.NewQueryClient(grpcConn), - authority: authoritytypes.NewQueryClient(grpcConn), - tendermint: tmservice.NewServiceClient(grpcConn), - }, accountNumber: accountsMap, seqNumber: seqMap, diff --git a/zetaclient/zetacore/client_query_cosmos.go b/zetaclient/zetacore/client_cosmos.go similarity index 64% rename from zetaclient/zetacore/client_query_cosmos.go rename to zetaclient/zetacore/client_cosmos.go index 61d690d54a..815615c3bd 100644 --- a/zetaclient/zetacore/client_query_cosmos.go +++ b/zetaclient/zetacore/client_cosmos.go @@ -8,7 +8,6 @@ import ( tmhttp "github.com/cometbft/cometbft/rpc/client/http" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" - upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" "github.com/pkg/errors" "github.com/zeta-chain/zetacore/cmd/zetacored/config" @@ -42,31 +41,6 @@ func (c *Client) GetGenesisSupply(ctx context.Context) (sdkmath.Int, error) { return bankstate.Supply.AmountOf(config.BaseDenom), nil } -// GetUpgradePlan returns the current upgrade plan. -// if there is no active upgrade plan, plan will be nil, err will be nil as well. -func (c *Client) GetUpgradePlan(ctx context.Context) (*upgradetypes.Plan, error) { - in := &upgradetypes.QueryCurrentPlanRequest{} - - resp, err := c.client.upgrade.CurrentPlan(ctx, in) - if err != nil { - return nil, errors.Wrap(err, "failed to get current upgrade plan") - } - - return resp.Plan, nil -} - -// GetZetaTokenSupplyOnNode returns the zeta token supply on the node -func (c *Client) GetZetaTokenSupplyOnNode(ctx context.Context) (sdkmath.Int, error) { - in := &banktypes.QuerySupplyOfRequest{Denom: config.BaseDenom} - - resp, err := c.client.bank.SupplyOf(ctx, in) - if err != nil { - return sdkmath.ZeroInt(), errors.Wrap(err, "failed to get zeta token supply") - } - - return resp.GetAmount().Amount, nil -} - // GetZetaHotKeyBalance returns the zeta hot key balance func (c *Client) GetZetaHotKeyBalance(ctx context.Context) (sdkmath.Int, error) { address, err := c.keys.GetAddress() @@ -79,7 +53,7 @@ func (c *Client) GetZetaHotKeyBalance(ctx context.Context) (sdkmath.Int, error) Denom: config.BaseDenom, } - resp, err := c.client.bank.Balance(ctx, in) + resp, err := c.Clients.Bank.Balance(ctx, in) if err != nil { return sdkmath.ZeroInt(), errors.Wrap(err, "failed to get zeta hot key balance") } diff --git a/zetaclient/zetacore/client_query_authority.go b/zetaclient/zetacore/client_query_authority.go deleted file mode 100644 index 044a3d47ee..0000000000 --- a/zetaclient/zetacore/client_query_authority.go +++ /dev/null @@ -1,18 +0,0 @@ -package zetacore - -import ( - "context" - - "github.com/zeta-chain/zetacore/pkg/chains" - authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" -) - -// GetAdditionalChains returns the additional chains -func (c *Client) GetAdditionalChains(ctx context.Context) ([]chains.Chain, error) { - resp, err := c.client.authority.ChainInfo(ctx, &authoritytypes.QueryGetChainInfoRequest{}) - if err != nil { - return nil, err - } - - return resp.GetChainInfo().Chains, nil -} diff --git a/zetaclient/zetacore/client_query_crosschain.go b/zetaclient/zetacore/client_query_crosschain.go deleted file mode 100644 index 262b766a6b..0000000000 --- a/zetaclient/zetacore/client_query_crosschain.go +++ /dev/null @@ -1,194 +0,0 @@ -package zetacore - -import ( - "context" - "sort" - - "cosmossdk.io/errors" - "github.com/cosmos/cosmos-sdk/types/query" - "google.golang.org/grpc" - - "github.com/zeta-chain/zetacore/pkg/chains" - "github.com/zeta-chain/zetacore/x/crosschain/types" - "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" -) - -// 32MB -var maxSizeOption = grpc.MaxCallRecvMsgSize(32 * 1024 * 1024) - -// GetLastBlockHeight returns the zetachain block height -func (c *Client) GetLastBlockHeight(ctx context.Context) (uint64, error) { - resp, err := c.client.crosschain.LastBlockHeight(ctx, &types.QueryGetLastBlockHeightRequest{}) - if err != nil { - return 0, errors.Wrap(err, "failed to get block height") - } - - return resp.GetLastBlockHeight().LastInboundHeight, nil -} - -// GetBlockHeight returns the zetachain block height -func (c *Client) GetBlockHeight(ctx context.Context) (int64, error) { - resp, err := c.client.crosschain.LastZetaHeight(ctx, &types.QueryLastZetaHeightRequest{}) - if err != nil { - return 0, err - } - - return resp.Height, nil -} - -// GetAbortedZetaAmount returns the amount of zeta that has been aborted -func (c *Client) GetAbortedZetaAmount(ctx context.Context) (string, error) { - resp, err := c.client.crosschain.ZetaAccounting(ctx, &types.QueryZetaAccountingRequest{}) - if err != nil { - return "", errors.Wrap(err, "failed to get aborted zeta amount") - } - - return resp.AbortedZetaAmount, nil -} - -// GetRateLimiterFlags returns the rate limiter flags -func (c *Client) GetRateLimiterFlags(ctx context.Context) (types.RateLimiterFlags, error) { - resp, err := c.client.crosschain.RateLimiterFlags(ctx, &types.QueryRateLimiterFlagsRequest{}) - if err != nil { - return types.RateLimiterFlags{}, errors.Wrap(err, "failed to get rate limiter flags") - } - - return resp.RateLimiterFlags, nil -} - -// GetRateLimiterInput returns input data for the rate limit checker -func (c *Client) GetRateLimiterInput(ctx context.Context, window int64) (*types.QueryRateLimiterInputResponse, error) { - in := &types.QueryRateLimiterInputRequest{Window: window} - - resp, err := c.client.crosschain.RateLimiterInput(ctx, in, maxSizeOption) - if err != nil { - return nil, errors.Wrap(err, "failed to get rate limiter input") - } - - return resp, nil -} - -// GetAllCctx returns all cross chain transactions -func (c *Client) GetAllCctx(ctx context.Context) ([]*types.CrossChainTx, error) { - resp, err := c.client.crosschain.CctxAll(ctx, &types.QueryAllCctxRequest{}) - if err != nil { - return nil, errors.Wrap(err, "failed to get all cross chain transactions") - } - - return resp.CrossChainTx, nil -} - -func (c *Client) GetCctxByHash(ctx context.Context, sendHash string) (*types.CrossChainTx, error) { - in := &types.QueryGetCctxRequest{Index: sendHash} - resp, err := c.client.crosschain.Cctx(ctx, in) - if err != nil { - return nil, errors.Wrap(err, "failed to get cctx by hash") - } - - return resp.CrossChainTx, nil -} - -// GetCctxByNonce returns a cross chain transaction by nonce -func (c *Client) GetCctxByNonce(ctx context.Context, chainID int64, nonce uint64) (*types.CrossChainTx, error) { - resp, err := c.client.crosschain.CctxByNonce(ctx, &types.QueryGetCctxByNonceRequest{ - ChainID: chainID, - Nonce: nonce, - }) - if err != nil { - return nil, errors.Wrap(err, "failed to get cctx by nonce") - } - - return resp.CrossChainTx, nil -} - -// ListPendingCCTXWithinRateLimit returns a list of pending cctxs that do not exceed the outbound rate limit -// - The max size of the list is crosschainkeeper.MaxPendingCctxs -// - The returned `rateLimitExceeded` flag indicates if the rate limit is exceeded or not -func (c *Client) ListPendingCCTXWithinRateLimit( - ctx context.Context, -) (*types.QueryListPendingCctxWithinRateLimitResponse, error) { - in := &types.QueryListPendingCctxWithinRateLimitRequest{} - - resp, err := c.client.crosschain.ListPendingCctxWithinRateLimit(ctx, in, maxSizeOption) - if err != nil { - return nil, errors.Wrap(err, "failed to get pending cctxs within rate limit") - } - - return resp, nil -} - -// ListPendingCCTX returns a list of pending cctxs for a given chainID -// - The max size of the list is crosschainkeeper.MaxPendingCctxs -func (c *Client) ListPendingCCTX(ctx context.Context, chainID int64) ([]*types.CrossChainTx, uint64, error) { - in := &types.QueryListPendingCctxRequest{ChainId: chainID} - - resp, err := c.client.crosschain.ListPendingCctx(ctx, in, maxSizeOption) - if err != nil { - return nil, 0, errors.Wrap(err, "failed to get pending cctxs") - } - - return resp.CrossChainTx, resp.TotalPending, nil -} - -// GetOutboundTracker returns the outbound tracker for a chain and nonce -func (c *Client) GetOutboundTracker( - ctx context.Context, - chain chains.Chain, - nonce uint64, -) (*types.OutboundTracker, error) { - in := &types.QueryGetOutboundTrackerRequest{ChainID: chain.ChainId, Nonce: nonce} - - resp, err := c.client.crosschain.OutboundTracker(ctx, in) - if err != nil { - return nil, err - } - - return &resp.OutboundTracker, nil -} - -// GetInboundTrackersForChain returns the inbound trackers for a chain -func (c *Client) GetInboundTrackersForChain(ctx context.Context, chainID int64) ([]types.InboundTracker, error) { - in := &types.QueryAllInboundTrackerByChainRequest{ChainId: chainID} - - resp, err := c.client.crosschain.InboundTrackerAllByChain(ctx, in) - if err != nil { - return nil, err - } - - return resp.InboundTracker, nil -} - -// GetAllOutboundTrackerByChain returns all outbound trackers for a chain -func (c *Client) GetAllOutboundTrackerByChain( - ctx context.Context, - chainID int64, - order interfaces.Order, -) ([]types.OutboundTracker, error) { - in := &types.QueryAllOutboundTrackerByChainRequest{ - Chain: chainID, - Pagination: &query.PageRequest{ - Key: nil, - Offset: 0, - Limit: 2000, - CountTotal: false, - Reverse: false, - }, - } - - resp, err := c.client.crosschain.OutboundTrackerAllByChain(ctx, in) - if err != nil { - return nil, errors.Wrap(err, "failed to get all outbound trackers") - } - - if order == interfaces.Ascending { - sort.SliceStable(resp.OutboundTracker, func(i, j int) bool { - return resp.OutboundTracker[i].Nonce < resp.OutboundTracker[j].Nonce - }) - } else if order == interfaces.Descending { - sort.SliceStable(resp.OutboundTracker, func(i, j int) bool { - return resp.OutboundTracker[i].Nonce > resp.OutboundTracker[j].Nonce - }) - } - - return resp.OutboundTracker, nil -} diff --git a/zetaclient/zetacore/client_query_ethermint.go b/zetaclient/zetacore/client_query_ethermint.go deleted file mode 100644 index b9fc5a4a7a..0000000000 --- a/zetaclient/zetacore/client_query_ethermint.go +++ /dev/null @@ -1,23 +0,0 @@ -package zetacore - -import ( - "context" - "fmt" - - "cosmossdk.io/errors" - feemarkettypes "github.com/zeta-chain/ethermint/x/feemarket/types" -) - -// GetBaseGasPrice returns the base gas price -func (c *Client) GetBaseGasPrice(ctx context.Context) (int64, error) { - resp, err := c.client.fees.Params(ctx, &feemarkettypes.QueryParamsRequest{}) - if err != nil { - return 0, errors.Wrap(err, "failed to get base gas price") - } - - if resp.Params.BaseFee.IsNil() { - return 0, fmt.Errorf("base fee is nil") - } - - return resp.Params.BaseFee.Int64(), nil -} diff --git a/zetaclient/zetacore/client_query_lightclient.go b/zetaclient/zetacore/client_query_lightclient.go deleted file mode 100644 index f5999a5d2a..0000000000 --- a/zetaclient/zetacore/client_query_lightclient.go +++ /dev/null @@ -1,57 +0,0 @@ -package zetacore - -import ( - "context" - - "cosmossdk.io/errors" - - "github.com/zeta-chain/zetacore/pkg/proofs" - "github.com/zeta-chain/zetacore/x/lightclient/types" -) - -// GetBlockHeaderEnabledChains returns the enabled chains for block headers -func (c *Client) GetBlockHeaderEnabledChains(ctx context.Context) ([]types.HeaderSupportedChain, error) { - resp, err := c.client.light.HeaderEnabledChains(ctx, &types.QueryHeaderEnabledChainsRequest{}) - if err != nil { - return []types.HeaderSupportedChain{}, err - } - - return resp.HeaderEnabledChains, nil -} - -// GetBlockHeaderChainState returns the block header chain state -func (c *Client) GetBlockHeaderChainState(ctx context.Context, chainID int64) (*types.ChainState, error) { - in := &types.QueryGetChainStateRequest{ChainId: chainID} - - resp, err := c.client.light.ChainState(ctx, in) - if err != nil { - return nil, errors.Wrap(err, "failed to get chain state") - } - - return resp.ChainState, nil -} - -// Prove returns whether a proof is valid -func (c *Client) Prove( - ctx context.Context, - blockHash string, - txHash string, - txIndex int64, - proof *proofs.Proof, - chainID int64, -) (bool, error) { - in := &types.QueryProveRequest{ - BlockHash: blockHash, - TxIndex: txIndex, - Proof: proof, - ChainId: chainID, - TxHash: txHash, - } - - resp, err := c.client.light.Prove(ctx, in) - if err != nil { - return false, errors.Wrap(err, "failed to prove") - } - - return resp.Valid, nil -} diff --git a/zetaclient/zetacore/client_query_observer.go b/zetaclient/zetacore/client_query_observer.go deleted file mode 100644 index a8ed20c998..0000000000 --- a/zetaclient/zetacore/client_query_observer.go +++ /dev/null @@ -1,218 +0,0 @@ -package zetacore - -import ( - "context" - "fmt" - - "cosmossdk.io/errors" - - "github.com/zeta-chain/zetacore/pkg/chains" - "github.com/zeta-chain/zetacore/pkg/retry" - "github.com/zeta-chain/zetacore/x/observer/types" -) - -// GetCrosschainFlags returns the crosschain flags -func (c *Client) GetCrosschainFlags(ctx context.Context) (types.CrosschainFlags, error) { - resp, err := c.client.observer.CrosschainFlags(ctx, &types.QueryGetCrosschainFlagsRequest{}) - if err != nil { - return types.CrosschainFlags{}, err - } - - return resp.CrosschainFlags, nil -} - -// GetSupportedChains returns the supported chains -func (c *Client) GetSupportedChains(ctx context.Context) ([]chains.Chain, error) { - resp, err := c.client.observer.SupportedChains(ctx, &types.QuerySupportedChains{}) - if err != nil { - return nil, errors.Wrap(err, "failed to get supported chains") - } - - return resp.GetChains(), nil -} - -// GetChainParams returns all the chain params -func (c *Client) GetChainParams(ctx context.Context) ([]*types.ChainParams, error) { - in := &types.QueryGetChainParamsRequest{} - - resp, err := retry.DoTypedWithRetry(func() (*types.QueryGetChainParamsResponse, error) { - return c.client.observer.GetChainParams(ctx, in) - }) - - if err != nil { - return nil, errors.Wrap(err, "failed to get chain params") - } - - return resp.ChainParams.ChainParams, nil -} - -// GetChainParamsForChainID returns the chain params for a given chain ID -func (c *Client) GetChainParamsForChainID( - ctx context.Context, - externalChainID int64, -) (*types.ChainParams, error) { - in := &types.QueryGetChainParamsForChainRequest{ChainId: externalChainID} - - resp, err := c.client.observer.GetChainParamsForChain(ctx, in) - if err != nil { - return &types.ChainParams{}, err - } - - return resp.ChainParams, nil -} - -// GetObserverList returns the list of observers -func (c *Client) GetObserverList(ctx context.Context) ([]string, error) { - in := &types.QueryObserverSet{} - - resp, err := retry.DoTypedWithRetry(func() (*types.QueryObserverSetResponse, error) { - return c.client.observer.ObserverSet(ctx, in) - }) - - if err != nil { - return nil, errors.Wrap(err, "failed to get observer list") - } - - return resp.Observers, nil -} - -// GetBallotByID returns a ballot by ID -func (c *Client) GetBallotByID(ctx context.Context, id string) (*types.QueryBallotByIdentifierResponse, error) { - in := &types.QueryBallotByIdentifierRequest{BallotIdentifier: id} - - return c.client.observer.BallotByIdentifier(ctx, in) -} - -// GetNonceByChain returns the nonce by chain -func (c *Client) GetNonceByChain(ctx context.Context, chain chains.Chain) (types.ChainNonces, error) { - in := &types.QueryGetChainNoncesRequest{ChainId: chain.ChainId} - - resp, err := c.client.observer.ChainNonces(ctx, in) - if err != nil { - return types.ChainNonces{}, errors.Wrap(err, "failed to get nonce by chain") - } - - return resp.ChainNonces, nil -} - -// GetKeyGen returns the keygen -func (c *Client) GetKeyGen(ctx context.Context) (types.Keygen, error) { - in := &types.QueryGetKeygenRequest{} - - resp, err := retry.DoTypedWithRetry(func() (*types.QueryGetKeygenResponse, error) { - return c.client.observer.Keygen(ctx, in) - }) - - switch { - case err != nil: - return types.Keygen{}, errors.Wrap(err, "failed to get keygen") - case resp.Keygen == nil: - return types.Keygen{}, fmt.Errorf("keygen is nil") - } - - return *resp.Keygen, nil -} - -// GetAllNodeAccounts returns all node accounts -func (c *Client) GetAllNodeAccounts(ctx context.Context) ([]*types.NodeAccount, error) { - resp, err := c.client.observer.NodeAccountAll(ctx, &types.QueryAllNodeAccountRequest{}) - if err != nil { - return nil, errors.Wrap(err, "failed to get all node accounts") - } - - c.logger.Debug().Int("node_account.len", len(resp.NodeAccount)).Msg("GetAllNodeAccounts: OK") - - return resp.NodeAccount, nil -} - -// GetBallot returns a ballot by ID -func (c *Client) GetBallot( - ctx context.Context, - ballotIdentifier string, -) (*types.QueryBallotByIdentifierResponse, error) { - in := &types.QueryBallotByIdentifierRequest{BallotIdentifier: ballotIdentifier} - - resp, err := c.client.observer.BallotByIdentifier(ctx, in) - if err != nil { - return nil, errors.Wrap(err, "failed to get ballot") - } - - return resp, nil -} - -// GetEVMTSSAddress returns the current EVM TSS address. -func (c *Client) GetEVMTSSAddress(ctx context.Context) (string, error) { - resp, err := c.client.observer.GetTssAddress(ctx, &types.QueryGetTssAddressRequest{}) - if err != nil { - return "", errors.Wrap(err, "failed to get eth tss address") - } - - return resp.Eth, nil -} - -// GetBTCTSSAddress returns the current BTC TSS address -func (c *Client) GetBTCTSSAddress(ctx context.Context, chainID int64) (string, error) { - in := &types.QueryGetTssAddressRequest{BitcoinChainId: chainID} - - resp, err := c.client.observer.GetTssAddress(ctx, in) - if err != nil { - return "", errors.Wrap(err, "failed to get btc tss address") - } - return resp.Btc, nil -} - -// GetTSS returns the current TSS -func (c *Client) GetTSS(ctx context.Context) (types.TSS, error) { - resp, err := c.client.observer.TSS(ctx, &types.QueryGetTSSRequest{}) - if err != nil { - return types.TSS{}, errors.Wrap(err, "failed to get tss") - } - return resp.TSS, nil -} - -// GetTSSHistory returns the historical list of TSS -func (c *Client) GetTSSHistory(ctx context.Context) ([]types.TSS, error) { - resp, err := c.client.observer.TssHistory(ctx, &types.QueryTssHistoryRequest{}) - if err != nil { - return nil, errors.Wrap(err, "failed to get tss history") - } - - return resp.TssList, nil -} - -// GetPendingNonces returns the pending nonces -func (c *Client) GetPendingNonces(ctx context.Context) (*types.QueryAllPendingNoncesResponse, error) { - resp, err := c.client.observer.PendingNoncesAll(ctx, &types.QueryAllPendingNoncesRequest{}) - if err != nil { - return nil, errors.Wrap(err, "failed to get pending nonces") - } - - return resp, nil -} - -// GetPendingNoncesByChain returns the pending nonces for a chain and current tss address -func (c *Client) GetPendingNoncesByChain(ctx context.Context, chainID int64) (types.PendingNonces, error) { - in := &types.QueryPendingNoncesByChainRequest{ChainId: chainID} - - resp, err := c.client.observer.PendingNoncesByChain(ctx, in) - if err != nil { - return types.PendingNonces{}, errors.Wrap(err, "failed to get pending nonces by chain") - } - - return resp.PendingNonces, nil -} - -// HasVoted returns whether an observer has voted -func (c *Client) HasVoted(ctx context.Context, ballotIndex string, voterAddress string) (bool, error) { - in := &types.QueryHasVotedRequest{ - BallotIdentifier: ballotIndex, - VoterAddress: voterAddress, - } - - resp, err := c.client.observer.HasVoted(ctx, in) - if err != nil { - return false, errors.Wrap(err, "failed to check if observer has voted") - } - - return resp.HasVoted, nil -} diff --git a/zetaclient/zetacore/client_query_tendermint.go b/zetaclient/zetacore/client_query_tendermint.go deleted file mode 100644 index adb38d0bab..0000000000 --- a/zetaclient/zetacore/client_query_tendermint.go +++ /dev/null @@ -1,35 +0,0 @@ -package zetacore - -import ( - "context" - - "cosmossdk.io/errors" - "github.com/cosmos/cosmos-sdk/client/grpc/tmservice" - - "github.com/zeta-chain/zetacore/pkg/retry" -) - -// GetLatestZetaBlock returns the latest zeta block -func (c *Client) GetLatestZetaBlock(ctx context.Context) (*tmservice.Block, error) { - res, err := c.client.tendermint.GetLatestBlock(ctx, &tmservice.GetLatestBlockRequest{}) - if err != nil { - return nil, errors.Wrap(err, "failed to get latest zeta block") - } - - return res.SdkBlock, nil -} - -// GetNodeInfo returns the node info -func (c *Client) GetNodeInfo(ctx context.Context) (*tmservice.GetNodeInfoResponse, error) { - var err error - - res, err := retry.DoTypedWithRetry(func() (*tmservice.GetNodeInfoResponse, error) { - return c.client.tendermint.GetNodeInfo(ctx, &tmservice.GetNodeInfoRequest{}) - }) - - if err != nil { - return nil, errors.Wrap(err, "failed to get node info") - } - - return res, nil -} diff --git a/zetaclient/zetacore/client_query_test.go b/zetaclient/zetacore/client_query_test.go deleted file mode 100644 index cf3ddb8d50..0000000000 --- a/zetaclient/zetacore/client_query_test.go +++ /dev/null @@ -1,1024 +0,0 @@ -package zetacore - -import ( - "context" - "net" - "testing" - - authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" - - abci "github.com/cometbft/cometbft/abci/types" - tmtypes "github.com/cometbft/cometbft/proto/tendermint/types" - cosmosclient "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/grpc/tmservice" - "github.com/cosmos/cosmos-sdk/testutil/mock" - "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/query" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" - "github.com/golang/mock/gomock" - "github.com/rs/zerolog" - "github.com/stretchr/testify/require" - feemarkettypes "github.com/zeta-chain/ethermint/x/feemarket/types" - keyinterfaces "github.com/zeta-chain/zetacore/zetaclient/keys/interfaces" - "go.nhat.io/grpcmock" - "go.nhat.io/grpcmock/planner" - - "github.com/zeta-chain/zetacore/cmd/zetacored/config" - "github.com/zeta-chain/zetacore/pkg/chains" - "github.com/zeta-chain/zetacore/pkg/coin" - "github.com/zeta-chain/zetacore/testutil/sample" - crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" - lightclienttypes "github.com/zeta-chain/zetacore/x/lightclient/types" - observertypes "github.com/zeta-chain/zetacore/x/observer/types" - "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" - "github.com/zeta-chain/zetacore/zetaclient/keys" - "github.com/zeta-chain/zetacore/zetaclient/testutils/mocks" -) - -const skipMethod = "skip" - -// setupMockServer setup mock zetacore GRPC server -func setupMockServer( - t *testing.T, - serviceFunc any, method string, input any, expectedOutput any, - extra ...grpcmock.ServerOption, -) *grpcmock.Server { - listener, err := net.Listen("tcp", "127.0.0.1:9090") - require.NoError(t, err) - - opts := []grpcmock.ServerOption{ - grpcmock.RegisterService(serviceFunc), - grpcmock.WithPlanner(planner.FirstMatch()), - grpcmock.WithListener(listener), - } - - opts = append(opts, extra...) - - if method != skipMethod { - opts = append(opts, func(s *grpcmock.Server) { - s.ExpectUnary(method). - UnlimitedTimes(). - WithPayload(input). - Return(expectedOutput) - }) - } - - server := grpcmock.MockUnstartedServer(opts...)(t) - - server.Serve() - - t.Cleanup(func() { - require.NoError(t, server.Close()) - }) - - return server -} - -func withDummyServer(zetaBlockHeight int64) []grpcmock.ServerOption { - return []grpcmock.ServerOption{ - grpcmock.RegisterService(crosschaintypes.RegisterQueryServer), - grpcmock.RegisterService(crosschaintypes.RegisterMsgServer), - grpcmock.RegisterService(feemarkettypes.RegisterQueryServer), - grpcmock.RegisterService(authtypes.RegisterQueryServer), - grpcmock.RegisterService(abci.RegisterABCIApplicationServer), - func(s *grpcmock.Server) { - // Block Height - s.ExpectUnary("/zetachain.zetacore.crosschain.Query/LastZetaHeight"). - UnlimitedTimes(). - Return(crosschaintypes.QueryLastZetaHeightResponse{Height: zetaBlockHeight}) - - // London Base Fee - s.ExpectUnary("/ethermint.feemarket.v1.Query/Params"). - UnlimitedTimes(). - Return(feemarkettypes.QueryParamsResponse{ - Params: feemarkettypes.Params{BaseFee: types.NewInt(100)}, - }) - }, - } -} - -type clientTestConfig struct { - keys keyinterfaces.ObserverKeys - opts []Opt -} - -type clientTestOpt func(*clientTestConfig) - -func withObserverKeys(keys keyinterfaces.ObserverKeys) clientTestOpt { - return func(cfg *clientTestConfig) { cfg.keys = keys } -} - -func withDefaultObserverKeys() clientTestOpt { - var ( - key = mocks.TestKeyringPair - address = types.AccAddress(key.PubKey().Address().Bytes()) - keyRing = mocks.NewKeyring() - ) - - return withObserverKeys(keys.NewKeysWithKeybase(keyRing, address, testSigner, "")) -} - -func withTendermint(client cosmosclient.TendermintRPC) clientTestOpt { - return func(cfg *clientTestConfig) { cfg.opts = append(cfg.opts, WithTendermintClient(client)) } -} - -func withAccountRetriever(t *testing.T, accNum uint64, accSeq uint64) clientTestOpt { - ctrl := gomock.NewController(t) - ac := mock.NewMockAccountRetriever(ctrl) - ac.EXPECT(). - GetAccountNumberSequence(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(accNum, accSeq, nil) - - return func(cfg *clientTestConfig) { - cfg.opts = append(cfg.opts, WithCustomAccountRetriever(ac)) - } -} - -func setupZetacoreClient(t *testing.T, opts ...clientTestOpt) *Client { - const ( - chainIP = "127.0.0.1" - signer = testSigner - chainID = "zetachain_7000-1" - ) - - var cfg clientTestConfig - for _, opt := range opts { - opt(&cfg) - } - - if cfg.keys == nil { - cfg.keys = &keys.Keys{} - } - - c, err := NewClient( - cfg.keys, - chainIP, signer, - chainID, - false, - zerolog.Nop(), - cfg.opts..., - ) - - require.NoError(t, err) - - return c -} - -func TestZetacore_GetBallot(t *testing.T) { - ctx := context.Background() - - expectedOutput := observertypes.QueryBallotByIdentifierResponse{ - BallotIdentifier: "123", - Voters: nil, - ObservationType: 0, - BallotStatus: 0, - } - input := observertypes.QueryBallotByIdentifierRequest{BallotIdentifier: "123"} - method := "/zetachain.zetacore.observer.Query/BallotByIdentifier" - setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetBallotByID(ctx, "123") - require.NoError(t, err) - require.Equal(t, expectedOutput, *resp) -} - -func TestZetacore_GetCrosschainFlags(t *testing.T) { - ctx := context.Background() - - expectedOutput := observertypes.QueryGetCrosschainFlagsResponse{CrosschainFlags: observertypes.CrosschainFlags{ - IsInboundEnabled: true, - IsOutboundEnabled: false, - GasPriceIncreaseFlags: nil, - }} - input := observertypes.QueryGetCrosschainFlagsRequest{} - method := "/zetachain.zetacore.observer.Query/CrosschainFlags" - setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetCrosschainFlags(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput.CrosschainFlags, resp) -} - -func TestZetacore_GetRateLimiterFlags(t *testing.T) { - ctx := context.Background() - - // create sample flags - rateLimiterFlags := sample.RateLimiterFlags() - expectedOutput := crosschaintypes.QueryRateLimiterFlagsResponse{ - RateLimiterFlags: rateLimiterFlags, - } - - // setup mock server - input := crosschaintypes.QueryRateLimiterFlagsRequest{} - method := "/zetachain.zetacore.crosschain.Query/RateLimiterFlags" - setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - // query - resp, err := client.GetRateLimiterFlags(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput.RateLimiterFlags, resp) -} - -func TestZetacore_HeaderEnabledChains(t *testing.T) { - ctx := context.Background() - - expectedOutput := lightclienttypes.QueryHeaderEnabledChainsResponse{ - HeaderEnabledChains: []lightclienttypes.HeaderSupportedChain{ - { - ChainId: chains.Ethereum.ChainId, - Enabled: true, - }, - { - ChainId: chains.BitcoinMainnet.ChainId, - Enabled: true, - }, - }, - } - input := lightclienttypes.QueryHeaderEnabledChainsRequest{} - method := "/zetachain.zetacore.lightclient.Query/HeaderEnabledChains" - setupMockServer(t, lightclienttypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetBlockHeaderEnabledChains(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput.HeaderEnabledChains, resp) -} - -func TestZetacore_GetChainParamsForChainID(t *testing.T) { - ctx := context.Background() - - expectedOutput := observertypes.QueryGetChainParamsForChainResponse{ChainParams: &observertypes.ChainParams{ - ChainId: 123, - BallotThreshold: types.ZeroDec(), - MinObserverDelegation: types.ZeroDec(), - }} - input := observertypes.QueryGetChainParamsForChainRequest{ChainId: 123} - method := "/zetachain.zetacore.observer.Query/GetChainParamsForChain" - setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetChainParamsForChainID(ctx, 123) - require.NoError(t, err) - require.Equal(t, expectedOutput.ChainParams, resp) -} - -func TestZetacore_GetChainParams(t *testing.T) { - ctx := context.Background() - - expectedOutput := observertypes.QueryGetChainParamsResponse{ChainParams: &observertypes.ChainParamsList{ - ChainParams: []*observertypes.ChainParams{ - { - ChainId: 123, - MinObserverDelegation: types.ZeroDec(), - BallotThreshold: types.ZeroDec(), - }, - }, - }} - input := observertypes.QueryGetChainParamsRequest{} - method := "/zetachain.zetacore.observer.Query/GetChainParams" - setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetChainParams(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput.ChainParams.ChainParams, resp) -} - -func TestZetacore_GetUpgradePlan(t *testing.T) { - ctx := context.Background() - - expectedOutput := upgradetypes.QueryCurrentPlanResponse{ - Plan: &upgradetypes.Plan{ - Name: "big upgrade", - Height: 100, - }, - } - input := upgradetypes.QueryCurrentPlanRequest{} - method := "/cosmos.upgrade.v1beta1.Query/CurrentPlan" - setupMockServer(t, upgradetypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetUpgradePlan(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput.Plan, resp) -} - -func TestZetacore_GetAllCctx(t *testing.T) { - ctx := context.Background() - - expectedOutput := crosschaintypes.QueryAllCctxResponse{ - CrossChainTx: []*crosschaintypes.CrossChainTx{ - { - Index: "cross-chain4456", - }, - }, - Pagination: nil, - } - input := crosschaintypes.QueryAllCctxRequest{} - method := "/zetachain.zetacore.crosschain.Query/CctxAll" - setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetAllCctx(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput.CrossChainTx, resp) -} - -func TestZetacore_GetCctxByHash(t *testing.T) { - ctx := context.Background() - - expectedOutput := crosschaintypes.QueryGetCctxResponse{CrossChainTx: &crosschaintypes.CrossChainTx{ - Index: "9c8d02b6956b9c78ecb6090a8160faaa48e7aecfd0026fcdf533721d861436a3", - }} - input := crosschaintypes.QueryGetCctxRequest{ - Index: "9c8d02b6956b9c78ecb6090a8160faaa48e7aecfd0026fcdf533721d861436a3", - } - method := "/zetachain.zetacore.crosschain.Query/Cctx" - setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetCctxByHash(ctx, "9c8d02b6956b9c78ecb6090a8160faaa48e7aecfd0026fcdf533721d861436a3") - require.NoError(t, err) - require.Equal(t, expectedOutput.CrossChainTx, resp) -} - -func TestZetacore_GetCctxByNonce(t *testing.T) { - ctx := context.Background() - - expectedOutput := crosschaintypes.QueryGetCctxResponse{CrossChainTx: &crosschaintypes.CrossChainTx{ - Index: "9c8d02b6956b9c78ecb6090a8160faaa48e7aecfd0026fcdf533721d861436a3", - }} - input := crosschaintypes.QueryGetCctxByNonceRequest{ - ChainID: 7000, - Nonce: 55, - } - method := "/zetachain.zetacore.crosschain.Query/CctxByNonce" - setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetCctxByNonce(ctx, 7000, 55) - require.NoError(t, err) - require.Equal(t, expectedOutput.CrossChainTx, resp) -} - -func TestZetacore_GetObserverList(t *testing.T) { - ctx := context.Background() - - expectedOutput := observertypes.QueryObserverSetResponse{ - Observers: []string{ - "zeta19jr7nl82lrktge35f52x9g5y5prmvchmk40zhg", - "zeta1cxj07f3ju484ry2cnnhxl5tryyex7gev0yzxtj", - "zeta1hjct6q7npsspsg3dgvzk3sdf89spmlpf7rqmnw", - }, - } - input := observertypes.QueryObserverSet{} - method := "/zetachain.zetacore.observer.Query/ObserverSet" - setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetObserverList(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput.Observers, resp) -} - -func TestZetacore_GetRateLimiterInput(t *testing.T) { - ctx := context.Background() - - expectedOutput := &crosschaintypes.QueryRateLimiterInputResponse{ - Height: 10, - CctxsMissed: []*crosschaintypes.CrossChainTx{sample.CrossChainTx(t, "1-1")}, - CctxsPending: []*crosschaintypes.CrossChainTx{sample.CrossChainTx(t, "1-2")}, - TotalPending: 1, - PastCctxsValue: "123456", - PendingCctxsValue: "1234", - LowestPendingCctxHeight: 2, - } - input := crosschaintypes.QueryRateLimiterInputRequest{Window: 10} - method := "/zetachain.zetacore.crosschain.Query/RateLimiterInput" - setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetRateLimiterInput(ctx, 10) - require.NoError(t, err) - require.Equal(t, expectedOutput, resp) -} - -func TestZetacore_ListPendingCctx(t *testing.T) { - ctx := context.Background() - - expectedOutput := crosschaintypes.QueryListPendingCctxResponse{ - CrossChainTx: []*crosschaintypes.CrossChainTx{ - { - Index: "cross-chain4456", - }, - }, - TotalPending: 1, - } - input := crosschaintypes.QueryListPendingCctxRequest{ChainId: 7000} - method := "/zetachain.zetacore.crosschain.Query/ListPendingCctx" - setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, totalPending, err := client.ListPendingCCTX(ctx, 7000) - require.NoError(t, err) - require.Equal(t, expectedOutput.CrossChainTx, resp) - require.Equal(t, expectedOutput.TotalPending, totalPending) -} - -func TestZetacore_GetAbortedZetaAmount(t *testing.T) { - ctx := context.Background() - - expectedOutput := crosschaintypes.QueryZetaAccountingResponse{AbortedZetaAmount: "1080999"} - input := crosschaintypes.QueryZetaAccountingRequest{} - method := "/zetachain.zetacore.crosschain.Query/ZetaAccounting" - setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetAbortedZetaAmount(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput.AbortedZetaAmount, resp) -} - -// Need to test after refactor -func TestZetacore_GetGenesisSupply(t *testing.T) { -} - -func TestZetacore_GetZetaTokenSupplyOnNode(t *testing.T) { - ctx := context.Background() - - expectedOutput := banktypes.QuerySupplyOfResponse{ - Amount: types.Coin{ - Denom: config.BaseDenom, - Amount: types.NewInt(329438), - }} - input := banktypes.QuerySupplyOfRequest{Denom: config.BaseDenom} - method := "/cosmos.bank.v1beta1.Query/SupplyOf" - setupMockServer(t, banktypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetZetaTokenSupplyOnNode(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput.GetAmount().Amount, resp) -} - -func TestZetacore_GetBlockHeight(t *testing.T) { - ctx := context.Background() - - method := "/zetachain.zetacore.crosschain.Query/LastZetaHeight" - input := &crosschaintypes.QueryLastZetaHeightRequest{} - output := &crosschaintypes.QueryLastZetaHeightResponse{Height: 12345} - - setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, output) - - client := setupZetacoreClient(t, - withDefaultObserverKeys(), - ) - - t.Run("last block height", func(t *testing.T) { - height, err := client.GetBlockHeight(ctx) - require.NoError(t, err) - require.Equal(t, int64(12345), height) - }) -} - -func TestZetacore_GetLatestZetaBlock(t *testing.T) { - ctx := context.Background() - - expectedOutput := tmservice.GetLatestBlockResponse{ - SdkBlock: &tmservice.Block{ - Header: tmservice.Header{}, - Data: tmtypes.Data{}, - Evidence: tmtypes.EvidenceList{}, - LastCommit: nil, - }, - } - input := tmservice.GetLatestBlockRequest{} - method := "/cosmos.base.tendermint.v1beta1.Service/GetLatestBlock" - setupMockServer(t, tmservice.RegisterServiceServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetLatestZetaBlock(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput.SdkBlock, resp) -} - -func TestZetacore_GetNodeInfo(t *testing.T) { - ctx := context.Background() - - expectedOutput := tmservice.GetNodeInfoResponse{ - DefaultNodeInfo: nil, - ApplicationVersion: &tmservice.VersionInfo{}, - } - input := tmservice.GetNodeInfoRequest{} - method := "/cosmos.base.tendermint.v1beta1.Service/GetNodeInfo" - setupMockServer(t, tmservice.RegisterServiceServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetNodeInfo(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput, *resp) -} - -func TestZetacore_GetBaseGasPrice(t *testing.T) { - ctx := context.Background() - - expectedOutput := feemarkettypes.QueryParamsResponse{ - Params: feemarkettypes.Params{ - BaseFee: types.NewInt(23455), - }, - } - input := feemarkettypes.QueryParamsRequest{} - method := "/ethermint.feemarket.v1.Query/Params" - setupMockServer(t, feemarkettypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetBaseGasPrice(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput.Params.BaseFee.Int64(), resp) -} - -func TestZetacore_GetNonceByChain(t *testing.T) { - ctx := context.Background() - - chain := chains.BscMainnet - expectedOutput := observertypes.QueryGetChainNoncesResponse{ - ChainNonces: observertypes.ChainNonces{ - Creator: "", - ChainId: chain.ChainId, - Nonce: 8446, - Signers: nil, - FinalizedHeight: 0, - }, - } - input := observertypes.QueryGetChainNoncesRequest{ChainId: chain.ChainId} - method := "/zetachain.zetacore.observer.Query/ChainNonces" - setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetNonceByChain(ctx, chain) - require.NoError(t, err) - require.Equal(t, expectedOutput.ChainNonces, resp) -} - -func TestZetacore_GetAllNodeAccounts(t *testing.T) { - ctx := context.Background() - - expectedOutput := observertypes.QueryAllNodeAccountResponse{ - NodeAccount: []*observertypes.NodeAccount{ - { - Operator: "zeta19jr7nl82lrktge35f52x9g5y5prmvchmk40zhg", - GranteeAddress: "zeta1kxhesgcvl6j5upupd9m3d3g3gfz4l3pcpqfnw6", - GranteePubkey: nil, - NodeStatus: 0, - }, - }, - } - input := observertypes.QueryAllNodeAccountRequest{} - method := "/zetachain.zetacore.observer.Query/NodeAccountAll" - setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetAllNodeAccounts(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput.NodeAccount, resp) -} - -func TestZetacore_GetKeyGen(t *testing.T) { - ctx := context.Background() - - expectedOutput := observertypes.QueryGetKeygenResponse{ - Keygen: &observertypes.Keygen{ - Status: observertypes.KeygenStatus_KeyGenSuccess, - GranteePubkeys: nil, - BlockNumber: 5646, - }} - input := observertypes.QueryGetKeygenRequest{} - method := "/zetachain.zetacore.observer.Query/Keygen" - setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetKeyGen(ctx) - require.NoError(t, err) - require.Equal(t, *expectedOutput.Keygen, resp) -} - -func TestZetacore_GetBallotByID(t *testing.T) { - ctx := context.Background() - - expectedOutput := observertypes.QueryBallotByIdentifierResponse{ - BallotIdentifier: "ballot1235", - } - input := observertypes.QueryBallotByIdentifierRequest{BallotIdentifier: "ballot1235"} - method := "/zetachain.zetacore.observer.Query/BallotByIdentifier" - setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetBallot(ctx, "ballot1235") - require.NoError(t, err) - require.Equal(t, expectedOutput, *resp) -} - -func TestZetacore_GetInboundTrackersForChain(t *testing.T) { - ctx := context.Background() - - chainID := chains.BscMainnet.ChainId - expectedOutput := crosschaintypes.QueryAllInboundTrackerByChainResponse{ - InboundTracker: []crosschaintypes.InboundTracker{ - { - ChainId: chainID, - TxHash: "DC76A6DCCC3AA62E89E69042ADC44557C50D59E4D3210C37D78DC8AE49B3B27F", - CoinType: coin.CoinType_Gas, - }, - }, - } - input := crosschaintypes.QueryAllInboundTrackerByChainRequest{ChainId: chainID} - method := "/zetachain.zetacore.crosschain.Query/InboundTrackerAllByChain" - setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetInboundTrackersForChain(ctx, chainID) - require.NoError(t, err) - require.Equal(t, expectedOutput.InboundTracker, resp) -} - -func TestZetacore_GetTss(t *testing.T) { - ctx := context.Background() - - expectedOutput := observertypes.QueryGetTSSResponse{ - TSS: observertypes.TSS{ - TssPubkey: "zetapub1addwnpepqtadxdyt037h86z60nl98t6zk56mw5zpnm79tsmvspln3hgt5phdc79kvfc", - TssParticipantList: nil, - OperatorAddressList: nil, - FinalizedZetaHeight: 1000, - KeyGenZetaHeight: 900, - }, - } - input := observertypes.QueryGetTSSRequest{} - method := "/zetachain.zetacore.observer.Query/TSS" - setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetTSS(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput.TSS, resp) -} - -func TestZetacore_GetEthTssAddress(t *testing.T) { - ctx := context.Background() - - expectedOutput := observertypes.QueryGetTssAddressResponse{ - Eth: "0x70e967acfcc17c3941e87562161406d41676fd83", - Btc: "bc1qm24wp577nk8aacckv8np465z3dvmu7ry45el6y", - } - input := observertypes.QueryGetTssAddressRequest{} - method := "/zetachain.zetacore.observer.Query/GetTssAddress" - setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetEVMTSSAddress(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput.Eth, resp) -} - -func TestZetacore_GetBtcTssAddress(t *testing.T) { - ctx := context.Background() - - expectedOutput := observertypes.QueryGetTssAddressResponse{ - Eth: "0x70e967acfcc17c3941e87562161406d41676fd83", - Btc: "bc1qm24wp577nk8aacckv8np465z3dvmu7ry45el6y", - } - input := observertypes.QueryGetTssAddressRequest{BitcoinChainId: 8332} - method := "/zetachain.zetacore.observer.Query/GetTssAddress" - setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetBTCTSSAddress(ctx, 8332) - require.NoError(t, err) - require.Equal(t, expectedOutput.Btc, resp) -} - -func TestZetacore_GetTssHistory(t *testing.T) { - ctx := context.Background() - - expectedOutput := observertypes.QueryTssHistoryResponse{ - TssList: []observertypes.TSS{ - { - TssPubkey: "zetapub1addwnpepqtadxdyt037h86z60nl98t6zk56mw5zpnm79tsmvspln3hgt5phdc79kvfc", - TssParticipantList: nil, - OperatorAddressList: nil, - FinalizedZetaHeight: 46546, - KeyGenZetaHeight: 6897, - }, - }, - } - input := observertypes.QueryTssHistoryRequest{} - method := "/zetachain.zetacore.observer.Query/TssHistory" - setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetTSSHistory(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput.TssList, resp) -} - -func TestZetacore_GetOutboundTracker(t *testing.T) { - chain := chains.BscMainnet - expectedOutput := crosschaintypes.QueryGetOutboundTrackerResponse{ - OutboundTracker: crosschaintypes.OutboundTracker{ - Index: "tracker12345", - ChainId: chain.ChainId, - Nonce: 456, - HashList: nil, - }, - } - input := crosschaintypes.QueryGetOutboundTrackerRequest{ - ChainID: chain.ChainId, - Nonce: 456, - } - method := "/zetachain.zetacore.crosschain.Query/OutboundTracker" - setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - ctx := context.Background() - resp, err := client.GetOutboundTracker(ctx, chain, 456) - require.NoError(t, err) - require.Equal(t, expectedOutput.OutboundTracker, *resp) -} - -func TestZetacore_GetAllOutboundTrackerByChain(t *testing.T) { - ctx := context.Background() - - chain := chains.BscMainnet - expectedOutput := crosschaintypes.QueryAllOutboundTrackerByChainResponse{ - OutboundTracker: []crosschaintypes.OutboundTracker{ - { - Index: "tracker23456", - ChainId: chain.ChainId, - Nonce: 123456, - HashList: nil, - }, - }, - } - input := crosschaintypes.QueryAllOutboundTrackerByChainRequest{ - Chain: chain.ChainId, - Pagination: &query.PageRequest{ - Key: nil, - Offset: 0, - Limit: 2000, - CountTotal: false, - Reverse: false, - }, - } - method := "/zetachain.zetacore.crosschain.Query/OutboundTrackerAllByChain" - setupMockServer(t, crosschaintypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetAllOutboundTrackerByChain(ctx, chain.ChainId, interfaces.Ascending) - require.NoError(t, err) - require.Equal(t, expectedOutput.OutboundTracker, resp) - - resp, err = client.GetAllOutboundTrackerByChain(ctx, chain.ChainId, interfaces.Descending) - require.NoError(t, err) - require.Equal(t, expectedOutput.OutboundTracker, resp) -} - -func TestZetacore_GetPendingNoncesByChain(t *testing.T) { - ctx := context.Background() - - expectedOutput := observertypes.QueryPendingNoncesByChainResponse{ - PendingNonces: observertypes.PendingNonces{ - NonceLow: 0, - NonceHigh: 0, - ChainId: chains.Ethereum.ChainId, - Tss: "", - }, - } - input := observertypes.QueryPendingNoncesByChainRequest{ChainId: chains.Ethereum.ChainId} - method := "/zetachain.zetacore.observer.Query/PendingNoncesByChain" - setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetPendingNoncesByChain(ctx, chains.Ethereum.ChainId) - require.NoError(t, err) - require.Equal(t, expectedOutput.PendingNonces, resp) -} - -func TestZetacore_GetBlockHeaderChainState(t *testing.T) { - ctx := context.Background() - - chainID := chains.BscMainnet.ChainId - expectedOutput := lightclienttypes.QueryGetChainStateResponse{ChainState: &lightclienttypes.ChainState{ - ChainId: chainID, - LatestHeight: 5566654, - EarliestHeight: 4454445, - LatestBlockHash: nil, - }} - input := lightclienttypes.QueryGetChainStateRequest{ChainId: chainID} - method := "/zetachain.zetacore.lightclient.Query/ChainState" - setupMockServer(t, lightclienttypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetBlockHeaderChainState(ctx, chainID) - require.NoError(t, err) - require.Equal(t, expectedOutput.ChainState, resp) -} - -func TestZetacore_GetSupportedChains(t *testing.T) { - ctx := context.Background() - - expectedOutput := observertypes.QuerySupportedChainsResponse{ - Chains: []chains.Chain{ - { - ChainId: chains.BitcoinMainnet.ChainId, - Network: chains.BscMainnet.Network, - NetworkType: chains.BscMainnet.NetworkType, - Vm: chains.BscMainnet.Vm, - Consensus: chains.BscMainnet.Consensus, - IsExternal: chains.BscMainnet.IsExternal, - Name: chains.BscMainnet.Name, - }, - { - ChainId: chains.Ethereum.ChainId, - Network: chains.Ethereum.Network, - NetworkType: chains.Ethereum.NetworkType, - Vm: chains.Ethereum.Vm, - Consensus: chains.Ethereum.Consensus, - IsExternal: chains.Ethereum.IsExternal, - Name: chains.Ethereum.Name, - }, - }, - } - input := observertypes.QuerySupportedChains{} - method := "/zetachain.zetacore.observer.Query/SupportedChains" - setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetSupportedChains(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput.Chains, resp) -} - -func TestZetacore_GetAdditionalChains(t *testing.T) { - ctx := context.Background() - - expectedOutput := authoritytypes.QueryGetChainInfoResponse{ - ChainInfo: authoritytypes.ChainInfo{ - Chains: []chains.Chain{ - chains.BitcoinMainnet, - chains.Ethereum, - }, - }, - } - input := observertypes.QuerySupportedChains{} - method := "/zetachain.zetacore.authority.Query/ChainInfo" - - setupMockServer(t, authoritytypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, - withDefaultObserverKeys(), - withAccountRetriever(t, 100, 100), - withTendermint(mocks.NewSDKClientWithErr(t, nil, 0).SetBroadcastTxHash(sampleHash)), - ) - - resp, err := client.GetAdditionalChains(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput.ChainInfo.Chains, resp) -} - -func TestZetacore_GetPendingNonces(t *testing.T) { - ctx := context.Background() - - expectedOutput := observertypes.QueryAllPendingNoncesResponse{ - PendingNonces: []observertypes.PendingNonces{ - { - NonceLow: 225, - NonceHigh: 226, - ChainId: 8332, - Tss: "bc1qm24wp577nk8aacckv8np465z3dvmu7ry45el6y", - }, - }, - } - input := observertypes.QueryAllPendingNoncesRequest{} - method := "/zetachain.zetacore.observer.Query/PendingNoncesAll" - setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.GetPendingNonces(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput, *resp) -} - -func TestZetacore_Prove(t *testing.T) { - ctx := context.Background() - - chainId := chains.BscMainnet.ChainId - txHash := "9c8d02b6956b9c78ecb6090a8160faaa48e7aecfd0026fcdf533721d861436a3" - blockHash := "0000000000000000000172c9a64f86f208b867a84dc7a0b7c75be51e750ed8eb" - txIndex := 555 - expectedOutput := lightclienttypes.QueryProveResponse{ - Valid: true, - } - input := lightclienttypes.QueryProveRequest{ - ChainId: chainId, - TxHash: txHash, - Proof: nil, - BlockHash: blockHash, - TxIndex: int64(txIndex), - } - method := "/zetachain.zetacore.lightclient.Query/Prove" - setupMockServer(t, lightclienttypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.Prove(ctx, blockHash, txHash, int64(txIndex), nil, chainId) - require.NoError(t, err) - require.Equal(t, expectedOutput.Valid, resp) -} - -func TestZetacore_HasVoted(t *testing.T) { - ctx := context.Background() - - expectedOutput := observertypes.QueryHasVotedResponse{HasVoted: true} - input := observertypes.QueryHasVotedRequest{ - BallotIdentifier: "123456asdf", - VoterAddress: "zeta1l40mm7meacx03r4lp87s9gkxfan32xnznp42u6", - } - method := "/zetachain.zetacore.observer.Query/HasVoted" - setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - resp, err := client.HasVoted(ctx, "123456asdf", "zeta1l40mm7meacx03r4lp87s9gkxfan32xnznp42u6") - require.NoError(t, err) - require.Equal(t, expectedOutput.HasVoted, resp) -} - -func TestZetacore_GetZetaHotKeyBalance(t *testing.T) { - ctx := context.Background() - - expectedOutput := banktypes.QueryBalanceResponse{ - Balance: &types.Coin{ - Denom: config.BaseDenom, - Amount: types.NewInt(55646484), - }, - } - input := banktypes.QueryBalanceRequest{ - Address: types.AccAddress(mocks.TestKeyringPair.PubKey().Address().Bytes()).String(), - Denom: config.BaseDenom, - } - method := "/cosmos.bank.v1beta1.Query/Balance" - setupMockServer(t, banktypes.RegisterQueryServer, method, input, expectedOutput) - - client := setupZetacoreClient(t, withDefaultObserverKeys()) - - // should be able to get balance of signer - client.keys = keys.NewKeysWithKeybase(mocks.NewKeyring(), types.AccAddress{}, "bob", "") - resp, err := client.GetZetaHotKeyBalance(ctx) - require.NoError(t, err) - require.Equal(t, expectedOutput.Balance.Amount, resp) - - // should return error on empty signer - client.keys = keys.NewKeysWithKeybase(mocks.NewKeyring(), types.AccAddress{}, "", "") - resp, err = client.GetZetaHotKeyBalance(ctx) - require.Error(t, err) - require.Equal(t, types.ZeroInt(), resp) -} diff --git a/zetaclient/zetacore/client_test.go b/zetaclient/zetacore/client_test.go new file mode 100644 index 0000000000..723f29084d --- /dev/null +++ b/zetaclient/zetacore/client_test.go @@ -0,0 +1,191 @@ +package zetacore + +import ( + "context" + "net" + "testing" + + abci "github.com/cometbft/cometbft/abci/types" + cosmosclient "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/testutil/mock" + "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/golang/mock/gomock" + "github.com/rs/zerolog" + "github.com/stretchr/testify/require" + feemarkettypes "github.com/zeta-chain/ethermint/x/feemarket/types" + keyinterfaces "github.com/zeta-chain/zetacore/zetaclient/keys/interfaces" + "go.nhat.io/grpcmock" + "go.nhat.io/grpcmock/planner" + + "github.com/zeta-chain/zetacore/cmd/zetacored/config" + crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" + "github.com/zeta-chain/zetacore/zetaclient/keys" + "github.com/zeta-chain/zetacore/zetaclient/testutils/mocks" +) + +const skipMethod = "skip" + +// setupMockServer setup mock zetacore GRPC server +func setupMockServer( + t *testing.T, + serviceFunc any, method string, input any, expectedOutput any, + extra ...grpcmock.ServerOption, +) *grpcmock.Server { + listener, err := net.Listen("tcp", "127.0.0.1:9090") + require.NoError(t, err) + + opts := []grpcmock.ServerOption{ + grpcmock.RegisterService(serviceFunc), + grpcmock.WithPlanner(planner.FirstMatch()), + grpcmock.WithListener(listener), + } + + opts = append(opts, extra...) + + if method != skipMethod { + opts = append(opts, func(s *grpcmock.Server) { + s.ExpectUnary(method). + UnlimitedTimes(). + WithPayload(input). + Return(expectedOutput) + }) + } + + server := grpcmock.MockUnstartedServer(opts...)(t) + + server.Serve() + + t.Cleanup(func() { + require.NoError(t, server.Close()) + }) + + return server +} + +func withDummyServer(zetaBlockHeight int64) []grpcmock.ServerOption { + return []grpcmock.ServerOption{ + grpcmock.RegisterService(crosschaintypes.RegisterQueryServer), + grpcmock.RegisterService(crosschaintypes.RegisterMsgServer), + grpcmock.RegisterService(feemarkettypes.RegisterQueryServer), + grpcmock.RegisterService(authtypes.RegisterQueryServer), + grpcmock.RegisterService(abci.RegisterABCIApplicationServer), + func(s *grpcmock.Server) { + // Block Height + s.ExpectUnary("/zetachain.zetacore.crosschain.Query/LastZetaHeight"). + UnlimitedTimes(). + Return(crosschaintypes.QueryLastZetaHeightResponse{Height: zetaBlockHeight}) + + // London Base Fee + s.ExpectUnary("/ethermint.feemarket.v1.Query/Params"). + UnlimitedTimes(). + Return(feemarkettypes.QueryParamsResponse{ + Params: feemarkettypes.Params{BaseFee: types.NewInt(100)}, + }) + }, + } +} + +type clientTestConfig struct { + keys keyinterfaces.ObserverKeys + opts []Opt +} + +type clientTestOpt func(*clientTestConfig) + +func withObserverKeys(keys keyinterfaces.ObserverKeys) clientTestOpt { + return func(cfg *clientTestConfig) { cfg.keys = keys } +} + +func withDefaultObserverKeys() clientTestOpt { + var ( + key = mocks.TestKeyringPair + address = types.AccAddress(key.PubKey().Address().Bytes()) + keyRing = mocks.NewKeyring() + ) + + return withObserverKeys(keys.NewKeysWithKeybase(keyRing, address, testSigner, "")) +} + +func withTendermint(client cosmosclient.TendermintRPC) clientTestOpt { + return func(cfg *clientTestConfig) { cfg.opts = append(cfg.opts, WithTendermintClient(client)) } +} + +func withAccountRetriever(t *testing.T, accNum uint64, accSeq uint64) clientTestOpt { + ctrl := gomock.NewController(t) + ac := mock.NewMockAccountRetriever(ctrl) + ac.EXPECT(). + GetAccountNumberSequence(gomock.Any(), gomock.Any()). + AnyTimes(). + Return(accNum, accSeq, nil) + + return func(cfg *clientTestConfig) { + cfg.opts = append(cfg.opts, WithCustomAccountRetriever(ac)) + } +} + +func setupZetacoreClient(t *testing.T, opts ...clientTestOpt) *Client { + const ( + chainIP = "127.0.0.1" + signer = testSigner + chainID = "zetachain_7000-1" + ) + + var cfg clientTestConfig + for _, opt := range opts { + opt(&cfg) + } + + if cfg.keys == nil { + cfg.keys = &keys.Keys{} + } + + c, err := NewClient( + cfg.keys, + chainIP, signer, + chainID, + false, + zerolog.Nop(), + cfg.opts..., + ) + + require.NoError(t, err) + + return c +} + +// Need to test after refactor +func TestZetacore_GetGenesisSupply(t *testing.T) { +} + +func TestZetacore_GetZetaHotKeyBalance(t *testing.T) { + ctx := context.Background() + + expectedOutput := banktypes.QueryBalanceResponse{ + Balance: &types.Coin{ + Denom: config.BaseDenom, + Amount: types.NewInt(55646484), + }, + } + input := banktypes.QueryBalanceRequest{ + Address: types.AccAddress(mocks.TestKeyringPair.PubKey().Address().Bytes()).String(), + Denom: config.BaseDenom, + } + method := "/cosmos.bank.v1beta1.Query/Balance" + setupMockServer(t, banktypes.RegisterQueryServer, method, input, expectedOutput) + + client := setupZetacoreClient(t, withDefaultObserverKeys()) + + // should be able to get balance of signer + client.keys = keys.NewKeysWithKeybase(mocks.NewKeyring(), types.AccAddress{}, "bob", "") + resp, err := client.GetZetaHotKeyBalance(ctx) + require.NoError(t, err) + require.Equal(t, expectedOutput.Balance.Amount, resp) + + // should return error on empty signer + client.keys = keys.NewKeysWithKeybase(mocks.NewKeyring(), types.AccAddress{}, "", "") + resp, err = client.GetZetaHotKeyBalance(ctx) + require.Error(t, err) + require.Equal(t, types.ZeroInt(), resp) +} From aaadc78a4a01873d1cb0e2a446ca16d788e150fc Mon Sep 17 00:00:00 2001 From: Alex Gartner Date: Thu, 29 Aug 2024 12:25:16 -0700 Subject: [PATCH 6/8] fmt --- cmd/zetae2e/config/clients.go | 7 +++++-- e2e/runner/clients.go | 1 + pkg/rpc/clients.go | 4 +++- pkg/rpc/clients_test.go | 25 ------------------------- 4 files changed, 9 insertions(+), 28 deletions(-) diff --git a/cmd/zetae2e/config/clients.go b/cmd/zetae2e/config/clients.go index dc4751e6b1..a2b1909111 100644 --- a/cmd/zetae2e/config/clients.go +++ b/cmd/zetae2e/config/clients.go @@ -8,12 +8,12 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/ethclient" "github.com/gagliardetto/solana-go/rpc" - zetacore_rpc "github.com/zeta-chain/zetacore/pkg/rpc" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "github.com/zeta-chain/zetacore/e2e/config" "github.com/zeta-chain/zetacore/e2e/runner" + zetacore_rpc "github.com/zeta-chain/zetacore/pkg/rpc" ) // getClientsFromConfig get clients from config @@ -108,7 +108,10 @@ func getEVMClient( func GetZetacoreClient(ctx context.Context, conf config.Config) (zetacore_rpc.Clients, error) { if conf.RPCs.ZetaCoreGRPC != "" { - return zetacore_rpc.NewGRPCClients(conf.RPCs.ZetaCoreGRPC, grpc.WithTransportCredentials(insecure.NewCredentials())) + return zetacore_rpc.NewGRPCClients( + conf.RPCs.ZetaCoreGRPC, + grpc.WithTransportCredentials(insecure.NewCredentials()), + ) } if conf.RPCs.ZetaCoreRPC != "" { return zetacore_rpc.NewCometBFTClients(conf.RPCs.ZetaCoreRPC) diff --git a/e2e/runner/clients.go b/e2e/runner/clients.go index 6e08a8aae2..9573a53e29 100644 --- a/e2e/runner/clients.go +++ b/e2e/runner/clients.go @@ -5,6 +5,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/ethclient" "github.com/gagliardetto/solana-go/rpc" + zetacore_rpc "github.com/zeta-chain/zetacore/pkg/rpc" ) diff --git a/pkg/rpc/clients.go b/pkg/rpc/clients.go index 2e36e84021..2fef17cf26 100644 --- a/pkg/rpc/clients.go +++ b/pkg/rpc/clients.go @@ -9,9 +9,9 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + feemarkettypes "github.com/zeta-chain/ethermint/x/feemarket/types" "google.golang.org/grpc" - feemarkettypes "github.com/zeta-chain/ethermint/x/feemarket/types" etherminttypes "github.com/zeta-chain/zetacore/rpc/types" authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" @@ -21,6 +21,8 @@ import ( ) // Clients contains RPC client interfaces to interact with ZetaCore +// +// Clients also has some high level wrappers for the clients type Clients struct { // Cosmos SDK clients diff --git a/pkg/rpc/clients_test.go b/pkg/rpc/clients_test.go index 8b61f8335d..ed4f7ccffa 100644 --- a/pkg/rpc/clients_test.go +++ b/pkg/rpc/clients_test.go @@ -9,12 +9,10 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - abci "github.com/cometbft/cometbft/abci/types" tmtypes "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cosmos/cosmos-sdk/client/grpc/tmservice" "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" "github.com/stretchr/testify/require" @@ -72,29 +70,6 @@ func setupMockServer( return server } -func withDummyServer(zetaBlockHeight int64) []grpcmock.ServerOption { - return []grpcmock.ServerOption{ - grpcmock.RegisterService(crosschaintypes.RegisterQueryServer), - grpcmock.RegisterService(crosschaintypes.RegisterMsgServer), - grpcmock.RegisterService(feemarkettypes.RegisterQueryServer), - grpcmock.RegisterService(authtypes.RegisterQueryServer), - grpcmock.RegisterService(abci.RegisterABCIApplicationServer), - func(s *grpcmock.Server) { - // Block Height - s.ExpectUnary("/zetachain.zetacore.crosschain.Query/LastZetaHeight"). - UnlimitedTimes(). - Return(crosschaintypes.QueryLastZetaHeightResponse{Height: zetaBlockHeight}) - - // London Base Fee - s.ExpectUnary("/ethermint.feemarket.v1.Query/Params"). - UnlimitedTimes(). - Return(feemarkettypes.QueryParamsResponse{ - Params: feemarkettypes.Params{BaseFee: types.NewInt(100)}, - }) - }, - } -} - func setupZetacoreClients(t *testing.T) Clients { c, err := NewGRPCClients(gRPCListenPath, grpc.WithTransportCredentials(insecure.NewCredentials())) From fa7a6b75a9103d79e6fc778dc829a96e0f476f9b Mon Sep 17 00:00:00 2001 From: Alex Gartner Date: Thu, 29 Aug 2024 12:28:28 -0700 Subject: [PATCH 7/8] fix e2e lint --- cmd/zetae2e/config/clients.go | 4 ++-- cmd/zetae2e/run.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/zetae2e/config/clients.go b/cmd/zetae2e/config/clients.go index a2b1909111..3aec591737 100644 --- a/cmd/zetae2e/config/clients.go +++ b/cmd/zetae2e/config/clients.go @@ -35,7 +35,7 @@ func getClientsFromConfig(ctx context.Context, conf config.Config, account confi if err != nil { return runner.Clients{}, fmt.Errorf("failed to get evm client: %w", err) } - zetaCoreClients, err := GetZetacoreClient(ctx, conf) + zetaCoreClients, err := GetZetacoreClient(conf) if err != nil { return runner.Clients{}, fmt.Errorf("failed to get zetacore client: %w", err) } @@ -106,7 +106,7 @@ func getEVMClient( return evmClient, evmAuth, nil } -func GetZetacoreClient(ctx context.Context, conf config.Config) (zetacore_rpc.Clients, error) { +func GetZetacoreClient(conf config.Config) (zetacore_rpc.Clients, error) { if conf.RPCs.ZetaCoreGRPC != "" { return zetacore_rpc.NewGRPCClients( conf.RPCs.ZetaCoreGRPC, diff --git a/cmd/zetae2e/run.go b/cmd/zetae2e/run.go index a710e98504..5f38a39cbd 100644 --- a/cmd/zetae2e/run.go +++ b/cmd/zetae2e/run.go @@ -179,7 +179,7 @@ func parseCmdArgsToE2ETestRunConfig(args []string) ([]runner.E2ETestRunConfig, e // findERC20 loads ERC20 addresses via gRPC given CLI flags func findERC20(ctx context.Context, conf config.Config, erc20ChainName, erc20Symbol string) (string, string, error) { - clients, err := zetae2econfig.GetZetacoreClient(ctx, conf) + clients, err := zetae2econfig.GetZetacoreClient(conf) if err != nil { return "", "", fmt.Errorf("get zeta clients: %w", err) } From 9f11b8e3943241893a8ec3ebfef34fb93b07b39b Mon Sep 17 00:00:00 2001 From: Alex Gartner Date: Thu, 29 Aug 2024 12:58:20 -0700 Subject: [PATCH 8/8] changelog --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index e1b73cd957..53d03c8805 100644 --- a/changelog.md +++ b/changelog.md @@ -15,6 +15,7 @@ * [2644](https://github.com/zeta-chain/node/pull/2644) - add created_timestamp to cctx status * [2673](https://github.com/zeta-chain/node/pull/2673) - add relayer key importer, encryption and decryption * [2633](https://github.com/zeta-chain/node/pull/2633) - support for stateful precompiled contracts. +* [2788](https://github.com/zeta-chain/node/pull/2788) - add common importable zetacored rpc package ### Refactor