Skip to content

Commit

Permalink
POC for alternative solution to pull tx info from events
Browse files Browse the repository at this point in the history
  • Loading branch information
skosito committed May 22, 2024
1 parent 134036e commit 2e275f8
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 78 deletions.
121 changes: 55 additions & 66 deletions rpc/backend/tracing.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ package backend
import (
"encoding/json"
"fmt"
"math/big"

"github.com/cometbft/cometbft/abci/types"
tmrpctypes "github.com/cometbft/cometbft/rpc/core/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
Expand All @@ -34,7 +34,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, additional, err := b.GetTxByEthHash(hash)
transaction, _, err := b.GetTxByEthHash(hash)
if err != nil {
b.logger.Debug("tx not found", "hash", hash)
return nil, err
Expand Down Expand Up @@ -70,16 +70,18 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi
b.logger.Debug("failed to decode transaction in block", "height", blk.Block.Height, "error", err.Error())
continue
}
for _, msg := range tx.GetMsgs() {
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
ethTx, err := tryGetEthereumTxFromTxRes(blockResult.TxsResults[i])
if ethTx != nil && err == nil {
predecessors = append(predecessors, ethTx)
}

// get parsed eth txs from events from tx result
parsed, err := rpctypes.ParseTxResult(blockResult.TxsResults[i], tx)

Check failure on line 75 in rpc/backend/tracing.go

View workflow job for this annotation

GitHub Actions / lint

Consider pre-allocating `predecessors` (prealloc)
if err != nil {
return nil, err
}

for _, parsedTx := range parsed.Txs {
ethMsg := getMsgEthereumTxFromParsedTx(parsedTx, tx)
if ethMsg == nil {
continue
}

predecessors = append(predecessors, ethMsg)
}
}
Expand All @@ -90,33 +92,30 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi
return nil, err
}

