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

RPC: debug_traceBlockByNumber #555

Merged
merged 30 commits into from
Sep 15, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
64eaacd
Refactor traceTx
crypto-facs Sep 12, 2021
5bc3527
add getTendermintBlock on backend
crypto-facs Sep 12, 2021
bbcbf18
keeper concurrency
crypto-facs Sep 13, 2021
0c4b322
first version
crypto-facs Sep 13, 2021
055870a
json rpc concurrency
crypto-facs Sep 13, 2021
df5d302
rever makefile change
crypto-facs Sep 13, 2021
99bab87
remove grpc traceblock
crypto-facs Sep 14, 2021
086cefc
create internal traceBlock function
crypto-facs Sep 14, 2021
c488e33
added types to evm module
crypto-facs Sep 14, 2021
0782e37
tendermintBlockByNumber rename
crypto-facs Sep 14, 2021
832078e
added safe message check
crypto-facs Sep 14, 2021
bfa4e8f
remove unnecesary line
crypto-facs Sep 14, 2021
1163597
check error
crypto-facs Sep 14, 2021
9541bd0
fix lint
crypto-facs Sep 14, 2021
44f4693
fix linter
crypto-facs Sep 14, 2021
756319d
Update ethereum/rpc/namespaces/debug/api.go
crypto-facs Sep 14, 2021
012fcc6
Update ethereum/rpc/namespaces/debug/api.go
crypto-facs Sep 14, 2021
05c4217
Update ethereum/rpc/backend/backend.go
crypto-facs Sep 14, 2021
1ea48b9
improve traceBlock performance
crypto-facs Sep 14, 2021
a022c8e
fix linter
crypto-facs Sep 14, 2021
50a1b61
Merge branch 'trace-block' of github.com:crypto-facs/ethermint into t…
crypto-facs Sep 14, 2021
a795c61
add extra line on function parameters
crypto-facs Sep 14, 2021
e6c8f6d
changed index to uint 64
crypto-facs Sep 14, 2021
aa4816f
fix lint
crypto-facs Sep 14, 2021
2746285
proto gen
crypto-facs Sep 14, 2021
607f0b0
update endpoints documentation
crypto-facs Sep 15, 2021
1090ed2
update changelog
crypto-facs Sep 15, 2021
2872935
Apply suggestions from code review
fedekunze Sep 15, 2021
7803ad5
Update ethereum/rpc/namespaces/eth/filters/filters.go
fedekunze Sep 15, 2021
181d552
Merge branch 'main' into trace-block
fedekunze Sep 15, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
51 changes: 51 additions & 0 deletions docs/api/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,15 @@
- [QueryStaticCallResponse](#ethermint.evm.v1.QueryStaticCallResponse)
- [QueryStorageRequest](#ethermint.evm.v1.QueryStorageRequest)
- [QueryStorageResponse](#ethermint.evm.v1.QueryStorageResponse)
- [QueryTraceBlockRequest](#ethermint.evm.v1.QueryTraceBlockRequest)
- [QueryTraceBlockResponse](#ethermint.evm.v1.QueryTraceBlockResponse)
- [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)
- [QueryValidatorAccountResponse](#ethermint.evm.v1.QueryValidatorAccountResponse)
- [TraceBlockTransaction](#ethermint.evm.v1.TraceBlockTransaction)

- [Query](#ethermint.evm.v1.Query)

Expand Down Expand Up @@ -838,6 +841,37 @@ method.



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

### QueryTraceBlockRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `trace_config` | [TraceConfig](#ethermint.evm.v1.TraceConfig) | | TODO add comments |
| `transactions` | [TraceBlockTransaction](#ethermint.evm.v1.TraceBlockTransaction) | repeated | |






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

### QueryTraceBlockResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `result` | [bytes](#bytes) | | |






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

### QueryTraceTxRequest
Expand Down Expand Up @@ -935,6 +969,22 @@ Query/ValidatorAccount RPC method.




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

### TraceBlockTransaction



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `msg` | [MsgEthereumTx](#ethermint.evm.v1.MsgEthereumTx) | | msgEthereumTx for the requested transaction |
| `index` | [uint32](#uint32) | | transaction index |





<!-- end messages -->

<!-- end enums -->
Expand Down Expand Up @@ -962,6 +1012,7 @@ Query defines the gRPC querier service.
| `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|
| `TraceBlock` | [QueryTraceBlockRequest](#ethermint.evm.v1.QueryTraceBlockRequest) | [QueryTraceBlockResponse](#ethermint.evm.v1.QueryTraceBlockResponse) | TraceTx implements the `debug_traceTransaction` rpc api | GET|/ethermint/evm/v1/trace_block|

<!-- end services -->

Expand Down
55 changes: 32 additions & 23 deletions ethereum/rpc/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type Backend interface {
BlockNumber() (hexutil.Uint64, error)
GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map[string]interface{}, error)
GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error)
GetTendermintBlock(blockNum types.BlockNumber) (*tmrpctypes.ResultBlock, error)
HeaderByNumber(blockNum types.BlockNumber) (*ethtypes.Header, error)
HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error)
PendingTransactions() ([]*sdk.Tx, error)
Expand Down Expand Up @@ -116,6 +117,36 @@ func (e *EVMBackend) BlockNumber() (hexutil.Uint64, error) {

// GetBlockByNumber returns the block identified by number.
func (e *EVMBackend) GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map[string]interface{}, error) {
resBlock, err := e.GetTendermintBlock(blockNum)
if err != nil {
return nil, err
}

res, err := e.EthBlockFromTendermint(resBlock.Block, fullTx)
if err != nil {
e.logger.Debug("EthBlockFromTendermint failed", "height", blockNum, "error", err.Error())
}

return res, err
crypto-facs marked this conversation as resolved.
Show resolved Hide resolved
}

// GetBlockByHash returns the block identified by hash.
func (e *EVMBackend) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) {
resBlock, err := e.clientCtx.Client.BlockByHash(e.ctx, hash.Bytes())
if err != nil {
e.logger.Debug("BlockByHash block not found", "hash", hash.Hex(), "error", err.Error())
return nil, err
}

if resBlock.Block == nil {
e.logger.Debug("BlockByHash block not found", "hash", hash.Hex())
return nil, nil
}

return e.EthBlockFromTendermint(resBlock.Block, fullTx)
}

func (e *EVMBackend) GetTendermintBlock(blockNum types.BlockNumber) (*tmrpctypes.ResultBlock, error) {
crypto-facs marked this conversation as resolved.
Show resolved Hide resolved
height := blockNum.Int64()
currentBlockNumber, _ := e.BlockNumber()

Expand Down Expand Up @@ -152,29 +183,7 @@ func (e *EVMBackend) GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (
e.logger.Debug("GetBlockByNumber block not found", "height", height)
return nil, nil
}

res, err := e.EthBlockFromTendermint(resBlock.Block, fullTx)
if err != nil {
e.logger.Debug("EthBlockFromTendermint failed", "height", height, "error", err.Error())
}

return res, err
}

// GetBlockByHash returns the block identified by hash.
func (e *EVMBackend) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) {
resBlock, err := e.clientCtx.Client.BlockByHash(e.ctx, hash.Bytes())
if err != nil {
e.logger.Debug("BlockByHash block not found", "hash", hash.Hex(), "error", err.Error())
return nil, err
}

if resBlock.Block == nil {
e.logger.Debug("BlockByHash block not found", "hash", hash.Hex())
return nil, nil
}

return e.EthBlockFromTendermint(resBlock.Block, fullTx)
return resBlock, nil
}

// EthBlockFromTendermint returns a JSON-RPC compatible Ethereum block from a given Tendermint block.
Expand Down
79 changes: 79 additions & 0 deletions ethereum/rpc/namespaces/debug/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,85 @@ func (a *API) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfig) (
return decodedResult, nil
}

func (a *API) TraceBlockByNumber(height rpctypes.BlockNumber, config *evmtypes.TraceConfig) ([]*TxTraceResult, error) {
crypto-facs marked this conversation as resolved.
Show resolved Hide resolved
a.logger.Debug("debug_traceBlockByNumber", "height", height)
if height == 0 {
return nil, errors.New("genesis is not traceable")
}
// Get Tendermint Block
resBlock, err := a.backend.GetTendermintBlock(height)
if err != nil {
return nil, err
}

txsLength := len(resBlock.Block.Txs)

if txsLength == 0 {
// If there are no transactions return empty array
return []*TxTraceResult{}, nil
}

var (
results = make([]*TxTraceResult, txsLength)
wg = new(sync.WaitGroup)
jobs = make(chan *TxTraceTask, txsLength)
)

threads := runtime.NumCPU()
if threads > txsLength {
threads = txsLength
}
crypto-facs marked this conversation as resolved.
Show resolved Hide resolved
wg.Add(threads)
for th := 0; th < threads; th++ {
go func() {
defer wg.Done()
// Fetch and execute the next transaction trace tasks
for task := range jobs {
tx, err := a.clientCtx.TxConfig.TxDecoder()(resBlock.Block.Txs[task.Index])
crypto-facs marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
a.logger.Debug("tx not found", "hash", resBlock.Block.Txs[task.Index].Hash())
crypto-facs marked this conversation as resolved.
Show resolved Hide resolved
continue
}

ethMessage, ok := tx.GetMsgs()[0].(*evmtypes.MsgEthereumTx)
crypto-facs marked this conversation as resolved.
Show resolved Hide resolved
if !ok {
// Just considers Ethereum transactions
continue
}
traceTxRequest := &evmtypes.QueryTraceTxRequest{
Msg: ethMessage,
TxIndex: uint32(task.Index),
crypto-facs marked this conversation as resolved.
Show resolved Hide resolved
TraceConfig: config,
}

res, err := a.queryClient.TraceTx(rpctypes.ContextWithHeight(int64(height)), traceTxRequest)
crypto-facs marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
results[task.Index] = &TxTraceResult{Error: err.Error()}
continue
}
// Response format is unknown due to custom tracer config param
// More information can be found here https://geth.ethereum.org/docs/dapp/tracing-filtered
var decodedResult interface{}
err = json.Unmarshal(res.Data, &decodedResult)
if err != nil {
crypto-facs marked this conversation as resolved.
Show resolved Hide resolved
results[task.Index] = &TxTraceResult{Error: err.Error()}
continue
}
results[task.Index] = &TxTraceResult{Result: decodedResult}
}
}()
}

for i, _ := range resBlock.Block.Txs {
jobs <- &TxTraceTask{Index: i}
}

close(jobs)
wg.Wait()

return results, nil
}

// 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.
Expand Down
13 changes: 13 additions & 0 deletions ethereum/rpc/namespaces/debug/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package debug

// TxTraceTask represents a single transaction trace task when an entire block
// is being traced.
type TxTraceTask struct {
crypto-facs marked this conversation as resolved.
Show resolved Hide resolved
Index int // Transaction offset in the block
}

// TxTraceResult is the result of a single transaction trace.
type TxTraceResult struct {
Result interface{} `json:"result,omitempty"` // Trace results produced by the tracer
Error string `json:"error,omitempty"` // Trace failure produced by the tracer
}
12 changes: 11 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ require (
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f // indirect
golang.org/x/sys v0.0.0-20210903071746-97244b99971b // indirect
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af
google.golang.org/grpc v1.40.0
gopkg.in/yaml.v2 v2.4.0
)
Expand All @@ -44,9 +44,13 @@ require (
github.com/99designs/keyring v1.1.6 // indirect
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
github.com/DataDog/zstd v1.4.8 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
github.com/VictoriaMetrics/fastcache v1.5.7 // indirect
github.com/Workiva/go-datastructures v1.0.52 // indirect
github.com/aokoli/goutils v1.1.1 // indirect
github.com/armon/go-metrics v0.3.9 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bgentry/speakeasy v0.1.0 // indirect
Expand All @@ -68,6 +72,7 @@ require (
github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect
github.com/edsrzf/mmap-go v1.0.0 // indirect
github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 // indirect
github.com/envoyproxy/protoc-gen-validate v0.6.1 // indirect
github.com/felixge/httpsnoop v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
Expand All @@ -92,7 +97,9 @@ require (
github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
github.com/holiman/uint256 v1.1.1 // indirect
github.com/huandu/xstrings v1.3.2 // indirect
github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 // indirect
github.com/jmhodges/levigo v1.0.0 // indirect
Expand All @@ -105,8 +112,10 @@ require (
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect
github.com/minio/highwayhash v1.0.1 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/mtibben/percent v0.2.1 // indirect
github.com/mwitkow/go-proto-validators v0.3.2 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pelletier/go-toml v1.9.3 // indirect
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
Expand All @@ -116,6 +125,7 @@ require (
github.com/prometheus/common v0.29.0 // indirect
github.com/prometheus/procfs v0.6.0 // indirect
github.com/prometheus/tsdb v0.7.1 // indirect
github.com/pseudomuto/protoc-gen-doc v1.5.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rjeczalik/notify v0.9.1 // indirect
github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect
Expand Down