From f7e5c078be59f9b6aa1ae6e8cf232894e9e221b9 Mon Sep 17 00:00:00 2001 From: Charlie Chen <34498985+ws4charlie@users.noreply.github.com> Date: Fri, 19 Apr 2024 22:42:24 -0500 Subject: [PATCH] feat: outbound cctx scheduling with rate limiter (#2045) * initial commit of grpc pending cctx query with rate limiter * replace big.Float with sdk.Dec and update mock rate limiter flags * split big loop into backwards loop and forwards loop to be more accurate * adjust zetaclient code to query pending cctx with rate limit * update change log and add one more rate limiter flag test * use outboun amount for calculation * some minimum code refactor * created separate file for cctx query with rate limit * improved a few error handlling * use old cctx query as fallback when rate limiter is disabled; some renaming * fixed unit test compile * added unit test for fallback query --------- Co-authored-by: Lucas Bertrand --- changelog.md | 1 + cmd/zetae2e/stress.go | 2 +- docs/openapi/openapi.swagger.yaml | 88 +- proto/crosschain/query.proto | 23 +- testutil/keeper/mocks/crosschain/fungible.go | 20 + testutil/keeper/mocks/crosschain/observer.go | 20 + testutil/sample/fungible.go | 30 + typescript/crosschain/query_pb.d.ts | 90 +- x/crosschain/client/cli/cli_cctx.go | 4 +- x/crosschain/keeper/abci.go | 2 +- x/crosschain/keeper/cctx_utils.go | 2 +- x/crosschain/keeper/cctx_utils_test.go | 10 +- x/crosschain/keeper/evm_deposit_test.go | 22 +- x/crosschain/keeper/foreign_coins.go | 4 +- x/crosschain/keeper/foreign_coins_test.go | 3 +- x/crosschain/keeper/gas_payment_test.go | 28 +- x/crosschain/keeper/grpc_query_cctx.go | 77 +- .../keeper/grpc_query_cctx_rate_limit.go | 259 ++++++ .../keeper/grpc_query_cctx_rate_limit_test.go | 182 ++++ x/crosschain/keeper/grpc_query_cctx_test.go | 36 +- .../msg_server_add_to_intx_tracker_test.go | 16 +- .../keeper/msg_server_add_to_outtx_tracker.go | 2 +- .../msg_server_migrate_tss_funds_test.go | 28 +- .../msg_server_refund_aborted_tx_test.go | 26 +- .../keeper/msg_server_vote_inbound_tx_test.go | 4 +- .../msg_server_vote_outbound_tx_test.go | 12 +- .../keeper/msg_server_whitelist_erc20_test.go | 10 +- x/crosschain/keeper/process_inbound_test.go | 20 +- x/crosschain/keeper/process_outbound_test.go | 16 +- x/crosschain/keeper/rate_limiter_flags.go | 34 + .../keeper/rate_limiter_flags_test.go | 67 ++ x/crosschain/keeper/refund_test.go | 32 +- x/crosschain/keeper/utils_test.go | 6 +- x/crosschain/types/expected_keepers.go | 2 + x/crosschain/types/query.pb.go | 831 ++++++++++++++---- x/crosschain/types/query.pb.gw.go | 117 ++- x/fungible/keeper/foreign_coins.go | 18 + x/observer/keeper/chain_params.go | 13 + zetaclient/evm/evm_signer.go | 2 +- zetaclient/interfaces/interfaces.go | 1 + zetaclient/testutils/stub/core_bridge.go | 7 + zetaclient/zetabridge/query.go | 26 +- zetaclient/zetabridge/query_test.go | 6 +- zetaclient/zetacore_observer.go | 48 +- 44 files changed, 1798 insertions(+), 449 deletions(-) create mode 100644 x/crosschain/keeper/grpc_query_cctx_rate_limit.go create mode 100644 x/crosschain/keeper/grpc_query_cctx_rate_limit_test.go diff --git a/changelog.md b/changelog.md index dac460d24a..ede402b460 100644 --- a/changelog.md +++ b/changelog.md @@ -54,6 +54,7 @@ * [1954](https://github.com/zeta-chain/node/pull/1954) - add metric for concurrent keysigns * [1979](https://github.com/zeta-chain/node/pull/1979) - add script to import genesis data into an existing genesis file * [2006](https://github.com/zeta-chain/node/pull/2006) - add Amoy testnet static chain information +* [2045](https://github.com/zeta-chain/node/pull/2046) - add grpc query with outbound rate limit for zetaclient to use * [2046](https://github.com/zeta-chain/node/pull/2046) - add state variable in crosschain for rate limiter flags * [2034](https://github.com/zeta-chain/node/pull/2034) - add support for zEVM message passing diff --git a/cmd/zetae2e/stress.go b/cmd/zetae2e/stress.go index 5228905074..f8ca5b9f28 100644 --- a/cmd/zetae2e/stress.go +++ b/cmd/zetae2e/stress.go @@ -252,7 +252,7 @@ func EchoNetworkMetrics(runner *runner.E2ERunner) { case <-ticker.C: numTicks++ // Get all pending outbound transactions - cctxResp, err := runner.CctxClient.CctxListPending(context.Background(), &crosschaintypes.QueryListCctxPendingRequest{ + cctxResp, err := runner.CctxClient.ListPendingCctx(context.Background(), &crosschaintypes.QueryListPendingCctxRequest{ ChainId: chainID.Int64(), }) if err != nil { diff --git a/docs/openapi/openapi.swagger.yaml b/docs/openapi/openapi.swagger.yaml index f18907f74f..1eb8fe4593 100644 --- a/docs/openapi/openapi.swagger.yaml +++ b/docs/openapi/openapi.swagger.yaml @@ -26582,32 +26582,6 @@ paths: type: string tags: - Query - /zeta-chain/crosschain/cctxPending: - get: - summary: Queries a list of pending cctxs. - operationId: Query_CctxListPending - responses: - "200": - description: A successful response. - schema: - $ref: '#/definitions/crosschainQueryListCctxPendingResponse' - default: - description: An unexpected error response. - schema: - $ref: '#/definitions/googlerpcStatus' - parameters: - - name: chain_id - in: query - required: false - type: string - format: int64 - - name: limit - in: query - required: false - type: integer - format: int64 - tags: - - Query /zeta-chain/crosschain/convertGasToZeta: get: operationId: Query_ConvertGasToZeta @@ -27173,6 +27147,53 @@ paths: type: boolean tags: - Query + /zeta-chain/crosschain/pendingCctx: + get: + summary: Queries a list of pending cctxs. + operationId: Query_ListPendingCctx + responses: + "200": + description: A successful response. + schema: + $ref: '#/definitions/crosschainQueryListPendingCctxResponse' + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/googlerpcStatus' + parameters: + - name: chain_id + in: query + required: false + type: string + format: int64 + - name: limit + in: query + required: false + type: integer + format: int64 + tags: + - Query + /zeta-chain/crosschain/pendingCctxWithinRateLimit: + get: + summary: Queries a list of pending cctxs within rate limit. + operationId: Query_ListPendingCctxWithinRateLimit + responses: + "200": + description: A successful response. + schema: + $ref: '#/definitions/crosschainQueryListPendingCctxWithinRateLimitResponse' + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/googlerpcStatus' + parameters: + - name: limit + in: query + required: false + type: integer + format: int64 + tags: + - Query /zeta-chain/crosschain/protocolFee: get: operationId: Query_ProtocolFee @@ -53970,7 +53991,7 @@ definitions: Height: type: string format: int64 - crosschainQueryListCctxPendingResponse: + crosschainQueryListPendingCctxResponse: type: object properties: CrossChainTx: @@ -53981,6 +54002,19 @@ definitions: totalPending: type: string format: uint64 + crosschainQueryListPendingCctxWithinRateLimitResponse: + type: object + properties: + cross_chain_tx: + type: array + items: + type: object + $ref: '#/definitions/crosschainCrossChainTx' + total_pending: + type: string + format: uint64 + rate_limit_exceeded: + type: boolean crosschainQueryMessagePassingProtocolFeeResponse: type: object properties: diff --git a/proto/crosschain/query.proto b/proto/crosschain/query.proto index 326b615560..b017e2c523 100644 --- a/proto/crosschain/query.proto +++ b/proto/crosschain/query.proto @@ -95,8 +95,13 @@ service Query { } // Queries a list of pending cctxs. - rpc CctxListPending(QueryListCctxPendingRequest) returns (QueryListCctxPendingResponse) { - option (google.api.http).get = "/zeta-chain/crosschain/cctxPending"; + rpc ListPendingCctx(QueryListPendingCctxRequest) returns (QueryListPendingCctxResponse) { + option (google.api.http).get = "/zeta-chain/crosschain/pendingCctx"; + } + + // Queries a list of pending cctxs within rate limit. + rpc ListPendingCctxWithinRateLimit(QueryListPendingCctxWithinRateLimitRequest) returns (QueryListPendingCctxWithinRateLimitResponse) { + option (google.api.http).get = "/zeta-chain/crosschain/pendingCctxWithinRateLimit"; } rpc ZetaAccounting(QueryZetaAccountingRequest) returns (QueryZetaAccountingResponse) { @@ -248,16 +253,26 @@ message QueryAllCctxResponse { cosmos.base.query.v1beta1.PageResponse pagination = 2; } -message QueryListCctxPendingRequest { +message QueryListPendingCctxRequest { int64 chain_id = 1; uint32 limit = 2; } -message QueryListCctxPendingResponse { +message QueryListPendingCctxResponse { repeated CrossChainTx CrossChainTx = 1; uint64 totalPending = 2; } +message QueryListPendingCctxWithinRateLimitRequest { + uint32 limit = 1; +} + +message QueryListPendingCctxWithinRateLimitResponse { + repeated CrossChainTx cross_chain_tx = 1; + uint64 total_pending = 2; + bool rate_limit_exceeded = 3; +} + message QueryLastZetaHeightRequest {} message QueryLastZetaHeightResponse { diff --git a/testutil/keeper/mocks/crosschain/fungible.go b/testutil/keeper/mocks/crosschain/fungible.go index 1380308910..587c1676a6 100644 --- a/testutil/keeper/mocks/crosschain/fungible.go +++ b/testutil/keeper/mocks/crosschain/fungible.go @@ -254,6 +254,26 @@ func (_m *CrosschainFungibleKeeper) GetAllForeignCoinsForChain(ctx types.Context return r0 } +// GetAllForeignERC20CoinMap provides a mock function with given fields: ctx +func (_m *CrosschainFungibleKeeper) GetAllForeignERC20CoinMap(ctx types.Context) map[int64]map[string]fungibletypes.ForeignCoins { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetAllForeignERC20CoinMap") + } + + var r0 map[int64]map[string]fungibletypes.ForeignCoins + if rf, ok := ret.Get(0).(func(types.Context) map[int64]map[string]fungibletypes.ForeignCoins); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[int64]map[string]fungibletypes.ForeignCoins) + } + } + + return r0 +} + // GetForeignCoinFromAsset provides a mock function with given fields: ctx, asset, chainID func (_m *CrosschainFungibleKeeper) GetForeignCoinFromAsset(ctx types.Context, asset string, chainID int64) (fungibletypes.ForeignCoins, bool) { ret := _m.Called(ctx, asset, chainID) diff --git a/testutil/keeper/mocks/crosschain/observer.go b/testutil/keeper/mocks/crosschain/observer.go index aa05e13226..37b8ea2720 100644 --- a/testutil/keeper/mocks/crosschain/observer.go +++ b/testutil/keeper/mocks/crosschain/observer.go @@ -596,6 +596,26 @@ func (_m *CrosschainObserverKeeper) GetSupportedChains(ctx types.Context) []*cha return r0 } +// GetSupportedForeignChains provides a mock function with given fields: ctx +func (_m *CrosschainObserverKeeper) GetSupportedForeignChains(ctx types.Context) []*chains.Chain { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetSupportedForeignChains") + } + + var r0 []*chains.Chain + if rf, ok := ret.Get(0).(func(types.Context) []*chains.Chain); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*chains.Chain) + } + } + + return r0 +} + // GetTSS provides a mock function with given fields: ctx func (_m *CrosschainObserverKeeper) GetTSS(ctx types.Context) (observertypes.TSS, bool) { ret := _m.Called(ctx) diff --git a/testutil/sample/fungible.go b/testutil/sample/fungible.go index 73fdc2b2e3..3be91d06a3 100644 --- a/testutil/sample/fungible.go +++ b/testutil/sample/fungible.go @@ -3,6 +3,7 @@ package sample import ( "testing" + "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/pkg/coin" "github.com/zeta-chain/zetacore/x/fungible/types" ) @@ -22,6 +23,35 @@ func ForeignCoins(t *testing.T, address string) types.ForeignCoins { } } +func ForeignCoinList(t *testing.T, zrc20ETH, zrc20BTC, zrc20ERC20, erc20Asset string) []types.ForeignCoins { + // eth and btc chain id + ethChainID := chains.GoerliLocalnetChain().ChainId + btcChainID := chains.BtcRegtestChain().ChainId + + // add zrc20 ETH + fcGas := ForeignCoins(t, zrc20ETH) + fcGas.Asset = "" + fcGas.ForeignChainId = ethChainID + fcGas.Decimals = 18 + fcGas.CoinType = coin.CoinType_Gas + + // add zrc20 BTC + fcBTC := ForeignCoins(t, zrc20BTC) + fcBTC.Asset = "" + fcBTC.ForeignChainId = btcChainID + fcBTC.Decimals = 8 + fcBTC.CoinType = coin.CoinType_Gas + + // add zrc20 ERC20 + fcERC20 := ForeignCoins(t, zrc20ERC20) + fcERC20.Asset = erc20Asset + fcERC20.ForeignChainId = ethChainID + fcERC20.Decimals = 6 + fcERC20.CoinType = coin.CoinType_ERC20 + + return []types.ForeignCoins{fcGas, fcBTC, fcERC20} +} + func SystemContract() *types.SystemContract { return &types.SystemContract{ SystemContract: EthAddress().String(), diff --git a/typescript/crosschain/query_pb.d.ts b/typescript/crosschain/query_pb.d.ts index e73ef4394d..34b4a44f38 100644 --- a/typescript/crosschain/query_pb.d.ts +++ b/typescript/crosschain/query_pb.d.ts @@ -814,9 +814,9 @@ export declare class QueryAllCctxResponse extends Message } /** - * @generated from message zetachain.zetacore.crosschain.QueryListCctxPendingRequest + * @generated from message zetachain.zetacore.crosschain.QueryListPendingCctxRequest */ -export declare class QueryListCctxPendingRequest extends Message { +export declare class QueryListPendingCctxRequest extends Message { /** * @generated from field: int64 chain_id = 1; */ @@ -827,25 +827,25 @@ export declare class QueryListCctxPendingRequest extends Message); + constructor(data?: PartialMessage); static readonly runtime: typeof proto3; - static readonly typeName = "zetachain.zetacore.crosschain.QueryListCctxPendingRequest"; + static readonly typeName = "zetachain.zetacore.crosschain.QueryListPendingCctxRequest"; static readonly fields: FieldList; - static fromBinary(bytes: Uint8Array, options?: Partial): QueryListCctxPendingRequest; + static fromBinary(bytes: Uint8Array, options?: Partial): QueryListPendingCctxRequest; - static fromJson(jsonValue: JsonValue, options?: Partial): QueryListCctxPendingRequest; + static fromJson(jsonValue: JsonValue, options?: Partial): QueryListPendingCctxRequest; - static fromJsonString(jsonString: string, options?: Partial): QueryListCctxPendingRequest; + static fromJsonString(jsonString: string, options?: Partial): QueryListPendingCctxRequest; - static equals(a: QueryListCctxPendingRequest | PlainMessage | undefined, b: QueryListCctxPendingRequest | PlainMessage | undefined): boolean; + static equals(a: QueryListPendingCctxRequest | PlainMessage | undefined, b: QueryListPendingCctxRequest | PlainMessage | undefined): boolean; } /** - * @generated from message zetachain.zetacore.crosschain.QueryListCctxPendingResponse + * @generated from message zetachain.zetacore.crosschain.QueryListPendingCctxResponse */ -export declare class QueryListCctxPendingResponse extends Message { +export declare class QueryListPendingCctxResponse extends Message { /** * @generated from field: repeated zetachain.zetacore.crosschain.CrossChainTx CrossChainTx = 1; */ @@ -856,19 +856,77 @@ export declare class QueryListCctxPendingResponse extends Message); + constructor(data?: PartialMessage); static readonly runtime: typeof proto3; - static readonly typeName = "zetachain.zetacore.crosschain.QueryListCctxPendingResponse"; + static readonly typeName = "zetachain.zetacore.crosschain.QueryListPendingCctxResponse"; static readonly fields: FieldList; - static fromBinary(bytes: Uint8Array, options?: Partial): QueryListCctxPendingResponse; + static fromBinary(bytes: Uint8Array, options?: Partial): QueryListPendingCctxResponse; - static fromJson(jsonValue: JsonValue, options?: Partial): QueryListCctxPendingResponse; + static fromJson(jsonValue: JsonValue, options?: Partial): QueryListPendingCctxResponse; - static fromJsonString(jsonString: string, options?: Partial): QueryListCctxPendingResponse; + static fromJsonString(jsonString: string, options?: Partial): QueryListPendingCctxResponse; - static equals(a: QueryListCctxPendingResponse | PlainMessage | undefined, b: QueryListCctxPendingResponse | PlainMessage | undefined): boolean; + static equals(a: QueryListPendingCctxResponse | PlainMessage | undefined, b: QueryListPendingCctxResponse | PlainMessage | undefined): boolean; +} + +/** + * @generated from message zetachain.zetacore.crosschain.QueryListPendingCctxWithinRateLimitRequest + */ +export declare class QueryListPendingCctxWithinRateLimitRequest extends Message { + /** + * @generated from field: uint32 limit = 1; + */ + limit: number; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "zetachain.zetacore.crosschain.QueryListPendingCctxWithinRateLimitRequest"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): QueryListPendingCctxWithinRateLimitRequest; + + static fromJson(jsonValue: JsonValue, options?: Partial): QueryListPendingCctxWithinRateLimitRequest; + + static fromJsonString(jsonString: string, options?: Partial): QueryListPendingCctxWithinRateLimitRequest; + + static equals(a: QueryListPendingCctxWithinRateLimitRequest | PlainMessage | undefined, b: QueryListPendingCctxWithinRateLimitRequest | PlainMessage | undefined): boolean; +} + +/** + * @generated from message zetachain.zetacore.crosschain.QueryListPendingCctxWithinRateLimitResponse + */ +export declare class QueryListPendingCctxWithinRateLimitResponse extends Message { + /** + * @generated from field: repeated zetachain.zetacore.crosschain.CrossChainTx cross_chain_tx = 1; + */ + crossChainTx: CrossChainTx[]; + + /** + * @generated from field: uint64 total_pending = 2; + */ + totalPending: bigint; + + /** + * @generated from field: bool rate_limit_exceeded = 3; + */ + rateLimitExceeded: boolean; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "zetachain.zetacore.crosschain.QueryListPendingCctxWithinRateLimitResponse"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): QueryListPendingCctxWithinRateLimitResponse; + + static fromJson(jsonValue: JsonValue, options?: Partial): QueryListPendingCctxWithinRateLimitResponse; + + static fromJsonString(jsonString: string, options?: Partial): QueryListPendingCctxWithinRateLimitResponse; + + static equals(a: QueryListPendingCctxWithinRateLimitResponse | PlainMessage | undefined, b: QueryListPendingCctxWithinRateLimitResponse | PlainMessage | undefined): boolean; } /** diff --git a/x/crosschain/client/cli/cli_cctx.go b/x/crosschain/client/cli/cli_cctx.go index 87991442d1..b5add8610b 100644 --- a/x/crosschain/client/cli/cli_cctx.go +++ b/x/crosschain/client/cli/cli_cctx.go @@ -69,13 +69,13 @@ func CmdPendingCctx() *cobra.Command { return err } - params := &types.QueryListCctxPendingRequest{ + params := &types.QueryListPendingCctxRequest{ ChainId: chainID, // #nosec G701 bit size verified Limit: uint32(limit), } - res, err := queryClient.CctxListPending(context.Background(), params) + res, err := queryClient.ListPendingCctx(context.Background(), params) if err != nil { return err } diff --git a/x/crosschain/keeper/abci.go b/x/crosschain/keeper/abci.go index 5a02c53676..f893e795bb 100644 --- a/x/crosschain/keeper/abci.go +++ b/x/crosschain/keeper/abci.go @@ -51,7 +51,7 @@ IterateChains: for _, chain := range chains { // support only external evm chains if zetachains.IsEVMChain(chain.ChainId) && !zetachains.IsZetaChain(chain.ChainId) { - res, err := k.CctxListPending(sdk.UnwrapSDKContext(ctx), &types.QueryListCctxPendingRequest{ + res, err := k.ListPendingCctx(sdk.UnwrapSDKContext(ctx), &types.QueryListPendingCctxRequest{ ChainId: chain.ChainId, Limit: gasPriceIncreaseFlags.MaxPendingCctxs, }) diff --git a/x/crosschain/keeper/cctx_utils.go b/x/crosschain/keeper/cctx_utils.go index 6ae826f9ed..6f9651967a 100644 --- a/x/crosschain/keeper/cctx_utils.go +++ b/x/crosschain/keeper/cctx_utils.go @@ -86,7 +86,7 @@ func (k Keeper) GetRevertGasLimit(ctx sdk.Context, cctx types.CrossChainTx) (uin return 0, nil } -func IsPending(cctx types.CrossChainTx) bool { +func IsPending(cctx *types.CrossChainTx) bool { // pending inbound is not considered a "pending" state because it has not reached consensus yet return cctx.CctxStatus.Status == types.CctxStatus_PendingOutbound || cctx.CctxStatus.Status == types.CctxStatus_PendingRevert } diff --git a/x/crosschain/keeper/cctx_utils_test.go b/x/crosschain/keeper/cctx_utils_test.go index 1c807a97c1..af6445744c 100644 --- a/x/crosschain/keeper/cctx_utils_test.go +++ b/x/crosschain/keeper/cctx_utils_test.go @@ -42,7 +42,7 @@ func TestGetRevertGasLimit(t *testing.T) { k, ctx, sdkk, zk := keepertest.CrosschainKeeper(t) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) gas := setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, chainID, "foo", "FOO") @@ -63,7 +63,7 @@ func TestGetRevertGasLimit(t *testing.T) { k, ctx, sdkk, zk := keepertest.CrosschainKeeper(t) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) asset := sample.EthAddress().String() zrc20Addr := deployZRC20( @@ -107,7 +107,7 @@ func TestGetRevertGasLimit(t *testing.T) { k, ctx, _, zk := keepertest.CrosschainKeeper(t) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() zk.FungibleKeeper.SetForeignCoins(ctx, fungibletypes.ForeignCoins{ Zrc20ContractAddress: sample.EthAddress().String(), @@ -141,7 +141,7 @@ func TestGetRevertGasLimit(t *testing.T) { k, ctx, _, zk := keepertest.CrosschainKeeper(t) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() asset := sample.EthAddress().String() zk.FungibleKeeper.SetForeignCoins(ctx, fungibletypes.ForeignCoins{ @@ -215,7 +215,7 @@ func Test_IsPending(t *testing.T) { } for _, tc := range tt { t.Run(fmt.Sprintf("status %s", tc.status), func(t *testing.T) { - require.Equal(t, tc.expected, crosschainkeeper.IsPending(types.CrossChainTx{CctxStatus: &types.Status{Status: tc.status}})) + require.Equal(t, tc.expected, crosschainkeeper.IsPending(&types.CrossChainTx{CctxStatus: &types.Status{Status: tc.status}})) }) } } diff --git a/x/crosschain/keeper/evm_deposit_test.go b/x/crosschain/keeper/evm_deposit_test.go index 1f6cd4fad4..d30424697c 100644 --- a/x/crosschain/keeper/evm_deposit_test.go +++ b/x/crosschain/keeper/evm_deposit_test.go @@ -84,7 +84,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { UseFungibleMock: true, }) - senderChain := getValidEthChainID(t) + senderChain := getValidEthChainID() fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) receiver := sample.EthAddress() @@ -127,7 +127,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { UseFungibleMock: true, }) - senderChain := getValidEthChainID(t) + senderChain := getValidEthChainID() fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) receiver := sample.EthAddress() @@ -186,7 +186,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { UseFungibleMock: true, }) - senderChain := getValidEthChainID(t) + senderChain := getValidEthChainID() fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) receiver := sample.EthAddress() @@ -273,7 +273,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { UseFungibleMock: true, }) - senderChain := getValidEthChainID(t) + senderChain := getValidEthChainID() fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) receiver := sample.EthAddress() @@ -317,7 +317,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { UseFungibleMock: true, }) - senderChain := getValidEthChainID(t) + senderChain := getValidEthChainID() fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) receiver := sample.EthAddress() @@ -361,7 +361,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { UseFungibleMock: true, }) - senderChain := getValidEthChainID(t) + senderChain := getValidEthChainID() fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) receiver := sample.EthAddress() @@ -404,7 +404,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { UseFungibleMock: true, }) - senderChain := getValidEthChainID(t) + senderChain := getValidEthChainID() fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) receiver := sample.EthAddress() @@ -447,7 +447,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { UseFungibleMock: true, }) - senderChain := getValidEthChainID(t) + senderChain := getValidEthChainID() fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) receiver := sample.EthAddress() @@ -487,7 +487,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ UseFungibleMock: true, }) - senderChain := getValidEthChainID(t) + senderChain := getValidEthChainID() cctx := sample.CrossChainTx(t, "foo") cctx.GetCurrentOutTxParam().Receiver = sample.EthAddress().String() @@ -509,7 +509,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { UseFungibleMock: true, }) - senderChain := getValidEthChainID(t) + senderChain := getValidEthChainID() fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) receiver := sample.EthAddress() @@ -555,7 +555,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { UseFungibleMock: true, }) - senderChain := getValidEthChainID(t) + senderChain := getValidEthChainID() fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) receiver := sample.EthAddress() diff --git a/x/crosschain/keeper/foreign_coins.go b/x/crosschain/keeper/foreign_coins.go index 1ceeb39bf7..15ecd54260 100644 --- a/x/crosschain/keeper/foreign_coins.go +++ b/x/crosschain/keeper/foreign_coins.go @@ -5,11 +5,11 @@ import ( fungibleModuleTypes "github.com/zeta-chain/zetacore/x/fungible/types" ) -func (k Keeper) GetAllForeignCoins(ctx sdk.Context) ([]fungibleModuleTypes.ForeignCoins, error) { +func (k Keeper) GetAllForeignCoins(ctx sdk.Context) []fungibleModuleTypes.ForeignCoins { chains := k.zetaObserverKeeper.GetSupportedChains(ctx) var fCoins []fungibleModuleTypes.ForeignCoins for _, chain := range chains { fCoins = append(fCoins, k.fungibleKeeper.GetAllForeignCoinsForChain(ctx, chain.ChainId)...) } - return fCoins, nil + return fCoins } diff --git a/x/crosschain/keeper/foreign_coins_test.go b/x/crosschain/keeper/foreign_coins_test.go index 5d145b08f1..aaa359cd72 100644 --- a/x/crosschain/keeper/foreign_coins_test.go +++ b/x/crosschain/keeper/foreign_coins_test.go @@ -14,7 +14,6 @@ func TestKeeper_GetAllForeignCoins(t *testing.T) { fc.ForeignChainId = 101 k.GetFungibleKeeper().SetForeignCoins(ctx, fc) - res, err := k.GetAllForeignCoins(ctx) - require.NoError(t, err) + res := k.GetAllForeignCoins(ctx) require.Equal(t, 1, len(res)) } diff --git a/x/crosschain/keeper/gas_payment_test.go b/x/crosschain/keeper/gas_payment_test.go index 569a360327..8079c3c67a 100644 --- a/x/crosschain/keeper/gas_payment_test.go +++ b/x/crosschain/keeper/gas_payment_test.go @@ -30,7 +30,7 @@ func TestKeeper_PayGasNativeAndUpdateCctx(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) // deploy gas coin and set fee params - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() setSupportedChain(ctx, zk, chainID) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) @@ -72,7 +72,7 @@ func TestKeeper_PayGasNativeAndUpdateCctx(t *testing.T) { t.Run("should fail if not coin type gas", func(t *testing.T) { k, ctx, _, _ := testkeeper.CrosschainKeeper(t) - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() cctx := types.CrossChainTx{ InboundTxParams: &types.InboundTxParams{ CoinType: coin.CoinType_Zeta, @@ -98,7 +98,7 @@ func TestKeeper_PayGasNativeAndUpdateCctx(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) // deploy gas coin and set fee params - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() setSupportedChain(ctx, zk, chainID) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, chainID, "foobar", "foobar") @@ -127,7 +127,7 @@ func TestKeeper_PayGasNativeAndUpdateCctx(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) // deploy gas coin and set fee params - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() setSupportedChain(ctx, zk, chainID) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) zrc20 := setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, chainID, "foobar", "foobar") @@ -170,7 +170,7 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) // deploy gas coin, erc20 and set fee params - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() setSupportedChain(ctx, zk, chainID) assetAddress := sample.EthAddress().String() deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) @@ -236,7 +236,7 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { t.Run("should fail if not coin type erc20", func(t *testing.T) { k, ctx, _, _ := testkeeper.CrosschainKeeper(t) - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() cctx := types.CrossChainTx{ InboundTxParams: &types.InboundTxParams{ CoinType: coin.CoinType_Gas, @@ -262,7 +262,7 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) // deploy gas coin and set fee params - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() setSupportedChain(ctx, zk, chainID) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, chainID, "foobar", "foobar") @@ -291,7 +291,7 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) // deploy gas coin, erc20 and set fee params - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() setSupportedChain(ctx, zk, chainID) assetAddress := sample.EthAddress().String() deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) @@ -333,7 +333,7 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) // deploy gas coin, erc20 and set fee params - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() setSupportedChain(ctx, zk, chainID) assetAddress := sample.EthAddress().String() deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) @@ -385,7 +385,7 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) // deploy gas coin, erc20 and set fee params - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() setSupportedChain(ctx, zk, chainID) assetAddress := sample.EthAddress().String() deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) @@ -453,7 +453,7 @@ func TestKeeper_PayGasInZetaAndUpdateCctx(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) // deploy gas coin and set fee params - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() setSupportedChain(ctx, zk, chainID) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) zrc20 := setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, chainID, "foobar", "foobar") @@ -514,7 +514,7 @@ func TestKeeper_PayGasInZetaAndUpdateCctx(t *testing.T) { t.Run("should fail if pay gas in zeta with coin type other than zeta", func(t *testing.T) { k, ctx, _, _ := testkeeper.CrosschainKeeper(t) - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() cctx := types.CrossChainTx{ InboundTxParams: &types.InboundTxParams{ CoinType: coin.CoinType_Gas, @@ -540,7 +540,7 @@ func TestKeeper_PayGasInZetaAndUpdateCctx(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) // deploy gas coin and set fee params - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() setSupportedChain(ctx, zk, chainID) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, chainID, "foobar", "foobar") @@ -571,7 +571,7 @@ func TestKeeper_PayGasInZetaAndUpdateCctx(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) // deploy gas coin and set fee params - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() setSupportedChain(ctx, zk, chainID) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) zrc20 := setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, chainID, "foobar", "foobar") diff --git a/x/crosschain/keeper/grpc_query_cctx.go b/x/crosschain/keeper/grpc_query_cctx.go index 66e809b6b7..8e96757b44 100644 --- a/x/crosschain/keeper/grpc_query_cctx.go +++ b/x/crosschain/keeper/grpc_query_cctx.go @@ -8,6 +8,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" "github.com/zeta-chain/zetacore/x/crosschain/types" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -78,42 +79,32 @@ func (k Keeper) CctxByNonce(c context.Context, req *types.QueryGetCctxByNonceReq return nil, status.Error(codes.Internal, "tss not found") } // #nosec G701 always in range - res, found := k.GetObserverKeeper().GetNonceToCctx(ctx, tss.TssPubkey, req.ChainID, int64(req.Nonce)) - if !found { - return nil, status.Error(codes.Internal, fmt.Sprintf("nonceToCctx not found: nonce %d, chainid %d", req.Nonce, req.ChainID)) - } - val, found := k.GetCrossChainTx(ctx, res.CctxIndex) - if !found { - return nil, status.Error(codes.Internal, fmt.Sprintf("cctx not found: index %s", res.CctxIndex)) + cctx, err := getCctxByChainIDAndNonce(k, ctx, tss.TssPubkey, req.ChainID, int64(req.Nonce)) + if err != nil { + return nil, err } - return &types.QueryGetCctxResponse{CrossChainTx: &val}, nil + return &types.QueryGetCctxResponse{CrossChainTx: cctx}, nil } -// CctxListPending returns a list of pending cctxs and the total number of pending cctxs -// a limit for the number of cctxs to return can be specified -// if no limit is specified, the default is MaxPendingCctxs -func (k Keeper) CctxListPending(c context.Context, req *types.QueryListCctxPendingRequest) (*types.QueryListCctxPendingResponse, error) { +// ListPendingCctx returns a list of pending cctxs and the total number of pending cctxs +// a limit for the number of cctxs to return can be specified or the default is MaxPendingCctxs +func (k Keeper) ListPendingCctx(c context.Context, req *types.QueryListPendingCctxRequest) (*types.QueryListPendingCctxResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "invalid request") } - // check limit - // if no limit specified, default to MaxPendingCctxs - if req.Limit > MaxPendingCctxs { - return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("limit exceeds max limit of %d", MaxPendingCctxs)) - } + // use default MaxPendingCctxs if not specified or too high limit := req.Limit - if limit == 0 { + if limit == 0 || limit > MaxPendingCctxs { limit = MaxPendingCctxs } - ctx := sdk.UnwrapSDKContext(c) // query the nonces that are pending tss, found := k.zetaObserverKeeper.GetTSS(ctx) if !found { - return nil, status.Error(codes.Internal, "tss not found") + return nil, observertypes.ErrTssNotFound } pendingNonces, found := k.GetObserverKeeper().GetPendingNonces(ctx, tss.TssPubkey, req.ChainId) if !found { @@ -136,21 +127,16 @@ func (k Keeper) CctxListPending(c context.Context, req *types.QueryListCctxPendi startNonce = 0 } for i := startNonce; i < pendingNonces.NonceLow; i++ { - nonceToCctx, found := k.GetObserverKeeper().GetNonceToCctx(ctx, tss.TssPubkey, req.ChainId, i) - if !found { - return nil, status.Error(codes.Internal, fmt.Sprintf("nonceToCctx not found: nonce %d, chainid %d", i, req.ChainId)) - } - cctx, found := k.GetCrossChainTx(ctx, nonceToCctx.CctxIndex) - if !found { - return nil, status.Error(codes.Internal, fmt.Sprintf("cctx not found: index %s", nonceToCctx.CctxIndex)) + cctx, err := getCctxByChainIDAndNonce(k, ctx, tss.TssPubkey, req.ChainId, i) + if err != nil { + return nil, err } - if cctx.CctxStatus.Status == types.CctxStatus_PendingOutbound || cctx.CctxStatus.Status == types.CctxStatus_PendingRevert { - totalPending++ - // we check here if max cctxs is reached because we want to return the total pending cctxs - // even if we have reached the limit + // only take a `limit` number of pending cctxs as result but still count the total pending cctxs + if IsPending(cctx) { + totalPending++ if !maxCCTXsReached() { - cctxs = append(cctxs, &cctx) + cctxs = append(cctxs, cctx) } } } @@ -161,19 +147,28 @@ func (k Keeper) CctxListPending(c context.Context, req *types.QueryListCctxPendi // now query the pending nonces that we know are pending for i := pendingNonces.NonceLow; i < pendingNonces.NonceHigh && !maxCCTXsReached(); i++ { - nonceToCctx, found := k.GetObserverKeeper().GetNonceToCctx(ctx, tss.TssPubkey, req.ChainId, i) - if !found { - return nil, status.Error(codes.Internal, "nonceToCctx not found") - } - cctx, found := k.GetCrossChainTx(ctx, nonceToCctx.CctxIndex) - if !found { - return nil, status.Error(codes.Internal, "cctxIndex not found") + cctx, err := getCctxByChainIDAndNonce(k, ctx, tss.TssPubkey, req.ChainId, i) + if err != nil { + return nil, err } - cctxs = append(cctxs, &cctx) + cctxs = append(cctxs, cctx) } - return &types.QueryListCctxPendingResponse{ + return &types.QueryListPendingCctxResponse{ CrossChainTx: cctxs, TotalPending: totalPending, }, nil } + +// getCctxByChainIDAndNonce returns the cctx by chainID and nonce +func getCctxByChainIDAndNonce(k Keeper, ctx sdk.Context, tssPubkey string, chainID int64, nonce int64) (*types.CrossChainTx, error) { + nonceToCctx, found := k.GetObserverKeeper().GetNonceToCctx(ctx, tssPubkey, chainID, nonce) + if !found { + return nil, status.Error(codes.Internal, fmt.Sprintf("nonceToCctx not found: chainid %d, nonce %d", chainID, nonce)) + } + cctx, found := k.GetCrossChainTx(ctx, nonceToCctx.CctxIndex) + if !found { + return nil, status.Error(codes.Internal, fmt.Sprintf("cctx not found: index %s", nonceToCctx.CctxIndex)) + } + return &cctx, nil +} diff --git a/x/crosschain/keeper/grpc_query_cctx_rate_limit.go b/x/crosschain/keeper/grpc_query_cctx_rate_limit.go new file mode 100644 index 0000000000..b3b30ca939 --- /dev/null +++ b/x/crosschain/keeper/grpc_query_cctx_rate_limit.go @@ -0,0 +1,259 @@ +package keeper + +import ( + "context" + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/zeta-chain/zetacore/pkg/coin" + "github.com/zeta-chain/zetacore/x/crosschain/types" + fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// ListPendingCctxWithinRateLimit returns a list of pending cctxs that do not exceed the outbound rate limit +// a limit for the number of cctxs to return can be specified or the default is MaxPendingCctxs +func (k Keeper) ListPendingCctxWithinRateLimit(c context.Context, req *types.QueryListPendingCctxWithinRateLimitRequest) (*types.QueryListPendingCctxWithinRateLimitResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + // use default MaxPendingCctxs if not specified or too high + limit := req.Limit + if limit == 0 || limit > MaxPendingCctxs { + limit = MaxPendingCctxs + } + ctx := sdk.UnwrapSDKContext(c) + + // define a few variables to be used in the query loops + limitExceeded := false + totalPending := uint64(0) + totalCctxValueInZeta := sdk.NewDec(0) + cctxs := make([]*types.CrossChainTx, 0) + chains := k.zetaObserverKeeper.GetSupportedForeignChains(ctx) + + // check rate limit flags to decide if we should apply rate limit + applyLimit := true + rateLimitFlags, found := k.GetRateLimiterFlags(ctx) + if !found || !rateLimitFlags.Enabled { + applyLimit = false + } + + // fallback to non-rate-limited query if rate limiter is disabled + if !applyLimit { + for _, chain := range chains { + resp, err := k.ListPendingCctx(ctx, &types.QueryListPendingCctxRequest{ChainId: chain.ChainId, Limit: limit}) + if err == nil { + cctxs = append(cctxs, resp.CrossChainTx...) + totalPending += resp.TotalPending + } + } + return &types.QueryListPendingCctxWithinRateLimitResponse{ + CrossChainTx: cctxs, + TotalPending: totalPending, + RateLimitExceeded: false, + }, nil + } + + // get current height and tss + height := ctx.BlockHeight() + if height <= 0 { + return nil, status.Error(codes.OutOfRange, "height out of range") + } + tss, found := k.zetaObserverKeeper.GetTSS(ctx) + if !found { + return nil, observertypes.ErrTssNotFound + } + + // calculate the rate limiter sliding window left boundary (inclusive) + leftWindowBoundary := height - rateLimitFlags.Window + if leftWindowBoundary < 0 { + leftWindowBoundary = 0 + } + + // get the conversion rates for all foreign coins + var gasCoinRates map[int64]sdk.Dec + var erc20CoinRates map[int64]map[string]sdk.Dec + var erc20Coins map[int64]map[string]fungibletypes.ForeignCoins + var rateLimitInZeta sdk.Dec + if applyLimit { + gasCoinRates, erc20CoinRates = k.GetRateLimiterRates(ctx) + erc20Coins = k.fungibleKeeper.GetAllForeignERC20CoinMap(ctx) + rateLimitInZeta = sdk.NewDecFromBigInt(rateLimitFlags.Rate.BigInt()) + } + + // the criteria to stop adding cctxs to the rpc response + maxCCTXsReached := func() bool { + // #nosec G701 len always positive + return uint32(len(cctxs)) >= limit + } + + // query pending nonces for each foreign chain + // Note: The pending nonces could change during the RPC call, so query them beforehand + pendingNoncesMap := make(map[int64]*observertypes.PendingNonces) + for _, chain := range chains { + pendingNonces, found := k.GetObserverKeeper().GetPendingNonces(ctx, tss.TssPubkey, chain.ChainId) + if !found { + return nil, status.Error(codes.Internal, "pending nonces not found") + } + pendingNoncesMap[chain.ChainId] = &pendingNonces + } + + // query backwards for potential missed pending cctxs for each foreign chain +LoopBackwards: + for _, chain := range chains { + // we should at least query 1000 prior to find any pending cctx that we might have missed + // this logic is needed because a confirmation of higher nonce will automatically update the p.NonceLow + // therefore might mask some lower nonce cctx that is still pending. + pendingNonces := pendingNoncesMap[chain.ChainId] + startNonce := pendingNonces.NonceLow - 1 + endNonce := pendingNonces.NonceLow - 1000 + if endNonce < 0 { + endNonce = 0 + } + + // query cctx by nonce backwards to the left boundary of the rate limit sliding window + for nonce := startNonce; nonce >= 0; nonce-- { + cctx, err := getCctxByChainIDAndNonce(k, ctx, tss.TssPubkey, chain.ChainId, nonce) + if err != nil { + return nil, err + } + + // We should at least go backwards by 1000 nonces to pick up missed pending cctxs + // We might go even further back if rate limiter is enabled and the endNonce hasn't hit the left window boundary yet + // There are two criteria to stop scanning backwards: + // criteria #1: we'll stop at the left window boundary if the `endNonce` hasn't hit it yet + // #nosec G701 always positive + if nonce < endNonce && cctx.InboundTxParams.InboundTxObservedExternalHeight < uint64(leftWindowBoundary) { + break + } + // criteria #2: we should finish the RPC call if the rate limit is exceeded + if rateLimitExceeded(chain.ChainId, cctx, gasCoinRates, erc20CoinRates, erc20Coins, &totalCctxValueInZeta, rateLimitInZeta) { + limitExceeded = true + break LoopBackwards + } + + // only take a `limit` number of pending cctxs as result but still count the total pending cctxs + if IsPending(cctx) { + totalPending++ + if !maxCCTXsReached() { + cctxs = append(cctxs, cctx) + } + } + } + + // add the pending nonces to the total pending + // Note: the `totalPending` may not be accurate only if the rate limiter triggers early exit + // `totalPending` is now used for metrics only and it's okay to trade off accuracy for performance + // #nosec G701 always in range + totalPending += uint64(pendingNonces.NonceHigh - pendingNonces.NonceLow) + } + + // query forwards for pending cctxs for each foreign chain +LoopForwards: + for _, chain := range chains { + // query the pending cctxs in range [NonceLow, NonceHigh) + pendingNonces := pendingNoncesMap[chain.ChainId] + for nonce := pendingNonces.NonceLow; nonce < pendingNonces.NonceHigh; nonce++ { + cctx, err := getCctxByChainIDAndNonce(k, ctx, tss.TssPubkey, chain.ChainId, nonce) + if err != nil { + return nil, err + } + + // only take a `limit` number of pending cctxs as result + if maxCCTXsReached() { + break LoopForwards + } + // criteria #2: we should finish the RPC call if the rate limit is exceeded + if rateLimitExceeded(chain.ChainId, cctx, gasCoinRates, erc20CoinRates, erc20Coins, &totalCctxValueInZeta, rateLimitInZeta) { + limitExceeded = true + break LoopForwards + } + cctxs = append(cctxs, cctx) + } + } + + return &types.QueryListPendingCctxWithinRateLimitResponse{ + CrossChainTx: cctxs, + TotalPending: totalPending, + RateLimitExceeded: limitExceeded, + }, nil +} + +// convertCctxValue converts the value of the cctx in ZETA using given conversion rates +func convertCctxValue( + chainID int64, + cctx *types.CrossChainTx, + gasCoinRates map[int64]sdk.Dec, + erc20CoinRates map[int64]map[string]sdk.Dec, + erc20Coins map[int64]map[string]fungibletypes.ForeignCoins, +) sdk.Dec { + var rate sdk.Dec + var decimals uint64 + switch cctx.InboundTxParams.CoinType { + case coin.CoinType_Zeta: + // no conversion needed for ZETA + rate = sdk.NewDec(1) + case coin.CoinType_Gas: + rate = gasCoinRates[chainID] + case coin.CoinType_ERC20: + // get the ERC20 coin decimals + _, found := erc20Coins[chainID] + if !found { + // skip if no coin found for this chainID + return sdk.NewDec(0) + } + fCoin, found := erc20Coins[chainID][strings.ToLower(cctx.InboundTxParams.Asset)] + if !found { + // skip if no coin found for this Asset + return sdk.NewDec(0) + } + // #nosec G701 always in range + decimals = uint64(fCoin.Decimals) + + // get the ERC20 coin rate + _, found = erc20CoinRates[chainID] + if !found { + // skip if no rate found for this chainID + return sdk.NewDec(0) + } + rate = erc20CoinRates[chainID][strings.ToLower(cctx.InboundTxParams.Asset)] + default: + // skip CoinType_Cmd + return sdk.NewDec(0) + } + + // should not happen, return 0 to skip if it happens + if rate.LTE(sdk.NewDec(0)) { + return sdk.NewDec(0) + } + + // the reciprocal of `rate` is the amount of zrc20 needed to buy 1 ZETA + // for example, given rate = 0.8, the reciprocal is 1.25, which means 1.25 ZRC20 can buy 1 ZETA + // given decimals = 6, the `oneZeta` amount will be 1.25 * 10^6 = 1250000 + oneZrc20 := sdk.NewDec(1).Power(decimals) + oneZeta := oneZrc20.Quo(rate) + + // convert asset amount into ZETA + amountCctx := sdk.NewDecFromBigInt(cctx.GetCurrentOutTxParam().Amount.BigInt()) + amountZeta := amountCctx.Quo(oneZeta) + return amountZeta +} + +// rateLimitExceeded accumulates the cctx value and then checks if the rate limit is exceeded +// returns true if the rate limit is exceeded +func rateLimitExceeded( + chainID int64, + cctx *types.CrossChainTx, + gasCoinRates map[int64]sdk.Dec, + erc20CoinRates map[int64]map[string]sdk.Dec, + erc20Coins map[int64]map[string]fungibletypes.ForeignCoins, + currentCctxValue *sdk.Dec, + rateLimitValue sdk.Dec, +) bool { + amountZeta := convertCctxValue(chainID, cctx, gasCoinRates, erc20CoinRates, erc20Coins) + *currentCctxValue = currentCctxValue.Add(amountZeta) + return currentCctxValue.GT(rateLimitValue) +} diff --git a/x/crosschain/keeper/grpc_query_cctx_rate_limit_test.go b/x/crosschain/keeper/grpc_query_cctx_rate_limit_test.go new file mode 100644 index 0000000000..31939862b5 --- /dev/null +++ b/x/crosschain/keeper/grpc_query_cctx_rate_limit_test.go @@ -0,0 +1,182 @@ +package keeper_test + +import ( + "fmt" + "sort" + "testing" + + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/pkg/coin" + keepertest "github.com/zeta-chain/zetacore/testutil/keeper" + "github.com/zeta-chain/zetacore/testutil/sample" + "github.com/zeta-chain/zetacore/x/crosschain/keeper" + "github.com/zeta-chain/zetacore/x/crosschain/types" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" +) + +// createTestRateLimiterFlags creates a custom rate limiter flags +func createTestRateLimiterFlags( + zrc20ETH string, + zrc20BTC string, + zrc20USDT string, + ethRate string, + btcRate string, + usdtRate string, +) types.RateLimiterFlags { + var rateLimiterFlags = types.RateLimiterFlags{ + Enabled: true, + Window: 100, // 100 zeta blocks, 10 minutes + Rate: math.NewUint(1000), // 1000 ZETA + Conversions: []types.Conversion{ + // ETH + { + Zrc20: zrc20ETH, + Rate: sdk.MustNewDecFromStr(ethRate), + }, + // BTC + { + Zrc20: zrc20BTC, + Rate: sdk.MustNewDecFromStr(btcRate), + }, + // USDT + { + Zrc20: zrc20USDT, + Rate: sdk.MustNewDecFromStr(usdtRate), + }, + }, + } + return rateLimiterFlags +} + +// createCctxWithCopyTypeAndBlockRange +// - create 1 cctx per block from lowBlock to highBlock (inclusive) +// +// return created cctxs +func createCctxWithCopyTypeAndHeightRange( + t *testing.T, + ctx sdk.Context, + k keeper.Keeper, + zk keepertest.ZetaKeepers, + tss observertypes.TSS, + lowBlock uint64, + highBlock uint64, + chainID int64, + coinType coin.CoinType, + asset string, + amount uint64, + status types.CctxStatus, +) (cctxs []*types.CrossChainTx) { + // create 1 pending cctxs per block + for i := lowBlock; i <= highBlock; i++ { + nonce := i - 1 + cctx := sample.CrossChainTx(t, fmt.Sprintf("%d-%d", chainID, nonce)) + cctx.CctxStatus.Status = status + cctx.InboundTxParams.SenderChainId = chainID + cctx.InboundTxParams.CoinType = coinType + cctx.InboundTxParams.Asset = asset + cctx.InboundTxParams.InboundTxObservedExternalHeight = i + cctx.GetCurrentOutTxParam().Amount = sdk.NewUint(amount) + cctx.GetCurrentOutTxParam().OutboundTxTssNonce = nonce + k.SetCrossChainTx(ctx, *cctx) + zk.ObserverKeeper.SetNonceToCctx(ctx, observertypes.NonceToCctx{ + ChainId: chainID, + // #nosec G701 always in range for tests + Nonce: int64(nonce), + CctxIndex: cctx.Index, + Tss: tss.TssPubkey, + }) + cctxs = append(cctxs, cctx) + } + return cctxs +} + +// setPendingNonces sets the pending nonces for the given chainID +func setPendingNonces( + ctx sdk.Context, + zk keepertest.ZetaKeepers, + chainID int64, + nonceLow int64, + nonceHigh int64, + tssPubKey string, +) { + zk.ObserverKeeper.SetPendingNonces(ctx, observertypes.PendingNonces{ + ChainId: chainID, + NonceLow: nonceLow, + NonceHigh: nonceHigh, + Tss: tssPubKey, + }) +} + +// setupForeignCoins adds ETH, BTC, USDT to the foreign coins store +func setupForeignCoins( + t *testing.T, + ctx sdk.Context, + zk keepertest.ZetaKeepers, + zrc20ETH, zrc20BTC, zrc20USDT, assetUSDT string, +) { + // set foreign coins + fCoins := sample.ForeignCoinList(t, zrc20ETH, zrc20BTC, zrc20USDT, assetUSDT) + for _, fc := range fCoins { + zk.FungibleKeeper.SetForeignCoins(ctx, fc) + } +} + +func TestKeeper_ListPendingCctxWithinRateLimit(t *testing.T) { + // chain IDs + ethChainID := getValidEthChainID() + + // define cctx status + statusPending := types.CctxStatus_PendingOutbound + statusMined := types.CctxStatus_OutboundMined + + t.Run("should fail for empty req", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + _, err := k.ListPendingCctxWithinRateLimit(ctx, nil) + require.ErrorContains(t, err, "invalid request") + }) + t.Run("should use fallback query", func(t *testing.T) { + k, ctx, _, zk := keepertest.CrosschainKeeper(t) + + // Set TSS + tss := sample.Tss() + zk.ObserverKeeper.SetTSS(ctx, tss) + + // Set rate limiter flags as disabled + rateLimiterFlags := sample.RateLimiterFlags() + rateLimiterFlags.Enabled = false + k.SetRateLimiterFlags(ctx, rateLimiterFlags) + + // Create cctxs [0~999] and [1000~1199] for Eth chain, 0.001 ETH per cctx + _ = createCctxWithCopyTypeAndHeightRange(t, ctx, *k, zk, tss, 1, 1000, ethChainID, coin.CoinType_Gas, "", uint64(1e15), statusMined) + cctxETH := createCctxWithCopyTypeAndHeightRange(t, ctx, *k, zk, tss, 1001, 1200, ethChainID, coin.CoinType_Gas, "", uint64(1e15), statusPending) + + // Set Eth chain pending nonces which contains 100 missing cctxs + setPendingNonces(ctx, zk, ethChainID, 1100, 1200, tss.TssPubkey) + + // Query pending cctxs use small limit + res, err := k.ListPendingCctxWithinRateLimit(ctx, &types.QueryListPendingCctxWithinRateLimitRequest{Limit: 100}) + require.NoError(t, err) + require.Equal(t, 100, len(res.CrossChainTx)) + + // sort res.CrossChainTx by outbound nonce ascending so that we can compare with cctxETH + sort.Slice(res.CrossChainTx, func(i, j int) bool { + return res.CrossChainTx[i].GetCurrentOutTxParam().OutboundTxTssNonce < res.CrossChainTx[j].GetCurrentOutTxParam().OutboundTxTssNonce + }) + require.EqualValues(t, cctxETH[:100], res.CrossChainTx) + require.EqualValues(t, uint64(200), res.TotalPending) + + // Query pending cctxs use max limit + res, err = k.ListPendingCctxWithinRateLimit(ctx, &types.QueryListPendingCctxWithinRateLimitRequest{Limit: keeper.MaxPendingCctxs}) + require.NoError(t, err) + require.Equal(t, 200, len(res.CrossChainTx)) + + // sort res.CrossChainTx by outbound nonce ascending so that we can compare with cctxETH + sort.Slice(res.CrossChainTx, func(i, j int) bool { + return res.CrossChainTx[i].GetCurrentOutTxParam().OutboundTxTssNonce < res.CrossChainTx[j].GetCurrentOutTxParam().OutboundTxTssNonce + }) + require.EqualValues(t, cctxETH, res.CrossChainTx) + require.EqualValues(t, uint64(200), res.TotalPending) + }) +} diff --git a/x/crosschain/keeper/grpc_query_cctx_test.go b/x/crosschain/keeper/grpc_query_cctx_test.go index 59b0b68863..f530ef305b 100644 --- a/x/crosschain/keeper/grpc_query_cctx_test.go +++ b/x/crosschain/keeper/grpc_query_cctx_test.go @@ -66,19 +66,19 @@ func createCctxWithNonceRange( func TestKeeper_CctxListPending(t *testing.T) { t.Run("should fail for empty req", func(t *testing.T) { k, ctx, _, _ := keepertest.CrosschainKeeper(t) - _, err := k.CctxListPending(ctx, nil) + _, err := k.ListPendingCctx(ctx, nil) require.ErrorContains(t, err, "invalid request") }) - t.Run("should fail if limit is too high", func(t *testing.T) { + t.Run("should use max limit if limit is too high", func(t *testing.T) { k, ctx, _, _ := keepertest.CrosschainKeeper(t) - _, err := k.CctxListPending(ctx, &types.QueryListCctxPendingRequest{Limit: keeper.MaxPendingCctxs + 1}) - require.ErrorContains(t, err, "limit exceeds max limit of") + _, err := k.ListPendingCctx(ctx, &types.QueryListPendingCctxRequest{Limit: keeper.MaxPendingCctxs + 1}) + require.ErrorContains(t, err, "tss not found") }) t.Run("should fail if no TSS", func(t *testing.T) { k, ctx, _, _ := keepertest.CrosschainKeeper(t) - _, err := k.CctxListPending(ctx, &types.QueryListCctxPendingRequest{Limit: 1}) + _, err := k.ListPendingCctx(ctx, &types.QueryListPendingCctxRequest{Limit: 1}) require.ErrorContains(t, err, "tss not found") }) @@ -88,24 +88,24 @@ func TestKeeper_CctxListPending(t *testing.T) { // set TSS zk.ObserverKeeper.SetTSS(ctx, sample.Tss()) - _, err := k.CctxListPending(ctx, &types.QueryListCctxPendingRequest{Limit: 1}) + _, err := k.ListPendingCctx(ctx, &types.QueryListPendingCctxRequest{Limit: 1}) require.ErrorContains(t, err, "pending nonces not found") }) t.Run("can retrieve pending cctx in range", func(t *testing.T) { k, ctx, _, zk := keepertest.CrosschainKeeper(t) - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() tss := sample.Tss() zk.ObserverKeeper.SetTSS(ctx, tss) cctxs := createCctxWithNonceRange(t, ctx, *k, 1000, 2000, chainID, tss, zk) - res, err := k.CctxListPending(ctx, &types.QueryListCctxPendingRequest{ChainId: chainID, Limit: 100}) + res, err := k.ListPendingCctx(ctx, &types.QueryListPendingCctxRequest{ChainId: chainID, Limit: 100}) require.NoError(t, err) require.Equal(t, 100, len(res.CrossChainTx)) require.EqualValues(t, cctxs[0:100], res.CrossChainTx) require.EqualValues(t, uint64(1000), res.TotalPending) - res, err = k.CctxListPending(ctx, &types.QueryListCctxPendingRequest{ChainId: chainID}) + res, err = k.ListPendingCctx(ctx, &types.QueryListPendingCctxRequest{ChainId: chainID}) require.NoError(t, err) require.Equal(t, keeper.MaxPendingCctxs, len(res.CrossChainTx)) require.EqualValues(t, cctxs[0:keeper.MaxPendingCctxs], res.CrossChainTx) @@ -114,12 +114,12 @@ func TestKeeper_CctxListPending(t *testing.T) { t.Run("can retrieve pending cctx with range smaller than max", func(t *testing.T) { k, ctx, _, zk := keepertest.CrosschainKeeper(t) - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() tss := sample.Tss() zk.ObserverKeeper.SetTSS(ctx, tss) cctxs := createCctxWithNonceRange(t, ctx, *k, 1000, 1100, chainID, tss, zk) - res, err := k.CctxListPending(ctx, &types.QueryListCctxPendingRequest{ChainId: chainID}) + res, err := k.ListPendingCctx(ctx, &types.QueryListPendingCctxRequest{ChainId: chainID}) require.NoError(t, err) require.Equal(t, 100, len(res.CrossChainTx)) require.EqualValues(t, cctxs, res.CrossChainTx) @@ -128,7 +128,7 @@ func TestKeeper_CctxListPending(t *testing.T) { t.Run("can retrieve pending cctx with pending cctx below nonce low", func(t *testing.T) { k, ctx, _, zk := keepertest.CrosschainKeeper(t) - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() tss := sample.Tss() zk.ObserverKeeper.SetTSS(ctx, tss) cctxs := createCctxWithNonceRange(t, ctx, *k, 1000, 2000, chainID, tss, zk) @@ -144,7 +144,7 @@ func TestKeeper_CctxListPending(t *testing.T) { cctx2.CctxStatus.Status = types.CctxStatus_PendingOutbound k.SetCrossChainTx(ctx, cctx2) - res, err := k.CctxListPending(ctx, &types.QueryListCctxPendingRequest{ChainId: chainID, Limit: 100}) + res, err := k.ListPendingCctx(ctx, &types.QueryListPendingCctxRequest{ChainId: chainID, Limit: 100}) require.NoError(t, err) require.Equal(t, 100, len(res.CrossChainTx)) @@ -157,7 +157,7 @@ func TestKeeper_CctxListPending(t *testing.T) { t.Run("error if some before low nonce are missing", func(t *testing.T) { k, ctx, _, zk := keepertest.CrosschainKeeper(t) - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() tss := sample.Tss() zk.ObserverKeeper.SetTSS(ctx, tss) cctxs := createCctxWithNonceRange(t, ctx, *k, 1000, 2000, chainID, tss, zk) @@ -173,7 +173,7 @@ func TestKeeper_CctxListPending(t *testing.T) { cctx2.CctxStatus.Status = types.CctxStatus_PendingOutbound k.SetCrossChainTx(ctx, cctx2) - res, err := k.CctxListPending(ctx, &types.QueryListCctxPendingRequest{ChainId: chainID, Limit: 100}) + res, err := k.ListPendingCctx(ctx, &types.QueryListPendingCctxRequest{ChainId: chainID, Limit: 100}) require.NoError(t, err) require.Equal(t, 100, len(res.CrossChainTx)) @@ -226,7 +226,7 @@ func TestKeeper_CctxByNonce(t *testing.T) { t.Run("should error if nonce to cctx not found", func(t *testing.T) { k, ctx, _, zk := keepertest.CrosschainKeeper(t) - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() tss := sample.Tss() zk.ObserverKeeper.SetTSS(ctx, tss) @@ -239,7 +239,7 @@ func TestKeeper_CctxByNonce(t *testing.T) { t.Run("should error if crosschain tx not found", func(t *testing.T) { k, ctx, _, zk := keepertest.CrosschainKeeper(t) - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() tss := sample.Tss() zk.ObserverKeeper.SetTSS(ctx, tss) nonce := 1000 @@ -262,7 +262,7 @@ func TestKeeper_CctxByNonce(t *testing.T) { t.Run("should return if crosschain tx found", func(t *testing.T) { k, ctx, _, zk := keepertest.CrosschainKeeper(t) - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() tss := sample.Tss() zk.ObserverKeeper.SetTSS(ctx, tss) nonce := 1000 diff --git a/x/crosschain/keeper/msg_server_add_to_intx_tracker_test.go b/x/crosschain/keeper/msg_server_add_to_intx_tracker_test.go index a18d7e737a..9c0547e9fb 100644 --- a/x/crosschain/keeper/msg_server_add_to_intx_tracker_test.go +++ b/x/crosschain/keeper/msg_server_add_to_intx_tracker_test.go @@ -36,7 +36,7 @@ func TestMsgServer_AddToInTxTracker(t *testing.T) { observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) txHash := "string" - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() _, err := msgServer.AddToInTxTracker(ctx, &types.MsgAddToInTxTracker{ Creator: nonAdmin, @@ -63,7 +63,7 @@ func TestMsgServer_AddToInTxTracker(t *testing.T) { observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(nil) txHash := "string" - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() _, err := msgServer.AddToInTxTracker(ctx, &types.MsgAddToInTxTracker{ Creator: sample.AccAddress(), @@ -95,7 +95,7 @@ func TestMsgServer_AddToInTxTracker(t *testing.T) { observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) txHash := "string" - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() setSupportedChain(ctx, zk, chainID) _, err := msgServer.AddToInTxTracker(ctx, &types.MsgAddToInTxTracker{ @@ -128,7 +128,7 @@ func TestMsgServer_AddToInTxTracker(t *testing.T) { observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(true) txHash := "string" - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() _, err := msgServer.AddToInTxTracker(ctx, &types.MsgAddToInTxTracker{ Creator: admin, @@ -163,7 +163,7 @@ func TestMsgServer_AddToInTxTracker(t *testing.T) { lightclientMock.On("VerifyProof", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errors.New("error")) txHash := "string" - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() _, err := msgServer.AddToInTxTracker(ctx, &types.MsgAddToInTxTracker{ Creator: admin, @@ -197,7 +197,7 @@ func TestMsgServer_AddToInTxTracker(t *testing.T) { observerMock.On("GetChainParamsByChainID", mock.Anything, mock.Anything).Return(nil, false) txHash := "string" - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() _, err := msgServer.AddToInTxTracker(ctx, &types.MsgAddToInTxTracker{ Creator: admin, @@ -232,7 +232,7 @@ func TestMsgServer_AddToInTxTracker(t *testing.T) { observerMock.On("GetTssAddress", mock.Anything, mock.Anything).Return(nil, errors.New("error")) txHash := "string" - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() setSupportedChain(ctx, zk, chainID) _, err := msgServer.AddToInTxTracker(ctx, &types.MsgAddToInTxTracker{ @@ -272,7 +272,7 @@ func TestMsgServer_AddToInTxTracker(t *testing.T) { lightclientMock.On("VerifyProof", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]byte("invalid"), nil) txHash := "string" - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() setSupportedChain(ctx, zk, chainID) _, err := msgServer.AddToInTxTracker(ctx, &types.MsgAddToInTxTracker{ diff --git a/x/crosschain/keeper/msg_server_add_to_outtx_tracker.go b/x/crosschain/keeper/msg_server_add_to_outtx_tracker.go index 9031d0bfe5..4f149a901f 100644 --- a/x/crosschain/keeper/msg_server_add_to_outtx_tracker.go +++ b/x/crosschain/keeper/msg_server_add_to_outtx_tracker.go @@ -41,7 +41,7 @@ func (k msgServer) AddToOutTxTracker(goCtx context.Context, msg *types.MsgAddToO } // tracker submission is only allowed when the cctx is pending - if !IsPending(*cctx.CrossChainTx) { + if !IsPending(cctx.CrossChainTx) { // garbage tracker (for any reason) is harmful to outTx observation and should be removed if it exists // it if does not exist, RemoveOutTxTracker is a no-op k.RemoveOutTxTracker(ctx, msg.ChainId, msg.Nonce) diff --git a/x/crosschain/keeper/msg_server_migrate_tss_funds_test.go b/x/crosschain/keeper/msg_server_migrate_tss_funds_test.go index f13a0065ae..5865c6ccca 100644 --- a/x/crosschain/keeper/msg_server_migrate_tss_funds_test.go +++ b/x/crosschain/keeper/msg_server_migrate_tss_funds_test.go @@ -89,7 +89,7 @@ func TestKeeper_MigrateTSSFundsForChain(t *testing.T) { keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupAdmin, true) msgServer := keeper.NewMsgServerImpl(*k) - chain := getValidEthChain(t) + chain := getValidEthChain() amount := sdkmath.NewUintFromString("10000000000000000000") indexString, _ := setupTssMigrationParams(zk, k, ctx, *chain, amount, true, true) gp, found := k.GetMedianGasPriceInUint(ctx, chain.ChainId) @@ -149,7 +149,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupAdmin, false) msgServer := keeper.NewMsgServerImpl(*k) - chain := getValidEthChain(t) + chain := getValidEthChain() amount := sdkmath.NewUintFromString("10000000000000000000") _, err := msgServer.MigrateTssFunds(ctx, &crosschaintypes.MsgMigrateTssFunds{ Creator: admin, @@ -172,7 +172,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) observerMock.On("IsInboundEnabled", mock.Anything).Return(true) msgServer := keeper.NewMsgServerImpl(*k) - chain := getValidEthChain(t) + chain := getValidEthChain() amount := sdkmath.NewUintFromString("10000000000000000000") _, err := msgServer.MigrateTssFunds(ctx, &crosschaintypes.MsgMigrateTssFunds{ Creator: admin, @@ -197,7 +197,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { observerMock.On("GetTSS", mock.Anything).Return(observertypes.TSS{}, false) msgServer := keeper.NewMsgServerImpl(*k) - chain := getValidEthChain(t) + chain := getValidEthChain() amount := sdkmath.NewUintFromString("10000000000000000000") _, err := msgServer.MigrateTssFunds(ctx, &crosschaintypes.MsgMigrateTssFunds{ Creator: admin, @@ -223,7 +223,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { observerMock.On("GetAllTSS", mock.Anything).Return([]observertypes.TSS{}) msgServer := keeper.NewMsgServerImpl(*k) - chain := getValidEthChain(t) + chain := getValidEthChain() amount := sdkmath.NewUintFromString("10000000000000000000") _, err := msgServer.MigrateTssFunds(ctx, &crosschaintypes.MsgMigrateTssFunds{ Creator: admin, @@ -250,7 +250,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { observerMock.On("GetAllTSS", mock.Anything).Return([]observertypes.TSS{tss}) msgServer := keeper.NewMsgServerImpl(*k) - chain := getValidEthChain(t) + chain := getValidEthChain() amount := sdkmath.NewUintFromString("10000000000000000000") _, err := msgServer.MigrateTssFunds(ctx, &crosschaintypes.MsgMigrateTssFunds{ Creator: admin, @@ -280,7 +280,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { observerMock.On("GetAllTSS", mock.Anything).Return([]observertypes.TSS{tss2}) msgServer := keeper.NewMsgServerImpl(*k) - chain := getValidEthChain(t) + chain := getValidEthChain() amount := sdkmath.NewUintFromString("10000000000000000000") _, err := msgServer.MigrateTssFunds(ctx, &crosschaintypes.MsgMigrateTssFunds{ Creator: admin, @@ -311,7 +311,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { observerMock.On("GetPendingNonces", mock.Anything, mock.Anything, mock.Anything).Return(observertypes.PendingNonces{}, false) msgServer := keeper.NewMsgServerImpl(*k) - chain := getValidEthChain(t) + chain := getValidEthChain() amount := sdkmath.NewUintFromString("10000000000000000000") _, err := msgServer.MigrateTssFunds(ctx, &crosschaintypes.MsgMigrateTssFunds{ Creator: admin, @@ -331,7 +331,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupAdmin, true) msgServer := keeper.NewMsgServerImpl(*k) - chain := getValidEthChain(t) + chain := getValidEthChain() amount := sdkmath.NewUintFromString("10000000000000000000") indexString, _ := setupTssMigrationParams(zk, k, ctx, *chain, amount, true, true) _, err := msgServer.MigrateTssFunds(ctx, &crosschaintypes.MsgMigrateTssFunds{ @@ -359,7 +359,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupAdmin, true) msgServer := keeper.NewMsgServerImpl(*k) - chain := getValidEthChain(t) + chain := getValidEthChain() amount := sdkmath.NewUintFromString("100") indexString, _ := setupTssMigrationParams(zk, k, ctx, *chain, amount, true, true) _, err := msgServer.MigrateTssFunds(ctx, &crosschaintypes.MsgMigrateTssFunds{ @@ -384,7 +384,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupAdmin, true) msgServer := keeper.NewMsgServerImpl(*k) - chain := getValidEthChain(t) + chain := getValidEthChain() amount := sdkmath.NewUintFromString("10000000000000000000") indexString, _ := setupTssMigrationParams(zk, k, ctx, *chain, amount, false, true) _, err := msgServer.MigrateTssFunds(ctx, &crosschaintypes.MsgMigrateTssFunds{ @@ -409,7 +409,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupAdmin, true) msgServer := keeper.NewMsgServerImpl(*k) - chain := getValidEthChain(t) + chain := getValidEthChain() amount := sdkmath.NewUintFromString("10000000000000000000") indexString, tssPubkey := setupTssMigrationParams(zk, k, ctx, *chain, amount, true, true) k.GetObserverKeeper().SetPendingNonces(ctx, observertypes.PendingNonces{ @@ -441,7 +441,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupAdmin, true) msgServer := keeper.NewMsgServerImpl(*k) - chain := getValidEthChain(t) + chain := getValidEthChain() amount := sdkmath.NewUintFromString("10000000000000000000") indexString, tssPubkey := setupTssMigrationParams(zk, k, ctx, *chain, amount, true, true) k.GetObserverKeeper().SetPendingNonces(ctx, observertypes.PendingNonces{ @@ -482,7 +482,7 @@ func TestMsgServer_MigrateTssFunds(t *testing.T) { keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupAdmin, true) msgServer := keeper.NewMsgServerImpl(*k) - chain := getValidEthChain(t) + chain := getValidEthChain() amount := sdkmath.NewUintFromString("10000000000000000000") indexString, _ := setupTssMigrationParams(zk, k, ctx, *chain, amount, false, false) currentTss, found := k.GetObserverKeeper().GetTSS(ctx) diff --git a/x/crosschain/keeper/msg_server_refund_aborted_tx_test.go b/x/crosschain/keeper/msg_server_refund_aborted_tx_test.go index f5615c8963..0b54a93c69 100644 --- a/x/crosschain/keeper/msg_server_refund_aborted_tx_test.go +++ b/x/crosschain/keeper/msg_server_refund_aborted_tx_test.go @@ -42,7 +42,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { }) admin := sample.AccAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) @@ -81,7 +81,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { }) admin := sample.AccAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) @@ -120,7 +120,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { }) admin := sample.AccAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) @@ -160,7 +160,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { }) admin := sample.AccAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) @@ -192,7 +192,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { }) admin := sample.AccAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) @@ -224,7 +224,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { }) admin := sample.AccAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) @@ -263,7 +263,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { }) admin := sample.AccAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() asset := sample.EthAddress().String() authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) @@ -352,7 +352,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { }) admin := sample.AccAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) @@ -383,7 +383,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { }) admin := sample.AccAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) @@ -414,7 +414,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { }) admin := sample.AccAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) @@ -447,7 +447,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { }) admin := sample.AccAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) @@ -507,7 +507,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { }) admin := sample.AccAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) @@ -537,7 +537,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { }) admin := sample.AccAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, false) diff --git a/x/crosschain/keeper/msg_server_vote_inbound_tx_test.go b/x/crosschain/keeper/msg_server_vote_inbound_tx_test.go index f8d6a4bcb8..379f24741b 100644 --- a/x/crosschain/keeper/msg_server_vote_inbound_tx_test.go +++ b/x/crosschain/keeper/msg_server_vote_inbound_tx_test.go @@ -312,7 +312,7 @@ func TestKeeper_SaveInbound(t *testing.T) { zk.ObserverKeeper.SetTSS(ctx, sample.Tss()) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() cctx := GetERC20Cctx(t, receiver, *senderChain, "", amount) eventIndex := sample.Uint64InRange(1, 100) k.SaveInbound(ctx, cctx, eventIndex) @@ -326,7 +326,7 @@ func TestKeeper_SaveInbound(t *testing.T) { k, ctx, _, zk := keepertest.CrosschainKeeper(t) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() cctx := GetERC20Cctx(t, receiver, *senderChain, "", amount) hash := sample.Hash() cctx.InboundTxParams.InboundTxObservedHash = hash.String() diff --git a/x/crosschain/keeper/msg_server_vote_outbound_tx_test.go b/x/crosschain/keeper/msg_server_vote_outbound_tx_test.go index fa9884f25a..11ea50a514 100644 --- a/x/crosschain/keeper/msg_server_vote_outbound_tx_test.go +++ b/x/crosschain/keeper/msg_server_vote_outbound_tx_test.go @@ -129,7 +129,7 @@ func TestKeeper_VoteOnObservedOutboundTx(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" observer := sample.AccAddress() tss := sample.Tss() @@ -180,7 +180,7 @@ func TestKeeper_VoteOnObservedOutboundTx(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" observer := sample.AccAddress() tss := sample.Tss() @@ -239,7 +239,7 @@ func TestKeeper_VoteOnObservedOutboundTx(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" observer := sample.AccAddress() tss := sample.Tss() @@ -302,7 +302,7 @@ func TestKeeper_VoteOnObservedOutboundTx(t *testing.T) { fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" observer := sample.AccAddress() tss := sample.Tss() @@ -354,7 +354,7 @@ func TestKeeper_VoteOnObservedOutboundTx(t *testing.T) { // Setup mock data receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) @@ -401,7 +401,7 @@ func TestKeeper_VoteOnObservedOutboundTx(t *testing.T) { // Setup mock data receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) diff --git a/x/crosschain/keeper/msg_server_whitelist_erc20_test.go b/x/crosschain/keeper/msg_server_whitelist_erc20_test.go index 2d193e8f5b..6db8243405 100644 --- a/x/crosschain/keeper/msg_server_whitelist_erc20_test.go +++ b/x/crosschain/keeper/msg_server_whitelist_erc20_test.go @@ -26,7 +26,7 @@ func TestKeeper_WhitelistERC20(t *testing.T) { msgServer := crosschainkeeper.NewMsgServerImpl(*k) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() setSupportedChain(ctx, zk, chainID) admin := sample.AccAddress() @@ -104,7 +104,7 @@ func TestKeeper_WhitelistERC20(t *testing.T) { _, err := msgServer.WhitelistERC20(ctx, &types.MsgWhitelistERC20{ Creator: admin, Erc20Address: sample.EthAddress().Hex(), - ChainId: getValidEthChainID(t), + ChainId: getValidEthChainID(), Name: "foo", Symbol: "FOO", Decimals: 18, @@ -128,7 +128,7 @@ func TestKeeper_WhitelistERC20(t *testing.T) { _, err := msgServer.WhitelistERC20(ctx, &types.MsgWhitelistERC20{ Creator: admin, Erc20Address: "invalid", - ChainId: getValidEthChainID(t), + ChainId: getValidEthChainID(), Name: "foo", Symbol: "FOO", Decimals: 18, @@ -149,7 +149,7 @@ func TestKeeper_WhitelistERC20(t *testing.T) { authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() asset := sample.EthAddress().Hex() fc := sample.ForeignCoins(t, sample.EthAddress().Hex()) fc.Asset = asset @@ -176,7 +176,7 @@ func TestKeeper_WhitelistERC20(t *testing.T) { msgServer := crosschainkeeper.NewMsgServerImpl(*k) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() admin := sample.AccAddress() authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) diff --git a/x/crosschain/keeper/process_inbound_test.go b/x/crosschain/keeper/process_inbound_test.go index ec3bcaea94..3e86cd68c5 100644 --- a/x/crosschain/keeper/process_inbound_test.go +++ b/x/crosschain/keeper/process_inbound_test.go @@ -83,7 +83,7 @@ func TestKeeper_ProcessInboundZEVMDeposit(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() errDeposit := fmt.Errorf("deposit failed") // Setup expected calls @@ -113,7 +113,7 @@ func TestKeeper_ProcessInboundZEVMDeposit(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" errDeposit := fmt.Errorf("deposit failed") @@ -145,7 +145,7 @@ func TestKeeper_ProcessInboundZEVMDeposit(t *testing.T) { fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" // Setup expected calls @@ -182,7 +182,7 @@ func TestKeeper_ProcessInboundZEVMDeposit(t *testing.T) { fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" // Setup expected calls @@ -220,7 +220,7 @@ func TestKeeper_ProcessInboundZEVMDeposit(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" errDeposit := fmt.Errorf("deposit failed") @@ -260,7 +260,7 @@ func TestKeeper_ProcessInboundZEVMDeposit(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" errDeposit := fmt.Errorf("deposit failed") @@ -299,7 +299,7 @@ func TestKeeper_ProcessInboundZEVMDeposit(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" errDeposit := fmt.Errorf("deposit failed") @@ -335,7 +335,7 @@ func TestKeeper_ProcessInboundProcessCrosschainMsgPassing(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - receiverChain := getValidEthChain(t) + receiverChain := getValidEthChain() // mock successful PayGasAndUpdateCctx keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *receiverChain, "") @@ -360,7 +360,7 @@ func TestKeeper_ProcessInboundProcessCrosschainMsgPassing(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - receiverChain := getValidEthChain(t) + receiverChain := getValidEthChain() // mock unsuccessful PayGasAndUpdateCctx observerMock.On("GetSupportedChainFromChainID", mock.Anything, receiverChain.ChainId). @@ -384,7 +384,7 @@ func TestKeeper_ProcessInboundProcessCrosschainMsgPassing(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - receiverChain := getValidEthChain(t) + receiverChain := getValidEthChain() // mock successful PayGasAndUpdateCctx keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *receiverChain, "") diff --git a/x/crosschain/keeper/process_outbound_test.go b/x/crosschain/keeper/process_outbound_test.go index 2bd17818c6..b4dbbef200 100644 --- a/x/crosschain/keeper/process_outbound_test.go +++ b/x/crosschain/keeper/process_outbound_test.go @@ -137,7 +137,7 @@ func TestKeeper_ProcessFailedOutbound(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" // mock successful GetRevertGasLimit for ERC20 @@ -169,7 +169,7 @@ func TestKeeper_ProcessFailedOutbound(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" // mock successful GetRevertGasLimit for ERC20 @@ -201,7 +201,7 @@ func TestKeeper_ProcessFailedOutbound(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" // mock successful GetRevertGasLimit for ERC20 @@ -232,7 +232,7 @@ func TestKeeper_ProcessFailedOutbound(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" // mock successful GetRevertGasLimit for ERC20 @@ -258,7 +258,7 @@ func TestKeeper_ProcessFailedOutbound(t *testing.T) { fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" // mock failed GetRevertGasLimit for ERC20 @@ -324,7 +324,7 @@ func TestKeeper_ProcessOutbound(t *testing.T) { fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) @@ -353,7 +353,7 @@ func TestKeeper_ProcessOutbound(t *testing.T) { fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) @@ -381,7 +381,7 @@ func TestKeeper_ProcessOutbound(t *testing.T) { observerMock := keepertest.GetCrosschainObserverMock(t, k) receiver := sample.EthAddress() amount := big.NewInt(42) - senderChain := getValidEthChain(t) + senderChain := getValidEthChain() asset := "" cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) diff --git a/x/crosschain/keeper/rate_limiter_flags.go b/x/crosschain/keeper/rate_limiter_flags.go index d0d7e2febc..324c636f93 100644 --- a/x/crosschain/keeper/rate_limiter_flags.go +++ b/x/crosschain/keeper/rate_limiter_flags.go @@ -1,8 +1,11 @@ package keeper import ( + "strings" + "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/zeta-chain/zetacore/pkg/coin" "github.com/zeta-chain/zetacore/x/crosschain/types" ) @@ -25,3 +28,34 @@ func (k Keeper) GetRateLimiterFlags(ctx sdk.Context) (val types.RateLimiterFlags k.cdc.MustUnmarshal(b, &val) return val, true } + +// GetRateLimiterRates returns two maps of foreign coins and their rates +// The 1st map: foreign chain id -> gas coin rate +// The 2nd map: foreign chain id -> erc20 asset -> erc20 coin rate +func (k Keeper) GetRateLimiterRates(ctx sdk.Context) (map[int64]sdk.Dec, map[int64]map[string]sdk.Dec) { + rateLimiterFlags, _ := k.GetRateLimiterFlags(ctx) + + // the result maps + gasCoinRates := make(map[int64]sdk.Dec) + erc20CoinRates := make(map[int64]map[string]sdk.Dec) + + // loop through the rate limiter flags to get the rate + for _, conversion := range rateLimiterFlags.Conversions { + fCoin, found := k.fungibleKeeper.GetForeignCoins(ctx, conversion.Zrc20) + if !found { + continue + } + + chainID := fCoin.ForeignChainId + switch fCoin.CoinType { + case coin.CoinType_Gas: + gasCoinRates[chainID] = conversion.Rate + case coin.CoinType_ERC20: + if _, found := erc20CoinRates[chainID]; !found { + erc20CoinRates[chainID] = make(map[string]sdk.Dec) + } + erc20CoinRates[chainID][strings.ToLower(fCoin.Asset)] = conversion.Rate + } + } + return gasCoinRates, erc20CoinRates +} diff --git a/x/crosschain/keeper/rate_limiter_flags_test.go b/x/crosschain/keeper/rate_limiter_flags_test.go index 044d02bc67..0b8010031d 100644 --- a/x/crosschain/keeper/rate_limiter_flags_test.go +++ b/x/crosschain/keeper/rate_limiter_flags_test.go @@ -1,11 +1,16 @@ package keeper_test import ( + "strings" "testing" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/pkg/chains" + "github.com/zeta-chain/zetacore/pkg/coin" keepertest "github.com/zeta-chain/zetacore/testutil/keeper" "github.com/zeta-chain/zetacore/testutil/sample" + "github.com/zeta-chain/zetacore/x/crosschain/types" ) func TestKeeper_GetRateLimiterFlags(t *testing.T) { @@ -22,3 +27,65 @@ func TestKeeper_GetRateLimiterFlags(t *testing.T) { require.True(t, found) require.Equal(t, flags, r) } + +func TestKeeper_GetRateLimiterRates(t *testing.T) { + k, ctx, _, zk := keepertest.CrosschainKeeper(t) + + // create test flags + zrc20GasAddr := sample.EthAddress().Hex() + zrc20ERC20Addr1 := sample.EthAddress().Hex() + zrc20ERC20Addr2 := sample.EthAddress().Hex() + flags := types.RateLimiterFlags{ + Rate: sdk.NewUint(100), + Conversions: []types.Conversion{ + { + Zrc20: zrc20GasAddr, + Rate: sdk.NewDec(1), + }, + { + Zrc20: zrc20ERC20Addr1, + Rate: sdk.NewDec(2), + }, + { + Zrc20: zrc20ERC20Addr2, + Rate: sdk.NewDec(3), + }, + }, + } + + chainID := chains.GoerliLocalnetChain().ChainId + + // add gas coin + fcGas := sample.ForeignCoins(t, zrc20GasAddr) + fcGas.CoinType = coin.CoinType_Gas + fcGas.ForeignChainId = chainID + zk.FungibleKeeper.SetForeignCoins(ctx, fcGas) + + // add two erc20 coins + asset1 := sample.EthAddress().Hex() + fcERC20 := sample.ForeignCoins(t, zrc20ERC20Addr1) + fcERC20.Asset = asset1 + fcERC20.ForeignChainId = chainID + zk.FungibleKeeper.SetForeignCoins(ctx, fcERC20) + + asset2 := sample.EthAddress().Hex() + fcERC20 = sample.ForeignCoins(t, zrc20ERC20Addr2) + fcERC20.Asset = asset2 + fcERC20.ForeignChainId = chainID + zk.FungibleKeeper.SetForeignCoins(ctx, fcERC20) + + // set flags + k.SetRateLimiterFlags(ctx, flags) + r, found := k.GetRateLimiterFlags(ctx) + require.True(t, found) + require.Equal(t, flags, r) + + // get rates + gasRates, erc20Rates := k.GetRateLimiterRates(ctx) + require.Equal(t, 1, len(gasRates)) + require.Equal(t, 1, len(erc20Rates)) + require.Equal(t, sdk.NewDec(1), gasRates[chainID]) + require.Equal(t, 2, len(erc20Rates[chainID])) + require.Equal(t, sdk.NewDec(2), erc20Rates[chainID][strings.ToLower(asset1)]) + require.Equal(t, sdk.NewDec(3), erc20Rates[chainID][strings.ToLower(asset2)]) +} diff --git a/x/crosschain/keeper/refund_test.go b/x/crosschain/keeper/refund_test.go index 09732bd23a..5f00310be3 100644 --- a/x/crosschain/keeper/refund_test.go +++ b/x/crosschain/keeper/refund_test.go @@ -23,7 +23,7 @@ func TestKeeper_RefundAmountOnZetaChainGas(t *testing.T) { k, ctx, sdkk, zk := keepertest.CrosschainKeeper(t) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) sender := sample.EthAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) zrc20 := setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, chainID, "foobar", "foobar") @@ -54,7 +54,7 @@ func TestKeeper_RefundAmountOnZetaChainGas(t *testing.T) { fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) sender := sample.EthAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() fungibleMock.On("GetGasCoinForForeignCoin", mock.Anything, mock.Anything).Return(fungibletypes.ForeignCoins{ Zrc20ContractAddress: "0x", @@ -84,7 +84,7 @@ func TestKeeper_RefundAmountOnZetaChainGas(t *testing.T) { fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) sender := sample.EthAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() fungibleMock.On("GetGasCoinForForeignCoin", mock.Anything, mock.Anything).Return(fungibletypes.ForeignCoins{ Zrc20ContractAddress: sample.EthAddress().Hex(), @@ -113,7 +113,7 @@ func TestKeeper_RefundAmountOnZetaChainGas(t *testing.T) { k, ctx, sdkk, zk := keepertest.CrosschainKeeper(t) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) sender := sample.EthAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) zrc20 := setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, chainID, "foobar", "foobar") @@ -137,7 +137,7 @@ func TestKeeper_RefundAmountOnZetaChainGas(t *testing.T) { k, ctx, sdkk, zk := keepertest.CrosschainKeeper(t) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) sender := sample.EthAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) err := k.RefundAmountOnZetaChainGas(ctx, types.CrossChainTx{ InboundTxParams: &types.InboundTxParams{ @@ -160,7 +160,7 @@ func TestKeeper_RefundAmountOnZetaChainGas(t *testing.T) { k, ctx, sdkk, zk := keepertest.CrosschainKeeper(t) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) sender := sample.EthAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) _ = setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, chainID, "foobar", "foobar") @@ -188,7 +188,7 @@ func TestKeeper_RefundAmountOnZetaChainZeta(t *testing.T) { k, ctx, sdkk, _ := keepertest.CrosschainKeeper(t) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) sender := sample.EthAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() err := k.RefundAmountOnZetaChainZeta(ctx, types.CrossChainTx{ InboundTxParams: &types.InboundTxParams{ @@ -240,7 +240,7 @@ func TestKeeper_RefundAmountOnZetaChainZeta(t *testing.T) { fungibleMock.On("DepositCoinZeta", mock.Anything, mock.Anything, mock.Anything).Return(errors.New("err")) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) sender := sample.EthAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() err := k.RefundAmountOnZetaChainZeta(ctx, types.CrossChainTx{ InboundTxParams: &types.InboundTxParams{ @@ -263,7 +263,7 @@ func TestKeeper_RefundAmountOnZetaChainZeta(t *testing.T) { k, ctx, sdkk, _ := keepertest.CrosschainKeeper(t) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) sender := sample.EthAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() err := k.RefundAmountOnZetaChainZeta(ctx, types.CrossChainTx{ InboundTxParams: &types.InboundTxParams{ @@ -284,7 +284,7 @@ func TestKeeper_RefundAmountOnZetaChainZeta(t *testing.T) { k, ctx, _, _ := keepertest.CrosschainKeeper(t) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) sender := sample.EthAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() err := k.RefundAmountOnZetaChainZeta(ctx, types.CrossChainTx{ InboundTxParams: &types.InboundTxParams{ @@ -310,7 +310,7 @@ func TestKeeper_RefundAmountOnZetaChainERC20(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) asset := sample.EthAddress().String() sender := sample.EthAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() // deploy zrc20 deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) @@ -376,7 +376,7 @@ func TestKeeper_RefundAmountOnZetaChainERC20(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) asset := sample.EthAddress().String() sender := sample.EthAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() err := k.RefundAmountOnZetaChainERC20(ctx, types.CrossChainTx{ InboundTxParams: &types.InboundTxParams{ @@ -403,7 +403,7 @@ func TestKeeper_RefundAmountOnZetaChainERC20(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) asset := sample.EthAddress().String() sender := sample.EthAddress() - chainID := getValidEthChainID(t) + chainID := getValidEthChainID() fungibleMock.On("GetForeignCoinFromAsset", mock.Anything, mock.Anything, mock.Anything).Return(fungibletypes.ForeignCoins{ Zrc20ContractAddress: sample.EthAddress().Hex(), @@ -462,7 +462,7 @@ func TestKeeper_RefundAmountOnZetaChainERC20(t *testing.T) { err = k.RefundAmountOnZetaChainERC20(ctx, types.CrossChainTx{ InboundTxParams: &types.InboundTxParams{ CoinType: coin.CoinType_ERC20, - SenderChainId: getValidEthChainID(t), + SenderChainId: getValidEthChainID(), Sender: sample.EthAddress().String(), Amount: math.Uint{}, }}, @@ -473,7 +473,7 @@ func TestKeeper_RefundAmountOnZetaChainERC20(t *testing.T) { err = k.RefundAmountOnZetaChainERC20(ctx, types.CrossChainTx{ InboundTxParams: &types.InboundTxParams{ CoinType: coin.CoinType_ERC20, - SenderChainId: getValidEthChainID(t), + SenderChainId: getValidEthChainID(), Sender: sample.EthAddress().String(), Amount: math.ZeroUint(), }}, @@ -485,7 +485,7 @@ func TestKeeper_RefundAmountOnZetaChainERC20(t *testing.T) { err = k.RefundAmountOnZetaChainERC20(ctx, types.CrossChainTx{ InboundTxParams: &types.InboundTxParams{ CoinType: coin.CoinType_ERC20, - SenderChainId: getValidEthChainID(t), + SenderChainId: getValidEthChainID(), Sender: sample.EthAddress().String(), Asset: sample.EthAddress().String(), Amount: math.NewUint(42), diff --git a/x/crosschain/keeper/utils_test.go b/x/crosschain/keeper/utils_test.go index 732ec5d0bd..3b3ab6967c 100644 --- a/x/crosschain/keeper/utils_test.go +++ b/x/crosschain/keeper/utils_test.go @@ -22,12 +22,12 @@ import ( ) // getValidEthChainID get a valid eth chain id -func getValidEthChainID(t *testing.T) int64 { - return getValidEthChain(t).ChainId +func getValidEthChainID() int64 { + return getValidEthChain().ChainId } // getValidEthChain get a valid eth chain -func getValidEthChain(_ *testing.T) *chains.Chain { +func getValidEthChain() *chains.Chain { goerli := chains.GoerliLocalnetChain() return &goerli } diff --git a/x/crosschain/types/expected_keepers.go b/x/crosschain/types/expected_keepers.go index ed5aacb267..af4f580794 100644 --- a/x/crosschain/types/expected_keepers.go +++ b/x/crosschain/types/expected_keepers.go @@ -90,11 +90,13 @@ type ObserverKeeper interface { ) (bool, bool, observertypes.Ballot, string, error) GetSupportedChainFromChainID(ctx sdk.Context, chainID int64) *chains.Chain GetSupportedChains(ctx sdk.Context) []*chains.Chain + GetSupportedForeignChains(ctx sdk.Context) []*chains.Chain } type FungibleKeeper interface { GetForeignCoins(ctx sdk.Context, zrc20Addr string) (val fungibletypes.ForeignCoins, found bool) GetAllForeignCoins(ctx sdk.Context) (list []fungibletypes.ForeignCoins) + GetAllForeignERC20CoinMap(ctx sdk.Context) map[int64]map[string]fungibletypes.ForeignCoins SetForeignCoins(ctx sdk.Context, foreignCoins fungibletypes.ForeignCoins) GetAllForeignCoinsForChain(ctx sdk.Context, foreignChainID int64) (list []fungibletypes.ForeignCoins) GetForeignCoinFromAsset(ctx sdk.Context, asset string, chainID int64) (fungibletypes.ForeignCoins, bool) diff --git a/x/crosschain/types/query.pb.go b/x/crosschain/types/query.pb.go index 2add2ae2ae..879dcce901 100644 --- a/x/crosschain/types/query.pb.go +++ b/x/crosschain/types/query.pb.go @@ -1483,23 +1483,23 @@ func (m *QueryAllCctxResponse) GetPagination() *query.PageResponse { return nil } -type QueryListCctxPendingRequest struct { +type QueryListPendingCctxRequest struct { ChainId int64 `protobuf:"varint,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` Limit uint32 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"` } -func (m *QueryListCctxPendingRequest) Reset() { *m = QueryListCctxPendingRequest{} } -func (m *QueryListCctxPendingRequest) String() string { return proto.CompactTextString(m) } -func (*QueryListCctxPendingRequest) ProtoMessage() {} -func (*QueryListCctxPendingRequest) Descriptor() ([]byte, []int) { +func (m *QueryListPendingCctxRequest) Reset() { *m = QueryListPendingCctxRequest{} } +func (m *QueryListPendingCctxRequest) String() string { return proto.CompactTextString(m) } +func (*QueryListPendingCctxRequest) ProtoMessage() {} +func (*QueryListPendingCctxRequest) Descriptor() ([]byte, []int) { return fileDescriptor_65a992045e92a606, []int{31} } -func (m *QueryListCctxPendingRequest) XXX_Unmarshal(b []byte) error { +func (m *QueryListPendingCctxRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *QueryListCctxPendingRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *QueryListPendingCctxRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_QueryListCctxPendingRequest.Marshal(b, m, deterministic) + return xxx_messageInfo_QueryListPendingCctxRequest.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -1509,49 +1509,49 @@ func (m *QueryListCctxPendingRequest) XXX_Marshal(b []byte, deterministic bool) return b[:n], nil } } -func (m *QueryListCctxPendingRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryListCctxPendingRequest.Merge(m, src) +func (m *QueryListPendingCctxRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryListPendingCctxRequest.Merge(m, src) } -func (m *QueryListCctxPendingRequest) XXX_Size() int { +func (m *QueryListPendingCctxRequest) XXX_Size() int { return m.Size() } -func (m *QueryListCctxPendingRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryListCctxPendingRequest.DiscardUnknown(m) +func (m *QueryListPendingCctxRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryListPendingCctxRequest.DiscardUnknown(m) } -var xxx_messageInfo_QueryListCctxPendingRequest proto.InternalMessageInfo +var xxx_messageInfo_QueryListPendingCctxRequest proto.InternalMessageInfo -func (m *QueryListCctxPendingRequest) GetChainId() int64 { +func (m *QueryListPendingCctxRequest) GetChainId() int64 { if m != nil { return m.ChainId } return 0 } -func (m *QueryListCctxPendingRequest) GetLimit() uint32 { +func (m *QueryListPendingCctxRequest) GetLimit() uint32 { if m != nil { return m.Limit } return 0 } -type QueryListCctxPendingResponse struct { +type QueryListPendingCctxResponse struct { CrossChainTx []*CrossChainTx `protobuf:"bytes,1,rep,name=CrossChainTx,proto3" json:"CrossChainTx,omitempty"` TotalPending uint64 `protobuf:"varint,2,opt,name=totalPending,proto3" json:"totalPending,omitempty"` } -func (m *QueryListCctxPendingResponse) Reset() { *m = QueryListCctxPendingResponse{} } -func (m *QueryListCctxPendingResponse) String() string { return proto.CompactTextString(m) } -func (*QueryListCctxPendingResponse) ProtoMessage() {} -func (*QueryListCctxPendingResponse) Descriptor() ([]byte, []int) { +func (m *QueryListPendingCctxResponse) Reset() { *m = QueryListPendingCctxResponse{} } +func (m *QueryListPendingCctxResponse) String() string { return proto.CompactTextString(m) } +func (*QueryListPendingCctxResponse) ProtoMessage() {} +func (*QueryListPendingCctxResponse) Descriptor() ([]byte, []int) { return fileDescriptor_65a992045e92a606, []int{32} } -func (m *QueryListCctxPendingResponse) XXX_Unmarshal(b []byte) error { +func (m *QueryListPendingCctxResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *QueryListCctxPendingResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *QueryListPendingCctxResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_QueryListCctxPendingResponse.Marshal(b, m, deterministic) + return xxx_messageInfo_QueryListPendingCctxResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -1561,32 +1561,144 @@ func (m *QueryListCctxPendingResponse) XXX_Marshal(b []byte, deterministic bool) return b[:n], nil } } -func (m *QueryListCctxPendingResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryListCctxPendingResponse.Merge(m, src) +func (m *QueryListPendingCctxResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryListPendingCctxResponse.Merge(m, src) } -func (m *QueryListCctxPendingResponse) XXX_Size() int { +func (m *QueryListPendingCctxResponse) XXX_Size() int { return m.Size() } -func (m *QueryListCctxPendingResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryListCctxPendingResponse.DiscardUnknown(m) +func (m *QueryListPendingCctxResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryListPendingCctxResponse.DiscardUnknown(m) } -var xxx_messageInfo_QueryListCctxPendingResponse proto.InternalMessageInfo +var xxx_messageInfo_QueryListPendingCctxResponse proto.InternalMessageInfo -func (m *QueryListCctxPendingResponse) GetCrossChainTx() []*CrossChainTx { +func (m *QueryListPendingCctxResponse) GetCrossChainTx() []*CrossChainTx { if m != nil { return m.CrossChainTx } return nil } -func (m *QueryListCctxPendingResponse) GetTotalPending() uint64 { +func (m *QueryListPendingCctxResponse) GetTotalPending() uint64 { if m != nil { return m.TotalPending } return 0 } +type QueryListPendingCctxWithinRateLimitRequest struct { + Limit uint32 `protobuf:"varint,1,opt,name=limit,proto3" json:"limit,omitempty"` +} + +func (m *QueryListPendingCctxWithinRateLimitRequest) Reset() { + *m = QueryListPendingCctxWithinRateLimitRequest{} +} +func (m *QueryListPendingCctxWithinRateLimitRequest) String() string { + return proto.CompactTextString(m) +} +func (*QueryListPendingCctxWithinRateLimitRequest) ProtoMessage() {} +func (*QueryListPendingCctxWithinRateLimitRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_65a992045e92a606, []int{33} +} +func (m *QueryListPendingCctxWithinRateLimitRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryListPendingCctxWithinRateLimitRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryListPendingCctxWithinRateLimitRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryListPendingCctxWithinRateLimitRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryListPendingCctxWithinRateLimitRequest.Merge(m, src) +} +func (m *QueryListPendingCctxWithinRateLimitRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryListPendingCctxWithinRateLimitRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryListPendingCctxWithinRateLimitRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryListPendingCctxWithinRateLimitRequest proto.InternalMessageInfo + +func (m *QueryListPendingCctxWithinRateLimitRequest) GetLimit() uint32 { + if m != nil { + return m.Limit + } + return 0 +} + +type QueryListPendingCctxWithinRateLimitResponse struct { + CrossChainTx []*CrossChainTx `protobuf:"bytes,1,rep,name=cross_chain_tx,json=crossChainTx,proto3" json:"cross_chain_tx,omitempty"` + TotalPending uint64 `protobuf:"varint,2,opt,name=total_pending,json=totalPending,proto3" json:"total_pending,omitempty"` + RateLimitExceeded bool `protobuf:"varint,3,opt,name=rate_limit_exceeded,json=rateLimitExceeded,proto3" json:"rate_limit_exceeded,omitempty"` +} + +func (m *QueryListPendingCctxWithinRateLimitResponse) Reset() { + *m = QueryListPendingCctxWithinRateLimitResponse{} +} +func (m *QueryListPendingCctxWithinRateLimitResponse) String() string { + return proto.CompactTextString(m) +} +func (*QueryListPendingCctxWithinRateLimitResponse) ProtoMessage() {} +func (*QueryListPendingCctxWithinRateLimitResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_65a992045e92a606, []int{34} +} +func (m *QueryListPendingCctxWithinRateLimitResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryListPendingCctxWithinRateLimitResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryListPendingCctxWithinRateLimitResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryListPendingCctxWithinRateLimitResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryListPendingCctxWithinRateLimitResponse.Merge(m, src) +} +func (m *QueryListPendingCctxWithinRateLimitResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryListPendingCctxWithinRateLimitResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryListPendingCctxWithinRateLimitResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryListPendingCctxWithinRateLimitResponse proto.InternalMessageInfo + +func (m *QueryListPendingCctxWithinRateLimitResponse) GetCrossChainTx() []*CrossChainTx { + if m != nil { + return m.CrossChainTx + } + return nil +} + +func (m *QueryListPendingCctxWithinRateLimitResponse) GetTotalPending() uint64 { + if m != nil { + return m.TotalPending + } + return 0 +} + +func (m *QueryListPendingCctxWithinRateLimitResponse) GetRateLimitExceeded() bool { + if m != nil { + return m.RateLimitExceeded + } + return false +} + type QueryLastZetaHeightRequest struct { } @@ -1594,7 +1706,7 @@ func (m *QueryLastZetaHeightRequest) Reset() { *m = QueryLastZetaHeightR func (m *QueryLastZetaHeightRequest) String() string { return proto.CompactTextString(m) } func (*QueryLastZetaHeightRequest) ProtoMessage() {} func (*QueryLastZetaHeightRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_65a992045e92a606, []int{33} + return fileDescriptor_65a992045e92a606, []int{35} } func (m *QueryLastZetaHeightRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1631,7 +1743,7 @@ func (m *QueryLastZetaHeightResponse) Reset() { *m = QueryLastZetaHeight func (m *QueryLastZetaHeightResponse) String() string { return proto.CompactTextString(m) } func (*QueryLastZetaHeightResponse) ProtoMessage() {} func (*QueryLastZetaHeightResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_65a992045e92a606, []int{34} + return fileDescriptor_65a992045e92a606, []int{36} } func (m *QueryLastZetaHeightResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1676,7 +1788,7 @@ func (m *QueryConvertGasToZetaRequest) Reset() { *m = QueryConvertGasToZ func (m *QueryConvertGasToZetaRequest) String() string { return proto.CompactTextString(m) } func (*QueryConvertGasToZetaRequest) ProtoMessage() {} func (*QueryConvertGasToZetaRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_65a992045e92a606, []int{35} + return fileDescriptor_65a992045e92a606, []int{37} } func (m *QueryConvertGasToZetaRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1729,7 +1841,7 @@ func (m *QueryConvertGasToZetaResponse) Reset() { *m = QueryConvertGasTo func (m *QueryConvertGasToZetaResponse) String() string { return proto.CompactTextString(m) } func (*QueryConvertGasToZetaResponse) ProtoMessage() {} func (*QueryConvertGasToZetaResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_65a992045e92a606, []int{36} + return fileDescriptor_65a992045e92a606, []int{38} } func (m *QueryConvertGasToZetaResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1786,7 +1898,7 @@ func (m *QueryMessagePassingProtocolFeeRequest) Reset() { *m = QueryMess func (m *QueryMessagePassingProtocolFeeRequest) String() string { return proto.CompactTextString(m) } func (*QueryMessagePassingProtocolFeeRequest) ProtoMessage() {} func (*QueryMessagePassingProtocolFeeRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_65a992045e92a606, []int{37} + return fileDescriptor_65a992045e92a606, []int{39} } func (m *QueryMessagePassingProtocolFeeRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1825,7 +1937,7 @@ func (m *QueryMessagePassingProtocolFeeResponse) Reset() { func (m *QueryMessagePassingProtocolFeeResponse) String() string { return proto.CompactTextString(m) } func (*QueryMessagePassingProtocolFeeResponse) ProtoMessage() {} func (*QueryMessagePassingProtocolFeeResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_65a992045e92a606, []int{38} + return fileDescriptor_65a992045e92a606, []int{40} } func (m *QueryMessagePassingProtocolFeeResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1868,7 +1980,7 @@ func (m *QueryRateLimiterFlagsRequest) Reset() { *m = QueryRateLimiterFl func (m *QueryRateLimiterFlagsRequest) String() string { return proto.CompactTextString(m) } func (*QueryRateLimiterFlagsRequest) ProtoMessage() {} func (*QueryRateLimiterFlagsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_65a992045e92a606, []int{39} + return fileDescriptor_65a992045e92a606, []int{41} } func (m *QueryRateLimiterFlagsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1905,7 +2017,7 @@ func (m *QueryRateLimiterFlagsResponse) Reset() { *m = QueryRateLimiterF func (m *QueryRateLimiterFlagsResponse) String() string { return proto.CompactTextString(m) } func (*QueryRateLimiterFlagsResponse) ProtoMessage() {} func (*QueryRateLimiterFlagsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_65a992045e92a606, []int{40} + return fileDescriptor_65a992045e92a606, []int{42} } func (m *QueryRateLimiterFlagsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1973,8 +2085,10 @@ func init() { proto.RegisterType((*QueryGetCctxResponse)(nil), "zetachain.zetacore.crosschain.QueryGetCctxResponse") proto.RegisterType((*QueryAllCctxRequest)(nil), "zetachain.zetacore.crosschain.QueryAllCctxRequest") proto.RegisterType((*QueryAllCctxResponse)(nil), "zetachain.zetacore.crosschain.QueryAllCctxResponse") - proto.RegisterType((*QueryListCctxPendingRequest)(nil), "zetachain.zetacore.crosschain.QueryListCctxPendingRequest") - proto.RegisterType((*QueryListCctxPendingResponse)(nil), "zetachain.zetacore.crosschain.QueryListCctxPendingResponse") + proto.RegisterType((*QueryListPendingCctxRequest)(nil), "zetachain.zetacore.crosschain.QueryListPendingCctxRequest") + proto.RegisterType((*QueryListPendingCctxResponse)(nil), "zetachain.zetacore.crosschain.QueryListPendingCctxResponse") + proto.RegisterType((*QueryListPendingCctxWithinRateLimitRequest)(nil), "zetachain.zetacore.crosschain.QueryListPendingCctxWithinRateLimitRequest") + proto.RegisterType((*QueryListPendingCctxWithinRateLimitResponse)(nil), "zetachain.zetacore.crosschain.QueryListPendingCctxWithinRateLimitResponse") proto.RegisterType((*QueryLastZetaHeightRequest)(nil), "zetachain.zetacore.crosschain.QueryLastZetaHeightRequest") proto.RegisterType((*QueryLastZetaHeightResponse)(nil), "zetachain.zetacore.crosschain.QueryLastZetaHeightResponse") proto.RegisterType((*QueryConvertGasToZetaRequest)(nil), "zetachain.zetacore.crosschain.QueryConvertGasToZetaRequest") @@ -1988,120 +2102,126 @@ func init() { func init() { proto.RegisterFile("crosschain/query.proto", fileDescriptor_65a992045e92a606) } var fileDescriptor_65a992045e92a606 = []byte{ - // 1796 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x59, 0xcf, 0x6f, 0x14, 0xc7, - 0x12, 0x76, 0x7b, 0x31, 0x98, 0xb6, 0xc1, 0xd0, 0xf8, 0xf1, 0xfc, 0x16, 0x7b, 0x0d, 0xe3, 0x07, - 0xf6, 0x83, 0xe7, 0x1d, 0x30, 0x60, 0x1e, 0x60, 0x9e, 0xb2, 0x36, 0xb1, 0x41, 0x31, 0xe0, 0xac, - 0x1c, 0x25, 0x22, 0x8a, 0x56, 0xed, 0xd9, 0x66, 0x76, 0xc4, 0x78, 0xc6, 0xec, 0xcc, 0x22, 0x1b, - 0xcb, 0x17, 0x0e, 0x39, 0x47, 0xe2, 0x90, 0x4b, 0xae, 0x51, 0x72, 0xc8, 0x21, 0x52, 0xa2, 0xe4, - 0x10, 0x89, 0x28, 0x4a, 0x42, 0x38, 0x22, 0x45, 0x8a, 0xa2, 0x44, 0x8a, 0x22, 0xc8, 0x1f, 0x12, - 0x4d, 0x4f, 0xcd, 0x6e, 0xcf, 0xaf, 0xdd, 0xf6, 0x7a, 0x39, 0x70, 0xf2, 0xf6, 0x74, 0x57, 0xf5, - 0xf7, 0x55, 0x57, 0x57, 0x57, 0x95, 0xf1, 0x61, 0xad, 0x6a, 0x3b, 0x8e, 0x56, 0xa1, 0x86, 0xa5, - 0xde, 0xab, 0xb1, 0xea, 0x46, 0x7e, 0xad, 0x6a, 0xbb, 0x36, 0x19, 0x79, 0xc0, 0x5c, 0xca, 0x3f, - 0xe7, 0xf9, 0x2f, 0xbb, 0xca, 0xf2, 0x8d, 0xa5, 0xd9, 0x93, 0x9a, 0xed, 0xac, 0xda, 0x8e, 0xba, - 0x42, 0x1d, 0xe6, 0xcb, 0xa9, 0xf7, 0xcf, 0xac, 0x30, 0x97, 0x9e, 0x51, 0xd7, 0xa8, 0x6e, 0x58, - 0xd4, 0x35, 0x6c, 0xcb, 0x57, 0x95, 0x1d, 0x15, 0xb6, 0xe0, 0x3f, 0x4b, 0xfc, 0x77, 0xc9, 0x5d, - 0x87, 0x05, 0x59, 0x61, 0x81, 0x4e, 0x9d, 0xd2, 0x5a, 0xd5, 0xd0, 0x18, 0xcc, 0x8d, 0x09, 0x73, - 0x5c, 0xa6, 0x54, 0xa1, 0x4e, 0xa5, 0xe4, 0xda, 0x25, 0x4d, 0xab, 0x2b, 0xc8, 0xc5, 0x16, 0xb9, - 0x55, 0xaa, 0xdd, 0x65, 0x55, 0x98, 0x57, 0x84, 0x79, 0x93, 0x3a, 0x6e, 0x69, 0xc5, 0xb4, 0xb5, - 0xbb, 0xa5, 0x0a, 0x33, 0xf4, 0x8a, 0x9b, 0x80, 0xd2, 0xae, 0xb9, 0x71, 0x25, 0x22, 0x92, 0x2a, - 0x75, 0x59, 0xc9, 0x34, 0x56, 0x0d, 0x97, 0x55, 0x4b, 0x77, 0x4c, 0xaa, 0x3b, 0xb0, 0x68, 0x50, - 0xb7, 0x75, 0x9b, 0xff, 0x54, 0xbd, 0x5f, 0xf0, 0x75, 0x58, 0xb7, 0x6d, 0xdd, 0x64, 0x2a, 0x5d, - 0x33, 0x54, 0x6a, 0x59, 0xb6, 0xcb, 0xcd, 0x03, 0x32, 0xca, 0x30, 0xce, 0xbe, 0xe9, 0x59, 0xf0, - 0x36, 0x73, 0x69, 0x41, 0xd3, 0xec, 0x9a, 0xe5, 0x1a, 0x96, 0x5e, 0x64, 0xf7, 0x6a, 0xcc, 0x71, - 0x95, 0x1b, 0xf8, 0x48, 0xe2, 0xac, 0xb3, 0x66, 0x5b, 0x0e, 0x23, 0x79, 0x7c, 0x88, 0xae, 0xd8, - 0x55, 0x97, 0x95, 0x4b, 0xde, 0x39, 0x95, 0xe8, 0xaa, 0xb7, 0x62, 0x08, 0x1d, 0x45, 0x13, 0x7b, - 0x8b, 0x07, 0x61, 0x8a, 0xcb, 0xf2, 0x89, 0xba, 0xba, 0x05, 0xe6, 0xde, 0xaa, 0xb9, 0xcb, 0xeb, - 0xcb, 0x3e, 0x47, 0xd8, 0x8d, 0x0c, 0xe1, 0x3d, 0x9c, 0xe1, 0xf5, 0xab, 0x5c, 0x45, 0xa6, 0x18, - 0x0c, 0xc9, 0x20, 0xee, 0xb1, 0x6c, 0x4b, 0x63, 0x43, 0xdd, 0x47, 0xd1, 0xc4, 0xae, 0xa2, 0x3f, - 0x50, 0x6a, 0x78, 0x38, 0x59, 0x1d, 0xc0, 0x7b, 0x0b, 0xf7, 0xdb, 0xc2, 0x77, 0xae, 0xb4, 0x6f, - 0xea, 0x54, 0xbe, 0xa9, 0x77, 0xe5, 0x45, 0x55, 0xb3, 0xbb, 0x9e, 0xfe, 0x31, 0xda, 0x55, 0x0c, - 0xa9, 0x51, 0x18, 0xb0, 0x28, 0x98, 0x66, 0x12, 0x8b, 0x79, 0x8c, 0x1b, 0x5e, 0x08, 0x7b, 0x9e, - 0xc8, 0xfb, 0x2e, 0x9b, 0xf7, 0x5c, 0x36, 0xef, 0xbb, 0x3a, 0xb8, 0x6c, 0x7e, 0x89, 0xea, 0x0c, - 0x64, 0x8b, 0x82, 0xa4, 0xf2, 0x18, 0x01, 0xbd, 0xd8, 0x3e, 0xa9, 0xf4, 0x32, 0x1d, 0xa0, 0x47, - 0x16, 0x42, 0xf8, 0xbb, 0x39, 0xfe, 0xf1, 0x96, 0xf8, 0x7d, 0x4c, 0x21, 0x02, 0x0f, 0x11, 0x56, - 0x92, 0x08, 0xcc, 0x6e, 0xcc, 0x79, 0x48, 0x02, 0x7b, 0x0d, 0xe2, 0x1e, 0x8e, 0x0c, 0xce, 0xdc, - 0x1f, 0x44, 0xac, 0xd8, 0xdd, 0xb6, 0x15, 0x7f, 0x44, 0x78, 0xac, 0x29, 0x88, 0x57, 0xc4, 0x98, - 0xef, 0x23, 0x7c, 0x2c, 0xe0, 0x71, 0xdd, 0x4a, 0xb3, 0xe5, 0xbf, 0x70, 0xaf, 0x1f, 0xde, 0x8c, - 0x72, 0xf8, 0x0a, 0x95, 0x3b, 0x66, 0xd0, 0xef, 0x84, 0x53, 0x4d, 0x02, 0x02, 0xf6, 0x2c, 0xe2, - 0x3e, 0xc3, 0x8a, 0x9a, 0xf3, 0x64, 0x0b, 0x73, 0x8a, 0xfa, 0x7c, 0x6b, 0x8a, 0x4a, 0x3a, 0x67, - 0x4c, 0xe1, 0x06, 0x0b, 0x5b, 0x3a, 0x9d, 0xbe, 0xc1, 0xdf, 0x08, 0x37, 0x38, 0xbc, 0xcf, 0xab, - 0x60, 0xa4, 0xcb, 0x78, 0x24, 0x88, 0xae, 0xde, 0x96, 0xd7, 0xa8, 0x53, 0x59, 0xb6, 0xe7, 0x34, - 0x77, 0x3d, 0x30, 0x53, 0x16, 0xf7, 0x1a, 0x30, 0x01, 0x21, 0xbf, 0x3e, 0x56, 0xb6, 0x70, 0x2e, - 0x4d, 0x18, 0xb8, 0xbf, 0x8b, 0xf7, 0x1b, 0xa1, 0x19, 0x30, 0xf4, 0xa4, 0x04, 0xfd, 0x86, 0x10, - 0x58, 0x20, 0xa2, 0x4a, 0x99, 0x81, 0xed, 0xc3, 0x8b, 0xaf, 0x52, 0x97, 0xca, 0x80, 0x7f, 0x80, - 0x47, 0x53, 0xa5, 0x01, 0xfd, 0xdb, 0x78, 0xdf, 0x9c, 0x87, 0x89, 0x3b, 0xfd, 0xf2, 0xba, 0x23, - 0x19, 0x2f, 0x44, 0x19, 0x80, 0x1e, 0xd6, 0xa3, 0xe8, 0x60, 0x75, 0x70, 0x99, 0xb8, 0xd5, 0x3b, - 0xe5, 0x9c, 0x4f, 0x10, 0xd8, 0x28, 0x61, 0xa7, 0x26, 0x47, 0x94, 0xe9, 0xd0, 0x11, 0x75, 0xce, - 0x4f, 0x55, 0xfc, 0xcf, 0xc0, 0xd5, 0x16, 0xa8, 0xb3, 0xe4, 0xa5, 0x6f, 0xc2, 0xd3, 0x62, 0x58, - 0x65, 0xb6, 0x0e, 0x27, 0xec, 0x0f, 0x94, 0x12, 0x1e, 0x8a, 0x0b, 0x00, 0xe5, 0x39, 0xdc, 0x1b, - 0x7c, 0x03, 0xdb, 0x8e, 0xb7, 0x20, 0x5b, 0x57, 0x51, 0x17, 0x54, 0x28, 0x20, 0x2a, 0x98, 0x66, - 0x14, 0x51, 0xa7, 0x4e, 0xef, 0x53, 0x04, 0x24, 0x42, 0x7b, 0x24, 0x92, 0xc8, 0xb4, 0x45, 0xa2, - 0x73, 0xe7, 0x33, 0xdd, 0x08, 0x05, 0x8b, 0xd4, 0x71, 0x67, 0xbd, 0xec, 0xf7, 0x1a, 0x4f, 0x7e, - 0x9b, 0x1f, 0xd3, 0x26, 0xdc, 0xc2, 0x24, 0x39, 0x20, 0xfa, 0x0e, 0x1e, 0x88, 0x4c, 0x81, 0x49, - 0xf3, 0x2d, 0xf8, 0x46, 0x15, 0x46, 0xd5, 0x28, 0x95, 0xc6, 0xe5, 0x48, 0x01, 0xdd, 0xa9, 0x93, - 0xfc, 0x01, 0x01, 0xcf, 0xa4, 0xad, 0x9a, 0xf1, 0xcc, 0x74, 0x80, 0x67, 0xe7, 0x4e, 0xf9, 0x14, - 0x3e, 0x14, 0x9c, 0x96, 0x18, 0xad, 0x92, 0x8f, 0x76, 0x11, 0x8a, 0x0e, 0x58, 0x3c, 0xbb, 0x71, - 0xd3, 0xcb, 0xe7, 0xdb, 0x2d, 0x03, 0x74, 0x3c, 0x18, 0xde, 0x1a, 0xac, 0x76, 0x0b, 0xf7, 0x8b, - 0xb1, 0x55, 0x32, 0xfd, 0x17, 0x45, 0x8a, 0x21, 0x05, 0xca, 0x7b, 0xc0, 0xb1, 0x60, 0x9a, 0x2f, - 0x23, 0x22, 0x7f, 0x8e, 0x80, 0x48, 0x5d, 0x7f, 0x2a, 0x91, 0xcc, 0x8e, 0x88, 0x74, 0xee, 0xd4, - 0x6f, 0x42, 0x22, 0xb5, 0x68, 0x38, 0xdc, 0xf6, 0x4b, 0xcc, 0x2a, 0x37, 0xca, 0xc7, 0x66, 0xe9, - 0xe8, 0x20, 0xee, 0xe1, 0x25, 0x2c, 0xdf, 0x7d, 0x5f, 0xd1, 0x1f, 0x28, 0x8f, 0x82, 0x8c, 0x29, - 0xa6, 0xf0, 0x65, 0x99, 0x42, 0xc1, 0xfd, 0xae, 0xed, 0x52, 0x13, 0x36, 0x02, 0xcf, 0x0a, 0x7d, - 0xab, 0xd7, 0xc8, 0xde, 0xe5, 0xf1, 0xaa, 0xd9, 0x50, 0x20, 0x50, 0xce, 0x07, 0x36, 0x88, 0xcc, - 0x02, 0xe2, 0xc3, 0x78, 0xb7, 0x10, 0x9a, 0x32, 0x45, 0x18, 0x29, 0xcb, 0xc0, 0x74, 0xce, 0xb6, - 0xee, 0xb3, 0xaa, 0xf7, 0x12, 0x2d, 0xdb, 0x9e, 0x78, 0xec, 0x16, 0xc4, 0x4c, 0x97, 0xc5, 0xbd, - 0x3a, 0x75, 0x16, 0xeb, 0xd6, 0xdb, 0x5b, 0xac, 0x8f, 0x95, 0x8f, 0x11, 0xe4, 0x0f, 0x71, 0xb5, - 0x80, 0xe7, 0xbf, 0xf8, 0xa0, 0x5d, 0x73, 0x57, 0xec, 0x9a, 0x55, 0x5e, 0xa0, 0xce, 0x75, 0xcb, - 0x9b, 0x0c, 0x2a, 0xf6, 0xd8, 0x84, 0xb7, 0x9a, 0xf7, 0x09, 0x34, 0xdb, 0x9c, 0x67, 0x0c, 0x56, - 0xfb, 0x9b, 0xc6, 0x27, 0xc8, 0x04, 0x1e, 0xf0, 0xfe, 0x8a, 0x71, 0x2a, 0xc3, 0xed, 0x19, 0xfd, - 0xac, 0x8c, 0xe3, 0xe3, 0x1c, 0xe6, 0x0d, 0xe6, 0x38, 0x54, 0x67, 0x4b, 0xd4, 0x71, 0x0c, 0x4b, - 0x5f, 0x6a, 0x68, 0x0c, 0xac, 0x3b, 0x8f, 0x4f, 0xb4, 0x5a, 0x08, 0xc4, 0x86, 0xf1, 0xde, 0x3b, - 0x75, 0x88, 0x3e, 0xa1, 0xc6, 0x07, 0x25, 0x07, 0xe6, 0x2e, 0x52, 0x97, 0x2d, 0xfa, 0xbd, 0x93, - 0x79, 0x93, 0xea, 0x41, 0xce, 0xef, 0x15, 0xab, 0x23, 0x29, 0x0b, 0x40, 0x3f, 0xc5, 0x07, 0xaa, - 0x91, 0x39, 0xb8, 0xec, 0x6a, 0x0b, 0xf7, 0x8b, 0xaa, 0x84, 0x8c, 0x28, 0xa6, 0x6e, 0xea, 0x8b, - 0x51, 0xdc, 0xc3, 0x41, 0x90, 0x27, 0x08, 0xf7, 0x8b, 0xc5, 0x25, 0xb9, 0xd4, 0x62, 0x8f, 0x26, - 0x7d, 0x95, 0xec, 0xe5, 0xb6, 0x64, 0x7d, 0xda, 0xca, 0x95, 0x87, 0x3f, 0xff, 0xf5, 0xa8, 0xfb, - 0x02, 0x39, 0xaf, 0x7a, 0xa2, 0x93, 0x42, 0x27, 0xad, 0xde, 0xae, 0xaa, 0x0b, 0xa9, 0x9b, 0x10, - 0xa9, 0xb7, 0xd4, 0x4d, 0x1e, 0x9b, 0xb7, 0xc8, 0xd7, 0x08, 0x0f, 0x88, 0x7a, 0x0b, 0xa6, 0x29, - 0xc7, 0x25, 0xb9, 0xbb, 0x22, 0xc7, 0x25, 0xa5, 0x63, 0xa2, 0x9c, 0xe2, 0x5c, 0x8e, 0x93, 0x31, - 0x09, 0x2e, 0xe4, 0x77, 0x84, 0x0f, 0x47, 0x90, 0x43, 0x91, 0x4b, 0x0a, 0x6d, 0x80, 0x08, 0x57, - 0xea, 0xd9, 0xd9, 0x9d, 0xa8, 0x00, 0x3a, 0x97, 0x38, 0x9d, 0x73, 0x64, 0x4a, 0x82, 0x0e, 0xc8, - 0xc2, 0x09, 0x6d, 0x91, 0xdf, 0x10, 0xfe, 0x87, 0x50, 0x49, 0x0a, 0xe4, 0x5e, 0x93, 0x44, 0x96, - 0xda, 0x85, 0xc8, 0x16, 0x76, 0xa0, 0x01, 0xa8, 0xcd, 0x70, 0x6a, 0xd3, 0xe4, 0x5c, 0x0a, 0x35, - 0xc3, 0x4a, 0x61, 0x56, 0x32, 0xca, 0x5b, 0xe4, 0x2b, 0x84, 0xf7, 0x87, 0xc9, 0x49, 0xfb, 0x5c, - 0x42, 0x3f, 0x40, 0xda, 0xe7, 0x92, 0x6a, 0xfc, 0x96, 0x3e, 0x27, 0x30, 0x71, 0xc8, 0x4f, 0x00, - 0x5c, 0xa8, 0x93, 0x66, 0x24, 0x2f, 0x6f, 0x62, 0xb5, 0x98, 0xbd, 0xd2, 0xa6, 0x34, 0x80, 0xff, - 0x1f, 0x07, 0x3f, 0x45, 0x4e, 0x37, 0x01, 0xdf, 0x10, 0x53, 0x37, 0x83, 0xf1, 0x16, 0xf9, 0x05, - 0x61, 0x12, 0xaf, 0x9f, 0x89, 0x14, 0x9e, 0xd4, 0xaa, 0x3d, 0xfb, 0xff, 0x76, 0xc5, 0x81, 0x4f, - 0x81, 0xf3, 0xb9, 0x4c, 0x2e, 0xa6, 0xf2, 0x89, 0x36, 0xf9, 0x4b, 0x65, 0xea, 0x52, 0x91, 0xd8, - 0xb7, 0x08, 0x1f, 0x0c, 0xef, 0xe0, 0xb9, 0xd7, 0xcc, 0x36, 0x5c, 0xa4, 0xcd, 0x53, 0x4a, 0xad, - 0xd3, 0x95, 0x49, 0xce, 0x6a, 0x9c, 0x1c, 0x97, 0x3a, 0x25, 0xf2, 0x19, 0x6a, 0xd4, 0x87, 0x64, - 0x5a, 0xd2, 0x41, 0x22, 0x85, 0x6c, 0xf6, 0xc2, 0xb6, 0xe5, 0x00, 0xac, 0xca, 0xc1, 0xfe, 0x87, - 0x8c, 0xa7, 0x80, 0xd5, 0x41, 0xc0, 0xb3, 0x79, 0x99, 0xad, 0x6f, 0x91, 0x4f, 0x10, 0xee, 0x0b, - 0xb4, 0x78, 0xa6, 0x9e, 0x96, 0x34, 0x56, 0x5b, 0x88, 0x13, 0xca, 0x69, 0x65, 0x9c, 0x23, 0x3e, - 0x46, 0x46, 0x5b, 0x20, 0x26, 0x8f, 0x11, 0x3e, 0x10, 0xcd, 0xbb, 0x88, 0x54, 0xf0, 0x48, 0x49, - 0x02, 0xb3, 0x33, 0xed, 0x09, 0x4b, 0x9a, 0x5a, 0x8b, 0x62, 0x7d, 0x82, 0x70, 0x9f, 0x90, 0x5a, - 0x91, 0xab, 0x32, 0xdb, 0xb7, 0x4a, 0xe1, 0xb2, 0xaf, 0xef, 0x50, 0x0b, 0xb0, 0x39, 0xc9, 0xd9, - 0xfc, 0x9b, 0x28, 0x29, 0x6c, 0x84, 0x74, 0x94, 0x3c, 0x45, 0xb1, 0x8a, 0x99, 0xc8, 0x86, 0xc2, - 0xe4, 0x7a, 0x5f, 0x2e, 0xf4, 0xa4, 0xf7, 0x2a, 0x94, 0x69, 0x0e, 0xff, 0x34, 0xc9, 0xa7, 0xc0, - 0x37, 0xc3, 0x72, 0x75, 0xf7, 0xff, 0x1e, 0x61, 0x12, 0xd1, 0xe9, 0xdd, 0x02, 0xd9, 0x90, 0xb1, - 0x13, 0x36, 0xe9, 0x1d, 0x09, 0x25, 0xcf, 0xd9, 0x4c, 0x90, 0x13, 0x72, 0x6c, 0xc8, 0x47, 0x08, - 0xef, 0xe2, 0xc1, 0x67, 0x4a, 0xd2, 0x8c, 0x62, 0x78, 0x3c, 0xbb, 0x2d, 0x19, 0xc9, 0x77, 0x57, - 0x83, 0x07, 0x8b, 0x1b, 0xf9, 0x4b, 0x84, 0xfb, 0x84, 0x4e, 0x04, 0xb9, 0xb8, 0x8d, 0x1d, 0xc3, - 0xdd, 0x8b, 0xf6, 0xc0, 0x9e, 0xe7, 0x60, 0x55, 0x32, 0xd9, 0x14, 0x6c, 0x2c, 0xb9, 0xfe, 0x10, - 0xe1, 0x3d, 0xc1, 0x0b, 0x34, 0x25, 0x79, 0xa2, 0xdb, 0x36, 0x6c, 0xa4, 0x1b, 0xa1, 0x8c, 0x71, - 0xac, 0x23, 0xe4, 0x48, 0x13, 0xac, 0x5e, 0x06, 0x36, 0xe0, 0x49, 0x79, 0x75, 0x3c, 0x94, 0xd1, - 0x72, 0x29, 0x58, 0x72, 0x27, 0x41, 0x2e, 0x05, 0x4b, 0x69, 0x1a, 0xb4, 0x8c, 0x1c, 0x5a, 0x43, - 0x86, 0xa7, 0x8e, 0xe1, 0xff, 0x76, 0xcb, 0x39, 0x43, 0xe2, 0xff, 0xcf, 0xb3, 0x97, 0xda, 0x11, - 0x95, 0x7c, 0xd5, 0x1f, 0x84, 0x51, 0x7a, 0xc0, 0xc3, 0x2d, 0x08, 0x39, 0xe0, 0x89, 0x4d, 0x0d, - 0x39, 0xe0, 0xc9, 0x1d, 0x8f, 0x96, 0xc0, 0xcd, 0x30, 0x4a, 0xef, 0xd5, 0x8c, 0x56, 0xc8, 0x72, - 0xaf, 0x66, 0x4a, 0x2d, 0x2f, 0xf7, 0x6a, 0xa6, 0xd5, 0xf9, 0x2d, 0x5f, 0xcd, 0x68, 0xd5, 0x3e, - 0xfb, 0xc6, 0xd3, 0xe7, 0x39, 0xf4, 0xec, 0x79, 0x0e, 0xfd, 0xf9, 0x3c, 0x87, 0x3e, 0x78, 0x91, - 0xeb, 0x7a, 0xf6, 0x22, 0xd7, 0xf5, 0xeb, 0x8b, 0x5c, 0xd7, 0xed, 0x33, 0xba, 0xe1, 0x56, 0x6a, - 0x2b, 0x79, 0xcd, 0x5e, 0x15, 0x95, 0x05, 0x98, 0xd4, 0x75, 0x51, 0xaf, 0xbb, 0xb1, 0xc6, 0x9c, - 0x95, 0xdd, 0xfc, 0x19, 0x3b, 0xfb, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe2, 0x51, 0x5a, 0xb9, - 0x1b, 0x23, 0x00, 0x00, + // 1901 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x5a, 0xc1, 0x6f, 0xdc, 0x4a, + 0x19, 0xcf, 0x64, 0x9b, 0xf7, 0xd2, 0x49, 0xda, 0xbc, 0xcc, 0x0b, 0x25, 0xf8, 0x25, 0x9b, 0xd6, + 0xa1, 0x4d, 0x48, 0xc8, 0xfa, 0x25, 0x7d, 0xcd, 0xa3, 0x6d, 0x1e, 0x62, 0x93, 0xbe, 0xa4, 0x81, + 0xb4, 0x4d, 0x57, 0x41, 0x45, 0x45, 0xc8, 0x9a, 0x78, 0xa7, 0x5e, 0xab, 0x8e, 0x9d, 0xae, 0xbd, + 0xd5, 0xa6, 0x51, 0x2e, 0x3d, 0x70, 0x46, 0xea, 0x81, 0x0b, 0x57, 0x44, 0x0f, 0x1c, 0x38, 0x20, + 0x38, 0x20, 0x15, 0x21, 0xa0, 0xf4, 0x58, 0x09, 0x81, 0x10, 0x48, 0x08, 0xb5, 0xfc, 0x05, 0xfc, + 0x05, 0xc8, 0xe3, 0xcf, 0xbb, 0x63, 0xaf, 0xbd, 0x3b, 0xd9, 0x6c, 0x0f, 0x3d, 0x75, 0xed, 0x99, + 0xef, 0x9b, 0xdf, 0xef, 0x9b, 0x6f, 0x3e, 0x7f, 0xf3, 0x6b, 0xf0, 0x39, 0xa3, 0xea, 0x7a, 0x9e, + 0x51, 0xa1, 0x96, 0xa3, 0x3d, 0xaa, 0xb1, 0xea, 0x41, 0x61, 0xbf, 0xea, 0xfa, 0x2e, 0x99, 0x7c, + 0xc2, 0x7c, 0xca, 0x5f, 0x17, 0xf8, 0x2f, 0xb7, 0xca, 0x0a, 0xcd, 0xa9, 0xca, 0x9c, 0xe1, 0x7a, + 0x7b, 0xae, 0xa7, 0xed, 0x52, 0x8f, 0x85, 0x76, 0xda, 0xe3, 0xc5, 0x5d, 0xe6, 0xd3, 0x45, 0x6d, + 0x9f, 0x9a, 0x96, 0x43, 0x7d, 0xcb, 0x75, 0x42, 0x57, 0xca, 0x94, 0xb0, 0x04, 0xff, 0xa9, 0xf3, + 0xdf, 0xba, 0x5f, 0x87, 0x09, 0x8a, 0x30, 0xc1, 0xa4, 0x9e, 0xbe, 0x5f, 0xb5, 0x0c, 0x06, 0x63, + 0xd3, 0xc2, 0x18, 0xb7, 0xd1, 0x2b, 0xd4, 0xab, 0xe8, 0xbe, 0xab, 0x1b, 0x46, 0xc3, 0x41, 0xbe, + 0x65, 0x92, 0x5f, 0xa5, 0xc6, 0x43, 0x56, 0x85, 0x71, 0x55, 0x18, 0xb7, 0xa9, 0xe7, 0xeb, 0xbb, + 0xb6, 0x6b, 0x3c, 0xd4, 0x2b, 0xcc, 0x32, 0x2b, 0x7e, 0x0a, 0x4a, 0xb7, 0xe6, 0xb7, 0x3a, 0x11, + 0x91, 0x54, 0xa9, 0xcf, 0x74, 0xdb, 0xda, 0xb3, 0x7c, 0x56, 0xd5, 0x1f, 0xd8, 0xd4, 0xf4, 0x60, + 0xd2, 0x98, 0xe9, 0x9a, 0x2e, 0xff, 0xa9, 0x05, 0xbf, 0xe0, 0xed, 0x84, 0xe9, 0xba, 0xa6, 0xcd, + 0x34, 0xba, 0x6f, 0x69, 0xd4, 0x71, 0x5c, 0x9f, 0x87, 0x07, 0x6c, 0xd4, 0x09, 0xac, 0xdc, 0x0d, + 0x22, 0x78, 0x9f, 0xf9, 0xb4, 0x68, 0x18, 0x6e, 0xcd, 0xf1, 0x2d, 0xc7, 0x2c, 0xb1, 0x47, 0x35, + 0xe6, 0xf9, 0xea, 0x2d, 0xfc, 0x49, 0xea, 0xa8, 0xb7, 0xef, 0x3a, 0x1e, 0x23, 0x05, 0xfc, 0x31, + 0xdd, 0x75, 0xab, 0x3e, 0x2b, 0xeb, 0xc1, 0x3e, 0xe9, 0x74, 0x2f, 0x98, 0x31, 0x8e, 0xce, 0xa3, + 0xd9, 0xd3, 0xa5, 0x51, 0x18, 0xe2, 0xb6, 0x7c, 0xa0, 0xe1, 0x6e, 0x83, 0xf9, 0x77, 0x6a, 0xfe, + 0x4e, 0x7d, 0x27, 0xe4, 0x08, 0xab, 0x91, 0x71, 0xfc, 0x21, 0x67, 0xb8, 0x79, 0x83, 0xbb, 0xc8, + 0x95, 0xa2, 0x47, 0x32, 0x86, 0x07, 0x1c, 0xd7, 0x31, 0xd8, 0x78, 0xff, 0x79, 0x34, 0x7b, 0xaa, + 0x14, 0x3e, 0xa8, 0x35, 0x3c, 0x91, 0xee, 0x0e, 0xe0, 0x7d, 0x1f, 0x0f, 0xbb, 0xc2, 0x7b, 0xee, + 0x74, 0x68, 0x69, 0xbe, 0xd0, 0x36, 0xbb, 0x0a, 0xa2, 0xab, 0xd5, 0x53, 0xaf, 0xfe, 0x3d, 0xd5, + 0x57, 0x8a, 0xb9, 0x51, 0x19, 0xb0, 0x28, 0xda, 0x76, 0x1a, 0x8b, 0x75, 0x8c, 0x9b, 0x59, 0x08, + 0x6b, 0x5e, 0x2a, 0x84, 0x29, 0x5b, 0x08, 0x52, 0xb6, 0x10, 0xa6, 0x3a, 0xa4, 0x6c, 0x61, 0x9b, + 0x9a, 0x0c, 0x6c, 0x4b, 0x82, 0xa5, 0xfa, 0x02, 0x01, 0xbd, 0x96, 0x75, 0x32, 0xe9, 0xe5, 0x7a, + 0x40, 0x8f, 0x6c, 0xc4, 0xf0, 0xf7, 0x73, 0xfc, 0x33, 0x1d, 0xf1, 0x87, 0x98, 0x62, 0x04, 0x9e, + 0x22, 0xac, 0xa6, 0x11, 0x58, 0x3d, 0x58, 0x0b, 0x90, 0x44, 0xf1, 0x1a, 0xc3, 0x03, 0x1c, 0x19, + 0xec, 0x79, 0xf8, 0x90, 0x88, 0x62, 0x7f, 0xd7, 0x51, 0xfc, 0x33, 0xc2, 0xd3, 0x6d, 0x41, 0xbc, + 0x27, 0xc1, 0xfc, 0x31, 0xc2, 0x17, 0x22, 0x1e, 0x9b, 0x4e, 0x56, 0x2c, 0xbf, 0x86, 0x07, 0xc3, + 0xf2, 0x66, 0x95, 0xe3, 0x47, 0xa8, 0xdc, 0xb3, 0x80, 0xfe, 0x41, 0xd8, 0xd5, 0x34, 0x20, 0x10, + 0xcf, 0x12, 0x1e, 0xb2, 0x9c, 0x64, 0x38, 0xe7, 0x3a, 0x84, 0x53, 0xf4, 0x17, 0x46, 0x53, 0x74, + 0xd2, 0xbb, 0x60, 0x0a, 0x27, 0x58, 0x58, 0xd2, 0xeb, 0xf5, 0x09, 0xfe, 0x9d, 0x70, 0x82, 0xe3, + 0xeb, 0xbc, 0x0f, 0x41, 0xba, 0x8e, 0x27, 0xa3, 0xea, 0x1a, 0x2c, 0x79, 0x93, 0x7a, 0x95, 0x1d, + 0x77, 0xcd, 0xf0, 0xeb, 0x51, 0x98, 0x14, 0x3c, 0x68, 0xc1, 0x00, 0x94, 0xfc, 0xc6, 0xb3, 0x7a, + 0x84, 0xf3, 0x59, 0xc6, 0xc0, 0xfd, 0x87, 0xf8, 0xac, 0x15, 0x1b, 0x81, 0x40, 0x2f, 0x48, 0xd0, + 0x6f, 0x1a, 0x41, 0x04, 0x12, 0xae, 0xd4, 0x15, 0x58, 0x3e, 0x3e, 0xf9, 0x06, 0xf5, 0xa9, 0x0c, + 0xf8, 0x27, 0x78, 0x2a, 0xd3, 0x1a, 0xd0, 0xdf, 0xc3, 0x67, 0xd6, 0x02, 0x4c, 0x3c, 0xe9, 0x77, + 0xea, 0x9e, 0x64, 0xbd, 0x10, 0x6d, 0x00, 0x7a, 0xdc, 0x8f, 0x6a, 0x42, 0xd4, 0x21, 0x65, 0x5a, + 0xa3, 0xde, 0xab, 0xe4, 0x7c, 0x89, 0x20, 0x46, 0x29, 0x2b, 0xb5, 0xd9, 0xa2, 0x5c, 0x8f, 0xb6, + 0xa8, 0x77, 0x79, 0xaa, 0xe1, 0xaf, 0x46, 0xa9, 0xb6, 0x41, 0xbd, 0xed, 0xa0, 0x7d, 0x13, 0x3e, + 0x2d, 0x96, 0x53, 0x66, 0x75, 0xd8, 0xe1, 0xf0, 0x41, 0xd5, 0xf1, 0x78, 0xab, 0x01, 0x50, 0x5e, + 0xc3, 0x83, 0xd1, 0x3b, 0x88, 0xed, 0x4c, 0x07, 0xb2, 0x0d, 0x17, 0x0d, 0x43, 0x95, 0x02, 0xa2, + 0xa2, 0x6d, 0x27, 0x11, 0xf5, 0x6a, 0xf7, 0x9e, 0x23, 0x20, 0x11, 0x5b, 0x23, 0x95, 0x44, 0xae, + 0x2b, 0x12, 0xbd, 0xdb, 0x9f, 0xe5, 0x66, 0x29, 0xd8, 0xa2, 0x9e, 0xbf, 0x1a, 0x74, 0xbf, 0x37, + 0x79, 0xf3, 0xdb, 0x7e, 0x9b, 0x0e, 0xe1, 0x14, 0xa6, 0xd9, 0x01, 0xd1, 0x1f, 0xe0, 0x91, 0xc4, + 0x10, 0x84, 0xb4, 0xd0, 0x81, 0x6f, 0xd2, 0x61, 0xd2, 0x8d, 0x5a, 0x69, 0x1e, 0x8e, 0x0c, 0xd0, + 0xbd, 0xda, 0xc9, 0x3f, 0x21, 0xe0, 0x99, 0xb6, 0x54, 0x3b, 0x9e, 0xb9, 0x1e, 0xf0, 0xec, 0xdd, + 0x2e, 0xcf, 0xe3, 0x8f, 0xa3, 0xdd, 0x12, 0xab, 0x55, 0xfa, 0xd6, 0x6e, 0xc1, 0xa5, 0x03, 0x26, + 0xaf, 0x1e, 0xdc, 0x0e, 0xfa, 0xf9, 0x6e, 0xaf, 0x01, 0x26, 0x1e, 0x8b, 0x2f, 0x0d, 0x51, 0xbb, + 0x83, 0x87, 0xc5, 0xda, 0x2a, 0xd9, 0xfe, 0x8b, 0x26, 0xa5, 0x98, 0x03, 0xf5, 0x47, 0xc0, 0xb1, + 0x68, 0xdb, 0xef, 0xa2, 0x22, 0xff, 0x0a, 0x01, 0x91, 0x86, 0xff, 0x4c, 0x22, 0xb9, 0x13, 0x11, + 0xe9, 0xdd, 0xae, 0xdf, 0x86, 0x46, 0x6a, 0xcb, 0xf2, 0xfc, 0x6d, 0xe6, 0x94, 0x2d, 0xc7, 0x14, + 0x23, 0xd3, 0xa6, 0x1d, 0x1d, 0xc3, 0x03, 0xfc, 0x0a, 0xcb, 0x57, 0x3f, 0x53, 0x0a, 0x1f, 0xd4, + 0x67, 0x51, 0xc7, 0xd4, 0xe2, 0xf0, 0x5d, 0x85, 0x42, 0xc5, 0xc3, 0xbe, 0xeb, 0x53, 0x1b, 0x16, + 0x83, 0xcc, 0x8a, 0xbd, 0x53, 0x57, 0xf1, 0x5c, 0x1a, 0xa8, 0x7b, 0x96, 0x5f, 0xb1, 0x9c, 0x12, + 0xf5, 0xd9, 0x56, 0x00, 0x5e, 0x48, 0xf9, 0x90, 0x19, 0x12, 0x99, 0xfd, 0x0d, 0xe1, 0x79, 0x29, + 0x27, 0x40, 0xf4, 0x2e, 0x3e, 0x1b, 0x97, 0x2b, 0xba, 0xa2, 0x6a, 0x88, 0x54, 0xa7, 0xf1, 0x19, + 0x4e, 0x4b, 0xdf, 0xcf, 0xe6, 0x1a, 0x5c, 0xe9, 0x9b, 0xfa, 0x82, 0xce, 0xea, 0x06, 0x63, 0x65, + 0x56, 0x1e, 0xcf, 0x9d, 0x47, 0xb3, 0x83, 0xa5, 0xd1, 0x6a, 0x84, 0xf3, 0x4b, 0x18, 0x68, 0xe8, + 0x07, 0x41, 0x61, 0x09, 0x6e, 0xfa, 0xb1, 0x22, 0xa9, 0x5e, 0x89, 0xf2, 0x23, 0x31, 0x0a, 0x24, + 0xcf, 0xe1, 0x0f, 0x84, 0xb2, 0x9d, 0x2b, 0xc1, 0x93, 0xba, 0x03, 0x59, 0xb0, 0xe6, 0x3a, 0x8f, + 0x59, 0x35, 0xf8, 0x4a, 0xef, 0xb8, 0x81, 0x79, 0x4b, 0x85, 0x68, 0x49, 0x2b, 0x05, 0x0f, 0x9a, + 0xd4, 0xdb, 0x6a, 0x64, 0xd6, 0xe9, 0x52, 0xe3, 0x59, 0xfd, 0x39, 0x82, 0xde, 0xaa, 0xd5, 0x2d, + 0xe0, 0xf9, 0x26, 0x1e, 0x75, 0x6b, 0xfe, 0xae, 0x5b, 0x73, 0xca, 0x1b, 0xd4, 0xdb, 0x74, 0x82, + 0xc1, 0x48, 0xcd, 0x68, 0x19, 0x08, 0x66, 0x73, 0x0d, 0xc5, 0x70, 0xed, 0x75, 0xc6, 0x60, 0x76, + 0xb8, 0x68, 0xeb, 0x00, 0x99, 0xc5, 0x23, 0xc1, 0xbf, 0x62, 0x0d, 0xcf, 0xf1, 0xf8, 0x27, 0x5f, + 0xab, 0x33, 0xf8, 0x22, 0x87, 0x79, 0x8b, 0x79, 0x1e, 0x35, 0xd9, 0x36, 0xf5, 0x3c, 0xcb, 0x31, + 0xb7, 0x9b, 0x1e, 0xa3, 0xe8, 0xae, 0xe3, 0x4b, 0x9d, 0x26, 0x02, 0xb1, 0x09, 0x7c, 0xfa, 0x41, + 0x03, 0x62, 0x48, 0xa8, 0xf9, 0x42, 0xcd, 0x43, 0xb8, 0x1b, 0x59, 0xc8, 0xaa, 0xeb, 0x36, 0x35, + 0xa3, 0xfb, 0x50, 0x70, 0x91, 0x9f, 0xcc, 0x98, 0x00, 0xfe, 0x29, 0xfe, 0xa8, 0x9a, 0x18, 0x83, + 0x42, 0xa8, 0x75, 0xc8, 0xd7, 0xa4, 0x4b, 0xe8, 0x16, 0x5b, 0xdc, 0x2d, 0x3d, 0xbf, 0x80, 0x07, + 0x38, 0x08, 0xf2, 0x12, 0xe1, 0x61, 0xf1, 0xe2, 0x4d, 0xae, 0x75, 0x58, 0xa3, 0x8d, 0xe6, 0xa4, + 0x5c, 0xef, 0xca, 0x36, 0xa4, 0xad, 0x7e, 0xf1, 0xf4, 0xaf, 0xff, 0x7d, 0xd6, 0xff, 0x39, 0xb9, + 0xa2, 0x05, 0xa6, 0x0b, 0x82, 0xca, 0xd8, 0x90, 0xf2, 0x1a, 0x46, 0xda, 0x21, 0x7c, 0xc5, 0x8e, + 0xb4, 0x43, 0xfe, 0xdd, 0x3a, 0x22, 0xbf, 0x45, 0x78, 0x44, 0xf4, 0x5b, 0xb4, 0x6d, 0x39, 0x2e, + 0xe9, 0xca, 0x93, 0x1c, 0x97, 0x0c, 0x35, 0x49, 0x9d, 0xe7, 0x5c, 0x2e, 0x92, 0x69, 0x09, 0x2e, + 0xe4, 0x5f, 0x08, 0x9f, 0x4b, 0x20, 0x07, 0x01, 0x80, 0x14, 0xbb, 0x00, 0x11, 0x57, 0x31, 0x94, + 0xd5, 0x93, 0xb8, 0x00, 0x3a, 0xd7, 0x38, 0x9d, 0xcf, 0xc8, 0x92, 0x04, 0x1d, 0xb0, 0x85, 0x1d, + 0x3a, 0x22, 0xff, 0x44, 0xf8, 0x2b, 0xc2, 0x2d, 0x5b, 0x20, 0xf7, 0x1d, 0x49, 0x64, 0x99, 0x0a, + 0x8d, 0x52, 0x3c, 0x81, 0x07, 0xa0, 0xb6, 0xc2, 0xa9, 0x2d, 0x93, 0xcf, 0x32, 0xa8, 0x59, 0x4e, + 0x06, 0x33, 0xdd, 0x2a, 0x1f, 0x91, 0xdf, 0x20, 0x7c, 0x36, 0x4e, 0x4e, 0x3a, 0xe7, 0x52, 0xb4, + 0x12, 0xe9, 0x9c, 0x4b, 0xd3, 0x3f, 0x3a, 0xe6, 0x9c, 0xc0, 0xc4, 0x23, 0x7f, 0x01, 0xe0, 0xc2, + 0x1d, 0x72, 0x45, 0xf2, 0xf0, 0xa6, 0xde, 0xa4, 0x95, 0x2f, 0xba, 0xb4, 0x06, 0xf0, 0xdf, 0xe2, + 0xe0, 0x97, 0xc8, 0xa7, 0x6d, 0xc0, 0x37, 0xcd, 0xb4, 0xc3, 0xe8, 0xf9, 0x88, 0xfc, 0x1d, 0x61, + 0xd2, 0xaa, 0x2d, 0x10, 0x29, 0x3c, 0x99, 0x8a, 0x86, 0xf2, 0xed, 0x6e, 0xcd, 0x81, 0x4f, 0x91, + 0xf3, 0xb9, 0x4e, 0xae, 0x66, 0xf2, 0x49, 0xfe, 0x07, 0x88, 0x5e, 0xa6, 0x3e, 0x15, 0x89, 0xfd, + 0x1e, 0xe1, 0xd1, 0xf8, 0x0a, 0x41, 0x7a, 0xad, 0x1c, 0x23, 0x45, 0xba, 0xdc, 0xa5, 0x4c, 0x0d, + 0x43, 0x5d, 0xe0, 0xac, 0x66, 0xc8, 0x45, 0xa9, 0x5d, 0x22, 0xbf, 0x44, 0xcd, 0xbb, 0x33, 0x59, + 0x96, 0x4c, 0x90, 0xc4, 0x25, 0x5f, 0xf9, 0xfc, 0xd8, 0x76, 0x00, 0x56, 0xe3, 0x60, 0xbf, 0x41, + 0x66, 0x32, 0xc0, 0x9a, 0x60, 0x10, 0xc4, 0xbc, 0xcc, 0xea, 0x47, 0xe4, 0x17, 0x08, 0x0f, 0x45, + 0x5e, 0x82, 0x50, 0x2f, 0x4b, 0x06, 0xab, 0x2b, 0xc4, 0x29, 0x52, 0x83, 0x3a, 0xc3, 0x11, 0x5f, + 0x20, 0x53, 0x1d, 0x10, 0x93, 0x17, 0x08, 0x7f, 0x94, 0xec, 0xbb, 0x88, 0x54, 0xf1, 0xc8, 0x68, + 0x02, 0x95, 0x95, 0xee, 0x8c, 0x25, 0x43, 0x6d, 0x24, 0xb1, 0xbe, 0x44, 0x78, 0x48, 0x68, 0xad, + 0xc8, 0x0d, 0x99, 0xe5, 0x3b, 0xb5, 0x70, 0xca, 0x97, 0x27, 0xf4, 0x02, 0x6c, 0xe6, 0x38, 0x9b, + 0xaf, 0x13, 0x35, 0x83, 0x8d, 0xd0, 0x8e, 0x92, 0x57, 0xa8, 0x45, 0x4d, 0x20, 0xb2, 0xa5, 0x30, + 0x5d, 0x0b, 0x91, 0x2b, 0x3d, 0xd9, 0x3a, 0x8e, 0xba, 0xcc, 0xe1, 0x7f, 0x4a, 0x0a, 0x19, 0xf0, + 0xed, 0xb8, 0x5d, 0x23, 0xfd, 0xff, 0x88, 0x30, 0x49, 0xf8, 0x0c, 0x4e, 0x81, 0x6c, 0xc9, 0x38, + 0x09, 0x9b, 0x6c, 0xb5, 0x46, 0x2d, 0x70, 0x36, 0xb3, 0xe4, 0x92, 0x1c, 0x1b, 0xf2, 0x33, 0x84, + 0x4f, 0xf1, 0xe2, 0xb3, 0x24, 0x19, 0x46, 0xb1, 0x3c, 0x5e, 0x3e, 0x96, 0x8d, 0xe4, 0x77, 0xd7, + 0x80, 0x0f, 0x16, 0x0f, 0xf2, 0xaf, 0x11, 0x1e, 0x12, 0x54, 0x1a, 0x72, 0xf5, 0x18, 0x2b, 0xc6, + 0x95, 0x9d, 0xee, 0xc0, 0x5e, 0xe1, 0x60, 0x35, 0xb2, 0xd0, 0x16, 0x6c, 0x4b, 0x73, 0xfd, 0x53, + 0x84, 0x3f, 0x8c, 0xbe, 0x40, 0x4b, 0x92, 0x3b, 0x7a, 0xec, 0xc0, 0x26, 0x94, 0x1a, 0x75, 0x9a, + 0x63, 0x9d, 0x24, 0x9f, 0xb4, 0xc1, 0x1a, 0x74, 0x60, 0x23, 0x09, 0x15, 0x40, 0xae, 0x05, 0x4b, + 0x57, 0x59, 0xe4, 0x5a, 0xb0, 0x0c, 0x41, 0xa5, 0x73, 0xe5, 0x10, 0x40, 0xfe, 0x0f, 0xe1, 0x7c, + 0x7b, 0xf9, 0x82, 0x6c, 0x76, 0x81, 0x25, 0x5d, 0x47, 0x51, 0xbe, 0xdb, 0x0b, 0x57, 0xc0, 0xf2, + 0x2a, 0x67, 0x79, 0x99, 0x2c, 0x76, 0x66, 0x99, 0x64, 0x14, 0xf4, 0xcb, 0xf1, 0x3f, 0x7f, 0x90, + 0x3b, 0x01, 0xa9, 0x7f, 0x50, 0xa1, 0x5c, 0xeb, 0xc6, 0x54, 0xb2, 0x95, 0x79, 0x12, 0x47, 0x19, + 0x00, 0x8f, 0xeb, 0x2e, 0x72, 0xc0, 0x53, 0x95, 0x1c, 0x39, 0xe0, 0xe9, 0x32, 0x4f, 0x47, 0xe0, + 0x76, 0x1c, 0x65, 0xd0, 0x2a, 0x24, 0x65, 0x01, 0xb9, 0x56, 0x21, 0x43, 0xc0, 0x90, 0x6b, 0x15, + 0xb2, 0xc4, 0x8d, 0x8e, 0xad, 0x42, 0x52, 0xaa, 0x58, 0xfd, 0xde, 0xab, 0x37, 0x79, 0xf4, 0xfa, + 0x4d, 0x1e, 0xfd, 0xe7, 0x4d, 0x1e, 0xfd, 0xe4, 0x6d, 0xbe, 0xef, 0xf5, 0xdb, 0x7c, 0xdf, 0x3f, + 0xde, 0xe6, 0xfb, 0xee, 0x2f, 0x9a, 0x96, 0x5f, 0xa9, 0xed, 0x16, 0x0c, 0x77, 0x4f, 0x74, 0x16, + 0x61, 0xd2, 0xea, 0xa2, 0x5f, 0xff, 0x60, 0x9f, 0x79, 0xbb, 0x1f, 0xf0, 0x6f, 0xf7, 0xe5, 0xff, + 0x07, 0x00, 0x00, 0xff, 0xff, 0x25, 0x12, 0xcf, 0x1a, 0x2c, 0x25, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -2146,7 +2266,9 @@ type QueryClient interface { // Queries a list of send items. CctxAll(ctx context.Context, in *QueryAllCctxRequest, opts ...grpc.CallOption) (*QueryAllCctxResponse, error) // Queries a list of pending cctxs. - CctxListPending(ctx context.Context, in *QueryListCctxPendingRequest, opts ...grpc.CallOption) (*QueryListCctxPendingResponse, error) + ListPendingCctx(ctx context.Context, in *QueryListPendingCctxRequest, opts ...grpc.CallOption) (*QueryListPendingCctxResponse, error) + // Queries a list of pending cctxs within rate limit. + ListPendingCctxWithinRateLimit(ctx context.Context, in *QueryListPendingCctxWithinRateLimitRequest, opts ...grpc.CallOption) (*QueryListPendingCctxWithinRateLimitResponse, error) ZetaAccounting(ctx context.Context, in *QueryZetaAccountingRequest, opts ...grpc.CallOption) (*QueryZetaAccountingResponse, error) // Queries a list of lastMetaHeight items. LastZetaHeight(ctx context.Context, in *QueryLastZetaHeightRequest, opts ...grpc.CallOption) (*QueryLastZetaHeightResponse, error) @@ -2315,9 +2437,18 @@ func (c *queryClient) CctxAll(ctx context.Context, in *QueryAllCctxRequest, opts return out, nil } -func (c *queryClient) CctxListPending(ctx context.Context, in *QueryListCctxPendingRequest, opts ...grpc.CallOption) (*QueryListCctxPendingResponse, error) { - out := new(QueryListCctxPendingResponse) - err := c.cc.Invoke(ctx, "/zetachain.zetacore.crosschain.Query/CctxListPending", in, out, opts...) +func (c *queryClient) ListPendingCctx(ctx context.Context, in *QueryListPendingCctxRequest, opts ...grpc.CallOption) (*QueryListPendingCctxResponse, error) { + out := new(QueryListPendingCctxResponse) + err := c.cc.Invoke(ctx, "/zetachain.zetacore.crosschain.Query/ListPendingCctx", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) ListPendingCctxWithinRateLimit(ctx context.Context, in *QueryListPendingCctxWithinRateLimitRequest, opts ...grpc.CallOption) (*QueryListPendingCctxWithinRateLimitResponse, error) { + out := new(QueryListPendingCctxWithinRateLimitResponse) + err := c.cc.Invoke(ctx, "/zetachain.zetacore.crosschain.Query/ListPendingCctxWithinRateLimit", in, out, opts...) if err != nil { return nil, err } @@ -2383,7 +2514,9 @@ type QueryServer interface { // Queries a list of send items. CctxAll(context.Context, *QueryAllCctxRequest) (*QueryAllCctxResponse, error) // Queries a list of pending cctxs. - CctxListPending(context.Context, *QueryListCctxPendingRequest) (*QueryListCctxPendingResponse, error) + ListPendingCctx(context.Context, *QueryListPendingCctxRequest) (*QueryListPendingCctxResponse, error) + // Queries a list of pending cctxs within rate limit. + ListPendingCctxWithinRateLimit(context.Context, *QueryListPendingCctxWithinRateLimitRequest) (*QueryListPendingCctxWithinRateLimitResponse, error) ZetaAccounting(context.Context, *QueryZetaAccountingRequest) (*QueryZetaAccountingResponse, error) // Queries a list of lastMetaHeight items. LastZetaHeight(context.Context, *QueryLastZetaHeightRequest) (*QueryLastZetaHeightResponse, error) @@ -2446,8 +2579,11 @@ func (*UnimplementedQueryServer) CctxByNonce(ctx context.Context, req *QueryGetC func (*UnimplementedQueryServer) CctxAll(ctx context.Context, req *QueryAllCctxRequest) (*QueryAllCctxResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CctxAll not implemented") } -func (*UnimplementedQueryServer) CctxListPending(ctx context.Context, req *QueryListCctxPendingRequest) (*QueryListCctxPendingResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method CctxListPending not implemented") +func (*UnimplementedQueryServer) ListPendingCctx(ctx context.Context, req *QueryListPendingCctxRequest) (*QueryListPendingCctxResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListPendingCctx not implemented") +} +func (*UnimplementedQueryServer) ListPendingCctxWithinRateLimit(ctx context.Context, req *QueryListPendingCctxWithinRateLimitRequest) (*QueryListPendingCctxWithinRateLimitResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListPendingCctxWithinRateLimit not implemented") } func (*UnimplementedQueryServer) ZetaAccounting(ctx context.Context, req *QueryZetaAccountingRequest) (*QueryZetaAccountingResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ZetaAccounting not implemented") @@ -2769,20 +2905,38 @@ func _Query_CctxAll_Handler(srv interface{}, ctx context.Context, dec func(inter return interceptor(ctx, in, info, handler) } -func _Query_CctxListPending_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryListCctxPendingRequest) +func _Query_ListPendingCctx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryListPendingCctxRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(QueryServer).CctxListPending(ctx, in) + return srv.(QueryServer).ListPendingCctx(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/zetachain.zetacore.crosschain.Query/CctxListPending", + FullMethod: "/zetachain.zetacore.crosschain.Query/ListPendingCctx", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).CctxListPending(ctx, req.(*QueryListCctxPendingRequest)) + return srv.(QueryServer).ListPendingCctx(ctx, req.(*QueryListPendingCctxRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_ListPendingCctxWithinRateLimit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryListPendingCctxWithinRateLimitRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ListPendingCctxWithinRateLimit(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zetachain.zetacore.crosschain.Query/ListPendingCctxWithinRateLimit", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ListPendingCctxWithinRateLimit(ctx, req.(*QueryListPendingCctxWithinRateLimitRequest)) } return interceptor(ctx, in, info, handler) } @@ -2914,8 +3068,12 @@ var _Query_serviceDesc = grpc.ServiceDesc{ Handler: _Query_CctxAll_Handler, }, { - MethodName: "CctxListPending", - Handler: _Query_CctxListPending_Handler, + MethodName: "ListPendingCctx", + Handler: _Query_ListPendingCctx_Handler, + }, + { + MethodName: "ListPendingCctxWithinRateLimit", + Handler: _Query_ListPendingCctxWithinRateLimit_Handler, }, { MethodName: "ZetaAccounting", @@ -4093,7 +4251,7 @@ func (m *QueryAllCctxResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *QueryListCctxPendingRequest) Marshal() (dAtA []byte, err error) { +func (m *QueryListPendingCctxRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -4103,12 +4261,12 @@ func (m *QueryListCctxPendingRequest) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *QueryListCctxPendingRequest) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryListPendingCctxRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryListCctxPendingRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryListPendingCctxRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -4126,7 +4284,77 @@ func (m *QueryListCctxPendingRequest) MarshalToSizedBuffer(dAtA []byte) (int, er return len(dAtA) - i, nil } -func (m *QueryListCctxPendingResponse) Marshal() (dAtA []byte, err error) { +func (m *QueryListPendingCctxResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryListPendingCctxResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryListPendingCctxResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.TotalPending != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.TotalPending)) + i-- + dAtA[i] = 0x10 + } + if len(m.CrossChainTx) > 0 { + for iNdEx := len(m.CrossChainTx) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.CrossChainTx[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryListPendingCctxWithinRateLimitRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryListPendingCctxWithinRateLimitRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryListPendingCctxWithinRateLimitRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Limit != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.Limit)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryListPendingCctxWithinRateLimitResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -4136,16 +4364,26 @@ func (m *QueryListCctxPendingResponse) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *QueryListCctxPendingResponse) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryListPendingCctxWithinRateLimitResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryListCctxPendingResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryListPendingCctxWithinRateLimitResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l + if m.RateLimitExceeded { + i-- + if m.RateLimitExceeded { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x18 + } if m.TotalPending != 0 { i = encodeVarintQuery(dAtA, i, uint64(m.TotalPending)) i-- @@ -4871,7 +5109,7 @@ func (m *QueryAllCctxResponse) Size() (n int) { return n } -func (m *QueryListCctxPendingRequest) Size() (n int) { +func (m *QueryListPendingCctxRequest) Size() (n int) { if m == nil { return 0 } @@ -4886,7 +5124,37 @@ func (m *QueryListCctxPendingRequest) Size() (n int) { return n } -func (m *QueryListCctxPendingResponse) Size() (n int) { +func (m *QueryListPendingCctxResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.CrossChainTx) > 0 { + for _, e := range m.CrossChainTx { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.TotalPending != 0 { + n += 1 + sovQuery(uint64(m.TotalPending)) + } + return n +} + +func (m *QueryListPendingCctxWithinRateLimitRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Limit != 0 { + n += 1 + sovQuery(uint64(m.Limit)) + } + return n +} + +func (m *QueryListPendingCctxWithinRateLimitResponse) Size() (n int) { if m == nil { return 0 } @@ -4901,6 +5169,9 @@ func (m *QueryListCctxPendingResponse) Size() (n int) { if m.TotalPending != 0 { n += 1 + sovQuery(uint64(m.TotalPending)) } + if m.RateLimitExceeded { + n += 2 + } return n } @@ -7921,7 +8192,7 @@ func (m *QueryAllCctxResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryListCctxPendingRequest) Unmarshal(dAtA []byte) error { +func (m *QueryListPendingCctxRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -7944,10 +8215,10 @@ func (m *QueryListCctxPendingRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryListCctxPendingRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QueryListPendingCctxRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryListCctxPendingRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryListPendingCctxRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -8009,7 +8280,7 @@ func (m *QueryListCctxPendingRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryListCctxPendingResponse) Unmarshal(dAtA []byte) error { +func (m *QueryListPendingCctxResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -8032,10 +8303,10 @@ func (m *QueryListCctxPendingResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryListCctxPendingResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryListPendingCctxResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryListCctxPendingResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryListPendingCctxResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -8112,6 +8383,198 @@ func (m *QueryListCctxPendingResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryListPendingCctxWithinRateLimitRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryListPendingCctxWithinRateLimitRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryListPendingCctxWithinRateLimitRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType) + } + m.Limit = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Limit |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryListPendingCctxWithinRateLimitResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryListPendingCctxWithinRateLimitResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryListPendingCctxWithinRateLimitResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CrossChainTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CrossChainTx = append(m.CrossChainTx, &CrossChainTx{}) + if err := m.CrossChainTx[len(m.CrossChainTx)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalPending", wireType) + } + m.TotalPending = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalPending |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RateLimitExceeded", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.RateLimitExceeded = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *QueryLastZetaHeightRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/x/crosschain/types/query.pb.gw.go b/x/crosschain/types/query.pb.gw.go index e25a590184..6a4aa48cdd 100644 --- a/x/crosschain/types/query.pb.gw.go +++ b/x/crosschain/types/query.pb.gw.go @@ -870,37 +870,73 @@ func local_request_Query_CctxAll_0(ctx context.Context, marshaler runtime.Marsha } var ( - filter_Query_CctxListPending_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} + filter_Query_ListPendingCctx_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) -func request_Query_CctxListPending_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryListCctxPendingRequest +func request_Query_ListPendingCctx_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryListPendingCctxRequest var metadata runtime.ServerMetadata if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_CctxListPending_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ListPendingCctx_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.CctxListPending(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.ListPendingCctx(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func local_request_Query_CctxListPending_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryListCctxPendingRequest +func local_request_Query_ListPendingCctx_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryListPendingCctxRequest var metadata runtime.ServerMetadata if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_CctxListPending_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ListPendingCctx_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.CctxListPending(ctx, &protoReq) + msg, err := server.ListPendingCctx(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_ListPendingCctxWithinRateLimit_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_ListPendingCctxWithinRateLimit_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryListPendingCctxWithinRateLimitRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ListPendingCctxWithinRateLimit_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.ListPendingCctxWithinRateLimit(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_ListPendingCctxWithinRateLimit_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryListPendingCctxWithinRateLimitRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ListPendingCctxWithinRateLimit_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ListPendingCctxWithinRateLimit(ctx, &protoReq) return msg, metadata, err } @@ -1356,7 +1392,30 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) - mux.Handle("GET", pattern_Query_CctxListPending_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle("GET", pattern_Query_ListPendingCctx_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ListPendingCctx_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ListPendingCctx_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ListPendingCctxWithinRateLimit_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream @@ -1367,7 +1426,7 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Query_CctxListPending_0(rctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_Query_ListPendingCctxWithinRateLimit_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { @@ -1375,7 +1434,7 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv return } - forward_Query_CctxListPending_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_Query_ListPendingCctxWithinRateLimit_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -1829,7 +1888,7 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) - mux.Handle("GET", pattern_Query_CctxListPending_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle("GET", pattern_Query_ListPendingCctx_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) @@ -1838,14 +1897,34 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Query_CctxListPending_0(rctx, inboundMarshaler, client, req, pathParams) + resp, md, err := request_Query_ListPendingCctx_0(rctx, inboundMarshaler, client, req, pathParams) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_Query_CctxListPending_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_Query_ListPendingCctx_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ListPendingCctxWithinRateLimit_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_ListPendingCctxWithinRateLimit_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ListPendingCctxWithinRateLimit_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -1947,7 +2026,9 @@ var ( pattern_Query_CctxAll_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"zeta-chain", "crosschain", "cctx"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_CctxListPending_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"zeta-chain", "crosschain", "cctxPending"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_ListPendingCctx_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"zeta-chain", "crosschain", "pendingCctx"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_ListPendingCctxWithinRateLimit_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"zeta-chain", "crosschain", "pendingCctxWithinRateLimit"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_ZetaAccounting_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"zeta-chain", "crosschain", "zetaAccounting"}, "", runtime.AssumeColonVerbOpt(false))) @@ -1991,7 +2072,9 @@ var ( forward_Query_CctxAll_0 = runtime.ForwardResponseMessage - forward_Query_CctxListPending_0 = runtime.ForwardResponseMessage + forward_Query_ListPendingCctx_0 = runtime.ForwardResponseMessage + + forward_Query_ListPendingCctxWithinRateLimit_0 = runtime.ForwardResponseMessage forward_Query_ZetaAccounting_0 = runtime.ForwardResponseMessage diff --git a/x/fungible/keeper/foreign_coins.go b/x/fungible/keeper/foreign_coins.go index ee424e92c1..5f0a31da4a 100644 --- a/x/fungible/keeper/foreign_coins.go +++ b/x/fungible/keeper/foreign_coins.go @@ -1,6 +1,8 @@ package keeper import ( + "strings" + "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" ethcommon "github.com/ethereum/go-ethereum/common" @@ -79,6 +81,22 @@ func (k Keeper) GetAllForeignCoins(ctx sdk.Context) (list []types.ForeignCoins) return } +// GetAllForeignERC20CoinMap returns all foreign ERC20 coins in a map of chainID -> asset -> coin +func (k Keeper) GetAllForeignERC20CoinMap(ctx sdk.Context) map[int64]map[string]types.ForeignCoins { + allForeignCoins := k.GetAllForeignCoins(ctx) + + erc20CoinMap := make(map[int64]map[string]types.ForeignCoins) + for _, c := range allForeignCoins { + if c.CoinType == coin.CoinType_ERC20 { + if _, found := erc20CoinMap[c.ForeignChainId]; !found { + erc20CoinMap[c.ForeignChainId] = make(map[string]types.ForeignCoins) + } + erc20CoinMap[c.ForeignChainId][strings.ToLower(c.Asset)] = c + } + } + return erc20CoinMap +} + // GetGasCoinForForeignCoin returns the gas coin for a given chain func (k Keeper) GetGasCoinForForeignCoin(ctx sdk.Context, chainID int64) (types.ForeignCoins, bool) { foreignCoinList := k.GetAllForeignCoinsForChain(ctx, chainID) diff --git a/x/observer/keeper/chain_params.go b/x/observer/keeper/chain_params.go index 7b5e0a246e..8c4d7301fb 100644 --- a/x/observer/keeper/chain_params.go +++ b/x/observer/keeper/chain_params.go @@ -71,3 +71,16 @@ func (k Keeper) GetSupportedChains(ctx sdk.Context) []*chains.Chain { } return c } + +// GetSupportedForeignChains returns the list of supported foreign chains +func (k Keeper) GetSupportedForeignChains(ctx sdk.Context) []*chains.Chain { + allChains := k.GetSupportedChains(ctx) + + foreignChains := make([]*chains.Chain, 0) + for _, chain := range allChains { + if !chain.IsZetaChain() { + foreignChains = append(foreignChains, chain) + } + } + return foreignChains +} diff --git a/zetaclient/evm/evm_signer.go b/zetaclient/evm/evm_signer.go index c0de8ea40b..d9b6eb25dd 100644 --- a/zetaclient/evm/evm_signer.go +++ b/zetaclient/evm/evm_signer.go @@ -567,7 +567,7 @@ func (signer *Signer) reportToOutTxTracker(zetaBridge interfaces.ZetaCoreBridger cctx, err := zetaBridge.GetCctxByNonce(chainID, nonce) if err != nil { logger.Err(err).Msgf("reportToOutTxTracker: error getting cctx for chain %d nonce %d outTxHash %s", chainID, nonce, outTxHash) - } else if !crosschainkeeper.IsPending(*cctx) { + } else if !crosschainkeeper.IsPending(cctx) { logger.Info().Msgf("reportToOutTxTracker: cctx already finalized for chain %d nonce %d outTxHash %s", chainID, nonce, outTxHash) break } diff --git a/zetaclient/interfaces/interfaces.go b/zetaclient/interfaces/interfaces.go index 387e764688..0fbaba26b3 100644 --- a/zetaclient/interfaces/interfaces.go +++ b/zetaclient/interfaces/interfaces.go @@ -98,6 +98,7 @@ type ZetaCoreBridger interface { GetZetaBlockHeight() (int64, error) GetLastBlockHeightByChain(chain chains.Chain) (*crosschaintypes.LastBlockHeight, error) ListPendingCctx(chainID int64) ([]*crosschaintypes.CrossChainTx, uint64, error) + ListPendingCctxWithinRatelimit() ([]*crosschaintypes.CrossChainTx, uint64, bool, error) GetPendingNoncesByChain(chainID int64) (observertypes.PendingNonces, error) GetCctxByNonce(chainID int64, nonce uint64) (*crosschaintypes.CrossChainTx, error) GetOutTxTracker(chain chains.Chain, nonce uint64) (*crosschaintypes.OutTxTracker, error) diff --git a/zetaclient/testutils/stub/core_bridge.go b/zetaclient/testutils/stub/core_bridge.go index 2f0ddaa732..e66c309cc6 100644 --- a/zetaclient/testutils/stub/core_bridge.go +++ b/zetaclient/testutils/stub/core_bridge.go @@ -121,6 +121,13 @@ func (z *MockZetaCoreBridge) ListPendingCctx(_ int64) ([]*cctxtypes.CrossChainTx return []*cctxtypes.CrossChainTx{}, 0, nil } +func (z *MockZetaCoreBridge) ListPendingCctxWithinRatelimit() ([]*cctxtypes.CrossChainTx, uint64, bool, error) { + if z.paused { + return nil, 0, false, errors.New(ErrMsgPaused) + } + return []*cctxtypes.CrossChainTx{}, 0, false, nil +} + func (z *MockZetaCoreBridge) GetPendingNoncesByChain(_ int64) (observerTypes.PendingNonces, error) { if z.paused { return observerTypes.PendingNonces{}, errors.New(ErrMsgPaused) diff --git a/zetaclient/zetabridge/query.go b/zetaclient/zetabridge/query.go index b9e08bef56..09d3b20e82 100644 --- a/zetaclient/zetabridge/query.go +++ b/zetaclient/zetabridge/query.go @@ -121,18 +121,38 @@ func (b *ZetaCoreBridge) GetObserverList() ([]string, error) { } // ListPendingCctx returns a list of pending cctxs for a given chainID -// the returned list has a limited size of crosschainkeeper.MaxPendingCctxs -// the total number of pending cctxs is returned +// - The max size of the list is crosschainkeeper.MaxPendingCctxs func (b *ZetaCoreBridge) ListPendingCctx(chainID int64) ([]*types.CrossChainTx, uint64, error) { client := types.NewQueryClient(b.grpcConn) maxSizeOption := grpc.MaxCallRecvMsgSize(32 * 1024 * 1024) - resp, err := client.CctxListPending(context.Background(), &types.QueryListCctxPendingRequest{ChainId: chainID}, maxSizeOption) + resp, err := client.ListPendingCctx( + context.Background(), + &types.QueryListPendingCctxRequest{ChainId: chainID}, + maxSizeOption, + ) if err != nil { return nil, 0, err } return resp.CrossChainTx, resp.TotalPending, 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 (b *ZetaCoreBridge) ListPendingCctxWithinRatelimit() ([]*types.CrossChainTx, uint64, bool, error) { + client := types.NewQueryClient(b.grpcConn) + maxSizeOption := grpc.MaxCallRecvMsgSize(32 * 1024 * 1024) + resp, err := client.ListPendingCctxWithinRateLimit( + context.Background(), + &types.QueryListPendingCctxWithinRateLimitRequest{}, + maxSizeOption, + ) + if err != nil { + return nil, 0, false, err + } + return resp.CrossChainTx, resp.TotalPending, resp.RateLimitExceeded, nil +} + func (b *ZetaCoreBridge) GetAbortedZetaAmount() (string, error) { client := types.NewQueryClient(b.grpcConn) resp, err := client.ZetaAccounting(context.Background(), &types.QueryZetaAccountingRequest{}) diff --git a/zetaclient/zetabridge/query_test.go b/zetaclient/zetabridge/query_test.go index 3844482dd3..ea76fa78fd 100644 --- a/zetaclient/zetabridge/query_test.go +++ b/zetaclient/zetabridge/query_test.go @@ -267,7 +267,7 @@ func TestZetaCoreBridge_GetObserverList(t *testing.T) { } func TestZetaCoreBridge_ListPendingCctx(t *testing.T) { - expectedOutput := crosschainTypes.QueryListCctxPendingResponse{ + expectedOutput := crosschainTypes.QueryListPendingCctxResponse{ CrossChainTx: []*crosschainTypes.CrossChainTx{ { Index: "cross-chain4456", @@ -275,8 +275,8 @@ func TestZetaCoreBridge_ListPendingCctx(t *testing.T) { }, TotalPending: 1, } - input := crosschainTypes.QueryListCctxPendingRequest{ChainId: 7000} - method := "/zetachain.zetacore.crosschain.Query/CctxListPending" + input := crosschainTypes.QueryListPendingCctxRequest{ChainId: 7000} + method := "/zetachain.zetacore.crosschain.Query/ListPendingCctx" server := setupMockServer(t, crosschainTypes.RegisterQueryServer, method, input, expectedOutput) server.Serve() defer closeMockServer(t, server) diff --git a/zetaclient/zetacore_observer.go b/zetaclient/zetacore_observer.go index 48771bc9bc..c66f15f50a 100644 --- a/zetaclient/zetacore_observer.go +++ b/zetaclient/zetacore_observer.go @@ -130,16 +130,29 @@ func (co *CoreObserver) startCctxScheduler(appContext *appcontext.AppContext) { } } - // Set Current Hot key burn rate + // set current hot key burn rate metrics.HotKeyBurnRate.Set(float64(co.ts.HotKeyBurnRate.GetBurnRate().Int64())) + // query pending cctxs across all foreign chains with rate limit + cctxMap, err := co.getAllPendingCctxWithRatelimit() + if err != nil { + co.logger.ZetaChainWatcher.Error().Err(err).Msgf("startCctxScheduler: queryPendingCctxWithRatelimit failed") + } + // schedule keysign for pending cctxs on each chain coreContext := appContext.ZetaCoreContext() supportedChains := coreContext.GetEnabledChains() for _, c := range supportedChains { - if c.ChainId == co.bridge.ZetaChain().ChainId { + if c.IsZetaChain() { + continue + } + // get cctxs from map and set pending transactions prometheus gauge + cctxList := cctxMap[c.ChainId] + metrics.PendingTxsPerChain.WithLabelValues(c.ChainName.String()).Set(float64(len(cctxList))) + if len(cctxList) == 0 { continue } + // update chain parameters for signer and chain client signer, err := co.GetUpdatedSigner(coreContext, c.ChainId) if err != nil { @@ -155,14 +168,6 @@ func (co *CoreObserver) startCctxScheduler(appContext *appcontext.AppContext) { continue } - cctxList, totalPending, err := co.bridge.ListPendingCctx(c.ChainId) - if err != nil { - co.logger.ZetaChainWatcher.Error().Err(err).Msgf("startCctxScheduler: ListPendingCctx failed for chain %d", c.ChainId) - continue - } - // Set Pending transactions prometheus gauge - metrics.PendingTxsPerChain.WithLabelValues(c.ChainName.String()).Set(float64(totalPending)) - // #nosec G701 range is verified zetaHeight := uint64(bn) if chains.IsEVMChain(c.ChainId) { @@ -184,6 +189,29 @@ func (co *CoreObserver) startCctxScheduler(appContext *appcontext.AppContext) { } } +// getAllPendingCctxWithRatelimit get pending cctxs across all foreign chains with rate limit +func (co *CoreObserver) getAllPendingCctxWithRatelimit() (map[int64][]*types.CrossChainTx, error) { + cctxList, totalPending, rateLimitExceeded, err := co.bridge.ListPendingCctxWithinRatelimit() + if err != nil { + return nil, err + } + if rateLimitExceeded { + co.logger.ZetaChainWatcher.Warn().Msgf("rate limit exceeded, fetched %d cctxs out of %d", len(cctxList), totalPending) + } + + // classify pending cctxs by chain id + cctxMap := make(map[int64][]*types.CrossChainTx) + for _, cctx := range cctxList { + chainID := cctx.GetCurrentOutTxParam().ReceiverChainId + if _, found := cctxMap[chainID]; !found { + cctxMap[chainID] = make([]*types.CrossChainTx, 0) + } + cctxMap[chainID] = append(cctxMap[chainID], cctx) + } + + return cctxMap, nil +} + // scheduleCctxEVM schedules evm outtx keysign on each ZetaChain block (the ticker) func (co *CoreObserver) scheduleCctxEVM( outTxMan *outtxprocessor.Processor,