Skip to content

Commit

Permalink
fix block proptests
Browse files Browse the repository at this point in the history
  • Loading branch information
Rjected committed Jun 20, 2024
1 parent db638e3 commit b1dc8ec
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 21 deletions.
44 changes: 42 additions & 2 deletions crates/primitives-traits/src/header/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ use alloy_primitives::{keccak256, Address, BlockNumber, Bloom, Bytes, B256, B64,
use alloy_rlp::{length_of_length, Decodable, Encodable};
use bytes::BufMut;
use core::mem;
use reth_codecs::{main_codec, Compact};
use reth_codecs::{add_arbitrary_tests, main_codec, Compact};
use revm_primitives::{calc_blob_gasprice, calc_excess_blob_gas};

/// Block header
#[main_codec]
#[main_codec(no_arbitrary)]
#[add_arbitrary_tests(rlp, 25)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Header {
/// The Keccak 256-bit hash of the parent
Expand Down Expand Up @@ -487,3 +488,42 @@ impl Decodable for Header {
Ok(this)
}
}

#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for Header {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
// Generate an arbitrary header, passing it to the generate_valid_header function to make
// sure it is valid _with respect to hardforks only_.
let base = Self {
parent_hash: u.arbitrary()?,
ommers_hash: u.arbitrary()?,
beneficiary: u.arbitrary()?,
state_root: u.arbitrary()?,
transactions_root: u.arbitrary()?,
receipts_root: u.arbitrary()?,
logs_bloom: u.arbitrary()?,
difficulty: u.arbitrary()?,
number: u.arbitrary()?,
gas_limit: u.arbitrary()?,
gas_used: u.arbitrary()?,
timestamp: u.arbitrary()?,
extra_data: u.arbitrary()?,
mix_hash: u.arbitrary()?,
nonce: u.arbitrary()?,
base_fee_per_gas: u.arbitrary()?,
blob_gas_used: u.arbitrary()?,
excess_blob_gas: u.arbitrary()?,
parent_beacon_block_root: u.arbitrary()?,
requests_root: u.arbitrary()?,
withdrawals_root: u.arbitrary()?,
};

Ok(test_utils::generate_valid_header(
base,
u.arbitrary()?,
u.arbitrary()?,
u.arbitrary()?,
u.arbitrary()?,
))
}
}
10 changes: 1 addition & 9 deletions crates/primitives-traits/src/header/sealed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,6 @@ impl proptest::arbitrary::Arbitrary for SealedHeader {
#[cfg(any(test, feature = "arbitrary"))]
impl<'a> arbitrary::Arbitrary<'a> for SealedHeader {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let sealed_header = crate::test_utils::generate_valid_header(
u.arbitrary()?,
u.arbitrary()?,
u.arbitrary()?,
u.arbitrary()?,
u.arbitrary()?,
)
.seal_slow();
Ok(sealed_header)
Ok(Header::arbitrary(u)?.seal_slow())
}
}
31 changes: 24 additions & 7 deletions crates/primitives/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ prop_compose! {
/// Ethereum full block.
///
/// Withdrawals can be optionally included at the end of the RLP encoded message.
#[derive_arbitrary(rlp, 25)]
#[add_arbitrary_tests(rlp, 25)]
#[derive(
Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, Deref, RlpEncodable, RlpDecodable,
)]
Expand Down Expand Up @@ -171,6 +171,28 @@ impl Block {
}
}

#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for Block {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
// first generate up to 100 txs
let transactions = (0..100)
.map(|_| TransactionSigned::arbitrary(u))
.collect::<arbitrary::Result<Vec<_>>>()?;

// then generate up to 2 ommers
let ommers = (0..2).map(|_| Header::arbitrary(u)).collect::<arbitrary::Result<Vec<_>>>()?;

Ok(Self {
header: u.arbitrary()?,
body: transactions,
ommers,
// for now just generate empty requests, see HACK above
requests: u.arbitrary()?,
withdrawals: u.arbitrary()?,
})
}
}

/// Sealed block with senders recovered from transactions.
#[derive(Debug, Clone, PartialEq, Eq, Default, Deref, DerefMut)]
pub struct BlockWithSenders {
Expand Down Expand Up @@ -567,12 +589,7 @@ impl<'a> arbitrary::Arbitrary<'a> for BlockBody {
let ommers = (0..2).map(|_| Header::arbitrary(u)).collect::<arbitrary::Result<Vec<_>>>()?;

// for now just generate empty requests, see HACK above
Ok(Self {
transactions,
ommers,
requests: None,
withdrawals: arbitrary::Arbitrary::arbitrary(u)?,
})
Ok(Self { transactions, ommers, requests: None, withdrawals: u.arbitrary()? })
}
}

Expand Down
14 changes: 11 additions & 3 deletions crates/primitives/src/transaction/eip4844.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,20 +148,28 @@ impl TxEip4844 {
/// - `max_fee_per_blob_gas`
/// - `blob_versioned_hashes`
pub fn decode_inner(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
Ok(Self {
let mut tx = Self {
chain_id: Decodable::decode(buf)?,
nonce: Decodable::decode(buf)?,
max_priority_fee_per_gas: Decodable::decode(buf)?,
max_fee_per_gas: Decodable::decode(buf)?,
gas_limit: Decodable::decode(buf)?,
placeholder: Some(()),
placeholder: None,
to: Decodable::decode(buf)?,
value: Decodable::decode(buf)?,
input: Decodable::decode(buf)?,
access_list: Decodable::decode(buf)?,
max_fee_per_blob_gas: Decodable::decode(buf)?,
blob_versioned_hashes: Decodable::decode(buf)?,
})
};

// HACK: our arbitrary implementation sets the placeholder this way for backwards
// compatibility, and should be removed once `placeholder` can be removed
if tx.to != Address::default() {
tx.placeholder = Some(())
}

Ok(tx)
}

/// Outputs the length of the transaction's fields, without a RLP header.
Expand Down

0 comments on commit b1dc8ec

Please sign in to comment.