Skip to content
This repository has been archived by the owner on Apr 4, 2024. It is now read-only.

RPC: debug_traceTransaction endpoint #506

Merged
merged 32 commits into from
Sep 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
2fe9a1e
fix typo
crypto-facs Aug 4, 2021
962e9e3
Merge branch 'main' into debug-trace
crypto-facs Aug 8, 2021
b8cc691
Added tracers package to debug API
crypto-facs Aug 8, 2021
5f87bd1
Add GetTransactionByHash function to backend package
crypto-facs Aug 8, 2021
5c94b61
merge conflicts
crypto-facs Aug 10, 2021
8ce8cdc
merge conflicts
crypto-facs Aug 12, 2021
a09e3b5
Merge branch 'main' into debug-trace
crypto-facs Aug 16, 2021
991269d
Merge branch 'main' into debug-trace
crypto-facs Aug 20, 2021
c0d9870
first version
crypto-facs Aug 23, 2021
d0711cd
traceTransaction first version
crypto-facs Aug 25, 2021
009504e
clean PR
crypto-facs Aug 27, 2021
6b12514
revert debug changes
crypto-facs Aug 27, 2021
6435413
merge conflicts
crypto-facs Aug 27, 2021
dc116d2
Update proto/ethermint/evm/v1/query.proto
crypto-facs Aug 30, 2021
2503d7b
remove unnecesary panic
crypto-facs Sep 2, 2021
9828b1a
remove internal debug api
crypto-facs Sep 2, 2021
ca5a4e9
trace transaction javascript tracer
crypto-facs Sep 2, 2021
b0fdc02
add support for custom logConfig
crypto-facs Sep 2, 2021
327cddc
added comment
crypto-facs Sep 2, 2021
c63a6cf
traceTransactions tests
crypto-facs Sep 3, 2021
2001bbf
resolve conflicts
crypto-facs Sep 3, 2021
f7a2721
fix linter
crypto-facs Sep 3, 2021
d9f53a5
remove unused
crypto-facs Sep 3, 2021
e2f6596
add comments to traceConfig
crypto-facs Sep 4, 2021
3660b0d
update dependencies
crypto-facs Sep 4, 2021
521dc12
fix merge conflicts
crypto-facs Sep 4, 2021
aa0897e
updated endpoints md
crypto-facs Sep 4, 2021
b95a1fd
Apply suggestions from code review
fedekunze Sep 4, 2021
7e8a53a
Update x/evm/keeper/grpc_query.go
crypto-facs Sep 4, 2021
81e06f4
Update x/evm/keeper/grpc_query.go
crypto-facs Sep 4, 2021
f91540a
update features changelog
crypto-facs Sep 4, 2021
80424e7
Merge branch 'debug-trace' of github.com:crypto-facs/ethermint into d…
crypto-facs Sep 4, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

