Skip to content

Commit

Permalink
remove proptest specific encoding logic (paradigmxyz#6503)
Browse files Browse the repository at this point in the history
Co-authored-by: Dan Cline <[email protected]>
  • Loading branch information
supernovahs and Rjected authored Feb 28, 2024
1 parent 790bc62 commit 3519270
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 119 deletions.
1 change: 0 additions & 1 deletion crates/net/downloaders/src/file_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,6 @@ mod tests {
async fn test_download_headers_from_file() {
// Generate some random blocks
let (file, headers, _) = generate_bodies_file(0..=19).await;

// now try to read them back
let client = Arc::new(FileClient::from_file(file).await.unwrap());

Expand Down
41 changes: 39 additions & 2 deletions crates/net/eth-wire/src/types/blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@
//! types.
use alloy_rlp::{RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper};
use reth_codecs::derive_arbitrary;
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 @@ -38,14 +43,46 @@ pub struct GetBlockHeaders {
}

/// The response to [`GetBlockHeaders`], containing headers if any headers were found.
#[derive_arbitrary(rlp)]
#[derive(Clone, Debug, PartialEq, Eq, RlpEncodableWrapper, RlpDecodableWrapper, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[add_arbitrary_tests(rlp, 10)]
pub struct BlockHeaders(
/// The requested headers.
pub Vec<Header>,
);

#[cfg(any(test, feature = "arbitrary"))]
impl proptest::arbitrary::Arbitrary for BlockHeaders {
type Parameters = ();
type Strategy = proptest::prelude::BoxedStrategy<Self>;

fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
let headers_strategy = vec(valid_header_strategy(), 0..10); // Adjust the range as needed

headers_strategy.prop_map(BlockHeaders).boxed()
}
}

#[cfg(any(test, feature = "arbitrary"))]
impl<'a> arbitrary::Arbitrary<'a> for BlockHeaders {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let headers_count: usize = u.int_in_range(0..=10)?;
let mut headers = Vec::with_capacity(headers_count);

for _ in 0..headers_count {
headers.push(generate_valid_header(
u.arbitrary()?,
u.arbitrary()?,
u.arbitrary()?,
u.arbitrary()?,
u.arbitrary()?,
))
}

Ok(BlockHeaders(headers))
}
}

impl From<Vec<Header>> for BlockHeaders {
fn from(headers: Vec<Header>) -> Self {
BlockHeaders(headers)
Expand Down
2 changes: 1 addition & 1 deletion crates/net/eth-wire/src/types/broadcast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ impl From<NewBlockHashes> for Vec<BlockHashNumber> {

/// A new block with the current total difficulty, which includes the difficulty of the returned
/// block.
#[derive_arbitrary(rlp, 25)]
#[derive(Clone, Debug, PartialEq, Eq, RlpEncodable, RlpDecodable, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive_arbitrary(rlp, 25)]
pub struct NewBlock {
/// A new block.
pub block: Block,
Expand Down
103 changes: 94 additions & 9 deletions crates/primitives/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use crate::{
TransactionSignedEcRecovered, Withdrawals, B256,
};
use alloy_rlp::{RlpDecodable, RlpEncodable};
#[cfg(any(test, feature = "arbitrary"))]
use proptest::prelude::{any, prop_compose};
use reth_codecs::derive_arbitrary;
use serde::{Deserialize, Serialize};
use std::ops::Deref;
Expand All @@ -14,19 +16,34 @@ pub use reth_rpc_types::{
/// Ethereum full block.
///
/// Withdrawals can be optionally included at the end of the RLP encoded message.
#[derive_arbitrary(rlp, 25)]
#[derive(
Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, RlpEncodable, RlpDecodable,
)]
#[derive_arbitrary(rlp, 25)]
#[rlp(trailing)]
pub struct Block {
/// Block header.
#[cfg_attr(any(test, feature = "arbitrary"), proptest(strategy = "valid_header_strategy()"))]
pub header: Header,
/// Transactions in this block.
#[cfg_attr(
any(test, feature = "arbitrary"),
proptest(
strategy = "proptest::collection::vec(proptest::arbitrary::any::<TransactionSigned>(), 0..=100)"
)
)]
pub body: Vec<TransactionSigned>,
/// Ommers/uncles header.
#[cfg_attr(
any(test, feature = "arbitrary"),
proptest(strategy = "proptest::collection::vec(valid_header_strategy(), 0..=2)")
)]
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 @@ -206,7 +223,7 @@ impl std::ops::DerefMut for BlockWithSenders {
/// Sealed Ethereum full block.
///
/// Withdrawals can be optionally included at the end of the RLP encoded message.
#[derive_arbitrary(rlp, 10)]
#[derive_arbitrary(rlp)]
#[derive(
Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, RlpEncodable, RlpDecodable,
)]
Expand All @@ -215,13 +232,87 @@ pub struct SealedBlock {
/// Locked block header.
pub header: SealedHeader,
/// Transactions with signatures.
#[cfg_attr(
any(test, feature = "arbitrary"),
proptest(
strategy = "proptest::collection::vec(proptest::arbitrary::any::<TransactionSigned>(), 0..=100)"
)
)]
pub body: Vec<TransactionSigned>,
/// Ommer/uncle headers
#[cfg_attr(
any(test, feature = "arbitrary"),
proptest(strategy = "proptest::collection::vec(valid_header_strategy(), 0..=2)")
)]
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! {
/// 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 {
generate_valid_header(header, eip_4844_active, blob_gas_used, excess_blob_gas, parent_beacon_block_root)
}
}

impl SealedBlock {
/// Create a new sealed block instance using the sealed header and block body.
#[inline]
Expand Down Expand Up @@ -466,16 +557,10 @@ pub struct BlockBody {
/// Uncle headers for the given block
#[cfg_attr(
any(test, feature = "arbitrary"),
proptest(
strategy = "proptest::collection::vec(proptest::arbitrary::any::<Header>(), 0..=2)"
)
proptest(strategy = "proptest::collection::vec(valid_header_strategy(), 0..=2)")
)]
pub ommers: Vec<Header>,
/// Withdrawals in the block.
#[cfg_attr(
any(test, feature = "arbitrary"),
proptest(strategy = "proptest::option::of(proptest::arbitrary::any::<Withdrawals>())")
)]
pub withdrawals: Option<Withdrawals>,
}

Expand Down
Loading

0 comments on commit 3519270

Please sign in to comment.