[go: up one dir, main page]

Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

remove proptest specific encoding logic #6503

Merged
merged 22 commits into from
Feb 28, 2024
Prev Previous commit
Next Next commit
reusable strategy and generation method
  • Loading branch information
Rjected committed Feb 28, 2024
commit 868b70405134bfdf21cf7d7a18ab3bb14c4a3da0
78 changes: 12 additions & 66 deletions crates/net/eth-wire/src/types/blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ use alloy_rlp::{RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWra
use reth_codecs::{add_arbitrary_tests, derive_arbitrary};
use reth_primitives::{BlockBody, BlockHashOrNumber, Header, HeadersDirection, B256};

#[cfg(any(test, feature = "arbitrary"))]
use proptest::{collection::vec, prelude::*};
#[cfg(any(test, feature = "arbitrary"))]
use reth_primitives::{generate_valid_header, valid_header_strategy};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -52,42 +57,6 @@ impl proptest::arbitrary::Arbitrary for BlockHeaders {
type Strategy = proptest::prelude::BoxedStrategy<Self>;

fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
use proptest::{collection::vec, prelude::*};
prop_compose! {
fn valid_header_strategy()(
mut header in any::<Header>(),
eip_4844_active in any::<bool>(),
blob_gas_used in any::<u64>(),
excess_blob_gas in any::<u64>(),
parent_beacon_block_root in any::<B256>()
) -> Header {
// EIP-1559 logic
if header.base_fee_per_gas.is_none() {
// If EIP-1559 is not active, clear related fields
header.withdrawals_root = None;
header.blob_gas_used = None;
header.excess_blob_gas = None;
header.parent_beacon_block_root = None;
} else if header.withdrawals_root.is_none() {
// If EIP-4895 is not active, clear related fields
header.blob_gas_used = None;
header.excess_blob_gas = None;
header.parent_beacon_block_root = None;
} else if eip_4844_active {
// Set fields based on EIP-4844 being active
header.blob_gas_used = Some(blob_gas_used);
header.excess_blob_gas = Some(excess_blob_gas);
header.parent_beacon_block_root = Some(parent_beacon_block_root);
} else {
// If EIP-4844 is not active, clear related fields
header.blob_gas_used = None;
header.excess_blob_gas = None;
header.parent_beacon_block_root = None;
}

header
}
}
let headers_strategy = vec(valid_header_strategy(), 0..10); // Adjust the range as needed

headers_strategy.prop_map(BlockHeaders).boxed()
Expand All @@ -101,36 +70,13 @@ impl<'a> arbitrary::Arbitrary<'a> for BlockHeaders {
let mut headers = Vec::with_capacity(headers_count);

for _ in 0..headers_count {
let mut header: Header = Header::arbitrary(u)?;
let blob_gas_used: u64 = u.arbitrary()?;
let excess_blob_gas: u64 = u.arbitrary()?;
let parent_beacon_block_root: B256 = u.arbitrary()?;
// Determine if EIP-4844 is active using a random bool
let eip_4844_active: bool = u.arbitrary()?;
// EIP-1559 logic
if header.base_fee_per_gas.is_none() {
// If EIP-1559 is not active, clear related fields
header.withdrawals_root = None;
header.blob_gas_used = None;
header.excess_blob_gas = None;
header.parent_beacon_block_root = None;
} else if header.withdrawals_root.is_none() {
// If EIP-4895 is not active, clear related fields
header.blob_gas_used = None;
header.excess_blob_gas = None;
header.parent_beacon_block_root = None;
} else if eip_4844_active {
// Set fields based on EIP-4844 being active
header.blob_gas_used = Some(blob_gas_used);
header.excess_blob_gas = Some(excess_blob_gas);
header.parent_beacon_block_root = Some(parent_beacon_block_root);
} else {
// If EIP-4844 is not active, clear related fields
header.blob_gas_used = None;
header.excess_blob_gas = None;
header.parent_beacon_block_root = None;
}
headers.push(header);
headers.push(generate_valid_header(
u.arbitrary()?,
u.arbitrary()?,
u.arbitrary()?,
u.arbitrary()?,
u.arbitrary()?,
))
}

Ok(BlockHeaders(headers))
Expand Down
85 changes: 58 additions & 27 deletions crates/primitives/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ pub struct Block {
)]
pub ommers: Vec<Header>,
/// Block withdrawals.
#[cfg_attr(
any(test, feature = "arbitrary"),
proptest(strategy = "proptest::option::of(proptest::arbitrary::any::<Withdrawals>())")
)]
pub withdrawals: Option<Withdrawals>,
}

Expand Down Expand Up @@ -242,43 +246,70 @@ pub struct SealedBlock {
)]
pub ommers: Vec<Header>,
/// Block withdrawals.
#[cfg_attr(
any(test, feature = "arbitrary"),
proptest(strategy = "proptest::option::of(proptest::arbitrary::any::<Withdrawals>())")
)]
pub withdrawals: Option<Withdrawals>,
}

/// Generates a header which is valid __with respect to past and future forks__. This means, for
/// example, that if the withdrawals root is present, the base fee per gas is also present.
///
/// If blob gas used were present, then the excess blob gas and parent beacon block root are also
/// present. In this example, the withdrawals root would also be present.
///
/// This __does not, and should not guarantee__ that the header is valid with respect to __anything
/// else__.
#[cfg(any(test, feature = "arbitrary"))]
pub fn generate_valid_header(
mut header: Header,
eip_4844_active: bool,
blob_gas_used: u64,
excess_blob_gas: u64,
parent_beacon_block_root: B256,
) -> Header {
// EIP-1559 logic
if header.base_fee_per_gas.is_none() {
// If EIP-1559 is not active, clear related fields
header.withdrawals_root = None;
header.blob_gas_used = None;
header.excess_blob_gas = None;
header.parent_beacon_block_root = None;
} else if header.withdrawals_root.is_none() {
// If EIP-4895 is not active, clear related fields
header.blob_gas_used = None;
header.excess_blob_gas = None;
header.parent_beacon_block_root = None;
} else if eip_4844_active {
// Set fields based on EIP-4844 being active
header.blob_gas_used = Some(blob_gas_used);
header.excess_blob_gas = Some(excess_blob_gas);
header.parent_beacon_block_root = Some(parent_beacon_block_root);
} else {
// If EIP-4844 is not active, clear related fields
header.blob_gas_used = None;
header.excess_blob_gas = None;
header.parent_beacon_block_root = None;
}

header
}

