Skip to content

Commit 296b5ea

Browse files
cloudgrayvladjdk
andauthored
feat(rpc): add debug_traceCall api (#711)
* add debug_traceBlock api * add test cases for debug_traceCall * chore: update CHANGELOG.md * add debug_traceBlock api * feat(rpc): add debug_getRawBlock api and fix debug_traceBlock api * test(rpc): fix test cases for debug apis * test(rpc): modify test case for debug_traceCall * chore: fix lint * fix test code * Merge branch 'main' into feat(rpc)-traceCall * chore: modify comments * fix(x/vm): apply default args to TraceCall method * test(jsonrpc): add type comparison of debug_traceCall response from evmd vs geth * chore: remove useless method call * fix: non-deterministic system test result * fix: non-deterministic system test result * fix: non-deterministic system test result * fix: non-deterministic system test result * fix: non-deterministic system test result * fix: non-deterministic system test result * fix: non-deterministic system test result * fix: non-deterministic system test result * fix: non-deterministic system test result * fix: return type of eth apis * fix: non-deterministic system test result * chore: non-deterministic calculation for query * fix: non-deterministic system test result * test: fix eth_feeHistory api test code * test: fix eth_feeHistory api test code --------- Co-authored-by: Vlad J <[email protected]>
1 parent 8c0698d commit 296b5ea

File tree

30 files changed

+3709
-662
lines changed

30 files changed

+3709
-662
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
- [\#684](https://github.com/cosmos/evm/pull/684) Add unit test cases for EIP-7702
5252
- [\#685](https://github.com/cosmos/evm/pull/685) Add EIP-7702 e2e test
5353
- [\#680](https://github.com/cosmos/evm/pull/680) Introduce a `StaticPrecompiles` builder
54+
- [\#691](https://github.com/cosmos/evm/pull/691) Add debug_traceCall api
5455
- [\#701](https://github.com/cosmos/evm/pull/701) Add address codec support to ERC20 IBC callbacks to handle hex addresses in addition to bech32 addresses.
5556
- [\#702](https://github.com/cosmos/evm/pull/702) Fix mempool e2e test
5657
- [\#704](https://github.com/cosmos/evm/pull/704) Fix EIP-7702 test cases

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ test-rpc-compat-stop:
381381
test-system: build-v04 build
382382
mkdir -p ./tests/systemtests/binaries/
383383
cp $(BUILDDIR)/evmd ./tests/systemtests/binaries/
384+
cd tests/systemtests/Counter && forge build
384385
$(MAKE) -C tests/systemtests test
385386

386387
build-v04:

api/cosmos/evm/vm/v1/query.pulsar.go

Lines changed: 1695 additions & 216 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/cosmos/evm/vm/v1/query_grpc.pb.go

Lines changed: 39 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

proto/cosmos/evm/vm/v1/query.proto

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ service Query {
7575
option (google.api.http).get = "/cosmos/evm/vm/v1/trace_block";
7676
}
7777

78+
// TraceCall implements the `debug_traceCall` rpc api
79+
rpc TraceCall(QueryTraceCallRequest) returns (QueryTraceCallResponse) {
80+
option (google.api.http).get = "/cosmos/evm/vm/v1/trace_call";
81+
}
82+
7883
// BaseFee queries the base fee of the parent block of the current block,
7984
// it's similar to feemarket module's method, but also checks london hardfork
8085
// status.
@@ -343,6 +348,32 @@ message QueryTraceBlockResponse {
343348
bytes data = 1;
344349
}
345350

351+
// QueryTraceCallRequest defines TraceCall request
352+
message QueryTraceCallRequest {
353+
// args uses the same json format as the json rpc api.
354+
bytes args = 1;
355+
// gas_cap defines the default gas cap to be used
356+
uint64 gas_cap = 2;
357+
// proposer_address of the requested block in hex format
358+
bytes proposer_address = 3 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.ConsAddress"];
359+
// trace_config holds extra parameters to trace functions.
360+
TraceConfig trace_config = 4;
361+
// block_number of requested transaction
362+
int64 block_number = 5;
363+
// block_hash of requested transaction
364+
string block_hash = 6;
365+
// block_time of requested transaction
366+
google.protobuf.Timestamp block_time = 7 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
367+
// chain_id is the the eip155 chain id parsed from the requested block header
368+
int64 chain_id = 8;
369+
}
370+
371+
// QueryTraceCallResponse defines TraceCall response
372+
message QueryTraceCallResponse {
373+
// data is the response serialized in bytes
374+
bytes data = 1;
375+
}
376+
346377
// QueryBaseFeeRequest defines the request type for querying the EIP1559 base
347378
// fee.
348379
message QueryBaseFeeRequest {}

rpc/backend/backend.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ type EVMBackend interface {
134134
// Tracing
135135
TraceTransaction(hash common.Hash, config *types.TraceConfig) (interface{}, error)
136136
TraceBlock(height types.BlockNumber, config *types.TraceConfig, block *tmrpctypes.ResultBlock) ([]*evmtypes.TxTraceResult, error)
137+
TraceCall(args evmtypes.TransactionArgs, blockNrOrHash types.BlockNumberOrHash, config *types.TraceConfig) (interface{}, error)
137138
}
138139

139140
var _ BackendI = (*Backend)(nil)

rpc/backend/chain_info.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ func (b *Backend) FeeHistory(
210210

211211
thisBaseFee := make([]*hexutil.Big, blocks+1)
212212
thisGasUsedRatio := make([]float64, blocks)
213+
thisBlobBaseFee := make([]*hexutil.Big, blocks+1)
214+
thisBlobGasUsedRatio := make([]float64, blocks)
213215

214216
// rewards should only be calculated if reward percentiles were included
215217
calculateRewards := rewardCount != 0
@@ -274,6 +276,11 @@ func (b *Backend) FeeHistory(
274276
thisBaseFee[index+1] = (*hexutil.Big)(oneFeeHistory.NextBaseFee)
275277
}
276278
thisGasUsedRatio[index] = oneFeeHistory.GasUsedRatio
279+
thisBlobBaseFee[index] = (*hexutil.Big)(oneFeeHistory.BlobBaseFee)
280+
if int(index) == len(thisBlobBaseFee)-2 {
281+
thisBlobBaseFee[index+1] = (*hexutil.Big)(oneFeeHistory.NextBlobBaseFee)
282+
}
283+
thisBlobGasUsedRatio[index] = oneFeeHistory.BlobGasUsedRatio
277284
if calculateRewards {
278285
for j := 0; j < rewardCount; j++ {
279286
reward[index][j] = (*hexutil.Big)(oneFeeHistory.Reward[j])
@@ -296,9 +303,11 @@ func (b *Backend) FeeHistory(
296303
}
297304

298305
feeHistory := rpctypes.FeeHistoryResult{
299-
OldestBlock: oldestBlock,
300-
BaseFee: thisBaseFee,
301-
GasUsedRatio: thisGasUsedRatio,
306+
OldestBlock: oldestBlock,
307+
BaseFee: thisBaseFee,
308+
GasUsedRatio: thisGasUsedRatio,
309+
BlobBaseFee: thisBlobBaseFee,
310+
BlobGasUsedRatio: thisBlobGasUsedRatio,
302311
}
303312

304313
if calculateRewards {

rpc/backend/mocks/evm_query_client.go

Lines changed: 37 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rpc/backend/tracing.go

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *rpctypes.TraceConfi
116116
// minus one to get the context of block beginning
117117
contextHeight := transaction.Height - 1
118118
if contextHeight < 1 {
119-
// 0 is a special value in `ContextWithHeight`
119+
// In Ethereum, the genesis block height is 0, but in CometBFT, the genesis block height is 1.
120+
// So here we set the minimum requested height to 1.
120121
contextHeight = 1
121122
}
122123
traceResult, err := b.QueryClient.TraceTx(rpctypes.ContextWithHeight(contextHeight), &traceTxRequest)
@@ -229,3 +230,69 @@ func (b *Backend) TraceBlock(height rpctypes.BlockNumber,
229230

230231
return decodedResults, nil
231232
}
233+
234+
// TraceCall executes a call with the given arguments and returns the structured logs
235+
// created during the execution of EVM. It returns them as a JSON object.
236+
func (b *Backend) TraceCall(
237+
args evmtypes.TransactionArgs,
238+
blockNrOrHash rpctypes.BlockNumberOrHash,
239+
config *rpctypes.TraceConfig,
240+
) (interface{}, error) {
241+
// Marshal tx args
242+
bz, err := json.Marshal(&args)
243+
if err != nil {
244+
return nil, err
245+
}
246+
247+
// Get block number from blockNrOrHash
248+
blockNr, err := b.BlockNumberFromComet(blockNrOrHash)
249+
if err != nil {
250+
return nil, err
251+
}
252+
253+
// Get the block to get necessary context
254+
header, err := b.CometHeaderByNumber(blockNr)
255+
if err != nil {
256+
b.Logger.Debug("block not found", "number", blockNr)
257+
return nil, err
258+
}
259+
260+
traceCallRequest := evmtypes.QueryTraceCallRequest{
261+
Args: bz,
262+
GasCap: b.RPCGasCap(),
263+
ProposerAddress: sdk.ConsAddress(header.Header.ProposerAddress),
264+
BlockNumber: header.Header.Height,
265+
BlockHash: common.Bytes2Hex(header.Header.Hash()),
266+
BlockTime: header.Header.Time,
267+
ChainId: b.EvmChainID.Int64(),
268+
}
269+
270+
if config != nil {
271+
traceCallRequest.TraceConfig = b.convertConfig(config)
272+
}
273+
274+
// get the context of provided block
275+
contextHeight := header.Header.Height
276+
if contextHeight < 1 {
277+
// In Ethereum, the genesis block height is 0, but in CometBFT, the genesis block height is 1.
278+
// So here we set the minimum requested height to 1.
279+
contextHeight = 1
280+
}
281+
282+
// Use the block height as context for the query
283+
ctxWithHeight := rpctypes.ContextWithHeight(contextHeight)
284+
traceResult, err := b.QueryClient.TraceCall(ctxWithHeight, &traceCallRequest)
285+
if err != nil {
286+
return nil, err
287+
}
288+
289+
// Response format is unknown due to custom tracer config param
290+
// More information can be found here https://geth.ethereum.org/docs/dapp/tracing-filtered
291+
var decodedResult interface{}
292+
err = json.Unmarshal(traceResult.Data, &decodedResult)
293+
if err != nil {
294+
return nil, err
295+
}
296+
297+
return decodedResult, nil
298+
}

0 commit comments

Comments
 (0)