feat: add mux tracer for native call tracer and native prestate tracers (#615)

* hack to use native tracers

* update

* fix

* add prestate

* fix marshal

* format

* draft

* move

* separate `MuxTracer`

* fix

* update miner/worker.go

* update api

* rename

* remove

* bump go version

* bump golangci

* goimports lint

* fix tests

* minor

* clean up

* fix tests

* sync error handling

* bump go version in Dockerfiles

* bump version

* lint: disable `goconst` & `goimports`

* bump version again

* add comments

---------

Co-authored-by: lightsing <light.tsing@gmail.com>
This commit is contained in:
HAOYUatHZ 2024-01-18 14:58:27 +08:00 committed by GitHub
parent fc06826a04
commit 88349c600d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
50 changed files with 883 additions and 447 deletions

View file

@ -20,7 +20,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: 1.18.x
go-version: 1.20.x
- name: Checkout code
uses: actions/checkout@v2
- name: Build
@ -33,7 +33,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: 1.19.x
go-version: 1.20.x
- name: Install rust
uses: actions-rs/toolchain@v1
with:
@ -55,7 +55,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: 1.18.x
go-version: 1.20.x
- name: Checkout code
uses: actions/checkout@v2
- name: Lint
@ -69,7 +69,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: 1.18.x
go-version: 1.20.x
- name: Install goimports
run: go install golang.org/x/tools/cmd/goimports@latest
- name: Checkout code
@ -89,7 +89,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: 1.18.x
go-version: 1.20.x
- name: Checkout code
uses: actions/checkout@v2
- name: Test

View file

@ -13,8 +13,8 @@ linters:
disable-all: true
enable:
- deadcode
- goconst
- goimports
# - goconst
# - goimports
- gosimple
- govet
- ineffassign

View file

@ -4,7 +4,7 @@ ARG VERSION=""
ARG BUILDNUM=""
# Build libzkp dependency
FROM scrolltech/go-rust-builder:go-1.19-rust-nightly-2022-12-10 as chef
FROM scrolltech/go-rust-builder:go-1.20-rust-nightly-2022-12-10 as chef
WORKDIR app
FROM chef as planner
@ -21,7 +21,7 @@ RUN cargo build --release
RUN find ./ | grep libzktrie.so | xargs -I{} cp {} /app/target/release/
# Build Geth in a stock Go builder container
FROM scrolltech/go-rust-builder:go-1.19-rust-nightly-2022-12-10 as builder
FROM scrolltech/go-rust-builder:go-1.20-rust-nightly-2022-12-10 as builder
ADD . /go-ethereum
COPY --from=zkp-builder /app/target/release/libzkp.so /usr/local/lib/

View file

@ -4,7 +4,7 @@ ARG VERSION=""
ARG BUILDNUM=""
# Build Geth in a stock Go builder container
FROM golang:1.19-alpine as builder
FROM golang:1.20-alpine as builder
RUN apk add --no-cache gcc musl-dev linux-headers git

View file

@ -4,7 +4,7 @@ ARG VERSION=""
ARG BUILDNUM=""
# Build Geth in a stock Go builder container
FROM scrolltech/go-rust-builder:go-1.19-rust-nightly-2022-12-10 as builder
FROM scrolltech/go-rust-builder:go-1.20-rust-nightly-2022-12-10 as builder
ADD . /go-ethereum
RUN cd /go-ethereum && env GO111MODULE=on go run build/ci.go install ./cmd/geth

View file

@ -4,7 +4,7 @@ ARG VERSION=""
ARG BUILDNUM=""
# Build Geth in a stock Go builder container
FROM golang:1.18-alpine as builder
FROM golang:1.20-alpine as builder
RUN apk add --no-cache gcc musl-dev linux-headers git

View file

@ -79,7 +79,7 @@ type SimulatedBackend struct {
func NewSimulatedBackendWithDatabase(database ethdb.Database, alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
genesis := core.Genesis{Config: params.AllEthashProtocolChanges, GasLimit: gasLimit, Alloc: alloc}
genesis.MustCommit(database)
blockchain, _ := core.NewBlockChain(database, nil, genesis.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
blockchain, _ := core.NewBlockChain(database, nil, genesis.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
backend := &SimulatedBackend{
database: database,

View file

@ -15,24 +15,30 @@ c4b2349a8d11350ca038b8c57f3cc58dc0b31284bcbed4f7fca39aeed28b4a51 go1.17.2.linux
fa6da0b829a66f5fab7e4e312fd6aa1b2d8f045c7ecee83b3d00f6fe5306759a go1.17.2.windows-amd64.zip
00575c85dc7a129ba892685a456b27a3f3670f71c8bfde1c5ad151f771d55df7 go1.17.2.windows-arm64.zip
658078aaaf7608693f37c4cf1380b2af418ab8b2d23fdb33e7e2d4339328590e golangci-lint-1.46.2-darwin-amd64.tar.gz
81f9b4afd62ec5e612ef8bc3b1d612a88b56ff289874831845cdad394427385f golangci-lint-1.46.2-darwin-arm64.tar.gz
943486e703e62ec55ecd90caeb22bcd39f8cc3962a93eec18c06b7bae12cb46f golangci-lint-1.46.2-freebsd-386.tar.gz
a75dd9ba7e08e8315c411697171db5375c0f6a1ece9e6fbeb9e9a4386822e17d golangci-lint-1.46.2-freebsd-amd64.tar.gz
83eedca1af72e8be055a1235177eb1b33524fbf08bec5730df2e6c3efade2b23 golangci-lint-1.46.2-freebsd-armv6.tar.gz
513d276c490de6f82baa01f9346d8d78b385f2ae97608f42f05d1f0f1314cd54 golangci-lint-1.46.2-freebsd-armv7.tar.gz
461a60016d516c69d406dc3e2d4957b722dbe684b7085dfac4802d0f84409e27 golangci-lint-1.46.2-linux-386.tar.gz
242cd4f2d6ac0556e315192e8555784d13da5d1874e51304711570769c4f2b9b golangci-lint-1.46.2-linux-amd64.tar.gz
ff5448ada2b3982581984d64b0dec614dba0a3ea4cab2d6a343c77927fc89f7e golangci-lint-1.46.2-linux-arm64.tar.gz
177f5210ef04aee282bfbc6ec519d36af5fb7d2b2c8d3f4ea5e59fdba71b0a27 golangci-lint-1.46.2-linux-armv6.tar.gz
10dd512a36ee978a1009edbca3ba3af410f0fda8df4d85f0e4793a24213870cc golangci-lint-1.46.2-linux-armv7.tar.gz
67779fa517c688c9db1090c3c456117d95c6b92979c623fe8cce8fb84251f21e golangci-lint-1.46.2-linux-mips64.tar.gz
c085f0f57bdccbb2c902a41b72ce210a3dfff16ca856789374745ab52004b6ee golangci-lint-1.46.2-linux-mips64le.tar.gz
abecef6421499248e58ed75d2938bc12b4b1f98b057f25060680b77bb51a881e golangci-lint-1.46.2-linux-ppc64le.tar.gz
134843a8f5c5c182c11979ea75f5866945d54757b2a04f3e5e04a0cf4fbf3a39 golangci-lint-1.46.2-linux-riscv64.tar.gz
9fe21a9476567aafe7a2e1a926b9641a39f920d4c0ea8eda9d968bc6136337f9 golangci-lint-1.46.2-linux-s390x.tar.gz
b48a421ec12a43f8fc8f977b9cf7d4a1ea1c4b97f803a238de7d3ce4ab23a84b golangci-lint-1.46.2-windows-386.zip
604acc1378a566abb0eac799362f3a37b7fcb5fa2268aeb2d5d954c829367301 golangci-lint-1.46.2-windows-amd64.zip
927def10db073da9687594072e6a3d9c891f67fa897105a2cfd715e018e7386c golangci-lint-1.46.2-windows-arm64.zip
729b76ed1d8b4e2612e38772b211503cb940e00a137bbaace1aa066f7c943737 golangci-lint-1.46.2-windows-armv6.zip
ea27c86d91e0b245ecbcfbf6cdb4ac0522d4bc6dca56bba02ea1bc77ad2917ac golangci-lint-1.46.2-windows-armv7.zip
632e96e6d5294fbbe7b2c410a49c8fa01c60712a0af85a567de85bcc1623ea21 golangci-lint-1.55.2-darwin-amd64.tar.gz
234463f059249f82045824afdcdd5db5682d0593052f58f6a3039a0a1c3899f6 golangci-lint-1.55.2-darwin-arm64.tar.gz
2bdd105e2d4e003a9058c33a22bb191a1e0f30fa0790acca0d8fbffac1d6247c golangci-lint-1.55.2-freebsd-386.tar.gz
e75056e8b082386676ce23eba455cf893931a792c0d87e1e3743c0aec33c7fb5 golangci-lint-1.55.2-freebsd-amd64.tar.gz
5789b933facaf6136bd23f1d50add67b79bbcf8dfdfc9069a37f729395940a66 golangci-lint-1.55.2-freebsd-armv6.tar.gz
7f21ab1008d05f32c954f99470fc86a83a059e530fe2add1d0b7d8ed4d8992a7 golangci-lint-1.55.2-freebsd-armv7.tar.gz
33ab06139b9219a28251f10821da94423db30285cc2af97494cbb2a281927de9 golangci-lint-1.55.2-illumos-amd64.tar.gz
57ce6f8ce3ad6ee45d7cc3d9a047545a851c2547637834a3fcb086c7b40b1e6b golangci-lint-1.55.2-linux-386.tar.gz
ca21c961a33be3bc15e4292dc40c98c8dcc5463a7b6768a3afc123761630c09c golangci-lint-1.55.2-linux-amd64.tar.gz
8eb0cee9b1dbf0eaa49871798c7f8a5b35f2960c52d776a5f31eb7d886b92746 golangci-lint-1.55.2-linux-arm64.tar.gz
3195f3e0f37d353fd5bd415cabcd4e263f5c29d3d0ffb176c26ff3d2c75eb3bb golangci-lint-1.55.2-linux-armv6.tar.gz
c823ee36eb1a719e171de1f2f5ca3068033dce8d9817232fd10ed71fd6650406 golangci-lint-1.55.2-linux-armv7.tar.gz
758a5d2a356dc494bd13ed4c0d4bf5a54a4dc91267ea5ecdd87b86c7ca0624e7 golangci-lint-1.55.2-linux-loong64.tar.gz
2c7b9abdce7cae802a67d583cd7c6dca520bff6d0e17c8535a918e2f2b437aa0 golangci-lint-1.55.2-linux-mips64.tar.gz
024e0a15b85352cc27271285526e16a4ab66d3e67afbbe446c9808c06cb8dbed golangci-lint-1.55.2-linux-mips64le.tar.gz
6b00f89ba5506c1de1efdd9fa17c54093013a294fefd8b9b31534db626a672ee golangci-lint-1.55.2-linux-ppc64le.tar.gz
0faa0d047d9bf7b703ed3ea65b6117043c93504f9ca1de25ae929d3901c73d4a golangci-lint-1.55.2-linux-riscv64.tar.gz
30dec9b22e7d5bb4e9d5ccea96da20f71cd7db3c8cf30b8ddc7cb9174c4d742a golangci-lint-1.55.2-linux-s390x.tar.gz
5a0ede48f79ad707902fdb29be8cd2abd8302dc122b65ebae3fdfc86751c7698 golangci-lint-1.55.2-netbsd-386.tar.gz
95af20a2e617126dd5b08122ece7819101070e1582a961067ce8c41172f901ad golangci-lint-1.55.2-netbsd-amd64.tar.gz
94fb7dacb7527847cc95d7120904e19a2a0a81a0d50d61766c9e0251da72ab9d golangci-lint-1.55.2-netbsd-armv6.tar.gz
ca906bce5fee9619400e4a321c56476fe4a4efb6ac4fc989d340eb5563348873 golangci-lint-1.55.2-netbsd-armv7.tar.gz
45b442f69fc8915c4500201c0247b7f3f69544dbc9165403a61f9095f2c57355 golangci-lint-1.55.2-windows-386.zip
f57d434d231d43417dfa631587522f8c1991220b43c8ffadb9c7bd279508bf81 golangci-lint-1.55.2-windows-amd64.zip
fd7dc8f4c6829ee6fafb252a4d81d2155cd35da7833665cbb25d53ce7cecd990 golangci-lint-1.55.2-windows-arm64.zip
1892c3c24f9e7ef44b02f6750c703864b6dc350129f3ec39510300007b2376f1 golangci-lint-1.55.2-windows-armv6.zip
a5e68ae73d38748b5269fad36ac7575e3c162a5dc63ef58abdea03cc5da4522a golangci-lint-1.55.2-windows-armv7.zip

View file

@ -24,19 +24,18 @@ Usage: go run build/ci.go <command> <command flags/arguments>
Available commands are:
install [ -arch architecture ] [ -cc compiler ] [ packages... ] -- builds packages and executables
test [ -coverage ] [ packages... ] -- runs the tests
lint -- runs certain pre-selected linters
archive [ -arch architecture ] [ -type zip|tar ] [ -signer key-envvar ] [ -signify key-envvar ] [ -upload dest ] -- archives build artifacts
importkeys -- imports signing keys from env
debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package
nsis -- creates a Windows NSIS installer
aar [ -local ] [ -sign key-id ] [-deploy repo] [ -upload dest ] -- creates an Android archive
xcode [ -local ] [ -sign key-id ] [-deploy repo] [ -upload dest ] -- creates an iOS XCode framework
purge [ -store blobstore ] [ -days threshold ] -- purges old archives from the blobstore
install [ -arch architecture ] [ -cc compiler ] [ packages... ] -- builds packages and executables
test [ -coverage ] [ packages... ] -- runs the tests
lint -- runs certain pre-selected linters
archive [ -arch architecture ] [ -type zip|tar ] [ -signer key-envvar ] [ -signify key-envvar ] [ -upload dest ] -- archives build artifacts
importkeys -- imports signing keys from env
debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package
nsis -- creates a Windows NSIS installer
aar [ -local ] [ -sign key-id ] [-deploy repo] [ -upload dest ] -- creates an Android archive
xcode [ -local ] [ -sign key-id ] [-deploy repo] [ -upload dest ] -- creates an iOS XCode framework
purge [ -store blobstore ] [ -days threshold ] -- purges old archives from the blobstore
For all commands, -n prevents execution of external programs (dry run mode).
*/
package main
@ -148,7 +147,7 @@ var (
// This is the version of go that will be downloaded by
//
// go run ci.go install -dlgo
dlgoVersion = "1.17.2"
dlgoVersion = "1.20.2"
)
var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin"))
@ -336,7 +335,7 @@ func doLint(cmdline []string) {
// downloadLinter downloads and unpacks golangci-lint.
func downloadLinter(cachedir string) string {
const version = "1.46.2"
const version = "1.55.2"
csdb := build.MustLoadChecksums("build/checksums.txt")
base := fmt.Sprintf("golangci-lint-%s-%s-%s", version, runtime.GOOS, runtime.GOARCH)

View file

@ -73,6 +73,7 @@ import (
"github.com/scroll-tech/go-ethereum/p2p/nat"
"github.com/scroll-tech/go-ethereum/p2p/netutil"
"github.com/scroll-tech/go-ethereum/params"
"github.com/scroll-tech/go-ethereum/rollup/tracing"
"github.com/scroll-tech/go-ethereum/rpc"
)
@ -1904,7 +1905,8 @@ func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend
if err != nil {
Fatalf("Failed to register the Ethereum service: %v", err)
}
stack.RegisterAPIs(tracers.APIs(backend.ApiBackend))
scrollTracerWrapper := tracing.NewTracerWrapper()
stack.RegisterAPIs(tracers.APIs(backend.ApiBackend, scrollTracerWrapper))
return backend.ApiBackend, nil
}
@ -1933,7 +1935,8 @@ func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend
Fatalf("Failed to create the LES server: %v", err)
}
}
stack.RegisterAPIs(tracers.APIs(backend.APIBackend))
scrollTracerWrapper := tracing.NewTracerWrapper()
stack.RegisterAPIs(tracers.APIs(backend.APIBackend, scrollTracerWrapper))
return backend.APIBackend, backend
}
@ -2130,7 +2133,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai
// TODO(rjl493456442) disable snapshot generation/wiping if the chain is read only.
// Disable transaction indexing/unindexing by default.
chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil, nil, false)
chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil, nil)
if err != nil {
Fatalf("Can't create BlockChain: %v", err)
}

View file

@ -55,7 +55,7 @@ func TestReimportMirroredState(t *testing.T) {
genesis := genspec.MustCommit(db)
// Generate a batch of blocks, each properly signed
chain, _ := core.NewBlockChain(db, nil, params.AllCliqueProtocolChanges, engine, vm.Config{}, nil, nil, false)
chain, _ := core.NewBlockChain(db, nil, params.AllCliqueProtocolChanges, engine, vm.Config{}, nil, nil)
defer chain.Stop()
blocks, _ := core.GenerateChain(params.AllCliqueProtocolChanges, genesis, engine, db, 3, func(i int, block *core.BlockGen) {
@ -89,7 +89,7 @@ func TestReimportMirroredState(t *testing.T) {
db = rawdb.NewMemoryDatabase()
genspec.MustCommit(db)
chain, _ = core.NewBlockChain(db, nil, params.AllCliqueProtocolChanges, engine, vm.Config{}, nil, nil, false)
chain, _ = core.NewBlockChain(db, nil, params.AllCliqueProtocolChanges, engine, vm.Config{}, nil, nil)
defer chain.Stop()
if _, err := chain.InsertChain(blocks[:2]); err != nil {
@ -102,7 +102,7 @@ func TestReimportMirroredState(t *testing.T) {
// Simulate a crash by creating a new chain on top of the database, without
// flushing the dirty states out. Insert the last block, triggering a sidechain
// reimport.
chain, _ = core.NewBlockChain(db, nil, params.AllCliqueProtocolChanges, engine, vm.Config{}, nil, nil, false)
chain, _ = core.NewBlockChain(db, nil, params.AllCliqueProtocolChanges, engine, vm.Config{}, nil, nil)
defer chain.Stop()
if _, err := chain.InsertChain(blocks[2:]); err != nil {

View file

@ -450,7 +450,7 @@ func TestClique(t *testing.T) {
batches[len(batches)-1] = append(batches[len(batches)-1], block)
}
// Pass all the headers through clique and ensure tallying succeeds
chain, err := core.NewBlockChain(db, nil, &config, engine, vm.Config{}, nil, nil, false)
chain, err := core.NewBlockChain(db, nil, &config, engine, vm.Config{}, nil, nil)
if err != nil {
t.Errorf("test %d: failed to create test chain: %v", i, err)
continue

View file

@ -201,7 +201,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
// Time the insertion of the new chain.
// State and blocks are stored in the same DB.
chainman, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
chainman, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
defer chainman.Stop()
b.ReportAllocs()
b.ResetTimer()
@ -316,7 +316,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
if err != nil {
b.Fatalf("error opening database at %v: %v", dir, err)
}
chain, err := NewBlockChain(db, &cacheConfig, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil, false)
chain, err := NewBlockChain(db, &cacheConfig, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil)
if err != nil {
b.Fatalf("error creating chain: %v", err)
}

View file

@ -43,25 +43,32 @@ type BlockValidator struct {
// circuit capacity checker related fields
checkCircuitCapacity bool // whether enable circuit capacity check
db ethdb.Database // db to store row consumption
cMu sync.Mutex // mutex for circuit capacity checker
tracer tracerWrapper // scroll tracer wrapper
circuitCapacityChecker *circuitcapacitychecker.CircuitCapacityChecker // circuit capacity checker instance
}
// NewBlockValidator returns a new block validator which is safe for re-use
func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engine consensus.Engine, db ethdb.Database, checkCircuitCapacity bool) *BlockValidator {
func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engine consensus.Engine) *BlockValidator {
validator := &BlockValidator{
config: config,
engine: engine,
bc: blockchain,
checkCircuitCapacity: checkCircuitCapacity,
db: db,
circuitCapacityChecker: circuitcapacitychecker.NewCircuitCapacityChecker(true),
config: config,
engine: engine,
bc: blockchain,
}
log.Info("created new BlockValidator", "CircuitCapacityChecker ID", validator.circuitCapacityChecker.ID)
return validator
}
type tracerWrapper interface {
CreateTraceEnvAndGetBlockTrace(*params.ChainConfig, ChainContext, consensus.Engine, ethdb.Database, *state.StateDB, *types.Block, *types.Block, bool) (*types.BlockTrace, error)
}
func (v *BlockValidator) SetupTracerAndCircuitCapacityChecker(tracer tracerWrapper) {
v.checkCircuitCapacity = true
v.tracer = tracer
v.circuitCapacityChecker = circuitcapacitychecker.NewCircuitCapacityChecker(true)
log.Info("new CircuitCapacityChecker in BlockValidator", "ID", v.circuitCapacityChecker.ID)
}
// ValidateBody validates the given block's uncles and verifies the block
// header's transaction and uncle roots. The headers are assumed to be already
// validated at this point.
@ -101,7 +108,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
// if a block's RowConsumption has been stored, which means it has been processed before,
// (e.g., in miner/worker.go or in insertChain),
// we simply skip its calculation and validation
if rawdb.ReadBlockRowConsumption(v.db, block.Hash()) != nil {
if rawdb.ReadBlockRowConsumption(v.bc.db, block.Hash()) != nil {
return nil
}
rowConsumption, err := v.validateCircuitRowConsumption(block)
@ -115,7 +122,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
"hash", block.Hash().String(),
"rowConsumption", rowConsumption,
)
rawdb.WriteBlockRowConsumption(v.db, block.Hash(), rowConsumption)
rawdb.WriteBlockRowConsumption(v.bc.db, block.Hash(), rowConsumption)
}
return nil
}
@ -179,7 +186,7 @@ func (v *BlockValidator) ValidateL1Messages(block *types.Block) error {
l1msg := it.L1Message()
skippedTx := types.NewTx(&l1msg)
log.Debug("Skipped L1 message", "queueIndex", index, "tx", skippedTx.Hash().String(), "block", blockHash.String())
rawdb.WriteSkippedTransaction(v.db, skippedTx, nil, "unknown", block.NumberU64(), &blockHash)
rawdb.WriteSkippedTransaction(v.bc.db, skippedTx, nil, "unknown", block.NumberU64(), &blockHash)
}
queueIndex = txQueueIndex + 1
@ -260,7 +267,7 @@ func CalcGasLimit(parentGasLimit, desiredLimit uint64) uint64 {
return limit
}
func (v *BlockValidator) createTraceEnv(block *types.Block) (*TraceEnv, error) {
func (v *BlockValidator) createTraceEnvAndGetBlockTrace(block *types.Block) (*types.BlockTrace, error) {
parent := v.bc.GetBlock(block.ParentHash(), block.NumberU64()-1)
if parent == nil {
return nil, errors.New("validateCircuitRowConsumption: no parent block found")
@ -271,7 +278,7 @@ func (v *BlockValidator) createTraceEnv(block *types.Block) (*TraceEnv, error) {
return nil, err
}
return CreateTraceEnv(v.config, v.bc, v.engine, v.db, statedb, parent, block, true)
return v.tracer.CreateTraceEnvAndGetBlockTrace(v.config, v.bc, v.engine, v.bc.db, statedb, parent, block, true)
}
func (v *BlockValidator) validateCircuitRowConsumption(block *types.Block) (*types.RowConsumption, error) {
@ -283,12 +290,7 @@ func (v *BlockValidator) validateCircuitRowConsumption(block *types.Block) (*typ
"len(txs)", block.Transactions().Len(),
)
env, err := v.createTraceEnv(block)
if err != nil {
return nil, err
}
traces, err := env.GetBlockTrace(block)
traces, err := v.createTraceEnvAndGetBlockTrace(block)
if err != nil {
return nil, err
}

View file

@ -42,7 +42,7 @@ func TestHeaderVerification(t *testing.T) {
headers[i] = block.Header()
}
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil, false)
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil)
defer chain.Stop()
for i := 0; i < len(blocks); i++ {
@ -106,11 +106,11 @@ func testHeaderConcurrentVerification(t *testing.T, threads int) {
var results <-chan error
if valid {
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil, false)
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil)
_, results = chain.engine.VerifyHeaders(chain, headers, seals)
chain.Stop()
} else {
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeFailer(uint64(len(headers)-1)), vm.Config{}, nil, nil, false)
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeFailer(uint64(len(headers)-1)), vm.Config{}, nil, nil)
_, results = chain.engine.VerifyHeaders(chain, headers, seals)
chain.Stop()
}
@ -173,7 +173,7 @@ func testHeaderConcurrentAbortion(t *testing.T, threads int) {
defer runtime.GOMAXPROCS(old)
// Start the verifications and immediately abort
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeDelayer(time.Millisecond), vm.Config{}, nil, nil, false)
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeDelayer(time.Millisecond), vm.Config{}, nil, nil)
defer chain.Stop()
abort, results := chain.engine.VerifyHeaders(chain, headers, seals)

View file

@ -220,7 +220,7 @@ type BlockChain struct {
// NewBlockChain returns a fully initialised block chain using information
// available in the database. It initialises the default Ethereum Validator and
// Processor.
func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(block *types.Block) bool, txLookupLimit *uint64, checkCircuitCapacity bool) (*BlockChain, error) {
func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(block *types.Block) bool, txLookupLimit *uint64) (*BlockChain, error) {
if cacheConfig == nil {
cacheConfig = defaultCacheConfig
}
@ -263,7 +263,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
engine: engine,
vmConfig: vmConfig,
}
bc.validator = NewBlockValidator(chainConfig, bc, engine, db, checkCircuitCapacity)
bc.validator = NewBlockValidator(chainConfig, bc, engine)
bc.prefetcher = newStatePrefetcher(chainConfig, bc, engine)
bc.processor = NewStateProcessor(chainConfig, bc, engine)

View file

@ -1783,7 +1783,7 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
config.SnapshotLimit = 256
config.SnapshotWait = true
}
chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil, false)
chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to create chain: %v", err)
}
@ -1836,7 +1836,7 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
}
defer db.Close()
chain, err = NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil, false)
chain, err = NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
@ -1907,7 +1907,7 @@ func TestIssue23496(t *testing.T) {
SnapshotWait: true,
}
)
chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil, false)
chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to create chain: %v", err)
}
@ -1951,7 +1951,7 @@ func TestIssue23496(t *testing.T) {
}
defer db.Close()
chain, err = NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil, false)
chain, err = NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}

