Skip to content

Commit

Permalink
Update tracer
Browse files Browse the repository at this point in the history
BeginBlock and EndBlock will fetch the tracer from the sdk.Context, when calling ApplyTransaction, we will fetch the tracer from the keeper.evmTracer
  • Loading branch information
Eduard-Voiculescu committed Oct 15, 2024
1 parent 3f8d55e commit 7867d50
Show file tree
Hide file tree
Showing 15 changed files with 267 additions and 182 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ replace (
cosmossdk.io/store => github.com/InjectiveLabs/cosmos-sdk/store v0.0.0-20240904140803-b4127ecb5410
cosmossdk.io/x/tx => github.com/InjectiveLabs/cosmos-sdk/x/tx v0.0.0-20240904140803-b4127ecb5410

github.com/cometbft/cometbft => github.com/streamingfast/cometbft v0.38.11-inj-5
github.com/cometbft/cometbft => github.com/Injectivelabs/cometbft v0.38.11-inj-5
github.com/cosmos/cosmos-sdk => github.com/InjectiveLabs/cosmos-sdk v0.50.10-0.20241010141128-de2b5199b23e
github.com/ethereum/go-ethereum => github.com/InjectiveLabs/go-ethereum v1.9.22-0.20240923100242-5e28e23d353e
nhooyr.io/websocket => github.com/coder/websocket v1.8.10 // replaced as instructed here:https://coder.com/blog/websocket
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ github.com/InjectiveLabs/go-ethereum v1.9.22-0.20240923100242-5e28e23d353e h1:yX
github.com/InjectiveLabs/go-ethereum v1.9.22-0.20240923100242-5e28e23d353e/go.mod h1:PHp+ZPjvQGBT2/iU18sro79JX+Ffy8IIqU7lnuVX3oE=
github.com/InjectiveLabs/metrics v0.0.10 h1:BoOwXnCtRRIPmq06jcI20pXZYE758eusaCI5jDOoN4U=
github.com/InjectiveLabs/metrics v0.0.10/go.mod h1:eYu++0DVUjk/jjV9WgvCo8gQU+16Yoyhp1iu+ghKNME=
github.com/Injectivelabs/cometbft v0.38.11-inj-5 h1:VrfeIvIEhdHwF7KfMZ1KmQRiT0TseSVRmx0NDoQc0Dw=
github.com/Injectivelabs/cometbft v0.38.11-inj-5/go.mod h1:WreBJKC7CtZ9cNsb5p6uNpfCBwNWDu+risVb58GTLfY=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
Expand Down Expand Up @@ -1119,8 +1121,6 @@ github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
github.com/streamingfast/cometbft v0.38.11-inj-5 h1:6nEaRsiBtihMb3QUhcgATQzCG7V+DKxFGH707hA1Ju8=
github.com/streamingfast/cometbft v0.38.11-inj-5/go.mod h1:WreBJKC7CtZ9cNsb5p6uNpfCBwNWDu+risVb58GTLfY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
Expand Down
3 changes: 2 additions & 1 deletion rpc/backend/tx_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac
}
}
}
// if we still unable to find the eth tx index, return error, shouldn't happen.

// if we are still unable to find the eth tx index, return error, shouldn't happen.
if res.EthTxIndex == -1 {
return nil, errors.New("can't find index of ethereum tx")
}
Expand Down
13 changes: 7 additions & 6 deletions x/evm/keeper/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package keeper

import (
sdk "github.com/cosmos/cosmos-sdk/types"
cosmostracing "github.com/evmos/ethermint/x/evm/tracing"
)

// BeginBlock sets the sdk Context and EIP155 chain id to the Keeper.
Expand All @@ -29,8 +30,9 @@ func (k *Keeper) BeginBlock(ctx sdk.Context) error {
return err
}

