[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
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)]
supernovahs marked this conversation as resolved.
Show resolved Hide resolved
#[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)]
supernovahs marked this conversation as resolved.
Show resolved Hide resolved
#[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)]
supernovahs marked this conversation as resolved.
Show resolved Hide resolved
#[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)]
supernovahs marked this conversation as resolved.
Show resolved Hide resolved
#[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
Loading