Remove TestRandom (#9006)

We  have a legacy `TestRandom` trait which generates random types for testing and fuzzing.
This function overlaps with `arbitrary` which is used very commonly in the ecosystem.


  Remove `TestRandom` and generate random type instances using `Arbitrary`.


Co-Authored-By: Mac L <mjladson@pm.me>

Co-Authored-By: Michael Sproul <michael@sigmaprime.io>
This commit is contained in:
Mac L
2026-05-05 10:35:57 +04:00
committed by GitHub
parent 4b314d8e79
commit 3351db1ba8
121 changed files with 418 additions and 1141 deletions

View File

@@ -1041,8 +1041,6 @@ mod test {
EphemeralHarnessType, NumBlobs, generate_data_column_indices_rand_order,
generate_rand_block_and_data_columns, get_kzg,
};
use rand::SeedableRng;
use rand::prelude::StdRng;
use slot_clock::{SlotClock, TestingSlotClock};
use std::collections::HashSet;
use std::sync::Arc;
@@ -1061,7 +1059,7 @@ mod test {
fn should_exclude_rpc_columns_not_required_for_sampling() {
// SETUP
let spec = Arc::new(ForkName::Fulu.make_genesis_spec(E::default_spec()));
let mut rng = StdRng::seed_from_u64(0xDEADBEEF0BAD5EEDu64);
let mut u = types::test_utils::test_unstructured();
let da_checker = new_da_checker(spec.clone());
let custody_context = &da_checker.custody_context;
@@ -1093,9 +1091,10 @@ mod test {
let (_, data_columns) = generate_rand_block_and_data_columns::<E>(
ForkName::Fulu,
NumBlobs::Number(1),
&mut rng,
&mut u,
&spec,
);
)
.unwrap();
let block_root = Hash256::random();
// Get 10 columns using the "latest" CGC (head) that block lookup would use.
// The CGC change becomes effective after CUSTODY_CHANGE_DA_EFFECTIVE_DELAY_SECONDS,
@@ -1147,7 +1146,7 @@ mod test {
fn should_exclude_gossip_columns_not_required_for_sampling() {
// SETUP
let spec = Arc::new(ForkName::Fulu.make_genesis_spec(E::default_spec()));
let mut rng = StdRng::seed_from_u64(0xDEADBEEF0BAD5EEDu64);
let mut u = types::test_utils::test_unstructured();
let da_checker = new_da_checker(spec.clone());
let custody_context = &da_checker.custody_context;
@@ -1180,9 +1179,10 @@ mod test {
let (_, data_columns) = generate_rand_block_and_data_columns::<E>(
ForkName::Fulu,
NumBlobs::Number(1),
&mut rng,
&mut u,
&spec,
);
)
.unwrap();
let block_root = Hash256::random();
// Get 10 columns using the "latest" CGC that gossip subscriptions would use.
// The CGC change becomes effective after CUSTODY_CHANGE_DA_EFFECTIVE_DELAY_SECONDS,
@@ -1230,7 +1230,7 @@ mod test {
#[test]
fn verify_kzg_for_range_sync_blocks_should_not_truncate_data_columns_fulu() {
let spec = Arc::new(ForkName::Fulu.make_genesis_spec(E::default_spec()));
let mut rng = StdRng::seed_from_u64(0xDEADBEEF0BAD5EEDu64);
let mut u = types::test_utils::test_unstructured();
let da_checker = new_da_checker(spec.clone());
// GIVEN multiple RPC blocks with data columns totalling more than 128
@@ -1239,9 +1239,10 @@ mod test {
let (block, data_columns) = generate_rand_block_and_data_columns::<E>(
ForkName::Fulu,
NumBlobs::Number(1),
&mut rng,
&mut u,
&spec,
);
)
.unwrap();
let custody_columns = if index == 0 {
// 128 valid data columns in the first block
@@ -1293,7 +1294,7 @@ mod test {
fn should_exclude_reconstructed_columns_not_required_for_sampling() {
// SETUP
let spec = Arc::new(ForkName::Fulu.make_genesis_spec(E::default_spec()));
let mut rng = StdRng::seed_from_u64(0xDEADBEEF0BAD5EEDu64);
let mut u = types::test_utils::test_unstructured();
let da_checker = new_da_checker(spec.clone());
let custody_context = &da_checker.custody_context;
@@ -1314,9 +1315,10 @@ mod test {
let (block, data_columns) = generate_rand_block_and_data_columns::<E>(
ForkName::Fulu,
NumBlobs::Number(1),
&mut rng,
&mut u,
&spec,
);
)
.unwrap();
let block_root = Hash256::random();
// Add the block to the DA checker
da_checker

View File

@@ -1077,13 +1077,11 @@ mod pending_components_tests {
use crate::PayloadVerificationOutcome;
use crate::block_verification_types::BlockImportData;
use crate::test_utils::{NumBlobs, generate_rand_block_and_blobs, test_spec};
use arbitrary::Arbitrary;
use fixed_bytes::FixedBytesExtended;
use fork_choice::PayloadVerificationStatus;
use kzg::KzgCommitment;
use rand::SeedableRng;
use rand::rngs::StdRng;
use state_processing::ConsensusContext;
use types::test_utils::TestRandom;
use types::{BeaconState, ForkName, MainnetEthSpec, SignedBeaconBlock, Slot};
type E = MainnetEthSpec;
@@ -1096,10 +1094,10 @@ mod pending_components_tests {
);
pub fn pre_setup() -> Setup<E> {
let mut rng = StdRng::seed_from_u64(0xDEADBEEF0BAD5EEDu64);
let mut u = types::test_utils::test_unstructured();
let spec = test_spec::<E>();
let (block, blobs_vec) =
generate_rand_block_and_blobs::<E>(ForkName::Deneb, NumBlobs::Random, &mut rng);
generate_rand_block_and_blobs::<E>(ForkName::Deneb, NumBlobs::Random, &mut u).unwrap();
let max_len = spec.max_blobs_per_block(block.epoch()) as usize;
let mut blobs: RuntimeFixedVector<Option<Arc<BlobSidecar<E>>>> =
RuntimeFixedVector::default(max_len);
@@ -1115,7 +1113,7 @@ mod pending_components_tests {
for (index, blob) in blobs.iter().enumerate() {
if let Some(invalid_blob) = blob {
let mut blob_copy = invalid_blob.as_ref().clone();
blob_copy.kzg_commitment = KzgCommitment::random_for_test(&mut rng);
blob_copy.kzg_commitment = KzgCommitment::arbitrary(&mut u).unwrap();
*invalid_blobs.get_mut(index).unwrap() = Some(Arc::new(blob_copy));
}
}

View File

@@ -582,20 +582,20 @@ mod tests {
use tree_hash::TreeHash;
use types::{
Attestation, AttestationBase, AttestationElectra, Fork, Hash256, SyncCommitteeMessage,
test_utils::{generate_deterministic_keypair, test_random_instance},
test_utils::{generate_deterministic_keypair, test_arbitrary_instance},
};
type E = types::MainnetEthSpec;
fn get_attestation_base(slot: Slot) -> Attestation<E> {
let mut a: AttestationBase<E> = test_random_instance();
let mut a: AttestationBase<E> = test_arbitrary_instance();
a.data.slot = slot;
a.aggregation_bits = BitList::with_capacity(4).expect("should create bitlist");
Attestation::Base(a)
}
fn get_attestation_electra(slot: Slot) -> Attestation<E> {
let mut a: AttestationElectra<E> = test_random_instance();
let mut a: AttestationElectra<E> = test_arbitrary_instance();
a.data.slot = slot;
a.aggregation_bits = BitList::with_capacity(4).expect("should create bitlist");
a.committee_bits = BitVector::new();
@@ -606,7 +606,7 @@ mod tests {
}
fn get_sync_contribution(slot: Slot) -> SyncCommitteeContribution<E> {
let mut a: SyncCommitteeContribution<E> = test_random_instance();
let mut a: SyncCommitteeContribution<E> = test_arbitrary_instance();
a.slot = slot;
a.aggregation_bits = BitVector::new();
a

View File

@@ -474,12 +474,12 @@ where
mod tests {
use super::*;
use fixed_bytes::FixedBytesExtended;
use types::{AttestationBase, Hash256, test_utils::test_random_instance};
use types::{AttestationBase, Hash256, test_utils::test_arbitrary_instance};
type E = types::MainnetEthSpec;
fn get_attestation(slot: Slot, beacon_block_root: u64) -> Attestation<E> {
let a: AttestationBase<E> = test_random_instance();
let a: AttestationBase<E> = test_arbitrary_instance();
let mut a = Attestation::Base(a);
a.data_mut().slot = slot;
a.data_mut().beacon_block_root = Hash256::from_low_u64_be(beacon_block_root);
@@ -487,7 +487,7 @@ mod tests {
}
fn get_sync_contribution(slot: Slot, beacon_block_root: u64) -> SyncCommitteeContribution<E> {
let mut a: SyncCommitteeContribution<E> = test_random_instance();
let mut a: SyncCommitteeContribution<E> = test_arbitrary_instance();
a.slot = slot;
a.beacon_block_root = Hash256::from_low_u64_be(beacon_block_root);
a

View File

@@ -20,6 +20,8 @@ pub use crate::{
sync_committee_verification::Error as SyncCommitteeError,
validator_monitor::{ValidatorMonitor, ValidatorMonitorConfig},
};
#[cfg(feature = "arbitrary")]
use arbitrary::Arbitrary;
use bls::get_withdrawal_credentials;
use bls::{
AggregateSignature, Keypair, PublicKey, PublicKeyBytes, SecretKey, Signature, SignatureBytes,
@@ -73,7 +75,6 @@ use typenum::U4294967296;
use types::attestation::IndexedAttestationBase;
use types::data::CustodyIndex;
use types::execution::BlockProductionVersion;
use types::test_utils::TestRandom;
pub use types::test_utils::generate_deterministic_keypairs;
use types::*;
@@ -96,7 +97,9 @@ pub const TEST_DATA_COLUMN_SIDECARS_GLOAS_SSZ: &[u8] =
pub const DEFAULT_TARGET_AGGREGATORS: u64 = u64::MAX;
// Minimum and maximum number of blobs to generate in each slot when using the `NumBlobs::Random` option (default).
#[cfg(feature = "arbitrary")]
const DEFAULT_MIN_BLOBS: usize = 1;
#[cfg(feature = "arbitrary")]
const DEFAULT_MAX_BLOBS: usize = 2;
static KZG: LazyLock<Arc<Kzg>> = LazyLock::new(|| {
@@ -3741,10 +3744,11 @@ pub enum NumBlobs {
None,
}
#[cfg(feature = "arbitrary")]
macro_rules! add_blob_transactions {
($message:expr, $payload_type:ty, $num_blobs:expr, $rng:expr, $fork_name:expr) => {{
($message:expr, $payload_type:ty, $num_blobs:expr, $u:expr, $fork_name:expr) => {{
let num_blobs = match $num_blobs {
NumBlobs::Random => $rng.random_range(DEFAULT_MIN_BLOBS..=DEFAULT_MAX_BLOBS),
NumBlobs::Random => $u.int_in_range(DEFAULT_MIN_BLOBS..=DEFAULT_MAX_BLOBS)?,
NumBlobs::Number(n) => n,
NumBlobs::None => 0,
};
@@ -3761,28 +3765,30 @@ macro_rules! add_blob_transactions {
}};
}
#[cfg(feature = "arbitrary")]
#[allow(clippy::type_complexity)]
pub fn generate_rand_block_and_blobs<E: EthSpec>(
fork_name: ForkName,
num_blobs: NumBlobs,
rng: &mut impl Rng,
) -> (SignedBeaconBlock<E, FullPayload<E>>, Vec<BlobSidecar<E>>) {
let inner = map_fork_name!(fork_name, BeaconBlock, <_>::random_for_test(rng));
u: &mut arbitrary::Unstructured,
) -> arbitrary::Result<(SignedBeaconBlock<E, FullPayload<E>>, Vec<BlobSidecar<E>>)> {
let inner = map_fork_name!(fork_name, BeaconBlock, <_>::arbitrary(&mut *u)?);
let mut block = SignedBeaconBlock::from_block(inner, Signature::random_for_test(rng));
let mut block = SignedBeaconBlock::from_block(inner, Signature::arbitrary(&mut *u)?);
let mut blob_sidecars = vec![];
let bundle = match block {
SignedBeaconBlock::Deneb(SignedBeaconBlockDeneb {
ref mut message, ..
}) => add_blob_transactions!(message, FullPayloadDeneb<E>, num_blobs, rng, fork_name),
}) => add_blob_transactions!(message, FullPayloadDeneb<E>, num_blobs, u, fork_name),
SignedBeaconBlock::Electra(SignedBeaconBlockElectra {
ref mut message, ..
}) => add_blob_transactions!(message, FullPayloadElectra<E>, num_blobs, rng, fork_name),
}) => add_blob_transactions!(message, FullPayloadElectra<E>, num_blobs, u, fork_name),
SignedBeaconBlock::Fulu(SignedBeaconBlockFulu {
ref mut message, ..
}) => add_blob_transactions!(message, FullPayloadFulu<E>, num_blobs, rng, fork_name),
}) => add_blob_transactions!(message, FullPayloadFulu<E>, num_blobs, u, fork_name),
// TODO(EIP-7732) Add `SignedBeaconBlock::Gloas` variant
_ => return (block, blob_sidecars),
_ => return Ok((block, blob_sidecars)),
};
let eth2::types::BlobsBundle {
@@ -3807,21 +3813,23 @@ pub fn generate_rand_block_and_blobs<E: EthSpec>(
.unwrap(),
});
}
(block, blob_sidecars)
Ok((block, blob_sidecars))
}
#[cfg(feature = "arbitrary")]
#[allow(clippy::type_complexity)]
pub fn generate_rand_block_and_data_columns<E: EthSpec>(
fork_name: ForkName,
num_blobs: NumBlobs,
rng: &mut impl Rng,
u: &mut arbitrary::Unstructured,
spec: &ChainSpec,
) -> (
) -> arbitrary::Result<(
SignedBeaconBlock<E, FullPayload<E>>,
DataColumnSidecarList<E>,
) {
let (block, _blobs) = generate_rand_block_and_blobs(fork_name, num_blobs, rng);
)> {
let (block, _blobs) = generate_rand_block_and_blobs(fork_name, num_blobs, u)?;
let data_columns = generate_data_column_sidecars_from_block(&block, spec);
(block, data_columns)
Ok((block, data_columns))
}
/// Generate data column sidecars from pre-computed cells and proofs.