diff --git a/CHANGELOG.md b/CHANGELOG.md index 0908f2f8b..9df469730 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -115,6 +115,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#2017](https://github.com/NibiruChain/nibiru/pull/2017) - fix(evm): Fix DynamicFeeTx gas cap parameters - [#2019](https://github.com/NibiruChain/nibiru/pull/2019) - chore(evm): enabled debug rpc api on localnet. - [#2020](https://github.com/NibiruChain/nibiru/pull/2020) - test(evm): e2e tests for debug namespace +- [#2022](https://github.com/NibiruChain/nibiru/pull/2022) - feat(evm): debug_traceCall method implemented - [#2023](https://github.com/NibiruChain/nibiru/pull/2023) - fix(evm)!: adjusted generation and parsing of the block bloom events #### Dapp modules: perp, spot, oracle, etc diff --git a/e2e/evm/test/debug_queries.test.ts b/e2e/evm/test/debug_queries.test.ts index c348d2c3f..934767b2c 100644 --- a/e2e/evm/test/debug_queries.test.ts +++ b/e2e/evm/test/debug_queries.test.ts @@ -1,7 +1,8 @@ import { describe, expect, it, beforeAll } from "@jest/globals" import { TransactionReceipt, parseEther } from "ethers" import { provider } from "./setup" -import { alice, deployContractTestERC20 } from "./utils" +import { alice, deployContractTestERC20, hexify } from "./utils" +import { TestERC20Compiled__factory } from "../types/ethers-contracts" describe("debug queries", () => { let contractAddress: string @@ -28,8 +29,7 @@ describe("debug queries", () => { blockHash = receipt.blockHash }, 20e3) - // TODO: impl in EVM: remove skip - it.skip("debug_traceBlockByNumber", async () => { + it("debug_traceBlockByNumber", async () => { const traceResult = await provider.send("debug_traceBlockByNumber", [ blockNumber, ]) @@ -37,7 +37,7 @@ describe("debug queries", () => { }) // TODO: impl in EVM: remove skip - it.skip("debug_traceBlockByHash", async () => { + it("debug_traceBlockByHash", async () => { const traceResult = await provider.send("debug_traceBlockByHash", [ blockHash, ]) @@ -50,6 +50,22 @@ describe("debug queries", () => { expectTrace([{ result: traceResult }]) }) + it("debug_traceCall", async () => { + const contractInterface = TestERC20Compiled__factory.createInterface() + const callData = contractInterface.encodeFunctionData("totalSupply") + const tx = { + to: contractAddress, + data: callData, + gas: hexify(1000_000), + } + const traceResult = await provider.send("debug_traceCall", [ + tx, + "latest", + {}, + ]) + expectTrace([{ result: traceResult }]) + }) + // TODO: impl in EVM: remove skip it.skip("debug_getBadBlocks", async () => { const traceResult = await provider.send("debug_getBadBlocks", [txHash]) diff --git a/eth/rpc/backend/backend.go b/eth/rpc/backend/backend.go index 776c4b0a6..aecadec75 100644 --- a/eth/rpc/backend/backend.go +++ b/eth/rpc/backend/backend.go @@ -122,6 +122,11 @@ type EVMBackend interface { config *evm.TraceConfig, block *tmrpctypes.ResultBlock, ) ([]*evm.TxTraceResult, error) + TraceCall( + txArgs evm.JsonTxArgs, + contextHeight rpc.BlockNumber, + config *evm.TraceConfig, + ) (interface{}, error) } var _ BackendI = (*Backend)(nil) diff --git a/eth/rpc/backend/evm_query_client_test.go b/eth/rpc/backend/evm_query_client_test.go index cb0d9eb9f..ee05fe7c2 100644 --- a/eth/rpc/backend/evm_query_client_test.go +++ b/eth/rpc/backend/evm_query_client_test.go @@ -57,6 +57,24 @@ func RegisterTraceTransaction( Return(&evm.QueryTraceTxResponse{Data: data}, nil) } +func RegisterTraceCall( + queryClient *mocks.EVMQueryClient, msgEthTx *evm.MsgEthereumTx, +) { + data := []byte{0x7b, 0x22, 0x74, 0x65, 0x73, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x22, 0x7d} + queryClient.On( + "TraceCall", + rpc.NewContextWithHeight(1), + &evm.QueryTraceTxRequest{ + Msg: msgEthTx, + BlockNumber: 1, + ChainId: TEST_CHAIN_ID_NUMBER(), + BlockMaxGas: -1, + TraceConfig: &evm.TraceConfig{}, + }, + ). + Return(&evm.QueryTraceTxResponse{Data: data}, nil) +} + func RegisterTraceTransactionError( queryClient *mocks.EVMQueryClient, msgEthTx *evm.MsgEthereumTx, ) { diff --git a/eth/rpc/backend/mocks/README.md b/eth/rpc/backend/mocks/README.md new file mode 100644 index 000000000..376dbe6de --- /dev/null +++ b/eth/rpc/backend/mocks/README.md @@ -0,0 +1,13 @@ +# Mocks Generation + +To generate mocks, install `mockery` tool: +https://vektra.github.io/mockery/latest/installation/ + +```bash +cd x/evm +mockery \ + --name QueryClient \ + --filename evm_query_client.go \ + --output ../../eth/rpc/backend/mocks \ + --structname EVMQueryClient +``` diff --git a/eth/rpc/backend/mocks/evm_query_client.go b/eth/rpc/backend/mocks/evm_query_client.go index 52eceb18e..301e84995 100644 --- a/eth/rpc/backend/mocks/evm_query_client.go +++ b/eth/rpc/backend/mocks/evm_query_client.go @@ -1,24 +1,23 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.45.0. DO NOT EDIT. package mocks import ( context "context" + evm "github.com/NibiruChain/nibiru/v2/x/evm" grpc "google.golang.org/grpc" mock "github.com/stretchr/testify/mock" - - "github.com/NibiruChain/nibiru/v2/x/evm" ) -// EVMQueryClient is an autogenerated mock type for the EVMQueryClient type +// EVMQueryClient is an autogenerated mock type for the QueryClient type type EVMQueryClient struct { mock.Mock } -// EthAccount provides a mock function with given fields: ctx, in, opts -func (_m *EVMQueryClient) EthAccount(ctx context.Context, in *evm.QueryEthAccountRequest, opts ...grpc.CallOption) (*evm.QueryEthAccountResponse, error) { +// Balance provides a mock function with given fields: ctx, in, opts +func (_m *EVMQueryClient) Balance(ctx context.Context, in *evm.QueryBalanceRequest, opts ...grpc.CallOption) (*evm.QueryBalanceResponse, error) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] @@ -28,37 +27,15 @@ func (_m *EVMQueryClient) EthAccount(ctx context.Context, in *evm.QueryEthAccoun _ca = append(_ca, _va...) ret := _m.Called(_ca...) - var r0 *evm.QueryEthAccountResponse - if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryEthAccountRequest, ...grpc.CallOption) *evm.QueryEthAccountResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm.QueryEthAccountResponse) - } + if len(ret) == 0 { + panic("no return value specified for Balance") } + var r0 *evm.QueryBalanceResponse var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *evm.QueryEthAccountRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) + if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryBalanceRequest, ...grpc.CallOption) (*evm.QueryBalanceResponse, error)); ok { + return rf(ctx, in, opts...) } - - return r0, r1 -} - -// Balance provides a mock function with given fields: ctx, in, opts -func (_m *EVMQueryClient) Balance(ctx context.Context, in *evm.QueryBalanceRequest, opts ...grpc.CallOption) (*evm.QueryBalanceResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - var r0 *evm.QueryBalanceResponse if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryBalanceRequest, ...grpc.CallOption) *evm.QueryBalanceResponse); ok { r0 = rf(ctx, in, opts...) } else { @@ -67,7 +44,6 @@ func (_m *EVMQueryClient) Balance(ctx context.Context, in *evm.QueryBalanceReque } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *evm.QueryBalanceRequest, ...grpc.CallOption) error); ok { r1 = rf(ctx, in, opts...) } else { @@ -88,7 +64,15 @@ func (_m *EVMQueryClient) BaseFee(ctx context.Context, in *evm.QueryBaseFeeReque _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for BaseFee") + } + var r0 *evm.QueryBaseFeeResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryBaseFeeRequest, ...grpc.CallOption) (*evm.QueryBaseFeeResponse, error)); ok { + return rf(ctx, in, opts...) + } if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryBaseFeeRequest, ...grpc.CallOption) *evm.QueryBaseFeeResponse); ok { r0 = rf(ctx, in, opts...) } else { @@ -97,7 +81,6 @@ func (_m *EVMQueryClient) BaseFee(ctx context.Context, in *evm.QueryBaseFeeReque } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *evm.QueryBaseFeeRequest, ...grpc.CallOption) error); ok { r1 = rf(ctx, in, opts...) } else { @@ -118,7 +101,15 @@ func (_m *EVMQueryClient) Code(ctx context.Context, in *evm.QueryCodeRequest, op _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for Code") + } + var r0 *evm.QueryCodeResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryCodeRequest, ...grpc.CallOption) (*evm.QueryCodeResponse, error)); ok { + return rf(ctx, in, opts...) + } if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryCodeRequest, ...grpc.CallOption) *evm.QueryCodeResponse); ok { r0 = rf(ctx, in, opts...) } else { @@ -127,7 +118,6 @@ func (_m *EVMQueryClient) Code(ctx context.Context, in *evm.QueryCodeRequest, op } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *evm.QueryCodeRequest, ...grpc.CallOption) error); ok { r1 = rf(ctx, in, opts...) } else { @@ -148,7 +138,15 @@ func (_m *EVMQueryClient) EstimateGas(ctx context.Context, in *evm.EthCallReques _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for EstimateGas") + } + var r0 *evm.EstimateGasResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *evm.EthCallRequest, ...grpc.CallOption) (*evm.EstimateGasResponse, error)); ok { + return rf(ctx, in, opts...) + } if rf, ok := ret.Get(0).(func(context.Context, *evm.EthCallRequest, ...grpc.CallOption) *evm.EstimateGasResponse); ok { r0 = rf(ctx, in, opts...) } else { @@ -157,7 +155,6 @@ func (_m *EVMQueryClient) EstimateGas(ctx context.Context, in *evm.EthCallReques } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *evm.EthCallRequest, ...grpc.CallOption) error); ok { r1 = rf(ctx, in, opts...) } else { @@ -167,6 +164,43 @@ func (_m *EVMQueryClient) EstimateGas(ctx context.Context, in *evm.EthCallReques return r0, r1 } +// EthAccount provides a mock function with given fields: ctx, in, opts +func (_m *EVMQueryClient) EthAccount(ctx context.Context, in *evm.QueryEthAccountRequest, opts ...grpc.CallOption) (*evm.QueryEthAccountResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for EthAccount") + } + + var r0 *evm.QueryEthAccountResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryEthAccountRequest, ...grpc.CallOption) (*evm.QueryEthAccountResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryEthAccountRequest, ...grpc.CallOption) *evm.QueryEthAccountResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*evm.QueryEthAccountResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *evm.QueryEthAccountRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // EthCall provides a mock function with given fields: ctx, in, opts func (_m *EVMQueryClient) EthCall(ctx context.Context, in *evm.EthCallRequest, opts ...grpc.CallOption) (*evm.MsgEthereumTxResponse, error) { _va := make([]interface{}, len(opts)) @@ -178,7 +212,15 @@ func (_m *EVMQueryClient) EthCall(ctx context.Context, in *evm.EthCallRequest, o _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for EthCall") + } + var r0 *evm.MsgEthereumTxResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *evm.EthCallRequest, ...grpc.CallOption) (*evm.MsgEthereumTxResponse, error)); ok { + return rf(ctx, in, opts...) + } if rf, ok := ret.Get(0).(func(context.Context, *evm.EthCallRequest, ...grpc.CallOption) *evm.MsgEthereumTxResponse); ok { r0 = rf(ctx, in, opts...) } else { @@ -187,7 +229,6 @@ func (_m *EVMQueryClient) EthCall(ctx context.Context, in *evm.EthCallRequest, o } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *evm.EthCallRequest, ...grpc.CallOption) error); ok { r1 = rf(ctx, in, opts...) } else { @@ -197,6 +238,43 @@ func (_m *EVMQueryClient) EthCall(ctx context.Context, in *evm.EthCallRequest, o return r0, r1 } +// FunTokenMapping provides a mock function with given fields: ctx, in, opts +func (_m *EVMQueryClient) FunTokenMapping(ctx context.Context, in *evm.QueryFunTokenMappingRequest, opts ...grpc.CallOption) (*evm.QueryFunTokenMappingResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for FunTokenMapping") + } + + var r0 *evm.QueryFunTokenMappingResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryFunTokenMappingRequest, ...grpc.CallOption) (*evm.QueryFunTokenMappingResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryFunTokenMappingRequest, ...grpc.CallOption) *evm.QueryFunTokenMappingResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*evm.QueryFunTokenMappingResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *evm.QueryFunTokenMappingRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // Params provides a mock function with given fields: ctx, in, opts func (_m *EVMQueryClient) Params(ctx context.Context, in *evm.QueryParamsRequest, opts ...grpc.CallOption) (*evm.QueryParamsResponse, error) { _va := make([]interface{}, len(opts)) @@ -208,7 +286,15 @@ func (_m *EVMQueryClient) Params(ctx context.Context, in *evm.QueryParamsRequest _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for Params") + } + var r0 *evm.QueryParamsResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryParamsRequest, ...grpc.CallOption) (*evm.QueryParamsResponse, error)); ok { + return rf(ctx, in, opts...) + } if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryParamsRequest, ...grpc.CallOption) *evm.QueryParamsResponse); ok { r0 = rf(ctx, in, opts...) } else { @@ -217,7 +303,6 @@ func (_m *EVMQueryClient) Params(ctx context.Context, in *evm.QueryParamsRequest } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *evm.QueryParamsRequest, ...grpc.CallOption) error); ok { r1 = rf(ctx, in, opts...) } else { @@ -238,7 +323,15 @@ func (_m *EVMQueryClient) Storage(ctx context.Context, in *evm.QueryStorageReque _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for Storage") + } + var r0 *evm.QueryStorageResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryStorageRequest, ...grpc.CallOption) (*evm.QueryStorageResponse, error)); ok { + return rf(ctx, in, opts...) + } if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryStorageRequest, ...grpc.CallOption) *evm.QueryStorageResponse); ok { r0 = rf(ctx, in, opts...) } else { @@ -247,7 +340,6 @@ func (_m *EVMQueryClient) Storage(ctx context.Context, in *evm.QueryStorageReque } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *evm.QueryStorageRequest, ...grpc.CallOption) error); ok { r1 = rf(ctx, in, opts...) } else { @@ -268,7 +360,15 @@ func (_m *EVMQueryClient) TraceBlock(ctx context.Context, in *evm.QueryTraceBloc _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for TraceBlock") + } + var r0 *evm.QueryTraceBlockResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryTraceBlockRequest, ...grpc.CallOption) (*evm.QueryTraceBlockResponse, error)); ok { + return rf(ctx, in, opts...) + } if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryTraceBlockRequest, ...grpc.CallOption) *evm.QueryTraceBlockResponse); ok { r0 = rf(ctx, in, opts...) } else { @@ -277,7 +377,6 @@ func (_m *EVMQueryClient) TraceBlock(ctx context.Context, in *evm.QueryTraceBloc } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *evm.QueryTraceBlockRequest, ...grpc.CallOption) error); ok { r1 = rf(ctx, in, opts...) } else { @@ -287,8 +386,8 @@ func (_m *EVMQueryClient) TraceBlock(ctx context.Context, in *evm.QueryTraceBloc return r0, r1 } -// TraceTx provides a mock function with given fields: ctx, in, opts -func (_m *EVMQueryClient) TraceTx(ctx context.Context, in *evm.QueryTraceTxRequest, opts ...grpc.CallOption) (*evm.QueryTraceTxResponse, error) { +// TraceCall provides a mock function with given fields: ctx, in, opts +func (_m *EVMQueryClient) TraceCall(ctx context.Context, in *evm.QueryTraceTxRequest, opts ...grpc.CallOption) (*evm.QueryTraceTxResponse, error) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] @@ -298,7 +397,15 @@ func (_m *EVMQueryClient) TraceTx(ctx context.Context, in *evm.QueryTraceTxReque _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for TraceCall") + } + var r0 *evm.QueryTraceTxResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryTraceTxRequest, ...grpc.CallOption) (*evm.QueryTraceTxResponse, error)); ok { + return rf(ctx, in, opts...) + } if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryTraceTxRequest, ...grpc.CallOption) *evm.QueryTraceTxResponse); ok { r0 = rf(ctx, in, opts...) } else { @@ -307,7 +414,6 @@ func (_m *EVMQueryClient) TraceTx(ctx context.Context, in *evm.QueryTraceTxReque } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *evm.QueryTraceTxRequest, ...grpc.CallOption) error); ok { r1 = rf(ctx, in, opts...) } else { @@ -317,8 +423,8 @@ func (_m *EVMQueryClient) TraceTx(ctx context.Context, in *evm.QueryTraceTxReque return r0, r1 } -// ValidatorAccount provides a mock function with given fields: ctx, in, opts -func (_m *EVMQueryClient) ValidatorAccount(ctx context.Context, in *evm.QueryValidatorAccountRequest, opts ...grpc.CallOption) (*evm.QueryValidatorAccountResponse, error) { +// TraceTx provides a mock function with given fields: ctx, in, opts +func (_m *EVMQueryClient) TraceTx(ctx context.Context, in *evm.QueryTraceTxRequest, opts ...grpc.CallOption) (*evm.QueryTraceTxResponse, error) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] @@ -328,17 +434,24 @@ func (_m *EVMQueryClient) ValidatorAccount(ctx context.Context, in *evm.QueryVal _ca = append(_ca, _va...) ret := _m.Called(_ca...) - var r0 *evm.QueryValidatorAccountResponse - if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryValidatorAccountRequest, ...grpc.CallOption) *evm.QueryValidatorAccountResponse); ok { + if len(ret) == 0 { + panic("no return value specified for TraceTx") + } + + var r0 *evm.QueryTraceTxResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryTraceTxRequest, ...grpc.CallOption) (*evm.QueryTraceTxResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryTraceTxRequest, ...grpc.CallOption) *evm.QueryTraceTxResponse); ok { r0 = rf(ctx, in, opts...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm.QueryValidatorAccountResponse) + r0 = ret.Get(0).(*evm.QueryTraceTxResponse) } } - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *evm.QueryValidatorAccountRequest, ...grpc.CallOption) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *evm.QueryTraceTxRequest, ...grpc.CallOption) error); ok { r1 = rf(ctx, in, opts...) } else { r1 = ret.Error(1) @@ -347,8 +460,8 @@ func (_m *EVMQueryClient) ValidatorAccount(ctx context.Context, in *evm.QueryVal return r0, r1 } -// FunTokenMapping provides a mock function with given fields: ctx, in, opts -func (_m *EVMQueryClient) FunTokenMapping(ctx context.Context, in *evm.QueryFunTokenMappingRequest, opts ...grpc.CallOption) (*evm.QueryFunTokenMappingResponse, error) { +// ValidatorAccount provides a mock function with given fields: ctx, in, opts +func (_m *EVMQueryClient) ValidatorAccount(ctx context.Context, in *evm.QueryValidatorAccountRequest, opts ...grpc.CallOption) (*evm.QueryValidatorAccountResponse, error) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] @@ -358,17 +471,24 @@ func (_m *EVMQueryClient) FunTokenMapping(ctx context.Context, in *evm.QueryFunT _ca = append(_ca, _va...) ret := _m.Called(_ca...) - var r0 *evm.QueryFunTokenMappingResponse - if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryFunTokenMappingRequest, ...grpc.CallOption) *evm.QueryFunTokenMappingResponse); ok { + if len(ret) == 0 { + panic("no return value specified for ValidatorAccount") + } + + var r0 *evm.QueryValidatorAccountResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryValidatorAccountRequest, ...grpc.CallOption) (*evm.QueryValidatorAccountResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *evm.QueryValidatorAccountRequest, ...grpc.CallOption) *evm.QueryValidatorAccountResponse); ok { r0 = rf(ctx, in, opts...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm.QueryFunTokenMappingResponse) + r0 = ret.Get(0).(*evm.QueryValidatorAccountResponse) } } - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *evm.QueryFunTokenMappingRequest, ...grpc.CallOption) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *evm.QueryValidatorAccountRequest, ...grpc.CallOption) error); ok { r1 = rf(ctx, in, opts...) } else { r1 = ret.Error(1) @@ -377,13 +497,12 @@ func (_m *EVMQueryClient) FunTokenMapping(ctx context.Context, in *evm.QueryFunT return r0, r1 } -type mockConstructorTestingTNewEVMQueryClient interface { +// NewEVMQueryClient creates a new instance of EVMQueryClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewEVMQueryClient(t interface { mock.TestingT Cleanup(func()) -} - -// NewEVMQueryClient creates a new instance of EVMQueryClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewEVMQueryClient(t mockConstructorTestingTNewEVMQueryClient) *EVMQueryClient { +}) *EVMQueryClient { mock := &EVMQueryClient{} mock.Mock.Test(t) diff --git a/eth/rpc/backend/tracing.go b/eth/rpc/backend/tracing.go index fc19c7d32..1362aab4f 100644 --- a/eth/rpc/backend/tracing.go +++ b/eth/rpc/backend/tracing.go @@ -209,3 +209,54 @@ func (b *Backend) TraceBlock(height rpc.BlockNumber, return decodedResults, nil } + +// TraceCall implements eth debug_traceCall method which lets you run an eth_call +// within the context of the given block execution using the final state of parent block as the base. +// Method returns the structured logs created during the execution of EVM. +// The method returns the same output as debug_traceTransaction. +// https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-debug#debugtracecall +func (b *Backend) TraceCall( + txArgs evm.JsonTxArgs, + contextBlock rpc.BlockNumber, + config *evm.TraceConfig, +) (interface{}, error) { + blk, err := b.TendermintBlockByNumber(contextBlock) + if err != nil { + b.logger.Debug("block not found", "contextBlock", contextBlock) + return nil, err + } + nc, ok := b.clientCtx.Client.(tmrpcclient.NetworkClient) + if !ok { + return nil, errors.New("invalid rpc client") + } + + cp, err := nc.ConsensusParams(b.ctx, &blk.Block.Height) + if err != nil { + return nil, err + } + + traceTxRequest := evm.QueryTraceTxRequest{ + Msg: txArgs.ToMsgEthTx(), + Predecessors: nil, + BlockNumber: blk.Block.Height, + BlockTime: blk.Block.Time, + BlockHash: common.Bytes2Hex(blk.BlockID.Hash), + ProposerAddress: sdk.ConsAddress(blk.Block.ProposerAddress), + ChainId: b.chainID.Int64(), + BlockMaxGas: cp.ConsensusParams.Block.MaxGas, + } + + if config != nil { + traceTxRequest.TraceConfig = config + } + traceResult, err := b.queryClient.TraceCall(rpc.NewContextWithHeight(contextBlock.Int64()), &traceTxRequest) + if err != nil { + return nil, err + } + var decodedResult interface{} + err = json.Unmarshal(traceResult.Data, &decodedResult) + if err != nil { + return nil, err + } + return decodedResult, nil +} diff --git a/eth/rpc/backend/tracing_test.go b/eth/rpc/backend/tracing_test.go index f80f60f84..914524f55 100644 --- a/eth/rpc/backend/tracing_test.go +++ b/eth/rpc/backend/tracing_test.go @@ -2,6 +2,7 @@ package backend import ( "fmt" + "math/big" dbm "github.com/cometbft/cometbft-db" abci "github.com/cometbft/cometbft/abci/types" @@ -10,10 +11,12 @@ import ( "github.com/cometbft/cometbft/types" "github.com/cosmos/cosmos-sdk/crypto" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" gethcore "github.com/ethereum/go-ethereum/core/types" "github.com/NibiruChain/nibiru/v2/eth/crypto/ethsecp256k1" "github.com/NibiruChain/nibiru/v2/eth/indexer" + "github.com/NibiruChain/nibiru/v2/eth/rpc" "github.com/NibiruChain/nibiru/v2/eth/rpc/backend/mocks" "github.com/NibiruChain/nibiru/v2/x/evm" ) @@ -263,3 +266,56 @@ func (s *BackendSuite) TestTraceBlock() { }) } } + +func (s *BackendSuite) TestTraceCall() { + priv, _ := ethsecp256k1.GenerateKey() + from := common.BytesToAddress(priv.PubKey().Address().Bytes()) + + txArgs := evm.JsonTxArgs{ + From: &from, + Value: (*hexutil.Big)(big.NewInt(1e12)), + } + + testCases := []struct { + name string + registerMock func() + expResult interface{} + expPass bool + }{ + { + "pass - valid call", + func() { + var ( + queryClient = s.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) + client = s.backend.clientCtx.Client.(*mocks.Client) + height int64 = 1 + ) + + msgEthereumTx := txArgs.ToMsgEthTx() + + _, err := RegisterBlock(client, height, nil) + s.Require().NoError(err) + RegisterTraceCall(queryClient, msgEthereumTx) + RegisterConsensusParams(client, height) + }, + map[string]interface{}{"test": "hello"}, + true, + }, + } + + for _, tc := range testCases { + s.Run(fmt.Sprintf("case %s", tc.name), func() { + s.SetupTest() // reset test and queries + tc.registerMock() + + txResult, err := s.backend.TraceCall(txArgs, rpc.NewBlockNumber(big.NewInt(1)), &evm.TraceConfig{}) + + if tc.expPass { + s.Require().NoError(err) + s.Require().Equal(tc.expResult, txResult) + } else { + s.Require().Error(err) + } + }) + } +} diff --git a/eth/rpc/rpcapi/debugapi/api.go b/eth/rpc/rpcapi/debugapi/api.go index b8708eadc..ebb2cebaf 100644 --- a/eth/rpc/rpcapi/debugapi/api.go +++ b/eth/rpc/rpcapi/debugapi/api.go @@ -106,6 +106,27 @@ func (a *DebugAPI) TraceBlockByHash(hash common.Hash, config *evm.TraceConfig) ( return a.backend.TraceBlock(rpc.BlockNumber(resBlock.Block.Height), config, resBlock) } +// TraceCall implements eth debug_traceCall method which lets you run an eth_call +// within the context of the given block execution using the final state of parent block as the base. +// Method returns the structured logs created during the execution of EVM. +// The method returns the same output as debug_traceTransaction. +// https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-debug#debugtracecall +func (a *DebugAPI) TraceCall( + args evm.JsonTxArgs, + blockNrOrHash rpc.BlockNumberOrHash, + config *evm.TraceConfig, +) (interface{}, error) { + a.logger.Debug("debug_traceCall", args.String(), "block number or hash", blockNrOrHash) + + // Get Tendermint Block + resBlock, err := a.backend.BlockNumberFromTendermint(blockNrOrHash) + if err != nil { + a.logger.Debug("get block failed", "blockNrOrHash", blockNrOrHash, "error", err.Error()) + return nil, err + } + return a.backend.TraceCall(args, resBlock, config) +} + // BlockProfile turns on goroutine profiling for nsec seconds and writes profile data to // file. It uses a profile rate of 1 for most accurate information. If a different rate is // desired, set the rate and write the profile manually. diff --git a/proto/eth/evm/v1/query.proto b/proto/eth/evm/v1/query.proto index b0a5a8a24..f45b12153 100644 --- a/proto/eth/evm/v1/query.proto +++ b/proto/eth/evm/v1/query.proto @@ -66,6 +66,11 @@ service Query { option (google.api.http).get = "/nibiru/evm/v1/trace_block"; } + // TraceCall implements the `debug_traceCall` rpc api + rpc TraceCall(QueryTraceTxRequest) returns (QueryTraceTxResponse) { + option (google.api.http).get = "/nibiru/evm/v1/trace_call"; + } + // BaseFee queries the base fee of the parent block of the current block, // Similar to feemarket module's method rpc BaseFee(QueryBaseFeeRequest) returns (QueryBaseFeeResponse) { diff --git a/x/evm/keeper/grpc_query.go b/x/evm/keeper/grpc_query.go index fae288468..4509e5ed2 100644 --- a/x/evm/keeper/grpc_query.go +++ b/x/evm/keeper/grpc_query.go @@ -533,7 +533,94 @@ func (k Keeper) TraceTx( _ = json.Unmarshal([]byte(req.TraceConfig.TracerJsonConfig), &tracerConfig) } - result, _, err := k.TraceEthTxMsg(ctx, cfg, txConfig, signer, tx, req.TraceConfig, false, tracerConfig) + msg, err := tx.AsMessage(signer, cfg.BaseFee) + if err != nil { + return nil, err + } + + result, _, err := k.TraceEthTxMsg(ctx, cfg, txConfig, msg, req.TraceConfig, false, tracerConfig) + if err != nil { + // error will be returned with detail status from traceTx + return nil, err + } + + resultData, err := json.Marshal(result) + if err != nil { + return nil, grpcstatus.Error(grpccodes.Internal, err.Error()) + } + + return &evm.QueryTraceTxResponse{ + Data: resultData, + }, nil +} + +// TraceCall configures a new tracer according to the provided configuration, and +// executes the given message in the provided environment. The return value will +// be tracer dependent. +func (k Keeper) TraceCall( + goCtx context.Context, req *evm.QueryTraceTxRequest, +) (*evm.QueryTraceTxResponse, error) { + if err := req.Validate(); err != nil { + return nil, err + } + + // get the context of block beginning + contextHeight := req.BlockNumber + if contextHeight < 1 { + // 0 is a special value in `ContextWithHeight` + contextHeight = 1 + } + + ctx := sdk.UnwrapSDKContext(goCtx) + ctx = ctx.WithBlockHeight(contextHeight) + ctx = ctx.WithBlockTime(req.BlockTime) + ctx = ctx.WithHeaderHash(gethcommon.Hex2Bytes(req.BlockHash)) + + // to get the base fee we only need the block max gas in the consensus params + ctx = ctx.WithConsensusParams(&cmtproto.ConsensusParams{ + Block: &cmtproto.BlockParams{MaxGas: req.BlockMaxGas}, + }) + + chainID := k.EthChainID(ctx) + cfg, err := k.GetEVMConfig(ctx, ParseProposerAddr(ctx, req.ProposerAddress), chainID) + if err != nil { + return nil, grpcstatus.Errorf(grpccodes.Internal, "failed to load evm config: %s", err.Error()) + } + + // compute and use base fee of the height that is being traced + baseFee := k.GetBaseFee(ctx) + if baseFee != nil { + cfg.BaseFee = baseFee + } + + txConfig := statedb.NewEmptyTxConfig(gethcommon.BytesToHash(ctx.HeaderHash().Bytes())) + + var tracerConfig json.RawMessage + if req.TraceConfig != nil && req.TraceConfig.TracerJsonConfig != "" { + // ignore error. default to no traceConfig + _ = json.Unmarshal([]byte(req.TraceConfig.TracerJsonConfig), &tracerConfig) + } + + // req.Msg is not signed, so to gethcore.Message because it's not signed and will fail on getting + msgEthTx := req.Msg + txData, err := evm.UnpackTxData(req.Msg.Data) + if err != nil { + return nil, grpcstatus.Errorf(grpccodes.Internal, "failed to unpack tx data: %s", err.Error()) + } + msg := gethcore.NewMessage( + gethcommon.HexToAddress(msgEthTx.From), + txData.GetTo(), + txData.GetNonce(), + txData.GetValueWei(), + txData.GetGas(), + txData.GetGasPrice(), + txData.GetGasFeeCapWei(), + txData.GetGasTipCapWei(), + txData.GetData(), + txData.GetAccessList(), + false, + ) + result, _, err := k.TraceEthTxMsg(ctx, cfg, txConfig, msg, req.TraceConfig, false, tracerConfig) if err != nil { // error will be returned with detail status from traceTx return nil, err @@ -606,7 +693,12 @@ func (k Keeper) TraceBlock( ethTx := tx.AsTransaction() txConfig.TxHash = ethTx.Hash() txConfig.TxIndex = uint(i) - traceResult, logIndex, err := k.TraceEthTxMsg(ctx, cfg, txConfig, signer, ethTx, req.TraceConfig, true, nil) + msg, err := ethTx.AsMessage(signer, cfg.BaseFee) + if err != nil { + result.Error = err.Error() + continue + } + traceResult, logIndex, err := k.TraceEthTxMsg(ctx, cfg, txConfig, msg, req.TraceConfig, true, nil) if err != nil { result.Error = err.Error() } else { @@ -632,8 +724,7 @@ func (k *Keeper) TraceEthTxMsg( ctx sdk.Context, cfg *statedb.EVMConfig, txConfig statedb.TxConfig, - signer gethcore.Signer, - tx *gethcore.Transaction, + msg gethcore.Message, traceConfig *evm.TraceConfig, commitMessage bool, tracerJSONConfig json.RawMessage, @@ -645,11 +736,6 @@ func (k *Keeper) TraceEthTxMsg( err error timeout = DefaultGethTraceTimeout ) - msg, err := tx.AsMessage(signer, cfg.BaseFee) - if err != nil { - return nil, 0, grpcstatus.Error(grpccodes.Internal, err.Error()) - } - if traceConfig == nil { traceConfig = &evm.TraceConfig{} } diff --git a/x/evm/keeper/grpc_query_test.go b/x/evm/keeper/grpc_query_test.go index 9234bbe6b..6fc4da754 100644 --- a/x/evm/keeper/grpc_query_test.go +++ b/x/evm/keeper/grpc_query_test.go @@ -917,6 +917,88 @@ func (s *Suite) TestTraceBlock() { } } +func (s *Suite) TestTraceCall() { + type In = *evm.QueryTraceTxRequest + type Out = string + + testCases := []TestCase[In, Out]{ + { + name: "sad: nil query", + scenario: func(deps *evmtest.TestDeps) (req In, wantResp Out) { + return nil, "" + }, + wantErr: "InvalidArgument", + }, + { + name: "happy: simple nibi transfer tx", + scenario: func(deps *evmtest.TestDeps) (req In, wantResp Out) { + recipient := evmtest.NewEthPrivAcc().EthAddr + gas := uint64(21000) + txArgs := evm.JsonTxArgs{ + From: &deps.Sender.EthAddr, + To: &recipient, + Value: (*hexutil.Big)(big.NewInt(1e12)), + Gas: (*hexutil.Uint64)(&gas), + } + req = &evm.QueryTraceTxRequest{ + Msg: txArgs.ToMsgEthTx(), + } + wantResp = TraceNibiTransfer() + return req, wantResp + }, + wantErr: "", + }, + { + name: "happy: trace erc-20 transfer tx", + scenario: func(deps *evmtest.TestDeps) (req In, wantResp Out) { + s.T().Log("Deploy ERC20") + + deployResp, err := evmtest.DeployContract( + deps, embeds.SmartContract_TestERC20, + ) + s.Require().NoError(err) + data, err := deployResp.ContractData.ABI.Pack( + "transfer", evmtest.NewEthPrivAcc().EthAddr, new(big.Int).SetUint64(1000), + ) + s.Require().NoError(err) + gas := uint64(1e6) + + txArgs := evm.JsonTxArgs{ + From: &deps.Sender.EthAddr, + To: &deployResp.ContractAddr, + Data: (*hexutil.Bytes)(&data), + Gas: (*hexutil.Uint64)(&gas), + } + req = &evm.QueryTraceTxRequest{ + Msg: txArgs.ToMsgEthTx(), + } + wantResp = TraceERC20Transfer() + return req, wantResp + }, + wantErr: "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + deps := evmtest.NewTestDeps() + if tc.setup != nil { + tc.setup(&deps) + } + req, _ := tc.scenario(&deps) + goCtx := sdk.WrapSDKContext(deps.Ctx) + gotResp, err := deps.EvmKeeper.TraceCall(goCtx, req) + if tc.wantErr != "" { + s.Require().ErrorContains(err, tc.wantErr) + return + } + s.Assert().NoError(err) + s.Assert().NotNil(gotResp) + s.Assert().NotNil(gotResp.Data) + }) + } +} + func (s *Suite) TestQueryFunTokenMapping() { type In = *evm.QueryFunTokenMappingRequest type Out = *evm.QueryFunTokenMappingResponse diff --git a/x/evm/query.pb.go b/x/evm/query.pb.go index ba4c8e065..83b582c56 100644 --- a/x/evm/query.pb.go +++ b/x/evm/query.pb.go @@ -1342,104 +1342,105 @@ func init() { func init() { proto.RegisterFile("eth/evm/v1/query.proto", fileDescriptor_ffa36cdc5add14ed) } var fileDescriptor_ffa36cdc5add14ed = []byte{ - // 1549 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x56, 0xcf, 0x6f, 0x1b, 0xc5, - 0x17, 0x8f, 0x63, 0x27, 0x76, 0xc6, 0x69, 0x93, 0xef, 0x34, 0x6d, 0x12, 0x37, 0xb1, 0x93, 0xcd, - 0x97, 0x24, 0x2d, 0xed, 0x2e, 0x71, 0x11, 0x88, 0x8a, 0x4a, 0xd4, 0x51, 0x1a, 0x4a, 0x7f, 0xa8, - 0x5d, 0x22, 0x90, 0x40, 0xc8, 0x1a, 0xaf, 0x27, 0xbb, 0x2b, 0xdb, 0x3b, 0xee, 0xce, 0xd8, 0x75, - 0x28, 0xb9, 0xd0, 0x0b, 0x12, 0x42, 0xaa, 0xc4, 0x3f, 0xd0, 0x13, 0xff, 0x02, 0x7f, 0x00, 0x97, - 0xde, 0xa8, 0xc4, 0x05, 0x71, 0x28, 0xa8, 0xe5, 0xc0, 0x99, 0x23, 0x27, 0x34, 0xbf, 0xec, 0xb5, - 0xbd, 0x4e, 0xa8, 0x2a, 0x6e, 0x9c, 0x76, 0xf6, 0xcd, 0x9b, 0xcf, 0xfb, 0xcc, 0x9b, 0x99, 0xcf, - 0x7b, 0xe0, 0x0c, 0x66, 0x9e, 0x85, 0xdb, 0x0d, 0xab, 0xbd, 0x65, 0xdd, 0x6b, 0xe1, 0xf0, 0xc0, - 0x6c, 0x86, 0x84, 0x11, 0x08, 0x30, 0xf3, 0x4c, 0xdc, 0x6e, 0x98, 0xed, 0xad, 0xdc, 0x79, 0x87, - 0xd0, 0x06, 0xa1, 0x56, 0x05, 0x51, 0x2c, 0x9d, 0xac, 0xf6, 0x56, 0x05, 0x33, 0xb4, 0x65, 0x35, - 0x91, 0xeb, 0x07, 0x88, 0xf9, 0x24, 0x90, 0xeb, 0x72, 0x73, 0x11, 0x3c, 0xbe, 0x5c, 0x5a, 0x4f, - 0x45, 0xac, 0xac, 0xa3, 0x5d, 0x5d, 0xe2, 0x12, 0x31, 0xb4, 0xf8, 0x48, 0x59, 0x97, 0x5c, 0x42, - 0xdc, 0x3a, 0xb6, 0x50, 0xd3, 0xb7, 0x50, 0x10, 0x10, 0x26, 0xd0, 0xa9, 0x9a, 0x2d, 0xa8, 0x59, - 0xf1, 0x57, 0x69, 0xed, 0x5b, 0xcc, 0x6f, 0x60, 0xca, 0x50, 0xa3, 0x29, 0x1d, 0x8c, 0x77, 0xc1, - 0x99, 0xbb, 0x9c, 0xe1, 0x0e, 0xf3, 0xae, 0x3a, 0x0e, 0x69, 0x05, 0xcc, 0xc6, 0xf7, 0x5a, 0x98, - 0x32, 0xb8, 0x00, 0xd2, 0xa8, 0x5a, 0x0d, 0x31, 0xa5, 0x0b, 0x89, 0x95, 0xc4, 0xe6, 0x94, 0xad, - 0x7f, 0x2f, 0x67, 0xbe, 0x7a, 0x5c, 0x18, 0xfb, 0xe3, 0x71, 0x61, 0xcc, 0xf8, 0x31, 0x01, 0xe6, - 0x87, 0x96, 0xd3, 0x26, 0x09, 0x28, 0xe6, 0xeb, 0x2b, 0xa8, 0x8e, 0x02, 0x07, 0xeb, 0xf5, 0xea, - 0x17, 0x16, 0x40, 0x56, 0x0d, 0xcb, 0xf7, 0xb1, 0xbf, 0x30, 0x2e, 0x66, 0x81, 0x32, 0x7d, 0x8c, - 0x7d, 0x78, 0x16, 0x4c, 0x39, 0xa4, 0x8a, 0xcb, 0x1e, 0xa2, 0xde, 0x42, 0x52, 0x4c, 0x67, 0xb8, - 0xe1, 0x7d, 0x44, 0x3d, 0x38, 0x07, 0x26, 0x02, 0xc2, 0x51, 0x53, 0x2b, 0x89, 0xcd, 0x94, 0x2d, - 0x7f, 0x38, 0x26, 0x66, 0x5e, 0x59, 0x33, 0x9e, 0x90, 0x98, 0x98, 0x79, 0x57, 0xa5, 0x05, 0xbe, - 0x06, 0x4e, 0x56, 0xb0, 0xe3, 0x5d, 0x2a, 0x76, 0x7d, 0x26, 0x85, 0xcf, 0x09, 0x69, 0x55, 0x6e, - 0xc6, 0x0d, 0xb0, 0x24, 0x36, 0xf4, 0x11, 0xaa, 0xfb, 0x55, 0xc4, 0x48, 0x38, 0x90, 0x95, 0x55, - 0x30, 0xed, 0x90, 0x80, 0x96, 0xfb, 0x53, 0x93, 0xe5, 0xb6, 0xab, 0x43, 0xe9, 0xf9, 0x3a, 0x01, - 0x96, 0x47, 0xa0, 0xa9, 0x24, 0x6d, 0x80, 0x19, 0x24, 0x4d, 0x03, 0x88, 0x27, 0x95, 0x59, 0xd3, - 0xcf, 0x81, 0x0c, 0xe5, 0x14, 0xf8, 0xc6, 0xc7, 0xc5, 0xc6, 0xbb, 0xff, 0x7c, 0x6b, 0x1a, 0x24, - 0x68, 0x35, 0x2a, 0x38, 0x14, 0x39, 0x4b, 0xd9, 0x27, 0x94, 0xf5, 0xb6, 0x30, 0x1a, 0xef, 0x80, - 0x53, 0x82, 0x4c, 0x49, 0x26, 0xfa, 0x65, 0xce, 0xf9, 0x2e, 0x98, 0xeb, 0x5f, 0xfa, 0xca, 0x67, - 0x6c, 0xdc, 0x50, 0x6c, 0x3e, 0x64, 0x24, 0x44, 0xee, 0xf1, 0x6c, 0xe0, 0x2c, 0x48, 0xd6, 0xf0, - 0x81, 0x42, 0xe2, 0xc3, 0x08, 0xbf, 0x0b, 0x8a, 0x5f, 0x17, 0x4c, 0xf1, 0x9b, 0x03, 0x13, 0x6d, - 0x54, 0x6f, 0x69, 0x76, 0xf2, 0xc7, 0x78, 0x0b, 0xcc, 0x0a, 0xef, 0x6d, 0x52, 0x7d, 0xa9, 0x2c, - 0x6c, 0x80, 0xff, 0x45, 0xd6, 0xa9, 0x10, 0x10, 0xa4, 0xf8, 0xd5, 0x14, 0xab, 0xa6, 0x6d, 0x31, - 0x36, 0x3e, 0x07, 0x50, 0x38, 0xee, 0x75, 0x6e, 0x12, 0x97, 0xea, 0x10, 0x10, 0xa4, 0xc4, 0x85, - 0x96, 0xf8, 0x62, 0x0c, 0xaf, 0x01, 0xd0, 0x93, 0x04, 0xb1, 0xb7, 0x6c, 0x71, 0xdd, 0x94, 0xfa, - 0x61, 0x72, 0xfd, 0x30, 0xa5, 0xc8, 0x28, 0xfd, 0x30, 0xef, 0xf4, 0x52, 0x65, 0x47, 0x56, 0x46, - 0x48, 0x3e, 0x4c, 0xa8, 0xc4, 0xea, 0xe0, 0x8a, 0xe7, 0x1a, 0x48, 0xd5, 0x89, 0xcb, 0x77, 0x97, - 0xdc, 0xcc, 0x16, 0x67, 0xcc, 0x9e, 0x5e, 0x99, 0x37, 0x89, 0x6b, 0x8b, 0x49, 0xb8, 0x1b, 0x43, - 0x67, 0xe3, 0x58, 0x3a, 0x32, 0x42, 0x94, 0x8f, 0x31, 0xa7, 0x32, 0x70, 0x07, 0x85, 0xa8, 0xa1, - 0x33, 0x60, 0xec, 0x2a, 0x6a, 0xda, 0xaa, 0xa8, 0xbd, 0x01, 0x26, 0x9b, 0xc2, 0x22, 0x52, 0x93, - 0x2d, 0xc2, 0x28, 0x39, 0xe9, 0x5b, 0x4a, 0x3d, 0x79, 0x56, 0x18, 0xb3, 0x95, 0x9f, 0xf1, 0x7d, - 0x02, 0x9c, 0xdc, 0x61, 0xde, 0x36, 0xaa, 0xd7, 0x23, 0xd9, 0x45, 0xa1, 0x4b, 0xf5, 0x39, 0xf0, - 0x31, 0x9c, 0x07, 0x69, 0x17, 0xd1, 0xb2, 0x83, 0x9a, 0xea, 0xcd, 0x4c, 0xba, 0x88, 0x6e, 0xa3, - 0x26, 0xfc, 0x0c, 0xcc, 0x36, 0x43, 0xd2, 0x24, 0x14, 0x87, 0xdd, 0x77, 0xc7, 0xdf, 0xcc, 0x74, - 0xa9, 0xf8, 0xd7, 0xb3, 0x82, 0xe9, 0xfa, 0xcc, 0x6b, 0x55, 0x4c, 0x87, 0x34, 0x2c, 0x25, 0xe5, - 0xf2, 0x73, 0x91, 0x56, 0x6b, 0x16, 0x3b, 0x68, 0x62, 0x6a, 0x6e, 0xf7, 0x1e, 0xbc, 0x3d, 0xa3, - 0xb1, 0xf4, 0x63, 0x5d, 0x04, 0x19, 0xc7, 0x43, 0x7e, 0x50, 0xf6, 0xab, 0x42, 0xa5, 0x92, 0x76, - 0x5a, 0xfc, 0x5f, 0xaf, 0x1a, 0x1b, 0xe0, 0xd4, 0x0e, 0x65, 0x7e, 0x03, 0x31, 0xbc, 0x8b, 0x7a, - 0x29, 0x98, 0x05, 0x49, 0x17, 0x49, 0xf2, 0x29, 0x9b, 0x0f, 0x8d, 0x3f, 0x93, 0xfa, 0x1c, 0x43, - 0xe4, 0xe0, 0xbd, 0x8e, 0xde, 0xe7, 0xeb, 0x20, 0xd9, 0xa0, 0xae, 0xca, 0xd4, 0x62, 0x34, 0x53, - 0xb7, 0xa8, 0xbb, 0xc3, 0x3c, 0x1c, 0xe2, 0x56, 0x63, 0xaf, 0x63, 0x73, 0x2f, 0x78, 0x19, 0x4c, - 0x33, 0xbe, 0xbc, 0xec, 0x90, 0x60, 0xdf, 0x77, 0xc5, 0x1e, 0xb3, 0xc5, 0xf9, 0xe8, 0x2a, 0x01, - 0xbf, 0x2d, 0xa6, 0xed, 0x2c, 0xeb, 0xfd, 0xc0, 0x2b, 0x60, 0xba, 0x19, 0xe2, 0x2a, 0x76, 0x30, - 0xa5, 0x24, 0xa4, 0x0b, 0x29, 0x71, 0x71, 0x8e, 0x88, 0xd8, 0xe7, 0xce, 0x85, 0xb2, 0x52, 0x27, - 0x4e, 0x4d, 0x4b, 0xd2, 0x84, 0xc8, 0x43, 0x56, 0xd8, 0xa4, 0x20, 0xc1, 0x65, 0x00, 0xa4, 0x8b, - 0x78, 0x16, 0x52, 0x8e, 0xa7, 0x84, 0x45, 0x08, 0xfd, 0xb6, 0x9e, 0xe6, 0x35, 0x6b, 0x21, 0x2d, - 0xa8, 0xe7, 0x4c, 0x59, 0xd0, 0x4c, 0x5d, 0xd0, 0xcc, 0x3d, 0x5d, 0xd0, 0x4a, 0x19, 0x7e, 0x45, - 0x1e, 0xfd, 0x5a, 0x48, 0x28, 0x10, 0x3e, 0x13, 0x7b, 0xd2, 0x99, 0x7f, 0xe7, 0xa4, 0xa7, 0xfa, - 0x4e, 0x1a, 0x1a, 0xe0, 0x84, 0xa4, 0xdf, 0x40, 0x9d, 0x32, 0x3f, 0x5c, 0x10, 0xc9, 0xc0, 0x2d, - 0xd4, 0xd9, 0x45, 0xf4, 0x83, 0x54, 0x66, 0x7c, 0x36, 0x69, 0x67, 0x58, 0xa7, 0xec, 0x07, 0x55, - 0xdc, 0x31, 0xce, 0x2b, 0x1d, 0xeb, 0x9e, 0x79, 0x4f, 0x64, 0xaa, 0x88, 0x21, 0x7d, 0xb9, 0xf9, - 0xd8, 0xf8, 0x2e, 0xa9, 0x4a, 0xb7, 0x70, 0x2e, 0x71, 0xd4, 0xc8, 0x1d, 0x61, 0x1d, 0xfd, 0xd4, - 0x8f, 0xba, 0x23, 0xac, 0x43, 0x5f, 0xe9, 0x8e, 0xfc, 0x77, 0xc8, 0xc7, 0x1f, 0xb2, 0x71, 0x51, - 0xf5, 0x48, 0xd1, 0x73, 0x3a, 0xe2, 0x5c, 0x4f, 0x77, 0xcb, 0x34, 0xc5, 0xd7, 0xb0, 0x56, 0x7b, - 0xe3, 0x66, 0xb7, 0x04, 0x2b, 0xb3, 0x82, 0x78, 0x13, 0x64, 0xb8, 0x30, 0x97, 0xf7, 0xb1, 0xaa, - 0x72, 0xa5, 0xc5, 0x5f, 0x9e, 0x15, 0x4e, 0xcb, 0x1d, 0xd2, 0x6a, 0xcd, 0xf4, 0x89, 0xd5, 0x40, - 0xcc, 0x33, 0xaf, 0x07, 0x8c, 0x97, 0x67, 0xb1, 0xda, 0xb8, 0x02, 0xce, 0x0a, 0xb4, 0x6b, 0xad, - 0x60, 0x8f, 0xd4, 0x70, 0x70, 0x0b, 0x35, 0x9b, 0x7e, 0xe0, 0xea, 0x0b, 0x34, 0x07, 0x26, 0x18, - 0x37, 0xeb, 0xba, 0x29, 0x7e, 0x22, 0x45, 0xe6, 0x53, 0xd5, 0x25, 0x0d, 0x2d, 0x57, 0xa4, 0xb6, - 0xc0, 0xd4, 0x7e, 0x2b, 0x28, 0xf7, 0x30, 0xb2, 0xc5, 0xb9, 0xe8, 0x85, 0xd2, 0xeb, 0xec, 0xcc, - 0xbe, 0x1a, 0xf5, 0xc0, 0x8b, 0x3f, 0x64, 0xc1, 0x84, 0x40, 0x87, 0x0f, 0x13, 0x00, 0xf4, 0x3a, - 0x4b, 0x68, 0x44, 0x21, 0xe2, 0xbb, 0xd6, 0xdc, 0xda, 0x91, 0x3e, 0x92, 0x9e, 0x71, 0xe1, 0xcb, - 0x9f, 0x7e, 0xff, 0x76, 0x7c, 0x1d, 0xfe, 0xdf, 0x0a, 0xfc, 0x8a, 0x1f, 0xb6, 0xba, 0x0d, 0x38, - 0xef, 0x20, 0xa5, 0xaf, 0xf5, 0x40, 0x5d, 0xa4, 0x43, 0xf8, 0x38, 0x01, 0x66, 0x07, 0x1b, 0x38, - 0xb8, 0x39, 0x14, 0x67, 0x44, 0xc7, 0x98, 0x3b, 0xf7, 0x0f, 0x3c, 0x15, 0xaf, 0xb7, 0x05, 0xaf, - 0x2d, 0x68, 0x0d, 0xf0, 0x6a, 0xeb, 0x05, 0x3d, 0x76, 0xd1, 0x26, 0xf4, 0x10, 0xde, 0x07, 0xe9, - 0x92, 0x6e, 0xbc, 0x86, 0xc2, 0xf5, 0xf7, 0x7b, 0xb9, 0x95, 0xd1, 0x0e, 0x8a, 0xc6, 0x39, 0x41, - 0x63, 0x0d, 0xae, 0x0e, 0xd0, 0x50, 0xdd, 0x1b, 0x8d, 0xe4, 0xe6, 0x0b, 0x90, 0x56, 0x3d, 0x57, - 0x4c, 0xe0, 0xfe, 0xd6, 0x2e, 0x26, 0xf0, 0x40, 0xbb, 0x66, 0x98, 0x22, 0xf0, 0x26, 0x5c, 0x1f, - 0x08, 0x4c, 0xa5, 0x5f, 0x2f, 0xae, 0xf5, 0xa0, 0x86, 0x0f, 0x0e, 0x61, 0x0d, 0xa4, 0x78, 0x2f, - 0x06, 0x97, 0x86, 0x90, 0x23, 0xad, 0x5d, 0x6e, 0x79, 0xc4, 0xac, 0x0a, 0xba, 0x2e, 0x82, 0xae, - 0xc0, 0xfc, 0x40, 0x50, 0xde, 0xc9, 0x45, 0xb7, 0xea, 0x81, 0x49, 0xd9, 0x8b, 0xc0, 0xfc, 0x10, - 0x60, 0x5f, 0x9b, 0x93, 0x2b, 0x8c, 0x9c, 0x57, 0x21, 0x97, 0x45, 0xc8, 0x79, 0x78, 0x7a, 0x20, - 0xa4, 0xec, 0x6e, 0xa0, 0x0f, 0xd2, 0xaa, 0xb9, 0x81, 0xb9, 0x28, 0x54, 0x7f, 0xc7, 0x93, 0x5b, - 0x1d, 0x2d, 0xec, 0x3a, 0x50, 0x41, 0x04, 0x5a, 0x84, 0xf3, 0x31, 0x17, 0xdd, 0xe1, 0xf8, 0x04, - 0x64, 0x23, 0xed, 0xc8, 0x91, 0xe1, 0xfa, 0x76, 0x15, 0xd3, 0xc3, 0x18, 0x6b, 0x22, 0xd8, 0x32, - 0x3c, 0x3b, 0x18, 0x4c, 0xf9, 0x72, 0x7d, 0x84, 0x0d, 0x90, 0x56, 0xc5, 0x2d, 0xe6, 0xc2, 0xf4, - 0xb7, 0x3a, 0x31, 0x17, 0x66, 0xa0, 0x2e, 0x8e, 0xdc, 0x9f, 0x2c, 0x68, 0xac, 0x03, 0x0f, 0x00, - 0xe8, 0xc9, 0x6e, 0x8c, 0x80, 0x0c, 0xd5, 0xce, 0x18, 0x01, 0x19, 0xd6, 0x6d, 0xc3, 0x10, 0x71, - 0x97, 0x60, 0x2e, 0x36, 0xae, 0x10, 0x7f, 0xbe, 0x53, 0xa5, 0xd5, 0xb1, 0x6f, 0x32, 0x2a, 0xee, - 0xb1, 0x6f, 0xb2, 0x4f, 0xe6, 0x47, 0xee, 0x54, 0x6b, 0x3f, 0xfc, 0x26, 0x01, 0x66, 0x06, 0xe4, - 0x18, 0x6e, 0x0c, 0xc1, 0xc6, 0xeb, 0x7d, 0x6e, 0xf3, 0x78, 0x47, 0xc5, 0x63, 0x43, 0xf0, 0x58, - 0x85, 0x85, 0x01, 0x1e, 0xfb, 0xad, 0x40, 0xa8, 0xbd, 0xf5, 0x40, 0x7c, 0x0e, 0x4b, 0xef, 0x3d, - 0x79, 0x9e, 0x4f, 0x3c, 0x7d, 0x9e, 0x4f, 0xfc, 0xf6, 0x3c, 0x9f, 0x78, 0xf4, 0x22, 0x3f, 0xf6, - 0xf4, 0x45, 0x7e, 0xec, 0xe7, 0x17, 0xf9, 0xb1, 0x4f, 0xd6, 0x23, 0xf5, 0xf8, 0xb6, 0x00, 0xd9, - 0xe6, 0xd5, 0x54, 0x03, 0xb6, 0x8b, 0x56, 0x87, 0xa3, 0x56, 0x26, 0x45, 0xf9, 0xbf, 0xf4, 0x77, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xef, 0x87, 0xa2, 0xb5, 0x73, 0x11, 0x00, 0x00, + // 1568 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x56, 0x4f, 0x6f, 0x1b, 0x45, + 0x14, 0x8f, 0x63, 0x27, 0x76, 0x9e, 0xd3, 0x26, 0x4c, 0xd3, 0x26, 0x71, 0x12, 0x3b, 0xd9, 0x40, + 0x92, 0x96, 0x76, 0x97, 0xb8, 0x08, 0x44, 0x45, 0x25, 0xea, 0x28, 0x0d, 0xa5, 0x7f, 0xd4, 0x9a, + 0x08, 0x24, 0x10, 0xb2, 0xc6, 0xf6, 0x64, 0xbd, 0x8a, 0xbd, 0xe3, 0x7a, 0xc6, 0xae, 0x43, 0xc9, + 0x85, 0x5e, 0x90, 0x10, 0x52, 0x25, 0xbe, 0x40, 0x4f, 0x7c, 0x04, 0xf8, 0x0a, 0xbd, 0x51, 0x89, + 0x0b, 0xe2, 0x50, 0x50, 0xcb, 0x81, 0x33, 0x47, 0x4e, 0x68, 0xfe, 0xd9, 0x6b, 0x7b, 0x9d, 0x50, + 0x15, 0x6e, 0x9c, 0x76, 0xe6, 0xcd, 0x7b, 0xbf, 0xf7, 0x9b, 0x37, 0x6f, 0xdf, 0x7b, 0x70, 0x86, + 0xf0, 0x8a, 0x43, 0x5a, 0x35, 0xa7, 0xb5, 0xe9, 0xdc, 0x6d, 0x92, 0xc6, 0x81, 0x5d, 0x6f, 0x50, + 0x4e, 0x11, 0x10, 0x5e, 0xb1, 0x49, 0xab, 0x66, 0xb7, 0x36, 0x53, 0xe7, 0x4a, 0x94, 0xd5, 0x28, + 0x73, 0x8a, 0x98, 0x11, 0xa5, 0xe4, 0xb4, 0x36, 0x8b, 0x84, 0xe3, 0x4d, 0xa7, 0x8e, 0x5d, 0xcf, + 0xc7, 0xdc, 0xa3, 0xbe, 0xb2, 0x4b, 0xcd, 0x04, 0xf0, 0x84, 0xb9, 0x92, 0x9e, 0x0a, 0x48, 0x79, + 0xdb, 0xa8, 0xba, 0xd4, 0xa5, 0x72, 0xe9, 0x88, 0x95, 0x96, 0x2e, 0xba, 0x94, 0xba, 0x55, 0xe2, + 0xe0, 0xba, 0xe7, 0x60, 0xdf, 0xa7, 0x5c, 0xa2, 0x33, 0x7d, 0x9a, 0xd1, 0xa7, 0x72, 0x57, 0x6c, + 0xee, 0x39, 0xdc, 0xab, 0x11, 0xc6, 0x71, 0xad, 0xae, 0x14, 0xac, 0x77, 0xe1, 0xcc, 0x1d, 0xc1, + 0x70, 0x9b, 0x57, 0xae, 0x94, 0x4a, 0xb4, 0xe9, 0xf3, 0x3c, 0xb9, 0xdb, 0x24, 0x8c, 0xa3, 0x39, + 0x88, 0xe3, 0x72, 0xb9, 0x41, 0x18, 0x9b, 0x8b, 0x2c, 0x47, 0x36, 0x26, 0xf2, 0x66, 0x7b, 0x29, + 0xf1, 0xd5, 0xa3, 0xcc, 0xc8, 0x1f, 0x8f, 0x32, 0x23, 0xd6, 0x8f, 0x11, 0x98, 0x1d, 0x30, 0x67, + 0x75, 0xea, 0x33, 0x22, 0xec, 0x8b, 0xb8, 0x8a, 0xfd, 0x12, 0x31, 0xf6, 0x7a, 0x8b, 0x32, 0x90, + 0xd4, 0xcb, 0xc2, 0x3d, 0xe2, 0xcd, 0x8d, 0xca, 0x53, 0xd0, 0xa2, 0x8f, 0x89, 0x87, 0x16, 0x60, + 0xa2, 0x44, 0xcb, 0xa4, 0x50, 0xc1, 0xac, 0x32, 0x17, 0x95, 0xc7, 0x09, 0x21, 0x78, 0x1f, 0xb3, + 0x0a, 0x9a, 0x81, 0x31, 0x9f, 0x0a, 0xd4, 0xd8, 0x72, 0x64, 0x23, 0x96, 0x57, 0x1b, 0x81, 0x49, + 0x78, 0xa5, 0x60, 0x18, 0x8f, 0x29, 0x4c, 0xc2, 0x2b, 0x57, 0x94, 0x04, 0xbd, 0x06, 0x27, 0x8b, + 0xa4, 0x54, 0xb9, 0x98, 0xed, 0xe8, 0x8c, 0x4b, 0x9d, 0x13, 0x4a, 0xaa, 0xd5, 0xac, 0xeb, 0xb0, + 0x28, 0x2f, 0xf4, 0x11, 0xae, 0x7a, 0x65, 0xcc, 0x69, 0xa3, 0x2f, 0x2a, 0x2b, 0x30, 0x59, 0xa2, + 0x3e, 0x2b, 0xf4, 0x86, 0x26, 0x29, 0x64, 0x57, 0x06, 0xc2, 0xf3, 0x75, 0x04, 0x96, 0x86, 0xa0, + 0xe9, 0x20, 0xad, 0xc3, 0x14, 0x56, 0xa2, 0x3e, 0xc4, 0x93, 0x5a, 0x6c, 0xe8, 0xa7, 0x20, 0xc1, + 0x04, 0x05, 0x71, 0xf1, 0x51, 0x79, 0xf1, 0xce, 0x5e, 0x5c, 0xcd, 0x80, 0xf8, 0xcd, 0x5a, 0x91, + 0x34, 0x64, 0xcc, 0x62, 0xf9, 0x13, 0x5a, 0x7a, 0x4b, 0x0a, 0xad, 0x77, 0xe0, 0x94, 0x24, 0x93, + 0x53, 0x81, 0x7e, 0x91, 0x77, 0xbe, 0x03, 0x33, 0xbd, 0xa6, 0x2f, 0xfd, 0xc6, 0xd6, 0x75, 0xcd, + 0xe6, 0x43, 0x4e, 0x1b, 0xd8, 0x3d, 0x9e, 0x0d, 0x9a, 0x86, 0xe8, 0x3e, 0x39, 0xd0, 0x48, 0x62, + 0x19, 0xe0, 0x77, 0x5e, 0xf3, 0xeb, 0x80, 0x69, 0x7e, 0x33, 0x30, 0xd6, 0xc2, 0xd5, 0xa6, 0x61, + 0xa7, 0x36, 0xd6, 0x5b, 0x30, 0x2d, 0xb5, 0xb7, 0x68, 0xf9, 0x85, 0xa2, 0xb0, 0x0e, 0xaf, 0x04, + 0xec, 0xb4, 0x0b, 0x04, 0x31, 0x91, 0x9a, 0xd2, 0x6a, 0x32, 0x2f, 0xd7, 0xd6, 0xe7, 0x80, 0xa4, + 0xe2, 0x6e, 0xfb, 0x06, 0x75, 0x99, 0x71, 0x81, 0x20, 0x26, 0x13, 0x5a, 0xe1, 0xcb, 0x35, 0xba, + 0x0a, 0xd0, 0x2d, 0x09, 0xf2, 0x6e, 0xc9, 0xec, 0x9a, 0xad, 0xea, 0x87, 0x2d, 0xea, 0x87, 0xad, + 0x8a, 0x8c, 0xae, 0x1f, 0xf6, 0xed, 0x6e, 0xa8, 0xf2, 0x01, 0xcb, 0x00, 0xc9, 0x07, 0x11, 0x1d, + 0x58, 0xe3, 0x5c, 0xf3, 0x5c, 0x85, 0x58, 0x95, 0xba, 0xe2, 0x76, 0xd1, 0x8d, 0x64, 0x76, 0xca, + 0xee, 0xd6, 0x2b, 0xfb, 0x06, 0x75, 0xf3, 0xf2, 0x10, 0xed, 0x84, 0xd0, 0x59, 0x3f, 0x96, 0x8e, + 0xf2, 0x10, 0xe4, 0x63, 0xcd, 0xe8, 0x08, 0xdc, 0xc6, 0x0d, 0x5c, 0x33, 0x11, 0xb0, 0x76, 0x34, + 0x35, 0x23, 0xd5, 0xd4, 0xde, 0x80, 0xf1, 0xba, 0x94, 0xc8, 0xd0, 0x24, 0xb3, 0x28, 0x48, 0x4e, + 0xe9, 0xe6, 0x62, 0x8f, 0x9f, 0x66, 0x46, 0xf2, 0x5a, 0xcf, 0xfa, 0x21, 0x02, 0x27, 0xb7, 0x79, + 0x65, 0x0b, 0x57, 0xab, 0x81, 0xe8, 0xe2, 0x86, 0xcb, 0xcc, 0x3b, 0x88, 0x35, 0x9a, 0x85, 0xb8, + 0x8b, 0x59, 0xa1, 0x84, 0xeb, 0xfa, 0x9f, 0x19, 0x77, 0x31, 0xdb, 0xc2, 0x75, 0xf4, 0x19, 0x4c, + 0xd7, 0x1b, 0xb4, 0x4e, 0x19, 0x69, 0x74, 0xfe, 0x3b, 0xf1, 0xcf, 0x4c, 0xe6, 0xb2, 0x7f, 0x3d, + 0xcd, 0xd8, 0xae, 0xc7, 0x2b, 0xcd, 0xa2, 0x5d, 0xa2, 0x35, 0x47, 0x97, 0x72, 0xf5, 0xb9, 0xc0, + 0xca, 0xfb, 0x0e, 0x3f, 0xa8, 0x13, 0x66, 0x6f, 0x75, 0x7f, 0xf8, 0xfc, 0x94, 0xc1, 0x32, 0x3f, + 0xeb, 0x3c, 0x24, 0x4a, 0x15, 0xec, 0xf9, 0x05, 0xaf, 0x2c, 0xab, 0x54, 0x34, 0x1f, 0x97, 0xfb, + 0x6b, 0x65, 0x6b, 0x1d, 0x4e, 0x6d, 0x33, 0xee, 0xd5, 0x30, 0x27, 0x3b, 0xb8, 0x1b, 0x82, 0x69, + 0x88, 0xba, 0x58, 0x91, 0x8f, 0xe5, 0xc5, 0xd2, 0xfa, 0x33, 0x6a, 0xde, 0xb1, 0x81, 0x4b, 0x64, + 0xb7, 0x6d, 0xee, 0xf9, 0x3a, 0x44, 0x6b, 0xcc, 0xd5, 0x91, 0x9a, 0x0f, 0x46, 0xea, 0x26, 0x73, + 0xb7, 0x79, 0x85, 0x34, 0x48, 0xb3, 0xb6, 0xdb, 0xce, 0x0b, 0x2d, 0x74, 0x09, 0x26, 0xb9, 0x30, + 0x2f, 0x94, 0xa8, 0xbf, 0xe7, 0xb9, 0xf2, 0x8e, 0xc9, 0xec, 0x6c, 0xd0, 0x4a, 0xc2, 0x6f, 0xc9, + 0xe3, 0x7c, 0x92, 0x77, 0x37, 0xe8, 0x32, 0x4c, 0xd6, 0x1b, 0xa4, 0x4c, 0x4a, 0x84, 0x31, 0xda, + 0x60, 0x73, 0x31, 0x99, 0x38, 0x47, 0x78, 0xec, 0x51, 0x17, 0x85, 0xb2, 0x58, 0xa5, 0xa5, 0x7d, + 0x53, 0x92, 0xc6, 0x64, 0x1c, 0x92, 0x52, 0xa6, 0x0a, 0x12, 0x5a, 0x02, 0x50, 0x2a, 0xf2, 0xb7, + 0x50, 0xe5, 0x78, 0x42, 0x4a, 0x64, 0xa1, 0xdf, 0x32, 0xc7, 0xa2, 0x67, 0xcd, 0xc5, 0x25, 0xf5, + 0x94, 0xad, 0x1a, 0x9a, 0x6d, 0x1a, 0x9a, 0xbd, 0x6b, 0x1a, 0x5a, 0x2e, 0x21, 0x52, 0xe4, 0xe1, + 0xaf, 0x99, 0x88, 0x06, 0x11, 0x27, 0xa1, 0x2f, 0x9d, 0xf8, 0x6f, 0x5e, 0x7a, 0xa2, 0xe7, 0xa5, + 0x91, 0x05, 0x27, 0x14, 0xfd, 0x1a, 0x6e, 0x17, 0xc4, 0xe3, 0x42, 0x20, 0x02, 0x37, 0x71, 0x7b, + 0x07, 0xb3, 0x0f, 0x62, 0x89, 0xd1, 0xe9, 0x68, 0x3e, 0xc1, 0xdb, 0x05, 0xcf, 0x2f, 0x93, 0xb6, + 0x75, 0x4e, 0xd7, 0xb1, 0xce, 0x9b, 0x77, 0x8b, 0x4c, 0x19, 0x73, 0x6c, 0x92, 0x5b, 0xac, 0xad, + 0xef, 0xa2, 0xba, 0x75, 0x4b, 0xe5, 0x9c, 0x40, 0x0d, 0xe4, 0x08, 0x6f, 0x9b, 0x5f, 0xfd, 0xa8, + 0x1c, 0xe1, 0x6d, 0xf6, 0x52, 0x39, 0xf2, 0xff, 0x23, 0x1f, 0xff, 0xc8, 0xd6, 0x05, 0x3d, 0x23, + 0x05, 0xdf, 0xe9, 0x88, 0x77, 0x3d, 0xdd, 0x69, 0xd3, 0x8c, 0x5c, 0x25, 0xa6, 0xda, 0x5b, 0x37, + 0x3a, 0x2d, 0x58, 0x8b, 0x35, 0xc4, 0x9b, 0x90, 0x10, 0x85, 0xb9, 0xb0, 0x47, 0x74, 0x97, 0xcb, + 0xcd, 0xff, 0xf2, 0x34, 0x73, 0x5a, 0xdd, 0x90, 0x95, 0xf7, 0x6d, 0x8f, 0x3a, 0x35, 0xcc, 0x2b, + 0xf6, 0x35, 0x9f, 0x8b, 0xf6, 0x2c, 0xad, 0xad, 0xcb, 0xb0, 0x20, 0xd1, 0xae, 0x36, 0xfd, 0x5d, + 0xba, 0x4f, 0xfc, 0x9b, 0xb8, 0x5e, 0xf7, 0x7c, 0xd7, 0x24, 0xd0, 0x0c, 0x8c, 0x71, 0x21, 0x36, + 0x7d, 0x53, 0x6e, 0x02, 0x4d, 0xe6, 0x53, 0x3d, 0x25, 0x0d, 0x98, 0x6b, 0x52, 0x9b, 0x30, 0xb1, + 0xd7, 0xf4, 0x0b, 0x5d, 0x8c, 0x64, 0x76, 0x26, 0x98, 0x50, 0xc6, 0x2e, 0x9f, 0xd8, 0xd3, 0xab, + 0x2e, 0x78, 0xf6, 0xfb, 0x49, 0x18, 0x93, 0xe8, 0xe8, 0x41, 0x04, 0xa0, 0x3b, 0x59, 0x22, 0x2b, + 0x08, 0x11, 0x3e, 0xb5, 0xa6, 0x56, 0x8f, 0xd4, 0x51, 0xf4, 0xac, 0xf3, 0x5f, 0xfe, 0xf4, 0xfb, + 0xb7, 0xa3, 0x6b, 0xe8, 0x55, 0xc7, 0xf7, 0x8a, 0x5e, 0xa3, 0xd9, 0x19, 0xc0, 0xc5, 0x04, 0xa9, + 0x74, 0x9d, 0xfb, 0x3a, 0x91, 0x0e, 0xd1, 0xa3, 0x08, 0x4c, 0xf7, 0x0f, 0x70, 0x68, 0x63, 0xc0, + 0xcf, 0x90, 0x89, 0x31, 0x75, 0xf6, 0x1f, 0x68, 0x6a, 0x5e, 0x6f, 0x4b, 0x5e, 0x9b, 0xc8, 0xe9, + 0xe3, 0xd5, 0x32, 0x06, 0x5d, 0x76, 0xc1, 0x21, 0xf4, 0x10, 0xdd, 0x83, 0x78, 0xce, 0x0c, 0x5e, + 0x03, 0xee, 0x7a, 0xe7, 0xbd, 0xd4, 0xf2, 0x70, 0x05, 0x4d, 0xe3, 0xac, 0xa4, 0xb1, 0x8a, 0x56, + 0xfa, 0x68, 0xe8, 0xe9, 0x8d, 0x05, 0x62, 0xf3, 0x05, 0xc4, 0xf5, 0xcc, 0x15, 0xe2, 0xb8, 0x77, + 0xb4, 0x0b, 0x71, 0xdc, 0x37, 0xae, 0x59, 0xb6, 0x74, 0xbc, 0x81, 0xd6, 0xfa, 0x1c, 0x33, 0xa5, + 0xd7, 0xf5, 0xeb, 0xdc, 0xdf, 0x27, 0x07, 0x87, 0x68, 0x1f, 0x62, 0x62, 0x16, 0x43, 0x8b, 0x03, + 0xc8, 0x81, 0xd1, 0x2e, 0xb5, 0x34, 0xe4, 0x54, 0x3b, 0x5d, 0x93, 0x4e, 0x97, 0x51, 0xba, 0xcf, + 0xa9, 0x98, 0xe4, 0x82, 0x57, 0xad, 0xc0, 0xb8, 0x9a, 0x45, 0x50, 0x7a, 0x00, 0xb0, 0x67, 0xcc, + 0x49, 0x65, 0x86, 0x9e, 0x6b, 0x97, 0x4b, 0xd2, 0xe5, 0x2c, 0x3a, 0xdd, 0xe7, 0x52, 0x4d, 0x37, + 0xc8, 0x83, 0xb8, 0x1e, 0x6e, 0x50, 0x2a, 0x08, 0xd5, 0x3b, 0xf1, 0xa4, 0x56, 0x86, 0x17, 0x76, + 0xe3, 0x28, 0x23, 0x1d, 0xcd, 0xa3, 0xd9, 0x90, 0x44, 0x2f, 0x09, 0x7c, 0x0a, 0xc9, 0xc0, 0x38, + 0x72, 0xa4, 0xbb, 0x9e, 0x5b, 0x85, 0xcc, 0x30, 0xd6, 0xaa, 0x74, 0xb6, 0x84, 0x16, 0xfa, 0x9d, + 0x69, 0x5d, 0x51, 0x1f, 0x51, 0x0d, 0xe2, 0xba, 0xb9, 0x85, 0x24, 0x4c, 0xef, 0xa8, 0x13, 0x92, + 0x30, 0x7d, 0x7d, 0x71, 0xe8, 0xfd, 0x54, 0x43, 0xe3, 0x6d, 0x74, 0x00, 0xd0, 0x2d, 0xbb, 0x21, + 0x05, 0x64, 0xa0, 0x77, 0x86, 0x14, 0x90, 0xc1, 0xba, 0x6d, 0x59, 0xd2, 0xef, 0x22, 0x4a, 0x85, + 0xfa, 0x95, 0xc5, 0x1f, 0xdd, 0x85, 0x09, 0xd5, 0x37, 0x45, 0x9c, 0xff, 0x85, 0xbb, 0xae, 0x48, + 0x9f, 0x0b, 0x68, 0x3e, 0xd4, 0xa7, 0x7c, 0xcd, 0x9a, 0x28, 0x03, 0xb2, 0xc0, 0x87, 0x96, 0x81, + 0x60, 0x3f, 0x09, 0x2d, 0x03, 0x3d, 0x9d, 0x65, 0x68, 0x70, 0x4d, 0xbb, 0x41, 0xdf, 0x44, 0x60, + 0xaa, 0xaf, 0x03, 0xa0, 0xf5, 0x01, 0xd8, 0xf0, 0x16, 0x93, 0xda, 0x38, 0x5e, 0x51, 0xf3, 0x58, + 0x97, 0x3c, 0x56, 0x50, 0xa6, 0x8f, 0xc7, 0x5e, 0xd3, 0x97, 0x0d, 0xc6, 0xb9, 0x2f, 0x3f, 0x87, + 0xb9, 0xf7, 0x1e, 0x3f, 0x4b, 0x47, 0x9e, 0x3c, 0x4b, 0x47, 0x7e, 0x7b, 0x96, 0x8e, 0x3c, 0x7c, + 0x9e, 0x1e, 0x79, 0xf2, 0x3c, 0x3d, 0xf2, 0xf3, 0xf3, 0xf4, 0xc8, 0x27, 0x6b, 0x81, 0x11, 0xe0, + 0x96, 0x04, 0xd9, 0x12, 0x0d, 0xdc, 0x00, 0xb6, 0xb2, 0x4e, 0x5b, 0xa0, 0x16, 0xc7, 0xe5, 0xc4, + 0x71, 0xf1, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x51, 0x28, 0x9e, 0xd1, 0xe6, 0x11, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1477,6 +1478,8 @@ type QueryClient interface { TraceTx(ctx context.Context, in *QueryTraceTxRequest, opts ...grpc.CallOption) (*QueryTraceTxResponse, error) // TraceBlock implements the `debug_traceBlockByNumber` and `debug_traceBlockByHash` rpc api TraceBlock(ctx context.Context, in *QueryTraceBlockRequest, opts ...grpc.CallOption) (*QueryTraceBlockResponse, error) + // TraceCall implements the `debug_traceCall` rpc api + TraceCall(ctx context.Context, in *QueryTraceTxRequest, opts ...grpc.CallOption) (*QueryTraceTxResponse, error) // BaseFee queries the base fee of the parent block of the current block, // Similar to feemarket module's method BaseFee(ctx context.Context, in *QueryBaseFeeRequest, opts ...grpc.CallOption) (*QueryBaseFeeResponse, error) @@ -1581,6 +1584,15 @@ func (c *queryClient) TraceBlock(ctx context.Context, in *QueryTraceBlockRequest return out, nil } +func (c *queryClient) TraceCall(ctx context.Context, in *QueryTraceTxRequest, opts ...grpc.CallOption) (*QueryTraceTxResponse, error) { + out := new(QueryTraceTxResponse) + err := c.cc.Invoke(ctx, "/eth.evm.v1.Query/TraceCall", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *queryClient) BaseFee(ctx context.Context, in *QueryBaseFeeRequest, opts ...grpc.CallOption) (*QueryBaseFeeResponse, error) { out := new(QueryBaseFeeResponse) err := c.cc.Invoke(ctx, "/eth.evm.v1.Query/BaseFee", in, out, opts...) @@ -1624,6 +1636,8 @@ type QueryServer interface { TraceTx(context.Context, *QueryTraceTxRequest) (*QueryTraceTxResponse, error) // TraceBlock implements the `debug_traceBlockByNumber` and `debug_traceBlockByHash` rpc api TraceBlock(context.Context, *QueryTraceBlockRequest) (*QueryTraceBlockResponse, error) + // TraceCall implements the `debug_traceCall` rpc api + TraceCall(context.Context, *QueryTraceTxRequest) (*QueryTraceTxResponse, error) // BaseFee queries the base fee of the parent block of the current block, // Similar to feemarket module's method BaseFee(context.Context, *QueryBaseFeeRequest) (*QueryBaseFeeResponse, error) @@ -1664,6 +1678,9 @@ func (*UnimplementedQueryServer) TraceTx(ctx context.Context, req *QueryTraceTxR func (*UnimplementedQueryServer) TraceBlock(ctx context.Context, req *QueryTraceBlockRequest) (*QueryTraceBlockResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method TraceBlock not implemented") } +func (*UnimplementedQueryServer) TraceCall(ctx context.Context, req *QueryTraceTxRequest) (*QueryTraceTxResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method TraceCall not implemented") +} func (*UnimplementedQueryServer) BaseFee(ctx context.Context, req *QueryBaseFeeRequest) (*QueryBaseFeeResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method BaseFee not implemented") } @@ -1855,6 +1872,24 @@ func _Query_TraceBlock_Handler(srv interface{}, ctx context.Context, dec func(in return interceptor(ctx, in, info, handler) } +func _Query_TraceCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryTraceTxRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).TraceCall(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/eth.evm.v1.Query/TraceCall", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).TraceCall(ctx, req.(*QueryTraceTxRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Query_BaseFee_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(QueryBaseFeeRequest) if err := dec(in); err != nil { @@ -1935,6 +1970,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "TraceBlock", Handler: _Query_TraceBlock_Handler, }, + { + MethodName: "TraceCall", + Handler: _Query_TraceCall_Handler, + }, { MethodName: "BaseFee", Handler: _Query_BaseFee_Handler, diff --git a/x/evm/query.pb.gw.go b/x/evm/query.pb.gw.go index f34b01e01..7ed15c0b1 100644 --- a/x/evm/query.pb.gw.go +++ b/x/evm/query.pb.gw.go @@ -487,6 +487,42 @@ func local_request_Query_TraceBlock_0(ctx context.Context, marshaler runtime.Mar } +var ( + filter_Query_TraceCall_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_TraceCall_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryTraceTxRequest + 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_TraceCall_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.TraceCall(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_TraceCall_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryTraceTxRequest + 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_TraceCall_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.TraceCall(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_BaseFee_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryBaseFeeRequest var metadata runtime.ServerMetadata @@ -795,6 +831,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_TraceCall_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_TraceCall_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_TraceCall_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_BaseFee_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -1082,6 +1141,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_TraceCall_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_TraceCall_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_TraceCall_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_BaseFee_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -1146,6 +1225,8 @@ var ( pattern_Query_TraceBlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"nibiru", "evm", "v1", "trace_block"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_TraceCall_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"nibiru", "evm", "v1", "trace_call"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_BaseFee_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"nibiru", "evm", "v1", "base_fee"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_FunTokenMapping_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"nibiru", "evm", "v1", "funtoken", "token"}, "", runtime.AssumeColonVerbOpt(false))) @@ -1172,6 +1253,8 @@ var ( forward_Query_TraceBlock_0 = runtime.ForwardResponseMessage + forward_Query_TraceCall_0 = runtime.ForwardResponseMessage + forward_Query_BaseFee_0 = runtime.ForwardResponseMessage forward_Query_FunTokenMapping_0 = runtime.ForwardResponseMessage