* (evm) [tharsis#469](https://github.com/tharsis/ethermint/pull/469) Support [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559)
* (evm) [tharsis#417](https://github.com/tharsis/ethermint/pull/417) Add `EvmHooks` for tx post-processing
* (rpc) [tharsis#506](https://github.com/tharsis/ethermint/pull/506) Support for `debug_traceTransaction` RPC endpoint

### Bug Fixes

Expand Down
21 changes: 20 additions & 1 deletion docs/api/json-rpc/endpoints.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ Check the JSON-RPC methods supported on Ethermint. {synopsis}
| `debug_traceBlockFromFile` | Debug | | | |
| `debug_standardTraceBlockToFile` | Debug | | | |
| `debug_standardTraceBadBlockToFile` | Debug | | | |
| `debug_traceTransaction` | Debug | | | |
| [`debug_traceTransaction`](#debug-tracetransaction) | Debug | | | |
| `debug_verbosity` | Debug | | | |
| `debug_vmodule` | Debug | | | |
| `debug_writeBlockProfile` | Debug | ✔ | | |
Expand Down Expand Up @@ -989,6 +989,25 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"personal_ecRecover","params":["0
{"jsonrpc":"2.0","id":1,"result":"0x3b7252d007059ffc82d16d022da3cbf9992d2f70"}
```

## Debug Methods

### `debug_traceTransaction`

The `traceTransaction` debugging method will attempt to run the transaction in the exact same manner as it was executed on the network. It will replay any transaction that may have been executed prior to this one before it will finally attempt to execute the transaction that corresponds to the given hash.

#### Parameters

- Trace Config
fedekunze marked this conversation as resolved.
Show resolved Hide resolved

```json
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"debug_traceTransaction","params":["0xddecdb13226339681372b44e01df0fbc0f446fca6f834b2de5ecb1e569022ec8", {"tracer": "{data: [], fault: function(log) {}, step: function(log) { if(log.op.toString() == \"CALL\") this.data.push(log.stack.peek(0)); }, result: function() { return this.data; }}"}],"id":1}' -H "Content-Type: application/json" http://localhost:8545

//Result
["68410", "51470"]
```


## Miner Methods

### `miner_getHashrate`
Expand Down
76 changes: 76 additions & 0 deletions docs/api/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
- [AccessTuple](#ethermint.evm.v1.AccessTuple)
- [ChainConfig](#ethermint.evm.v1.ChainConfig)
- [Log](#ethermint.evm.v1.Log)
- [LogConfig](#ethermint.evm.v1.LogConfig)
- [Params](#ethermint.evm.v1.Params)
- [State](#ethermint.evm.v1.State)
- [TraceConfig](#ethermint.evm.v1.TraceConfig)
- [TransactionLogs](#ethermint.evm.v1.TransactionLogs)
- [TxResult](#ethermint.evm.v1.TxResult)

Expand Down Expand Up @@ -53,6 +55,8 @@
- [QueryStaticCallResponse](#ethermint.evm.v1.QueryStaticCallResponse)
- [QueryStorageRequest](#ethermint.evm.v1.QueryStorageRequest)
- [QueryStorageResponse](#ethermint.evm.v1.QueryStorageResponse)
- [QueryTraceTxRequest](#ethermint.evm.v1.QueryTraceTxRequest)
- [QueryTraceTxResponse](#ethermint.evm.v1.QueryTraceTxResponse)
- [QueryTxLogsRequest](#ethermint.evm.v1.QueryTxLogsRequest)
- [QueryTxLogsResponse](#ethermint.evm.v1.QueryTxLogsResponse)
- [QueryValidatorAccountRequest](#ethermint.evm.v1.QueryValidatorAccountRequest)
Expand Down Expand Up @@ -213,6 +217,27 @@ the node.



<a name="ethermint.evm.v1.LogConfig"></a>

### LogConfig
LogConfig are the configuration options for structured logger the EVM


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `disable_memory` | [bool](#bool) | | disable memory capture |
| `disable_stack` | [bool](#bool) | | disable stack capture |
| `disable_storage` | [bool](#bool) | | disable storage capture |
| `disable_return_data` | [bool](#bool) | | disable return data capture |
| `debug` | [bool](#bool) | | print output during capture end |
| `limit` | [int32](#int32) | | maximum length of output, but zero means unlimited |
| `overrides` | [ChainConfig](#ethermint.evm.v1.ChainConfig) | | Chain overrides, can be used to execute a trace using future fork rules |






<a name="ethermint.evm.v1.Params"></a>

### Params
Expand Down Expand Up @@ -248,6 +273,24 @@ State represents a single Storage key value pair item.



<a name="ethermint.evm.v1.TraceConfig"></a>

### TraceConfig
TraceConfig holds extra parameters to trace functions.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `tracer` | [string](#string) | | custom javascript tracer |
| `timeout` | [string](#string) | | overrides the default timeout of 5 seconds for JavaScript-based tracing calls |
| `reexec` | [uint64](#uint64) | | number of blocks the tracer is willing to go back |
| `log_config` | [LogConfig](#ethermint.evm.v1.LogConfig) | | configuration options for structured logger the EVM |






<a name="ethermint.evm.v1.TransactionLogs"></a>

### TransactionLogs
Expand Down Expand Up @@ -823,6 +866,38 @@ method.



<a name="ethermint.evm.v1.QueryTraceTxRequest"></a>

### QueryTraceTxRequest
QueryTraceTxRequest defines TraceTx request


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `msg` | [MsgEthereumTx](#ethermint.evm.v1.MsgEthereumTx) | | msgEthereumTx for the requested transaction |
| `tx_index` | [uint32](#uint32) | | transaction index |
| `trace_config` | [TraceConfig](#ethermint.evm.v1.TraceConfig) | | TraceConfig holds extra parameters to trace functions. |






<a name="ethermint.evm.v1.QueryTraceTxResponse"></a>

### QueryTraceTxResponse
QueryTraceTxResponse defines TraceTx response


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `data` | [bytes](#bytes) | | response serialized in bytes |






<a name="ethermint.evm.v1.QueryTxLogsRequest"></a>

### QueryTxLogsRequest
Expand Down Expand Up @@ -912,6 +987,7 @@ Query defines the gRPC querier service.
| `Params` | [QueryParamsRequest](#ethermint.evm.v1.QueryParamsRequest) | [QueryParamsResponse](#ethermint.evm.v1.QueryParamsResponse) | Params queries the parameters of x/evm module. | GET|/ethermint/evm/v1/params|
| `EthCall` | [EthCallRequest](#ethermint.evm.v1.EthCallRequest) | [MsgEthereumTxResponse](#ethermint.evm.v1.MsgEthereumTxResponse) | EthCall implements the `eth_call` rpc api | GET|/ethermint/evm/v1/eth_call|
| `EstimateGas` | [EthCallRequest](#ethermint.evm.v1.EthCallRequest) | [EstimateGasResponse](#ethermint.evm.v1.EstimateGasResponse) | EstimateGas implements the `eth_estimateGas` rpc api | GET|/ethermint/evm/v1/estimate_gas|
| `TraceTx` | [QueryTraceTxRequest](#ethermint.evm.v1.QueryTraceTxRequest) | [QueryTraceTxResponse](#ethermint.evm.v1.QueryTraceTxResponse) | TraceTx implements the `debug_traceTransaction` rpc api | GET|/ethermint/evm/v1/trace_tx|

<!-- end services -->

Expand Down
2 changes: 1 addition & 1 deletion ethereum/rpc/apis.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func GetRPCAPIs(ctx *server.Context, clientCtx client.Context, tmWSClient *rpccl
rpc.API{
Namespace: DebugNamespace,
Version: apiVersion,
Service: debug.NewInternalAPI(ctx),
Service: debug.NewAPI(ctx, evmBackend, clientCtx),
Public: true,
},
)
Expand Down
82 changes: 82 additions & 0 deletions ethereum/rpc/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/cosmos/cosmos-sdk/server"
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
"github.com/ethereum/go-ethereum/accounts/keystore"
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"

"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
Expand Down Expand Up @@ -49,6 +50,8 @@ type Backend interface {
GetLogs(blockHash common.Hash) ([][]*ethtypes.Log, error)
BloomStatus() (uint64, uint64)
GetCoinbase() (sdk.AccAddress, error)
GetTransactionByHash(txHash common.Hash) (*types.RPCTransaction, error)
GetTxByEthHash(txHash common.Hash) (*tmrpctypes.ResultTx, error)
EstimateGas(args evmtypes.CallArgs, blockNrOptional *types.BlockNumber) (hexutil.Uint64, error)
RPCGasCap() uint64
}
Expand Down Expand Up @@ -461,6 +464,85 @@ func (e *EVMBackend) GetCoinbase() (sdk.AccAddress, error) {
return address, nil
}

// GetTransactionByHash returns the Ethereum format transaction identified by Ethereum transaction hash
func (e *EVMBackend) GetTransactionByHash(txHash common.Hash) (*types.RPCTransaction, error) {
res, err := e.GetTxByEthHash(txHash)
if err != nil {
// try to find tx in mempool
txs, err := e.PendingTransactions()
if err != nil {
e.logger.Debug("tx not found", "hash", txHash.Hex(), "error", err.Error())
return nil, nil
}

for _, tx := range txs {
msg, err := evmtypes.UnwrapEthereumMsg(tx)
if err != nil {
// not ethereum tx
continue
}

if msg.Hash == txHash.Hex() {
rpctx, err := types.NewTransactionFromMsg(
msg,
common.Hash{},
uint64(0),
uint64(0),
e.chainID,
)
if err != nil {
return nil, err
}
return rpctx, nil
}
}

e.logger.Debug("tx not found", "hash", txHash.Hex())
return nil, nil
}

resBlock, err := e.clientCtx.Client.Block(e.ctx, &res.Height)
if err != nil {
e.logger.Debug("block not found", "height", res.Height, "error", err.Error())
return nil, nil
}

tx, err := e.clientCtx.TxConfig.TxDecoder()(res.Tx)
if err != nil {
e.logger.Debug("decoding failed", "error", err.Error())
return nil, fmt.Errorf("failed to decode tx: %w", err)
}

msg, err := evmtypes.UnwrapEthereumMsg(&tx)
if err != nil {
e.logger.Debug("invalid tx", "error", err.Error())
return nil, err
}

return types.NewTransactionFromMsg(
msg,
common.BytesToHash(resBlock.Block.Hash()),
uint64(res.Height),
uint64(res.Index),
e.chainID,
)
}

// GetTxByEthHash uses `/tx_query` to find transaction by ethereum tx hash
// TODO: Don't need to convert once hashing is fixed on Tendermint
// https://github.com/tendermint/tendermint/issues/6539
func (e *EVMBackend) GetTxByEthHash(hash common.Hash) (*tmrpctypes.ResultTx, error) {
query := fmt.Sprintf("%s.%s='%s'", evmtypes.TypeMsgEthereumTx, evmtypes.AttributeKeyEthereumTxHash, hash.Hex())
resTxs, err := e.clientCtx.Client.TxSearch(e.ctx, query, false, nil, nil, "")
if err != nil {
return nil, err
}
if len(resTxs.Txs) == 0 {
return nil, errors.Errorf("ethereum tx not found for hash %s", hash.Hex())
}
return resTxs.Txs[0], nil
}

func (e *EVMBackend) SendTransaction(args types.SendTxArgs) (common.Hash, error) {
// Look up the wallet containing the requested signer
_, err := e.clientCtx.Keyring.KeyByAddress(sdk.AccAddress(args.From.Bytes()))
Expand Down
Loading