mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-28 23:56:43 +00:00
Merge branch 'ethereum:master' into portal
This commit is contained in:
commit
305b567f7b
15 changed files with 217 additions and 127 deletions
|
|
@ -303,3 +303,21 @@ type ExecutionPayloadBodyV1 struct {
|
|||
TransactionData []hexutil.Bytes `json:"transactions"`
|
||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
}
|
||||
|
||||
// Client identifiers to support ClientVersionV1.
|
||||
const (
|
||||
ClientCode = "GE"
|
||||
ClientName = "go-ethereum"
|
||||
)
|
||||
|
||||
// ClientVersionV1 contains information which identifies a client implementation.
|
||||
type ClientVersionV1 struct {
|
||||
Code string `json:"code"`
|
||||
Name string `json:"clientName"`
|
||||
Version string `json:"version"`
|
||||
Commit string `json:"commit"`
|
||||
}
|
||||
|
||||
func (v *ClientVersionV1) String() string {
|
||||
return fmt.Sprintf("%s-%s-%s-%s", v.Code, v.Name, v.Version, v.Commit)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -762,7 +762,7 @@ func (s *Suite) makeBlobTxs(count, blobs int, discriminator byte) (txs types.Tra
|
|||
from, nonce := s.chain.GetSender(5)
|
||||
for i := 0; i < count; i++ {
|
||||
// Make blob data, max of 2 blobs per tx.
|
||||
blobdata := make([]byte, blobs%2)
|
||||
blobdata := make([]byte, blobs%3)
|
||||
for i := range blobdata {
|
||||
blobdata[i] = discriminator
|
||||
blobs -= 1
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
||||
"github.com/ethereum/go-ethereum/tests"
|
||||
|
|
@ -90,26 +89,27 @@ func runStateTest(fname string, cfg vm.Config, jsonOut, dump bool) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var tests map[string]tests.StateTest
|
||||
if err := json.Unmarshal(src, &tests); err != nil {
|
||||
var testsByName map[string]tests.StateTest
|
||||
if err := json.Unmarshal(src, &testsByName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Iterate over all the tests, run them and aggregate the results
|
||||
results := make([]StatetestResult, 0, len(tests))
|
||||
for key, test := range tests {
|
||||
results := make([]StatetestResult, 0, len(testsByName))
|
||||
for key, test := range testsByName {
|
||||
for _, st := range test.Subtests() {
|
||||
// Run the test and aggregate the result
|
||||
result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true}
|
||||
test.Run(st, cfg, false, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, statedb *state.StateDB) {
|
||||
test.Run(st, cfg, false, rawdb.HashScheme, func(err error, tstate *tests.StateTestState) {
|
||||
var root common.Hash
|
||||
if statedb != nil {
|
||||
root = statedb.IntermediateRoot(false)
|
||||
if tstate.StateDB != nil {
|
||||
root = tstate.StateDB.IntermediateRoot(false)
|
||||
result.Root = &root
|
||||
if jsonOut {
|
||||
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
|
||||
}
|
||||
if dump { // Dump any state to aid debugging
|
||||
cpy, _ := state.New(root, statedb.Database(), nil)
|
||||
cpy, _ := state.New(root, tstate.StateDB.Database(), nil)
|
||||
dump := cpy.RawDump(nil)
|
||||
result.State = &dump
|
||||
}
|
||||
|
|
|
|||
|
|
@ -258,6 +258,14 @@ func (t *Tree) Disable() {
|
|||
for _, layer := range t.layers {
|
||||
switch layer := layer.(type) {
|
||||
case *diskLayer:
|
||||
|
||||
layer.lock.RLock()
|
||||
generating := layer.genMarker != nil
|
||||
layer.lock.RUnlock()
|
||||
if !generating {
|
||||
// Generator is already aborted or finished
|
||||
break
|
||||
}
|
||||
// If the base layer is generating, abort it
|
||||
if layer.genAbort != nil {
|
||||
abort := make(chan *generatorStats)
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ func newBlobTxMeta(id uint64, size uint32, tx *types.Transaction) *blobTxMeta {
|
|||
// going up, crossing the smaller positive jump counter). As such, the pool
|
||||
// cares only about the min of the two delta values for eviction priority.
|
||||
//
|
||||
// priority = min(delta-basefee, delta-blobfee)
|
||||
// priority = min(deltaBasefee, deltaBlobfee)
|
||||
//
|
||||
// - The above very aggressive dimensionality and noise reduction should result
|
||||
// in transaction being grouped into a small number of buckets, the further
|
||||
|
|
@ -280,7 +280,7 @@ func newBlobTxMeta(id uint64, size uint32, tx *types.Transaction) *blobTxMeta {
|
|||
// with high fee caps since it could enable pool wars. As such, any positive
|
||||
// priority will be grouped together.
|
||||
//
|
||||
// priority = min(delta-basefee, delta-blobfee, 0)
|
||||
// priority = min(deltaBasefee, deltaBlobfee, 0)
|
||||
//
|
||||
// Optimisation tradeoffs:
|
||||
//
|
||||
|
|
|
|||
|
|
@ -30,9 +30,11 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||
"github.com/ethereum/go-ethereum/internal/version"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/miner"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/params/forks"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
|
@ -813,6 +815,23 @@ func (api *ConsensusAPI) ExchangeCapabilities([]string) []string {
|
|||
return caps
|
||||
}
|
||||
|
||||
// GetClientVersionV1 exchanges client version data of this node.
|
||||
func (api *ConsensusAPI) GetClientVersionV1(info engine.ClientVersionV1) []engine.ClientVersionV1 {
|
||||
log.Trace("Engine API request received", "method", "GetClientVersionV1", "info", info.String())
|
||||
commit := make([]byte, 4)
|
||||
if vcs, ok := version.VCS(); ok {
|
||||
commit = common.FromHex(vcs.Commit)[0:4]
|
||||
}
|
||||
return []engine.ClientVersionV1{
|
||||
{
|
||||
Code: engine.ClientCode,
|
||||
Name: engine.ClientName,
|
||||
Version: params.VersionWithMeta,
|
||||
Commit: hexutil.Encode(commit),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// GetPayloadBodiesByHashV1 implements engine_getPayloadBodiesByHashV1 which allows for retrieval of a list
|
||||
// of block bodies by the engine api.
|
||||
func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engine.ExecutionPayloadBodyV1 {
|
||||
|
|
|
|||
|
|
@ -1663,3 +1663,26 @@ func TestParentBeaconBlockRoot(t *testing.T) {
|
|||
t.Fatalf("incorrect root stored: want %s, got %s", *blockParams.BeaconRoot, root)
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetClientVersion verifies the expected version info is returned.
|
||||
func TestGetClientVersion(t *testing.T) {
|
||||
genesis, preMergeBlocks := generateMergeChain(10, false)
|
||||
n, ethservice := startEthService(t, genesis, preMergeBlocks)
|
||||
defer n.Close()
|
||||
|
||||
api := NewConsensusAPI(ethservice)
|
||||
info := engine.ClientVersionV1{
|
||||
Code: "TT",
|
||||
Name: "test",
|
||||
Version: "1.1.1",
|
||||
Commit: "0x12345678",
|
||||
}
|
||||
infos := api.GetClientVersionV1(info)
|
||||
if len(infos) != 1 {
|
||||
t.Fatalf("expected only one returned client version, got %d", len(infos))
|
||||
}
|
||||
info = infos[0]
|
||||
if info.Code != engine.ClientCode || info.Name != engine.ClientName || info.Version != params.VersionWithMeta {
|
||||
t.Fatalf("client info does match expected, got %s", info.String())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,9 +133,9 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
|
|||
GasLimit: uint64(test.Context.GasLimit),
|
||||
BaseFee: test.Genesis.BaseFee,
|
||||
}
|
||||
triedb, _, statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
|
||||
state = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
|
||||
)
|
||||
triedb.Close()
|
||||
state.Close()
|
||||
|
||||
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig)
|
||||
if err != nil {
|
||||
|
|
@ -145,7 +145,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||
}
|
||||
evm := vm.NewEVM(context, core.NewEVMTxContext(msg), statedb, test.Genesis.Config, vm.Config{Tracer: tracer})
|
||||
evm := vm.NewEVM(context, core.NewEVMTxContext(msg), state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer})
|
||||
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to execute transaction: %v", err)
|
||||
|
|
@ -235,8 +235,8 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
|
|||
if err != nil {
|
||||
b.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||
}
|
||||
triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
|
||||
defer triedb.Close()
|
||||
state := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
|
||||
defer state.Close()
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
|
@ -245,8 +245,8 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
|
|||
if err != nil {
|
||||
b.Fatalf("failed to create call tracer: %v", err)
|
||||
}
|
||||
evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Tracer: tracer})
|
||||
snap := statedb.Snapshot()
|
||||
evm := vm.NewEVM(context, txContext, state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer})
|
||||
snap := state.StateDB.Snapshot()
|
||||
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
||||
if _, err = st.TransitionDb(); err != nil {
|
||||
b.Fatalf("failed to execute transaction: %v", err)
|
||||
|
|
@ -254,7 +254,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
|
|||
if _, err = tracer.GetResult(); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
statedb.RevertToSnapshot(snap)
|
||||
state.StateDB.RevertToSnapshot(snap)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -362,7 +362,7 @@ func TestInternals(t *testing.T) {
|
|||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(),
|
||||
state := tests.MakePreState(rawdb.NewMemoryDatabase(),
|
||||
core.GenesisAlloc{
|
||||
to: core.GenesisAccount{
|
||||
Code: tc.code,
|
||||
|
|
@ -371,9 +371,9 @@ func TestInternals(t *testing.T) {
|
|||
Balance: big.NewInt(500000000000000),
|
||||
},
|
||||
}, false, rawdb.HashScheme)
|
||||
defer triedb.Close()
|
||||
defer state.Close()
|
||||
|
||||
evm := vm.NewEVM(context, txContext, statedb, params.MainnetChainConfig, vm.Config{Tracer: tc.tracer})
|
||||
evm := vm.NewEVM(context, txContext, state.StateDB, params.MainnetChainConfig, vm.Config{Tracer: tc.tracer})
|
||||
msg := &core.Message{
|
||||
To: &to,
|
||||
From: origin,
|
||||
|
|
|
|||
|
|
@ -95,8 +95,8 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
|
|||
Difficulty: (*big.Int)(test.Context.Difficulty),
|
||||
GasLimit: uint64(test.Context.GasLimit),
|
||||
}
|
||||
triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
|
||||
defer triedb.Close()
|
||||
state := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
|
||||
defer state.Close()
|
||||
|
||||
// Create the tracer, the EVM environment and run it
|
||||
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig)
|
||||
|
|
@ -107,7 +107,7 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
|
|||
if err != nil {
|
||||
return fmt.Errorf("failed to prepare transaction for tracing: %v", err)
|
||||
}
|
||||
evm := vm.NewEVM(context, core.NewEVMTxContext(msg), statedb, test.Genesis.Config, vm.Config{Tracer: tracer})
|
||||
evm := vm.NewEVM(context, core.NewEVMTxContext(msg), state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer})
|
||||
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
||||
|
||||
if _, err = st.TransitionDb(); err != nil {
|
||||
|
|
|
|||
|
|
@ -103,9 +103,9 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
|
|||
GasLimit: uint64(test.Context.GasLimit),
|
||||
BaseFee: test.Genesis.BaseFee,
|
||||
}
|
||||
triedb, _, statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
|
||||
state = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
|
||||
)
|
||||
defer triedb.Close()
|
||||
defer state.Close()
|
||||
|
||||
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig)
|
||||
if err != nil {
|
||||
|
|
@ -115,7 +115,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||
}
|
||||
evm := vm.NewEVM(context, core.NewEVMTxContext(msg), statedb, test.Genesis.Config, vm.Config{Tracer: tracer})
|
||||
evm := vm.NewEVM(context, core.NewEVMTxContext(msg), state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer})
|
||||
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
||||
if _, err = st.TransitionDb(); err != nil {
|
||||
t.Fatalf("failed to execute transaction: %v", err)
|
||||
|
|
|
|||
|
|
@ -79,8 +79,8 @@ func BenchmarkTransactionTrace(b *testing.B) {
|
|||
Code: []byte{},
|
||||
Balance: big.NewInt(500000000000000),
|
||||
}
|
||||
triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), alloc, false, rawdb.HashScheme)
|
||||
defer triedb.Close()
|
||||
state := tests.MakePreState(rawdb.NewMemoryDatabase(), alloc, false, rawdb.HashScheme)
|
||||
defer state.Close()
|
||||
|
||||
// Create the tracer, the EVM environment and run it
|
||||
tracer := logger.NewStructLogger(&logger.Config{
|
||||
|
|
@ -89,7 +89,7 @@ func BenchmarkTransactionTrace(b *testing.B) {
|
|||
//EnableMemory: false,
|
||||
//EnableReturnData: false,
|
||||
})
|
||||
evm := vm.NewEVM(context, txContext, statedb, params.AllEthashProtocolChanges, vm.Config{Tracer: tracer})
|
||||
evm := vm.NewEVM(context, txContext, state.StateDB, params.AllEthashProtocolChanges, vm.Config{Tracer: tracer})
|
||||
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
|
||||
if err != nil {
|
||||
b.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||
|
|
@ -98,13 +98,13 @@ func BenchmarkTransactionTrace(b *testing.B) {
|
|||
b.ReportAllocs()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
snap := statedb.Snapshot()
|
||||
snap := state.StateDB.Snapshot()
|
||||
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
||||
_, err = st.TransitionDb()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
statedb.RevertToSnapshot(snap)
|
||||
state.StateDB.RevertToSnapshot(snap)
|
||||
if have, want := len(tracer.StructLogs()), 244752; have != want {
|
||||
b.Fatalf("trace wrong, want %d steps, have %d", want, have)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -665,6 +665,12 @@ func toCallArg(msg ethereum.CallMsg) interface{} {
|
|||
if msg.AccessList != nil {
|
||||
arg["accessList"] = msg.AccessList
|
||||
}
|
||||
if msg.BlobGasFeeCap != nil {
|
||||
arg["maxFeePerBlobGas"] = (*hexutil.Big)(msg.BlobGasFeeCap)
|
||||
}
|
||||
if msg.BlobHashes != nil {
|
||||
arg["blobVersionedHashes"] = msg.BlobHashes
|
||||
}
|
||||
return arg
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -152,6 +152,10 @@ type CallMsg struct {
|
|||
Data []byte // input data, usually an ABI-encoded contract method invocation
|
||||
|
||||
AccessList types.AccessList // EIP-2930 access list.
|
||||
|
||||
// For BlobTxType
|
||||
BlobGasFeeCap *big.Int
|
||||
BlobHashes []common.Hash
|
||||
}
|
||||
|
||||
// A ContractCaller provides contract calls, essentially transactions that are executed by
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@ import (
|
|||
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
||||
|
|
@ -82,7 +80,7 @@ func TestState(t *testing.T) {
|
|||
t.Run(key+"/hash/trie", func(t *testing.T) {
|
||||
withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
|
||||
var result error
|
||||
test.Run(subtest, vmconfig, false, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
|
||||
test.Run(subtest, vmconfig, false, rawdb.HashScheme, func(err error, state *StateTestState) {
|
||||
result = st.checkFailure(t, err)
|
||||
})
|
||||
return result
|
||||
|
|
@ -91,9 +89,9 @@ func TestState(t *testing.T) {
|
|||
t.Run(key+"/hash/snap", func(t *testing.T) {
|
||||
withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
|
||||
var result error
|
||||
test.Run(subtest, vmconfig, true, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
|
||||
if snaps != nil && state != nil {
|
||||
if _, err := snaps.Journal(state.IntermediateRoot(false)); err != nil {
|
||||
test.Run(subtest, vmconfig, true, rawdb.HashScheme, func(err error, state *StateTestState) {
|
||||
if state.Snapshots != nil && state.StateDB != nil {
|
||||
if _, err := state.Snapshots.Journal(state.StateDB.IntermediateRoot(false)); err != nil {
|
||||
result = err
|
||||
return
|
||||
}
|
||||
|
|
@ -106,7 +104,7 @@ func TestState(t *testing.T) {
|
|||
t.Run(key+"/path/trie", func(t *testing.T) {
|
||||
withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
|
||||
var result error
|
||||
test.Run(subtest, vmconfig, false, rawdb.PathScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
|
||||
test.Run(subtest, vmconfig, false, rawdb.PathScheme, func(err error, state *StateTestState) {
|
||||
result = st.checkFailure(t, err)
|
||||
})
|
||||
return result
|
||||
|
|
@ -115,9 +113,9 @@ func TestState(t *testing.T) {
|
|||
t.Run(key+"/path/snap", func(t *testing.T) {
|
||||
withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
|
||||
var result error
|
||||
test.Run(subtest, vmconfig, true, rawdb.PathScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
|
||||
if snaps != nil && state != nil {
|
||||
if _, err := snaps.Journal(state.IntermediateRoot(false)); err != nil {
|
||||
test.Run(subtest, vmconfig, true, rawdb.PathScheme, func(err error, state *StateTestState) {
|
||||
if state.Snapshots != nil && state.StateDB != nil {
|
||||
if _, err := state.Snapshots.Journal(state.StateDB.IntermediateRoot(false)); err != nil {
|
||||
result = err
|
||||
return
|
||||
}
|
||||
|
|
@ -222,8 +220,8 @@ func runBenchmark(b *testing.B, t *StateTest) {
|
|||
|
||||
vmconfig.ExtraEips = eips
|
||||
block := t.genesis(config).ToBlock()
|
||||
triedb, _, statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, false, rawdb.HashScheme)
|
||||
defer triedb.Close()
|
||||
state := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, false, rawdb.HashScheme)
|
||||
defer state.Close()
|
||||
|
||||
var baseFee *big.Int
|
||||
if rules.IsLondon {
|
||||
|
|
@ -261,7 +259,7 @@ func runBenchmark(b *testing.B, t *StateTest) {
|
|||
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
|
||||
context.GetHash = vmTestBlockHash
|
||||
context.BaseFee = baseFee
|
||||
evm := vm.NewEVM(context, txContext, statedb, config, vmconfig)
|
||||
evm := vm.NewEVM(context, txContext, state.StateDB, config, vmconfig)
|
||||
|
||||
// Create "contract" for sender to cache code analysis.
|
||||
sender := vm.NewContract(vm.AccountRef(msg.From), vm.AccountRef(msg.From),
|
||||
|
|
@ -274,8 +272,8 @@ func runBenchmark(b *testing.B, t *StateTest) {
|
|||
)
|
||||
b.ResetTimer()
|
||||
for n := 0; n < b.N; n++ {
|
||||
snapshot := statedb.Snapshot()
|
||||
statedb.Prepare(rules, msg.From, context.Coinbase, msg.To, vm.ActivePrecompiles(rules), msg.AccessList)
|
||||
snapshot := state.StateDB.Snapshot()
|
||||
state.StateDB.Prepare(rules, msg.From, context.Coinbase, msg.To, vm.ActivePrecompiles(rules), msg.AccessList)
|
||||
b.StartTimer()
|
||||
start := time.Now()
|
||||
|
||||
|
|
@ -288,10 +286,10 @@ func runBenchmark(b *testing.B, t *StateTest) {
|
|||
|
||||
b.StopTimer()
|
||||
elapsed += uint64(time.Since(start))
|
||||
refund += statedb.GetRefund()
|
||||
refund += state.StateDB.GetRefund()
|
||||
gasUsed += msg.GasLimit - leftOverGas
|
||||
|
||||
statedb.RevertToSnapshot(snapshot)
|
||||
state.StateDB.RevertToSnapshot(snapshot)
|
||||
}
|
||||
if elapsed < 1 {
|
||||
elapsed = 1
|
||||
|
|
|
|||
|
|
@ -194,20 +194,14 @@ func (t *StateTest) checkError(subtest StateSubtest, err error) error {
|
|||
}
|
||||
|
||||
// Run executes a specific subtest and verifies the post-state and logs
|
||||
func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string, postCheck func(err error, snaps *snapshot.Tree, state *state.StateDB)) (result error) {
|
||||
triedb, snaps, statedb, root, err := t.RunNoVerify(subtest, vmconfig, snapshotter, scheme)
|
||||
|
||||
func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string, postCheck func(err error, st *StateTestState)) (result error) {
|
||||
st, root, err := t.RunNoVerify(subtest, vmconfig, snapshotter, scheme)
|
||||
// Invoke the callback at the end of function for further analysis.
|
||||
defer func() {
|
||||
postCheck(result, snaps, statedb)
|
||||
|
||||
if triedb != nil {
|
||||
triedb.Close()
|
||||
}
|
||||
if snaps != nil {
|
||||
snaps.Release()
|
||||
}
|
||||
postCheck(result, &st)
|
||||
st.Close()
|
||||
}()
|
||||
|
||||
checkedErr := t.checkError(subtest, err)
|
||||
if checkedErr != nil {
|
||||
return checkedErr
|
||||
|
|
@ -224,23 +218,24 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bo
|
|||
if root != common.Hash(post.Root) {
|
||||
return fmt.Errorf("post state root mismatch: got %x, want %x", root, post.Root)
|
||||
}
|
||||
if logs := rlpHash(statedb.Logs()); logs != common.Hash(post.Logs) {
|
||||
if logs := rlpHash(st.StateDB.Logs()); logs != common.Hash(post.Logs) {
|
||||
return fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, post.Logs)
|
||||
}
|
||||
statedb, _ = state.New(root, statedb.Database(), snaps)
|
||||
st.StateDB, _ = state.New(root, st.StateDB.Database(), st.Snapshots)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunNoVerify runs a specific subtest and returns the statedb and post-state root
|
||||
func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string) (*triedb.Database, *snapshot.Tree, *state.StateDB, common.Hash, error) {
|
||||
// RunNoVerify runs a specific subtest and returns the statedb and post-state root.
|
||||
// Remember to call state.Close after verifying the test result!
|
||||
func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string) (state StateTestState, root common.Hash, err error) {
|
||||
config, eips, err := GetChainConfig(subtest.Fork)
|
||||
if err != nil {
|
||||
return nil, nil, nil, common.Hash{}, UnsupportedForkError{subtest.Fork}
|
||||
return state, common.Hash{}, UnsupportedForkError{subtest.Fork}
|
||||
}
|
||||
vmconfig.ExtraEips = eips
|
||||
|
||||
block := t.genesis(config).ToBlock()
|
||||
triedb, snaps, statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, snapshotter, scheme)
|
||||
state = MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, snapshotter, scheme)
|
||||
|
||||
var baseFee *big.Int
|
||||
if config.IsLondon(new(big.Int)) {
|
||||
|
|
@ -254,8 +249,18 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
|
|||
post := t.json.Post[subtest.Fork][subtest.Index]
|
||||
msg, err := t.json.Tx.toMessage(post, baseFee)
|
||||
if err != nil {
|
||||
triedb.Close()
|
||||
return nil, nil, nil, common.Hash{}, err
|
||||
return state, common.Hash{}, err
|
||||
}
|
||||
|
||||
{ // Blob transactions may be present after the Cancun fork.
|
||||
// In production,
|
||||
// - the header is verified against the max in eip4844.go:VerifyEIP4844Header
|
||||
// - the block body is verified against the header in block_validator.go:ValidateBody
|
||||
// Here, we just do this shortcut smaller fix, since state tests do not
|
||||
// utilize those codepaths
|
||||
if len(msg.BlobHashes)*params.BlobTxBlobGasPerBlob > params.MaxBlobGasPerBlock {
|
||||
return state, common.Hash{}, errors.New("blob gas exceeds maximum")
|
||||
}
|
||||
}
|
||||
|
||||
// Try to recover tx with current signer
|
||||
|
|
@ -263,13 +268,10 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
|
|||
var ttx types.Transaction
|
||||
err := ttx.UnmarshalBinary(post.TxBytes)
|
||||
if err != nil {
|
||||
triedb.Close()
|
||||
return nil, nil, nil, common.Hash{}, err
|
||||
return state, common.Hash{}, err
|
||||
}
|
||||
|
||||
if _, err := types.Sender(types.LatestSigner(config), &ttx); err != nil {
|
||||
triedb.Close()
|
||||
return nil, nil, nil, common.Hash{}, err
|
||||
return state, common.Hash{}, err
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -290,78 +292,32 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
|
|||
if config.IsCancun(new(big.Int), block.Time()) && t.json.Env.ExcessBlobGas != nil {
|
||||
context.BlobBaseFee = eip4844.CalcBlobFee(*t.json.Env.ExcessBlobGas)
|
||||
}
|
||||
evm := vm.NewEVM(context, txContext, statedb, config, vmconfig)
|
||||
|
||||
{ // Blob transactions may be present after the Cancun fork.
|
||||
// In production,
|
||||
// - the header is verified against the max in eip4844.go:VerifyEIP4844Header
|
||||
// - the block body is verified against the header in block_validator.go:ValidateBody
|
||||
// Here, we just do this shortcut smaller fix, since state tests do not
|
||||
// utilize those codepaths
|
||||
if len(msg.BlobHashes)*params.BlobTxBlobGasPerBlob > params.MaxBlobGasPerBlock {
|
||||
return nil, nil, nil, common.Hash{}, errors.New("blob gas exceeds maximum")
|
||||
}
|
||||
}
|
||||
evm := vm.NewEVM(context, txContext, state.StateDB, config, vmconfig)
|
||||
|
||||
// Execute the message.
|
||||
snapshot := statedb.Snapshot()
|
||||
snapshot := state.StateDB.Snapshot()
|
||||
gaspool := new(core.GasPool)
|
||||
gaspool.AddGas(block.GasLimit())
|
||||
_, err = core.ApplyMessage(evm, msg, gaspool)
|
||||
if err != nil {
|
||||
statedb.RevertToSnapshot(snapshot)
|
||||
state.StateDB.RevertToSnapshot(snapshot)
|
||||
}
|
||||
// Add 0-value mining reward. This only makes a difference in the cases
|
||||
// where
|
||||
// - the coinbase self-destructed, or
|
||||
// - there are only 'bad' transactions, which aren't executed. In those cases,
|
||||
// the coinbase gets no txfee, so isn't created, and thus needs to be touched
|
||||
statedb.AddBalance(block.Coinbase(), new(uint256.Int))
|
||||
state.StateDB.AddBalance(block.Coinbase(), new(uint256.Int))
|
||||
|
||||
// Commit state mutations into database.
|
||||
root, _ := statedb.Commit(block.NumberU64(), config.IsEIP158(block.Number()))
|
||||
return triedb, snaps, statedb, root, err
|
||||
root, _ = state.StateDB.Commit(block.NumberU64(), config.IsEIP158(block.Number()))
|
||||
return state, root, err
|
||||
}
|
||||
|
||||
func (t *StateTest) gasLimit(subtest StateSubtest) uint64 {
|
||||
return t.json.Tx.GasLimit[t.json.Post[subtest.Fork][subtest.Index].Indexes.Gas]
|
||||
}
|
||||
|
||||
func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter bool, scheme string) (*triedb.Database, *snapshot.Tree, *state.StateDB) {
|
||||
tconf := &triedb.Config{Preimages: true}
|
||||
if scheme == rawdb.HashScheme {
|
||||
tconf.HashDB = hashdb.Defaults
|
||||
} else {
|
||||
tconf.PathDB = pathdb.Defaults
|
||||
}
|
||||
triedb := triedb.NewDatabase(db, tconf)
|
||||
sdb := state.NewDatabaseWithNodeDB(db, triedb)
|
||||
statedb, _ := state.New(types.EmptyRootHash, sdb, nil)
|
||||
for addr, a := range accounts {
|
||||
statedb.SetCode(addr, a.Code)
|
||||
statedb.SetNonce(addr, a.Nonce)
|
||||
statedb.SetBalance(addr, uint256.MustFromBig(a.Balance))
|
||||
for k, v := range a.Storage {
|
||||
statedb.SetState(addr, k, v)
|
||||
}
|
||||
}
|
||||
// Commit and re-open to start with a clean state.
|
||||
root, _ := statedb.Commit(0, false)
|
||||
|
||||
var snaps *snapshot.Tree
|
||||
if snapshotter {
|
||||
snapconfig := snapshot.Config{
|
||||
CacheSize: 1,
|
||||
Recovery: false,
|
||||
NoBuild: false,
|
||||
AsyncBuild: false,
|
||||
}
|
||||
snaps, _ = snapshot.New(snapconfig, db, triedb, root)
|
||||
}
|
||||
statedb, _ = state.New(root, sdb, snaps)
|
||||
return triedb, snaps, statedb
|
||||
}
|
||||
|
||||
func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis {
|
||||
genesis := &core.Genesis{
|
||||
Config: config,
|
||||
|
|
@ -478,3 +434,61 @@ func rlpHash(x interface{}) (h common.Hash) {
|
|||
func vmTestBlockHash(n uint64) common.Hash {
|
||||
return common.BytesToHash(crypto.Keccak256([]byte(big.NewInt(int64(n)).String())))
|
||||
}
|
||||
|
||||
// StateTestState groups all the state database objects together for use in tests.
|
||||
type StateTestState struct {
|
||||
StateDB *state.StateDB
|
||||
TrieDB *triedb.Database
|
||||
Snapshots *snapshot.Tree
|
||||
}
|
||||
|
||||
// MakePreState creates a state containing the given allocation.
|
||||
func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter bool, scheme string) StateTestState {
|
||||
tconf := &triedb.Config{Preimages: true}
|
||||
if scheme == rawdb.HashScheme {
|
||||
tconf.HashDB = hashdb.Defaults
|
||||
} else {
|
||||
tconf.PathDB = pathdb.Defaults
|
||||
}
|
||||
triedb := triedb.NewDatabase(db, tconf)
|
||||
sdb := state.NewDatabaseWithNodeDB(db, triedb)
|
||||
statedb, _ := state.New(types.EmptyRootHash, sdb, nil)
|
||||
for addr, a := range accounts {
|
||||
statedb.SetCode(addr, a.Code)
|
||||
statedb.SetNonce(addr, a.Nonce)
|
||||
statedb.SetBalance(addr, uint256.MustFromBig(a.Balance))
|
||||
for k, v := range a.Storage {
|
||||
statedb.SetState(addr, k, v)
|
||||
}
|
||||
}
|
||||
// Commit and re-open to start with a clean state.
|
||||
root, _ := statedb.Commit(0, false)
|
||||
|
||||
// If snapshot is requested, initialize the snapshotter and use it in state.
|
||||
var snaps *snapshot.Tree
|
||||
if snapshotter {
|
||||
snapconfig := snapshot.Config{
|
||||
CacheSize: 1,
|
||||
Recovery: false,
|
||||
NoBuild: false,
|
||||
AsyncBuild: false,
|
||||
}
|
||||
snaps, _ = snapshot.New(snapconfig, db, triedb, root)
|
||||
}
|
||||
statedb, _ = state.New(root, sdb, snaps)
|
||||
return StateTestState{statedb, triedb, snaps}
|
||||
}
|
||||
|
||||
// Close should be called when the state is no longer needed, ie. after running the test.
|
||||
func (st *StateTestState) Close() {
|
||||
if st.TrieDB != nil {
|
||||
st.TrieDB.Close()
|
||||
st.TrieDB = nil
|
||||
}
|
||||
if st.Snapshots != nil {
|
||||
// Need to call Disable here to quit the snapshot generator goroutine.
|
||||
st.Snapshots.Disable()
|
||||
st.Snapshots.Release()
|
||||
st.Snapshots = nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue