Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

simulators/ethereum/engine: Add randomness seed input #944

Merged
merged 2 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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