#[cfg(any(test, feature = "arbitrary"))]
prop_compose! {
fn valid_header_strategy()(
mut header in any::<Header>(),
/// Generates a proptest strategy for constructing an instance of a header which is valid __with
/// respect to past and future forks__.
///
/// See docs for [generate_valid_header] for more information.
pub fn valid_header_strategy()(
header in any::<Header>(),
eip_4844_active in any::<bool>(),
blob_gas_used in any::<u64>(),
excess_blob_gas in any::<u64>(),
parent_beacon_block_root in any::<B256>()
) -> Header {
// EIP-1559 logic
if header.base_fee_per_gas.is_none() {
// If EIP-1559 is not active, clear related fields
header.withdrawals_root = None;
header.blob_gas_used = None;
header.excess_blob_gas = None;
header.parent_beacon_block_root = None;
} else if header.withdrawals_root.is_none() {
// If EIP-4895 is not active, clear related fields
header.blob_gas_used = None;
header.excess_blob_gas = None;
header.parent_beacon_block_root = None;
} else if eip_4844_active {
// Set fields based on EIP-4844 being active
header.blob_gas_used = Some(blob_gas_used);
header.excess_blob_gas = Some(excess_blob_gas);
header.parent_beacon_block_root = Some(parent_beacon_block_root);
} else {
// If EIP-4844 is not active, clear related fields
header.blob_gas_used = None;
header.excess_blob_gas = None;
header.parent_beacon_block_root = None;
}

header
generate_valid_header(header, eip_4844_active, blob_gas_used, excess_blob_gas, parent_beacon_block_root)
}
}

Expand Down
90 changes: 12 additions & 78 deletions crates/primitives/src/header.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
basefee::calculate_next_block_base_fee,
block::{generate_valid_header, valid_header_strategy},
constants,
constants::{
ALLOWED_FUTURE_BLOCK_TIME_SECONDS, EMPTY_OMMER_ROOT_HASH, EMPTY_ROOT_HASH,
Expand Down Expand Up @@ -840,91 +841,24 @@ impl SealedHeader {
impl proptest::arbitrary::Arbitrary for SealedHeader {
type Parameters = ();
fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
prop_compose! {
fn valid_header_strategy()(
mut header in any::<Header>(),
eip_4844_active in any::<bool>(),
blob_gas_used in any::<u64>(),
excess_blob_gas in any::<u64>(),
parent_beacon_block_root in any::<B256>()
) -> SealedHeader {
// EIP-1559 logic
if header.base_fee_per_gas.is_none() {
// If EIP-1559 is not active, clear related fields
header.withdrawals_root = None;
header.blob_gas_used = None;
header.excess_blob_gas = None;
header.parent_beacon_block_root = None;
} else if header.withdrawals_root.is_none() {
// If EIP-4895 is not active, clear related fields
header.blob_gas_used = None;
header.excess_blob_gas = None;
header.parent_beacon_block_root = None;
} else if eip_4844_active {
// Set fields based on EIP-4844 being active
header.blob_gas_used = Some(blob_gas_used);
header.excess_blob_gas = Some(excess_blob_gas);
header.parent_beacon_block_root = Some(parent_beacon_block_root);
} else {
// If EIP-4844 is not active, clear related fields
header.blob_gas_used = None;
header.excess_blob_gas = None;
header.parent_beacon_block_root = None;
}

// Seal the header
header.seal_slow()
}
}

valid_header_strategy().boxed()
// map valid header strategy by sealing
valid_header_strategy().prop_map(|header| header.seal_slow()).boxed()
}
type Strategy = proptest::strategy::BoxedStrategy<SealedHeader>;
}

#[cfg(any(test, feature = "arbitrary"))]
impl<'a> arbitrary::Arbitrary<'a> for SealedHeader {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
// Directly generate values for Header and BlockHash using Unstructured
let mut header: Header = u.arbitrary()?;
let block_hash: BlockHash = u.arbitrary()?;
let blob_gas_used: u64 = u.arbitrary()?;
let excess_blob_gas: u64 = u.arbitrary()?;
let parent_beacon_block_root: B256 = u.arbitrary()?;
// Determine if EIP-4844 is active using a random bool
let eip_4844_active: bool = u.arbitrary()?;

// Set fields based on EIP-1559 activation
if header.base_fee_per_gas.is_none() {
// EIP-1559 not active, clear related fields
header.withdrawals_root = None;
header.blob_gas_used = None;
header.excess_blob_gas = None;
header.parent_beacon_block_root = None;
} else {
// 4895 is not active
if header.withdrawals_root.is_none() {
header.blob_gas_used = None;
header.excess_blob_gas = None;
header.parent_beacon_block_root = None;
} else {
// 4895 is active
if eip_4844_active {
// EIP-4844 is active
header.blob_gas_used = Some(blob_gas_used);
header.excess_blob_gas = Some(excess_blob_gas);
header.parent_beacon_block_root = Some(parent_beacon_block_root);
} else {
// EIP-4844 is not active
header.blob_gas_used = None;
header.excess_blob_gas = None;
header.parent_beacon_block_root = None;
};
}
}

// Seal the header and create SealedHeader
Ok(SealedHeader { header, hash: block_hash })
let sealed_header = generate_valid_header(
u.arbitrary()?,
u.arbitrary()?,
u.arbitrary()?,
u.arbitrary()?,
u.arbitrary()?,
)
.seal_slow();
Ok(sealed_header)
}
}

Expand Down
2 changes: 2 additions & 0 deletions crates/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ pub mod trie;
mod withdrawal;

pub use account::{Account, Bytecode};
#[cfg(any(test, feature = "arbitrary"))]
pub use block::{generate_valid_header, valid_header_strategy};
pub use block::{
Block, BlockBody, BlockHashOrNumber, BlockId, BlockNumHash, BlockNumberOrTag, BlockWithSenders,
ForkBlock, RpcBlockHash, SealedBlock, SealedBlockWithSenders,
Expand Down
Loading