Skip to content

Commit

Permalink
Porting EVM tracer + Firehose to seiv2
Browse files Browse the repository at this point in the history
  • Loading branch information
maoueh committed Apr 17, 2024
1 parent 4025070 commit 4763011
Show file tree
Hide file tree
Showing 21 changed files with 7,097 additions and 22 deletions.
83 changes: 79 additions & 4 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@ import (
"encoding/json"
"fmt"
"io"
"math/big"
"os"
"path/filepath"
"strings"
"sync"
"time"

ethcommon "github.com/ethereum/go-ethereum/common"
ethhexutil "github.com/ethereum/go-ethereum/common/hexutil"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
ethrpc "github.com/ethereum/go-ethereum/rpc"

"github.com/sei-protocol/sei-chain/app/antedecorators"
"github.com/sei-protocol/sei-chain/evmrpc"
"github.com/sei-protocol/sei-chain/precompiles"
Expand Down Expand Up @@ -126,6 +131,8 @@ import (
evmkeeper "github.com/sei-protocol/sei-chain/x/evm/keeper"
"github.com/sei-protocol/sei-chain/x/evm/querier"
"github.com/sei-protocol/sei-chain/x/evm/replay"
evmtracers "github.com/sei-protocol/sei-chain/x/evm/tracers"
"github.com/sei-protocol/sei-chain/x/evm/tracing"
evmtypes "github.com/sei-protocol/sei-chain/x/evm/types"
"github.com/spf13/cast"
abci "github.com/tendermint/tendermint/abci/types"
Expand Down Expand Up @@ -375,6 +382,7 @@ type App struct {

encodingConfig appparams.EncodingConfig
evmRPCConfig evmrpc.Config
evmTracer *tracing.Hooks
}

// New returns a reference to an initialized blockchain app
Expand Down Expand Up @@ -622,6 +630,15 @@ func New(
app.EvmKeeper.EthClient = ethclient.NewClient(rpcclient)
}

if app.evmRPCConfig.LiveEVMTracer != "" {
chainConfig := evmtypes.DefaultChainConfig().EthereumConfig(app.EvmKeeper.ChainID())
evmTracer, err := evmtracers.NewBlockchainTracer(evmtracers.GlobalLiveTracerRegistry, app.evmRPCConfig.LiveEVMTracer, chainConfig)
if err != nil {
panic(fmt.Sprintf("error creating EVM tracer due to %s", err))
}
app.evmTracer = evmTracer
}

customDependencyGenerators := aclmapping.NewCustomDependencyGenerator()
aclOpts = append(aclOpts, aclkeeper.WithResourceTypeToStoreKeyMap(aclutils.ResourceTypeToStoreKeyMap))
aclOpts = append(aclOpts, aclkeeper.WithDependencyGeneratorMappings(customDependencyGenerators.GetCustomDependencyGenerators(app.EvmKeeper)))
Expand Down Expand Up @@ -1416,12 +1433,23 @@ func (app *App) ProcessTXsWithOCC(ctx sdk.Context, txs [][]byte, typedTxs []sdk.
wg.Add(1)
go func(txIndex int, tx []byte) {
defer wg.Done()

var txTracer sdk.TxTracer
if app.evmTracer != nil {
txTracer = app.evmTracer
if app.evmTracer.GetTxTracer != nil {
txTracer = app.evmTracer.GetTxTracer(absoluteTxIndices[txIndex])
}
}

deliverTxEntry := &sdk.DeliverTxEntry{
Request: abci.RequestDeliverTx{Tx: tx},
SdkTx: typedTxs[txIndex],
Checksum: sha256.Sum256(tx),
AbsoluteIndex: absoluteTxIndices[txIndex],
TxTracer: txTracer,
}

// get prefill estimate
estimatedWritesets, err := app.AccessControlKeeper.GenerateEstimatedWritesets(ctx, app.GetAnteDepGenerator(), txIndex, typedTxs[txIndex])
// if no error, then we assign the mapped writesets for prefill estimate
Expand Down Expand Up @@ -1482,12 +1510,17 @@ func (app *App) BuildDependenciesAndRunTxs(ctx sdk.Context, txs [][]byte, typedT
return app.ProcessBlockSynchronous(ctx, txs, typedTxs, absoluteTxIndices), ctx
}

func (app *App) ProcessBlock(ctx sdk.Context, txs [][]byte, req BlockProcessRequest, lastCommit abci.CommitInfo) ([]abci.Event, []*abci.ExecTxResult, abci.ResponseEndBlock, error) {
func (app *App) ProcessBlock(ctx sdk.Context, txs [][]byte, req BlockProcessRequest, lastCommit abci.CommitInfo) (events []abci.Event, txResults []*abci.ExecTxResult, endBlockResp abci.ResponseEndBlock, err error) {
ctx = ctx.WithIsOCCEnabled(app.OccEnabled())

goCtx := app.decorateContextWithDexMemState(ctx.Context())
ctx = ctx.WithContext(goCtx)

events := []abci.Event{}
if app.evmTracer != nil {
ctx = evmtracers.SetCtxBlockchainTracer(ctx, app.evmTracer)
}

events = []abci.Event{}
beginBlockReq := abci.RequestBeginBlock{
Hash: req.GetHash(),
ByzantineValidators: utils.Map(req.GetByzantineValidators(), func(mis abci.Misbehavior) abci.Evidence {
Expand All @@ -1512,9 +1545,16 @@ func (app *App) ProcessBlock(ctx sdk.Context, txs [][]byte, req BlockProcessRequ
beginBlockResp := app.BeginBlock(ctx, beginBlockReq)
events = append(events, beginBlockResp.Events...)

txResults := make([]*abci.ExecTxResult, len(txs))
txResults = make([]*abci.ExecTxResult, len(txs))
typedTxs := app.DecodeTransactionsConcurrently(ctx, txs)

if app.evmTracer != nil {
header := ctx.BlockHeader()
app.evmTracer.OnSeiBlockStart(req.GetHash(), uint64(header.Size()), TmBlockHeaderToEVM(ctx, header, &app.EvmKeeper))
defer func() {
app.evmTracer.OnSeiBlockEnd(err)
}()
}
prioritizedTxs, otherTxs, prioritizedTypedTxs, otherTypedTxs, prioritizedIndices, otherIndices := app.PartitionPrioritizedTxs(ctx, txs, typedTxs)

// run the prioritized txs
Expand All @@ -1540,7 +1580,7 @@ func (app *App) ProcessBlock(ctx sdk.Context, txs [][]byte, req BlockProcessRequ
lazyWriteEvents := app.BankKeeper.WriteDeferredBalances(ctx)
events = append(events, lazyWriteEvents...)

endBlockResp := app.EndBlock(ctx, abci.RequestEndBlock{
endBlockResp = app.EndBlock(ctx, abci.RequestEndBlock{
Height: req.GetHeight(),
})

Expand Down Expand Up @@ -1851,3 +1891,38 @@ func init() {
// override max wasm size to 2MB
wasmtypes.MaxWasmSize = 2 * 1024 * 1024
}

func TmBlockHeaderToEVM(
ctx sdk.Context,
block tmproto.Header,
k *evmkeeper.Keeper,
) (header *ethtypes.Header) {
number := big.NewInt(block.Height)
lastHash := ethcommon.BytesToHash(block.LastBlockId.Hash)
appHash := ethcommon.BytesToHash(block.AppHash)
txHash := ethcommon.BytesToHash(block.DataHash)
resultHash := ethcommon.BytesToHash(block.LastResultsHash)
miner := ethcommon.BytesToAddress(block.ProposerAddress)
gasLimit, gasWanted := uint64(0), uint64(0)

header = &ethtypes.Header{
Number: number,
ParentHash: lastHash,
Nonce: ethtypes.BlockNonce{}, // inapplicable to Sei
MixDigest: ethcommon.Hash{}, // inapplicable to Sei
UncleHash: ethtypes.EmptyUncleHash, // inapplicable to Sei
Bloom: k.GetBlockBloom(ctx, block.Height),
Root: appHash,
Coinbase: miner,
Difficulty: big.NewInt(0), // inapplicable to Sei
Extra: ethhexutil.Bytes{}, // inapplicable to Sei
GasLimit: gasLimit,
GasUsed: gasWanted,
Time: uint64(block.Time.Unix()),
TxHash: txHash,
ReceiptHash: resultHash,
BaseFee: k.GetBaseFeePerGas(ctx).RoundInt().BigInt(),
}

return
}
4 changes: 2 additions & 2 deletions app/eth_replay.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
ethcore "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/tracing"
ethtracing "github.com/ethereum/go-ethereum/core/tracing"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
ethtests "github.com/ethereum/go-ethereum/tests"
Expand Down Expand Up @@ -85,7 +85,7 @@ func Replay(a *App) {
for _, w := range b.Withdrawals() {
amount := new(big.Int).SetUint64(w.Amount)
amount = amount.Mul(amount, big.NewInt(params.GWei))
s.AddBalance(w.Address, amount, tracing.BalanceIncreaseWithdrawal)
s.AddBalance(w.Address, amount, ethtracing.BalanceIncreaseWithdrawal)
}
_, _ = s.Finalize()
for _, tx := range b.Txs {
Expand Down
6 changes: 6 additions & 0 deletions buf.gen.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: v1
plugins:
- plugin: buf.build/protocolbuffers/go:v1.31.0
out: pb
opt: paths=source_relative

14 changes: 14 additions & 0 deletions evmrpc/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ type Config struct {
// Timeout for EVM call in simulation
SimulationEVMTimeout time.Duration `mapstructure:"simulation_evm_timeout"`

// The EVM tracer to use when doing node synchronization, applies to
// all block produced but traces only EVM transactions.
//
// Refer to x/evm/tracers/registry.go#GlobalLiveTracerRegistry for registered tracers.
LiveEVMTracer string `mapstructure:"live_evm_tracer"`

// list of CORS allowed origins, separated by comma
CORSOrigins string `mapstructure:"cors_origins"`

Expand Down Expand Up @@ -92,6 +98,7 @@ var DefaultConfig = Config{
IdleTimeout: rpc.DefaultHTTPTimeouts.IdleTimeout,
SimulationGasLimit: 10_000_000, // 10M
SimulationEVMTimeout: 60 * time.Second,
LiveEVMTracer: "",
CORSOrigins: "*",
WSOrigins: "*",
FilterTimeout: 120 * time.Second,
Expand All @@ -114,6 +121,7 @@ const (
flagIdleTimeout = "evm.idle_timeout"
flagSimulationGasLimit = "evm.simulation_gas_limit"
flagSimulationEVMTimeout = "evm.simulation_evm_timeout"
flagLiveEVMTracer = "evm.live_evm_tracer"
flagCORSOrigins = "evm.cors_origins"
flagWSOrigins = "evm.ws_origins"
flagFilterTimeout = "evm.filter_timeout"
Expand Down Expand Up @@ -178,6 +186,11 @@ func ReadConfig(opts servertypes.AppOptions) (Config, error) {
return cfg, err
}
}
if v := opts.Get(flagLiveEVMTracer); v != nil {
if cfg.LiveEVMTracer, err = cast.ToStringE(v); err != nil {
return cfg, err
}
}
if v := opts.Get(flagCORSOrigins); v != nil {
if cfg.CORSOrigins, err = cast.ToStringE(v); err != nil {
return cfg, err
Expand Down Expand Up @@ -223,5 +236,6 @@ func ReadConfig(opts servertypes.AppOptions) (Config, error) {
return cfg, err
}
}

return cfg, nil
}
8 changes: 7 additions & 1 deletion evmrpc/config_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package evmrpc_test

import (
"fmt"
"testing"
"time"

Expand All @@ -19,6 +20,7 @@ type opts struct {
idleTimeout interface{}
simulationGasLimit interface{}
simulationEVMTimeout interface{}
liveEVMTracer interface{}
corsOrigins interface{}
wsOrigins interface{}
filterTimeout interface{}
Expand Down Expand Up @@ -61,6 +63,9 @@ func (o *opts) Get(k string) interface{} {
if k == "evm.simulation_evm_timeout" {
return o.simulationEVMTimeout
}
if k == "evm.live_evm_tracer" {
return o.liveEVMTracer
}
if k == "evm.cors_origins" {
return o.corsOrigins
}
Expand Down Expand Up @@ -88,7 +93,7 @@ func (o *opts) Get(k string) interface{} {
if k == "evm.max_blocks_for_log" {
return o.maxBlocksForLog
}
panic("unknown key")
panic(fmt.Errorf("unknown key: %s", k))
}

func TestReadConfig(t *testing.T) {
Expand All @@ -105,6 +110,7 @@ func TestReadConfig(t *testing.T) {
time.Duration(60),
"",
"",
"",
time.Duration(5),
time.Duration(5),
1000,
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1433,6 +1433,8 @@ github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8L
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/sei-cosmos v0.0.0-20240327153024-8e22d1da5334 h1:+4kXknHWASf4Qq0yo67kDmZcBDeSUxVICb34CDEY6Kw=
github.com/streamingfast/sei-cosmos v0.0.0-20240327153024-8e22d1da5334/go.mod h1:ib/gp0gCxN7FXUZ40j5+x8BeyoI7AcX+rTvf53JoDsY=
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
27 changes: 27 additions & 0 deletions pb/sf/ethereum/type/v2/type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package pbeth

import (
"encoding/hex"
"math/big"
"time"
)

var b0 = big.NewInt(0)

func (b *Block) PreviousID() string {
return hex.EncodeToString(b.Header.ParentHash)
}

func (b *Block) Time() time.Time {
return b.Header.Timestamp.AsTime()
}

func (m *BigInt) Native() *big.Int {
if m == nil {
return b0
}

z := new(big.Int)
z.SetBytes(m.Bytes)
return z
}
Loading

0 comments on commit 4763011

Please sign in to comment.