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

Commit

Permalink
rpc: make trace transaction api work with batch tx (#907)
Browse files Browse the repository at this point in the history
* make trace transaction api work with batch tx

Closes: #906

fix linter

* review suggestion

Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
  • Loading branch information
yihuang and fedekunze committed Jan 16, 2022
1 parent 0b92af4 commit 351e6d6
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 20 deletions.
47 changes: 29 additions & 18 deletions rpc/ethereum/namespaces/debug/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,27 +89,32 @@ func (a *API) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfig) (
return nil, err
}

msgIndex, _ := rpctypes.FindTxAttributes(transaction.TxResult.Events, hash.Hex())
if msgIndex < 0 {
return nil, fmt.Errorf("ethereum tx not found in msgs: %s", hash.Hex())
}

// check tx index is not out of bound
if uint32(len(blk.Block.Txs)) < transaction.Index {
a.logger.Debug("tx index out of bounds", "index", transaction.Index, "hash", hash.String(), "height", blk.Block.Height)
return nil, fmt.Errorf("transaction not included in block %v", blk.Block.Height)
}

// nolint: prealloc
var 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
}
for _, msg := range tx.GetMsgs() {
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
continue
}

predecessors = append(predecessors, ethMsg)
predecessors = append(predecessors, ethMsg)
}
}

tx, err := a.clientCtx.TxConfig.TxDecoder()(transaction.Tx)
Expand All @@ -118,7 +123,16 @@ func (a *API) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfig) (
return nil, err
}

ethMessage, ok := tx.GetMsgs()[0].(*evmtypes.MsgEthereumTx)
// add predecessor messages in current cosmos tx
for i := 0; i < msgIndex; i++ {
ethMsg, ok := tx.GetMsgs()[i].(*evmtypes.MsgEthereumTx)
if !ok {
continue
}
predecessors = append(predecessors, ethMsg)
}

ethMessage, ok := tx.GetMsgs()[msgIndex].(*evmtypes.MsgEthereumTx)
if !ok {
a.logger.Debug("invalid transaction type", "type", fmt.Sprintf("%T", tx))
return nil, fmt.Errorf("invalid transaction type %T", tx)
Expand Down Expand Up @@ -209,7 +223,6 @@ func (a *API) traceBlock(height rpctypes.BlockNumber, config *evmtypes.TraceConf

txDecoder := a.clientCtx.TxConfig.TxDecoder()

// nolint: prealloc
var txsMessages []*evmtypes.MsgEthereumTx
for i, tx := range txs {
decodedTx, err := txDecoder(tx)
Expand All @@ -218,16 +231,14 @@ func (a *API) traceBlock(height rpctypes.BlockNumber, config *evmtypes.TraceConf
continue
}

messages := decodedTx.GetMsgs()
if len(messages) == 0 {
continue
}
ethMessage, ok := messages[0].(*evmtypes.MsgEthereumTx)
if !ok {
// Just considers Ethereum transactions
continue
for _, msg := range decodedTx.GetMsgs() {
ethMessage, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
// Just considers Ethereum transactions
continue
}
txsMessages = append(txsMessages, ethMessage)
}
txsMessages = append(txsMessages, ethMessage)
}

// minus one to get the context at the beginning of the block
Expand Down
7 changes: 5 additions & 2 deletions rpc/ethereum/namespaces/eth/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -699,12 +699,15 @@ func (e *PublicAPI) getTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock,
e.logger.Debug("invalid ethereum tx", "height", block.Block.Header, "index", idx)
return nil, nil
}
if len(tx.GetMsgs()) != 1 {
// find msg index in events
msgIndex := rpctypes.FindTxAttributesByIndex(res.TxResult.Events, uint64(idx))
if msgIndex < 0 {
e.logger.Debug("invalid ethereum tx", "height", block.Block.Header, "index", idx)
return nil, nil
}
var ok bool
msg, ok = tx.GetMsgs()[0].(*evmtypes.MsgEthereumTx)
// msgIndex is inferred from tx events, should be within bound.
msg, ok = tx.GetMsgs()[msgIndex].(*evmtypes.MsgEthereumTx)
if !ok {
e.logger.Debug("invalid ethereum tx", "height", block.Block.Header, "index", idx)
return nil, nil
Expand Down
25 changes: 25 additions & 0 deletions rpc/ethereum/types/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,31 @@ func FindTxAttributes(events []abci.Event, txHash string) (int, map[string]strin
return -1, nil
}

// FindTxAttributesByIndex search the msg in tx events by txIndex
// returns the msgIndex, returns -1 if not found.
func FindTxAttributesByIndex(events []abci.Event, txIndex uint64) int {
strIndex := []byte(strconv.FormatUint(txIndex, 10))
txIndexKey := []byte(evmtypes.AttributeKeyTxIndex)
msgIndex := -1
for _, event := range events {
if event.Type != evmtypes.EventTypeEthereumTx {
continue
}

msgIndex++

value := FindAttribute(event.Attributes, txIndexKey)
if !bytes.Equal(value, strIndex) {
continue
}

// found, convert attributes to map for later lookup
return msgIndex
}
// not found
return -1
}

// FindAttribute find event attribute with specified key, if not found returns nil.
func FindAttribute(attrs []abci.EventAttribute, key []byte) []byte {
for _, attr := range attrs {
Expand Down

0 comments on commit 351e6d6

Please sign in to comment.