Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
25 changes: 25 additions & 0 deletions rpc/backend/blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,31 @@ func (b *Backend) parseDerivedTxFromAdditionalFields(
ethMsg.From = additional.Sender.Hex()
return ethMsg
}
func (b *Backend) parseDerivedTxFromAdditionalFieldsForTrace(
additional *rpctypes.TxResultAdditionalFields,
) *evmtypes.MsgEthereumTx {
recipient := additional.Recipient
t := ethtypes.NewTx(&ethtypes.LegacyTx{
Nonce: additional.Nonce,
Data: additional.Data,
Gas: additional.GasUsed,
To: &recipient,
GasPrice: nil,
Value: additional.Value,
V: big.NewInt(27),
R: big.NewInt(1),
S: big.NewInt(1),
})
ethMsg := &evmtypes.MsgEthereumTx{}
err := ethMsg.FromEthereumTx(t)
if err != nil {
b.logger.Error("can not create eth msg", err.Error())
return nil
}
ethMsg.Hash = additional.Hash.Hex()
ethMsg.From = additional.Sender.Hex()
return ethMsg
}

// HeaderByNumber returns the block header identified by height.
func (b *Backend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Header, error) {
Expand Down
77 changes: 61 additions & 16 deletions rpc/backend/tracing.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
// and returns them as a JSON object.
func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfig) (interface{}, error) {
// Get transaction by hash
transaction, _, err := b.GetTxByEthHash(hash)
transaction, additional, err := b.GetTxByEthHash(hash)
if err != nil {
b.logger.Debug("tx not found", "hash", hash)
return nil, err
Expand Down Expand Up @@ -46,19 +46,39 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi
}

var predecessors []*evmtypes.MsgEthereumTx
for _, txBz := range blk.Block.Txs[:transaction.TxIndex] {
tx, err := b.clientCtx.TxConfig.TxDecoder()(txBz)
for i := 0; i < int(transaction.TxIndex); i++ {
_, txAdditional, err := b.GetTxByTxIndex(blk.Block.Height, uint(i))
if err != nil {
b.logger.Debug("failed to decode transaction in block", "height", blk.Block.Height, "error", err.Error())
b.logger.Debug("failed to get tx by index",
"height", blk.Block.Height,
"index", i,
"error", err.Error())
continue
}
for _, msg := range tx.GetMsgs() {
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
continue

if txAdditional != nil {
// Handle synthetic EVM transaction
ethMsg := b.parseDerivedTxFromAdditionalFieldsForTrace(txAdditional)
if ethMsg != nil {
predecessors = append(predecessors, ethMsg)
}
continue
}

predecessors = append(predecessors, ethMsg)
// Fallback: decode as normal Cosmos tx
tx, err := b.clientCtx.TxConfig.TxDecoder()(blk.Block.Txs[i])
if err != nil {
b.logger.Debug("failed to decode transaction in block",
"height", blk.Block.Height,
"index", i,
"error", err.Error())
continue
}

for _, msg := range tx.GetMsgs() {
if ethMsg, ok := msg.(*evmtypes.MsgEthereumTx); ok {
predecessors = append(predecessors, ethMsg)
}
}
}

Expand All @@ -70,18 +90,43 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi

// add predecessor messages in current cosmos tx
index := int(transaction.MsgIndex) // #nosec G115

for i := 0; i < index; i++ {
ethMsg, ok := tx.GetMsgs()[i].(*evmtypes.MsgEthereumTx)
if !ok {
msg := tx.GetMsgs()[i]
// Check if it’s a normal Ethereum tx
if ethMsg, ok := msg.(*evmtypes.MsgEthereumTx); ok {
predecessors = append(predecessors, ethMsg)
continue
}
predecessors = append(predecessors, ethMsg)
// Fetch additional data for predecessors
_, txAdditional, err := b.GetTxByEthHashAndMsgIndex(hash, i)
if err != nil {
b.logger.Debug("failed to get tx additional info", "error", err.Error())
continue
}

if txAdditional != nil {
ethMsg := b.parseDerivedTxFromAdditionalFieldsForTrace(txAdditional)
if ethMsg != nil {
predecessors = append(predecessors, ethMsg)
}
}
}
var ethMessage *evmtypes.MsgEthereumTx
var ok bool

ethMessage, ok := tx.GetMsgs()[transaction.MsgIndex].(*evmtypes.MsgEthereumTx)
if !ok {
b.logger.Debug("invalid transaction type", "type", fmt.Sprintf("%T", tx))
return nil, fmt.Errorf("invalid transaction type %T", tx)
if additional == nil {
ethMessage, ok = tx.GetMsgs()[transaction.MsgIndex].(*evmtypes.MsgEthereumTx)
if !ok {
b.logger.Debug("invalid transaction type", "type", fmt.Sprintf("%T", tx.GetMsgs()[transaction.MsgIndex]))
return nil, fmt.Errorf("invalid transaction type %T", tx.GetMsgs()[transaction.MsgIndex])
}
} else {
ethMessage = b.parseDerivedTxFromAdditionalFieldsForTrace(additional)
if ethMessage == nil {
b.logger.Error("failed to get derived eth msg from additional fields")
return nil, fmt.Errorf("failed to get derived eth msg from additional fields")
}
}

nc, ok := b.clientCtx.Client.(tmrpcclient.NetworkClient)
Expand Down
20 changes: 20 additions & 0 deletions rpc/backend/tx_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,26 @@ func (b *Backend) GetTxByEthHash(hash common.Hash) (*types.TxResult, *rpctypes.T
return txResult, txAdditional, nil
}

func (b *Backend) GetTxByEthHashAndMsgIndex(hash common.Hash, index int) (*types.TxResult, *rpctypes.TxResultAdditionalFields, error) {
if b.indexer != nil {
txRes, err := b.indexer.GetByTxHash(hash)
if err != nil {
return nil, nil, err
}
return txRes, nil, nil
}

// fallback to tendermint tx indexer
query := fmt.Sprintf("%s.%s='%s'", evmtypes.TypeMsgEthereumTx, evmtypes.AttributeKeyEthereumTxHash, hash.Hex())
txResult, txAdditional, err := b.queryTendermintTxIndexer(query, func(txs *rpctypes.ParsedTxs) *rpctypes.ParsedTx {
return txs.GetTxByMsgIndex(index)
})
if err != nil {
return nil, nil, errorsmod.Wrapf(err, "GetTxByEthHash %s", hash.Hex())
}
return txResult, txAdditional, nil
}

// GetTxByTxIndex uses `/tx_query` to find transaction by tx index of valid ethereum txs
func (b *Backend) GetTxByTxIndex(height int64, index uint) (*types.TxResult, *rpctypes.TxResultAdditionalFields, error) {
int32Index := int32(index) //#nosec G115 -- checked for int overflow already
Expand Down
Loading