Skip to content

Commit 3a95b1d

Browse files
committed
simulators/eth2/engine: Add test, several improvements
1 parent 7bfec36 commit 3a95b1d

File tree

7 files changed

+615
-166
lines changed

7 files changed

+615
-166
lines changed

simulators/eth2/engine/chain_generators.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package main
22

33
import (
4-
"crypto/rand"
5-
64
"github.com/ethereum/go-ethereum/consensus"
75
"github.com/ethereum/go-ethereum/consensus/ethash"
86
"github.com/ethereum/go-ethereum/core"
@@ -26,6 +24,8 @@ var PoWChainGeneratorDefaults = ethash.Config{
2624
type PoWChainGenerator struct {
2725
BlockCount int
2826
ethash.Config
27+
GenFunction func(int, *core.BlockGen)
28+
blocks []*types.Block
2929
}
3030

3131
// instaSeal wraps a consensus engine with instant block sealing. When a block is produced
@@ -46,16 +46,17 @@ func (e instaSeal) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header
4646
return <-sealedBlock, nil
4747
}
4848

49-
func (p PoWChainGenerator) Generate(genesis *setup.Eth1Genesis) ([]*types.Block, error) {
49+
func (p *PoWChainGenerator) Generate(genesis *setup.Eth1Genesis) ([]*types.Block, error) {
50+
// We generate a new chain only if the generator had not generated one already.
51+
// This is done because the chain generators can be reused on different clients to ensure
52+
// they start with the same chain.
53+
if p.blocks != nil {
54+
return p.blocks, nil
55+
}
5056
db := rawdb.NewMemoryDatabase()
5157
engine := ethash.New(p.Config, nil, false)
5258
insta := instaSeal{engine}
5359
genesisBlock := genesis.Genesis.ToBlock(db)
54-
gen := func(i int, blockGen *core.BlockGen) {
55-
data := make([]byte, 16)
56-
rand.Read(data)
57-
blockGen.SetExtra(data)
58-
}
59-
blocks, _ := core.GenerateChain(genesis.Genesis.Config, genesisBlock, insta, db, p.BlockCount, gen)
60-
return blocks, nil
60+
p.blocks, _ = core.GenerateChain(genesis.Genesis.Config, genesisBlock, insta, db, p.BlockCount, p.GenFunction)
61+
return p.blocks, nil
6162
}

simulators/eth2/engine/helper.go

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ type Config struct {
6969
SlotTime *big.Int
7070
TerminalTotalDifficulty *big.Int
7171
SafeSlotsToImportOptimistically *big.Int
72+
ExtraShares *big.Int
7273

7374
// Node configurations to launch. Each node as a proportional share of
7475
// validators.
@@ -104,6 +105,7 @@ func (a *Config) join(b *Config) *Config {
104105
c.SlotTime = choose(a.SlotTime, b.SlotTime)
105106
c.TerminalTotalDifficulty = choose(a.TerminalTotalDifficulty, b.TerminalTotalDifficulty)
106107
c.SafeSlotsToImportOptimistically = choose(a.SafeSlotsToImportOptimistically, b.SafeSlotsToImportOptimistically)
108+
c.ExtraShares = choose(a.ExtraShares, b.ExtraShares)
107109

108110
// EL config
109111
c.InitialBaseFeePerGas = choose(a.InitialBaseFeePerGas, b.InitialBaseFeePerGas)
@@ -560,9 +562,46 @@ func forkchoiceResponseSpoof(method string, status PayloadStatusV1, payloadID *P
560562
}, nil
561563
}
562564

565+
// List of Hashes that can be accessed concurrently
566+
type SyncHashes struct {
567+
Hashes []common.Hash
568+
Lock *sync.Mutex
569+
}
570+
571+
func NewSyncHashes(hashes ...common.Hash) *SyncHashes {
572+
newSyncHashes := &SyncHashes{
573+
Hashes: make([]common.Hash, 0),
574+
Lock: &sync.Mutex{},
575+
}
576+
for _, h := range hashes {
577+
newSyncHashes.Hashes = append(newSyncHashes.Hashes, h)
578+
}
579+
return newSyncHashes
580+
}
581+
582+
func (syncHashes *SyncHashes) Contains(hash common.Hash) bool {
583+
syncHashes.Lock.Lock()
584+
defer syncHashes.Lock.Unlock()
585+
if syncHashes.Hashes == nil {
586+
return false
587+
}
588+
for _, h := range syncHashes.Hashes {
589+
if h == hash {
590+
return true
591+
}
592+
}
593+
return false
594+
}
595+
596+
func (syncHashes *SyncHashes) Add(hash common.Hash) {
597+
syncHashes.Lock.Lock()
598+
defer syncHashes.Lock.Unlock()
599+
syncHashes.Hashes = append(syncHashes.Hashes, hash)
600+
}
601+
563602
// Generate a callback that invalidates either a call to `engine_forkchoiceUpdatedV1` or `engine_newPayloadV1`
564-
// if the hash of the payload matches the specified hash.
565-
func InvalidateExecutionPayloadByHash(method string, payloadHash common.Hash, called chan<- interface{}) func([]byte, []byte) *proxy.Spoof {
603+
// for all hashes with given exceptions, and a given LatestValidHash.
604+
func InvalidateExecutionPayloads(method string, exceptions *SyncHashes, latestValidHash *common.Hash, invalidated chan<- common.Hash) func([]byte, []byte) *proxy.Spoof {
566605
if method == EngineForkchoiceUpdatedV1 {
567606
return func(res []byte, req []byte) *proxy.Spoof {
568607
var (
@@ -575,18 +614,17 @@ func InvalidateExecutionPayloadByHash(method string, payloadHash common.Hash, ca
575614
if err != nil {
576615
panic(err)
577616
}
578-
if fcState.HeadBlockHash == payloadHash {
579-
zeroHash := common.Hash{}
617+
if !exceptions.Contains(fcState.HeadBlockHash) {
580618
spoof, err = forkchoiceResponseSpoof(EngineForkchoiceUpdatedV1, PayloadStatusV1{
581619
Status: Invalid,
582-
LatestValidHash: &zeroHash,
620+
LatestValidHash: latestValidHash,
583621
ValidationError: nil,
584622
}, nil)
585623
if err != nil {
586624
panic(err)
587625
}
588626
select {
589-
case called <- fcState:
627+
case invalidated <- fcState.HeadBlockHash:
590628
default:
591629
}
592630
return spoof
@@ -605,18 +643,17 @@ func InvalidateExecutionPayloadByHash(method string, payloadHash common.Hash, ca
605643
if err != nil {
606644
panic(err)
607645
}
608-
if payload.BlockHash == payloadHash {
609-
zeroHash := common.Hash{}
646+
if !exceptions.Contains(payload.BlockHash) {
610647
spoof, err = payloadStatusSpoof(EngineNewPayloadV1, &PayloadStatusV1{
611648
Status: Invalid,
612-
LatestValidHash: &zeroHash,
649+
LatestValidHash: latestValidHash,
613650
ValidationError: nil,
614651
})
615652
if err != nil {
616653
panic(err)
617654
}
618655
select {
619-
case called <- payload:
656+
case invalidated <- payload.BlockHash:
620657
default:
621658
}
622659
return spoof
@@ -713,8 +750,9 @@ func SlotsUntilBellatrix(genesisTime beacon.Timestamp, spec *beacon.Spec) beacon
713750
if currentTimestamp >= bellatrixTime {
714751
return beacon.Slot(0)
715752
}
716-
fmt.Printf("INFO: bellatrixTime:%d, currentTimestamp:%d\n", bellatrixTime, currentTimestamp)
717-
return beacon.Slot((bellatrixTime-currentTimestamp)/spec.SECONDS_PER_SLOT) + 1
753+
s := beacon.Slot((bellatrixTime-currentTimestamp)/spec.SECONDS_PER_SLOT) + 1
754+
fmt.Printf("INFO: bellatrixTime:%d, currentTimestamp:%d, slots=%d\n", bellatrixTime, currentTimestamp, s)
755+
return s
718756
}
719757

720758
func TimeUntilTerminalBlock(e *Eth1Node, c setup.Eth1Consensus, defaultTTD *big.Int, n node) uint64 {

simulators/eth2/engine/main.go

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ var (
1717
VAULT_KEY, _ = crypto.HexToECDSA("63b508a03c3b5937ceb903af8b1b0c191012ef6eb7e9c3fb7afa94e5d214d376")
1818
)
1919

20-
var tests = []testSpec{
20+
var engineTests = []testSpec{
2121
//{Name: "transition-testnet", Run: TransitionTestnet},
2222
{Name: "test-rpc-error", Run: TestRPCError},
2323
{Name: "block-latest-safe-finalized", Run: BlockLatestSafeFinalized},
@@ -28,7 +28,8 @@ var tests = []testSpec{
2828
{Name: "syncing-with-invalid-chain", Run: SyncingWithInvalidChain},
2929
{Name: "basefee-encoding-check", Run: BaseFeeEncodingCheck},
3030
{Name: "invalid-quantity-fields", Run: InvalidQuantityPayloadFields},
31-
31+
}
32+
var transitionTests = []testSpec{
3233
// Transition (TERMINAL_TOTAL_DIFFICULTY) tests
3334
{Name: "invalid-transition-payload", Run: InvalidPayloadGen(1, Invalid)},
3435
{Name: "unknown-pow-parent-transition-payload", Run: UnknownPoWParent},
@@ -40,14 +41,12 @@ var tests = []testSpec{
4041
{Name: "optimistic-syncing-with-valid-chain", Run: OptimisticSyncingWithValidChain},
4142
{Name: "syncing-with-chain-having-valid-transition-block", Run: SyncingWithChainHavingValidTransitionBlock},
4243
{Name: "syncing-with-chain-having-invalid-transition-block", Run: SyncingWithChainHavingInvalidTransitionBlock},
44+
{Name: "syncing-with-chain-having-invalid-post-transition-block", Run: SyncingWithChainHavingInvalidPostTransitionBlock},
45+
{Name: "re-org-and-sync-with-chain-having-invalid-terminal-block", Run: ReOrgSyncWithChainHavingInvalidTerminalBlock},
4346
}
4447

4548
func main() {
46-
// Create the test suite that will include all tests
47-
var suite = hivesim.Suite{
48-
Name: "eth2-engine",
49-
Description: `Collection of test vectors that use a ExecutionClient+BeaconNode+ValidatorClient testnet.`,
50-
}
49+
5150
// Create simulator that runs all tests
5251
sim := hivesim.New()
5352
// From the simulator we can get all client types provided
@@ -65,12 +64,27 @@ func main() {
6564
if len(c.Validator) != 1 {
6665
panic("choose 1 validator client type")
6766
}
68-
// Add all tests to the suite and then run it
69-
addAllTests(&suite, c)
70-
hivesim.MustRunSuite(sim, suite)
67+
// Create the test suites
68+
var (
69+
engineSuite = hivesim.Suite{
70+
Name: "eth2-engine",
71+
Description: `Collection of test vectors that use a ExecutionClient+BeaconNode+ValidatorClient testnet.`,
72+
}
73+
transitionSuite = hivesim.Suite{
74+
Name: "eth2-engine-transition",
75+
Description: `Collection of test vectors that use a ExecutionClient+BeaconNode+ValidatorClient transition testnet.`,
76+
}
77+
)
78+
// Add all tests to the suites
79+
addAllTests(&engineSuite, c, engineTests)
80+
addAllTests(&transitionSuite, c, transitionTests)
81+
82+
// Mark suites for execution
83+
hivesim.MustRunSuite(sim, engineSuite)
84+
hivesim.MustRunSuite(sim, transitionSuite)
7185
}
7286

73-
func addAllTests(suite *hivesim.Suite, c *ClientDefinitionsByRole) {
87+
func addAllTests(suite *hivesim.Suite, c *ClientDefinitionsByRole, tests []testSpec) {
7488
mnemonic := "couple kiwi radio river setup fortune hunt grief buddy forward perfect empty slim wear bounce drift execute nation tobacco dutch chapter festival ice fog"
7589

7690
// Generate validator keys to use for all tests.

0 commit comments

Comments
 (0)