View file

@ -1982,7 +1982,7 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
config.SnapshotLimit = 256
config.SnapshotWait = true
}
chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil, false)
chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to create chain: %v", err)
}

View file

@ -80,7 +80,7 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
// will happen during the block insertion.
cacheConfig = defaultCacheConfig
)
chain, err := NewBlockChain(db, cacheConfig, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil, false)
chain, err := NewBlockChain(db, cacheConfig, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to create chain: %v", err)
}
@ -223,7 +223,7 @@ func (snaptest *snapshotTest) test(t *testing.T) {
// Restart the chain normally
chain.Stop()
newchain, err := NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil, false)
newchain, err := NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
@ -259,13 +259,13 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) {
// the crash, we do restart twice here: one after the crash and one
// after the normal stop. It's used to ensure the broken snapshot
// can be detected all the time.
newchain, err := NewBlockChain(newdb, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil, false)
newchain, err := NewBlockChain(newdb, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
newchain.Stop()
newchain, err = NewBlockChain(newdb, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil, false)
newchain, err = NewBlockChain(newdb, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
@ -301,7 +301,7 @@ func (snaptest *gappedSnapshotTest) test(t *testing.T) {
TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 0,
}
newchain, err := NewBlockChain(snaptest.db, cacheConfig, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil, false)
newchain, err := NewBlockChain(snaptest.db, cacheConfig, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
@ -309,7 +309,7 @@ func (snaptest *gappedSnapshotTest) test(t *testing.T) {
newchain.Stop()
// Restart the chain with enabling the snapshot
newchain, err = NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil, false)
newchain, err = NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
@ -337,7 +337,7 @@ func (snaptest *setHeadSnapshotTest) test(t *testing.T) {
chain.SetHead(snaptest.setHead)
chain.Stop()
newchain, err := NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil, false)
newchain, err := NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
@ -368,7 +368,7 @@ func (snaptest *restartCrashSnapshotTest) test(t *testing.T) {
// and state committed.
chain.Stop()
newchain, err := NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil, false)
newchain, err := NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
@ -385,7 +385,7 @@ func (snaptest *restartCrashSnapshotTest) test(t *testing.T) {
// journal and latest state will be committed
// Restart the chain after the crash
newchain, err = NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil, false)
newchain, err = NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
@ -420,7 +420,7 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 0,
}
newchain, err := NewBlockChain(snaptest.db, config, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil, false)
newchain, err := NewBlockChain(snaptest.db, config, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
@ -436,13 +436,13 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
SnapshotLimit: 256,
SnapshotWait: false, // Don't wait rebuild
}
newchain, err = NewBlockChain(snaptest.db, config, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil, false)
newchain, err = NewBlockChain(snaptest.db, config, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
// Simulate the blockchain crash.
newchain, err = NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil, false)
newchain, err = NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}

View file

@ -58,7 +58,7 @@ func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *B
)
// Initialize a fresh chain with only a genesis block
blockchain, _ := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil, false)
blockchain, _ := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
// Create and inject the requested chain
if n == 0 {
return db, blockchain, nil
@ -524,7 +524,7 @@ func testReorgBadHashes(t *testing.T, full bool) {
blockchain.Stop()
// Create a new BlockChain and check that it rolled back the state.
ncm, err := NewBlockChain(blockchain.db, nil, blockchain.chainConfig, ethash.NewFaker(), vm.Config{}, nil, nil, false)
ncm, err := NewBlockChain(blockchain.db, nil, blockchain.chainConfig, ethash.NewFaker(), vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create new chain manager: %v", err)
}
@ -637,7 +637,7 @@ func TestFastVsFullChains(t *testing.T) {
// Import the chain as an archive node for the comparison baseline
archiveDb := rawdb.NewMemoryDatabase()
gspec.MustCommit(archiveDb)
archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
defer archive.Stop()
if n, err := archive.InsertChain(blocks); err != nil {
@ -646,7 +646,7 @@ func TestFastVsFullChains(t *testing.T) {
// Fast import the chain as a non-archive node to test
fastDb := rawdb.NewMemoryDatabase()
gspec.MustCommit(fastDb)
fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
defer fast.Stop()
headers := make([]*types.Header, len(blocks))
@ -670,7 +670,7 @@ func TestFastVsFullChains(t *testing.T) {
t.Fatalf("failed to create temp freezer db: %v", err)
}
gspec.MustCommit(ancientDb)
ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
defer ancient.Stop()
if n, err := ancient.InsertHeaderChain(headers, 1); err != nil {
@ -792,7 +792,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
archiveCaching := *defaultCacheConfig
archiveCaching.TrieDirtyDisabled = true
archive, _ := NewBlockChain(archiveDb, &archiveCaching, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
archive, _ := NewBlockChain(archiveDb, &archiveCaching, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
if n, err := archive.InsertChain(blocks); err != nil {
t.Fatalf("failed to process block %d: %v", n, err)
}
@ -805,7 +805,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
// Import the chain as a non-archive node and ensure all pointers are updated
fastDb, delfn := makeDb()
defer delfn()
fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
defer fast.Stop()
headers := make([]*types.Header, len(blocks))
@ -825,7 +825,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
// Import the chain as a ancient-first node and ensure all pointers are updated
ancientDb, delfn := makeDb()
defer delfn()
ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
defer ancient.Stop()
if n, err := ancient.InsertHeaderChain(headers, 1); err != nil {
@ -844,7 +844,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
// Import the chain as a light node and ensure all pointers are updated
lightDb, delfn := makeDb()
defer delfn()
light, _ := NewBlockChain(lightDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
light, _ := NewBlockChain(lightDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
if n, err := light.InsertHeaderChain(headers, 1); err != nil {
t.Fatalf("failed to insert header %d: %v", n, err)
}
@ -913,7 +913,7 @@ func TestChainTxReorgs(t *testing.T) {
}
})
// Import the chain. This runs all block validation rules.
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
if i, err := blockchain.InsertChain(chain); err != nil {
t.Fatalf("failed to insert original chain[%d]: %v", i, err)
}
@ -983,7 +983,7 @@ func TestLogReorgs(t *testing.T) {
signer = types.LatestSigner(gspec.Config)
)
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
defer blockchain.Stop()
rmLogsCh := make(chan RemovedLogsEvent)
@ -1036,7 +1036,7 @@ func TestLogRebirth(t *testing.T) {
genesis = gspec.MustCommit(db)
signer = types.LatestSigner(gspec.Config)
engine = ethash.NewFaker()
blockchain, _ = NewBlockChain(db, nil, gspec.Config, engine, vm.Config{}, nil, nil, false)
blockchain, _ = NewBlockChain(db, nil, gspec.Config, engine, vm.Config{}, nil, nil)
)
defer blockchain.Stop()
@ -1099,7 +1099,7 @@ func TestSideLogRebirth(t *testing.T) {
gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
genesis = gspec.MustCommit(db)
signer = types.LatestSigner(gspec.Config)
blockchain, _ = NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
blockchain, _ = NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
)
defer blockchain.Stop()
@ -1174,7 +1174,7 @@ func TestReorgSideEvent(t *testing.T) {
signer = types.LatestSigner(gspec.Config)
)
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
defer blockchain.Stop()
chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {})
@ -1306,7 +1306,7 @@ func TestEIP155Transition(t *testing.T) {
genesis = gspec.MustCommit(db)
)
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
defer blockchain.Stop()
blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, block *BlockGen) {
@ -1414,7 +1414,7 @@ func TestEIP161AccountRemoval(t *testing.T) {
}
genesis = gspec.MustCommit(db)
)
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
defer blockchain.Stop()
blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, block *BlockGen) {
@ -1489,7 +1489,7 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
diskdb := rawdb.NewMemoryDatabase()
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil, false)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@ -1533,7 +1533,7 @@ func TestTrieForkGC(t *testing.T) {
diskdb := rawdb.NewMemoryDatabase()
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil, false)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@ -1572,7 +1572,7 @@ func TestLargeReorgTrieGC(t *testing.T) {
diskdb := rawdb.NewMemoryDatabase()
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil, false)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@ -1633,7 +1633,7 @@ func TestBlockchainRecovery(t *testing.T) {
t.Fatalf("failed to create temp freezer db: %v", err)
}
gspec.MustCommit(ancientDb)
ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
headers := make([]*types.Header, len(blocks))
for i, block := range blocks {
@ -1653,7 +1653,7 @@ func TestBlockchainRecovery(t *testing.T) {
rawdb.WriteHeadFastBlockHash(ancientDb, midBlock.Hash())
// Reopen broken blockchain again
ancient, _ = NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
ancient, _ = NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
defer ancient.Stop()
if num := ancient.CurrentBlock().NumberU64(); num != 0 {
t.Errorf("head block mismatch: have #%v, want #%v", num, 0)
@ -1705,7 +1705,7 @@ func TestInsertReceiptChainRollback(t *testing.T) {
}
gspec := Genesis{Config: params.AllEthashProtocolChanges}
gspec.MustCommit(ancientDb)
ancientChain, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
ancientChain, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
defer ancientChain.Stop()
// Import the canonical header chain.
@ -1747,8 +1747,8 @@ func TestInsertReceiptChainRollback(t *testing.T) {
// overtake the 'canon' chain until after it's passed canon by about 200 blocks.
//
// Details at:
// - https://github.com/scroll-tech/go-ethereum/issues/18977
// - https://github.com/scroll-tech/go-ethereum/pull/18988
// - https://github.com/scroll-tech/go-ethereum/issues/18977
// - https://github.com/scroll-tech/go-ethereum/pull/18988
func TestLowDiffLongChain(t *testing.T) {
// Generate a canonical chain to act as the main dataset
engine := ethash.NewFaker()
@ -1766,7 +1766,7 @@ func TestLowDiffLongChain(t *testing.T) {
diskdb := rawdb.NewMemoryDatabase()
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil, false)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@ -1813,7 +1813,7 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TriesInMemory, nil)
diskdb := rawdb.NewMemoryDatabase()
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil, false)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@ -1867,7 +1867,8 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
// That is: the sidechain for import contains some blocks already present in canon chain.
// So the blocks are
// [ Cn, Cn+1, Cc, Sn+3 ... Sm]
// ^ ^ ^ pruned
//
// ^ ^ ^ pruned
func TestPrunedImportSide(t *testing.T) {
//glogger := log.NewGlogHandler(log.StreamHandler(os.Stdout, log.TerminalFormat(false)))
//glogger.Verbosity(3)
@ -1910,7 +1911,7 @@ func testInsertKnownChainData(t *testing.T, typ string) {
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(chaindb)
defer os.RemoveAll(dir)
chain, err := NewBlockChain(chaindb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil, false)
chain, err := NewBlockChain(chaindb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@ -2019,7 +2020,7 @@ func getLongAndShortChains() (bc *BlockChain, longChain []*types.Block, heavyCha
diskdb := rawdb.NewMemoryDatabase()
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil, false)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil)
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to create tester chain: %v", err)
}
@ -2212,7 +2213,7 @@ func TestTransactionIndices(t *testing.T) {
// Import all blocks into ancient db
l := uint64(0)
chain, err := NewBlockChain(ancientDb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, &l, false)
chain, err := NewBlockChain(ancientDb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, &l)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@ -2237,7 +2238,7 @@ func TestTransactionIndices(t *testing.T) {
t.Fatalf("failed to create temp freezer db: %v", err)
}
gspec.MustCommit(ancientDb)
chain, err = NewBlockChain(ancientDb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, &l, false)
chain, err = NewBlockChain(ancientDb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, &l)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@ -2261,7 +2262,7 @@ func TestTransactionIndices(t *testing.T) {
limit = []uint64{0, 64 /* drop stale */, 32 /* shorten history */, 64 /* extend history */, 0 /* restore all */}
tails := []uint64{0, 67 /* 130 - 64 + 1 */, 100 /* 131 - 32 + 1 */, 69 /* 132 - 64 + 1 */, 0}
for i, l := range limit {
chain, err = NewBlockChain(ancientDb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, &l, false)
chain, err = NewBlockChain(ancientDb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, &l)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@ -2339,7 +2340,7 @@ func TestSkipStaleTxIndicesInFastSync(t *testing.T) {
// Import all blocks into ancient db, only HEAD-32 indices are kept.
l := uint64(32)
chain, err := NewBlockChain(ancientDb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, &l, false)
chain, err := NewBlockChain(ancientDb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, &l)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@ -2403,7 +2404,7 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in
diskdb := rawdb.NewMemoryDatabase()
gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil, false)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil)
if err != nil {
b.Fatalf("failed to create tester chain: %v", err)
}
@ -2472,9 +2473,9 @@ func BenchmarkBlockChain_1x1000Executions(b *testing.B) {
// This internally leads to a sidechain import, since the blocks trigger an
// ErrPrunedAncestor error.
// This may e.g. happen if
// 1. Downloader rollbacks a batch of inserted blocks and exits
// 2. Downloader starts to sync again
// 3. The blocks fetched are all known and canonical blocks
// 1. Downloader rollbacks a batch of inserted blocks and exits
// 2. Downloader starts to sync again
// 3. The blocks fetched are all known and canonical blocks
func TestSideImportPrunedBlocks(t *testing.T) {
// Generate a canonical chain to act as the main dataset
engine := ethash.NewFaker()
@ -2485,7 +2486,7 @@ func TestSideImportPrunedBlocks(t *testing.T) {
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TriesInMemory, nil)
diskdb := rawdb.NewMemoryDatabase()
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil, false)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@ -2625,7 +2626,7 @@ func TestDeleteCreateRevert(t *testing.T) {
diskdb := rawdb.NewMemoryDatabase()
gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil, false)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@ -2636,20 +2637,19 @@ func TestDeleteCreateRevert(t *testing.T) {
// TestInitThenFailCreateContract tests a pretty notorious case that happened
// on mainnet over blocks 7338108, 7338110 and 7338115.
// - Block 7338108: address e771789f5cccac282f23bb7add5690e1f6ca467c is initiated
// with 0.001 ether (thus created but no code)
// - Block 7338110: a CREATE2 is attempted. The CREATE2 would deploy code on
// the same address e771789f5cccac282f23bb7add5690e1f6ca467c. However, the
// deployment fails due to OOG during initcode execution
// - Block 7338115: another tx checks the balance of
// e771789f5cccac282f23bb7add5690e1f6ca467c, and the snapshotter returned it as
// zero.
// - Block 7338108: address e771789f5cccac282f23bb7add5690e1f6ca467c is initiated
// with 0.001 ether (thus created but no code)
// - Block 7338110: a CREATE2 is attempted. The CREATE2 would deploy code on
// the same address e771789f5cccac282f23bb7add5690e1f6ca467c. However, the
// deployment fails due to OOG during initcode execution
// - Block 7338115: another tx checks the balance of
// e771789f5cccac282f23bb7add5690e1f6ca467c, and the snapshotter returned it as
// zero.
//
// The problem being that the snapshotter maintains a destructset, and adds items
// to the destructset in case something is created "onto" an existing item.
// We need to either roll back the snapDestructs, or not place it into snapDestructs
// in the first place.
//
func TestInitThenFailCreateContract(t *testing.T) {
var (
// Generate a canonical chain to act as the main dataset
@ -2730,7 +2730,7 @@ func TestInitThenFailCreateContract(t *testing.T) {
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{
//Debug: true,
//Tracer: vm.NewJSONLogger(nil, os.Stdout),
}, nil, nil, false)
}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@ -2817,7 +2817,7 @@ func TestEIP2718Transition(t *testing.T) {
diskdb := rawdb.NewMemoryDatabase()
gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}, nil, nil, false)
chain, err := NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@ -2838,13 +2838,13 @@ func TestEIP2718Transition(t *testing.T) {
// TestEIP1559Transition tests the following:
//
// 1. A transaction whose gasFeeCap is greater than the baseFee is valid.
// 2. Gas accounting for access lists on EIP-1559 transactions is correct.
// 3. Only the transaction's tip will be received by the coinbase.
// 4. The transaction sender pays for both the tip and baseFee.
// 5. The coinbase receives only the partially realized tip when
// gasFeeCap - gasTipCap < baseFee.
// 6. Legacy transaction behave as expected (e.g. gasPrice = gasFeeCap = gasTipCap).
// 1. A transaction whose gasFeeCap is greater than the baseFee is valid.
// 2. Gas accounting for access lists on EIP-1559 transactions is correct.
// 3. Only the transaction's tip will be received by the coinbase.
// 4. The transaction sender pays for both the tip and baseFee.
// 5. The coinbase receives only the partially realized tip when
// gasFeeCap - gasTipCap < baseFee.
// 6. Legacy transaction behave as expected (e.g. gasPrice = gasFeeCap = gasTipCap).
func TestEIP1559Transition(t *testing.T) {
var (
aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa")
@ -2912,7 +2912,7 @@ func TestEIP1559Transition(t *testing.T) {
diskdb := rawdb.NewMemoryDatabase()
gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}, nil, nil, false)
chain, err := NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@ -3036,7 +3036,7 @@ func TestPoseidonCodeHash(t *testing.T) {
genesis = gspec.MustCommit(db)
signer = types.LatestSigner(gspec.Config)
engine = ethash.NewFaker()
blockchain, _ = NewBlockChain(db, nil, gspec.Config, engine, vm.Config{}, nil, nil, false)
blockchain, _ = NewBlockChain(db, nil, gspec.Config, engine, vm.Config{}, nil, nil)
)
defer blockchain.Stop()
@ -3150,7 +3150,7 @@ func TestFeeVault(t *testing.T) {
diskdb := rawdb.NewMemoryDatabase()
gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}, nil, nil, false)
chain, err := NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@ -3202,7 +3202,7 @@ func TestTransactionCountLimit(t *testing.T) {
}
// Initialize blockchain
blockchain, err := NewBlockChain(db, nil, config, engine, vm.Config{}, nil, nil, false)
blockchain, err := NewBlockChain(db, nil, config, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create new chain manager: %v", err)
}
@ -3266,7 +3266,7 @@ func TestInsertBlocksWithL1Messages(t *testing.T) {
rawdb.WriteL1Messages(db, msgs)
// initialize blockchain
blockchain, _ := NewBlockChain(db, nil, config, engine, vm.Config{}, nil, nil, false)
blockchain, _ := NewBlockChain(db, nil, config, engine, vm.Config{}, nil, nil)
defer blockchain.Stop()
// generate blocks with 1 L1 message in each
@ -3377,7 +3377,7 @@ func TestL1MessageValidationFailure(t *testing.T) {
rawdb.WriteL1Messages(db, msgs)
// initialize blockchain
blockchain, _ := NewBlockChain(db, nil, config, engine, vm.Config{}, nil, nil, false)
blockchain, _ := NewBlockChain(db, nil, config, engine, vm.Config{}, nil, nil)
defer blockchain.Stop()
generateBlock := func(txs []*types.Transaction) ([]*types.Block, []types.Receipts) {
@ -3452,7 +3452,7 @@ func TestBlockPayloadSizeLimit(t *testing.T) {
}
// Initialize blockchain
blockchain, err := NewBlockChain(db, nil, config, engine, vm.Config{}, nil, nil, false)
blockchain, err := NewBlockChain(db, nil, config, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create new chain manager: %v", err)
}
@ -3564,7 +3564,7 @@ func TestEIP3651(t *testing.T) {
}
b.AddTx(tx)
})
chain, err := NewBlockChain(db, nil, gspec.Config, engine, vm.Config{}, nil, nil, false)
chain, err := NewBlockChain(db, nil, gspec.Config, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}

View file

@ -79,7 +79,7 @@ func ExampleGenerateChain() {
})
// Import the chain. This runs all block validation rules.
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
defer blockchain.Stop()
if i, err := blockchain.InsertChain(chain); err != nil {

View file

@ -45,7 +45,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
proConf.DAOForkBlock = forkBlock
proConf.DAOForkSupport = true
proBc, _ := NewBlockChain(proDb, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil, nil, false)
proBc, _ := NewBlockChain(proDb, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil, nil)
defer proBc.Stop()
conDb := rawdb.NewMemoryDatabase()
@ -55,7 +55,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
conConf.DAOForkBlock = forkBlock
conConf.DAOForkSupport = false
conBc, _ := NewBlockChain(conDb, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil, nil, false)
conBc, _ := NewBlockChain(conDb, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil, nil)
defer conBc.Stop()
if _, err := proBc.InsertChain(prefix); err != nil {
@ -69,7 +69,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Create a pro-fork block, and try to feed into the no-fork chain
db = rawdb.NewMemoryDatabase()
gspec.MustCommit(db)
bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil, nil, false)
bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil, nil)
defer bc.Stop()
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()))
@ -94,7 +94,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Create a no-fork block, and try to feed into the pro-fork chain
db = rawdb.NewMemoryDatabase()
gspec.MustCommit(db)
bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil, nil, false)
bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil, nil)
defer bc.Stop()
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()))
@ -120,7 +120,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Verify that contra-forkers accept pro-fork extra-datas after forking finishes
db = rawdb.NewMemoryDatabase()
gspec.MustCommit(db)
bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil, nil, false)
bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil, nil)
defer bc.Stop()
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()))
@ -140,7 +140,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Verify that pro-forkers accept contra-fork extra-datas after forking finishes
db = rawdb.NewMemoryDatabase()
gspec.MustCommit(db)
bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil, nil, false)
bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil, nil)
defer bc.Stop()
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()))

View file

@ -118,7 +118,7 @@ func TestSetupGenesis(t *testing.T) {
// Advance to block #4, past the homestead transition block of customg.
genesis := oldcustomg.MustCommit(db)
bc, _ := NewBlockChain(db, nil, oldcustomg.Config, ethash.NewFullFaker(), vm.Config{}, nil, nil, false)
bc, _ := NewBlockChain(db, nil, oldcustomg.Config, ethash.NewFullFaker(), vm.Config{}, nil, nil)
defer bc.Stop()
blocks, _ := GenerateChain(oldcustomg.Config, genesis, ethash.NewFaker(), db, 4, nil)

View file

@ -105,7 +105,7 @@ func TestStateProcessorErrors(t *testing.T) {
},
}
genesis = gspec.MustCommit(db)
blockchain, _ = NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
blockchain, _ = NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
)
defer blockchain.Stop()
bigNumber := new(big.Int).SetBytes(common.FromHex("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))
@ -246,7 +246,7 @@ func TestStateProcessorErrors(t *testing.T) {
},
}
genesis = gspec.MustCommit(db)
blockchain, _ = NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
blockchain, _ = NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
)
defer blockchain.Stop()
for i, tt := range []struct {
@ -286,7 +286,7 @@ func TestStateProcessorErrors(t *testing.T) {
},
}
genesis = gspec.MustCommit(db)
blockchain, _ = NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
blockchain, _ = NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
)
defer blockchain.Stop()
for i, tt := range []struct {
@ -341,7 +341,7 @@ func TestStateProcessorErrors(t *testing.T) {
},
}
genesis = gspec.MustCommit(db)
blockchain, _ = NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
blockchain, _ = NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
tooBigInitCode = [params.MaxInitCodeSize + 1]byte{}
smallInitCode = [320]byte{}
)

