Skip to content

Commit

Permalink
Enable unsigned transactions in tracing (#41)
Browse files Browse the repository at this point in the history
  • Loading branch information
skosito committed May 31, 2024
1 parent 35f3f79 commit 61d0400
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 9 deletions.
62 changes: 53 additions & 9 deletions x/evm/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,12 +424,22 @@ func (k Keeper) TraceTx(c context.Context, req *types.QueryTraceTxRequest) (*typ
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to load evm config: %s", err.Error())
}
signer := ethtypes.MakeSigner(cfg.ChainConfig, big.NewInt(ctx.BlockHeight()))

txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes()))

for i, tx := range req.Predecessors {
ethTx := tx.AsTransaction()
msg, err := ethTx.AsMessage(signer, cfg.BaseFee)
var msg ethtypes.Message
// if tx is not unsigned, from field should be derived from signer, which can be done using AsMessage function
if !isUnsigned(ethTx) {
signer := ethtypes.MakeSigner(cfg.ChainConfig, big.NewInt(ctx.BlockHeight()))
msg, err = ethTx.AsMessage(signer, cfg.BaseFee)
if err != nil {
continue
}
} else {
msg = unsignedTxAsMessage(msg.From(), ethTx)
}
if err != nil {
continue
}
Expand All @@ -454,7 +464,10 @@ func (k Keeper) TraceTx(c context.Context, req *types.QueryTraceTxRequest) (*typ
_ = json.Unmarshal([]byte(req.TraceConfig.TracerJsonConfig), &tracerConfig)
}

result, _, err := k.traceTx(ctx, cfg, txConfig, signer, tx, req.TraceConfig, false, tracerConfig)
result, _, err := k.traceTx(
ctx, cfg, txConfig, common.HexToAddress(req.Msg.From), tx,
req.TraceConfig, false, tracerConfig,
)
if err != nil {
// error will be returned with detail status from traceTx
return nil, err
Expand All @@ -470,6 +483,12 @@ func (k Keeper) TraceTx(c context.Context, req *types.QueryTraceTxRequest) (*typ
}, nil
}

func isUnsigned(ethTx *ethtypes.Transaction) bool {
r, v, s := ethTx.RawSignatureValues()

return (r == nil && v == nil && s == nil) || (r.Int64() == 0 && v.Int64() == 0 && s.Int64() == 0)
}

// TraceBlock configures a new tracer according to the provided configuration, and
// executes the given message in the provided environment for all the transactions in the queried block.
// The return value will be tracer dependent.
Expand Down Expand Up @@ -502,7 +521,6 @@ func (k Keeper) TraceBlock(c context.Context, req *types.QueryTraceBlockRequest)
if err != nil {
return nil, status.Error(codes.Internal, "failed to load evm config")
}
signer := ethtypes.MakeSigner(cfg.ChainConfig, big.NewInt(ctx.BlockHeight()))
txsLength := len(req.Txs)
results := make([]*types.TxTraceResult, 0, txsLength)

Expand All @@ -512,7 +530,10 @@ func (k Keeper) TraceBlock(c context.Context, req *types.QueryTraceBlockRequest)
ethTx := tx.AsTransaction()
txConfig.TxHash = ethTx.Hash()
txConfig.TxIndex = uint(i)
traceResult, logIndex, err := k.traceTx(ctx, cfg, txConfig, signer, ethTx, req.TraceConfig, true, nil)
traceResult, logIndex, err := k.traceTx(
ctx, cfg, txConfig, common.HexToAddress(tx.From),
ethTx, req.TraceConfig, true, nil,
)
if err != nil {
result.Error = err.Error()
} else {
Expand All @@ -537,7 +558,7 @@ func (k *Keeper) traceTx(
ctx sdk.Context,
cfg *statedb.EVMConfig,
txConfig statedb.TxConfig,
signer ethtypes.Signer,
from common.Address,
tx *ethtypes.Transaction,
traceConfig *types.TraceConfig,
commitMessage bool,
Expand All @@ -550,10 +571,16 @@ func (k *Keeper) traceTx(
err error
timeout = defaultTraceTimeout
)
msg, err := tx.AsMessage(signer, cfg.BaseFee)
if err != nil {
return nil, 0, status.Error(codes.Internal, err.Error())
// if tx is not unsigned, from field should be derived from signer, which can be done using AsMessage function
if !isUnsigned(tx) {
signer := ethtypes.MakeSigner(cfg.ChainConfig, big.NewInt(ctx.BlockHeight()))
m, err := tx.AsMessage(signer, cfg.BaseFee)
if err != nil {
return nil, 0, status.Error(codes.Internal, err.Error())
}
from = common.HexToAddress(m.From().String())
}
msg := unsignedTxAsMessage(from, tx)

if traceConfig == nil {
traceConfig = &types.TraceConfig{}
Expand Down Expand Up @@ -643,3 +670,20 @@ func getChainID(ctx sdk.Context, chainID int64) (*big.Int, error) {
}
return big.NewInt(chainID), nil
}

// same as ethTx.AsMessage, just from is provided instead of calculated from signature
func unsignedTxAsMessage(from common.Address, ethTx *ethtypes.Transaction) ethtypes.Message {
return ethtypes.NewMessage(
from,
ethTx.To(),
ethTx.Nonce(),
ethTx.Value(),
ethTx.Gas(),
new(big.Int).Set(ethTx.GasPrice()),
new(big.Int).Set(ethTx.GasFeeCap()),
new(big.Int).Set(ethTx.GasTipCap()),
ethTx.Data(),
ethTx.AccessList(),
false, // isFake
)
}
1 change: 1 addition & 0 deletions x/evm/keeper/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, msgEth *types.MsgEthereumTx)
return nil, errorsmod.Wrap(err, "failed to load evm config")
}
ethTx := msgEth.AsTransaction()

txConfig := k.TxConfig(ctx, ethTx.Hash())

// get the signer according to the chain rules from the config and block height
Expand Down
4 changes: 4 additions & 0 deletions x/evm/types/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ const (
AttributeKeyTxGasUsed = "txGasUsed"
AttributeKeyTxType = "txType"
AttributeKeyTxLog = "txLog"

AttributeKeyTxNonce = "txNonce"
AttributeKeyTxData = "txData"

// tx failed in eth vm execution
AttributeKeyEthereumTxFailed = "ethereumTxFailed"
AttributeValueCategory = ModuleName
Expand Down

0 comments on commit 61d0400

Please sign in to comment.