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

Commit

Permalink
Problem: traceTransaction fails for succesful tx
Browse files Browse the repository at this point in the history
Solution:
- Change the context to the begining of the block, rather than the end
  of it, while override block context to correct one

pass predecessors

pass current block information to grpc query
  • Loading branch information
yihuang committed Nov 5, 2021
1 parent d82b5c2 commit 7233abb
Show file tree
Hide file tree
Showing 7 changed files with 384 additions and 82 deletions.
4 changes: 4 additions & 0 deletions docs/api/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,10 @@ QueryTraceTxRequest defines TraceTx request
| `msg` | [MsgEthereumTx](#ethermint.evm.v1.MsgEthereumTx) | | msgEthereumTx for the requested transaction |
| `tx_index` | [uint64](#uint64) | | transaction index |
| `trace_config` | [TraceConfig](#ethermint.evm.v1.TraceConfig) | | TraceConfig holds extra parameters to trace functions. |
| `predecessors` | [MsgEthereumTx](#ethermint.evm.v1.MsgEthereumTx) | repeated | the predecessor transactions included in the same block need to be replayed first to get correct context for tracing. |
| `block_number` | [int64](#int64) | | |
| `block_hash` | [string](#string) | | |
| `block_time` | [int64](#int64) | | |



Expand Down
6 changes: 6 additions & 0 deletions proto/ethermint/evm/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,12 @@ message QueryTraceTxRequest {
uint64 tx_index = 2;
// TraceConfig holds extra parameters to trace functions.
TraceConfig trace_config = 3;
// the predecessor transactions included in the same block
// need to be replayed first to get correct context for tracing.
repeated MsgEthereumTx predecessors = 4;
int64 block_number = 5;
string block_hash = 6;
int64 block_time = 7;
}

// QueryTraceTxResponse defines TraceTx response
Expand Down
56 changes: 49 additions & 7 deletions rpc/ethereum/namespaces/debug/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"time"

"github.com/davecgh/go-spew/spew"
"github.com/tendermint/tendermint/types"
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"

evmtypes "github.com/tharsis/ethermint/x/evm/types"

Expand Down Expand Up @@ -81,6 +81,28 @@ func (a *API) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfig) (
return nil, errors.New("genesis is not traceable")
}

blk, err := a.backend.GetTendermintBlockByNumber(rpctypes.BlockNumber(transaction.Height))
if err != nil {
a.logger.Debug("block not found", "height", transaction.Height)
return nil, err
}

predecessors := []*evmtypes.MsgEthereumTx{}
for _, txBz := range blk.Block.Txs[:transaction.Index] {
tx, err := a.clientCtx.TxConfig.TxDecoder()(txBz)
if err != nil {
a.logger.Debug("failed to decode transaction in block", "height", blk.Block.Height, "error", err.Error())
continue
}
msg := tx.GetMsgs()[0]
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
continue
}

predecessors = append(predecessors, ethMsg)
}

tx, err := a.clientCtx.TxConfig.TxDecoder()(transaction.Tx)
if err != nil {
a.logger.Debug("tx not found", "hash", hash)
Expand All @@ -94,15 +116,25 @@ func (a *API) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfig) (
}

traceTxRequest := evmtypes.QueryTraceTxRequest{
Msg: ethMessage,
TxIndex: uint64(transaction.Index),
Msg: ethMessage,
TxIndex: uint64(transaction.Index),
Predecessors: predecessors,
BlockNumber: blk.Block.Height,
BlockTime: blk.Block.Time.Unix(),
BlockHash: blk.BlockID.Hash.String(),
}

if config != nil {
traceTxRequest.TraceConfig = config
}

traceResult, err := a.queryClient.TraceTx(rpctypes.ContextWithHeight(transaction.Height), &traceTxRequest)
// minus one to get the context of block beginning
contextHeight := transaction.Height - 1
if contextHeight < 1 {
// 0 is a special value in `ContextWithHeight`
contextHeight = 1
}
traceResult, err := a.queryClient.TraceTx(rpctypes.ContextWithHeight(contextHeight), &traceTxRequest)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -131,13 +163,14 @@ func (a *API) TraceBlockByNumber(height rpctypes.BlockNumber, config *evmtypes.T
return nil, err
}

return a.traceBlock(height, config, resBlock.Block.Txs)
return a.traceBlock(height, config, resBlock)
}

// traceBlock configures a new tracer according to the provided configuration, and
// executes all the transactions contained within. The return value will be one item
// per transaction, dependent on the requested tracer.
func (a API) traceBlock(height rpctypes.BlockNumber, config *evmtypes.TraceConfig, txs types.Txs) ([]*evmtypes.TxTraceResult, error) {
func (a API) traceBlock(height rpctypes.BlockNumber, config *evmtypes.TraceConfig, block *tmrpctypes.ResultBlock) ([]*evmtypes.TxTraceResult, error) {
txs := block.Block.Txs
txsLength := len(txs)

if txsLength == 0 {
Expand All @@ -156,7 +189,13 @@ func (a API) traceBlock(height rpctypes.BlockNumber, config *evmtypes.TraceConfi
threads = txsLength
}

ctxWithHeight := rpctypes.ContextWithHeight(int64(height))
// minus one to get the context at the begining of the block
contextHeight := height - 1
if contextHeight < 1 {
// 0 is a special value for `ContextWithHeight`.
contextHeight = 1
}
ctxWithHeight := rpctypes.ContextWithHeight(int64(contextHeight))

wg.Add(threads)
for th := 0; th < threads; th++ {
Expand Down Expand Up @@ -185,6 +224,9 @@ func (a API) traceBlock(height rpctypes.BlockNumber, config *evmtypes.TraceConfi
Msg: ethMessage,
TxIndex: uint64(task.Index),
TraceConfig: config,
BlockNumber: block.Block.Height,
BlockTime: block.Block.Time.Unix(),
BlockHash: block.BlockID.Hash.String(),
}

res, err := a.queryClient.TraceTx(ctxWithHeight, traceTxRequest)
Expand Down
20 changes: 19 additions & 1 deletion x/evm/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,14 +360,32 @@ func (k Keeper) TraceTx(c context.Context, req *types.QueryTraceTxRequest) (*typ
}

ctx := sdk.UnwrapSDKContext(c)
ctx = ctx.WithBlockHeight(req.BlockNumber)
ctx = ctx.WithBlockTime(time.Unix(req.BlockTime, 0))
ctx = ctx.WithHeaderHash(common.Hex2Bytes(req.BlockHash))
k.WithContext(ctx)

params := k.GetParams(ctx)
ethCfg := params.ChainConfig.EthereumConfig(k.eip155ChainID)
signer := ethtypes.MakeSigner(ethCfg, big.NewInt(ctx.BlockHeight()))
tx := req.Msg.AsTransaction()
baseFee := k.feeMarketKeeper.GetBaseFee(ctx)

for i, tx := range req.Predecessors {
ethTx := tx.AsTransaction()
msg, err := ethTx.AsMessage(signer)
if err != nil {
continue
}
k.SetTxHashTransient(ethTx.Hash())
k.SetTxIndexTransient(uint64(i))

_, err = k.ApplyMessage(msg, types.NewNoOpTracer(), true)
if err != nil {
continue
}
}

tx := req.Msg.AsTransaction()
result, err := k.traceTx(ctx, signer, req.TxIndex, ethCfg, tx, baseFee, req.TraceConfig)
if err != nil {
return nil, err
Expand Down

0 comments on commit 7233abb

Please sign in to comment.