if k.evmTracer != nil && k.evmTracer.OnCosmosBlockStart != nil {
k.evmTracer.OnCosmosBlockStart(
// In the case of BeginBlock hook, we can extract the tracer from the context
if tracer := cosmostracing.GetCtxBlockchainTracer(ctx); tracer != nil && tracer.OnCosmosBlockStart != nil {
tracer.OnCosmosBlockStart(
ToCosmosStartBlockEvent(
k,
ctx,
Expand All @@ -50,10 +52,9 @@ func (k *Keeper) EndBlock(ctx sdk.Context) error {
k.CollectTxBloom(ctx)
k.RemoveParamsCache(ctx)

if k.evmTracer != nil && k.evmTracer.OnCosmosBlockEnd != nil {
defer func() {
k.evmTracer.OnCosmosBlockEnd(ToCosmosEndBlockEvent(k, ctx), nil)
}()
// In the case of EndBlock hook, we can extract the tracer from the context
if tracer := cosmostracing.GetCtxBlockchainTracer(ctx); tracer != nil && tracer.OnCosmosBlockEnd != nil {
tracer.OnCosmosBlockEnd(ToCosmosEndBlockEvent(k, ctx), nil)
}

return nil
Expand Down
22 changes: 14 additions & 8 deletions x/evm/keeper/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
package keeper

import (
"github.com/ethereum/go-ethereum/eth/tracers"
cosmostracing "github.com/evmos/ethermint/x/evm/tracing"
"math/big"

errorsmod "cosmossdk.io/errors"
Expand Down Expand Up @@ -53,7 +53,7 @@ type EVMBlockConfig struct {
type EVMConfig struct {
*EVMBlockConfig
TxConfig statedb.TxConfig
Tracer *tracers.Tracer
Tracer *cosmostracing.Hooks
DebugTrace bool
Overrides *rpctypes.StateOverride
BlockOverrides *rpctypes.BlockOverrides
Expand Down Expand Up @@ -131,13 +131,19 @@ func (k *Keeper) EVMConfig(ctx sdk.Context, chainID *big.Int, txHash common.Hash
TxConfig: txConfig,
}

return cfg, nil
}

// EVMConfigWithTracer creates the EVMConfig based on current state and returns the evmTracer
func (k *Keeper) EVMConfigWithTracer(ctx sdk.Context, chainID *big.Int, txHash common.Hash) (*EVMConfig, error) {
cfg, err := k.EVMConfig(ctx, chainID, txHash)

if err != nil {
return nil, err
}

if k.evmTracer != nil {
t := &tracers.Tracer{
Hooks: k.evmTracer.Hooks,
GetResult: nil,
Stop: nil,
}
cfg.Tracer = t
cfg.Tracer = k.evmTracer
}

return cfg, nil
Expand Down
5 changes: 4 additions & 1 deletion x/evm/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"encoding/json"
"errors"
"fmt"
cosmostracing "github.com/evmos/ethermint/x/evm/tracing"
"math/big"
"time"

Expand Down Expand Up @@ -719,7 +720,9 @@ func (k *Keeper) prepareTrace(
cfg.BlockOverrides = &blockOverrides
}

cfg.Tracer = tracer
cfg.Tracer = &cosmostracing.Hooks{
Hooks: tracer.Hooks,
}
cfg.DebugTrace = true
res, err := k.ApplyMessageWithConfig(ctx, msg, cfg, commitMessage)
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions x/evm/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ func (k Keeper) ChainID() *big.Int {
return k.eip155ChainID
}

func (k *Keeper) InitChainer() {
if k.evmTracer != nil && k.evmTracer.OnBlockchainInit != nil {
k.evmTracer.OnBlockchainInit(evmtypes.DefaultChainConfig().EthereumConfig(k.ChainID()))
func (k *Keeper) InitChainer(ctx sdk.Context) {
if tracer := cosmostracing.GetCtxBlockchainTracer(ctx); tracer != nil && tracer.OnBlockchainInit != nil {
tracer.OnBlockchainInit(evmtypes.DefaultChainConfig().EthereumConfig(k.ChainID()))
}
}

Expand Down
114 changes: 45 additions & 69 deletions x/evm/keeper/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package keeper
import (
"bytes"
"fmt"
cosmostracing "github.com/evmos/ethermint/x/evm/tracing"
"math/big"
"sort"

Expand All @@ -33,14 +34,15 @@ import (

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/tracing"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/params"
)

var configOverridesErrDesc = "failed to apply state override"

// NewEVM generates a go-ethereum VM from the provided Message fields and the chain parameters
// (ChainConfig and module Params). It additionally sets the validator operator address as the
// coinbase address to make it available for the COINBASE opcode, even though there is no
Expand Down Expand Up @@ -73,13 +75,8 @@ func (k *Keeper) NewEVM(
txCtx := core.NewEVMTxContext(msg)

// Set Config Tracer if it was not already initialized
if k.evmTracer != nil {
t := &tracers.Tracer{
Hooks: k.evmTracer.Hooks,
GetResult: nil,
Stop: nil,
}
cfg.Tracer = t
if tracer := cosmostracing.GetCtxBlockchainTracer(ctx); tracer != nil {
cfg.Tracer = tracer
}

vmConfig := k.VMConfig(ctx, cfg)
Expand Down Expand Up @@ -159,7 +156,7 @@ func (k Keeper) GetHashFn(ctx sdk.Context) vm.GetHashFunc {
}
}

// ApplyTransaction runs and attempts to perform a state transition with the given transaction (i.e Message), that will
// ApplyTransaction runs and attempts to perform a state transition with the given transaction (i.e. Message), that will
// only be persisted (committed) to the underlying KVStore if the transaction does not fail.
//
// # Gas tracking
Expand All @@ -178,7 +175,7 @@ func (k Keeper) GetHashFn(ctx sdk.Context) vm.GetHashFunc {
// For relevant discussion see: https://github.com/cosmos/cosmos-sdk/discussions/9072
func (k *Keeper) ApplyTransaction(ctx sdk.Context, msgEth *types.MsgEthereumTx) (*types.MsgEthereumTxResponse, error) {
ethTx := msgEth.AsTransaction()
cfg, err := k.EVMConfig(ctx, k.eip155ChainID, ethTx.Hash())
cfg, err := k.EVMConfigWithTracer(ctx, k.eip155ChainID, ethTx.Hash())
if err != nil {
return nil, errorsmod.Wrap(err, "failed to load evm config")
}
Expand All @@ -196,9 +193,9 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, msgEth *types.MsgEthereumTx)
}

// pass true to commit the StateDB
res, err := k.ApplyMessageWithConfig(tmpCtx, msg, cfg, true)
if err != nil {
return nil, errorsmod.Wrap(err, "failed to apply ethereum core message")
res, applyMessageErr := k.ApplyMessageWithConfig(tmpCtx, msg, cfg, true)
if applyMessageErr != nil {
return nil, errorsmod.Wrap(applyMessageErr, "failed to apply ethereum core message")
}

logs := types.LogsToEthereum(res.Logs)
Expand Down Expand Up @@ -254,6 +251,19 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, msgEth *types.MsgEthereumTx)

// reset the gas meter for current cosmos transaction
k.ResetGasMeterAndConsumeGas(ctx, totalGasUsed)

defer func() {
// These errors are not vm related, so they should not be passed to the vm tracer
if !errorsmod.IsOf(applyMessageErr, types.ErrCreateDisabled, types.ErrCallDisabled) && (applyMessageErr != nil && applyMessageErr.Error() != configOverridesErrDesc) {
if cfg.Tracer != nil && cfg.Tracer.OnTxEnd != nil {
cfg.Tracer.OnTxEnd(
receipt,
applyMessageErr,
)
}
}
}()

return res, nil
}

Expand Down Expand Up @@ -337,69 +347,33 @@ func (k *Keeper) ApplyMessageWithConfig(
var evm *vm.EVM
if cfg.Overrides != nil {
if err := cfg.Overrides.Apply(stateDB); err != nil {
return nil, errorsmod.Wrap(err, "failed to apply state override")
return nil, errorsmod.Wrap(err, configOverridesErrDesc)
}
}

evm = k.NewEVM(ctx, msg, cfg, stateDB)
leftoverGas := msg.GasLimit
sender := vm.AccountRef(msg.From)

// Allow the tracer captures the tx level events, mainly the gas consumption.
vmCfg := evm.Config
tx := ethtypes.NewTx(&ethtypes.LegacyTx{
Nonce: msg.Nonce,
Gas: msg.GasLimit,
GasPrice: msg.GasPrice,
To: msg.To,
Value: msg.Value,
Data: msg.Data,
})

if vmCfg.Tracer != nil {
stateDB.SetTracer(k.evmTracer)
vmCfg.Tracer.OnTxStart(
if cfg.Tracer != nil && cfg.Tracer.OnCosmosTxStart != nil {
stateDB.SetTracer(cfg.Tracer)
cfg.Tracer.OnCosmosTxStart(
evm.GetVMContext(),
ethtypes.NewTx(&ethtypes.LegacyTx{
Nonce: msg.Nonce,
Gas: msg.GasLimit,
GasPrice: msg.GasPrice,
To: msg.To,
Value: msg.Value,
Data: msg.Data,
}),
tx,
cfg.TxConfig.TxHash,
msg.From,
)

//if cfg.DebugTrace {
// // msg.GasPrice should have been set to effective gas price
// senderAddr := sender.Address()
// stateDB.SubBalance(
// sender.Address(),
// uint256.MustFromBig(new(big.Int).Mul(msg.GasPrice, new(big.Int).SetUint64(msg.GasLimit))),
// tracing.BalanceChangeUnspecified,
// )
// stateDB.SetNonce(senderAddr, stateDB.GetNonce(senderAddr)+1)
//}

defer func() {
//if cfg.DebugTrace {
// stateDB.AddBalance(
// sender.Address(),
// uint256.MustFromBig(new(big.Int).Mul(msg.GasPrice, new(big.Int).SetUint64(leftoverGas))),
// tracing.BalanceChangeUnspecified,
// )
//}

traceErr := err
if vmErr != nil {
traceErr = vmErr
}

vmCfg.Tracer.OnTxEnd(
&ethtypes.Receipt{
GasUsed: gasUsed,
},
traceErr,
)
}()
}

//todo: on each of the exit conditions before the calls to if contractCreation {
// and manually catch them in the defer.vmcfg.tracer.ontxend
// also, I think that we have to manually craft a Call/Create?

rules := cfg.Rules
contractCreation := msg.To == nil
intrinsicGas, err := k.GetEthIntrinsicGas(msg, rules, contractCreation)
Expand Down Expand Up @@ -428,6 +402,7 @@ func (k *Keeper) ApplyMessageWithConfig(
stateDB.Prepare(rules, msg.From, cfg.CoinBase, msg.To, vm.DefaultActivePrecompiles(rules), msg.AccessList)

if contractCreation {
// FIXME: also why do we want to set the nonce in the statedb twice here?
// take over the nonce management from evm:
// - reset sender's nonce to msg.Nonce() before calling evm.
// - increase sender's nonce by one no matter the result.
Expand All @@ -436,6 +411,12 @@ func (k *Keeper) ApplyMessageWithConfig(
stateDB.SetNonce(sender.Address(), msg.Nonce+1)
} else {
ret, leftoverGas, vmErr = evm.Call(sender, *msg.To, msg.Data, leftoverGas, uint256.MustFromBig(msg.Value))

// if they do not want to make the nonce set to the statedb or do we want to manually call the onNonceChange hook
//stateDB.SetNonce(sender.Address(), msg.Nonce+1)
if cfg.Tracer != nil && cfg.Tracer.OnNonceChange != nil {
cfg.Tracer.OnNonceChange(sender.Address(), msg.Nonce, msg.Nonce+1)
}
}

refundQuotient := params.RefundQuotient
Expand Down Expand Up @@ -486,11 +467,6 @@ func (k *Keeper) ApplyMessageWithConfig(
// reset leftoverGas, to be used by the tracer
leftoverGas = msg.GasLimit - gasUsed

if k.evmTracer != nil && k.evmTracer.OnGasChange != nil {
//TODO: add test to make sure the onGasChange is not doubly called
k.evmTracer.OnGasChange(msg.GasLimit, leftoverGas, tracing.GasChangeTxLeftOverReturned)
}

return &types.MsgEthereumTxResponse{
GasUsed: gasUsed,
VmError: vmError,
Expand Down
Loading

0 comments on commit 7867d50

Please sign in to comment.