View file

@ -32,6 +32,10 @@ type Validator interface {
// ValidateState validates the given statedb and optionally the receipts and
// gas used.
ValidateState(block *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error
// SetupTracerAndCircuitCapacityChecker sets up ScrollTracerWrapper and CircuitCapacityChecker for validator,
// to get scroll-related traces and to validate the circuit row consumption
SetupTracerAndCircuitCapacityChecker(tracer tracerWrapper)
}
// Prefetcher is an interface for pre-caching transaction signatures and state.

View file

@ -67,6 +67,8 @@ type ExecutionResult struct {
// If it is a contract call, the contract code is returned.
ByteCode string `json:"byteCode,omitempty"`
StructLogs []*StructLogRes `json:"structLogs"`
CallTrace json.RawMessage `json:"callTrace"`
Prestate json.RawMessage `json:"prestate"`
}
// StructLogRes stores a structured log emitted by the EVM while replaying a

View file

@ -57,6 +57,7 @@ import (
"github.com/scroll-tech/go-ethereum/rlp"
"github.com/scroll-tech/go-ethereum/rollup/rollup_sync_service"
"github.com/scroll-tech/go-ethereum/rollup/sync_service"
"github.com/scroll-tech/go-ethereum/rollup/tracing"
"github.com/scroll-tech/go-ethereum/rpc"
)
@ -194,10 +195,15 @@ func New(stack *node.Node, config *ethconfig.Config, l1Client sync_service.EthCl
MPTWitness: config.MPTWitness,
}
)
eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, chainConfig, eth.engine, vmConfig, eth.shouldPreserve, &config.TxLookupLimit, config.CheckCircuitCapacity)
eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, chainConfig, eth.engine, vmConfig, eth.shouldPreserve, &config.TxLookupLimit)
if err != nil {
return nil, err
}
if config.CheckCircuitCapacity {
tracer := tracing.NewTracerWrapper()
eth.blockchain.Validator().SetupTracerAndCircuitCapacityChecker(tracer)
}
// Rewind the chain in case of an incompatible config upgrade.
if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
log.Warn("Rewinding chain to upgrade configuration", "err", compat)

