mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-21 20:26:41 +00:00
more updates
This commit is contained in:
parent
b86c15ea0e
commit
8b73b44533
14 changed files with 65 additions and 363 deletions
|
|
@ -158,7 +158,6 @@ var (
|
|||
utils.BeaconCheckpointFlag,
|
||||
utils.BeaconCheckpointFileFlag,
|
||||
utils.LogSlowBlockFlag,
|
||||
utils.ExperimentalBALFlag,
|
||||
}, utils.NetworkFlags, utils.DatabaseFlags)
|
||||
|
||||
rpcFlags = []cli.Flag{
|
||||
|
|
|
|||
|
|
@ -1024,14 +1024,6 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
|
|||
Value: metrics.DefaultConfig.InfluxDBOrganization,
|
||||
Category: flags.MetricsCategory,
|
||||
}
|
||||
|
||||
// Block Access List flags
|
||||
|
||||
ExperimentalBALFlag = &cli.BoolFlag{
|
||||
Name: "experimental.bal",
|
||||
Usage: "Enable generation of EIP-7928 block access lists when importing post-Cancun blocks which lack them. When this flag is specified, importing blocks containing access lists triggers validation of their correctness and execution based off them. The header block access list field is not set with blocks created when this flag is specified, nor is it validated when importing blocks that contain access lists. This is used for development purposes only. Do not enable it otherwise.",
|
||||
Category: flags.MiscCategory,
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -1963,8 +1955,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||
cfg.VMTraceJsonConfig = ctx.String(VMTraceJsonConfigFlag.Name)
|
||||
}
|
||||
}
|
||||
|
||||
cfg.ExperimentalBAL = ctx.Bool(ExperimentalBALFlag.Name)
|
||||
}
|
||||
|
||||
// MakeBeaconLightConfig constructs a beacon light client config based on the
|
||||
|
|
@ -2371,7 +2361,6 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
|||
}
|
||||
options.VmConfig = vmcfg
|
||||
|
||||
options.EnableBALForTesting = ctx.Bool(ExperimentalBALFlag.Name)
|
||||
chain, err := core.NewBlockChain(chainDb, gspec, engine, options)
|
||||
if err != nil {
|
||||
Fatalf("Can't create BlockChain: %v", err)
|
||||
|
|
|
|||
|
|
@ -22,13 +22,6 @@ type BlockAccessListTracer struct {
|
|||
// an access list to determine if the system calls being executed are
|
||||
// before/after the block transactions.
|
||||
sysCallCount int
|
||||
|
||||
// true if the tracer is processing post-tx state changes. in this case
|
||||
// we won't record the final index after the end of the second post-tx
|
||||
// system contract but after the finalization of the block.
|
||||
// This is because we have EIP-4895 withdrawals which are processed after the
|
||||
// last system contracts execute and must be included in the BAL.
|
||||
isPostTx bool
|
||||
}
|
||||
|
||||
// NewBlockAccessListTracer returns an BlockAccessListTracer and a set of hooks
|
||||
|
|
@ -55,24 +48,17 @@ func NewBlockAccessListTracer() (*BlockAccessListTracer, *tracing.Hooks) {
|
|||
return balTracer, wrappedHooks
|
||||
}
|
||||
|
||||
func (a *BlockAccessListTracer) SetPostTx() {
|
||||
a.isPostTx = true
|
||||
}
|
||||
|
||||
// AccessList returns the constructed access list.
|
||||
// It is assumed that this is only called after all the block state changes
|
||||
// have been executed and the block has been finalized.
|
||||
func (a *BlockAccessListTracer) AccessList() *bal.AccessListBuilder {
|
||||
return a.builder
|
||||
func (a *BlockAccessListTracer) AccessList() *bal.ConstructionBlockAccessList {
|
||||
return &a.builder.FinalizedAccesses
|
||||
}
|
||||
|
||||
func (a *BlockAccessListTracer) OnSystemCallEnd() {
|
||||
// finalize the post-block changes in OnBlockFinalization to account for
|
||||
// the EIP-4895 withdrawals which occur after the last system contracts
|
||||
// are executed.
|
||||
if a.isPostTx {
|
||||
return
|
||||
}
|
||||
a.sysCallCount++
|
||||
if a.sysCallCount == 2 {
|
||||
a.builder.FinaliseIdxChanges(a.balIdx)
|
||||
|
|
|
|||
|
|
@ -119,20 +119,6 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
|||
} else if err := block.Body().AccessList.Validate(len(block.Transactions())); err != nil {
|
||||
return fmt.Errorf("invalid block access list: %v", err)
|
||||
}
|
||||
} else if !v.bc.cfg.EnableBALForTesting {
|
||||
// if --experimental.bal is not enabled, block headers cannot have access list hash and bodies cannot have access lists.
|
||||
if block.Body().AccessList != nil {
|
||||
return fmt.Errorf("access list not allowed in block body if not in amsterdam or --experimental.bal is set")
|
||||
} else if block.Header().BlockAccessListHash != nil {
|
||||
return fmt.Errorf("access list hash in block header not allowed when --experimental.bal is set")
|
||||
}
|
||||
} else {
|
||||
// if --experimental.bal is enabled, the BAL hash is not allowed in the header.
|
||||
// this is in order that Geth can import pre-existing chains augmented with BALs
|
||||
// and not have a hash mismatch.
|
||||
if block.Header().BlockAccessListHash != nil {
|
||||
return fmt.Errorf("access list hash in block header not allowed pre-amsterdam")
|
||||
}
|
||||
}
|
||||
|
||||
// Ancestor block must be known.
|
||||
|
|
|
|||
|
|
@ -219,10 +219,6 @@ type BlockChainConfig struct {
|
|||
// SlowBlockThreshold is the block execution time threshold beyond which
|
||||
// detailed statistics will be logged.
|
||||
SlowBlockThreshold time.Duration
|
||||
// If EnableBALForTesting is enabled, block access lists will be created
|
||||
// from block execution and embedded in the body. The block access list
|
||||
// hash will not be set in the header.
|
||||
EnableBALForTesting bool
|
||||
}
|
||||
|
||||
// DefaultConfig returns the default config.
|
||||
|
|
@ -1990,7 +1986,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
|
|||
// The traced section of block import.
|
||||
start := time.Now()
|
||||
|
||||
res, err := bc.ProcessBlock(parent.Root, block, setHead, makeWitness && len(chain) == 1, bc.cfg.EnableBALForTesting)
|
||||
res, err := bc.ProcessBlock(parent.Root, block, setHead, makeWitness && len(chain) == 1)
|
||||
if err != nil {
|
||||
return nil, it.index, err
|
||||
}
|
||||
|
|
@ -2075,26 +2071,8 @@ func (bpr *blockProcessingResult) Stats() *ExecuteStats {
|
|||
|
||||
// ProcessBlock executes and validates the given block. If there was no error
|
||||
// it writes the block and associated state to database.
|
||||
func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, setHead bool, makeWitness bool, constructBALForTesting bool) (result *blockProcessingResult, blockEndErr error) {
|
||||
func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, setHead bool, makeWitness bool) (result *blockProcessingResult, blockEndErr error) {
|
||||
enableBALFork := bc.chainConfig.IsAmsterdam(block.Number(), block.Time())
|
||||
if enableBALFork || !bc.chainConfig.IsCancun(block.Number(), block.Time()) {
|
||||
// disable test-mode construction of BALs if we are not in the range [cancun, amsterdam)
|
||||
constructBALForTesting = false
|
||||
}
|
||||
// TODO: need to check that the block is also post-cancun if it contained an access list?
|
||||
// this should be checked during decoding (?)
|
||||
blockHasAccessList := block.Body().AccessList != nil
|
||||
// only construct and embed BALs in the block if:
|
||||
// * it has been enabled for testing purposes (pre-Amsterdam/post-Cancun blocks with --experimental.bal)
|
||||
// * we are after Amsterdam and the block was provided with bal omitted
|
||||
// (importing any historical block not near the chain head)
|
||||
constructBAL := constructBALForTesting || (enableBALFork && !blockHasAccessList)
|
||||
// do not verify the integrity of the BAL hash wrt the header-reported value
|
||||
// for any non-Amsterdam blocks: if the block being imported has been created
|
||||
// via --experimental.bal, the block access list hash is unset in the header
|
||||
// to keep the block hash unchanged (allow for importing historical blocks
|
||||
// with BALs for testing purposes).
|
||||
verifyBALHeader := enableBALFork
|
||||
|
||||
var (
|
||||
err error
|
||||
|
|
@ -2209,7 +2187,7 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
|
|||
var balTracer *BlockAccessListTracer
|
||||
|
||||
// Process block using the parent state as reference point
|
||||
if constructBAL {
|
||||
if enableBALFork {
|
||||
balTracer, bc.cfg.VmConfig.Tracer = NewBlockAccessListTracer()
|
||||
defer func() {
|
||||
bc.cfg.VmConfig.Tracer = nil
|
||||
|
|
@ -2224,7 +2202,7 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
|
|||
}
|
||||
ptime = time.Since(pstart)
|
||||
|
||||
if constructBAL {
|
||||
if enableBALFork {
|
||||
balTracer.OnBlockFinalization()
|
||||
}
|
||||
|
||||
|
|
@ -2238,23 +2216,19 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
|
|||
}
|
||||
vtime = time.Since(vstart)
|
||||
|
||||
if constructBAL {
|
||||
if verifyBALHeader && *block.Header().BlockAccessListHash != balTracer.AccessList().ToEncodingObj().Hash() {
|
||||
err := fmt.Errorf("block access list hash mismatch (reported=%x, computed=%x)", *block.Header().BlockAccessListHash, balTracer.AccessList().ToEncodingObj().Hash())
|
||||
if enableBALFork {
|
||||
computedAccessListHash := balTracer.AccessList().ToEncodingObj().Hash()
|
||||
|
||||
if *block.Header().BlockAccessListHash != computedAccessListHash {
|
||||
err := fmt.Errorf("block header access list hash mismatch with computed (header=%x computed=%x)", *block.Header().BlockAccessListHash, computedAccessListHash)
|
||||
bc.reportBadBlock(block, res, err)
|
||||
return nil, err
|
||||
}
|
||||
if block.Body().AccessList != nil && block.Body().AccessList.Hash() != computedAccessListHash {
|
||||
err := fmt.Errorf("block access list hash mismatch (remote=%x computed=%x)", block.Body().AccessList.Hash(), computedAccessListHash)
|
||||
bc.reportBadBlock(block, res, err)
|
||||
return nil, err
|
||||
} else if block.Body().AccessList != nil {
|
||||
// TODO: assert that the
|
||||
} else {
|
||||
// very ugly... deepcopy the block body before setting the block access
|
||||
// list on it to prevent mutating the block instance passed by the caller.
|
||||
existingBody := block.Body()
|
||||
block = block.WithBody(*existingBody)
|
||||
existingBody = block.Body()
|
||||
existingBody.AccessList = balTracer.AccessList().ToEncodingObj()
|
||||
block = block.WithBody(*existingBody)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If witnesses was generated and stateless self-validation requested, do
|
||||
|
|
|
|||
|
|
@ -128,12 +128,6 @@ type StateDB struct {
|
|||
thash common.Hash
|
||||
txIndex int
|
||||
|
||||
// block access list modifications will be recorded with this index.
|
||||
// 0 - state access before transaction execution
|
||||
// 1 -> len(block txs) - state access of each transaction
|
||||
// len(block txs) + 1 - state access after transaction execution.
|
||||
balIndex int
|
||||
|
||||
logs map[common.Hash][]*types.Log
|
||||
logSize uint
|
||||
|
||||
|
|
@ -755,7 +749,6 @@ func (s *StateDB) Copy() *StateDB {
|
|||
refund: s.refund,
|
||||
thash: s.thash,
|
||||
txIndex: s.txIndex,
|
||||
balIndex: s.txIndex,
|
||||
logs: make(map[common.Hash][]*types.Log, len(s.logs)),
|
||||
logSize: s.logSize,
|
||||
preimages: maps.Clone(s.preimages),
|
||||
|
|
@ -1061,14 +1054,6 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
|||
func (s *StateDB) SetTxContext(thash common.Hash, ti int) {
|
||||
s.thash = thash
|
||||
s.txIndex = ti
|
||||
s.balIndex = ti + 1
|
||||
}
|
||||
|
||||
// SetAccessListIndex sets the current index that state mutations will
|
||||
// be reported as in the BAL. It is only relevant if this StateDB instance
|
||||
// is being used in the BAL construction path.
|
||||
func (s *StateDB) SetAccessListIndex(idx int) {
|
||||
s.balIndex = idx
|
||||
}
|
||||
|
||||
func (s *StateDB) clearJournalAndRefund() {
|
||||
|
|
|
|||
|
|
@ -489,9 +489,11 @@ func (c *constructionAccountAccess) NonceChange(cur uint64) {
|
|||
c.nonce = &cur
|
||||
}
|
||||
|
||||
type ConstructionBlockAccessList map[common.Address]*ConstructionAccountAccesses
|
||||
|
||||
// AccessListBuilder is used to build an EIP-7928 block access list
|
||||
type AccessListBuilder struct {
|
||||
FinalizedAccesses map[common.Address]*ConstructionAccountAccesses
|
||||
FinalizedAccesses ConstructionBlockAccessList
|
||||
|
||||
idxBuilder *idxAccessListBuilder
|
||||
|
||||
|
|
@ -647,44 +649,6 @@ func (a *AccountMutations) LogDiff(addr common.Address, other *AccountMutations)
|
|||
}
|
||||
}
|
||||
|
||||
// Eq returns whether the calling instance is equal to the provided one.
|
||||
func (a *AccountMutations) Eq(other *AccountMutations) bool {
|
||||
if a.Balance != nil || other.Balance != nil {
|
||||
if a.Balance == nil || other.Balance == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if !a.Balance.Eq(other.Balance) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if (len(a.Code) != 0 || len(other.Code) != 0) && !bytes.Equal(a.Code, other.Code) {
|
||||
return false
|
||||
}
|
||||
|
||||
if a.Nonce != nil || other.Nonce != nil {
|
||||
if a.Nonce == nil || other.Nonce == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if *a.Nonce != *other.Nonce {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if a.StorageWrites != nil || other.StorageWrites != nil {
|
||||
if a.StorageWrites == nil || other.StorageWrites == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if !maps.Equal(a.StorageWrites, other.StorageWrites) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Copy returns a deep-copy of the instance.
|
||||
func (a *AccountMutations) Copy() *AccountMutations {
|
||||
res := &AccountMutations{
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ func (e *BlockAccessList) String() string {
|
|||
return res.String()
|
||||
}
|
||||
|
||||
// TODO: check that no fields are nil in Validate (unless it's valid for them to be nil)
|
||||
// Validate returns an error if the contents of the access list are not ordered
|
||||
// according to the spec or any code changes are contained which exceed protocol
|
||||
// max code size.
|
||||
|
|
@ -369,11 +370,11 @@ func (e *AccountAccess) Copy() AccountAccess {
|
|||
}
|
||||
|
||||
// EncodeRLP returns the RLP-encoded access list
|
||||
func (c *AccessListBuilder) EncodeRLP(wr io.Writer) error {
|
||||
func (c ConstructionBlockAccessList) EncodeRLP(wr io.Writer) error {
|
||||
return c.ToEncodingObj().EncodeRLP(wr)
|
||||
}
|
||||
|
||||
var _ rlp.Encoder = &AccessListBuilder{}
|
||||
var _ rlp.Encoder = &ConstructionBlockAccessList{}
|
||||
|
||||
// toEncodingObj creates an instance of the ConstructionAccountAccesses of the type that is
|
||||
// used as input for the encoding.
|
||||
|
|
@ -449,16 +450,16 @@ func (a *ConstructionAccountAccesses) toEncodingObj(addr common.Address) Account
|
|||
|
||||
// ToEncodingObj returns an instance of the access list expressed as the type
|
||||
// which is used as input for the encoding/decoding.
|
||||
func (c *AccessListBuilder) ToEncodingObj() *BlockAccessList {
|
||||
func (c ConstructionBlockAccessList) ToEncodingObj() *BlockAccessList {
|
||||
var addresses []common.Address
|
||||
for addr := range c.FinalizedAccesses {
|
||||
for addr := range c {
|
||||
addresses = append(addresses, addr)
|
||||
}
|
||||
slices.SortFunc(addresses, common.Address.Cmp)
|
||||
|
||||
var res BlockAccessList
|
||||
for _, addr := range addresses {
|
||||
res = append(res, c.FinalizedAccesses[addr].toEncodingObj(addr))
|
||||
res = append(res, c[addr].toEncodingObj(addr))
|
||||
}
|
||||
return &res
|
||||
}
|
||||
|
|
|
|||
|
|
@ -537,16 +537,13 @@ func gasStaticCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memo
|
|||
|
||||
func gasSelfdestruct(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||
var gas uint64
|
||||
fmt.Println("gasSelfdestruct")
|
||||
|
||||
// EIP150 homestead gas reprice fork:
|
||||
if evm.chainRules.IsEIP150 {
|
||||
gas = params.SelfdestructGasEIP150
|
||||
var address = common.Address(stack.Back(0).Bytes20())
|
||||
|
||||
fmt.Println("okay we're")
|
||||
if gas > contract.Gas {
|
||||
fmt.Println("here")
|
||||
return gas, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -504,7 +504,7 @@ func (api *DebugAPI) ExecutionWitness(bn rpc.BlockNumber) (*stateless.ExtWitness
|
|||
return &stateless.ExtWitness{}, fmt.Errorf("block number %v found, but parent missing", bn)
|
||||
}
|
||||
|
||||
result, err := bc.ProcessBlock(parent.Root, block, false, true, false)
|
||||
result, err := bc.ProcessBlock(parent.Root, block, false, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -522,7 +522,7 @@ func (api *DebugAPI) ExecutionWitnessByHash(hash common.Hash) (*stateless.ExtWit
|
|||
return &stateless.ExtWitness{}, fmt.Errorf("block number %x found, but parent missing", hash)
|
||||
}
|
||||
|
||||
result, err := bc.ProcessBlock(parent.Root, block, false, true, false)
|
||||
result, err := bc.ProcessBlock(parent.Root, block, false, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,7 +245,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
|||
TrieJournalDirectory: stack.ResolvePath("triedb"),
|
||||
StateSizeTracking: config.EnableStateSizeTracking,
|
||||
SlowBlockThreshold: config.SlowBlockThreshold,
|
||||
EnableBALForTesting: config.ExperimentalBAL,
|
||||
}
|
||||
)
|
||||
if config.VMTrace != "" {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ package tests
|
|||
|
||||
import (
|
||||
"math/rand"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
|
@ -68,119 +67,13 @@ func TestBlockchain(t *testing.T) {
|
|||
bt.skipLoad(`.*\.meta/.*`)
|
||||
|
||||
bt.walk(t, blockTestDir, func(t *testing.T, name string, test *BlockTest) {
|
||||
execBlockTest(t, bt, test, false)
|
||||
execBlockTest(t, bt, test)
|
||||
})
|
||||
// There is also a LegacyTests folder, containing blockchain tests generated
|
||||
// prior to Istanbul. However, they are all derived from GeneralStateTests,
|
||||
// which run natively, so there's no reason to run them here.
|
||||
}
|
||||
|
||||
func TestBlockchainBAL(t *testing.T) {
|
||||
bt := new(testMatcher)
|
||||
|
||||
// We are running most of GeneralStatetests to tests witness support, even
|
||||
// though they are ran as state tests too. Still, the performance tests are
|
||||
// less about state andmore about EVM number crunching, so skip those.
|
||||
bt.skipLoad(`^GeneralStateTests/VMTests/vmPerformance`)
|
||||
|
||||
// Skip random failures due to selfish mining test
|
||||
bt.skipLoad(`.*bcForgedTest/bcForkUncle\.json`)
|
||||
|
||||
// Slow tests
|
||||
bt.slow(`.*bcExploitTest/DelegateCallSpam.json`)
|
||||
bt.slow(`.*bcExploitTest/ShanghaiLove.json`)
|
||||
bt.slow(`.*bcExploitTest/SuicideIssue.json`)
|
||||
bt.slow(`.*/bcForkStressTest/`)
|
||||
bt.slow(`.*/bcGasPricerTest/RPC_API_Test.json`)
|
||||
bt.slow(`.*/bcWalletTest/`)
|
||||
|
||||
// Very slow test
|
||||
bt.skipLoad(`.*/stTimeConsuming/.*`)
|
||||
// test takes a lot for time and goes easily OOM because of sha3 calculation on a huge range,
|
||||
// using 4.6 TGas
|
||||
bt.skipLoad(`.*randomStatetest94.json.*`)
|
||||
|
||||
// After the merge we would accept side chains as canonical even if they have lower td
|
||||
bt.skipLoad(`.*bcMultiChainTest/ChainAtoChainB_difficultyB.json`)
|
||||
bt.skipLoad(`.*bcMultiChainTest/CallContractFromNotBestBlock.json`)
|
||||
bt.skipLoad(`.*bcTotalDifficultyTest/uncleBlockAtBlock3afterBlock4.json`)
|
||||
bt.skipLoad(`.*bcTotalDifficultyTest/lotsOfBranchesOverrideAtTheMiddle.json`)
|
||||
bt.skipLoad(`.*bcTotalDifficultyTest/sideChainWithMoreTransactions.json`)
|
||||
bt.skipLoad(`.*bcForkStressTest/ForkStressTest.json`)
|
||||
bt.skipLoad(`.*bcMultiChainTest/lotsOfLeafs.json`)
|
||||
bt.skipLoad(`.*bcFrontierToHomestead/blockChainFrontierWithLargerTDvsHomesteadBlockchain.json`)
|
||||
bt.skipLoad(`.*bcFrontierToHomestead/blockChainFrontierWithLargerTDvsHomesteadBlockchain2.json`)
|
||||
|
||||
// With chain history removal, TDs become unavailable, this transition tests based on TTD are unrunnable
|
||||
bt.skipLoad(`.*bcArrowGlacierToParis/powToPosBlockRejection.json`)
|
||||
|
||||
// This directory contains no test.
|
||||
bt.skipLoad(`.*\.meta/.*`)
|
||||
|
||||
bt.walk(t, blockTestDir, func(t *testing.T, name string, test *BlockTest) {
|
||||
config, ok := Forks[test.json.Network]
|
||||
if !ok {
|
||||
t.Fatalf("unsupported fork: %s\n", test.json.Network)
|
||||
}
|
||||
gspec := test.genesis(config)
|
||||
// skip any tests which are not past the cancun fork (selfdestruct removal)
|
||||
if gspec.Config.CancunTime == nil || *gspec.Config.CancunTime != 0 {
|
||||
return
|
||||
}
|
||||
execBlockTest(t, bt, test, true)
|
||||
})
|
||||
// There is also a LegacyTests folder, containing blockchain tests generated
|
||||
// prior to Istanbul. However, they are all derived from GeneralStateTests,
|
||||
// which run natively, so there's no reason to run them here.
|
||||
}
|
||||
|
||||
// TestExecutionSpecBlocktests runs the test fixtures from execution-spec-tests.
|
||||
// TODO: rename this to reflect that it tests creating/verifying BALs on pre-amsterdam tests
|
||||
func TestExecutionSpecBlocktestsBAL(t *testing.T) {
|
||||
if !common.FileExist(executionSpecBlockchainTestDir) {
|
||||
t.Skipf("directory %s does not exist", executionSpecBlockchainTestDir)
|
||||
}
|
||||
bt := new(testMatcher)
|
||||
|
||||
bt.skipLoad(".*prague/eip7251_consolidations/contract_deployment/system_contract_deployment.json")
|
||||
bt.skipLoad(".*prague/eip7002_el_triggerable_withdrawals/contract_deployment/system_contract_deployment.json")
|
||||
|
||||
bt.walk(t, executionSpecBlockchainTestDir, func(t *testing.T, name string, test *BlockTest) {
|
||||
config, ok := Forks[test.json.Network]
|
||||
if !ok {
|
||||
t.Fatalf("unsupported fork: %s\n", test.json.Network)
|
||||
}
|
||||
gspec := test.genesis(config)
|
||||
// skip any tests which are not past the cancun fork (selfdestruct removal)
|
||||
if gspec.Config.CancunTime == nil || *gspec.Config.CancunTime != 0 {
|
||||
return
|
||||
}
|
||||
execBlockTest(t, bt, test, true)
|
||||
})
|
||||
}
|
||||
|
||||
func TestExecutionSpecBlocktestsAmsterdam(t *testing.T) {
|
||||
var executionSpecAmsterdamBlockchainTestDir = filepath.Join(".", "fixtures-amsterdam-bal", "blockchain_tests")
|
||||
if !common.FileExist(executionSpecAmsterdamBlockchainTestDir) {
|
||||
t.Skipf("directory %s does not exist", executionSpecAmsterdamBlockchainTestDir)
|
||||
}
|
||||
bt := new(testMatcher)
|
||||
|
||||
bt.walk(t, executionSpecAmsterdamBlockchainTestDir, func(t *testing.T, name string, test *BlockTest) {
|
||||
config, ok := Forks[test.json.Network]
|
||||
if !ok {
|
||||
t.Fatalf("unsupported fork: %s\n", test.json.Network)
|
||||
}
|
||||
gspec := test.genesis(config)
|
||||
// skip any tests which are not past the cancun fork (selfdestruct removal)
|
||||
if gspec.Config.CancunTime == nil || *gspec.Config.CancunTime != 0 {
|
||||
return
|
||||
}
|
||||
// TODO: skip any tests that aren't amsterdam
|
||||
execBlockTest(t, bt, test, false)
|
||||
})
|
||||
}
|
||||
|
||||
// TestExecutionSpecBlocktests runs the test fixtures from execution-spec-tests.
|
||||
func TestExecutionSpecBlocktests(t *testing.T) {
|
||||
if !common.FileExist(executionSpecBlockchainTestDir) {
|
||||
|
|
@ -193,11 +86,11 @@ func TestExecutionSpecBlocktests(t *testing.T) {
|
|||
bt.skipLoad(".*prague/eip7002_el_triggerable_withdrawals/test_system_contract_deployment.json")
|
||||
|
||||
bt.walk(t, executionSpecBlockchainTestDir, func(t *testing.T, name string, test *BlockTest) {
|
||||
execBlockTest(t, bt, test, false)
|
||||
execBlockTest(t, bt, test)
|
||||
})
|
||||
}
|
||||
|
||||
func execBlockTest(t *testing.T, bt *testMatcher, test *BlockTest, buildAndVerifyBAL bool) {
|
||||
func execBlockTest(t *testing.T, bt *testMatcher, test *BlockTest) {
|
||||
// Define all the different flag combinations we should run the tests with,
|
||||
// picking only one for short tests.
|
||||
//
|
||||
|
|
@ -211,10 +104,9 @@ func execBlockTest(t *testing.T, bt *testMatcher, test *BlockTest, buildAndVerif
|
|||
snapshotConf = []bool{snapshotConf[rand.Int()%2]}
|
||||
dbschemeConf = []string{dbschemeConf[rand.Int()%2]}
|
||||
}
|
||||
|
||||
for _, snapshot := range snapshotConf {
|
||||
for _, dbscheme := range dbschemeConf {
|
||||
if err := bt.checkFailure(t, test.Run(snapshot, dbscheme, false, buildAndVerifyBAL, nil, nil)); err != nil {
|
||||
if err := bt.checkFailure(t, test.Run(snapshot, dbscheme, true, nil, nil)); err != nil {
|
||||
t.Errorf("test with config {snapshotter:%v, scheme:%v} failed: %v", snapshot, dbscheme, err)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,11 @@ import (
|
|||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
stdmath "math"
|
||||
"math/big"
|
||||
"os"
|
||||
"reflect"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
|
|
@ -32,7 +37,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/types/bal"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
|
|
@ -40,11 +44,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/hashdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||
stdmath "math"
|
||||
"math/big"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// A BlockTest checks handling of entire blocks.
|
||||
|
|
@ -72,7 +71,6 @@ type btBlock struct {
|
|||
ExpectException string
|
||||
Rlp string
|
||||
UncleHeaders []*btHeader
|
||||
AccessList *bal.BlockAccessList `json:"blockAccessList,omitempty"`
|
||||
}
|
||||
|
||||
//go:generate go run github.com/fjl/gencodec -type btHeader -field-override btHeaderMarshaling -out gen_btheader.go
|
||||
|
|
@ -99,7 +97,6 @@ type btHeader struct {
|
|||
BlobGasUsed *uint64
|
||||
ExcessBlobGas *uint64
|
||||
ParentBeaconBlockRoot *common.Hash
|
||||
BlockAccessListHash *common.Hash
|
||||
}
|
||||
|
||||
type btHeaderMarshaling struct {
|
||||
|
|
@ -114,20 +111,27 @@ type btHeaderMarshaling struct {
|
|||
ExcessBlobGas *math.HexOrDecimal64
|
||||
}
|
||||
|
||||
func (t *BlockTest) createTestBlockChain(config *params.ChainConfig, snapshotter bool, scheme string, witness, createAndVerifyBAL bool, tracer *tracing.Hooks) (*core.BlockChain, error) {
|
||||
func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *tracing.Hooks, postCheck func(error, *core.BlockChain)) (result error) {
|
||||
config, ok := Forks[t.json.Network]
|
||||
if !ok {
|
||||
return UnsupportedForkError{t.json.Network}
|
||||
}
|
||||
|
||||
// import pre accounts & construct test genesis block & state root
|
||||
// Commit genesis state
|
||||
var (
|
||||
gspec = t.genesis(config)
|
||||
db = rawdb.NewMemoryDatabase()
|
||||
tconf = &triedb.Config{
|
||||
Preimages: true,
|
||||
IsVerkle: gspec.Config.VerkleTime != nil && *gspec.Config.VerkleTime <= gspec.Timestamp,
|
||||
}
|
||||
)
|
||||
if scheme == rawdb.PathScheme {
|
||||
if scheme == rawdb.PathScheme || tconf.IsVerkle {
|
||||
tconf.PathDB = pathdb.Defaults
|
||||
} else {
|
||||
tconf.HashDB = hashdb.Defaults
|
||||
}
|
||||
gspec := t.genesis(config)
|
||||
|
||||
// if ttd is not specified, set an arbitrary huge value
|
||||
if gspec.Config.TerminalTotalDifficulty == nil {
|
||||
|
|
@ -136,15 +140,15 @@ func (t *BlockTest) createTestBlockChain(config *params.ChainConfig, snapshotter
|
|||
triedb := triedb.NewDatabase(db, tconf)
|
||||
gblock, err := gspec.Commit(db, triedb, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
triedb.Close() // close the db to prevent memory leak
|
||||
|
||||
if gblock.Hash() != t.json.Genesis.Hash {
|
||||
return nil, fmt.Errorf("genesis block hash doesn't match test: computed=%x, test=%x", gblock.Hash().Bytes()[:6], t.json.Genesis.Hash[:6])
|
||||
return fmt.Errorf("genesis block hash doesn't match test: computed=%x, test=%x", gblock.Hash().Bytes()[:6], t.json.Genesis.Hash[:6])
|
||||
}
|
||||
if gblock.Root() != t.json.Genesis.StateRoot {
|
||||
return nil, fmt.Errorf("genesis block state root does not match test: computed=%x, test=%x", gblock.Root().Bytes()[:6], t.json.Genesis.StateRoot[:6])
|
||||
return fmt.Errorf("genesis block state root does not match test: computed=%x, test=%x", gblock.Root().Bytes()[:6], t.json.Genesis.StateRoot[:6])
|
||||
}
|
||||
// Wrap the original engine within the beacon-engine
|
||||
engine := beacon.New(ethash.NewFaker())
|
||||
|
|
@ -158,28 +162,12 @@ func (t *BlockTest) createTestBlockChain(config *params.ChainConfig, snapshotter
|
|||
Tracer: tracer,
|
||||
StatelessSelfValidation: witness,
|
||||
},
|
||||
NoPrefetch: true,
|
||||
EnableBALForTesting: createAndVerifyBAL,
|
||||
}
|
||||
if snapshotter {
|
||||
options.SnapshotLimit = 1
|
||||
options.SnapshotWait = true
|
||||
}
|
||||
chain, err := core.NewBlockChain(db, gspec, engine, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return chain, nil
|
||||
}
|
||||
|
||||
func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, createAndVerifyBAL bool, tracer *tracing.Hooks, postCheck func(error, *core.BlockChain)) (result error) {
|
||||
config, ok := Forks[t.json.Network]
|
||||
if !ok {
|
||||
return UnsupportedForkError{t.json.Network}
|
||||
}
|
||||
// import pre accounts & construct test genesis block & state root
|
||||
|
||||
chain, err := t.createTestBlockChain(config, snapshotter, scheme, witness, createAndVerifyBAL, tracer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -213,50 +201,7 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, createAnd
|
|||
}
|
||||
}
|
||||
}
|
||||
err = t.validateImportedHeaders(chain, validBlocks)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if createAndVerifyBAL {
|
||||
newChain, _ := t.createTestBlockChain(config, snapshotter, scheme, witness, createAndVerifyBAL, tracer)
|
||||
defer newChain.Stop()
|
||||
|
||||
var blocksWithBAL types.Blocks
|
||||
for i := uint64(1); i <= chain.CurrentBlock().Number.Uint64(); i++ {
|
||||
block := chain.GetBlockByNumber(i)
|
||||
if block.Body().AccessList == nil {
|
||||
return fmt.Errorf("block %d missing BAL", block.NumberU64())
|
||||
}
|
||||
blocksWithBAL = append(blocksWithBAL, block)
|
||||
}
|
||||
|
||||
amt, err := newChain.InsertChain(blocksWithBAL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_ = amt
|
||||
newDB, err := newChain.State()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = t.validatePostState(newDB); err != nil {
|
||||
return fmt.Errorf("post state validation failed: %v", err)
|
||||
}
|
||||
// Cross-check the snapshot-to-hash against the trie hash
|
||||
if snapshotter {
|
||||
if newChain.Snapshots() != nil {
|
||||
if err := chain.Snapshots().Verify(chain.CurrentBlock().Root); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
err = t.validateImportedHeaders(newChain, validBlocks)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return t.validateImportedHeaders(chain, validBlocks)
|
||||
}
|
||||
|
||||
// Network returns the network/fork name for this test.
|
||||
|
|
@ -266,21 +211,20 @@ func (t *BlockTest) Network() string {
|
|||
|
||||
func (t *BlockTest) genesis(config *params.ChainConfig) *core.Genesis {
|
||||
return &core.Genesis{
|
||||
Config: config,
|
||||
Nonce: t.json.Genesis.Nonce.Uint64(),
|
||||
Timestamp: t.json.Genesis.Timestamp,
|
||||
ParentHash: t.json.Genesis.ParentHash,
|
||||
ExtraData: t.json.Genesis.ExtraData,
|
||||
GasLimit: t.json.Genesis.GasLimit,
|
||||
GasUsed: t.json.Genesis.GasUsed,
|
||||
Difficulty: t.json.Genesis.Difficulty,
|
||||
Mixhash: t.json.Genesis.MixHash,
|
||||
Coinbase: t.json.Genesis.Coinbase,
|
||||
Alloc: t.json.Pre,
|
||||
BaseFee: t.json.Genesis.BaseFeePerGas,
|
||||
BlobGasUsed: t.json.Genesis.BlobGasUsed,
|
||||
ExcessBlobGas: t.json.Genesis.ExcessBlobGas,
|
||||
BlockAccessListHash: t.json.Genesis.BlockAccessListHash,
|
||||
Config: config,
|
||||
Nonce: t.json.Genesis.Nonce.Uint64(),
|
||||
Timestamp: t.json.Genesis.Timestamp,
|
||||
ParentHash: t.json.Genesis.ParentHash,
|
||||
ExtraData: t.json.Genesis.ExtraData,
|
||||
GasLimit: t.json.Genesis.GasLimit,
|
||||
GasUsed: t.json.Genesis.GasUsed,
|
||||
Difficulty: t.json.Genesis.Difficulty,
|
||||
Mixhash: t.json.Genesis.MixHash,
|
||||
Coinbase: t.json.Genesis.Coinbase,
|
||||
Alloc: t.json.Pre,
|
||||
BaseFee: t.json.Genesis.BaseFeePerGas,
|
||||
BlobGasUsed: t.json.Genesis.BlobGasUsed,
|
||||
ExcessBlobGas: t.json.Genesis.ExcessBlobGas,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -310,16 +254,6 @@ func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]btBlock, error)
|
|||
return nil, fmt.Errorf("block RLP decoding failed when expected to succeed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// check that if we encode the same block, it will result in the same RLP
|
||||
var enc bytes.Buffer
|
||||
if err := rlp.Encode(&enc, cb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
expected := common.Hex2Bytes(strings.TrimLeft(b.Rlp, "0x"))
|
||||
if !bytes.Equal(enc.Bytes(), expected) {
|
||||
return nil, fmt.Errorf("mismatch. expected\n%s\ngot\n%x\n", expected, enc.Bytes())
|
||||
}
|
||||
// RLP decoding worked, try to insert into chain:
|
||||
blocks := types.Blocks{cb}
|
||||
i, err := blockchain.InsertChain(blocks)
|
||||
|
|
@ -332,7 +266,7 @@ func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]btBlock, error)
|
|||
}
|
||||
if b.BlockHeader == nil {
|
||||
if data, err := json.MarshalIndent(cb.Header(), "", " "); err == nil {
|
||||
fmt.Fprintf(os.Stderr, "block (index %d) insertion should have failed due to: %v:\n%v\n",
|
||||
fmt.Fprintf(os.Stdout, "block (index %d) insertion should have failed due to: %v:\n%v\n",
|
||||
bi, b.ExpectException, string(data))
|
||||
}
|
||||
return nil, fmt.Errorf("block (index %d) insertion should have failed due to: %v",
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ func (b btHeader) MarshalJSON() ([]byte, error) {
|
|||
enc.BlobGasUsed = (*math.HexOrDecimal64)(b.BlobGasUsed)
|
||||
enc.ExcessBlobGas = (*math.HexOrDecimal64)(b.ExcessBlobGas)
|
||||
enc.ParentBeaconBlockRoot = b.ParentBeaconBlockRoot
|
||||
enc.BlockAccessListHash = b.BlockAccessListHash
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
|
|
@ -159,8 +158,5 @@ func (b *btHeader) UnmarshalJSON(input []byte) error {
|
|||
if dec.ParentBeaconBlockRoot != nil {
|
||||
b.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
|
||||
}
|
||||
if dec.BlockAccessListHash != nil {
|
||||
b.BlockAccessListHash = dec.BlockAccessListHash
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue