Skip to content

Commit

Permalink
simulators/ethereum/engine: Add randomness seed input (ethereum#944)
Browse files Browse the repository at this point in the history
* simulators/ethereum/engine: randomness seed input

* simulators/ethereum/engine: Handle zero HIVE_RANDOM_SEED
  • Loading branch information
marioevz authored and Eikix committed Mar 1, 2024
1 parent 3fe3360 commit 74a3253
Show file tree
Hide file tree
Showing 15 changed files with 94 additions and 81 deletions.
13 changes: 6 additions & 7 deletions simulators/ethereum/engine/clmock/clmock.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,12 @@ type CLMocker struct {
// Global context which all procedures shall stop
TestContext context.Context
TimeoutContext context.Context
}

func NewCLMocker(t *hivesim.T, genesis *core.Genesis, forkConfig *config.ForkConfig) *CLMocker {
// Init random seed for different purposes
seed := time.Now().Unix()
t.Logf("Randomness seed: %v\n", seed)
rand.Seed(seed)
// Randomness source used to generate prevRandao
Rand *rand.Rand
}

func NewCLMocker(t *hivesim.T, genesis *core.Genesis, forkConfig *config.ForkConfig, randSource *rand.Rand) *CLMocker {
// Create the new CL mocker
newCLMocker := &CLMocker{
T: t,
Expand Down Expand Up @@ -161,6 +159,7 @@ func NewCLMocker(t *hivesim.T, genesis *core.Genesis, forkConfig *config.ForkCon
ForkConfig: forkConfig,
Genesis: genesis,
TestContext: context.Background(),
Rand: randSource,
}

// Create header history
Expand Down Expand Up @@ -420,7 +419,7 @@ func TimestampToBeaconRoot(timestamp uint64) common.Hash {
func (cl *CLMocker) GeneratePayloadAttributes() {
// Generate a random value for the PrevRandao field
nextPrevRandao := common.Hash{}
rand.Read(nextPrevRandao[:])
cl.Rand.Read(nextPrevRandao[:])

cl.LatestPayloadAttributes = typ.PayloadAttributes{
Random: nextPrevRandao,
Expand Down
34 changes: 17 additions & 17 deletions simulators/ethereum/engine/helper/customizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,17 +209,17 @@ func (customizer *DowngradeForkchoiceUpdatedVersion) ForkchoiceUpdatedVersion(he
var _ ForkchoiceUpdatedCustomizer = (*DowngradeForkchoiceUpdatedVersion)(nil)

type PayloadCustomizer interface {
CustomizePayload(basePayload *typ.ExecutableData) (*typ.ExecutableData, error)
CustomizePayload(randSource *rand.Rand, basePayload *typ.ExecutableData) (*typ.ExecutableData, error)
GetTimestamp(basePayload *typ.ExecutableData) (uint64, error)
}

type VersionedHashesCustomizer interface {
GetVersionedHashes(baseVesionedHashes *[]common.Hash) (*[]common.Hash, error)
GetVersionedHashes(randSource *rand.Rand, baseVesionedHashes *[]common.Hash) (*[]common.Hash, error)
}

type IncreaseVersionVersionedHashes struct{}

func (customizer *IncreaseVersionVersionedHashes) GetVersionedHashes(baseVesionedHashes *[]common.Hash) (*[]common.Hash, error) {
func (customizer *IncreaseVersionVersionedHashes) GetVersionedHashes(_ *rand.Rand, baseVesionedHashes *[]common.Hash) (*[]common.Hash, error) {
if baseVesionedHashes == nil {
return nil, fmt.Errorf("no versioned hashes available for modification")
}
Expand All @@ -236,7 +236,7 @@ func (customizer *IncreaseVersionVersionedHashes) GetVersionedHashes(baseVesione

type CorruptVersionedHashes struct{}

func (customizer *CorruptVersionedHashes) GetVersionedHashes(baseVesionedHashes *[]common.Hash) (*[]common.Hash, error) {
func (customizer *CorruptVersionedHashes) GetVersionedHashes(_ *rand.Rand, baseVesionedHashes *[]common.Hash) (*[]common.Hash, error) {
if baseVesionedHashes == nil {
return nil, fmt.Errorf("no versioned hashes available for modification")
}
Expand All @@ -253,7 +253,7 @@ func (customizer *CorruptVersionedHashes) GetVersionedHashes(baseVesionedHashes

type RemoveVersionedHash struct{}

func (customizer *RemoveVersionedHash) GetVersionedHashes(baseVesionedHashes *[]common.Hash) (*[]common.Hash, error) {
func (customizer *RemoveVersionedHash) GetVersionedHashes(_ *rand.Rand, baseVesionedHashes *[]common.Hash) (*[]common.Hash, error) {
if baseVesionedHashes == nil {
return nil, fmt.Errorf("no versioned hashes available for modification")
}
Expand All @@ -272,14 +272,14 @@ func (customizer *RemoveVersionedHash) GetVersionedHashes(baseVesionedHashes *[]

type ExtraVersionedHash struct{}

func (customizer *ExtraVersionedHash) GetVersionedHashes(baseVesionedHashes *[]common.Hash) (*[]common.Hash, error) {
func (customizer *ExtraVersionedHash) GetVersionedHashes(randSource *rand.Rand, baseVesionedHashes *[]common.Hash) (*[]common.Hash, error) {
if baseVesionedHashes == nil {
return nil, fmt.Errorf("no versioned hashes available for modification")
}
result := make([]common.Hash, len(*baseVesionedHashes)+1)
copy(result, *baseVesionedHashes)
extraHash := common.Hash{}
rand.Read(extraHash[:])
randSource.Read(extraHash[:])
extraHash[0] = cancun.BLOB_COMMITMENT_VERSION_KZG
result[len(result)-1] = extraHash

Expand Down Expand Up @@ -330,7 +330,7 @@ func (customData *CustomPayloadData) GetTimestamp(basePayload *typ.ExecutableDat

// Construct a customized payload by taking an existing payload as base and mixing it CustomPayloadData
// BlockHash is calculated automatically.
func (customData *CustomPayloadData) CustomizePayload(basePayload *typ.ExecutableData) (*typ.ExecutableData, error) {
func (customData *CustomPayloadData) CustomizePayload(randSource *rand.Rand, basePayload *typ.ExecutableData) (*typ.ExecutableData, error) {
txs := basePayload.Transactions
if customData.Transactions != nil {
txs = *customData.Transactions
Expand Down Expand Up @@ -460,7 +460,7 @@ func (customData *CustomPayloadData) CustomizePayload(basePayload *typ.Executabl
}

if customData.VersionedHashesCustomizer != nil {
result.VersionedHashes, err = customData.VersionedHashesCustomizer.GetVersionedHashes(basePayload.VersionedHashes)
result.VersionedHashes, err = customData.VersionedHashesCustomizer.GetVersionedHashes(randSource, basePayload.VersionedHashes)
if err != nil {
return nil, err
}
Expand All @@ -486,11 +486,11 @@ func (customizer *BaseNewPayloadVersionCustomizer) SetEngineAPIVersionResolver(v
customizer.EngineAPIVersionResolver = v
}

func (customNewPayload *BaseNewPayloadVersionCustomizer) CustomizePayload(basePayload *typ.ExecutableData) (*typ.ExecutableData, error) {
func (customNewPayload *BaseNewPayloadVersionCustomizer) CustomizePayload(randSource *rand.Rand, basePayload *typ.ExecutableData) (*typ.ExecutableData, error) {
if customNewPayload.PayloadCustomizer == nil {
return basePayload, nil
}
return customNewPayload.PayloadCustomizer.CustomizePayload(basePayload)
return customNewPayload.PayloadCustomizer.CustomizePayload(randSource, basePayload)
}

func (customNewPayload *BaseNewPayloadVersionCustomizer) GetExpectedError() (*int, error) {
Expand Down Expand Up @@ -527,7 +527,7 @@ func (customNewPayload *DowngradeNewPayloadVersion) NewPayloadVersion(timestamp
return version - 1
}

func CustomizePayloadTransactions(basePayload *typ.ExecutableData, customTransactions types.Transactions) (*typ.ExecutableData, error) {
func CustomizePayloadTransactions(randSource *rand.Rand, basePayload *typ.ExecutableData, customTransactions types.Transactions) (*typ.ExecutableData, error) {
byteTxs := make([][]byte, 0)
for _, tx := range customTransactions {
bytes, err := tx.MarshalBinary()
Expand All @@ -538,7 +538,7 @@ func CustomizePayloadTransactions(basePayload *typ.ExecutableData, customTransac
}
return (&CustomPayloadData{
Transactions: &byteTxs,
}).CustomizePayload(basePayload)
}).CustomizePayload(randSource, basePayload)
}

func (customData *CustomPayloadData) String() string {
Expand Down Expand Up @@ -590,7 +590,7 @@ func (customData *CustomPayloadData) String() string {

// This function generates an invalid payload by taking a base payload and modifying the specified field such that it ends up being invalid.
// One small consideration is that the payload needs to contain transactions and specially transactions using the PREVRANDAO opcode for all the fields to be compatible with this function.
func GenerateInvalidPayload(basePayload *typ.ExecutableData, payloadField InvalidPayloadBlockField) (*typ.ExecutableData, error) {
func GenerateInvalidPayload(randSource *rand.Rand, basePayload *typ.ExecutableData, payloadField InvalidPayloadBlockField) (*typ.ExecutableData, error) {

var customPayloadMod *CustomPayloadData
switch payloadField {
Expand Down Expand Up @@ -636,7 +636,7 @@ func GenerateInvalidPayload(basePayload *typ.ExecutableData, payloadField Invali
// This option potentially requires a transaction that uses the PREVRANDAO opcode.
// Otherwise the payload will still be valid.
modPrevRandao := common.Hash{}
rand.Read(modPrevRandao[:])
randSource.Read(modPrevRandao[:])
customPayloadMod = &CustomPayloadData{
PrevRandao: &modPrevRandao,
}
Expand Down Expand Up @@ -781,15 +781,15 @@ func GenerateInvalidPayload(basePayload *typ.ExecutableData, payloadField Invali
return &copyPayload, nil
}

return customPayloadMod.CustomizePayload(basePayload)
return customPayloadMod.CustomizePayload(randSource, basePayload)
}

/*
Generates an alternative withdrawals list that contains the same
amounts and accounts, but the order in the list is different, so
stateRoot of the resulting payload should be the same.
*/
func RandomizeWithdrawalsOrder(src types.Withdrawals) types.Withdrawals {
func RandomizeWithdrawalsOrder(rand *rand.Rand, src types.Withdrawals) types.Withdrawals {
dest := make(types.Withdrawals, len(src))
perm := rand.Perm(len(src))
for i, v := range perm {
Expand Down
14 changes: 13 additions & 1 deletion simulators/ethereum/engine/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"fmt"
"math/big"
"math/rand"
"os"
"strconv"
"sync"
Expand Down Expand Up @@ -105,7 +106,17 @@ func makeRunner(tests []test.Spec, nodeType string) func(t *hivesim.T) {
parallelism = p
}
}
t.Log("parallelism:", parallelism)
t.Log("parallelism", parallelism)

random_seed := time.Now().Unix()
if val, ok := os.LookupEnv("HIVE_RANDOM_SEED"); ok {
if p, err := strconv.Atoi(val); err != nil {
t.Logf("Warning: invalid HIVE_RANDOM_SEED value %q", val)
} else if p > 0 {
random_seed = int64(p)
}
}
t.Log("random_seed", random_seed)

var wg sync.WaitGroup
var testCh = make(chan hivesim.TestSpec)
Expand Down Expand Up @@ -214,6 +225,7 @@ func makeRunner(tests []test.Spec, nodeType string) func(t *hivesim.T) {
t,
c,
genesis,
rand.New(rand.NewSource(random_seed)),
newParams,
testFiles,
)
Expand Down
7 changes: 4 additions & 3 deletions simulators/ethereum/engine/suites/cancun/steps.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"fmt"
"math/big"
"math/rand"
"sync"
"time"

Expand Down Expand Up @@ -144,7 +145,7 @@ type VersionedHashes struct {
HashVersions []byte
}

func (v *VersionedHashes) GetVersionedHashes(*[]common.Hash) (*[]common.Hash, error) {
func (v *VersionedHashes) GetVersionedHashes(_ *rand.Rand, _ *[]common.Hash) (*[]common.Hash, error) {
if v.Blobs == nil {
return nil, nil
}
Expand Down Expand Up @@ -518,7 +519,7 @@ func (step NewPayloads) Execute(t *CancunTestContext) error {
step.NewPayloadCustomizer.SetEngineAPIVersionResolver(t.ForkConfig)
testEngine := t.TestEngine.WithEngineAPIVersionResolver(step.NewPayloadCustomizer)

payload, err = step.NewPayloadCustomizer.CustomizePayload(payload)
payload, err = step.NewPayloadCustomizer.CustomizePayload(t.Rand, payload)
if err != nil {
t.Fatalf("FAIL: Error customizing payload (payload %d/%d): %v", p+1, payloadCount, err)
}
Expand Down Expand Up @@ -714,7 +715,7 @@ func (step SendModifiedLatestPayload) Execute(t *CancunTestContext) error {

// Send a custom new payload
step.NewPayloadCustomizer.SetEngineAPIVersionResolver(t.ForkConfig)
payload, err = step.NewPayloadCustomizer.CustomizePayload(payload)
payload, err = step.NewPayloadCustomizer.CustomizePayload(t.Rand, payload)
if err != nil {
t.Fatalf("FAIL: Error customizing payload: %v", err)
}
Expand Down
7 changes: 3 additions & 4 deletions simulators/ethereum/engine/suites/engine/bad_hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package suite_engine

import (
"fmt"
"math/rand"

api "github.com/ethereum/go-ethereum/beacon/engine"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -84,7 +83,7 @@ func (b BadHashOnNewPayload) Execute(t *test.Env) {
} else if b.Syncing {
// We need to send an fcU to put the client in SYNCING state.
randomHeadBlock := common.Hash{}
rand.Read(randomHeadBlock[:])
t.Rand.Read(randomHeadBlock[:])
fcU := api.ForkchoiceStateV1{
HeadBlockHash: randomHeadBlock,
SafeBlockHash: t.CLMock.LatestHeader.Hash(),
Expand Down Expand Up @@ -125,7 +124,7 @@ func (b BadHashOnNewPayload) Execute(t *test.Env) {
customizer := &helper.CustomPayloadData{
ParentHash: &alteredPayload.BlockHash,
}
alteredPayload, err := customizer.CustomizePayload(&t.CLMock.LatestPayloadBuilt)
alteredPayload, err := customizer.CustomizePayload(t.Rand, &t.CLMock.LatestPayloadBuilt)
if err != nil {
t.Fatalf("FAIL (%s): Unable to modify payload: %v", t.TestName, err)
}
Expand Down Expand Up @@ -177,7 +176,7 @@ func (b ParentHashOnNewPayload) Execute(t *test.Env) {
alteredPayload := t.CLMock.LatestPayloadBuilt
if b.Syncing {
// Parent hash is unknown but also (incorrectly) set as the block hash
rand.Read(alteredPayload.ParentHash[:])
t.Rand.Read(alteredPayload.ParentHash[:])
}
alteredPayload.BlockHash = alteredPayload.ParentHash
// Execution specification::
Expand Down
5 changes: 2 additions & 3 deletions simulators/ethereum/engine/suites/engine/forkchoice.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package suite_engine

import (
"fmt"
"math/rand"

api "github.com/ethereum/go-ethereum/beacon/engine"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -52,7 +51,7 @@ func (tc InconsistentForkchoiceTest) Execute(t *test.Env) {
if len(alternativePayloads) > 0 {
customData.ParentHash = &alternativePayloads[len(alternativePayloads)-1].BlockHash
}
alternativePayload, err := customData.CustomizePayload(&t.CLMock.LatestPayloadBuilt)
alternativePayload, err := customData.CustomizePayload(t.Rand, &t.CLMock.LatestPayloadBuilt)
if err != nil {
t.Fatalf("FAIL (%s): Unable to construct alternative payload: %v", t.TestName, err)
}
Expand Down Expand Up @@ -112,7 +111,7 @@ func (tc ForkchoiceUpdatedUnknownBlockHashTest) Execute(t *test.Env) {

// Generate a random block hash
randomBlockHash := common.Hash{}
rand.Read(randomBlockHash[:])
t.Rand.Read(randomBlockHash[:])

if tc.Field == HeadBlockHash {

Expand Down
8 changes: 4 additions & 4 deletions simulators/ethereum/engine/suites/engine/invalid_ancestor.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,12 @@ func (tc InvalidMissingAncestorReOrgTest) Execute(t *test.Env) {
ParentHash: &altChainPayloads[len(altChainPayloads)-1].BlockHash,
ExtraData: &([]byte{0x01}),
}
sidePayload, err = customizer.CustomizePayload(&t.CLMock.LatestPayloadBuilt)
sidePayload, err = customizer.CustomizePayload(t.Rand, &t.CLMock.LatestPayloadBuilt)
if err != nil {
t.Fatalf("FAIL (%s): Unable to customize payload: %v", t.TestName, err)
}
if len(altChainPayloads) == tc.InvalidIndex {
sidePayload, err = helper.GenerateInvalidPayload(sidePayload, tc.InvalidField)
sidePayload, err = helper.GenerateInvalidPayload(t.Rand, sidePayload, tc.InvalidField)
if err != nil {
t.Fatalf("FAIL (%s): Unable to customize payload: %v", t.TestName, err)
}
Expand Down Expand Up @@ -321,12 +321,12 @@ func (tc InvalidMissingAncestorReOrgSyncTest) Execute(t *test.Env) {
ParentHash: &pHash,
ExtraData: &([]byte{0x01}),
}
sidePayload, err = customizer.CustomizePayload(&t.CLMock.LatestPayloadBuilt)
sidePayload, err = customizer.CustomizePayload(t.Rand, &t.CLMock.LatestPayloadBuilt)
if err != nil {
t.Fatalf("FAIL (%s): Unable to customize payload: %v", t.TestName, err)
}
if len(altChainPayloads) == tc.InvalidIndex {
sidePayload, err = helper.GenerateInvalidPayload(sidePayload, tc.InvalidField)
sidePayload, err = helper.GenerateInvalidPayload(t.Rand, sidePayload, tc.InvalidField)
if err != nil {
t.Fatalf("FAIL (%s): Unable to customize payload: %v", t.TestName, err)
}
Expand Down
6 changes: 3 additions & 3 deletions simulators/ethereum/engine/suites/engine/invalid_payload.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ func (tc InvalidPayloadTestCase) Execute(t *test.Env) {
t.Fatalf("FAIL (%s): No transactions in the base payload", t.TestName)
}

alteredPayload, err = helper.GenerateInvalidPayload(&t.CLMock.LatestPayloadBuilt, tc.InvalidField)
alteredPayload, err = helper.GenerateInvalidPayload(t.Rand, &t.CLMock.LatestPayloadBuilt, tc.InvalidField)
if err != nil {
t.Fatalf("FAIL (%s): Unable to modify payload (%v): %v", t.TestName, tc.InvalidField, err)
}
Expand Down Expand Up @@ -283,7 +283,7 @@ func (tc InvalidPayloadTestCase) Execute(t *test.Env) {
}
followUpAlteredPayload, err := (&helper.CustomPayloadData{
ParentHash: &alteredPayload.BlockHash,
}).CustomizePayload(&t.CLMock.LatestPayloadBuilt)
}).CustomizePayload(t.Rand, &t.CLMock.LatestPayloadBuilt)
if err != nil {
t.Fatalf("FAIL (%s): Unable to modify payload: %v", t.TestName, err)
}
Expand Down Expand Up @@ -376,7 +376,7 @@ func (tc PayloadBuildAfterInvalidPayloadTest) Execute(t *test.Env) {
)
s.ExpectNoError()

inv_p, err = helper.GenerateInvalidPayload(&s.Payload, helper.InvalidStateRoot)
inv_p, err = helper.GenerateInvalidPayload(t.Rand, &s.Payload, helper.InvalidStateRoot)
if err != nil {
t.Fatalf("FAIL (%s): Unable to invalidate payload: %v", t.TestName, err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package suite_engine

import (
"fmt"
"math/rand"

"github.com/ethereum/hive/simulators/ethereum/engine/clmock"
"github.com/ethereum/hive/simulators/ethereum/engine/config"
Expand Down Expand Up @@ -48,7 +47,7 @@ func (tc InvalidPayloadAttributesTest) Execute(t *test.Env) {
fcu := t.CLMock.LatestForkchoice
if tc.Syncing {
// Setting a random hash will put the client into `SYNCING`
rand.Read(fcu.HeadBlockHash[:])
t.Rand.Read(fcu.HeadBlockHash[:])
} else {
fcu.HeadBlockHash = t.CLMock.LatestPayloadBuilt.BlockHash
}
Expand Down
Loading

0 comments on commit 74a3253

Please sign in to comment.