View file

@ -370,7 +370,7 @@ func TestGetLogsRange(t *testing.T) {
(&core.Genesis{
Config: params.TestChainConfig,
}).MustCommit(db)
chain, _ := core.NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil, false)
chain, _ := core.NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil)
bs, _ := core.GenerateChain(params.TestChainConfig, chain.Genesis(), ethash.NewFaker(), db, 10, nil)
if _, err := chain.InsertChain(bs); err != nil {
panic(err)

View file

@ -144,7 +144,7 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBacke
// Construct testing chain
diskdb := rawdb.NewMemoryDatabase()
gspec.Commit(diskdb)
chain, err := core.NewBlockChain(diskdb, &core.CacheConfig{TrieCleanNoPrefetch: true}, &config, engine, vm.Config{}, nil, nil, false)
chain, err := core.NewBlockChain(diskdb, &core.CacheConfig{TrieCleanNoPrefetch: true}, &config, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("Failed to create local chain, %v", err)
}

View file

@ -105,8 +105,8 @@ func testForkIDSplit(t *testing.T, protocol uint) {
genesisNoFork = gspecNoFork.MustCommit(dbNoFork)
genesisProFork = gspecProFork.MustCommit(dbProFork)
chainNoFork, _ = core.NewBlockChain(dbNoFork, nil, configNoFork, engine, vm.Config{}, nil, nil, false)
chainProFork, _ = core.NewBlockChain(dbProFork, nil, configProFork, engine, vm.Config{}, nil, nil, false)
chainNoFork, _ = core.NewBlockChain(dbNoFork, nil, configNoFork, engine, vm.Config{}, nil, nil)
chainProFork, _ = core.NewBlockChain(dbProFork, nil, configProFork, engine, vm.Config{}, nil, nil)
blocksNoFork, _ = core.GenerateChain(configNoFork, genesisNoFork, engine, dbNoFork, 2, nil)
blocksProFork, _ = core.GenerateChain(configProFork, genesisProFork, engine, dbProFork, 2, nil)

View file

@ -137,7 +137,7 @@ func newTestHandlerWithBlocks(blocks int) *testHandler {
Alloc: core.GenesisAlloc{testAddr: {Balance: big.NewInt(1000000)}},
}).MustCommit(db)
chain, _ := core.NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil, false)
chain, _ := core.NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil)
bs, _ := core.GenerateChain(params.TestChainConfig, chain.Genesis(), ethash.NewFaker(), db, blocks, nil)
if _, err := chain.InsertChain(bs); err != nil {

View file

@ -69,7 +69,7 @@ func newTestBackendWithGenerator(blocks int, generator func(int, *core.BlockGen)
Alloc: core.GenesisAlloc{testAddr: {Balance: big.NewInt(100_000_000_000_000_000)}},
}).MustCommit(db)
chain, _ := core.NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil, false)
chain, _ := core.NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil)
bs, _ := core.GenerateChain(params.TestChainConfig, chain.Genesis(), ethash.NewFaker(), db, blocks, generator)
if _, err := chain.InsertChain(bs); err != nil {

View file

@ -86,12 +86,13 @@ type Backend interface {
// API is the collection of tracing APIs exposed over the private debugging endpoint.
type API struct {
backend Backend
backend Backend
scrollTracerWrapper scrollTracerWrapper
}
// NewAPI creates a new API definition for the tracing methods of the Ethereum service.
func NewAPI(backend Backend) *API {
return &API{backend: backend}
func NewAPI(backend Backend, scrollTracerWrapper scrollTracerWrapper) *API {
return &API{backend: backend, scrollTracerWrapper: scrollTracerWrapper}
}
type chainContext struct {
@ -979,19 +980,19 @@ func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Contex
}
// APIs return the collection of RPC services the tracer package offers.
func APIs(backend Backend) []rpc.API {
func APIs(backend Backend, scrollTracerWrapper scrollTracerWrapper) []rpc.API {
// Append all the local APIs and return
return []rpc.API{
{
Namespace: "debug",
Version: "1.0",
Service: NewAPI(backend),
Service: NewAPI(backend, scrollTracerWrapper),
Public: false,
},
{
Namespace: "scroll",
Version: "1.0",
Service: TraceBlock(NewAPI(backend)),
Service: TraceBlock(NewAPI(backend, scrollTracerWrapper)),
Public: true,
},
}

View file

@ -4,20 +4,34 @@ import (
"context"
"errors"
"github.com/scroll-tech/go-ethereum/consensus"
"github.com/scroll-tech/go-ethereum/core"
"github.com/scroll-tech/go-ethereum/core/state"
"github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/core/vm"
"github.com/scroll-tech/go-ethereum/ethdb"
"github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/params"
"github.com/scroll-tech/go-ethereum/rpc"
)
var errNoScrollTracerWrapper = errors.New("no ScrollTracerWrapper")
type TraceBlock interface {
GetBlockTraceByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, config *TraceConfig) (trace *types.BlockTrace, err error)
GetTxBlockTraceOnTopOfBlock(ctx context.Context, tx *types.Transaction, blockNrOrHash rpc.BlockNumberOrHash, config *TraceConfig) (*types.BlockTrace, error)
}
type scrollTracerWrapper interface {
CreateTraceEnvAndGetBlockTrace(*params.ChainConfig, core.ChainContext, consensus.Engine, ethdb.Database, *state.StateDB, *types.Block, *types.Block, bool) (*types.BlockTrace, error)
}
// GetBlockTraceByNumberOrHash replays the block and returns the structured BlockTrace by hash or number.
func (api *API) GetBlockTraceByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, config *TraceConfig) (trace *types.BlockTrace, err error) {
if api.scrollTracerWrapper == nil {
return nil, errNoScrollTracerWrapper
}
var block *types.Block
if number, ok := blockNrOrHash.Number(); ok {
block, err = api.blockByNumber(ctx, number)
@ -33,15 +47,14 @@ func (api *API) GetBlockTraceByNumberOrHash(ctx context.Context, blockNrOrHash r
return nil, errors.New("genesis is not traceable")
}
env, err := api.createTraceEnv(ctx, config, block)
if err != nil {
return nil, err
}
return env.GetBlockTrace(block)
return api.createTraceEnvAndGetBlockTrace(ctx, config, block)
}
func (api *API) GetTxBlockTraceOnTopOfBlock(ctx context.Context, tx *types.Transaction, blockNrOrHash rpc.BlockNumberOrHash, config *TraceConfig) (*types.BlockTrace, error) {
if api.scrollTracerWrapper == nil {
return nil, errNoScrollTracerWrapper
}
// Try to retrieve the specified block
var (
err error
@ -63,17 +76,11 @@ func (api *API) GetTxBlockTraceOnTopOfBlock(ctx context.Context, tx *types.Trans
block = types.NewBlockWithHeader(block.Header()).WithBody([]*types.Transaction{tx}, nil)
// create current execution environment.
env, err := api.createTraceEnv(ctx, config, block)
if err != nil {
return nil, err
}
return env.GetBlockTrace(block)
return api.createTraceEnvAndGetBlockTrace(ctx, config, block)
}
// Make trace environment for current block.
func (api *API) createTraceEnv(ctx context.Context, config *TraceConfig, block *types.Block) (*core.TraceEnv, error) {
// Make trace environment for current block, and then get the trace for the block.
func (api *API) createTraceEnvAndGetBlockTrace(ctx context.Context, config *TraceConfig, block *types.Block) (*types.BlockTrace, error) {
if config == nil {
config = &TraceConfig{
LogConfig: &vm.LogConfig{
@ -100,5 +107,5 @@ func (api *API) createTraceEnv(ctx context.Context, config *TraceConfig, block *
}
chaindb := api.backend.ChainDb()
return core.CreateTraceEnv(api.backend.ChainConfig(), api.chainContext(ctx), api.backend.Engine(), chaindb, statedb, parent, block, true)
return api.scrollTracerWrapper.CreateTraceEnvAndGetBlockTrace(api.backend.ChainConfig(), api.chainContext(ctx), api.backend.Engine(), chaindb, statedb, parent, block, true)
}

File diff suppressed because one or more lines are too long

View file

@ -82,7 +82,7 @@ func newTestBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i i
SnapshotLimit: 0,
TrieDirtyDisabled: true, // Archive mode
}
chain, err := core.NewBlockChain(backend.chaindb, cacheConfig, backend.chainConfig, backend.engine, vm.Config{}, nil, nil, false)
chain, err := core.NewBlockChain(backend.chaindb, cacheConfig, backend.chainConfig, backend.engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@ -203,7 +203,7 @@ func TestTraceCall(t *testing.T) {
// fee: 0 wei
tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key)
b.AddTx(tx)
}))
}), nil)
var testSuite = []struct {
blockNumber rpc.BlockNumber
@ -337,7 +337,7 @@ func TestTraceTransaction(t *testing.T) {
tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key)
b.AddTx(tx)
target = tx.Hash()
}))
}), nil)
result, err := api.TraceTransaction(context.Background(), target, nil)
if err != nil {
t.Errorf("Failed to trace transaction %v", err)
@ -371,7 +371,7 @@ func TestTraceBlock(t *testing.T) {
// fee: 0 wei
tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key)
b.AddTx(tx)
}))
}), nil)
var testSuite = []struct {
blockNumber rpc.BlockNumber
@ -446,7 +446,7 @@ func TestTracingWithOverrides(t *testing.T) {
// fee: 0 wei
tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key)
b.AddTx(tx)
}))
}), nil)
randomAccounts := newAccounts(3)
type res struct {
Gas int

View file

@ -0,0 +1,261 @@
package native
import (
"bytes"
"encoding/json"
"math/big"
"sync/atomic"
"time"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/core/vm"
"github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/eth/tracers"
"github.com/scroll-tech/go-ethereum/log"
)
func init() {
register("prestateTracer", newPrestateTracer)
}
type state = map[common.Address]*account
type account struct {
Balance *big.Int
Code []byte
Nonce uint64
Storage map[common.Hash]common.Hash
}
func (a *account) marshal() accountMarshaling {
return accountMarshaling{
Balance: bigToHex(a.Balance),
Code: bytesToHex(a.Code),
Nonce: a.Nonce,
Storage: a.Storage,
}
}
func (a *account) exists() bool {
return a.Nonce > 0 || len(a.Code) > 0 || len(a.Storage) > 0 || (a.Balance != nil && a.Balance.Sign() != 0)
}
type accountMarshaling struct {
Balance string `json:"balance,omitempty"`
Code string `json:"code,omitempty"`
Nonce uint64 `json:"nonce,omitempty"`
Storage map[common.Hash]common.Hash `json:"storage,omitempty"`
}
type prestateTracer struct {
noopTracer
env *vm.EVM
pre state
post state
create bool
to common.Address
gasLimit uint64 // Amount of gas bought for the whole tx
interrupt atomic.Bool // Atomic flag to signal execution interruption
reason error // Textual reason for the interruption
created map[common.Address]bool
deleted map[common.Address]bool
}
func newPrestateTracer() tracers.Tracer {
return &prestateTracer{
pre: state{},
post: state{},
created: make(map[common.Address]bool),
deleted: make(map[common.Address]bool),
}
}
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
func (t *prestateTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
t.env = env
t.create = create
t.to = to
t.lookupAccount(from)
t.lookupAccount(to)
t.lookupAccount(env.Context.Coinbase)
// The recipient balance includes the value transferred.
toBal := new(big.Int).Sub(t.pre[to].Balance, value)
t.pre[to].Balance = toBal
// The sender balance is after reducing: value and gasLimit.
// We need to re-add them to get the pre-tx balance.
fromBal := new(big.Int).Set(t.pre[from].Balance)
gasPrice := env.TxContext.GasPrice
consumedGas := new(big.Int).Mul(gasPrice, new(big.Int).SetUint64(t.gasLimit))
fromBal.Add(fromBal, new(big.Int).Add(value, consumedGas))
t.pre[from].Balance = fromBal
t.pre[from].Nonce--
}
// CaptureEnd is called after the call finishes to finalize the tracing.
func (t *prestateTracer) CaptureEnd(output []byte, gasUsed uint64, d time.Duration, err error) {
if t.create {
// Keep existing account prior to contract creation at that address
if s := t.pre[t.to]; s != nil && !s.exists() {
// Exclude newly created contract.
delete(t.pre, t.to)
}
}
}
// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
func (t *prestateTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
if err != nil {
return
}
// Skip if tracing was interrupted
if t.interrupt.Load() {
return
}
stack := scope.Stack
stackData := stack.Data()
stackLen := len(stackData)
caller := scope.Contract.Address()
switch {
case stackLen >= 1 && (op == vm.SLOAD || op == vm.SSTORE):
slot := common.Hash(stackData[stackLen-1].Bytes32())
t.lookupStorage(caller, slot)
case stackLen >= 1 && (op == vm.EXTCODECOPY || op == vm.EXTCODEHASH || op == vm.EXTCODESIZE || op == vm.BALANCE || op == vm.SELFDESTRUCT):
addr := common.Address(stackData[stackLen-1].Bytes20())
t.lookupAccount(addr)
if op == vm.SELFDESTRUCT {
t.deleted[caller] = true
}
case stackLen >= 5 && (op == vm.DELEGATECALL || op == vm.CALL || op == vm.STATICCALL || op == vm.CALLCODE):
addr := common.Address(stackData[stackLen-2].Bytes20())
t.lookupAccount(addr)
case op == vm.CREATE:
nonce := t.env.StateDB.GetNonce(caller)
addr := crypto.CreateAddress(caller, nonce)
t.lookupAccount(addr)
t.created[addr] = true
case stackLen >= 4 && op == vm.CREATE2:
offset := stackData[stackLen-2]
size := stackData[stackLen-3]
init, err := tracers.GetMemoryCopyPadded(scope.Memory, int64(offset.Uint64()), int64(size.Uint64()))
if err != nil {
log.Warn("failed to copy CREATE2 input", "err", err, "tracer", "prestateTracer", "offset", offset, "size", size)
return
}
inithash := crypto.Keccak256(init)
salt := stackData[stackLen-4]
addr := crypto.CreateAddress2(caller, salt.Bytes32(), inithash)
t.lookupAccount(addr)
t.created[addr] = true
}
}
func (t *prestateTracer) CaptureTxStart(gasLimit uint64) {
t.gasLimit = gasLimit
}
func (t *prestateTracer) CaptureTxEnd(restGas uint64) {
for addr, state := range t.pre {
// The deleted account's state is pruned from `post` but kept in `pre`
if _, ok := t.deleted[addr]; ok {
continue
}
modified := false
postAccount := &account{Storage: make(map[common.Hash]common.Hash)}
newBalance := t.env.StateDB.GetBalance(addr)
newNonce := t.env.StateDB.GetNonce(addr)
newCode := t.env.StateDB.GetCode(addr)
if newBalance.Cmp(t.pre[addr].Balance) != 0 {
modified = true
postAccount.Balance = newBalance
}
if newNonce != t.pre[addr].Nonce {
modified = true
postAccount.Nonce = newNonce
}
if !bytes.Equal(newCode, t.pre[addr].Code) {
modified = true
postAccount.Code = newCode
}
for key, val := range state.Storage {
// don't include the empty slot
if val == (common.Hash{}) {
delete(t.pre[addr].Storage, key)
}
newVal := t.env.StateDB.GetState(addr, key)
if val == newVal {
// Omit unchanged slots
delete(t.pre[addr].Storage, key)
} else {
modified = true
if newVal != (common.Hash{}) {
postAccount.Storage[key] = newVal
}
}
}
if modified {
t.post[addr] = postAccount
} else {
// if state is not modified, then no need to include into the pre state
delete(t.pre, addr)
}
}
// the new created contracts' prestate were empty, so delete them
for a := range t.created {
// the created contract maybe exists in statedb before the creating tx
if s := t.pre[a]; s != nil && !s.exists() {
delete(t.pre, a)
}
}
}
// GetResult returns the json-encoded nested list of call traces, and any
// error arising from the encoding or forceful termination (via `Stop`).
func (t *prestateTracer) GetResult() (json.RawMessage, error) {
pre := make(map[string]accountMarshaling)
for addr, state := range t.pre {
pre[addrToHex(addr)] = state.marshal()
}
res, err := json.Marshal(pre)
if err != nil {
return nil, err
}
return res, t.reason
}
// Stop terminates execution of the tracer at the first opportune moment.
func (t *prestateTracer) Stop(err error) {
t.reason = err
t.interrupt.Store(true)
}
// lookupAccount fetches details of an account and adds it to the prestate
// if it doesn't exist there.
func (t *prestateTracer) lookupAccount(addr common.Address) {
if _, ok := t.pre[addr]; ok {
return
}
t.pre[addr] = &account{
Balance: t.env.StateDB.GetBalance(addr),
Nonce: t.env.StateDB.GetNonce(addr),
Code: t.env.StateDB.GetCode(addr),
Storage: make(map[common.Hash]common.Hash),
}
}
// lookupStorage fetches the requested storage slot and adds
// it to the prestate of the given contract. It assumes `lookupAccount`
// has been performed on the contract before.
func (t *prestateTracer) lookupStorage(addr common.Address, key common.Hash) {
if _, ok := t.pre[addr].Storage[key]; ok {
return
}
t.pre[addr].Storage[key] = t.env.StateDB.GetState(addr, key)
}

View file

@ -20,6 +20,7 @@ package tracers
import (
"encoding/json"
"errors"
"fmt"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/core/vm"
@ -70,3 +71,27 @@ func New(code string, ctx *Context) (Tracer, error) {
}
return nil, errors.New("tracer not found")
}
const (
memoryPadLimit = 1024 * 1024
)
// GetMemoryCopyPadded returns offset + size as a new slice.
// It zero-pads the slice if it extends beyond memory bounds.
func GetMemoryCopyPadded(m *vm.Memory, offset, size int64) ([]byte, error) {
if offset < 0 || size < 0 {
return nil, errors.New("offset or size must not be negative")
}
if int(offset+size) < m.Len() { // slice fully inside memory
return m.GetCopy(offset, size), nil
}
paddingNeeded := int(offset+size) - m.Len()
if paddingNeeded > memoryPadLimit {
return nil, fmt.Errorf("reached limit for padding memory slice: %d", paddingNeeded)
}
cpy := make([]byte, size)
if overlap := int64(m.Len()) - offset; overlap > 0 {
copy(cpy, m.GetPtr(offset, overlap))
}
return cpy, nil
}

2
go.mod
View file

@ -1,6 +1,6 @@
module github.com/scroll-tech/go-ethereum
go 1.18
go 1.20
require (
github.com/Azure/azure-storage-blob-go v0.7.0

View file

@ -264,7 +264,7 @@ func testChainOdr(t *testing.T, protocol int, fn odrTestFn) {
)
gspec.MustCommit(ldb)
// Assemble the test environment
blockchain, _ := core.NewBlockChain(sdb, nil, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{}, nil, nil, false)
blockchain, _ := core.NewBlockChain(sdb, nil, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{}, nil, nil)
gchain, _ := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), sdb, 4, testChainGen)
if _, err := blockchain.InsertChain(gchain); err != nil {
t.Fatal(err)

View file

@ -45,7 +45,7 @@ func TestNodeIterator(t *testing.T) {
genesis = gspec.MustCommit(fulldb)
)
gspec.MustCommit(lightdb)
blockchain, _ := core.NewBlockChain(fulldb, nil, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{}, nil, nil, false)
blockchain, _ := core.NewBlockChain(fulldb, nil, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{}, nil, nil)
gchain, _ := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), fulldb, 4, testChainGen)
if _, err := blockchain.InsertChain(gchain); err != nil {
panic(err)

View file

@ -91,7 +91,7 @@ func TestTxPool(t *testing.T) {
)
gspec.MustCommit(ldb)
// Assemble the test environment
blockchain, _ := core.NewBlockChain(sdb, nil, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{}, nil, nil, false)
blockchain, _ := core.NewBlockChain(sdb, nil, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{}, nil, nil)
gchain, _ := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), sdb, poolTestBlocks, txPoolTestChainGen)
if _, err := blockchain.InsertChain(gchain); err != nil {
panic(err)

View file

@ -257,7 +257,7 @@ func createMiner(t *testing.T) (*Miner, *event.TypeMux) {
// Create consensus engine
engine := clique.New(chainConfig.Clique, chainDB)
// Create Ethereum backend
bc, err := core.NewBlockChain(chainDB, nil, chainConfig, engine, vm.Config{}, nil, nil, false)
bc, err := core.NewBlockChain(chainDB, nil, chainConfig, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("can't create new chain %v", err)
}

View file

@ -39,6 +39,7 @@ import (
"github.com/scroll-tech/go-ethereum/metrics"
"github.com/scroll-tech/go-ethereum/params"
"github.com/scroll-tech/go-ethereum/rollup/circuitcapacitychecker"
"github.com/scroll-tech/go-ethereum/rollup/tracing"
"github.com/scroll-tech/go-ethereum/trie"
)
@ -121,7 +122,7 @@ type environment struct {
receipts []*types.Receipt
// circuit capacity check related fields
traceEnv *core.TraceEnv // env for tracing
traceEnv *tracing.TraceEnv // env for tracing
accRows *types.RowConsumption // accumulated row consumption for a block
nextL1MsgIndex uint64 // next L1 queue index to be processed
}
@ -808,7 +809,7 @@ func (w *worker) makeCurrent(parent *types.Block, header *types.Header) error {
// don't commit the state during tracing for circuit capacity checker, otherwise we cannot revert.
// and even if we don't commit the state, the `refund` value will still be correct, as explained in `CommitTransaction`
commitStateAfterApply := false
traceEnv, err := core.CreateTraceEnv(w.chainConfig, w.chain, w.engine, w.eth.ChainDb(), state, parent,
traceEnv, err := tracing.CreateTraceEnv(w.chainConfig, w.chain, w.engine, w.eth.ChainDb(), state, parent,
// new block with a placeholder tx, for traceEnv's ExecutionResults length & TxStorageTraces length
types.NewBlockWithHeader(header).WithBody([]*types.Transaction{types.NewTx(&types.LegacyTx{})}, nil),
commitStateAfterApply)

View file

@ -141,7 +141,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine
chain, _ := core.NewBlockChain(db, &core.CacheConfig{TrieDirtyDisabled: true}, gspec.Config, engine, vm.Config{
Debug: true,
Tracer: vm.NewStructLogger(&vm.LogConfig{EnableMemory: true})}, nil, nil, false)
Tracer: vm.NewStructLogger(&vm.LogConfig{EnableMemory: true})}, nil, nil)
txpool := core.NewTxPool(testTxPoolConfig, chainConfig, chain)
// Generate a small n-block chain and an uncle block for it
@ -242,7 +242,7 @@ func testGenerateBlockAndImport(t *testing.T, isClique bool) {
b.genesis.MustCommit(db2)
chain, _ := core.NewBlockChain(db2, nil, b.chain.Config(), engine, vm.Config{
Debug: true,
Tracer: vm.NewStructLogger(&vm.LogConfig{EnableMemory: true, EnableReturnData: true})}, nil, nil, false)
Tracer: vm.NewStructLogger(&vm.LogConfig{EnableMemory: true, EnableReturnData: true})}, nil, nil)
defer chain.Stop()
// Ignore empty commit here for less noise.
@ -572,7 +572,7 @@ func testGenerateBlockWithL1Msg(t *testing.T, isClique bool) {
b.genesis.MustCommit(db)
chain, _ := core.NewBlockChain(db, nil, b.chain.Config(), engine, vm.Config{
Debug: true,
Tracer: vm.NewStructLogger(&vm.LogConfig{EnableMemory: true, EnableReturnData: true})}, nil, nil, false)
Tracer: vm.NewStructLogger(&vm.LogConfig{EnableMemory: true, EnableReturnData: true})}, nil, nil)
defer chain.Stop()
// Ignore empty commit here for less noise.
@ -639,7 +639,7 @@ func TestAcceptableTxlimit(t *testing.T) {
b.genesis.MustCommit(db)
chain, _ := core.NewBlockChain(db, nil, b.chain.Config(), engine, vm.Config{
Debug: true,
Tracer: vm.NewStructLogger(&vm.LogConfig{EnableMemory: true, EnableReturnData: true})}, nil, nil, false)
Tracer: vm.NewStructLogger(&vm.LogConfig{EnableMemory: true, EnableReturnData: true})}, nil, nil)
defer chain.Stop()
// Ignore empty commit here for less noise.
@ -702,7 +702,7 @@ func TestUnacceptableTxlimit(t *testing.T) {
b.genesis.MustCommit(db)
chain, _ := core.NewBlockChain(db, nil, b.chain.Config(), engine, vm.Config{
Debug: true,
Tracer: vm.NewStructLogger(&vm.LogConfig{EnableMemory: true, EnableReturnData: true})}, nil, nil, false)
Tracer: vm.NewStructLogger(&vm.LogConfig{EnableMemory: true, EnableReturnData: true})}, nil, nil)
defer chain.Stop()
// Ignore empty commit here for less noise.
@ -765,7 +765,7 @@ func TestL1MsgCorrectOrder(t *testing.T) {
b.genesis.MustCommit(db)
chain, _ := core.NewBlockChain(db, nil, b.chain.Config(), engine, vm.Config{
Debug: true,
Tracer: vm.NewStructLogger(&vm.LogConfig{EnableMemory: true, EnableReturnData: true})}, nil, nil, false)
Tracer: vm.NewStructLogger(&vm.LogConfig{EnableMemory: true, EnableReturnData: true})}, nil, nil)
defer chain.Stop()
// Ignore empty commit here for less noise.
@ -827,7 +827,7 @@ func l1MessageTest(t *testing.T, msgs []types.L1MessageTx, withL2Tx bool, callba
b.genesis.MustCommit(db)
chain, _ := core.NewBlockChain(db, nil, b.chain.Config(), engine, vm.Config{
Debug: true,
Tracer: vm.NewStructLogger(&vm.LogConfig{EnableMemory: true, EnableReturnData: true})}, nil, nil, false)
Tracer: vm.NewStructLogger(&vm.LogConfig{EnableMemory: true, EnableReturnData: true})}, nil, nil)
defer chain.Stop()
// Ignore empty commit here for less noise.
@ -1135,7 +1135,7 @@ func TestPrioritizeOverflowTx(t *testing.T) {
b.genesis.MustCommit(db2)
chain, _ := core.NewBlockChain(db2, nil, b.chain.Config(), engine, vm.Config{
Debug: true,
Tracer: vm.NewStructLogger(&vm.LogConfig{EnableMemory: true, EnableReturnData: true})}, nil, nil, false)
Tracer: vm.NewStructLogger(&vm.LogConfig{EnableMemory: true, EnableReturnData: true})}, nil, nil)
defer chain.Stop()
// Ignore empty commit here for less noise.