// add predecessor messages in current cosmos tx
// #nosec G701 always in range
for i := 0; i < int(transaction.MsgIndex); i++ {
// TODO: same fallback for predecessors?
ethMsg, ok := tx.GetMsgs()[i].(*evmtypes.MsgEthereumTx)
if !ok {
continue
}
predecessors = append(predecessors, ethMsg)
// get parsed eth txs from events from tx result
parsed, err := rpctypes.ParseTxResult(blockResult.TxsResults[transaction.TxIndex], tx)
if err != nil {
return nil, err
}

ethMessage, ok := tx.GetMsgs()[transaction.MsgIndex].(*evmtypes.MsgEthereumTx)
if !ok {
if additional == nil {
b.logger.Debug("invalid transaction type", "type", fmt.Sprintf("%T", tx))
return nil, fmt.Errorf("invalid transaction type %T", tx)
// iterate parsed eth txs, if its type 88, recreate it and get MsgEthereumTx, otherwise pull it from sdk.Msgs
// when requested tx is found, break, no more predecessors
var ethMsg *evmtypes.MsgEthereumTx
for _, parsedTx := range parsed.Txs {
ethMsg = getMsgEthereumTxFromParsedTx(parsedTx, tx)
if parsedTx.Hash.Hex() == hash.Hex() {
if ethMsg == nil {
return nil, errors.New("error while parsing tx")
}
break
}

ethMessage, err = tryGetEthereumTxFromTxRes(blockResult.TxsResults[transaction.TxIndex])
if err != nil {
b.logger.Debug("invalid transaction type", "type", fmt.Sprintf("%T", tx))
return nil, fmt.Errorf("invalid transaction type %T", tx)
if ethMsg == nil {
continue
}
predecessors = append(predecessors, ethMsg)
}

traceTxRequest := evmtypes.QueryTraceTxRequest{
Msg: ethMessage,
Msg: ethMsg,
Predecessors: predecessors,
BlockNumber: blk.Block.Height,
BlockTime: blk.Block.Time,
Expand Down Expand Up @@ -151,44 +150,34 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi
return decodedResult, nil
}

func tryGetEthereumTxFromTxRes(txRes *types.ResponseDeliverTx) (*evmtypes.MsgEthereumTx, error) {
ethTx := &evmtypes.MsgEthereumTx{}
txFound := false
for _, ev := range txRes.Events {
if ev.Type != evmtypes.EventTypeEthereumTx {
continue
func getMsgEthereumTxFromParsedTx(parsedTx rpctypes.ParsedTx, tx sdk.Tx) *evmtypes.MsgEthereumTx {
if parsedTx.Type == 88 {
recipient := parsedTx.Recipient
// TODO: is this ok?
t := ethtypes.NewTx(&ethtypes.LegacyTx{
Nonce: parsedTx.Nonce,
Data: parsedTx.Data,
Gas: parsedTx.GasUsed,
To: &recipient,
GasPrice: nil,
Value: parsedTx.Amount,
V: big.NewInt(0),
R: big.NewInt(0),
S: big.NewInt(0),
})
ethMsg := &evmtypes.MsgEthereumTx{}
err := ethMsg.FromEthereumTx(t)
if err != nil {
return nil
}
for _, attr := range ev.Attributes {
if string(attr.Key) == "TxBytes" {
txFound = true
hexBytes, err := hexutil.Decode(string(attr.Value))
if err != nil {
return nil, err
}
t := ethtypes.Transaction{}
if err := t.UnmarshalBinary(hexBytes); err != nil {
return nil, err
}

if err := ethTx.FromEthereumTx(&t); err != nil {
return nil, err
}
}

if attr.Key == "sender" {
ethTx.From = attr.Value
}

if attr.Key == "TxHash" {
ethTx.Hash = attr.Value
}
return ethMsg
} else {
ethMsg, ok := tx.GetMsgs()[parsedTx.MsgIndex].(*evmtypes.MsgEthereumTx)
if !ok {
return nil
}
return ethMsg
}

if !txFound {
return nil, nil
}
return ethTx, nil
}

// TraceBlock configures a new tracer according to the provided configuration, and

Check warning on line 183 in rpc/backend/tracing.go

View workflow job for this annotation

GitHub Actions / lint

indent-error-flow: if block ends with a return statement, so drop this else and outdent its block (revive)
Expand Down
30 changes: 30 additions & 0 deletions rpc/types/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ package types

import (
"fmt"
"math"
"math/big"
"strconv"

abci "github.com/cometbft/cometbft/abci/types"
tmrpctypes "github.com/cometbft/cometbft/rpc/core/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
ethermint "github.com/evmos/ethermint/types"
evmtypes "github.com/evmos/ethermint/x/evm/types"
)
Expand Down Expand Up @@ -68,6 +70,7 @@ const (

// ParsedTx is the tx infos parsed from events.
type ParsedTx struct {
// max uint32 means there is no sdk.Msg corresponding to eth tx
MsgIndex int

// the following fields are parsed from events
Expand All @@ -83,6 +86,8 @@ type ParsedTx struct {
Amount *big.Int
Recipient common.Address
Sender common.Address
Nonce uint64
Data []byte
}

// NewParsedTx initialize a ParsedTx
Expand Down Expand Up @@ -176,6 +181,18 @@ func ParseTxResult(result *abci.ResponseDeliverTx, tx sdk.Tx) (*ParsedTxs, error
p.Txs[i].GasUsed = gasLimit
}
}

// fix msg indexes, because some eth txs indexed here don't have corresponding sdk.Msg
currMsgIndex := -1
for _, tx := range p.Txs {
if tx.Type == 88 {
tx.MsgIndex = math.MaxUint32
// todo: fix mapping as well
} else {
currMsgIndex++
tx.MsgIndex = currMsgIndex
}
}
return p, nil
}

Expand Down Expand Up @@ -371,6 +388,19 @@ func fillTxAttribute(tx *ParsedTx, key []byte, value []byte) error {
if !success {
return nil
}
case "TxNonce":
nonce, err := strconv.ParseUint(string(value), 10, 64)
if err != nil {
return err
}
tx.Nonce = nonce

case "TxData":
hexBytes, err := hexutil.Decode(string(value))
if err != nil {
return err
}
tx.Data = hexBytes
}
return nil
}
Expand Down
15 changes: 3 additions & 12 deletions x/fungible/keeper/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,6 @@ func (k Keeper) CallEVMWithData(
if gasLimit != nil {
gasCap = gasLimit.Uint64()
}

msg := ethtypes.NewMessage(
from,
contract,
Expand Down Expand Up @@ -757,20 +756,12 @@ func (k Keeper) CallEVMWithData(

if !noEthereumTxEvent {
fmt.Println("88 tx", ethTxHash.Hex())
txBytes, err := ethtypes.NewTx(&ethtypes.DynamicFeeTx{
ChainID: k.evmKeeper.ChainID(),
Nonce: nonce,
GasTipCap: msg.GasTipCap(),
GasFeeCap: msg.GasFeeCap(),
Gas: msg.Gas(),
To: msg.To(),
Value: msg.Value(),
Data: msg.Data(),
}).MarshalBinary()
if err != nil {
return nil, fmt.Errorf("failed to convert tx msg, err=%w", err)

Check warning on line 760 in x/fungible/keeper/evm.go

View check run for this annotation

Codecov / codecov/patch

x/fungible/keeper/evm.go#L758-L760

Added lines #L758 - L760 were not covered by tests
}
attrs = append(attrs, sdk.NewAttribute("TxBytes", hexutil.Encode(txBytes)))
attrs = append(attrs, sdk.NewAttribute("TxData", hexutil.Encode(msg.Data())))
attrs = append(attrs, sdk.NewAttribute("TxNonce", fmt.Sprint(nonce)))

attrs = append(attrs, sdk.NewAttribute("TxHash", ethTxHash.Hex()))
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
Expand Down

0 comments on commit 2e275f8

Please sign in to comment.