diff --git a/app/k1util/k1util_test.go b/app/k1util/k1util_test.go index 184c1c670..3cb1d6a48 100644 --- a/app/k1util/k1util_test.go +++ b/app/k1util/k1util_test.go @@ -3,8 +3,8 @@ package k1util_test import ( + "crypto/rand" "encoding/hex" - "math/rand" "os" "path" "testing" diff --git a/app/obolapi/api_test.go b/app/obolapi/api_test.go index b0ad81415..bb6f0de1f 100644 --- a/app/obolapi/api_test.go +++ b/app/obolapi/api_test.go @@ -7,6 +7,7 @@ import ( "context" "encoding/json" "io" + "math/rand" "net/http" "net/http/httptest" "testing" @@ -45,7 +46,9 @@ func TestLockPublish(t *testing.T) { }, } - lock, _, _ := cluster.NewForT(t, 3, 3, 4, 0, opts...) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, _ := cluster.NewForT(t, 3, 3, 4, seed, random, opts...) cl, err := obolapi.New(srv.URL) require.NoError(t, err) diff --git a/cluster/cluster_internal_test.go b/cluster/cluster_internal_test.go index 6cb07a508..319b776b7 100644 --- a/cluster/cluster_internal_test.go +++ b/cluster/cluster_internal_test.go @@ -266,10 +266,14 @@ func TestSupportEIP712Sigs(t *testing.T) { } func RandomDepositData() DepositData { + return RandomDepositDataSeed(testutil.NewSeedRand()) +} + +func RandomDepositDataSeed(r *rand.Rand) DepositData { return DepositData{ - PubKey: testutil.RandomBytes48(), - WithdrawalCredentials: testutil.RandomBytes32(), - Amount: rand.Int(), - Signature: testutil.RandomBytes96(), + PubKey: testutil.RandomBytes48Seed(r), + WithdrawalCredentials: testutil.RandomBytes32Seed(r), + Amount: r.Int(), + Signature: testutil.RandomBytes96Seed(r), } } diff --git a/cluster/cluster_test.go b/cluster/cluster_test.go index 53ab199ba..8957a0142 100644 --- a/cluster/cluster_test.go +++ b/cluster/cluster_test.go @@ -37,7 +37,7 @@ func TestEncode(t *testing.T) { for _, version := range cluster.SupportedVersionsForT(t) { t.Run(version, func(t *testing.T) { vStr := strings.ReplaceAll(version, ".", "_") - rand.Seed(1) + r := rand.New(rand.NewSource(1)) const ( numVals = 2 @@ -52,13 +52,13 @@ func TestEncode(t *testing.T) { } // Definition version prior to v1.5 don't support multiple validator addresses. if isAnyVersion(version, v1_0, v1_1, v1_2, v1_3, v1_4) { - opts = append(opts, cluster.WithLegacyVAddrs(testutil.RandomETHAddress(), testutil.RandomETHAddress())) + opts = append(opts, cluster.WithLegacyVAddrs(testutil.RandomETHAddressSeed(r), testutil.RandomETHAddressSeed(r))) } var feeRecipientAddrs, withdrawalAddrs []string for i := 0; i < numVals; i++ { - feeRecipientAddrs = append(feeRecipientAddrs, testutil.RandomETHAddress()) - withdrawalAddrs = append(withdrawalAddrs, testutil.RandomETHAddress()) + feeRecipientAddrs = append(feeRecipientAddrs, testutil.RandomETHAddressSeed(r)) + withdrawalAddrs = append(withdrawalAddrs, testutil.RandomETHAddressSeed(r)) } definition, err := cluster.NewDefinition( @@ -69,21 +69,21 @@ func TestEncode(t *testing.T) { withdrawalAddrs, eth2util.Sepolia.GenesisForkVersionHex, cluster.Creator{ - Address: testutil.RandomETHAddress(), - ConfigSignature: testutil.RandomSecp256k1Signature(), + Address: testutil.RandomETHAddressSeed(r), + ConfigSignature: testutil.RandomSecp256k1SignatureSeed(r), }, []cluster.Operator{ { - Address: testutil.RandomETHAddress(), - ENR: fmt.Sprintf("enr://%x", testutil.RandomBytes32()), - ConfigSignature: testutil.RandomSecp256k1Signature(), - ENRSignature: testutil.RandomSecp256k1Signature(), + Address: testutil.RandomETHAddressSeed(r), + ENR: fmt.Sprintf("enr://%x", testutil.RandomBytes32Seed(r)), + ConfigSignature: testutil.RandomSecp256k1SignatureSeed(r), + ENRSignature: testutil.RandomSecp256k1SignatureSeed(r), }, { - Address: testutil.RandomETHAddress(), - ENR: fmt.Sprintf("enr://%x", testutil.RandomBytes32()), - ConfigSignature: testutil.RandomSecp256k1Signature(), - ENRSignature: testutil.RandomSecp256k1Signature(), + Address: testutil.RandomETHAddressSeed(r), + ENR: fmt.Sprintf("enr://%x", testutil.RandomBytes32Seed(r)), + ConfigSignature: testutil.RandomSecp256k1SignatureSeed(r), + ENRSignature: testutil.RandomSecp256k1SignatureSeed(r), }, }, []int{16, 16}, @@ -134,29 +134,29 @@ func TestEncode(t *testing.T) { lock := cluster.Lock{ Definition: definition, - SignatureAggregate: testutil.RandomBytes32(), + SignatureAggregate: testutil.RandomBytes32Seed(r), Validators: []cluster.DistValidator{ { - PubKey: testutil.RandomBytes48(), + PubKey: testutil.RandomBytes48Seed(r), PubShares: [][]byte{ - testutil.RandomBytes48(), - testutil.RandomBytes48(), + testutil.RandomBytes48Seed(r), + testutil.RandomBytes48Seed(r), }, - PartialDepositData: []cluster.DepositData{cluster.RandomDepositData()}, - BuilderRegistration: cluster.RandomRegistration(t, eth2util.Sepolia.Name), + PartialDepositData: []cluster.DepositData{cluster.RandomDepositDataSeed(r)}, + BuilderRegistration: cluster.RandomRegistrationSeed(t, eth2util.Sepolia.Name, r), }, { - PubKey: testutil.RandomBytes48(), + PubKey: testutil.RandomBytes48Seed(r), PubShares: [][]byte{ - testutil.RandomBytes48(), - testutil.RandomBytes48(), + testutil.RandomBytes48Seed(r), + testutil.RandomBytes48Seed(r), }, - PartialDepositData: []cluster.DepositData{cluster.RandomDepositData()}, - BuilderRegistration: cluster.RandomRegistration(t, eth2util.Sepolia.Name), + PartialDepositData: []cluster.DepositData{cluster.RandomDepositDataSeed(r)}, + BuilderRegistration: cluster.RandomRegistrationSeed(t, eth2util.Sepolia.Name, r), }, }, NodeSignatures: [][]byte{ - testutil.RandomBytes32(), - testutil.RandomBytes32(), + testutil.RandomBytes32Seed(r), + testutil.RandomBytes32Seed(r), }, } @@ -187,7 +187,7 @@ func TestEncode(t *testing.T) { // Lock version v1.8.0 supports multiple PartialDepositData. if isAnyVersion(version, v1_8) { for i := range lock.Validators { - dd := cluster.RandomDepositData() + dd := cluster.RandomDepositDataSeed(r) dd.PubKey = lock.Validators[i].PubKey lock.Validators[i].PartialDepositData = append(lock.Validators[i].PartialDepositData, dd) } @@ -265,7 +265,9 @@ func TestExamples(t *testing.T) { } func TestDefinitionPeers(t *testing.T) { - lock, _, _ := cluster.NewForT(t, 2, 3, 4, 5) + seed := 5 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, _ := cluster.NewForT(t, 2, 3, 4, seed, random) peers, err := lock.Peers() require.NoError(t, err) diff --git a/cluster/helpers_internal_test.go b/cluster/helpers_internal_test.go index 1bc3fdd4a..dbfa92fe6 100644 --- a/cluster/helpers_internal_test.go +++ b/cluster/helpers_internal_test.go @@ -5,6 +5,7 @@ package cluster import ( "context" "fmt" + "math/rand" "net/http" "net/http/httptest" "strings" @@ -72,7 +73,9 @@ func TestVerifySig(t *testing.T) { } func TestFetchDefinition(t *testing.T) { - lock, _, _ := NewForT(t, 1, 2, 3, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, _ := NewForT(t, 1, 2, 3, seed, random) validDef := lock.Definition invalidDef := Definition{} diff --git a/cluster/lock_test.go b/cluster/lock_test.go index afe541dca..e8295185e 100644 --- a/cluster/lock_test.go +++ b/cluster/lock_test.go @@ -3,6 +3,7 @@ package cluster_test import ( + "math/rand" "testing" "github.com/stretchr/testify/require" @@ -11,7 +12,9 @@ import ( ) func TestVerifyLock(t *testing.T) { - lock, _, _ := cluster.NewForT(t, 3, 3, 4, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, _ := cluster.NewForT(t, 3, 3, 4, seed, random) require.NoError(t, lock.Definition.VerifySignatures()) require.NoError(t, lock.VerifySignatures()) } diff --git a/cluster/manifest/cluster_test.go b/cluster/manifest/cluster_test.go index a2c081598..e6a77168b 100644 --- a/cluster/manifest/cluster_test.go +++ b/cluster/manifest/cluster_test.go @@ -3,6 +3,7 @@ package manifest_test import ( + "math/rand" "testing" "github.com/stretchr/testify/require" @@ -13,7 +14,9 @@ import ( ) func TestDuplicateENRs(t *testing.T) { - lock, _, _ := cluster.NewForT(t, 1, 3, 4, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, _ := cluster.NewForT(t, 1, 3, 4, seed, random) _, err := manifest.ClusterPeers(&manifestpb.Cluster{Operators: []*manifestpb.Operator{ {Enr: lock.Operators[0].ENR}, diff --git a/cluster/manifest/load_test.go b/cluster/manifest/load_test.go index 01a7a180e..657eea46b 100644 --- a/cluster/manifest/load_test.go +++ b/cluster/manifest/load_test.go @@ -115,7 +115,9 @@ func testLoadLegacy(t *testing.T, version string) { opts = append(opts, cluster.WithLegacyVAddrs(testutil.RandomETHAddress(), testutil.RandomETHAddress())) } - lock, _, _ := cluster.NewForT(t, rand.Intn(10), k, n, 0, opts...) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, _ := cluster.NewForT(t, rand.Intn(10), k, n, seed, random, opts...) b, err := json.MarshalIndent(lock, "", " ") require.NoError(t, err) diff --git a/cluster/manifest/mutationaddvalidator_test.go b/cluster/manifest/mutationaddvalidator_test.go index 94248d653..2ca4bb3ba 100644 --- a/cluster/manifest/mutationaddvalidator_test.go +++ b/cluster/manifest/mutationaddvalidator_test.go @@ -5,6 +5,7 @@ package manifest_test import ( "encoding/hex" "encoding/json" + "math/rand" "os" "testing" @@ -68,8 +69,9 @@ func TestAddValidators(t *testing.T) { setIncrementingTime(t) nodes := 4 - lock, secrets, _ := cluster.NewForT(t, 3, 3, nodes, 1) - + seed := 1 + random := rand.New(rand.NewSource(int64(seed))) + lock, secrets, _ := cluster.NewForT(t, 3, 3, nodes, seed, random) // Convert validators into manifest.Validator var vals []*manifestpb.Validator for i, validator := range lock.Validators { @@ -78,8 +80,7 @@ func TestAddValidators(t *testing.T) { vals = append(vals, val) } - - genVals, err := manifest.NewGenValidators(testutil.RandomBytes32(), vals) + genVals, err := manifest.NewGenValidators(testutil.RandomBytes32Seed(random), vals) require.NoError(t, err) genHash, err := manifest.Hash(genVals) testutil.RequireNoError(t, err) diff --git a/cluster/manifest/mutationnodeapproval_test.go b/cluster/manifest/mutationnodeapproval_test.go index 604fcbcb2..e72facb3d 100644 --- a/cluster/manifest/mutationnodeapproval_test.go +++ b/cluster/manifest/mutationnodeapproval_test.go @@ -3,6 +3,7 @@ package manifest_test import ( + "math/rand" "testing" "time" @@ -36,9 +37,11 @@ func setIncrementingTime(t *testing.T) { func TestNodeApprovals(t *testing.T) { setIncrementingTime(t) - lock, secrets, _ := cluster.NewForT(t, 1, 3, 4, 1) + seed := 1 + random := rand.New(rand.NewSource(int64(seed))) + lock, secrets, _ := cluster.NewForT(t, 1, 3, 4, seed, random) - parent := testutil.RandomBytes32() + parent := testutil.RandomBytes32Seed(random) var approvals []*manifestpb.SignedMutation for _, secret := range secrets { diff --git a/cluster/test_cluster.go b/cluster/test_cluster.go index 3a8147c34..c1a86744d 100644 --- a/cluster/test_cluster.go +++ b/cluster/test_cluster.go @@ -25,7 +25,7 @@ import ( // It also returns the peer p2p keys and BLS secret shares. If the seed is zero a random cluster on available loopback // ports is generated, else a deterministic cluster is generated. // Note this is not defined in testutil since it is tightly coupled with the cluster package. -func NewForT(t *testing.T, dv, k, n, seed int, opts ...func(*Definition)) (Lock, []*k1.PrivateKey, [][]tbls.PrivateKey) { +func NewForT(t *testing.T, dv, k, n, seed int, random *rand.Rand, opts ...func(*Definition)) (Lock, []*k1.PrivateKey, [][]tbls.PrivateKey) { t.Helper() var ( @@ -35,22 +35,20 @@ func NewForT(t *testing.T, dv, k, n, seed int, opts ...func(*Definition)) (Lock, dvShares [][]tbls.PrivateKey ) - random := io.Reader(rand.New(rand.NewSource(int64(seed)))) //nolint:gosec // Explicit use of weak random generator for determinism. + randomReader := io.Reader(rand.New(rand.NewSource(int64(seed)))) //nolint:gosec // Explicit use of weak random generator for determinism. if seed == 0 { - random = crand.Reader - } else { - rand.Seed(int64(seed)) + randomReader = crand.Reader } var feeRecipientAddrs, withdrawalAddrs []string for i := 0; i < dv; i++ { - rootSecret, err := tbls.GenerateInsecureKey(t, random) + rootSecret, err := tbls.GenerateInsecureKey(t, randomReader) require.NoError(t, err) rootPublic, err := tbls.SecretToPublicKey(rootSecret) require.NoError(t, err) - shares, err := tbls.ThresholdSplitInsecure(t, rootSecret, uint(n), uint(k), random) + shares, err := tbls.ThresholdSplitInsecure(t, rootSecret, uint(n), uint(k), randomReader) require.NoError(t, err) var pubshares [][]byte @@ -66,7 +64,7 @@ func NewForT(t *testing.T, dv, k, n, seed int, opts ...func(*Definition)) (Lock, privshares = append(privshares, sharePrivkey) } - feeRecipientAddr := testutil.RandomETHAddress() + feeRecipientAddr := testutil.RandomETHAddressSeed(random) reg := getSignedRegistration(t, rootSecret, feeRecipientAddr, eth2util.Goerli.Name) vals = append(vals, DistValidator{ @@ -76,7 +74,7 @@ func NewForT(t *testing.T, dv, k, n, seed int, opts ...func(*Definition)) (Lock, }) dvShares = append(dvShares, privshares) feeRecipientAddrs = append(feeRecipientAddrs, feeRecipientAddr) - withdrawalAddrs = append(withdrawalAddrs, testutil.RandomETHAddress()) + withdrawalAddrs = append(withdrawalAddrs, testutil.RandomETHAddressSeed(random)) } for i := 0; i < n; i++ { @@ -104,7 +102,7 @@ func NewForT(t *testing.T, dv, k, n, seed int, opts ...func(*Definition)) (Lock, def, err := NewDefinition("test cluster", dv, k, feeRecipientAddrs, withdrawalAddrs, - eth2util.Goerli.GenesisForkVersionHex, creator, ops, nil, random, opts...) + eth2util.Goerli.GenesisForkVersionHex, creator, ops, nil, randomReader, opts...) require.NoError(t, err) // Definition version prior to v1.3.0 don't support EIP712 signatures. @@ -189,17 +187,22 @@ func getSignedRegistration(t *testing.T, secret tbls.PrivateKey, feeRecipientAdd // RandomRegistration returns a random builder registration. func RandomRegistration(t *testing.T, network string) BuilderRegistration { t.Helper() + return RandomRegistrationSeed(t, network, testutil.NewSeedRand()) +} + +func RandomRegistrationSeed(t *testing.T, network string, r *rand.Rand) BuilderRegistration { + t.Helper() timestamp, err := eth2util.NetworkToGenesisTime(network) require.NoError(t, err) return BuilderRegistration{ Message: Registration{ - FeeRecipient: testutil.RandomBytes32()[:20], + FeeRecipient: testutil.RandomBytes32Seed(r)[:20], GasLimit: 30000000, Timestamp: timestamp, - PubKey: testutil.RandomBytes48(), + PubKey: testutil.RandomBytes48Seed(r), }, - Signature: testutil.RandomBytes96(), + Signature: testutil.RandomBytes96Seed(r), } } diff --git a/cluster/test_cluster_test.go b/cluster/test_cluster_test.go index 3d52422f8..ad3c14cc4 100644 --- a/cluster/test_cluster_test.go +++ b/cluster/test_cluster_test.go @@ -3,6 +3,7 @@ package cluster_test import ( + "math/rand" "testing" "github.com/stretchr/testify/require" @@ -11,7 +12,9 @@ import ( ) func TestNewCluster(t *testing.T) { - lock, _, _ := cluster.NewForT(t, 3, 3, 3, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, _ := cluster.NewForT(t, 3, 3, 3, seed, random) require.NoError(t, lock.VerifyHashes()) require.NoError(t, lock.VerifySignatures()) } diff --git a/cmd/addvalidators_internal_test.go b/cmd/addvalidators_internal_test.go index ec1289a38..f2542d059 100644 --- a/cmd/addvalidators_internal_test.go +++ b/cmd/addvalidators_internal_test.go @@ -5,6 +5,7 @@ package cmd import ( "context" "fmt" + "math/rand" "os" "path" "path/filepath" @@ -116,7 +117,9 @@ func TestRunAddValidators(t *testing.T) { } t.Run("add validators once", func(t *testing.T) { - lock, p2pKeys, _ := cluster.NewForT(t, valCount, n, n, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, p2pKeys, _ := cluster.NewForT(t, valCount, n, n, seed, random) tmp := t.TempDir() for _, dirname := range nodeDirnames { @@ -150,7 +153,9 @@ func TestRunAddValidators(t *testing.T) { }) t.Run("add validators twice", func(t *testing.T) { - lock, p2pKeys, _ := cluster.NewForT(t, valCount, n, n, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, p2pKeys, _ := cluster.NewForT(t, valCount, n, n, seed, random) tmp := t.TempDir() for _, dirname := range nodeDirnames { diff --git a/cmd/combine/combine_test.go b/cmd/combine/combine_test.go index 210e05ef1..02c29dd6e 100644 --- a/cmd/combine/combine_test.go +++ b/cmd/combine/combine_test.go @@ -7,6 +7,7 @@ import ( "context" "encoding/json" "fmt" + "math/rand" "os" "path" "path/filepath" @@ -35,7 +36,9 @@ func TestCombineNoLockfile(t *testing.T) { } func TestCombineCannotLoadKeystore(t *testing.T) { - lock, _, shares := cluster.NewForT(t, 2, 3, 4, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, shares := cluster.NewForT(t, 2, 3, 4, seed, random) for _, share := range shares { share := share @@ -92,7 +95,9 @@ func TestCombineCannotLoadKeystore(t *testing.T) { } func TestCombineAllManifest(t *testing.T) { - lock, _, shares := cluster.NewForT(t, 100, 3, 4, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, shares := cluster.NewForT(t, 100, 3, 4, seed, random) combineTest(t, lock, shares, false, false, noLockModif, []manifestChoice{ ManifestOnly, ManifestOnly, @@ -102,7 +107,9 @@ func TestCombineAllManifest(t *testing.T) { } func TestCombineBothManifestAndLockForAll(t *testing.T) { - lock, _, shares := cluster.NewForT(t, 100, 3, 4, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, shares := cluster.NewForT(t, 100, 3, 4, seed, random) combineTest(t, lock, shares, false, false, noLockModif, []manifestChoice{ Both, Both, @@ -112,7 +119,9 @@ func TestCombineBothManifestAndLockForAll(t *testing.T) { } func TestCombineBothManifestAndLockForSome(t *testing.T) { - lock, _, shares := cluster.NewForT(t, 100, 3, 4, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, shares := cluster.NewForT(t, 100, 3, 4, seed, random) combineTest(t, lock, shares, false, false, noLockModif, []manifestChoice{ ManifestOnly, Both, @@ -123,22 +132,30 @@ func TestCombineBothManifestAndLockForSome(t *testing.T) { // This test exists because of https://github.com/ObolNetwork/charon/issues/2151. func TestCombineLotsOfVals(t *testing.T) { - lock, _, shares := cluster.NewForT(t, 100, 3, 4, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, shares := cluster.NewForT(t, 100, 3, 4, seed, random) combineTest(t, lock, shares, false, false, noLockModif, nil) } func TestCombine(t *testing.T) { - lock, _, shares := cluster.NewForT(t, 2, 3, 4, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, shares := cluster.NewForT(t, 2, 3, 4, seed, random) combineTest(t, lock, shares, false, false, noLockModif, nil) } func TestCombineNoVerifyGoodLock(t *testing.T) { - lock, _, shares := cluster.NewForT(t, 2, 3, 4, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, shares := cluster.NewForT(t, 2, 3, 4, seed, random) combineTest(t, lock, shares, true, false, noLockModif, nil) } func TestCombineNoVerifyBadLock(t *testing.T) { - lock, _, shares := cluster.NewForT(t, 2, 3, 4, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, shares := cluster.NewForT(t, 2, 3, 4, seed, random) combineTest(t, lock, shares, true, false, func(valIndex int, src cluster.Lock) cluster.Lock { if valIndex == 1 { src.Name = "booohooo" @@ -149,7 +166,9 @@ func TestCombineNoVerifyBadLock(t *testing.T) { } func TestCombineBadLock(t *testing.T) { - lock, _, shares := cluster.NewForT(t, 2, 3, 4, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, shares := cluster.NewForT(t, 2, 3, 4, seed, random) combineTest(t, lock, shares, false, true, func(valIndex int, src cluster.Lock) cluster.Lock { if valIndex == 1 { src.Name = "booohooo" @@ -160,7 +179,9 @@ func TestCombineBadLock(t *testing.T) { } func TestCombineNoVerifyDifferentValidatorData(t *testing.T) { - lock, _, shares := cluster.NewForT(t, 2, 3, 4, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, shares := cluster.NewForT(t, 2, 3, 4, seed, random) combineTest(t, lock, shares, true, true, func(valIndex int, src cluster.Lock) cluster.Lock { if valIndex == 1 { src.Validators[valIndex].PubKey = bytes.Repeat([]byte{42}, 48) @@ -327,7 +348,9 @@ func combineTest( } func TestCombineTwiceWithoutForceFails(t *testing.T) { - lock, _, shares := cluster.NewForT(t, 2, 3, 4, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, shares := cluster.NewForT(t, 2, 3, 4, seed, random) // calculate expected public keys and secrets type expected struct { diff --git a/cmd/createcluster_internal_test.go b/cmd/createcluster_internal_test.go index 6a11e16c9..aa9f59c1d 100644 --- a/cmd/createcluster_internal_test.go +++ b/cmd/createcluster_internal_test.go @@ -8,6 +8,7 @@ import ( "encoding/hex" "encoding/json" "io" + "math/rand" "net/http" "net/http/httptest" "os" @@ -563,7 +564,9 @@ func TestMultipleAddresses(t *testing.T) { }) t.Run("insufficient addresses from remote URL", func(t *testing.T) { - lock, _, _ := cluster.NewForT(t, 2, 3, 4, 1, func(d *cluster.Definition) { + seed := 1 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, _ := cluster.NewForT(t, 2, 3, 4, seed, random, func(d *cluster.Definition) { d.ValidatorAddresses = []cluster.ValidatorAddresses{} }) diff --git a/cmd/view_cluster_manifest_internal_test.go b/cmd/view_cluster_manifest_internal_test.go index aab9e2445..79419747d 100644 --- a/cmd/view_cluster_manifest_internal_test.go +++ b/cmd/view_cluster_manifest_internal_test.go @@ -5,6 +5,7 @@ package cmd import ( "bytes" "encoding/json" + "math/rand" "os" "path/filepath" "testing" @@ -21,7 +22,9 @@ import ( //go:generate go test . -run=Test_viewClusterManifest -update func Test_viewClusterManifest(t *testing.T) { - lock, _, _ := cluster.NewForT(t, 1, 4, 4, 1, func(definition *cluster.Definition) { + seed := 1 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, _ := cluster.NewForT(t, 1, 4, 4, seed, random, func(definition *cluster.Definition) { definition.Timestamp = "2022-07-19T18:19:58+02:00" // Make deterministic }) diff --git a/core/consensus/component_test.go b/core/consensus/component_test.go index 0b2ae66cb..70a34e6ca 100644 --- a/core/consensus/component_test.go +++ b/core/consensus/component_test.go @@ -5,6 +5,7 @@ package consensus_test import ( "context" "fmt" + "math/rand" "testing" "github.com/libp2p/go-libp2p" @@ -65,7 +66,9 @@ func TestComponent(t *testing.T) { // Note it only instantiates the minimum amount of peers, ie threshold. func testComponent(t *testing.T, threshold, nodes int) { t.Helper() - lock, p2pkeys, _ := cluster.NewForT(t, 1, threshold, nodes, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, p2pkeys, _ := cluster.NewForT(t, 1, threshold, nodes, seed, random) var ( peers []p2p.Peer diff --git a/core/consensus/msg_internal_test.go b/core/consensus/msg_internal_test.go index 02edb4d7e..ec5c95777 100644 --- a/core/consensus/msg_internal_test.go +++ b/core/consensus/msg_internal_test.go @@ -22,8 +22,8 @@ import ( //go:generate go test . -update -clean func TestHashProto(t *testing.T) { - rand.Seed(0) - set := testutil.RandomUnsignedDataSet(t) + r := rand.New(rand.NewSource(0)) + set := testutil.RandomUnsignedDataSetSeed(t, r) testutil.RequireGoldenJSON(t, set) setPB, err := core.UnsignedDataSetToProto(set) diff --git a/dkg/disk_internal_test.go b/dkg/disk_internal_test.go index 66e8b09ae..52c895eb3 100644 --- a/dkg/disk_internal_test.go +++ b/dkg/disk_internal_test.go @@ -5,6 +5,7 @@ package dkg import ( "context" "encoding/json" + "math/rand" "os" "path" "path/filepath" @@ -19,7 +20,9 @@ func TestLoadDefinition(t *testing.T) { tmp := t.TempDir() // Valid definition - lock, _, _ := cluster.NewForT(t, 1, 2, 3, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, _, _ := cluster.NewForT(t, 1, 2, 3, seed, random) validDef := lock.Definition validFile := path.Join(tmp, "valid-cluster-definition.json") b, err := json.MarshalIndent(validDef, "", " ") diff --git a/dkg/dkg_test.go b/dkg/dkg_test.go index 7978243bd..f681197a5 100644 --- a/dkg/dkg_test.go +++ b/dkg/dkg_test.go @@ -6,6 +6,7 @@ import ( "context" "encoding/json" "fmt" + "math/rand" "net/http" "net/http/httptest" "os" @@ -86,7 +87,9 @@ func TestDKG(t *testing.T) { opts = append(opts, cluster.WithVersion(test.version)) } - lock, keys, _ := cluster.NewForT(t, vals, nodes, nodes, 1, opts...) + seed := 1 + random := rand.New(rand.NewSource(int64(seed))) + lock, keys, _ := cluster.NewForT(t, vals, nodes, nodes, seed, random, opts...) dir := t.TempDir() testDKG(t, lock.Definition, dir, keys, test.keymanager, test.publish) @@ -431,7 +434,9 @@ func TestSyncFlow(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { version := cluster.WithVersion("v1.7.0") // TODO(corver): remove this once v1.7 released. - lock, keys, _ := cluster.NewForT(t, test.vals, test.nodes, test.nodes, 0, version) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, keys, _ := cluster.NewForT(t, test.vals, test.nodes, test.nodes, seed, random, version) pIDs, err := lock.PeerIDs() require.NoError(t, err) diff --git a/eth2util/rlp/rlp_test.go b/eth2util/rlp/rlp_test.go index ff36c4f98..e0fc1fd4d 100644 --- a/eth2util/rlp/rlp_test.go +++ b/eth2util/rlp/rlp_test.go @@ -3,8 +3,8 @@ package rlp_test import ( + "crypto/rand" "fmt" - "math/rand" "testing" "github.com/stretchr/testify/require" @@ -185,7 +185,8 @@ func TestLengths(t *testing.T) { for _, length := range []int{0, 1, 55, 56, 1023, 1024} { t.Run(fmt.Sprint(length), func(t *testing.T) { buf := make([]byte, length) - rand.Read(buf) + _, err := rand.Read(buf) + require.NoError(t, err) encoded := rlp.EncodeBytes(buf) diff --git a/p2p/peer_test.go b/p2p/peer_test.go index 3716f7c71..48bffb48e 100644 --- a/p2p/peer_test.go +++ b/p2p/peer_test.go @@ -4,6 +4,7 @@ package p2p_test import ( "context" + "math/rand" "testing" k1 "github.com/decred/dcrd/dcrec/secp256k1/v4" @@ -36,7 +37,9 @@ func TestNewHost(t *testing.T) { } func TestVerifyP2PKey(t *testing.T) { - lock, keys, _ := cluster.NewForT(t, 1, 3, 4, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, keys, _ := cluster.NewForT(t, 1, 3, 4, seed, random) peers, err := lock.Peers() require.NoError(t, err) @@ -51,7 +54,9 @@ func TestVerifyP2PKey(t *testing.T) { } func TestPeerIDKey(t *testing.T) { - lock, keys, _ := cluster.NewForT(t, 1, 3, 4, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, keys, _ := cluster.NewForT(t, 1, 3, 4, seed, random) peers, err := lock.Peers() require.NoError(t, err) diff --git a/testutil/integration/infosync_test.go b/testutil/integration/infosync_test.go index 14835fd28..e769f3ca5 100644 --- a/testutil/integration/infosync_test.go +++ b/testutil/integration/infosync_test.go @@ -5,6 +5,7 @@ package integration_test import ( "context" "fmt" + "math/rand" "testing" "time" @@ -31,7 +32,9 @@ func TestInfoSync(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) const n = 3 - lock, p2pKeys, _ := cluster.NewForT(t, 1, n, n, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, p2pKeys, _ := cluster.NewForT(t, 1, n, n, seed, random) asserter := &priorityAsserter{ asserter: asserter{Timeout: time.Second * 10}, diff --git a/testutil/integration/nightly_dkg_test.go b/testutil/integration/nightly_dkg_test.go index 46dc0f4a3..ef7b04974 100644 --- a/testutil/integration/nightly_dkg_test.go +++ b/testutil/integration/nightly_dkg_test.go @@ -240,7 +240,9 @@ func mimicDKGNode(parentCtx context.Context, t *testing.T, dkgConf dkg.Config, w func testDef(t *testing.T, threshold, numNodes, numVals int) (cluster.Definition, []*k1.PrivateKey) { t.Helper() - lock, p2pKeys, _ := cluster.NewForT(t, numVals, threshold, numNodes, 1) + seed := 1 + random := rand.New(rand.NewSource(int64(seed))) + lock, p2pKeys, _ := cluster.NewForT(t, numVals, threshold, numNodes, seed, random) return lock.Definition, p2pKeys } diff --git a/testutil/integration/ping_test.go b/testutil/integration/ping_test.go index e28ba0e30..addc8cf54 100644 --- a/testutil/integration/ping_test.go +++ b/testutil/integration/ping_test.go @@ -5,6 +5,7 @@ package integration_test import ( "context" "fmt" + "math/rand" "net" "regexp" "testing" @@ -79,7 +80,9 @@ func pingCluster(t *testing.T, test pingTest) { const n = 3 - lock, p2pKeys, _ := cluster.NewForT(t, 1, n, n, 0) + seed := 0 + random := rand.New(rand.NewSource(int64(seed))) + lock, p2pKeys, _ := cluster.NewForT(t, 1, n, n, seed, random) asserter := &pingAsserter{ asserter: asserter{ Timeout: time.Second * 10, diff --git a/testutil/integration/simnet_test.go b/testutil/integration/simnet_test.go index 4ece2d120..1a9f24d5f 100644 --- a/testutil/integration/simnet_test.go +++ b/testutil/integration/simnet_test.go @@ -5,6 +5,7 @@ package integration_test import ( "context" "fmt" + "math/rand" "net/http" "os" "os/exec" @@ -199,7 +200,9 @@ func newSimnetArgs(t *testing.T) simnetArgs { n = 3 numDVs = 1 ) - lock, p2pKeys, secretShares := cluster.NewForT(t, numDVs, n, n, 99) + seed := 99 + random := rand.New(rand.NewSource(int64(seed))) + lock, p2pKeys, secretShares := cluster.NewForT(t, numDVs, n, n, seed, random) secrets := secretShares[0] diff --git a/testutil/random.go b/testutil/random.go index cb2803b81..bd5d17983 100644 --- a/testutil/random.go +++ b/testutil/random.go @@ -5,6 +5,7 @@ package testutil import ( "crypto/ecdsa" + crand "crypto/rand" "fmt" "math" "math/rand" @@ -40,9 +41,9 @@ import ( "github.com/obolnetwork/charon/tbls" ) -func deterministicPubkey(t *testing.T) tbls.PublicKey { +func deterministicPubkeySeed(t *testing.T, r *rand.Rand) tbls.PublicKey { t.Helper() - random := rand.New(rand.NewSource(rand.Int63())) + random := rand.New(rand.NewSource(r.Int63())) var key tbls.PublicKey _, err := random.Read(key[:]) @@ -51,10 +52,19 @@ func deterministicPubkey(t *testing.T) tbls.PublicKey { return key } +func NewSeedRand() *rand.Rand { + return rand.New(rand.NewSource(rand.Int63())) +} + // RandomCorePubKey returns a random core workflow pubkey. func RandomCorePubKey(t *testing.T) core.PubKey { t.Helper() - pubkey := deterministicPubkey(t) + return RandomCorePubKeySeed(t, NewSeedRand()) +} + +func RandomCorePubKeySeed(t *testing.T, r *rand.Rand) core.PubKey { + t.Helper() + pubkey := deterministicPubkeySeed(t, r) resp, err := core.PubKeyFromBytes(pubkey[:]) require.NoError(t, err) @@ -64,7 +74,12 @@ func RandomCorePubKey(t *testing.T) core.PubKey { // RandomEth2PubKey returns a random eth2 phase0 bls pubkey. func RandomEth2PubKey(t *testing.T) eth2p0.BLSPubKey { t.Helper() - pubkey := deterministicPubkey(t) + return RandomEth2PubKeySeed(t, NewSeedRand()) +} + +func RandomEth2PubKeySeed(t *testing.T, r *rand.Rand) eth2p0.BLSPubKey { + t.Helper() + pubkey := deterministicPubkeySeed(t, r) return eth2p0.BLSPubKey(pubkey) } @@ -118,12 +133,16 @@ func RandomAggregateAttestation() *eth2p0.Attestation { } func RandomAttestationData() *eth2p0.AttestationData { + return RandomAttestationDataSeed(NewSeedRand()) +} + +func RandomAttestationDataSeed(r *rand.Rand) *eth2p0.AttestationData { return ð2p0.AttestationData{ - Slot: RandomSlot(), - Index: RandomCommIdx(), - BeaconBlockRoot: RandomRoot(), - Source: RandomCheckpoint(), - Target: RandomCheckpoint(), + Slot: RandomSlotSeed(r), + Index: RandomCommIdxSeed(r), + BeaconBlockRoot: RandomRootSeed(r), + Source: RandomCheckpointSeed(r), + Target: RandomCheckpointSeed(r), } } @@ -712,7 +731,7 @@ func RandomSyncCommitteeDuty(t *testing.T) *eth2v1.SyncCommitteeDuty { func RandomSyncAggregate() *altair.SyncAggregate { var syncSSZ [160]byte - _, _ = rand.Read(syncSSZ[:]) + _, _ = crand.Read(syncSSZ[:]) sync := new(altair.SyncAggregate) err := sync.UnmarshalSSZ(syncSSZ[:]) if err != nil { @@ -810,15 +829,20 @@ func RandomDenebExecutionPayloadHeader() *deneb.ExecutionPayloadHeader { } func RandomAttestationDuty(t *testing.T) *eth2v1.AttesterDuty { + t.Helper() + return RandomAttestationDutySeed(t, NewSeedRand()) +} + +func RandomAttestationDutySeed(t *testing.T, r *rand.Rand) *eth2v1.AttesterDuty { t.Helper() return ð2v1.AttesterDuty{ - PubKey: RandomEth2PubKey(t), - Slot: RandomSlot(), - ValidatorIndex: RandomVIdx(), - CommitteeIndex: RandomCommIdx(), + PubKey: RandomEth2PubKeySeed(t, r), + Slot: RandomSlotSeed(r), + ValidatorIndex: RandomVIdxSeed(r), + CommitteeIndex: RandomCommIdxSeed(r), CommitteeLength: 256, CommitteesAtSlot: 256, - ValidatorCommitteeIndex: uint64(rand.Intn(256)), + ValidatorCommitteeIndex: uint64(r.Intn(256)), } } @@ -888,15 +912,19 @@ func RandomHistoricalSummary() *capella.HistoricalSummary { } func RandomRoot() eth2p0.Root { + return RandomRootSeed(NewSeedRand()) +} + +func RandomRootSeed(r *rand.Rand) eth2p0.Root { var resp eth2p0.Root - _, _ = rand.Read(resp[:]) + _, _ = r.Read(resp[:]) return resp } func RandomEth2Signature() eth2p0.BLSSignature { var resp eth2p0.BLSSignature - _, _ = rand.Read(resp[:]) + _, _ = crand.Read(resp[:]) return resp } @@ -910,35 +938,55 @@ func RandomEth2SignatureWithSeed(seed int64) eth2p0.BLSSignature { func RandomCoreSignature() core.Signature { resp := make(core.Signature, 96) - _, _ = rand.Read(resp) + _, _ = crand.Read(resp) return resp } func RandomCheckpoint() *eth2p0.Checkpoint { + return RandomCheckpointSeed(NewSeedRand()) +} + +func RandomCheckpointSeed(r *rand.Rand) *eth2p0.Checkpoint { var resp eth2p0.Root - _, _ = rand.Read(resp[:]) + _, _ = r.Read(resp[:]) return ð2p0.Checkpoint{ - Epoch: RandomEpoch(), - Root: RandomRoot(), + Epoch: RandomEpochSeed(r), + Root: RandomRootSeed(r), } } func RandomEpoch() eth2p0.Epoch { - return eth2p0.Epoch(rand.Int63n(int64(math.Pow(2, 53)))) + return RandomEpochSeed(NewSeedRand()) +} + +func RandomEpochSeed(r *rand.Rand) eth2p0.Epoch { + return eth2p0.Epoch(r.Int63n(int64(math.Pow(2, 53)))) } func RandomSlot() eth2p0.Slot { - return eth2p0.Slot(rand.Int63n(int64(math.Pow(2, 53)))) + return RandomSlotSeed(NewSeedRand()) +} + +func RandomSlotSeed(r *rand.Rand) eth2p0.Slot { + return eth2p0.Slot(r.Int63n(int64(math.Pow(2, 53)))) } func RandomCommIdx() eth2p0.CommitteeIndex { - return eth2p0.CommitteeIndex(rand.Int63n(int64(math.Pow(2, 53)))) + return RandomCommIdxSeed(NewSeedRand()) +} + +func RandomCommIdxSeed(r *rand.Rand) eth2p0.CommitteeIndex { + return eth2p0.CommitteeIndex(r.Int63n(int64(math.Pow(2, 53)))) } func RandomVIdx() eth2p0.ValidatorIndex { - return eth2p0.ValidatorIndex(rand.Int63n(int64(math.Pow(2, 53)))) + return RandomVIdxSeed(NewSeedRand()) +} + +func RandomVIdxSeed(r *rand.Rand) eth2p0.ValidatorIndex { + return eth2p0.ValidatorIndex(r.Int63n(int64(math.Pow(2, 53)))) } func RandomWithdrawalIdx() capella.WithdrawalIndex { @@ -950,7 +998,11 @@ func RandomGwei() eth2p0.Gwei { } func RandomETHAddress() string { - return fmt.Sprintf("%#x", RandomBytes32()[:20]) + return RandomETHAddressSeed(NewSeedRand()) +} + +func RandomETHAddressSeed(r *rand.Rand) string { + return fmt.Sprintf("%#x", RandomBytes32Seed(r)[:20]) } func RandomChecksummedETHAddress(t *testing.T, seed int) string { @@ -967,29 +1019,45 @@ func RandomChecksummedETHAddress(t *testing.T, seed int) string { } func RandomBytes96() []byte { + return RandomBytes96Seed(NewSeedRand()) +} + +func RandomBytes96Seed(r *rand.Rand) []byte { var resp [96]byte - _, _ = rand.Read(resp[:]) + _, _ = r.Read(resp[:]) return resp[:] } func RandomBytes48() []byte { + return RandomBytes48Seed(NewSeedRand()) +} + +func RandomBytes48Seed(r *rand.Rand) []byte { var resp [48]byte - _, _ = rand.Read(resp[:]) + _, _ = r.Read(resp[:]) return resp[:] } func RandomBytes32() []byte { + return RandomBytes32Seed(NewSeedRand()) +} + +func RandomBytes32Seed(r *rand.Rand) []byte { var resp [32]byte - _, _ = rand.Read(resp[:]) + _, _ = r.Read(resp[:]) return resp[:] } func RandomArray32() [32]byte { + return RandomArray32Seed(NewSeedRand()) +} + +func RandomArray32Seed(r *rand.Rand) [32]byte { var resp [32]byte - _, _ = rand.Read(resp[:]) + _, _ = r.Read(resp[:]) return resp } @@ -1024,8 +1092,12 @@ func RandomBitVec4() bitfield.Bitvector4 { // RandomSecp256k1Signature returns a random byte slice of length 65 with the last byte set to 0, 1, 27 or 28. func RandomSecp256k1Signature() []byte { + return RandomSecp256k1SignatureSeed(NewSeedRand()) +} + +func RandomSecp256k1SignatureSeed(r *rand.Rand) []byte { var resp [65]byte - _, _ = rand.Read(resp[:]) + _, _ = r.Read(resp[:]) r1 := resp[0] % 2 // 0 or 1 r2 := 27 * (resp[1] % 2) // 0 or 27 @@ -1037,7 +1109,7 @@ func RandomSecp256k1Signature() []byte { func RandomExecutionAddress() bellatrix.ExecutionAddress { var resp [20]byte - _, _ = rand.Read(resp[:]) + _, _ = crand.Read(resp[:]) return resp } @@ -1132,9 +1204,14 @@ func RandomENR(t *testing.T, seed int) (*k1.PrivateKey, enr.Record) { func RandomCoreAttestationData(t *testing.T) core.AttestationData { t.Helper() + return RandomCoreAttestationDataSeed(t, NewSeedRand()) +} - duty := RandomAttestationDuty(t) - data := RandomAttestationData() +func RandomCoreAttestationDataSeed(t *testing.T, r *rand.Rand) core.AttestationData { + t.Helper() + + duty := RandomAttestationDutySeed(t, r) + data := RandomAttestationDataSeed(r) return core.AttestationData{ Data: *data, @@ -1144,9 +1221,14 @@ func RandomCoreAttestationData(t *testing.T) core.AttestationData { func RandomUnsignedDataSet(t *testing.T) core.UnsignedDataSet { t.Helper() + return RandomUnsignedDataSetSeed(t, NewSeedRand()) +} + +func RandomUnsignedDataSetSeed(t *testing.T, r *rand.Rand) core.UnsignedDataSet { + t.Helper() return core.UnsignedDataSet{ - RandomCorePubKey(t): RandomCoreAttestationData(t), + RandomCorePubKeySeed(t, r): RandomCoreAttestationDataSeed(t, r), } }