Skip to content

Commit

Permalink
perf(primitives): avoid cloning receipts when calculating the root
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes committed May 22, 2024
1 parent d0386b8 commit 87d7357
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 30 deletions.
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 6 additions & 7 deletions crates/ethereum/consensus/src/validation.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use reth_consensus::ConsensusError;
use reth_primitives::{
gas_spent_by_transactions, BlockWithSenders, Bloom, ChainSpec, GotExpected, Receipt,
ReceiptWithBloom, B256,
gas_spent_by_transactions, BlockWithSenders, Bloom, ChainSpec, GotExpected, Receipt, B256,
};

/// Validate a block with regard to execution results:
Expand All @@ -18,7 +17,7 @@ pub fn validate_block_post_execution(
// transaction This was replaced with is_success flag.
// See more about EIP here: https://eips.ethereum.org/EIPS/eip-658
if chain_spec.is_byzantium_active_at_block(block.header.number) {
verify_receipts(block.header.receipts_root, block.header.logs_bloom, receipts.iter())?;
verify_receipts(block.header.receipts_root, block.header.logs_bloom, receipts)?;
}

// Check if gas used matches the value set in header.
Expand All @@ -39,13 +38,13 @@ pub fn validate_block_post_execution(
fn verify_receipts<'a>(
expected_receipts_root: B256,
expected_logs_bloom: Bloom,
receipts: impl Iterator<Item = &'a Receipt> + Clone,
receipts: &[Receipt],
) -> Result<(), ConsensusError> {
// Calculate receipts root.
let receipts_with_bloom = receipts.map(|r| r.clone().into()).collect::<Vec<ReceiptWithBloom>>();
let receipts_root = reth_primitives::proofs::calculate_receipt_root(&receipts_with_bloom);
let receipts_with_bloom = receipts.iter().map(Receipt::with_bloom_ref).collect::<Vec<_>>();
let receipts_root = reth_primitives::proofs::calculate_receipt_root_ref(&receipts_with_bloom);

// Create header log bloom.
// Calculate header logs bloom.
let logs_bloom = receipts_with_bloom.iter().fold(Bloom::ZERO, |bloom, r| bloom | r.bloom);

compare_receipts_root_and_logs_bloom(
Expand Down
6 changes: 1 addition & 5 deletions crates/primitives/src/log.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
use crate::Bloom;

/// Re-export `Log` from `alloy_primitives`.
pub use alloy_primitives::Log;

/// Calculate receipt logs bloom.
pub fn logs_bloom<'a, It>(logs: It) -> Bloom
where
It: IntoIterator<Item = &'a Log>,
{
pub fn logs_bloom<'a>(logs: impl IntoIterator<Item = &'a Log>) -> Bloom {
let mut bloom = Bloom::ZERO;
for log in logs {
bloom.m3_2048(log.address.as_slice());
Expand Down
20 changes: 11 additions & 9 deletions crates/primitives/src/proofs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use crate::{
B256, U256,
};
use alloy_rlp::Encodable;
use bytes::BufMut;
use itertools::Itertools;

/// Adjust the index of an item for rlp encoding.
Expand All @@ -30,18 +29,16 @@ pub fn ordered_trie_root<T: Encodable>(items: &[T]) -> B256 {
/// Compute a trie root of the collection of items with a custom encoder.
pub fn ordered_trie_root_with_encoder<T, F>(items: &[T], mut encode: F) -> B256
where
F: FnMut(&T, &mut dyn BufMut),
F: FnMut(&T, &mut Vec<u8>),
{
let mut index_buffer = Vec::new();
let mut value_buffer = Vec::new();

let mut hb = HashBuilder::default();
let items_len = items.len();
for i in 0..items_len {
let index = adjust_index_for_rlp(i, items_len);

index_buffer.clear();
index.encode(&mut index_buffer);
let index_buffer = alloy_rlp::encode_fixed_size(&index);

value_buffer.clear();
encode(&items[index], &mut value_buffer);
Expand Down Expand Up @@ -104,20 +101,25 @@ pub fn calculate_receipt_root_optimism(
ordered_trie_root_with_encoder(receipts, |r, buf| r.encode_inner(buf, false))
}

/// Calculates the receipt root for a header.
pub fn calculate_receipt_root_ref(receipts: &[ReceiptWithBloomRef<'_>]) -> B256 {
ordered_trie_root_with_encoder(receipts, |r, buf| r.encode_inner(buf, false))
}

/// Calculates the receipt root for a header for the reference type of [Receipt].
///
/// NOTE: Prefer [calculate_receipt_root] if you have log blooms memoized.
pub fn calculate_receipt_root_ref(receipts: &[&Receipt]) -> B256 {
/// NOTE: Prefer [`calculate_receipt_root`] if you have log blooms memoized.
pub fn calculate_receipt_root_no_memo(receipts: &[&Receipt]) -> B256 {
ordered_trie_root_with_encoder(receipts, |r, buf| {
ReceiptWithBloomRef::from(*r).encode_inner(buf, false)
})
}

/// Calculates the receipt root for a header for the reference type of [Receipt].
///
/// NOTE: Prefer [calculate_receipt_root] if you have log blooms memoized.
/// NOTE: Prefer [`calculate_receipt_root_optimism`] if you have log blooms memoized.
#[cfg(feature = "optimism")]
pub fn calculate_receipt_root_ref_optimism(
pub fn calculate_receipt_root_no_memo_optimism(
receipts: &[&Receipt],
chain_spec: &crate::ChainSpec,
timestamp: u64,
Expand Down
10 changes: 8 additions & 2 deletions crates/primitives/src/receipt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ impl Receipt {
pub fn with_bloom(self) -> ReceiptWithBloom {
self.into()
}

/// Calculates the bloom filter for the receipt and returns the [ReceiptWithBloomRef] container
/// type.
pub fn with_bloom_ref(&self) -> ReceiptWithBloomRef<'_> {
self.into()
}
}

/// A collection of receipts organized as a two-dimensional vector.
Expand Down Expand Up @@ -98,7 +104,7 @@ impl Receipts {

/// Retrieves the receipt root for all recorded receipts from index.
pub fn root_slow(&self, index: usize) -> Option<B256> {
Some(crate::proofs::calculate_receipt_root_ref(
Some(crate::proofs::calculate_receipt_root_no_memo(
&self.receipt_vec[index].iter().map(Option::as_ref).collect::<Option<Vec<_>>>()?,
))
}
Expand All @@ -111,7 +117,7 @@ impl Receipts {
chain_spec: &crate::ChainSpec,
timestamp: u64,
) -> Option<B256> {
Some(crate::proofs::calculate_receipt_root_ref_optimism(
Some(crate::proofs::calculate_receipt_root_no_memo_optimism(
&self.receipt_vec[index].iter().map(Option::as_ref).collect::<Option<Vec<_>>>()?,
chain_spec,
timestamp,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,11 @@ impl BundleStateWithReceipts {
/// Returns the receipt root for all recorded receipts.
/// Note: this function calculated Bloom filters for every receipt and created merkle trees
/// of receipt. This is a expensive operation.
#[allow(unused_variables)]
pub fn receipts_root_slow(&self, block_number: BlockNumber) -> Option<B256> {
pub fn receipts_root_slow(&self, _block_number: BlockNumber) -> Option<B256> {
#[cfg(feature = "optimism")]
panic!("This should not be called in optimism mode. Use `optimism_receipts_root_slow` instead.");
#[cfg(not(feature = "optimism"))]
self.receipts.root_slow(self.block_number_to_index(block_number)?)
self.receipts.root_slow(self.block_number_to_index(_block_number)?)
}

/// Returns the receipt root for all recorded receipts.
Expand Down

0 comments on commit 87d7357

Please sign in to comment.