Unverified Commit b818e73e authored by Martin Holst Swende's avatar Martin Holst Swende Committed by GitHub

tests: update tests (#26314)

This PR builds on #26299, but also updates the tests to the most recent version, which includes tests regarding TheMerge.

This change adds checks to the beacon consensus engine, making it more strict in validating the pre- and post-headers, and not relying on the caller to have already correctly sanitized the headers/blocks. 
parent 79a478bb
This diff is collapsed.
......@@ -230,7 +230,7 @@ func TestT8n(t *testing.T) {
{ // Test post-merge transition
base: "./testdata/24",
input: t8nInput{
"alloc.json", "txs.json", "env.json", "Merged", "",
"alloc.json", "txs.json", "env.json", "Merge", "",
},
output: t8nOutput{alloc: true, result: true},
expOut: "exp.json",
......@@ -238,7 +238,7 @@ func TestT8n(t *testing.T) {
{ // Test post-merge transition where input is missing random
base: "./testdata/24",
input: t8nInput{
"alloc.json", "txs.json", "env-missingrandom.json", "Merged", "",
"alloc.json", "txs.json", "env-missingrandom.json", "Merge", "",
},
output: t8nOutput{alloc: false, result: false},
expExitCode: 3,
......@@ -246,7 +246,7 @@ func TestT8n(t *testing.T) {
{ // Test base fee calculation
base: "./testdata/25",
input: t8nInput{
"alloc.json", "txs.json", "env.json", "Merged", "",
"alloc.json", "txs.json", "env.json", "Merge", "",
},
output: t8nOutput{alloc: true, result: true},
expOut: "exp.json",
......
This diff is collapsed.
......@@ -95,44 +95,71 @@ func (beacon *Beacon) VerifyHeader(chain consensus.ChainHeaderReader, header *ty
return beacon.verifyHeader(chain, header, parent)
}
// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers
// concurrently. The method returns a quit channel to abort the operations and
// a results channel to retrieve the async verifications.
// VerifyHeaders expect the headers to be ordered and continuous.
func (beacon *Beacon) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
if !beacon.IsPoSHeader(headers[len(headers)-1]) {
return beacon.ethone.VerifyHeaders(chain, headers, seals)
// errOut constructs an error channel with prefilled errors inside.
func errOut(n int, err error) chan error {
errs := make(chan error, n)
for i := 0; i < n; i++ {
errs <- err
}
return errs
}
// splitHeaders splits the provided header batch into two parts according to
// the configured ttd. It requires the parent of header batch along with its
// td are stored correctly in chain. If ttd is not configured yet, all headers
// will be treated legacy PoW headers.
// Note, this function will not verify the header validity but just split them.
func (beacon *Beacon) splitHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) ([]*types.Header, []*types.Header, error) {
// TTD is not defined yet, all headers should be in legacy format.
ttd := chain.Config().TerminalTotalDifficulty
if ttd == nil {
return headers, nil, nil
}
ptd := chain.GetTd(headers[0].ParentHash, headers[0].Number.Uint64()-1)
if ptd == nil {
return nil, nil, consensus.ErrUnknownAncestor
}
// The entire header batch already crosses the transition.
if ptd.Cmp(ttd) >= 0 {
return nil, headers, nil
}
var (
preHeaders []*types.Header
preHeaders = headers
postHeaders []*types.Header
preSeals []bool
td = new(big.Int).Set(ptd)
tdPassed bool
)
for index, header := range headers {
if beacon.IsPoSHeader(header) {
preHeaders = headers[:index]
postHeaders = headers[index:]
preSeals = seals[:index]
for i, header := range headers {
if tdPassed {
preHeaders = headers[:i]
postHeaders = headers[i:]
break
}
td = td.Add(td, header.Difficulty)
if td.Cmp(ttd) >= 0 {
// This is the last PoW header, it still belongs to
// the preHeaders, so we cannot split+break yet.
tdPassed = true
}
}
return preHeaders, postHeaders, nil
}
// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers
// concurrently. The method returns a quit channel to abort the operations and
// a results channel to retrieve the async verifications.
// VerifyHeaders expect the headers to be ordered and continuous.
func (beacon *Beacon) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
preHeaders, postHeaders, err := beacon.splitHeaders(chain, headers)
if err != nil {
return make(chan struct{}), errOut(len(headers), err)
}
if len(postHeaders) == 0 {
return beacon.ethone.VerifyHeaders(chain, headers, seals)
}
if len(preHeaders) == 0 {
// All the headers are pos headers. Verify that the parent block reached total terminal difficulty.
if reached, err := IsTTDReached(chain, headers[0].ParentHash, headers[0].Number.Uint64()-1); !reached {
// TTD not reached for the first block, mark subsequent with invalid terminal block
if err == nil {
err = consensus.ErrInvalidTerminalBlock
}
results := make(chan error, len(headers))
for i := 0; i < len(headers); i++ {
results <- err
}
return make(chan struct{}), results
}
return beacon.verifyHeaders(chain, headers, nil)
}
// The transition point exists in the middle, separate the headers
// into two batches and apply different verification rules for them.
var (
......@@ -144,16 +171,9 @@ func (beacon *Beacon) VerifyHeaders(chain consensus.ChainHeaderReader, headers [
old, new, out = 0, len(preHeaders), 0
errors = make([]error, len(headers))
done = make([]bool, len(headers))
oldDone, oldResult = beacon.ethone.VerifyHeaders(chain, preHeaders, preSeals)
oldDone, oldResult = beacon.ethone.VerifyHeaders(chain, preHeaders, seals[:len(preHeaders)])
newDone, newResult = beacon.verifyHeaders(chain, postHeaders, preHeaders[len(preHeaders)-1])
)
// Verify that pre-merge headers don't overflow the TTD
if index, err := verifyTerminalPoWBlock(chain, preHeaders); err != nil {
// Mark all subsequent pow headers with the error.
for i := index; i < len(preHeaders); i++ {
errors[i], done[i] = err, true
}
}
// Collect the results
for {
for ; done[out]; out++ {
......@@ -181,33 +201,6 @@ func (beacon *Beacon) VerifyHeaders(chain consensus.ChainHeaderReader, headers [
return abort, results
}
// verifyTerminalPoWBlock verifies that the preHeaders conform to the specification
// wrt. their total difficulty.
// It expects:
// - preHeaders to be at least 1 element
// - the parent of the header element to be stored in the chain correctly
// - the preHeaders to have a set difficulty
// - the last element to be the terminal block
func verifyTerminalPoWBlock(chain consensus.ChainHeaderReader, preHeaders []*types.Header) (int, error) {
td := chain.GetTd(preHeaders[0].ParentHash, preHeaders[0].Number.Uint64()-1)
if td == nil {
return 0, consensus.ErrUnknownAncestor
}
td = new(big.Int).Set(td)
// Check that all blocks before the last one are below the TTD
for i, head := range preHeaders {
if td.Cmp(chain.Config().TerminalTotalDifficulty) >= 0 {
return i, consensus.ErrInvalidTerminalBlock
}
td.Add(td, head.Difficulty)
}
// Check that the last block is the terminal block
if td.Cmp(chain.Config().TerminalTotalDifficulty) < 0 {
return len(preHeaders) - 1, consensus.ErrInvalidTerminalBlock
}
return 0, nil
}
// VerifyUncles verifies that the given block's uncles conform to the consensus
// rules of the Ethereum consensus engine.
func (beacon *Beacon) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
......@@ -419,11 +412,11 @@ func (beacon *Beacon) SetThreads(threads int) {
// IsTTDReached checks if the TotalTerminalDifficulty has been surpassed on the `parentHash` block.
// It depends on the parentHash already being stored in the database.
// If the parentHash is not stored in the database a UnknownAncestor error is returned.
func IsTTDReached(chain consensus.ChainHeaderReader, parentHash common.Hash, number uint64) (bool, error) {
func IsTTDReached(chain consensus.ChainHeaderReader, parentHash common.Hash, parentNumber uint64) (bool, error) {
if chain.Config().TerminalTotalDifficulty == nil {
return false, nil
}
td := chain.GetTd(parentHash, number)
td := chain.GetTd(parentHash, parentNumber)
if td == nil {
return false, consensus.ErrUnknownAncestor
}
......
package beacon
import (
"fmt"
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
)
type mockChain struct {
config *params.ChainConfig
tds map[uint64]*big.Int
}
func newMockChain() *mockChain {
return &mockChain{
config: new(params.ChainConfig),
tds: make(map[uint64]*big.Int),
}
}
func (m *mockChain) Config() *params.ChainConfig {
return m.config
}
func (m *mockChain) CurrentHeader() *types.Header { panic("not implemented") }
func (m *mockChain) GetHeader(hash common.Hash, number uint64) *types.Header {
panic("not implemented")
}
func (m *mockChain) GetHeaderByNumber(number uint64) *types.Header { panic("not implemented") }
func (m *mockChain) GetHeaderByHash(hash common.Hash) *types.Header { panic("not implemented") }
func (m *mockChain) GetTd(hash common.Hash, number uint64) *big.Int {
num, ok := m.tds[number]
if ok {
return new(big.Int).Set(num)
}
return nil
}
func TestVerifyTerminalBlock(t *testing.T) {
chain := newMockChain()
chain.tds[0] = big.NewInt(10)
chain.config.TerminalTotalDifficulty = big.NewInt(50)
tests := []struct {
preHeaders []*types.Header
ttd *big.Int
err error
index int
}{
// valid ttd
{
preHeaders: []*types.Header{
{Number: big.NewInt(1), Difficulty: big.NewInt(10)},
{Number: big.NewInt(2), Difficulty: big.NewInt(10)},
{Number: big.NewInt(3), Difficulty: big.NewInt(10)},
{Number: big.NewInt(4), Difficulty: big.NewInt(10)},
},
ttd: big.NewInt(50),
},
// last block doesn't reach ttd
{
preHeaders: []*types.Header{
{Number: big.NewInt(1), Difficulty: big.NewInt(10)},
{Number: big.NewInt(2), Difficulty: big.NewInt(10)},
{Number: big.NewInt(3), Difficulty: big.NewInt(10)},
{Number: big.NewInt(4), Difficulty: big.NewInt(9)},
},
ttd: big.NewInt(50),
err: consensus.ErrInvalidTerminalBlock,
index: 3,
},
// two blocks reach ttd
{
preHeaders: []*types.Header{
{Number: big.NewInt(1), Difficulty: big.NewInt(10)},
{Number: big.NewInt(2), Difficulty: big.NewInt(10)},
{Number: big.NewInt(3), Difficulty: big.NewInt(20)},
{Number: big.NewInt(4), Difficulty: big.NewInt(10)},
},
ttd: big.NewInt(50),
err: consensus.ErrInvalidTerminalBlock,
index: 3,
},
// three blocks reach ttd
{
preHeaders: []*types.Header{
{Number: big.NewInt(1), Difficulty: big.NewInt(10)},
{Number: big.NewInt(2), Difficulty: big.NewInt(10)},
{Number: big.NewInt(3), Difficulty: big.NewInt(20)},
{Number: big.NewInt(4), Difficulty: big.NewInt(10)},
{Number: big.NewInt(4), Difficulty: big.NewInt(10)},
},
ttd: big.NewInt(50),
err: consensus.ErrInvalidTerminalBlock,
index: 3,
},
// parent reached ttd
{
preHeaders: []*types.Header{
{Number: big.NewInt(1), Difficulty: big.NewInt(10)},
},
ttd: big.NewInt(9),
err: consensus.ErrInvalidTerminalBlock,
index: 0,
},
// unknown parent
{
preHeaders: []*types.Header{
{Number: big.NewInt(4), Difficulty: big.NewInt(10)},
},
ttd: big.NewInt(9),
err: consensus.ErrUnknownAncestor,
index: 0,
},
}
for i, test := range tests {
fmt.Printf("Test: %v\n", i)
chain.config.TerminalTotalDifficulty = test.ttd
index, err := verifyTerminalPoWBlock(chain, test.preHeaders)
if err != test.err {
t.Fatalf("Invalid error encountered, expected %v got %v", test.err, err)
}
if index != test.index {
t.Fatalf("Invalid index, expected %v got %v", test.index, index)
}
}
}
......@@ -17,7 +17,6 @@
package core
import (
"encoding/json"
"math/big"
"runtime"
"testing"
......@@ -135,31 +134,29 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
config := *params.TestChainConfig
gspec = &Genesis{Config: &config}
engine = beacon.New(ethash.NewFaker())
td := 0
td := int(params.GenesisDifficulty.Uint64())
genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 8, nil)
for _, block := range preBlocks {
for _, block := range blocks {
// calculate td
td += int(block.Difficulty().Uint64())
}
preBlocks = blocks
gspec.Config.TerminalTotalDifficulty = big.NewInt(int64(td))
postBlocks, _ = GenerateChain(gspec.Config, preBlocks[len(preBlocks)-1], engine, genDb, 8, nil)
t.Logf("Set ttd to %v\n", gspec.Config.TerminalTotalDifficulty)
postBlocks, _ = GenerateChain(gspec.Config, preBlocks[len(preBlocks)-1], engine, genDb, 8, func(i int, gen *BlockGen) {
gen.SetPoS()
})
}
// Assemble header batch
preHeaders := make([]*types.Header, len(preBlocks))
for i, block := range preBlocks {
preHeaders[i] = block.Header()
blob, _ := json.Marshal(block.Header())
t.Logf("Log header before the merging %d: %v", block.NumberU64(), string(blob))
t.Logf("Pre-merge header: %d", block.NumberU64())
}
postHeaders := make([]*types.Header, len(postBlocks))
for i, block := range postBlocks {
postHeaders[i] = block.Header()
blob, _ := json.Marshal(block.Header())
t.Logf("Log header after the merging %d: %v", block.NumberU64(), string(blob))
t.Logf("Post-merge header: %d", block.NumberU64())
}
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil)
......@@ -172,15 +169,15 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
select {
case result := <-results:
if result != nil {
t.Errorf("test %d: verification failed %v", i, result)
t.Errorf("pre-block %d: verification failed %v", i, result)
}
case <-time.After(time.Second):
t.Fatalf("test %d: verification timeout", i)
t.Fatalf("pre-block %d: verification timeout", i)
}
// Make sure no more data is returned
select {
case result := <-results:
t.Fatalf("test %d: unexpected result returned: %v", i, result)
t.Fatalf("pre-block %d: unexpected result returned: %v", i, result)
case <-time.After(25 * time.Millisecond):
}
chain.InsertChain(preBlocks[i : i+1])
......@@ -197,7 +194,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
select {
case result := <-results:
if result != nil {
t.Errorf("test %d: verification failed %v", i, result)
t.Errorf("post-block %d: verification failed %v", i, result)
}
case <-time.After(time.Second):
t.Fatalf("test %d: verification timeout", i)
......@@ -205,7 +202,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
// Make sure no more data is returned
select {
case result := <-results:
t.Fatalf("test %d: unexpected result returned: %v", i, result)
t.Fatalf("post-block %d: unexpected result returned: %v", i, result)
case <-time.After(25 * time.Millisecond):
}
chain.InsertBlockWithoutSetHead(postBlocks[i])
......
......@@ -1959,7 +1959,8 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
Alloc: GenesisAlloc{addr: {Balance: big.NewInt(math.MaxInt64)}},
BaseFee: big.NewInt(params.InitialBaseFee),
}
signer = types.LatestSigner(gspec.Config)
signer = types.LatestSigner(gspec.Config)
mergeBlock = math.MaxInt32
)
// Generate and import the canonical chain
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil)
......@@ -1970,6 +1971,7 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
// Activate the transition since genesis if required
if mergePoint == 0 {
mergeBlock = 0
merger.ReachTTD()
merger.FinalizePoS()
......@@ -1982,6 +1984,9 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
t.Fatalf("failed to create tx: %v", err)
}
gen.AddTx(tx)
if int(gen.header.Number.Uint64()) >= mergeBlock {
gen.SetPoS()
}
nonce++
})
if n, err := chain.InsertChain(blocks); err != nil {
......@@ -2006,7 +2011,10 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
merger.ReachTTD()
merger.FinalizePoS()
// Set the terminal total difficulty in the config
gspec.Config.TerminalTotalDifficulty = big.NewInt(int64(len(blocks)))
ttd := big.NewInt(int64(len(blocks)))
ttd.Mul(ttd, params.GenesisDifficulty)
gspec.Config.TerminalTotalDifficulty = ttd
mergeBlock = len(blocks)
}
// Generate the sidechain
......@@ -2018,6 +2026,9 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
parent := blocks[parentIndex]
fork, _ := GenerateChain(gspec.Config, parent, engine, genDb, 2*TriesInMemory, func(i int, b *BlockGen) {
b.SetCoinbase(common.Address{2})
if int(b.header.Number.Uint64()) >= mergeBlock {
b.SetPoS()
}
})
// Prepend the parent(s)
var sidechain []*types.Block
......@@ -2226,25 +2237,45 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
BaseFee: big.NewInt(params.InitialBaseFee),
Config: &chainConfig,
}
engine = beacon.New(ethash.NewFaker())
engine = beacon.New(ethash.NewFaker())
mergeBlock = uint64(math.MaxUint64)
)
// Apply merging since genesis
if mergeHeight == 0 {
genesis.Config.TerminalTotalDifficulty = big.NewInt(0)
mergeBlock = uint64(0)
}
genDb, blocks, receipts := GenerateChainWithGenesis(genesis, engine, 32, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
genDb, blocks, receipts := GenerateChainWithGenesis(genesis, engine, 32,
func(i int, b *BlockGen) {
if b.header.Number.Uint64() >= mergeBlock {
b.SetPoS()
}
b.SetCoinbase(common.Address{1})
})
// Apply merging after the first segment
if mergeHeight == 1 {
genesis.Config.TerminalTotalDifficulty = big.NewInt(int64(len(blocks)))
// TTD is genesis diff + blocks
ttd := big.NewInt(1 + int64(len(blocks)))
ttd.Mul(ttd, params.GenesisDifficulty)
genesis.Config.TerminalTotalDifficulty = ttd
mergeBlock = uint64(len(blocks))
}
// Longer chain and shorter chain
blocks2, receipts2 := GenerateChain(genesis.Config, blocks[len(blocks)-1], engine, genDb, 65, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
blocks2, receipts2 := GenerateChain(genesis.Config, blocks[len(blocks)-1], engine, genDb, 65, func(i int, b *BlockGen) {
b.SetCoinbase(common.Address{1})
if b.header.Number.Uint64() >= mergeBlock {
b.SetPoS()
}
})
blocks3, receipts3 := GenerateChain(genesis.Config, blocks[len(blocks)-1], engine, genDb, 64, func(i int, b *BlockGen) {
b.SetCoinbase(common.Address{1})
b.OffsetTime(-9) // Time shifted, difficulty shouldn't be changed
if b.header.Number.Uint64() >= mergeBlock {
b.SetPoS()
}
})
// Import the shared chain and the original canonical one
chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false)
if err != nil {
......@@ -2268,7 +2299,10 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
for _, block := range blocks {
headers = append(headers, block.Header())
}
_, err := chain.InsertHeaderChain(headers, 1)
i, err := chain.InsertHeaderChain(headers, 1)
if err != nil {
return fmt.Errorf("index %d, number %d: %w", i, headers[i].Number, err)
}
return err
}
asserter = func(t *testing.T, block *types.Block) {
......@@ -2282,9 +2316,9 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
for _, block := range blocks {
headers = append(headers, block.Header())
}
_, err := chain.InsertHeaderChain(headers, 1)
i, err := chain.InsertHeaderChain(headers, 1)
if err != nil {
return err
return fmt.Errorf("index %d: %w", i, err)
}
_, err = chain.InsertReceiptChain(blocks, receipts, 0)
return err
......@@ -2296,8 +2330,11 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
}
} else {
inserter = func(blocks []*types.Block, receipts []types.Receipts) error {
_, err := chain.InsertChain(blocks)
return err
i, err := chain.InsertChain(blocks)
if err != nil {
return fmt.Errorf("index %d: %w", i, err)
}
return nil
}
asserter = func(t *testing.T, block *types.Block) {
if chain.CurrentBlock().Hash() != block.Hash() {
......
......@@ -80,6 +80,11 @@ func (b *BlockGen) SetDifficulty(diff *big.Int) {
b.header.Difficulty = diff
}
// SetPos makes the header a PoS-header (0 difficulty)
func (b *BlockGen) SetPoS() {
b.header.Difficulty = new(big.Int)
}
// addTx adds a transaction to the generated block. If no coinbase has
// been set, the block's coinbase is set to the zero address.
//
......
......@@ -852,11 +852,11 @@ func TestInvalidBloom(t *testing.T) {
func TestNewPayloadOnInvalidTerminalBlock(t *testing.T) {
genesis, preMergeBlocks := generatePreMergeChain(100)
genesis.Config.TerminalTotalDifficulty = preMergeBlocks[0].Difficulty() //.Sub(genesis.Config.TerminalTotalDifficulty, preMergeBlocks[len(preMergeBlocks)-1].Difficulty())
n, ethservice := startEthService(t, genesis, preMergeBlocks)
defer n.Close()
genesis.Config.TerminalTotalDifficulty = preMergeBlocks[0].Difficulty() //.Sub(genesis.Config.TerminalTotalDifficulty, preMergeBlocks[len(preMergeBlocks)-1].Difficulty())
var (
api = NewConsensusAPI(ethservice)
parent = preMergeBlocks[len(preMergeBlocks)-1]
......
......@@ -44,7 +44,7 @@ var (
testBalance = big.NewInt(2e18)
)
func generatePreMergeChain(n int) (*core.Genesis, []*types.Header, []*types.Block) {
func generatePreMergeChain(pre, post int) (*core.Genesis, []*types.Header, []*types.Block, []*types.Header, []*types.Block) {
config := *params.AllEthashProtocolChanges
genesis := &core.Genesis{
Config: &config,
......@@ -53,21 +53,33 @@ func generatePreMergeChain(n int) (*core.Genesis, []*types.Header, []*types.Bloc
Timestamp: 9000,
BaseFee: big.NewInt(params.InitialBaseFee),
}
_, blocks, _ := core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), n, nil)
totalDifficulty := big.NewInt(0)
// Pre-merge blocks
db, preBLocks, _ := core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), pre, nil)
totalDifficulty := new(big.Int).Set(params.GenesisDifficulty)
var headers []*types.Header
for _, b := range blocks {
var preHeaders []*types.Header
for _, b := range preBLocks {
totalDifficulty.Add(totalDifficulty, b.Difficulty())
headers = append(headers, b.Header())
preHeaders = append(preHeaders, b.Header())
}
config.TerminalTotalDifficulty = totalDifficulty
// Post-merge blocks
postBlocks, _ := core.GenerateChain(genesis.Config,
preBLocks[len(preBLocks)-1], ethash.NewFaker(), db, post,
func(i int, b *core.BlockGen) {
b.SetPoS()
})
return genesis, headers, blocks
var postHeaders []*types.Header
for _, b := range postBlocks {
postHeaders = append(postHeaders, b.Header())
}
return genesis, preHeaders, preBLocks, postHeaders, postBlocks
}
func TestSetHeadBeforeTotalDifficulty(t *testing.T) {
genesis, headers, blocks := generatePreMergeChain(10)
genesis, headers, blocks, _, _ := generatePreMergeChain(10, 0)
n, lesService := startLesService(t, genesis, headers)
defer n.Close()
......@@ -83,21 +95,21 @@ func TestSetHeadBeforeTotalDifficulty(t *testing.T) {
}
func TestExecutePayloadV1(t *testing.T) {
genesis, headers, blocks := generatePreMergeChain(10)
n, lesService := startLesService(t, genesis, headers[:9])
genesis, headers, _, _, postBlocks := generatePreMergeChain(10, 2)
n, lesService := startLesService(t, genesis, headers)
lesService.Merger().ReachTTD()
defer n.Close()
api := NewConsensusAPI(lesService)
fcState := beacon.ForkchoiceStateV1{
HeadBlockHash: blocks[8].Hash(),
HeadBlockHash: postBlocks[0].Hash(),
SafeBlockHash: common.Hash{},
FinalizedBlockHash: common.Hash{},
}
if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
t.Errorf("Failed to update head %v", err)
}
block := blocks[9]
block := postBlocks[0]
fakeBlock := types.NewBlock(&types.Header{
ParentHash: block.ParentHash(),
......
......@@ -46,6 +46,7 @@ func TestBlockchain(t *testing.T) {
// 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.*`)
bt.walk(t, blockTestDir, func(t *testing.T, name string, test *BlockTest) {
if err := bt.checkFailure(t, test.Run(false)); err != nil {
t.Errorf("test without snapshotter failed: %v", err)
......
......@@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/beacon"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
......@@ -120,6 +121,9 @@ func (t *BlockTest) Run(snapshotter bool) error {
} else {
engine = ethash.NewShared()
}
// Wrap the original engine within the beacon-engine
engine = beacon.New(engine)
cache := &core.CacheConfig{TrieCleanLimit: 0}
if snapshotter {
cache.SnapshotLimit = 1
......
......@@ -197,6 +197,24 @@ var Forks = map[string]*params.ChainConfig{
LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0),
},
"ArrowGlacierToMergeAtDiffC0000": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0),
MergeNetsplitBlock: big.NewInt(0),
TerminalTotalDifficulty: big.NewInt(0xC0000),
},
"GrayGlacier": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
......@@ -213,7 +231,7 @@ var Forks = map[string]*params.ChainConfig{
ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0),
},
"Merged": {
"Merge": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
......
......@@ -56,14 +56,12 @@ func TestState(t *testing.T) {
// Uses 1GB RAM per tested fork
st.skipLoad(`^stStaticCall/static_Call1MB`)
// Not yet supported TODO
st.skipLoad(`^stEIP3540/`)
st.skipLoad(`^stEIP3860/`)
// Broken tests:
// Expected failures:
// st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/Byzantium/0`, "bug in test")
// st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/Byzantium/3`, "bug in test")
// st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/Constantinople/0`, "bug in test")
// st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/Constantinople/3`, "bug in test")
// st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/ConstantinopleFix/0`, "bug in test")
// st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/ConstantinopleFix/3`, "bug in test")
// For Istanbul, older tests were moved into LegacyTests
for _, dir := range []string{
......
......@@ -249,10 +249,16 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
context.GetHash = vmTestBlockHash
context.BaseFee = baseFee
context.Random = nil
if config.IsLondon(new(big.Int)) && t.json.Env.Random != nil {
rnd := common.BigToHash(t.json.Env.Random)
context.Random = &rnd
if config.IsLondon(new(big.Int)) {
if t.json.Env.Random != nil {
rnd := common.BigToHash(t.json.Env.Random)
context.Random = &rnd
}
context.Difficulty = big.NewInt(0)
} else {
if t.json.Env.Difficulty != nil {
context.Difficulty = new(big.Int).Set(t.json.Env.Difficulty)
}
}
evm := vm.NewEVM(context, txContext, statedb, config, vmconfig)
// Execute the message.
......
Subproject commit a380655e5ffab1a5ea0f4d860224bdb19013f06a
Subproject commit 24fa31adb30f71ee700b27decb5204e53a11d9f3
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment