From dc74fad816c74de008d4c368eb55918912ab66aa Mon Sep 17 00:00:00 2001 From: Bjerg Date: Wed, 21 Jun 2023 23:35:28 +0200 Subject: [PATCH] test: add support for seeded rng (#3270) --- .github/workflows/integration.yml | 1 + .github/workflows/unit.yml | 1 + README.md | 11 ++ crates/blockchain-tree/src/block_buffer.rs | 96 +++++++++------ crates/consensus/beacon/src/engine/mod.rs | 55 +++++---- crates/interfaces/Cargo.toml | 2 +- .../interfaces/src/test_utils/generators.rs | 114 +++++++++++------- crates/net/downloaders/src/bodies/bodies.rs | 5 +- crates/net/downloaders/src/bodies/request.rs | 5 +- crates/net/downloaders/src/test_utils/mod.rs | 6 +- crates/rpc/rpc-engine-api/src/engine_api.rs | 22 +++- .../rpc/rpc-types/src/eth/engine/payload.rs | 10 +- crates/stages/benches/setup/mod.rs | 28 +++-- crates/stages/src/pipeline/mod.rs | 6 +- crates/stages/src/stages/bodies.rs | 6 +- crates/stages/src/stages/finish.rs | 10 +- crates/stages/src/stages/hashing_account.rs | 11 +- crates/stages/src/stages/hashing_storage.rs | 24 ++-- crates/stages/src/stages/headers.rs | 20 +-- crates/stages/src/stages/merkle.rs | 16 ++- crates/stages/src/stages/sender_recovery.rs | 22 +++- crates/stages/src/stages/total_difficulty.rs | 6 +- crates/stages/src/stages/tx_lookup.rs | 21 +++- 23 files changed, 323 insertions(+), 175 deletions(-) diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 992c44746..fcff216a8 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -9,6 +9,7 @@ env: RUSTFLAGS: -D warnings CARGO_TERM_COLOR: always GETH_BUILD: 1.12.0-e501b3b0 + SEED: rustethereumethereumrust concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index 2e495074a..1204ffa5b 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -8,6 +8,7 @@ on: env: RUSTFLAGS: -D warnings CARGO_TERM_COLOR: always + SEED: rustethereumethereumrust concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} diff --git a/README.md b/README.md index f15395a82..dcb0ea323 100644 --- a/README.md +++ b/README.md @@ -94,10 +94,21 @@ cargo test --workspace # With Geth cargo test --workspace --features geth-tests + +# With Ethereum Foundation tests +# +# Note: Requires cloning https://github.com/ethereum/tests +# +# cd testing/ef-tests && git clone https://github.com/ethereum/tests ethereum-tests +cargo test --workspace --features ef-tests ``` We recommend using [`cargo nextest`](https://nexte.st/) to speed up testing. With nextest installed, simply substitute `cargo test` with `cargo nextest run`. +> **Note** +> +> Some tests use random number generators to generate test data. If you want to use a deterministic seed, you can set the `SEED` environment variable. + ## Getting Help If you have any questions, first see if the answer to your question can be found in the [book][book]. diff --git a/crates/blockchain-tree/src/block_buffer.rs b/crates/blockchain-tree/src/block_buffer.rs index a34427e0a..9ef9870d9 100644 --- a/crates/blockchain-tree/src/block_buffer.rs +++ b/crates/blockchain-tree/src/block_buffer.rs @@ -215,21 +215,23 @@ impl BlockBuffer { #[cfg(test)] mod tests { + use reth_interfaces::test_utils::generators; use std::collections::HashMap; - use reth_interfaces::test_utils::generators::random_block; + use reth_interfaces::test_utils::generators::{random_block, Rng}; use reth_primitives::{BlockHash, BlockNumHash, SealedBlockWithSenders}; use crate::BlockBuffer; - fn create_block(number: u64, parent: BlockHash) -> SealedBlockWithSenders { - let block = random_block(number, Some(parent), None, None); + fn create_block(rng: &mut R, number: u64, parent: BlockHash) -> SealedBlockWithSenders { + let block = random_block(rng, number, Some(parent), None, None); block.seal_with_senders().unwrap() } #[test] fn simple_insertion() { - let block1 = create_block(10, BlockHash::random()); + let mut rng = generators::rng(); + let block1 = create_block(&mut rng, 10, BlockHash::random()); let mut buffer = BlockBuffer::new(3); buffer.insert_block(block1.clone()); @@ -240,11 +242,13 @@ mod tests { #[test] fn take_all_chain_of_childrens() { + let mut rng = generators::rng(); + let main_parent = BlockNumHash::new(9, BlockHash::random()); - let block1 = create_block(10, main_parent.hash); - let block2 = create_block(11, block1.hash); - let block3 = create_block(12, block2.hash); - let block4 = create_block(14, BlockHash::random()); + let block1 = create_block(&mut rng, 10, main_parent.hash); + let block2 = create_block(&mut rng, 11, block1.hash); + let block3 = create_block(&mut rng, 12, block2.hash); + let block4 = create_block(&mut rng, 14, BlockHash::random()); let mut buffer = BlockBuffer::new(5); @@ -267,11 +271,13 @@ mod tests { #[test] fn take_all_multi_level_childrens() { + let mut rng = generators::rng(); + let main_parent = BlockNumHash::new(9, BlockHash::random()); - let block1 = create_block(10, main_parent.hash); - let block2 = create_block(11, block1.hash); - let block3 = create_block(11, block1.hash); - let block4 = create_block(12, block2.hash); + let block1 = create_block(&mut rng, 10, main_parent.hash); + let block2 = create_block(&mut rng, 11, block1.hash); + let block3 = create_block(&mut rng, 11, block1.hash); + let block4 = create_block(&mut rng, 12, block2.hash); let mut buffer = BlockBuffer::new(5); @@ -299,11 +305,13 @@ mod tests { #[test] fn take_self_with_childs() { + let mut rng = generators::rng(); + let main_parent = BlockNumHash::new(9, BlockHash::random()); - let block1 = create_block(10, main_parent.hash); - let block2 = create_block(11, block1.hash); - let block3 = create_block(11, block1.hash); - let block4 = create_block(12, block2.hash); + let block1 = create_block(&mut rng, 10, main_parent.hash); + let block2 = create_block(&mut rng, 11, block1.hash); + let block3 = create_block(&mut rng, 11, block1.hash); + let block4 = create_block(&mut rng, 12, block2.hash); let mut buffer = BlockBuffer::new(5); @@ -331,11 +339,13 @@ mod tests { #[test] fn clean_chain_of_children() { + let mut rng = generators::rng(); + let main_parent = BlockNumHash::new(9, BlockHash::random()); - let block1 = create_block(10, main_parent.hash); - let block2 = create_block(11, block1.hash); - let block3 = create_block(12, block2.hash); - let block4 = create_block(14, BlockHash::random()); + let block1 = create_block(&mut rng, 10, main_parent.hash); + let block2 = create_block(&mut rng, 11, block1.hash); + let block3 = create_block(&mut rng, 12, block2.hash); + let block4 = create_block(&mut rng, 14, BlockHash::random()); let mut buffer = BlockBuffer::new(5); @@ -351,11 +361,13 @@ mod tests { #[test] fn clean_all_multi_level_childrens() { + let mut rng = generators::rng(); + let main_parent = BlockNumHash::new(9, BlockHash::random()); - let block1 = create_block(10, main_parent.hash); - let block2 = create_block(11, block1.hash); - let block3 = create_block(11, block1.hash); - let block4 = create_block(12, block2.hash); + let block1 = create_block(&mut rng, 10, main_parent.hash); + let block2 = create_block(&mut rng, 11, block1.hash); + let block3 = create_block(&mut rng, 11, block1.hash); + let block4 = create_block(&mut rng, 12, block2.hash); let mut buffer = BlockBuffer::new(5); @@ -371,14 +383,16 @@ mod tests { #[test] fn clean_multi_chains() { + let mut rng = generators::rng(); + let main_parent = BlockNumHash::new(9, BlockHash::random()); - let block1 = create_block(10, main_parent.hash); - let block1a = create_block(10, main_parent.hash); - let block2 = create_block(11, block1.hash); - let block2a = create_block(11, block1.hash); - let random_block1 = create_block(10, BlockHash::random()); - let random_block2 = create_block(11, BlockHash::random()); - let random_block3 = create_block(12, BlockHash::random()); + let block1 = create_block(&mut rng, 10, main_parent.hash); + let block1a = create_block(&mut rng, 10, main_parent.hash); + let block2 = create_block(&mut rng, 11, block1.hash); + let block2a = create_block(&mut rng, 11, block1.hash); + let random_block1 = create_block(&mut rng, 10, BlockHash::random()); + let random_block2 = create_block(&mut rng, 11, BlockHash::random()); + let random_block3 = create_block(&mut rng, 12, BlockHash::random()); let mut buffer = BlockBuffer::new(10); @@ -420,11 +434,13 @@ mod tests { #[test] fn evict_with_gap() { + let mut rng = generators::rng(); + let main_parent = BlockNumHash::new(9, BlockHash::random()); - let block1 = create_block(10, main_parent.hash); - let block2 = create_block(11, block1.hash); - let block3 = create_block(12, block2.hash); - let block4 = create_block(13, BlockHash::random()); + let block1 = create_block(&mut rng, 10, main_parent.hash); + let block2 = create_block(&mut rng, 11, block1.hash); + let block3 = create_block(&mut rng, 12, block2.hash); + let block4 = create_block(&mut rng, 13, BlockHash::random()); let mut buffer = BlockBuffer::new(3); @@ -454,11 +470,13 @@ mod tests { #[test] fn simple_eviction() { + let mut rng = generators::rng(); + let main_parent = BlockNumHash::new(9, BlockHash::random()); - let block1 = create_block(10, main_parent.hash); - let block2 = create_block(11, block1.hash); - let block3 = create_block(12, block2.hash); - let block4 = create_block(13, BlockHash::random()); + let block1 = create_block(&mut rng, 10, main_parent.hash); + let block2 = create_block(&mut rng, 11, block1.hash); + let block3 = create_block(&mut rng, 12, block2.hash); + let block4 = create_block(&mut rng, 13, BlockHash::random()); let mut buffer = BlockBuffer::new(3); diff --git a/crates/consensus/beacon/src/engine/mod.rs b/crates/consensus/beacon/src/engine/mod.rs index cb3bac489..3516572cc 100644 --- a/crates/consensus/beacon/src/engine/mod.rs +++ b/crates/consensus/beacon/src/engine/mod.rs @@ -1751,7 +1751,7 @@ mod tests { mod fork_choice_updated { use super::*; use reth_db::{tables, transaction::DbTxMut}; - use reth_interfaces::test_utils::generators::random_block; + use reth_interfaces::test_utils::{generators, generators::random_block}; use reth_rpc_types::engine::ForkchoiceUpdateError; #[tokio::test] @@ -1786,6 +1786,7 @@ mod tests { #[tokio::test] async fn valid_forkchoice() { + let mut rng = generators::rng(); let chain_spec = Arc::new( ChainSpecBuilder::default() .chain(MAINNET.chain) @@ -1801,8 +1802,8 @@ mod tests { })])) .build(); - let genesis = random_block(0, None, None, Some(0)); - let block1 = random_block(1, Some(genesis.hash), None, Some(0)); + let genesis = random_block(&mut rng, 0, None, None, Some(0)); + let block1 = random_block(&mut rng, 1, Some(genesis.hash), None, Some(0)); insert_blocks(env.db.as_ref(), chain_spec.clone(), [&genesis, &block1].into_iter()); env.db .update(|tx| { @@ -1833,6 +1834,8 @@ mod tests { #[tokio::test] async fn unknown_head_hash() { + let mut rng = generators::rng(); + let chain_spec = Arc::new( ChainSpecBuilder::default() .chain(MAINNET.chain) @@ -1849,13 +1852,13 @@ mod tests { .disable_blockchain_tree_sync() .build(); - let genesis = random_block(0, None, None, Some(0)); - let block1 = random_block(1, Some(genesis.hash), None, Some(0)); + let genesis = random_block(&mut rng, 0, None, None, Some(0)); + let block1 = random_block(&mut rng, 1, Some(genesis.hash), None, Some(0)); insert_blocks(env.db.as_ref(), chain_spec.clone(), [&genesis, &block1].into_iter()); let mut engine_rx = spawn_consensus_engine(consensus_engine); - let next_head = random_block(2, Some(block1.hash), None, Some(0)); + let next_head = random_block(&mut rng, 2, Some(block1.hash), None, Some(0)); let next_forkchoice_state = ForkchoiceState { head_block_hash: next_head.hash, finalized_block_hash: block1.hash, @@ -1882,6 +1885,7 @@ mod tests { #[tokio::test] async fn unknown_finalized_hash() { + let mut rng = generators::rng(); let chain_spec = Arc::new( ChainSpecBuilder::default() .chain(MAINNET.chain) @@ -1898,8 +1902,8 @@ mod tests { .disable_blockchain_tree_sync() .build(); - let genesis = random_block(0, None, None, Some(0)); - let block1 = random_block(1, Some(genesis.hash), None, Some(0)); + let genesis = random_block(&mut rng, 0, None, None, Some(0)); + let block1 = random_block(&mut rng, 1, Some(genesis.hash), None, Some(0)); insert_blocks(env.db.as_ref(), chain_spec.clone(), [&genesis, &block1].into_iter()); let engine = spawn_consensus_engine(consensus_engine); @@ -1918,6 +1922,7 @@ mod tests { #[tokio::test] async fn forkchoice_updated_pre_merge() { + let mut rng = generators::rng(); let chain_spec = Arc::new( ChainSpecBuilder::default() .chain(MAINNET.chain) @@ -1934,16 +1939,16 @@ mod tests { ])) .build(); - let genesis = random_block(0, None, None, Some(0)); - let mut block1 = random_block(1, Some(genesis.hash), None, Some(0)); + let genesis = random_block(&mut rng, 0, None, None, Some(0)); + let mut block1 = random_block(&mut rng, 1, Some(genesis.hash), None, Some(0)); block1.header.difficulty = U256::from(1); // a second pre-merge block - let mut block2 = random_block(1, Some(genesis.hash), None, Some(0)); + let mut block2 = random_block(&mut rng, 1, Some(genesis.hash), None, Some(0)); block2.header.difficulty = U256::from(1); // a transition block - let mut block3 = random_block(1, Some(genesis.hash), None, Some(0)); + let mut block3 = random_block(&mut rng, 1, Some(genesis.hash), None, Some(0)); block3.header.difficulty = U256::from(1); insert_blocks( @@ -1971,6 +1976,7 @@ mod tests { #[tokio::test] async fn forkchoice_updated_invalid_pow() { + let mut rng = generators::rng(); let chain_spec = Arc::new( ChainSpecBuilder::default() .chain(MAINNET.chain) @@ -1986,8 +1992,8 @@ mod tests { ])) .build(); - let genesis = random_block(0, None, None, Some(0)); - let block1 = random_block(1, Some(genesis.hash), None, Some(0)); + let genesis = random_block(&mut rng, 0, None, None, Some(0)); + let block1 = random_block(&mut rng, 1, Some(genesis.hash), None, Some(0)); insert_blocks(env.db.as_ref(), chain_spec.clone(), [&genesis, &block1].into_iter()); @@ -2011,12 +2017,13 @@ mod tests { mod new_payload { use super::*; - use reth_interfaces::test_utils::generators::random_block; + use reth_interfaces::test_utils::{generators, generators::random_block}; use reth_primitives::{Hardfork, U256}; use reth_provider::test_utils::blocks::BlockChainTestData; #[tokio::test] async fn new_payload_before_forkchoice() { + let mut rng = generators::rng(); let chain_spec = Arc::new( ChainSpecBuilder::default() .chain(MAINNET.chain) @@ -2035,12 +2042,14 @@ mod tests { let mut engine_rx = spawn_consensus_engine(consensus_engine); // Send new payload - let res = env.send_new_payload(random_block(0, None, None, Some(0)).into()).await; + let res = + env.send_new_payload(random_block(&mut rng, 0, None, None, Some(0)).into()).await; // Invalid, because this is a genesis block assert_matches!(res, Ok(result) => assert_matches!(result.status, PayloadStatusEnum::Invalid { .. })); // Send new payload - let res = env.send_new_payload(random_block(1, None, None, Some(0)).into()).await; + let res = + env.send_new_payload(random_block(&mut rng, 1, None, None, Some(0)).into()).await; let expected_result = PayloadStatus::from_status(PayloadStatusEnum::Syncing); assert_matches!(res, Ok(result) => assert_eq!(result, expected_result)); @@ -2049,6 +2058,7 @@ mod tests { #[tokio::test] async fn payload_known() { + let mut rng = generators::rng(); let chain_spec = Arc::new( ChainSpecBuilder::default() .chain(MAINNET.chain) @@ -2064,9 +2074,9 @@ mod tests { })])) .build(); - let genesis = random_block(0, None, None, Some(0)); - let block1 = random_block(1, Some(genesis.hash), None, Some(0)); - let block2 = random_block(2, Some(block1.hash), None, Some(0)); + let genesis = random_block(&mut rng, 0, None, None, Some(0)); + let block1 = random_block(&mut rng, 1, Some(genesis.hash), None, Some(0)); + let block2 = random_block(&mut rng, 2, Some(block1.hash), None, Some(0)); insert_blocks( env.db.as_ref(), chain_spec.clone(), @@ -2098,6 +2108,7 @@ mod tests { #[tokio::test] async fn payload_parent_unknown() { + let mut rng = generators::rng(); let chain_spec = Arc::new( ChainSpecBuilder::default() .chain(MAINNET.chain) @@ -2113,7 +2124,7 @@ mod tests { })])) .build(); - let genesis = random_block(0, None, None, Some(0)); + let genesis = random_block(&mut rng, 0, None, None, Some(0)); insert_blocks(env.db.as_ref(), chain_spec.clone(), [&genesis].into_iter()); @@ -2132,7 +2143,7 @@ mod tests { assert_matches!(res, Ok(ForkchoiceUpdated { payload_status, .. }) => assert_eq!(payload_status, expected_result)); // Send new payload - let block = random_block(2, Some(H256::random()), None, Some(0)); + let block = random_block(&mut rng, 2, Some(H256::random()), None, Some(0)); let res = env.send_new_payload(block.into()).await; let expected_result = PayloadStatus::from_status(PayloadStatusEnum::Syncing); assert_matches!(res, Ok(result) => assert_eq!(result, expected_result)); diff --git a/crates/interfaces/Cargo.toml b/crates/interfaces/Cargo.toml index 3fbd20672..d358cdef0 100644 --- a/crates/interfaces/Cargo.toml +++ b/crates/interfaces/Cargo.toml @@ -52,4 +52,4 @@ secp256k1 = { workspace = true, features = [ ] } [features] -test-utils = ["tokio-stream/sync", "secp256k1"] +test-utils = ["tokio-stream/sync", "secp256k1", "rand/std_rng"] diff --git a/crates/interfaces/src/test_utils/generators.rs b/crates/interfaces/src/test_utils/generators.rs index 53733e21d..137996046 100644 --- a/crates/interfaces/src/test_utils/generators.rs +++ b/crates/interfaces/src/test_utils/generators.rs @@ -1,4 +1,7 @@ -use rand::{distributions::uniform::SampleRange, seq::SliceRandom, thread_rng, Rng}; +pub use rand::Rng; +use rand::{ + distributions::uniform::SampleRange, rngs::StdRng, seq::SliceRandom, thread_rng, SeedableRng, +}; use reth_primitives::{ proofs, sign_message, Account, Address, BlockNumber, Bytes, Header, SealedBlock, SealedHeader, Signature, StorageEntry, Transaction, TransactionKind, TransactionSigned, TxLegacy, H160, H256, @@ -7,23 +10,42 @@ use reth_primitives::{ use secp256k1::{KeyPair, Message as SecpMessage, Secp256k1, SecretKey, SECP256K1}; use std::{ cmp::{max, min}, - collections::BTreeMap, + collections::{hash_map::DefaultHasher, BTreeMap}, + hash::Hasher, ops::{Range, RangeInclusive, Sub}, }; // TODO(onbjerg): Maybe we should split this off to its own crate, or move the helpers to the // relevant crates? +/// Returns a random number generator that can be seeded using the `SEED` environment variable. +/// +/// If `SEED` is not set, a random seed is used. +pub fn rng() -> StdRng { + if let Ok(seed) = std::env::var("SEED") { + let mut hasher = DefaultHasher::new(); + hasher.write(seed.as_bytes()); + StdRng::seed_from_u64(hasher.finish()) + } else { + StdRng::from_rng(thread_rng()).expect("could not build rng") + } +} + /// Generates a range of random [SealedHeader]s. /// /// The parent hash of the first header /// in the result will be equal to `head`. /// /// The headers are assumed to not be correct if validated. -pub fn random_header_range(rng: std::ops::Range, head: H256) -> Vec { - let mut headers = Vec::with_capacity(rng.end.saturating_sub(rng.start) as usize); - for idx in rng { +pub fn random_header_range( + rng: &mut R, + range: std::ops::Range, + head: H256, +) -> Vec { + let mut headers = Vec::with_capacity(range.end.saturating_sub(range.start) as usize); + for idx in range { headers.push(random_header( + rng, idx, Some(headers.last().map(|h: &SealedHeader| h.hash()).unwrap_or(head)), )); @@ -34,11 +56,11 @@ pub fn random_header_range(rng: std::ops::Range, head: H256) -> Vec) -> SealedHeader { +pub fn random_header(rng: &mut R, number: u64, parent: Option) -> SealedHeader { let header = reth_primitives::Header { number, - nonce: rand::random(), - difficulty: U256::from(rand::random::()), + nonce: rng.gen(), + difficulty: U256::from(rng.gen::()), parent_hash: parent.unwrap_or_default(), ..Default::default() }; @@ -51,14 +73,14 @@ pub fn random_header(number: u64, parent: Option) -> SealedHeader { /// /// - The chain ID, which is always 1 /// - The input, which is always nothing -pub fn random_tx() -> Transaction { +pub fn random_tx(rng: &mut R) -> Transaction { Transaction::Legacy(TxLegacy { chain_id: Some(1), - nonce: rand::random::().into(), - gas_price: rand::random::().into(), - gas_limit: rand::random::().into(), + nonce: rng.gen::().into(), + gas_price: rng.gen::().into(), + gas_limit: rng.gen::().into(), to: TransactionKind::Call(Address::random()), - value: rand::random::().into(), + value: rng.gen::().into(), input: Bytes::default(), }) } @@ -68,10 +90,10 @@ pub fn random_tx() -> Transaction { /// On top of the considerations of [random_tx], these apply as well: /// /// - There is no guarantee that the nonce is not used twice for the same account -pub fn random_signed_tx() -> TransactionSigned { +pub fn random_signed_tx(rng: &mut R) -> TransactionSigned { let secp = Secp256k1::new(); - let key_pair = KeyPair::new(&secp, &mut rand::thread_rng()); - let tx = random_tx(); + let key_pair = KeyPair::new(&secp, rng); + let tx = random_tx(rng); sign_tx_with_key_pair(key_pair, tx) } @@ -96,23 +118,23 @@ pub fn sign_tx_with_key_pair(key_pair: KeyPair, tx: Transaction) -> TransactionS /// transactions in the block. /// /// The ommer headers are not assumed to be valid. -pub fn random_block( +pub fn random_block( + rng: &mut R, number: u64, parent: Option, tx_count: Option, ommers_count: Option, ) -> SealedBlock { - let mut rng = thread_rng(); - // Generate transactions let tx_count = tx_count.unwrap_or_else(|| rng.gen::()); - let transactions: Vec = (0..tx_count).map(|_| random_signed_tx()).collect(); + let transactions: Vec = + (0..tx_count).map(|_| random_signed_tx(rng)).collect(); let total_gas = transactions.iter().fold(0, |sum, tx| sum + tx.transaction.gas_limit()); // Generate ommers let ommers_count = ommers_count.unwrap_or_else(|| rng.gen_range(0..2)); let ommers = - (0..ommers_count).map(|_| random_header(number, parent).unseal()).collect::>(); + (0..ommers_count).map(|_| random_header(rng, number, parent).unseal()).collect::>(); // Calculate roots let transactions_root = proofs::calculate_transaction_root(&transactions); @@ -142,19 +164,21 @@ pub fn random_block( /// in the result will be equal to `head`. /// /// See [random_block] for considerations when validating the generated blocks. -pub fn random_block_range( +pub fn random_block_range( + rng: &mut R, block_numbers: RangeInclusive, head: H256, tx_count: Range, ) -> Vec { - let mut rng = rand::thread_rng(); let mut blocks = Vec::with_capacity(block_numbers.end().saturating_sub(*block_numbers.start()) as usize); for idx in block_numbers { + let tx_count = tx_count.clone().sample_single(rng); blocks.push(random_block( + rng, idx, Some(blocks.last().map(|block: &SealedBlock| block.header.hash()).unwrap_or(head)), - Some(tx_count.clone().sample_single(&mut rng)), + Some(tx_count), None, )); } @@ -169,7 +193,8 @@ type AccountState = (Account, Vec); /// /// Returns a Vec of account and storage changes for each transition, /// along with the final state of all accounts and storages. -pub fn random_transition_range<'a, IBlk, IAcc>( +pub fn random_transition_range<'a, R: Rng, IBlk, IAcc>( + rng: &mut R, blocks: IBlk, accounts: IAcc, n_changes: std::ops::Range, @@ -179,7 +204,6 @@ where IBlk: IntoIterator, IAcc: IntoIterator))>, { - let mut rng = rand::thread_rng(); let mut state: BTreeMap<_, _> = accounts .into_iter() .map(|(addr, (acc, st))| (addr, (acc, st.into_iter().map(|e| (e.key, e.value)).collect()))) @@ -192,7 +216,7 @@ where blocks.into_iter().for_each(|block| { let mut transition = Vec::new(); let (from, to, mut transfer, new_entries) = - random_account_change(&valid_addresses, n_changes.clone(), key_range.clone()); + random_account_change(rng, &valid_addresses, n_changes.clone(), key_range.clone()); // extract from sending account let (prev_from, _) = state.get_mut(&from).unwrap(); @@ -239,61 +263,63 @@ where /// Generate a random account change. /// /// Returns two addresses, a balance_change, and a Vec of new storage entries. -pub fn random_account_change( +pub fn random_account_change( + rng: &mut R, valid_addresses: &Vec
, n_changes: std::ops::Range, key_range: std::ops::Range, ) -> (Address, Address, U256, Vec) { - let mut rng = rand::thread_rng(); - let mut addresses = valid_addresses.choose_multiple(&mut rng, 2).cloned(); + let mut addresses = valid_addresses.choose_multiple(rng, 2).cloned(); let addr_from = addresses.next().unwrap_or_else(Address::random); let addr_to = addresses.next().unwrap_or_else(Address::random); let balance_change = U256::from(rng.gen::()); - let storage_changes = (0..n_changes.sample_single(&mut rng)) - .map(|_| random_storage_entry(key_range.clone())) + let storage_changes = (0..n_changes.sample_single(rng)) + .map(|_| random_storage_entry(rng, key_range.clone())) .collect(); (addr_from, addr_to, balance_change, storage_changes) } /// Generate a random storage change. -pub fn random_storage_entry(key_range: std::ops::Range) -> StorageEntry { - let mut rng = rand::thread_rng(); - - let key = H256::from_low_u64_be(key_range.sample_single(&mut rng)); +pub fn random_storage_entry(rng: &mut R, key_range: std::ops::Range) -> StorageEntry { + let key = H256::from_low_u64_be(key_range.sample_single(rng)); let value = U256::from(rng.gen::()); StorageEntry { key, value } } /// Generate random Externally Owned Account (EOA account without contract). -pub fn random_eoa_account() -> (Address, Account) { - let nonce: u64 = rand::random(); - let balance = U256::from(rand::random::()); - let addr = H160::from(rand::random::()); +pub fn random_eoa_account(rng: &mut R) -> (Address, Account) { + let nonce: u64 = rng.gen(); + let balance = U256::from(rng.gen::()); + let addr = H160::from(rng.gen::()); (addr, Account { nonce, balance, bytecode_hash: None }) } /// Generate random Externally Owned Accounts -pub fn random_eoa_account_range(acc_range: std::ops::Range) -> Vec<(Address, Account)> { +pub fn random_eoa_account_range( + rng: &mut R, + acc_range: std::ops::Range, +) -> Vec<(Address, Account)> { let mut accounts = Vec::with_capacity(acc_range.end.saturating_sub(acc_range.start) as usize); for _ in acc_range { - accounts.push(random_eoa_account()) + accounts.push(random_eoa_account(rng)) } accounts } /// Generate random Contract Accounts -pub fn random_contract_account_range( +pub fn random_contract_account_range( + rng: &mut R, acc_range: &mut std::ops::Range, ) -> Vec<(Address, Account)> { let mut accounts = Vec::with_capacity(acc_range.end.saturating_sub(acc_range.start) as usize); for _ in acc_range { - let (address, eoa_account) = random_eoa_account(); + let (address, eoa_account) = random_eoa_account(rng); let account = Account { bytecode_hash: Some(H256::random()), ..eoa_account }; accounts.push((address, account)) } diff --git a/crates/net/downloaders/src/bodies/bodies.rs b/crates/net/downloaders/src/bodies/bodies.rs index acc61f65b..e613f4977 100644 --- a/crates/net/downloaders/src/bodies/bodies.rs +++ b/crates/net/downloaders/src/bodies/bodies.rs @@ -595,7 +595,7 @@ mod tests { use assert_matches::assert_matches; use futures_util::stream::StreamExt; use reth_db::mdbx::{test_utils::create_test_db, EnvKind, WriteMap}; - use reth_interfaces::test_utils::{generators::random_block_range, TestConsensus}; + use reth_interfaces::test_utils::{generators, generators::random_block_range, TestConsensus}; use reth_primitives::{BlockBody, H256}; use std::{collections::HashMap, sync::Arc}; @@ -632,7 +632,8 @@ mod tests { async fn requests_correct_number_of_times() { // Generate some random blocks let db = create_test_db::(EnvKind::RW); - let blocks = random_block_range(0..=199, H256::zero(), 1..2); + let mut rng = generators::rng(); + let blocks = random_block_range(&mut rng, 0..=199, H256::zero(), 1..2); let headers = blocks.iter().map(|block| block.header.clone()).collect::>(); let bodies = blocks diff --git a/crates/net/downloaders/src/bodies/request.rs b/crates/net/downloaders/src/bodies/request.rs index e73836a43..a82b216cc 100644 --- a/crates/net/downloaders/src/bodies/request.rs +++ b/crates/net/downloaders/src/bodies/request.rs @@ -239,7 +239,7 @@ mod tests { }; use reth_interfaces::{ p2p::bodies::response::BlockResponse, - test_utils::{generators::random_header_range, TestConsensus}, + test_utils::{generators, generators::random_header_range, TestConsensus}, }; use reth_primitives::H256; use std::sync::Arc; @@ -247,7 +247,8 @@ mod tests { /// Check if future returns empty bodies without dispathing any requests. #[tokio::test] async fn request_returns_empty_bodies() { - let headers = random_header_range(0..20, H256::zero()); + let mut rng = generators::rng(); + let headers = random_header_range(&mut rng, 0..20, H256::zero()); let client = Arc::new(TestBodiesClient::default()); let fut = BodiesRequestFuture::new( diff --git a/crates/net/downloaders/src/test_utils/mod.rs b/crates/net/downloaders/src/test_utils/mod.rs index ad363ebef..98c850ef1 100644 --- a/crates/net/downloaders/src/test_utils/mod.rs +++ b/crates/net/downloaders/src/test_utils/mod.rs @@ -18,15 +18,17 @@ mod file_codec; pub use bodies_client::TestBodiesClient; pub use file_client::{FileClient, FileClientError}; pub(crate) use file_codec::BlockFileCodec; +use reth_interfaces::test_utils::generators; /// Metrics scope used for testing. pub(crate) const TEST_SCOPE: &str = "downloaders.test"; /// Generate a set of bodies and their corresponding block hashes pub(crate) fn generate_bodies( - rng: RangeInclusive, + range: RangeInclusive, ) -> (Vec, HashMap) { - let blocks = random_block_range(rng, H256::zero(), 0..2); + let mut rng = generators::rng(); + let blocks = random_block_range(&mut rng, range, H256::zero(), 0..2); let headers = blocks.iter().map(|block| block.header.clone()).collect(); let bodies = blocks diff --git a/crates/rpc/rpc-engine-api/src/engine_api.rs b/crates/rpc/rpc-engine-api/src/engine_api.rs index 20a085f0a..159f2a250 100644 --- a/crates/rpc/rpc-engine-api/src/engine_api.rs +++ b/crates/rpc/rpc-engine-api/src/engine_api.rs @@ -476,7 +476,7 @@ mod tests { // tests covering `engine_getPayloadBodiesByRange` and `engine_getPayloadBodiesByHash` mod get_payload_bodies { use super::*; - use reth_interfaces::test_utils::generators::random_block_range; + use reth_interfaces::test_utils::{generators, generators::random_block_range}; #[tokio::test] async fn invalid_params() { @@ -507,10 +507,12 @@ mod tests { #[tokio::test] async fn returns_payload_bodies() { + let mut rng = generators::rng(); let (handle, api) = setup_engine_api(); let (start, count) = (1, 10); - let blocks = random_block_range(start..=start + count - 1, H256::default(), 0..2); + let blocks = + random_block_range(&mut rng, start..=start + count - 1, H256::default(), 0..2); handle.provider.extend_blocks(blocks.iter().cloned().map(|b| (b.hash(), b.unseal()))); let expected = @@ -522,10 +524,12 @@ mod tests { #[tokio::test] async fn returns_payload_bodies_with_gaps() { + let mut rng = generators::rng(); let (handle, api) = setup_engine_api(); let (start, count) = (1, 100); - let blocks = random_block_range(start..=start + count - 1, H256::default(), 0..2); + let blocks = + random_block_range(&mut rng, start..=start + count - 1, H256::default(), 0..2); // Insert only blocks in ranges 1-25 and 50-75 let first_missing_range = 26..=50; @@ -566,6 +570,7 @@ mod tests { // https://github.com/ethereum/execution-apis/blob/main/src/engine/paris.md#specification-3 mod exchange_transition_configuration { use super::*; + use reth_interfaces::test_utils::generators; use reth_primitives::U256; #[tokio::test] @@ -589,11 +594,15 @@ mod tests { #[tokio::test] async fn terminal_block_hash_mismatch() { + let mut rng = generators::rng(); + let (handle, api) = setup_engine_api(); let terminal_block_number = 1000; - let consensus_terminal_block = random_block(terminal_block_number, None, None, None); - let execution_terminal_block = random_block(terminal_block_number, None, None, None); + let consensus_terminal_block = + random_block(&mut rng, terminal_block_number, None, None, None); + let execution_terminal_block = + random_block(&mut rng, terminal_block_number, None, None, None); let transition_config = TransitionConfiguration { terminal_total_difficulty: handle.chain_spec.fork(Hardfork::Paris).ttd().unwrap(), @@ -630,7 +639,8 @@ mod tests { let (handle, api) = setup_engine_api(); let terminal_block_number = 1000; - let terminal_block = random_block(terminal_block_number, None, None, None); + let terminal_block = + random_block(&mut generators::rng(), terminal_block_number, None, None, None); let transition_config = TransitionConfiguration { terminal_total_difficulty: handle.chain_spec.fork(Hardfork::Paris).ttd().unwrap(), diff --git a/crates/rpc/rpc-types/src/eth/engine/payload.rs b/crates/rpc/rpc-types/src/eth/engine/payload.rs index 6f64e121d..d60c81b5a 100644 --- a/crates/rpc/rpc-types/src/eth/engine/payload.rs +++ b/crates/rpc/rpc-types/src/eth/engine/payload.rs @@ -427,7 +427,7 @@ mod tests { use super::*; use assert_matches::assert_matches; use reth_interfaces::test_utils::generators::{ - random_block, random_block_range, random_header, + self, random_block, random_block_range, random_header, }; use reth_primitives::{ bytes::{Bytes, BytesMut}, @@ -453,7 +453,8 @@ mod tests { #[test] fn payload_body_roundtrip() { - for block in random_block_range(0..=99, H256::default(), 0..2) { + let mut rng = generators::rng(); + for block in random_block_range(&mut rng, 0..=99, H256::default(), 0..2) { let unsealed = block.clone().unseal(); let payload_body: ExecutionPayloadBody = unsealed.into(); @@ -472,7 +473,8 @@ mod tests { #[test] fn payload_validation() { - let block = random_block(100, Some(H256::random()), Some(3), Some(0)); + let mut rng = generators::rng(); + let block = random_block(&mut rng, 100, Some(H256::random()), Some(3), Some(0)); // Valid extra data let block_with_valid_extra_data = transform_block(block.clone(), |mut b| { @@ -514,7 +516,7 @@ mod tests { // Non empty ommers let block_with_ommers = transform_block(block.clone(), |mut b| { - b.ommers.push(random_header(100, None).unseal()); + b.ommers.push(random_header(&mut rng, 100, None).unseal()); b }); assert_matches!( diff --git a/crates/stages/benches/setup/mod.rs b/crates/stages/benches/setup/mod.rs index 8fca81471..008957b66 100644 --- a/crates/stages/benches/setup/mod.rs +++ b/crates/stages/benches/setup/mod.rs @@ -5,9 +5,12 @@ use reth_db::{ tables, transaction::{DbTx, DbTxMut}, }; -use reth_interfaces::test_utils::generators::{ - random_block_range, random_contract_account_range, random_eoa_account_range, - random_transition_range, +use reth_interfaces::test_utils::{ + generators, + generators::{ + random_block_range, random_contract_account_range, random_eoa_account_range, + random_transition_range, + }, }; use reth_primitives::{Account, Address, SealedBlock, H256, MAINNET}; use reth_provider::ProviderFactory; @@ -98,6 +101,9 @@ pub(crate) fn txs_testdata(num_blocks: u64) -> PathBuf { let n_eoa = 131; let n_contract = 31; + // rng + let mut rng = generators::rng(); + if !path.exists() { // create the dirs std::fs::create_dir_all(&path).unwrap(); @@ -105,15 +111,16 @@ pub(crate) fn txs_testdata(num_blocks: u64) -> PathBuf { let tx = TestTransaction::new(&path); let accounts: BTreeMap = concat([ - random_eoa_account_range(0..n_eoa), - random_contract_account_range(&mut (0..n_contract)), + random_eoa_account_range(&mut rng, 0..n_eoa), + random_contract_account_range(&mut rng, &mut (0..n_contract)), ]) .into_iter() .collect(); - let mut blocks = random_block_range(0..=num_blocks, H256::zero(), txs_range); + let mut blocks = random_block_range(&mut rng, 0..=num_blocks, H256::zero(), txs_range); let (transitions, start_state) = random_transition_range( + &mut rng, blocks.iter().take(2), accounts.into_iter().map(|(addr, acc)| (addr, (acc, Vec::new()))), n_changes.clone(), @@ -135,8 +142,13 @@ pub(crate) fn txs_testdata(num_blocks: u64) -> PathBuf { tx.insert_transitions(transitions, None).unwrap(); tx.commit(|tx| updates.flush(tx)).unwrap(); - let (transitions, final_state) = - random_transition_range(blocks.iter().skip(2), start_state, n_changes, key_range); + let (transitions, final_state) = random_transition_range( + &mut rng, + blocks.iter().skip(2), + start_state, + n_changes, + key_range, + ); tx.insert_transitions(transitions, Some(offset)).unwrap(); diff --git a/crates/stages/src/pipeline/mod.rs b/crates/stages/src/pipeline/mod.rs index ca9b7204e..96fb9b34a 100644 --- a/crates/stages/src/pipeline/mod.rs +++ b/crates/stages/src/pipeline/mod.rs @@ -482,7 +482,9 @@ mod tests { use assert_matches::assert_matches; use reth_db::mdbx::{self, test_utils, EnvKind}; use reth_interfaces::{ - consensus, provider::ProviderError, test_utils::generators::random_header, + consensus, + provider::ProviderError, + test_utils::{generators, generators::random_header}, }; use reth_primitives::{stage::StageCheckpoint, MAINNET}; use tokio_stream::StreamExt; @@ -787,7 +789,7 @@ mod tests { .add_stage( TestStage::new(StageId::Other("B")) .add_exec(Err(StageError::Validation { - block: random_header(5, Default::default()), + block: random_header(&mut generators::rng(), 5, Default::default()), error: consensus::ConsensusError::BaseFeeMissing, })) .add_unwind(Ok(UnwindOutput { checkpoint: StageCheckpoint::new(0) })) diff --git a/crates/stages/src/stages/bodies.rs b/crates/stages/src/stages/bodies.rs index 0108f7828..579ba2f17 100644 --- a/crates/stages/src/stages/bodies.rs +++ b/crates/stages/src/stages/bodies.rs @@ -473,6 +473,7 @@ mod tests { priority::Priority, }, test_utils::{ + generators, generators::{random_block_range, random_signed_tx}, TestConsensus, }, @@ -556,7 +557,8 @@ mod tests { fn seed_execution(&mut self, input: ExecInput) -> Result { let start = input.checkpoint().block_number; let end = input.target(); - let blocks = random_block_range(start..=end, GENESIS_HASH, 0..2); + let mut rng = generators::rng(); + let blocks = random_block_range(&mut rng, start..=end, GENESIS_HASH, 0..2); self.tx.insert_headers_with_td(blocks.iter().map(|block| &block.header))?; if let Some(progress) = blocks.first() { // Insert last progress data @@ -566,7 +568,7 @@ mod tests { tx_count: progress.body.len() as u64, }; body.tx_num_range().try_for_each(|tx_num| { - let transaction = random_signed_tx(); + let transaction = random_signed_tx(&mut rng); tx.put::(tx_num, transaction.into()) })?; diff --git a/crates/stages/src/stages/finish.rs b/crates/stages/src/stages/finish.rs index bae21c8c7..53d237049 100644 --- a/crates/stages/src/stages/finish.rs +++ b/crates/stages/src/stages/finish.rs @@ -40,7 +40,10 @@ mod tests { stage_test_suite_ext, ExecuteStageTestRunner, StageTestRunner, TestRunnerError, TestTransaction, UnwindStageTestRunner, }; - use reth_interfaces::test_utils::generators::{random_header, random_header_range}; + use reth_interfaces::test_utils::{ + generators, + generators::{random_header, random_header_range}, + }; use reth_primitives::SealedHeader; stage_test_suite_ext!(FinishTestRunner, finish); @@ -67,7 +70,8 @@ mod tests { fn seed_execution(&mut self, input: ExecInput) -> Result { let start = input.checkpoint().block_number; - let head = random_header(start, None); + let mut rng = generators::rng(); + let head = random_header(&mut rng, start, None); self.tx.insert_headers_with_td(std::iter::once(&head))?; // use previous progress as seed size @@ -77,7 +81,7 @@ mod tests { return Ok(Vec::default()) } - let mut headers = random_header_range(start + 1..end, head.hash()); + let mut headers = random_header_range(&mut rng, start + 1..end, head.hash()); self.tx.insert_headers_with_td(headers.iter())?; headers.insert(0, head); Ok(headers) diff --git a/crates/stages/src/stages/hashing_account.rs b/crates/stages/src/stages/hashing_account.rs index 255a09aa1..84485c745 100644 --- a/crates/stages/src/stages/hashing_account.rs +++ b/crates/stages/src/stages/hashing_account.rs @@ -83,18 +83,21 @@ impl AccountHashingStage { opts: SeedOpts, ) -> Result, StageError> { use reth_db::models::AccountBeforeTx; - use reth_interfaces::test_utils::generators::{ - random_block_range, random_eoa_account_range, + use reth_interfaces::test_utils::{ + generators, + generators::{random_block_range, random_eoa_account_range}, }; use reth_primitives::{Account, H256, U256}; use reth_provider::insert_canonical_block; - let blocks = random_block_range(opts.blocks.clone(), H256::zero(), opts.txs); + let mut rng = generators::rng(); + + let blocks = random_block_range(&mut rng, opts.blocks.clone(), H256::zero(), opts.txs); for block in blocks { insert_canonical_block(provider.tx_ref(), block, None).unwrap(); } - let mut accounts = random_eoa_account_range(opts.accounts); + let mut accounts = random_eoa_account_range(&mut rng, opts.accounts); { // Account State generator let mut account_cursor = diff --git a/crates/stages/src/stages/hashing_storage.rs b/crates/stages/src/stages/hashing_storage.rs index acb109b0e..2c298de33 100644 --- a/crates/stages/src/stages/hashing_storage.rs +++ b/crates/stages/src/stages/hashing_storage.rs @@ -231,13 +231,15 @@ mod tests { TestTransaction, UnwindStageTestRunner, }; use assert_matches::assert_matches; + use rand::Rng; use reth_db::{ cursor::{DbCursorRO, DbCursorRW}, mdbx::{tx::Tx, WriteMap, RW}, models::{BlockNumberAddress, StoredBlockBodyIndices}, }; - use reth_interfaces::test_utils::generators::{ - random_block_range, random_contract_account_range, + use reth_interfaces::test_utils::{ + generators, + generators::{random_block_range, random_contract_account_range}, }; use reth_primitives::{ stage::StageUnitCheckpoint, Address, SealedBlock, StorageEntry, H256, U256, @@ -487,11 +489,12 @@ mod tests { fn seed_execution(&mut self, input: ExecInput) -> Result { let stage_progress = input.next_block(); let end = input.target(); + let mut rng = generators::rng(); let n_accounts = 31; - let mut accounts = random_contract_account_range(&mut (0..n_accounts)); + let mut accounts = random_contract_account_range(&mut rng, &mut (0..n_accounts)); - let blocks = random_block_range(stage_progress..=end, H256::zero(), 0..3); + let blocks = random_block_range(&mut rng, stage_progress..=end, H256::zero(), 0..3); self.tx.insert_headers(blocks.iter().map(|block| &block.header))?; @@ -510,14 +513,13 @@ mod tests { transaction.clone().into(), )?; - let (addr, _) = accounts - .get_mut(rand::random::() % n_accounts as usize) - .unwrap(); + let (addr, _) = + accounts.get_mut(rng.gen::() % n_accounts as usize).unwrap(); for _ in 0..2 { let new_entry = StorageEntry { - key: keccak256([rand::random::()]), - value: U256::from(rand::random::() % 30 + 1), + key: keccak256([rng.gen::()]), + value: U256::from(rng.gen::() % 30 + 1), }; self.insert_storage_entry( tx, @@ -533,14 +535,14 @@ mod tests { )?; // Randomize rewards - let has_reward: bool = rand::random(); + let has_reward: bool = rng.gen(); if has_reward { self.insert_storage_entry( tx, (block_number, Address::random()).into(), StorageEntry { key: keccak256("mining"), - value: U256::from(rand::random::()), + value: U256::from(rng.gen::()), }, progress.header.number == stage_progress, )?; diff --git a/crates/stages/src/stages/headers.rs b/crates/stages/src/stages/headers.rs index 7c38fecec..1984e4d6f 100644 --- a/crates/stages/src/stages/headers.rs +++ b/crates/stages/src/stages/headers.rs @@ -388,7 +388,7 @@ mod tests { stage_test_suite, ExecuteStageTestRunner, StageTestRunner, UnwindStageTestRunner, }; use assert_matches::assert_matches; - use reth_interfaces::test_utils::generators::random_header; + use reth_interfaces::test_utils::{generators, generators::random_header}; use reth_primitives::{stage::StageUnitCheckpoint, H256, MAINNET}; use reth_provider::ProviderFactory; use test_runner::HeadersTestRunner; @@ -400,7 +400,8 @@ mod tests { ReverseHeadersDownloader, ReverseHeadersDownloaderBuilder, }; use reth_interfaces::test_utils::{ - generators::random_header_range, TestConsensus, TestHeaderDownloader, TestHeadersClient, + generators, generators::random_header_range, TestConsensus, TestHeaderDownloader, + TestHeadersClient, }; use reth_primitives::U256; use reth_provider::{BlockHashProvider, BlockNumProvider, HeaderProvider}; @@ -452,8 +453,9 @@ mod tests { type Seed = Vec; fn seed_execution(&mut self, input: ExecInput) -> Result { + let mut rng = generators::rng(); let start = input.checkpoint().block_number; - let head = random_header(start, None); + let head = random_header(&mut rng, start, None); self.tx.insert_headers(std::iter::once(&head))?; // patch td table for `update_head` call self.tx.commit(|tx| tx.put::(head.number, U256::ZERO.into()))?; @@ -465,7 +467,7 @@ mod tests { return Ok(Vec::default()) } - let mut headers = random_header_range(start + 1..end, head.hash()); + let mut headers = random_header_range(&mut rng, start + 1..end, head.hash()); headers.insert(0, head); Ok(headers) } @@ -505,7 +507,7 @@ mod tests { let tip = if !headers.is_empty() { headers.last().unwrap().hash() } else { - let tip = random_header(0, None); + let tip = random_header(&mut generators::rng(), 0, None); self.tx.insert_headers(std::iter::once(&tip))?; tip.hash() }; @@ -603,14 +605,16 @@ mod tests { let tx = provider.tx_ref(); let mut stage = runner.stage(); + let mut rng = generators::rng(); + let consensus_tip = H256::random(); runner.send_tip(consensus_tip); // Genesis let checkpoint = 0; - let head = random_header(0, None); - let gap_fill = random_header(1, Some(head.hash())); - let gap_tip = random_header(2, Some(gap_fill.hash())); + let head = random_header(&mut rng, 0, None); + let gap_fill = random_header(&mut rng, 1, Some(head.hash())); + let gap_tip = random_header(&mut rng, 2, Some(gap_fill.hash())); // Empty database assert_matches!( diff --git a/crates/stages/src/stages/merkle.rs b/crates/stages/src/stages/merkle.rs index bf70559f0..56cd21194 100644 --- a/crates/stages/src/stages/merkle.rs +++ b/crates/stages/src/stages/merkle.rs @@ -346,8 +346,12 @@ mod tests { tables, transaction::{DbTx, DbTxMut}, }; - use reth_interfaces::test_utils::generators::{ - random_block, random_block_range, random_contract_account_range, random_transition_range, + use reth_interfaces::test_utils::{ + generators, + generators::{ + random_block, random_block_range, random_contract_account_range, + random_transition_range, + }, }; use reth_primitives::{ keccak256, stage::StageUnitCheckpoint, SealedBlock, StorageEntry, H256, U256, @@ -469,9 +473,10 @@ mod tests { let stage_progress = input.checkpoint().block_number; let start = stage_progress + 1; let end = input.target(); + let mut rng = generators::rng(); let num_of_accounts = 31; - let accounts = random_contract_account_range(&mut (0..num_of_accounts)) + let accounts = random_contract_account_range(&mut rng, &mut (0..num_of_accounts)) .into_iter() .collect::>(); @@ -480,7 +485,7 @@ mod tests { )?; let SealedBlock { header, body, ommers, withdrawals } = - random_block(stage_progress, None, Some(0), None); + random_block(&mut rng, stage_progress, None, Some(0), None); let mut header = header.unseal(); header.state_root = state_root( @@ -493,10 +498,11 @@ mod tests { let head_hash = sealed_head.hash(); let mut blocks = vec![sealed_head]; - blocks.extend(random_block_range(start..=end, head_hash, 0..3)); + blocks.extend(random_block_range(&mut rng, start..=end, head_hash, 0..3)); self.tx.insert_blocks(blocks.iter(), None)?; let (transitions, final_state) = random_transition_range( + &mut rng, blocks.iter(), accounts.into_iter().map(|(addr, acc)| (addr, (acc, Vec::new()))), 0..3, diff --git a/crates/stages/src/stages/sender_recovery.rs b/crates/stages/src/stages/sender_recovery.rs index ba60007ac..5e012e3ab 100644 --- a/crates/stages/src/stages/sender_recovery.rs +++ b/crates/stages/src/stages/sender_recovery.rs @@ -231,7 +231,10 @@ struct FailedSenderRecoveryError { #[cfg(test)] mod tests { use assert_matches::assert_matches; - use reth_interfaces::test_utils::generators::{random_block, random_block_range}; + use reth_interfaces::test_utils::{ + generators, + generators::{random_block, random_block_range}, + }; use reth_primitives::{ stage::StageUnitCheckpoint, BlockNumber, SealedBlock, TransactionSigned, H256, }; @@ -249,6 +252,7 @@ mod tests { #[tokio::test] async fn execute_single_transaction() { let (previous_stage, stage_progress) = (500, 100); + let mut rng = generators::rng(); // Set up the runner let runner = SenderRecoveryTestRunner::default(); @@ -261,7 +265,13 @@ mod tests { let non_empty_block_number = stage_progress + 10; let blocks = (stage_progress..=input.target()) .map(|number| { - random_block(number, None, Some((number == non_empty_block_number) as u8), None) + random_block( + &mut rng, + number, + None, + Some((number == non_empty_block_number) as u8), + None, + ) }) .collect::>(); runner.tx.insert_blocks(blocks.iter(), None).expect("failed to insert blocks"); @@ -288,13 +298,16 @@ mod tests { /// Execute the stage twice with input range that exceeds the commit threshold #[tokio::test] async fn execute_intermediate_commit() { + let mut rng = generators::rng(); + let threshold = 10; let mut runner = SenderRecoveryTestRunner::default(); runner.set_threshold(threshold); let (stage_progress, previous_stage) = (1000, 1100); // input exceeds threshold // Manually seed once with full input range - let seed = random_block_range(stage_progress + 1..=previous_stage, H256::zero(), 0..4); // set tx count range high enough to hit the threshold + let seed = + random_block_range(&mut rng, stage_progress + 1..=previous_stage, H256::zero(), 0..4); // set tx count range high enough to hit the threshold runner.tx.insert_blocks(seed.iter(), None).expect("failed to seed execution"); let total_transactions = runner.tx.table::().unwrap().len() as u64; @@ -403,10 +416,11 @@ mod tests { type Seed = Vec; fn seed_execution(&mut self, input: ExecInput) -> Result { + let mut rng = generators::rng(); let stage_progress = input.checkpoint().block_number; let end = input.target(); - let blocks = random_block_range(stage_progress..=end, H256::zero(), 0..2); + let blocks = random_block_range(&mut rng, stage_progress..=end, H256::zero(), 0..2); self.tx.insert_blocks(blocks.iter(), None)?; Ok(blocks) } diff --git a/crates/stages/src/stages/total_difficulty.rs b/crates/stages/src/stages/total_difficulty.rs index 7175eb15f..deb78f7c6 100644 --- a/crates/stages/src/stages/total_difficulty.rs +++ b/crates/stages/src/stages/total_difficulty.rs @@ -126,6 +126,7 @@ mod tests { use assert_matches::assert_matches; use reth_db::transaction::DbTx; use reth_interfaces::test_utils::{ + generators, generators::{random_header, random_header_range}, TestConsensus, }; @@ -228,8 +229,9 @@ mod tests { type Seed = Vec; fn seed_execution(&mut self, input: ExecInput) -> Result { + let mut rng = generators::rng(); let start = input.checkpoint().block_number; - let head = random_header(start, None); + let head = random_header(&mut rng, start, None); self.tx.insert_headers(std::iter::once(&head))?; self.tx.commit(|tx| { let td: U256 = tx @@ -248,7 +250,7 @@ mod tests { return Ok(Vec::default()) } - let mut headers = random_header_range(start + 1..end, head.hash()); + let mut headers = random_header_range(&mut rng, start + 1..end, head.hash()); self.tx.insert_headers(headers.iter())?; headers.insert(0, head); Ok(headers) diff --git a/crates/stages/src/stages/tx_lookup.rs b/crates/stages/src/stages/tx_lookup.rs index d59209007..4afec7459 100644 --- a/crates/stages/src/stages/tx_lookup.rs +++ b/crates/stages/src/stages/tx_lookup.rs @@ -198,7 +198,10 @@ mod tests { TestTransaction, UnwindStageTestRunner, }; use assert_matches::assert_matches; - use reth_interfaces::test_utils::generators::{random_block, random_block_range}; + use reth_interfaces::test_utils::{ + generators, + generators::{random_block, random_block_range}, + }; use reth_primitives::{stage::StageUnitCheckpoint, BlockNumber, SealedBlock, H256}; use reth_provider::TransactionsProvider; @@ -208,6 +211,7 @@ mod tests { #[tokio::test] async fn execute_single_transaction_lookup() { let (previous_stage, stage_progress) = (500, 100); + let mut rng = generators::rng(); // Set up the runner let runner = TransactionLookupTestRunner::default(); @@ -220,7 +224,13 @@ mod tests { let non_empty_block_number = stage_progress + 10; let blocks = (stage_progress..=input.target()) .map(|number| { - random_block(number, None, Some((number == non_empty_block_number) as u8), None) + random_block( + &mut rng, + number, + None, + Some((number == non_empty_block_number) as u8), + None, + ) }) .collect::>(); runner.tx.insert_blocks(blocks.iter(), None).expect("failed to insert blocks"); @@ -256,9 +266,11 @@ mod tests { target: Some(previous_stage), checkpoint: Some(StageCheckpoint::new(stage_progress)), }; + let mut rng = generators::rng(); // Seed only once with full input range - let seed = random_block_range(stage_progress + 1..=previous_stage, H256::zero(), 0..4); // set tx count range high enough to hit the threshold + let seed = + random_block_range(&mut rng, stage_progress + 1..=previous_stage, H256::zero(), 0..4); // set tx count range high enough to hit the threshold runner.tx.insert_blocks(seed.iter(), None).expect("failed to seed execution"); let total_txs = runner.tx.table::().unwrap().len() as u64; @@ -366,8 +378,9 @@ mod tests { fn seed_execution(&mut self, input: ExecInput) -> Result { let stage_progress = input.checkpoint().block_number; let end = input.target(); + let mut rng = generators::rng(); - let blocks = random_block_range(stage_progress + 1..=end, H256::zero(), 0..2); + let blocks = random_block_range(&mut rng, stage_progress + 1..=end, H256::zero(), 0..2); self.tx.insert_blocks(blocks.iter(), None)?; Ok(blocks) }