2015-07-07 03:54:22 +03:00
|
|
|
// Copyright 2015 The go-ethereum Authors
|
2015-07-22 19:48:40 +03:00
|
|
|
// This file is part of the go-ethereum library.
|
2015-07-07 03:54:22 +03:00
|
|
|
//
|
2015-07-23 19:35:11 +03:00
|
|
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
2015-07-07 03:54:22 +03:00
|
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
2015-07-22 19:48:40 +03:00
|
|
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
2015-07-07 03:54:22 +03:00
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2015-07-22 19:48:40 +03:00
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2015-07-07 03:54:22 +03:00
|
|
|
// GNU Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
2015-07-22 19:48:40 +03:00
|
|
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
2015-07-07 03:54:22 +03:00
|
|
|
|
2017-07-11 14:49:14 +03:00
|
|
|
// Package tests implements execution of Ethereum JSON tests.
|
2015-03-13 19:01:51 +02:00
|
|
|
package tests
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/hex"
|
2017-07-11 14:49:14 +03:00
|
|
|
"encoding/json"
|
2015-03-13 19:01:51 +02:00
|
|
|
"fmt"
|
2024-10-23 09:26:18 +03:00
|
|
|
stdmath "math"
|
2015-03-13 19:01:51 +02:00
|
|
|
"math/big"
|
2021-06-07 15:37:56 +03:00
|
|
|
"os"
|
2023-02-06 22:52:51 +03:00
|
|
|
"reflect"
|
2015-03-13 19:01:51 +02:00
|
|
|
|
2015-03-16 12:27:38 +02:00
|
|
|
"github.com/ethereum/go-ethereum/common"
|
2017-07-11 14:49:14 +03:00
|
|
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
|
|
"github.com/ethereum/go-ethereum/common/math"
|
2022-12-20 17:56:52 +03:00
|
|
|
"github.com/ethereum/go-ethereum/consensus/beacon"
|
2017-04-05 01:16:29 +03:00
|
|
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
2015-04-17 17:30:15 +03:00
|
|
|
"github.com/ethereum/go-ethereum/core"
|
2018-09-24 15:57:49 +03:00
|
|
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
2015-03-23 23:05:12 +02:00
|
|
|
"github.com/ethereum/go-ethereum/core/state"
|
2024-03-22 20:53:53 +03:00
|
|
|
"github.com/ethereum/go-ethereum/core/tracing"
|
2015-03-17 00:10:26 +02:00
|
|
|
"github.com/ethereum/go-ethereum/core/types"
|
2017-01-17 14:19:50 +03:00
|
|
|
"github.com/ethereum/go-ethereum/core/vm"
|
2024-01-16 14:08:49 +03:00
|
|
|
"github.com/ethereum/go-ethereum/log"
|
2016-10-20 14:36:29 +03:00
|
|
|
"github.com/ethereum/go-ethereum/params"
|
2015-03-13 19:01:51 +02:00
|
|
|
"github.com/ethereum/go-ethereum/rlp"
|
2024-02-13 16:49:53 +03:00
|
|
|
"github.com/ethereum/go-ethereum/triedb"
|
|
|
|
"github.com/ethereum/go-ethereum/triedb/hashdb"
|
|
|
|
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
2015-03-13 19:01:51 +02:00
|
|
|
)
|
|
|
|
|
2017-07-11 14:49:14 +03:00
|
|
|
// A BlockTest checks handling of entire blocks.
|
2015-04-20 19:14:57 +03:00
|
|
|
type BlockTest struct {
|
2017-07-11 14:49:14 +03:00
|
|
|
json btJSON
|
|
|
|
}
|
2015-04-20 19:14:57 +03:00
|
|
|
|
2018-06-05 13:31:34 +03:00
|
|
|
// UnmarshalJSON implements json.Unmarshaler interface.
|
2017-07-11 14:49:14 +03:00
|
|
|
func (t *BlockTest) UnmarshalJSON(in []byte) error {
|
|
|
|
return json.Unmarshal(in, &t.json)
|
2015-04-20 19:14:57 +03:00
|
|
|
}
|
|
|
|
|
2015-03-13 19:01:51 +02:00
|
|
|
type btJSON struct {
|
2018-10-16 01:26:47 +03:00
|
|
|
Blocks []btBlock `json:"blocks"`
|
|
|
|
Genesis btHeader `json:"genesisBlockHeader"`
|
2024-02-16 21:05:33 +03:00
|
|
|
Pre types.GenesisAlloc `json:"pre"`
|
|
|
|
Post types.GenesisAlloc `json:"postState"`
|
2018-10-16 01:26:47 +03:00
|
|
|
BestBlock common.UnprefixedHash `json:"lastblockhash"`
|
|
|
|
Network string `json:"network"`
|
|
|
|
SealEngine string `json:"sealEngine"`
|
2015-03-13 19:01:51 +02:00
|
|
|
}
|
|
|
|
|
2015-04-20 19:14:57 +03:00
|
|
|
type btBlock struct {
|
2021-06-07 15:37:56 +03:00
|
|
|
BlockHeader *btHeader
|
|
|
|
ExpectException string
|
|
|
|
Rlp string
|
|
|
|
UncleHeaders []*btHeader
|
2015-04-20 19:14:57 +03:00
|
|
|
}
|
|
|
|
|
2022-04-12 21:24:02 +03:00
|
|
|
//go:generate go run github.com/fjl/gencodec -type btHeader -field-override btHeaderMarshaling -out gen_btheader.go
|
2015-03-13 19:01:51 +02:00
|
|
|
|
|
|
|
type btHeader struct {
|
2023-08-26 16:42:27 +03:00
|
|
|
Bloom types.Bloom
|
|
|
|
Coinbase common.Address
|
|
|
|
MixHash common.Hash
|
|
|
|
Nonce types.BlockNonce
|
|
|
|
Number *big.Int
|
|
|
|
Hash common.Hash
|
|
|
|
ParentHash common.Hash
|
|
|
|
ReceiptTrie common.Hash
|
|
|
|
StateRoot common.Hash
|
|
|
|
TransactionsTrie common.Hash
|
|
|
|
UncleHash common.Hash
|
|
|
|
ExtraData []byte
|
|
|
|
Difficulty *big.Int
|
|
|
|
GasLimit uint64
|
|
|
|
GasUsed uint64
|
|
|
|
Timestamp uint64
|
|
|
|
BaseFeePerGas *big.Int
|
|
|
|
WithdrawalsRoot *common.Hash
|
|
|
|
BlobGasUsed *uint64
|
|
|
|
ExcessBlobGas *uint64
|
|
|
|
ParentBeaconBlockRoot *common.Hash
|
2015-03-13 19:01:51 +02:00
|
|
|
}
|
|
|
|
|
2017-07-11 14:49:14 +03:00
|
|
|
type btHeaderMarshaling struct {
|
2021-07-29 15:05:22 +03:00
|
|
|
ExtraData hexutil.Bytes
|
|
|
|
Number *math.HexOrDecimal256
|
|
|
|
Difficulty *math.HexOrDecimal256
|
|
|
|
GasLimit math.HexOrDecimal64
|
|
|
|
GasUsed math.HexOrDecimal64
|
|
|
|
Timestamp math.HexOrDecimal64
|
|
|
|
BaseFeePerGas *math.HexOrDecimal256
|
2023-08-26 16:42:27 +03:00
|
|
|
BlobGasUsed *math.HexOrDecimal64
|
|
|
|
ExcessBlobGas *math.HexOrDecimal64
|
2015-06-15 00:55:03 +03:00
|
|
|
}
|
|
|
|
|
2024-06-25 14:48:08 +03:00
|
|
|
func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *tracing.Hooks, postCheck func(error, *core.BlockChain)) (result error) {
|
2017-08-10 12:38:17 +03:00
|
|
|
config, ok := Forks[t.json.Network]
|
|
|
|
if !ok {
|
|
|
|
return UnsupportedForkError{t.json.Network}
|
|
|
|
}
|
2017-07-11 14:49:14 +03:00
|
|
|
// import pre accounts & construct test genesis block & state root
|
all: activate pbss as experimental feature (#26274)
* all: activate pbss
* core/rawdb: fix compilation error
* cma, core, eth, les, trie: address comments
* cmd, core, eth, trie: polish code
* core, cmd, eth: address comments
* cmd, core, eth, les, light, tests: address comment
* cmd/utils: shorten log message
* trie/triedb/pathdb: limit node buffer size to 1gb
* cmd/utils: fix opening non-existing db
* cmd/utils: rename flag name
* cmd, core: group chain history flags and fix tests
* core, eth, trie: fix memory leak in snapshot generation
* cmd, eth, internal: deprecate flags
* all: enable state tests for pathdb, fixes
* cmd, core: polish code
* trie/triedb/pathdb: limit the node buffer size to 256mb
---------
Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2023-08-10 22:21:36 +03:00
|
|
|
var (
|
|
|
|
db = rawdb.NewMemoryDatabase()
|
2024-02-13 16:49:53 +03:00
|
|
|
tconf = &triedb.Config{
|
2023-11-28 15:54:17 +03:00
|
|
|
Preimages: true,
|
|
|
|
}
|
all: activate pbss as experimental feature (#26274)
* all: activate pbss
* core/rawdb: fix compilation error
* cma, core, eth, les, trie: address comments
* cmd, core, eth, trie: polish code
* core, cmd, eth: address comments
* cmd, core, eth, les, light, tests: address comment
* cmd/utils: shorten log message
* trie/triedb/pathdb: limit node buffer size to 1gb
* cmd/utils: fix opening non-existing db
* cmd/utils: rename flag name
* cmd, core: group chain history flags and fix tests
* core, eth, trie: fix memory leak in snapshot generation
* cmd, eth, internal: deprecate flags
* all: enable state tests for pathdb, fixes
* cmd, core: polish code
* trie/triedb/pathdb: limit the node buffer size to 256mb
---------
Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2023-08-10 22:21:36 +03:00
|
|
|
)
|
|
|
|
if scheme == rawdb.PathScheme {
|
|
|
|
tconf.PathDB = pathdb.Defaults
|
|
|
|
} else {
|
|
|
|
tconf.HashDB = hashdb.Defaults
|
|
|
|
}
|
|
|
|
// Commit genesis state
|
2022-08-30 19:22:28 +03:00
|
|
|
gspec := t.genesis(config)
|
2024-10-23 09:26:18 +03:00
|
|
|
|
|
|
|
// if ttd is not specified, set an arbitrary huge value
|
|
|
|
if gspec.Config.TerminalTotalDifficulty == nil {
|
|
|
|
gspec.Config.TerminalTotalDifficulty = big.NewInt(stdmath.MaxInt64)
|
|
|
|
}
|
2024-02-13 16:49:53 +03:00
|
|
|
triedb := triedb.NewDatabase(db, tconf)
|
all: activate pbss as experimental feature (#26274)
* all: activate pbss
* core/rawdb: fix compilation error
* cma, core, eth, les, trie: address comments
* cmd, core, eth, trie: polish code
* core, cmd, eth: address comments
* cmd, core, eth, les, light, tests: address comment
* cmd/utils: shorten log message
* trie/triedb/pathdb: limit node buffer size to 1gb
* cmd/utils: fix opening non-existing db
* cmd/utils: rename flag name
* cmd, core: group chain history flags and fix tests
* core, eth, trie: fix memory leak in snapshot generation
* cmd, eth, internal: deprecate flags
* all: enable state tests for pathdb, fixes
* cmd, core: polish code
* trie/triedb/pathdb: limit the node buffer size to 256mb
---------
Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2023-08-10 22:21:36 +03:00
|
|
|
gblock, err := gspec.Commit(db, triedb)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
triedb.Close() // close the db to prevent memory leak
|
|
|
|
|
2017-07-11 14:49:14 +03:00
|
|
|
if gblock.Hash() != t.json.Genesis.Hash {
|
2018-05-02 11:20:19 +03:00
|
|
|
return fmt.Errorf("genesis block hash doesn't match test: computed=%x, test=%x", gblock.Hash().Bytes()[:6], t.json.Genesis.Hash[:6])
|
2015-06-10 19:04:56 +03:00
|
|
|
}
|
2017-07-11 14:49:14 +03:00
|
|
|
if gblock.Root() != t.json.Genesis.StateRoot {
|
|
|
|
return fmt.Errorf("genesis block state root does not match test: computed=%x, test=%x", gblock.Root().Bytes()[:6], t.json.Genesis.StateRoot[:6])
|
2015-06-10 19:04:56 +03:00
|
|
|
}
|
2022-12-20 17:56:52 +03:00
|
|
|
// Wrap the original engine within the beacon-engine
|
2023-05-03 12:58:39 +03:00
|
|
|
engine := beacon.New(ethash.NewFaker())
|
2022-12-20 17:56:52 +03:00
|
|
|
|
2023-11-28 15:54:17 +03:00
|
|
|
cache := &core.CacheConfig{TrieCleanLimit: 0, StateScheme: scheme, Preimages: true}
|
2020-03-03 10:10:23 +03:00
|
|
|
if snapshotter {
|
|
|
|
cache.SnapshotLimit = 1
|
|
|
|
cache.SnapshotWait = true
|
|
|
|
}
|
2023-06-06 11:27:40 +03:00
|
|
|
chain, err := core.NewBlockChain(db, cache, gspec, nil, engine, vm.Config{
|
2024-06-25 14:48:08 +03:00
|
|
|
Tracer: tracer,
|
beacon, core, eth, miner: integrate witnesses into production Geth (#30069)
This PR integrates witness-enabled block production, witness-creating
payload execution and stateless cross-validation into the `engine` API.
The purpose of the PR is to enable the following use-cases (for API
details, please see next section):
- Cross validating locally created blocks:
- Call `forkchoiceUpdatedWithWitness` instead of `forkchoiceUpdated` to
trigger witness creation too.
- Call `getPayload` as before to retrieve the new block and also the
above created witness.
- Call `executeStatelessPayload` against another client to
cross-validate the block.
- Cross validating locally processed blocks:
- Call `newPayloadWithWitness` instead of `newPayload` to trigger
witness creation too.
- Call `executeStatelessPayload` against another client to
cross-validate the block.
- Block production for stateless clients (local or MEV builders):
- Call `forkchoiceUpdatedWithWitness` instead of `forkchoiceUpdated` to
trigger witness creation too.
- Call `getPayload` as before to retrieve the new block and also the
above created witness.
- Propagate witnesses across the consensus libp2p network for stateless
Ethereum.
- Stateless validator validation:
- Call `executeStatelessPayload` with the propagated witness to
statelessly validate the block.
*Note, the various `WithWitness` methods could also *just be* an
additional boolean flag on the base methods, but this PR wanted to keep
the methods separate until a final consensus is reached on how to
integrate in production.*
---
The following `engine` API types are introduced:
```go
// StatelessPayloadStatusV1 is the result of a stateless payload execution.
type StatelessPayloadStatusV1 struct {
Status string `json:"status"`
StateRoot common.Hash `json:"stateRoot"`
ReceiptsRoot common.Hash `json:"receiptsRoot"`
ValidationError *string `json:"validationError"`
}
```
- Add `forkchoiceUpdatedWithWitnessV1,2,3` with same params and returns
as `forkchoiceUpdatedV1,2,3`, but triggering a stateless witness
building if block production is requested.
- Extend `getPayloadV2,3` to return `executionPayloadEnvelope` with an
additional `witness` field of type `bytes` iff created via
`forkchoiceUpdatedWithWitnessV2,3`.
- Add `newPayloadWithWitnessV1,2,3,4` with same params and returns as
`newPayloadV1,2,3,4`, but triggering a stateless witness creation during
payload execution to allow cross validating it.
- Extend `payloadStatusV1` with a `witness` field of type `bytes` if
returned by `newPayloadWithWitnessV1,2,3,4`.
- Add `executeStatelessPayloadV1,2,3,4` with same base params as
`newPayloadV1,2,3,4` and one more additional param (`witness`) of type
`bytes`. The method returns `statelessPayloadStatusV1`, which mirrors
`payloadStatusV1` but replaces `latestValidHash` with `stateRoot` and
`receiptRoot`.
2024-09-20 16:43:42 +03:00
|
|
|
StatelessSelfValidation: witness,
|
2024-09-04 16:03:06 +03:00
|
|
|
}, nil)
|
2015-06-10 19:04:56 +03:00
|
|
|
if err != nil {
|
2015-10-06 17:35:55 +03:00
|
|
|
return err
|
2015-06-10 19:04:56 +03:00
|
|
|
}
|
2017-02-20 13:54:23 +03:00
|
|
|
defer chain.Stop()
|
2016-03-22 00:00:39 +02:00
|
|
|
|
2017-07-11 14:49:14 +03:00
|
|
|
validBlocks, err := t.insertBlocks(chain)
|
2015-06-10 19:04:56 +03:00
|
|
|
if err != nil {
|
2015-06-10 23:10:33 +03:00
|
|
|
return err
|
2015-06-10 19:04:56 +03:00
|
|
|
}
|
2023-11-28 15:54:17 +03:00
|
|
|
// Import succeeded: regardless of whether the _test_ succeeds or not, schedule
|
|
|
|
// the post-check to run
|
|
|
|
if postCheck != nil {
|
|
|
|
defer postCheck(result, chain)
|
|
|
|
}
|
2018-01-30 19:39:32 +03:00
|
|
|
cmlast := chain.CurrentBlock().Hash()
|
2017-07-11 14:49:14 +03:00
|
|
|
if common.Hash(t.json.BestBlock) != cmlast {
|
|
|
|
return fmt.Errorf("last block hash validation mismatch: want: %x, have: %x", t.json.BestBlock, cmlast)
|
2015-09-18 18:15:59 +03:00
|
|
|
}
|
2016-03-22 00:00:39 +02:00
|
|
|
newDB, err := chain.State()
|
2015-10-06 17:35:55 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-07-11 14:49:14 +03:00
|
|
|
if err = t.validatePostState(newDB); err != nil {
|
2015-06-10 23:10:33 +03:00
|
|
|
return fmt.Errorf("post state validation failed: %v", err)
|
2015-06-10 19:04:56 +03:00
|
|
|
}
|
2020-03-31 11:25:41 +03:00
|
|
|
// Cross-check the snapshot-to-hash against the trie hash
|
|
|
|
if snapshotter {
|
2023-03-02 09:29:15 +03:00
|
|
|
if err := chain.Snapshots().Verify(chain.CurrentBlock().Root); err != nil {
|
2020-04-29 12:53:08 +03:00
|
|
|
return err
|
2020-03-31 11:25:41 +03:00
|
|
|
}
|
|
|
|
}
|
2017-07-11 14:49:14 +03:00
|
|
|
return t.validateImportedHeaders(chain, validBlocks)
|
2015-06-10 19:04:56 +03:00
|
|
|
}
|
|
|
|
|
2017-07-11 14:49:14 +03:00
|
|
|
func (t *BlockTest) genesis(config *params.ChainConfig) *core.Genesis {
|
|
|
|
return &core.Genesis{
|
2023-08-26 16:42:27 +03:00
|
|
|
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,
|
2015-03-20 10:10:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-10 14:25:40 +03:00
|
|
|
/*
|
|
|
|
See https://github.com/ethereum/tests/wiki/Blockchain-Tests-II
|
2015-04-20 19:14:57 +03:00
|
|
|
|
2022-09-10 14:25:40 +03:00
|
|
|
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.
|
2015-04-20 19:14:57 +03:00
|
|
|
|
2022-09-10 14:25:40 +03:00
|
|
|
Since some tests mix valid and invalid blocks we need to check this for every block.
|
2015-04-20 19:14:57 +03:00
|
|
|
|
2022-09-10 14:25:40 +03:00
|
|
|
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.
|
2015-04-20 19:14:57 +03:00
|
|
|
*/
|
2017-07-11 14:49:14 +03:00
|
|
|
func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]btBlock, error) {
|
2015-09-18 18:15:59 +03:00
|
|
|
validBlocks := make([]btBlock, 0)
|
2015-04-20 19:14:57 +03:00
|
|
|
// insert the test blocks, which will execute all transactions
|
2021-06-07 15:37:56 +03:00
|
|
|
for bi, b := range t.json.Blocks {
|
2017-07-11 14:49:14 +03:00
|
|
|
cb, err := b.decode()
|
2015-04-20 19:14:57 +03:00
|
|
|
if err != nil {
|
|
|
|
if b.BlockHeader == nil {
|
2024-01-16 14:08:49 +03:00
|
|
|
log.Info("Block decoding failed", "index", bi, "err", err)
|
2015-04-20 19:14:57 +03:00
|
|
|
continue // OK - block is supposed to be invalid, continue with next block
|
|
|
|
} else {
|
2019-11-23 14:51:37 +03:00
|
|
|
return nil, fmt.Errorf("block RLP decoding failed when expected to succeed: %v", err)
|
2015-04-20 19:14:57 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// RLP decoding worked, try to insert into chain:
|
2016-01-20 00:48:50 +02:00
|
|
|
blocks := types.Blocks{cb}
|
|
|
|
i, err := blockchain.InsertChain(blocks)
|
2015-04-20 19:14:57 +03:00
|
|
|
if err != nil {
|
|
|
|
if b.BlockHeader == nil {
|
|
|
|
continue // OK - block is supposed to be invalid, continue with next block
|
|
|
|
} else {
|
2019-11-23 14:51:37 +03:00
|
|
|
return nil, fmt.Errorf("block #%v insertion into chain failed: %v", blocks[i].Number(), err)
|
2015-04-20 19:14:57 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if b.BlockHeader == nil {
|
2021-06-07 15:37:56 +03:00
|
|
|
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",
|
|
|
|
bi, b.ExpectException, string(data))
|
|
|
|
}
|
|
|
|
return nil, fmt.Errorf("block (index %d) insertion should have failed due to: %v",
|
|
|
|
bi, b.ExpectException)
|
2015-04-20 19:14:57 +03:00
|
|
|
}
|
2015-09-14 15:27:25 +03:00
|
|
|
|
|
|
|
// validate RLP decoding by checking all values against test file JSON
|
2015-09-18 18:15:59 +03:00
|
|
|
if err = validateHeader(b.BlockHeader, cb.Header()); err != nil {
|
2019-11-23 14:51:37 +03:00
|
|
|
return nil, fmt.Errorf("deserialised block header validation failed: %v", err)
|
2015-04-23 05:38:47 +03:00
|
|
|
}
|
2015-09-18 18:15:59 +03:00
|
|
|
validBlocks = append(validBlocks, b)
|
2015-04-23 05:38:47 +03:00
|
|
|
}
|
2015-09-18 18:15:59 +03:00
|
|
|
return validBlocks, nil
|
2015-04-23 05:38:47 +03:00
|
|
|
}
|
|
|
|
|
2015-09-18 18:15:59 +03:00
|
|
|
func validateHeader(h *btHeader, h2 *types.Header) error {
|
2017-07-11 14:49:14 +03:00
|
|
|
if h.Bloom != h2.Bloom {
|
2019-11-23 14:51:37 +03:00
|
|
|
return fmt.Errorf("bloom: want: %x have: %x", h.Bloom, h2.Bloom)
|
2015-04-23 05:38:47 +03:00
|
|
|
}
|
2017-07-11 14:49:14 +03:00
|
|
|
if h.Coinbase != h2.Coinbase {
|
2019-11-23 14:51:37 +03:00
|
|
|
return fmt.Errorf("coinbase: want: %x have: %x", h.Coinbase, h2.Coinbase)
|
2015-04-23 05:38:47 +03:00
|
|
|
}
|
2017-07-11 14:49:14 +03:00
|
|
|
if h.MixHash != h2.MixDigest {
|
|
|
|
return fmt.Errorf("MixHash: want: %x have: %x", h.MixHash, h2.MixDigest)
|
2015-04-23 05:38:47 +03:00
|
|
|
}
|
2017-07-11 14:49:14 +03:00
|
|
|
if h.Nonce != h2.Nonce {
|
2019-11-23 14:51:37 +03:00
|
|
|
return fmt.Errorf("nonce: want: %x have: %x", h.Nonce, h2.Nonce)
|
2015-04-23 05:38:47 +03:00
|
|
|
}
|
2017-07-11 14:49:14 +03:00
|
|
|
if h.Number.Cmp(h2.Number) != 0 {
|
2019-11-23 14:51:37 +03:00
|
|
|
return fmt.Errorf("number: want: %v have: %v", h.Number, h2.Number)
|
2015-04-23 05:38:47 +03:00
|
|
|
}
|
2017-07-11 14:49:14 +03:00
|
|
|
if h.ParentHash != h2.ParentHash {
|
2019-11-23 14:51:37 +03:00
|
|
|
return fmt.Errorf("parent hash: want: %x have: %x", h.ParentHash, h2.ParentHash)
|
2015-04-23 05:38:47 +03:00
|
|
|
}
|
2017-07-11 14:49:14 +03:00
|
|
|
if h.ReceiptTrie != h2.ReceiptHash {
|
2019-11-23 14:51:37 +03:00
|
|
|
return fmt.Errorf("receipt hash: want: %x have: %x", h.ReceiptTrie, h2.ReceiptHash)
|
2015-04-23 05:38:47 +03:00
|
|
|
}
|
2017-07-11 14:49:14 +03:00
|
|
|
if h.TransactionsTrie != h2.TxHash {
|
2019-11-23 14:51:37 +03:00
|
|
|
return fmt.Errorf("tx hash: want: %x have: %x", h.TransactionsTrie, h2.TxHash)
|
2015-04-23 05:38:47 +03:00
|
|
|
}
|
2017-07-11 14:49:14 +03:00
|
|
|
if h.StateRoot != h2.Root {
|
2019-11-23 14:51:37 +03:00
|
|
|
return fmt.Errorf("state hash: want: %x have: %x", h.StateRoot, h2.Root)
|
2015-04-23 05:38:47 +03:00
|
|
|
}
|
2017-07-11 14:49:14 +03:00
|
|
|
if h.UncleHash != h2.UncleHash {
|
2019-11-23 14:51:37 +03:00
|
|
|
return fmt.Errorf("uncle hash: want: %x have: %x", h.UncleHash, h2.UncleHash)
|
2015-04-23 05:38:47 +03:00
|
|
|
}
|
2017-07-11 14:49:14 +03:00
|
|
|
if !bytes.Equal(h.ExtraData, h2.Extra) {
|
2019-11-23 14:51:37 +03:00
|
|
|
return fmt.Errorf("extra data: want: %x have: %x", h.ExtraData, h2.Extra)
|
2015-04-17 17:30:15 +03:00
|
|
|
}
|
2017-07-11 14:49:14 +03:00
|
|
|
if h.Difficulty.Cmp(h2.Difficulty) != 0 {
|
2019-11-23 14:51:37 +03:00
|
|
|
return fmt.Errorf("difficulty: want: %v have: %v", h.Difficulty, h2.Difficulty)
|
2015-04-23 05:38:47 +03:00
|
|
|
}
|
2017-11-13 14:47:27 +03:00
|
|
|
if h.GasLimit != h2.GasLimit {
|
2019-11-23 14:51:37 +03:00
|
|
|
return fmt.Errorf("gasLimit: want: %d have: %d", h.GasLimit, h2.GasLimit)
|
2015-04-23 05:38:47 +03:00
|
|
|
}
|
2017-11-13 14:47:27 +03:00
|
|
|
if h.GasUsed != h2.GasUsed {
|
2019-11-23 14:51:37 +03:00
|
|
|
return fmt.Errorf("gasUsed: want: %d have: %d", h.GasUsed, h2.GasUsed)
|
2015-04-23 05:38:47 +03:00
|
|
|
}
|
2019-04-02 23:28:48 +03:00
|
|
|
if h.Timestamp != h2.Time {
|
2019-11-23 14:51:37 +03:00
|
|
|
return fmt.Errorf("timestamp: want: %v have: %v", h.Timestamp, h2.Time)
|
2015-04-23 05:38:47 +03:00
|
|
|
}
|
2023-02-06 22:52:51 +03:00
|
|
|
if !reflect.DeepEqual(h.BaseFeePerGas, h2.BaseFee) {
|
|
|
|
return fmt.Errorf("baseFeePerGas: want: %v have: %v", h.BaseFeePerGas, h2.BaseFee)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(h.WithdrawalsRoot, h2.WithdrawalsHash) {
|
|
|
|
return fmt.Errorf("withdrawalsRoot: want: %v have: %v", h.WithdrawalsRoot, h2.WithdrawalsHash)
|
|
|
|
}
|
2023-08-26 16:42:27 +03:00
|
|
|
if !reflect.DeepEqual(h.BlobGasUsed, h2.BlobGasUsed) {
|
|
|
|
return fmt.Errorf("blobGasUsed: want: %v have: %v", h.BlobGasUsed, h2.BlobGasUsed)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(h.ExcessBlobGas, h2.ExcessBlobGas) {
|
|
|
|
return fmt.Errorf("excessBlobGas: want: %v have: %v", h.ExcessBlobGas, h2.ExcessBlobGas)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(h.ParentBeaconBlockRoot, h2.ParentBeaconRoot) {
|
|
|
|
return fmt.Errorf("parentBeaconBlockRoot: want: %v have: %v", h.ParentBeaconBlockRoot, h2.ParentBeaconRoot)
|
|
|
|
}
|
2015-04-20 19:14:57 +03:00
|
|
|
return nil
|
2015-04-17 17:30:15 +03:00
|
|
|
}
|
|
|
|
|
2017-07-11 14:49:14 +03:00
|
|
|
func (t *BlockTest) validatePostState(statedb *state.StateDB) error {
|
2015-09-14 15:27:25 +03:00
|
|
|
// validate post state accounts in test file against what we have in state db
|
2017-07-11 14:49:14 +03:00
|
|
|
for addr, acct := range t.json.Post {
|
2015-03-20 10:10:13 +02:00
|
|
|
// address is indirectly verified by the other fields, as it's the db key
|
2017-07-11 14:49:14 +03:00
|
|
|
code2 := statedb.GetCode(addr)
|
2024-01-23 16:51:58 +03:00
|
|
|
balance2 := statedb.GetBalance(addr).ToBig()
|
2017-07-11 14:49:14 +03:00
|
|
|
nonce2 := statedb.GetNonce(addr)
|
|
|
|
if !bytes.Equal(code2, acct.Code) {
|
|
|
|
return fmt.Errorf("account code mismatch for addr: %s want: %v have: %s", addr, acct.Code, hex.EncodeToString(code2))
|
2015-03-20 10:10:13 +02:00
|
|
|
}
|
2017-07-11 14:49:14 +03:00
|
|
|
if balance2.Cmp(acct.Balance) != 0 {
|
|
|
|
return fmt.Errorf("account balance mismatch for addr: %s, want: %d, have: %d", addr, acct.Balance, balance2)
|
2015-03-20 10:10:13 +02:00
|
|
|
}
|
2017-07-11 14:49:14 +03:00
|
|
|
if nonce2 != acct.Nonce {
|
|
|
|
return fmt.Errorf("account nonce mismatch for addr: %s want: %d have: %d", addr, acct.Nonce, nonce2)
|
2015-03-20 10:10:13 +02:00
|
|
|
}
|
2023-11-17 17:56:21 +03:00
|
|
|
for k, v := range acct.Storage {
|
|
|
|
v2 := statedb.GetState(addr, k)
|
|
|
|
if v2 != v {
|
|
|
|
return fmt.Errorf("account storage mismatch for addr: %s, slot: %x, want: %x, have: %x", addr, k, v, v2)
|
|
|
|
}
|
|
|
|
}
|
2015-03-13 19:01:51 +02:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-07-11 14:49:14 +03:00
|
|
|
func (t *BlockTest) validateImportedHeaders(cm *core.BlockChain, validBlocks []btBlock) error {
|
2015-09-18 18:15:59 +03:00
|
|
|
// to get constant lookup when verifying block headers by hash (some tests have many blocks)
|
2017-07-11 14:49:14 +03:00
|
|
|
bmap := make(map[common.Hash]btBlock, len(t.json.Blocks))
|
2015-09-18 18:15:59 +03:00
|
|
|
for _, b := range validBlocks {
|
|
|
|
bmap[b.BlockHeader.Hash] = b
|
|
|
|
}
|
|
|
|
// iterate over blocks backwards from HEAD and validate imported
|
|
|
|
// headers vs test file. some tests have reorgs, and we import
|
|
|
|
// block-by-block, so we can only validate imported headers after
|
2017-07-11 14:49:14 +03:00
|
|
|
// all blocks have been processed by BlockChain, as they may not
|
2015-09-18 18:15:59 +03:00
|
|
|
// be part of the longest chain until last block is imported.
|
2023-03-02 09:29:15 +03:00
|
|
|
for b := cm.CurrentBlock(); b != nil && b.Number.Uint64() != 0; b = cm.GetBlockByHash(b.ParentHash).Header() {
|
|
|
|
if err := validateHeader(bmap[b.Hash()].BlockHeader, b); err != nil {
|
2019-11-23 14:51:37 +03:00
|
|
|
return fmt.Errorf("imported block header validation failed: %v", err)
|
2015-09-18 18:15:59 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-07-11 14:49:14 +03:00
|
|
|
func (bb *btBlock) decode() (*types.Block, error) {
|
|
|
|
data, err := hexutil.Decode(bb.Rlp)
|
2015-03-13 19:01:51 +02:00
|
|
|
if err != nil {
|
2015-06-11 01:11:30 +03:00
|
|
|
return nil, err
|
2015-03-13 19:01:51 +02:00
|
|
|
}
|
2017-07-11 14:49:14 +03:00
|
|
|
var b types.Block
|
|
|
|
err = rlp.DecodeBytes(data, &b)
|
|
|
|
return &b, err
|
2015-04-15 23:37:16 +03:00
|
|
|
}
|