View file

@ -24,7 +24,7 @@ import (
const (
VersionMajor = 5 // Major version component of the current release
VersionMinor = 1 // Minor version component of the current release
VersionPatch = 12 // Patch version component of the current release
VersionPatch = 13 // Patch version component of the current release
VersionMeta = "mainnet" // Version metadata to append to the version string
)

View file

@ -0,0 +1,69 @@
package tracing
import (
"math/big"
"time"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/core/vm"
_ "github.com/scroll-tech/go-ethereum/eth/tracers/native"
)
// MuxTracer is a tracer mux, to support running multiple tracers together
type MuxTracer struct {
tracers []vm.EVMLogger
}
// NewMuxTracer creates a new MuxTracer with multiple tracers
func NewMuxTracer(tracers ...vm.EVMLogger) *MuxTracer {
return &MuxTracer{tracers}
}
// CaptureStart runs CaptureStart for each tracer in the MuxTracer
func (t *MuxTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
for _, tracer := range t.tracers {
tracer.CaptureStart(env, from, to, create, input, gas, value)
}
}
// CaptureState runs CaptureState for each tracer in the MuxTracer
func (t *MuxTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
for _, tracer := range t.tracers {
tracer.CaptureState(pc, op, gas, cost, scope, rData, depth, err)
}
}
// CaptureStateAfter runs CaptureStateAfter for each tracer in the MuxTracer
func (t *MuxTracer) CaptureStateAfter(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
for _, tracer := range t.tracers {
tracer.CaptureStateAfter(pc, op, gas, cost, scope, rData, depth, err)
}
}
// CaptureEnter runs CaptureEnter for each tracer in the MuxTracer
func (t *MuxTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
for _, tracer := range t.tracers {
tracer.CaptureEnter(typ, from, to, input, gas, value)
}
}
// CaptureExit runs CaptureExit for each tracer in the MuxTracer
func (t *MuxTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
for _, tracer := range t.tracers {
tracer.CaptureExit(output, gasUsed, err)
}
}
// CaptureFault runs CaptureFault for each tracer in the MuxTracer
func (t *MuxTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
for _, tracer := range t.tracers {
tracer.CaptureFault(pc, op, gas, cost, scope, depth, err)
}
}
// CaptureEnd runs CaptureEnd for each tracer in the MuxTracer
func (t *MuxTracer) CaptureEnd(output []byte, gasUsed uint64, d time.Duration, err error) {
for _, tracer := range t.tracers {
tracer.CaptureEnd(output, gasUsed, d, err)
}
}

View file

@ -1,4 +1,4 @@
package core
package tracing
import (
"bytes"
@ -10,10 +10,13 @@ import (
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/common/hexutil"
"github.com/scroll-tech/go-ethereum/consensus"
"github.com/scroll-tech/go-ethereum/core"
"github.com/scroll-tech/go-ethereum/core/rawdb"
"github.com/scroll-tech/go-ethereum/core/state"
"github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/core/vm"
"github.com/scroll-tech/go-ethereum/eth/tracers"
_ "github.com/scroll-tech/go-ethereum/eth/tracers/native"
"github.com/scroll-tech/go-ethereum/ethdb"
"github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/params"
@ -23,6 +26,24 @@ import (
"github.com/scroll-tech/go-ethereum/trie/zkproof"
)
// TracerWrapper implements ScrollTracerWrapper interface
type TracerWrapper struct{}
// TracerWrapper creates a new TracerWrapper
func NewTracerWrapper() *TracerWrapper {
return &TracerWrapper{}
}
// CreateTraceEnvAndGetBlockTrace wraps the whole block tracing logic for a block
func (tw *TracerWrapper) CreateTraceEnvAndGetBlockTrace(chainConfig *params.ChainConfig, chainContext core.ChainContext, engine consensus.Engine, chaindb ethdb.Database, statedb *state.StateDB, parent *types.Block, block *types.Block, commitAfterApply bool) (*types.BlockTrace, error) {
traceEnv, err := CreateTraceEnv(chainConfig, chainContext, engine, chaindb, statedb, parent, block, commitAfterApply)
if err != nil {
return nil, err
}
return traceEnv.GetBlockTrace(block)
}
type TraceEnv struct {
logConfig *vm.LogConfig
commitAfterApply bool
@ -88,8 +109,9 @@ func CreateTraceEnvHelper(chainConfig *params.ChainConfig, logConfig *vm.LogConf
}
}
func CreateTraceEnv(chainConfig *params.ChainConfig, chainContext ChainContext, engine consensus.Engine, chaindb ethdb.Database, statedb *state.StateDB, parent *types.Block, block *types.Block, commitAfterApply bool) (*TraceEnv, error) {
func CreateTraceEnv(chainConfig *params.ChainConfig, chainContext core.ChainContext, engine consensus.Engine, chaindb ethdb.Database, statedb *state.StateDB, parent *types.Block, block *types.Block, commitAfterApply bool) (*TraceEnv, error) {
var coinbase common.Address
var err error
if chainConfig.Scroll.FeeVaultEnabled() {
coinbase = *chainConfig.Scroll.FeeVaultAddress
@ -119,11 +141,10 @@ func CreateTraceEnv(chainConfig *params.ChainConfig, chainContext ChainContext,
env := CreateTraceEnvHelper(
chainConfig,
&vm.LogConfig{
DisableStorage: true,
EnableMemory: false,
EnableReturnData: true,
},
NewEVMBlockContext(block.Header(), chainContext, chainConfig, nil),
core.NewEVMBlockContext(block.Header(), chainContext, chainConfig, nil),
*startL1QueueIndex,
coinbase,
statedb,
@ -189,13 +210,13 @@ func (env *TraceEnv) GetBlockTrace(block *types.Block) (*types.BlockTrace, error
// Generate the next state snapshot fast without tracing
msg, _ := tx.AsMessage(env.signer, block.BaseFee())
env.state.Prepare(tx.Hash(), i)
vmenv := vm.NewEVM(env.blockCtx, NewEVMTxContext(msg), env.state, env.chainConfig, vm.Config{})
vmenv := vm.NewEVM(env.blockCtx, core.NewEVMTxContext(msg), env.state, env.chainConfig, vm.Config{})
l1DataFee, err := fees.CalculateL1DataFee(tx, env.state)
if err != nil {
failed = err
break
}
if _, err = ApplyMessage(vmenv, msg, new(GasPool).AddGas(msg.Gas()), l1DataFee); err != nil {
if _, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()), l1DataFee); err != nil {
failed = err
break
}
@ -270,9 +291,24 @@ func (env *TraceEnv) getTxResult(state *state.StateDB, index int, block *types.B
}
}
tracer := vm.NewStructLogger(env.logConfig)
txContext := core.NewEVMTxContext(msg)
tracerContext := tracers.Context{
BlockHash: block.Hash(),
TxIndex: index,
TxHash: tx.Hash(),
}
callTracer, err := tracers.New("callTracer", &tracerContext)
if err != nil {
return fmt.Errorf("failed to create callTracer: %w", err)
}
prestateTracer, err := tracers.New("prestateTracer", &tracerContext)
if err != nil {
return fmt.Errorf("failed to create prestateTracer: %w", err)
}
structLogger := vm.NewStructLogger(env.logConfig)
tracer := NewMuxTracer(structLogger, callTracer, prestateTracer)
// Run the transaction with tracing enabled.
vmenv := vm.NewEVM(env.blockCtx, NewEVMTxContext(msg), state, env.chainConfig, vm.Config{Debug: true, Tracer: tracer, NoBaseFee: true})
vmenv := vm.NewEVM(env.blockCtx, txContext, state, env.chainConfig, vm.Config{Debug: true, Tracer: tracer, NoBaseFee: true})
// Call Prepare to clear out the statedb access list
state.Prepare(txctx.TxHash, txctx.TxIndex)
@ -282,7 +318,7 @@ func (env *TraceEnv) getTxResult(state *state.StateDB, index int, block *types.B
if err != nil {
return err
}
result, err := ApplyMessage(vmenv, msg, new(GasPool).AddGas(msg.Gas()), l1DataFee)
result, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()), l1DataFee)
if err != nil {
return err
}
@ -292,7 +328,7 @@ func (env *TraceEnv) getTxResult(state *state.StateDB, index int, block *types.B
returnVal = result.Revert()
}
createdAcc := tracer.CreatedAccount()
createdAcc := structLogger.CreatedAccount()
var after []*types.AccountWrapper
if to == nil {
if createdAcc == nil {
@ -325,7 +361,7 @@ func (env *TraceEnv) getTxResult(state *state.StateDB, index int, block *types.B
}
// merge required proof data
proofAccounts := tracer.UpdatedAccounts()
proofAccounts := structLogger.UpdatedAccounts()
proofAccounts[vmenv.FeeRecipient()] = struct{}{}
for addr := range proofAccounts {
addrStr := addr.String()
@ -351,7 +387,7 @@ func (env *TraceEnv) getTxResult(state *state.StateDB, index int, block *types.B
env.pMu.Unlock()
}
proofStorages := tracer.UpdatedStorages()
proofStorages := structLogger.UpdatedStorages()
for addr, keys := range proofStorages {
if _, existed := txStorageTrace.StorageProofs[addr.String()]; !existed {
txStorageTrace.StorageProofs[addr.String()] = make(map[string][]hexutil.Bytes)
@ -420,6 +456,15 @@ func (env *TraceEnv) getTxResult(state *state.StateDB, index int, block *types.B
}
}
callTrace, err := callTracer.GetResult()
if err != nil {
return fmt.Errorf("failed to get callTracer result: %w", err)
}
prestate, err := prestateTracer.GetResult()
if err != nil {
return fmt.Errorf("failed to get prestateTracer result: %w", err)
}
env.ExecutionResults[index] = &types.ExecutionResult{
From: sender,
To: receiver,
@ -429,7 +474,9 @@ func (env *TraceEnv) getTxResult(state *state.StateDB, index int, block *types.B
Gas: result.UsedGas,
Failed: result.Failed(),
ReturnValue: fmt.Sprintf("%x", returnVal),
StructLogs: vm.FormatLogs(tracer.StructLogs()),
StructLogs: vm.FormatLogs(structLogger.StructLogs()),
CallTrace: callTrace,
Prestate: prestate,
}
env.TxStorageTraces[index] = txStorageTrace

View file

@ -127,7 +127,7 @@ func (t *BlockTest) Run(snapshotter bool) error {
cache.SnapshotLimit = 1
cache.SnapshotWait = true
}
chain, err := core.NewBlockChain(db, cache, config, engine, vm.Config{}, nil, nil, false)
chain, err := core.NewBlockChain(db, cache, config, engine, vm.Config{}, nil, nil)
if err != nil {
return err
}
@ -174,17 +174,18 @@ func (t *BlockTest) genesis(config *params.ChainConfig) *core.Genesis {
}
}
/* See https://github.com/ethereum/tests/wiki/Blockchain-Tests-II
/*
See https://github.com/ethereum/tests/wiki/Blockchain-Tests-II
Whether a block is valid or not is a bit subtle, it's defined by presence of
blockHeader, transactions and uncleHeaders fields. If they are missing, the block is
invalid and we must verify that we do not accept it.
Whether a block is valid or not is a bit subtle, it's defined by presence of
blockHeader, transactions and uncleHeaders fields. If they are missing, the block is
invalid and we must verify that we do not accept it.
Since some tests mix valid and invalid blocks we need to check this for every block.
Since some tests mix valid and invalid blocks we need to check this for every block.
If a block is invalid it does not necessarily fail the test, if it's invalidness is
expected we are expected to ignore it and continue processing and then validate the
post state.
If a block is invalid it does not necessarily fail the test, if it's invalidness is
expected we are expected to ignore it and continue processing and then validate the
post state.
*/
func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]btBlock, error) {
validBlocks := make([]btBlock, 0)

View file

@ -80,7 +80,7 @@ func makechain() (bc *core.BlockChain, addrHashes, txHashes []common.Hash) {
addrHashes = append(addrHashes, crypto.Keccak256Hash(addr[:]))
txHashes = append(txHashes, tx.Hash())
})
bc, _ = core.NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil, false)
bc, _ = core.NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
if _, err := bc.InsertChain(blocks); err != nil {
panic(err)
}