Skip to content

Commit 7653e81

Browse files
authoredMay 22, 2024··
perf(primitives): avoid cloning receipts when calculating the root (#8350)
1 parent d0386b8 commit 7653e81

File tree

7 files changed

+39
-37
lines changed

7 files changed

+39
-37
lines changed
 

‎Cargo.lock

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎crates/ethereum/consensus/src/validation.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use reth_consensus::ConsensusError;
22
use reth_primitives::{
3-
gas_spent_by_transactions, BlockWithSenders, Bloom, ChainSpec, GotExpected, Receipt,
4-
ReceiptWithBloom, B256,
3+
gas_spent_by_transactions, BlockWithSenders, Bloom, ChainSpec, GotExpected, Receipt, B256,
54
};
65

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

2423
// Check if gas used matches the value set in header.
@@ -36,16 +35,16 @@ pub fn validate_block_post_execution(
3635

3736
/// Calculate the receipts root, and compare it against against the expected receipts root and logs
3837
/// bloom.
39-
fn verify_receipts<'a>(
38+
fn verify_receipts(
4039
expected_receipts_root: B256,
4140
expected_logs_bloom: Bloom,
42-
receipts: impl Iterator<Item = &'a Receipt> + Clone,
41+
receipts: &[Receipt],
4342
) -> Result<(), ConsensusError> {
4443
// Calculate receipts root.
45-
let receipts_with_bloom = receipts.map(|r| r.clone().into()).collect::<Vec<ReceiptWithBloom>>();
46-
let receipts_root = reth_primitives::proofs::calculate_receipt_root(&receipts_with_bloom);
44+
let receipts_with_bloom = receipts.iter().map(Receipt::with_bloom_ref).collect::<Vec<_>>();
45+
let receipts_root = reth_primitives::proofs::calculate_receipt_root_ref(&receipts_with_bloom);
4746

48-
// Create header log bloom.
47+
// Calculate header logs bloom.
4948
let logs_bloom = receipts_with_bloom.iter().fold(Bloom::ZERO, |bloom, r| bloom | r.bloom);
5049

5150
compare_receipts_root_and_logs_bloom(

‎crates/optimism/consensus/src/validation.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use reth_consensus::ConsensusError;
22
use reth_primitives::{
33
gas_spent_by_transactions, proofs::calculate_receipt_root_optimism, BlockWithSenders, Bloom,
4-
ChainSpec, GotExpected, Receipt, ReceiptWithBloom, B256,
4+
ChainSpec, GotExpected, Receipt, B256,
55
};
66

77
/// Validate a block with regard to execution results:
@@ -21,7 +21,7 @@ pub fn validate_block_post_execution(
2121
verify_receipts(
2222
block.header.receipts_root,
2323
block.header.logs_bloom,
24-
receipts.iter(),
24+
receipts,
2525
chain_spec,
2626
block.timestamp,
2727
)?;
@@ -41,19 +41,19 @@ pub fn validate_block_post_execution(
4141
}
4242

4343
/// Verify the calculated receipts root against the expected receipts root.
44-
fn verify_receipts<'a>(
44+
fn verify_receipts(
4545
expected_receipts_root: B256,
4646
expected_logs_bloom: Bloom,
47-
receipts: impl Iterator<Item = &'a Receipt> + Clone,
47+
receipts: &[Receipt],
4848
chain_spec: &ChainSpec,
4949
timestamp: u64,
5050
) -> Result<(), ConsensusError> {
5151
// Calculate receipts root.
52-
let receipts_with_bloom = receipts.map(|r| r.clone().into()).collect::<Vec<ReceiptWithBloom>>();
52+
let receipts_with_bloom = receipts.iter().cloned().map(Receipt::with_bloom).collect::<Vec<_>>();
5353
let receipts_root =
5454
calculate_receipt_root_optimism(&receipts_with_bloom, chain_spec, timestamp);
5555

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

5959
compare_receipts_root_and_logs_bloom(

‎crates/primitives/src/log.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
use crate::Bloom;
22

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

65
/// Calculate receipt logs bloom.
7-
pub fn logs_bloom<'a, It>(logs: It) -> Bloom
8-
where
9-
It: IntoIterator<Item = &'a Log>,
10-
{
6+
pub fn logs_bloom<'a>(logs: impl IntoIterator<Item = &'a Log>) -> Bloom {
117
let mut bloom = Bloom::ZERO;
128
for log in logs {
139
bloom.m3_2048(log.address.as_slice());

‎crates/primitives/src/proofs.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use crate::{
88
B256, U256,
99
};
1010
use alloy_rlp::Encodable;
11-
use bytes::BufMut;
1211
use itertools::Itertools;
1312

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

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

43-
index_buffer.clear();
44-
index.encode(&mut index_buffer);
41+
let index_buffer = alloy_rlp::encode_fixed_size(&index);
4542

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

104+
/// Calculates the receipt root for a header.
105+
pub fn calculate_receipt_root_ref(receipts: &[ReceiptWithBloomRef<'_>]) -> B256 {
106+
ordered_trie_root_with_encoder(receipts, |r, buf| r.encode_inner(buf, false))
107+
}
108+
107109
/// Calculates the receipt root for a header for the reference type of [Receipt].
108110
///
109-
/// NOTE: Prefer [calculate_receipt_root] if you have log blooms memoized.
110-
pub fn calculate_receipt_root_ref(receipts: &[&Receipt]) -> B256 {
111+
/// NOTE: Prefer [`calculate_receipt_root`] if you have log blooms memoized.
112+
pub fn calculate_receipt_root_no_memo(receipts: &[&Receipt]) -> B256 {
111113
ordered_trie_root_with_encoder(receipts, |r, buf| {
112114
ReceiptWithBloomRef::from(*r).encode_inner(buf, false)
113115
})
114116
}
115117

116118
/// Calculates the receipt root for a header for the reference type of [Receipt].
117119
///
118-
/// NOTE: Prefer [calculate_receipt_root] if you have log blooms memoized.
120+
/// NOTE: Prefer [`calculate_receipt_root_optimism`] if you have log blooms memoized.
119121
#[cfg(feature = "optimism")]
120-
pub fn calculate_receipt_root_ref_optimism(
122+
pub fn calculate_receipt_root_no_memo_optimism(
121123
receipts: &[&Receipt],
122124
chain_spec: &crate::ChainSpec,
123125
timestamp: u64,

‎crates/primitives/src/receipt.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ impl Receipt {
5656
pub fn with_bloom(self) -> ReceiptWithBloom {
5757
self.into()
5858
}
59+
60+
/// Calculates the bloom filter for the receipt and returns the [ReceiptWithBloomRef] container
61+
/// type.
62+
pub fn with_bloom_ref(&self) -> ReceiptWithBloomRef<'_> {
63+
self.into()
64+
}
5965
}
6066

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

99105
/// Retrieves the receipt root for all recorded receipts from index.
100106
pub fn root_slow(&self, index: usize) -> Option<B256> {
101-
Some(crate::proofs::calculate_receipt_root_ref(
107+
Some(crate::proofs::calculate_receipt_root_no_memo(
102108
&self.receipt_vec[index].iter().map(Option::as_ref).collect::<Option<Vec<_>>>()?,
103109
))
104110
}
@@ -111,7 +117,7 @@ impl Receipts {
111117
chain_spec: &crate::ChainSpec,
112118
timestamp: u64,
113119
) -> Option<B256> {
114-
Some(crate::proofs::calculate_receipt_root_ref_optimism(
120+
Some(crate::proofs::calculate_receipt_root_no_memo_optimism(
115121
&self.receipt_vec[index].iter().map(Option::as_ref).collect::<Option<Vec<_>>>()?,
116122
chain_spec,
117123
timestamp,

‎crates/storage/provider/src/bundle_state/bundle_state_with_receipts.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,11 @@ impl BundleStateWithReceipts {
182182
/// Returns the receipt root for all recorded receipts.
183183
/// Note: this function calculated Bloom filters for every receipt and created merkle trees
184184
/// of receipt. This is a expensive operation.
185-
#[allow(unused_variables)]
186-
pub fn receipts_root_slow(&self, block_number: BlockNumber) -> Option<B256> {
185+
pub fn receipts_root_slow(&self, _block_number: BlockNumber) -> Option<B256> {
187186
#[cfg(feature = "optimism")]
188187
panic!("This should not be called in optimism mode. Use `optimism_receipts_root_slow` instead.");
189188
#[cfg(not(feature = "optimism"))]
190-
self.receipts.root_slow(self.block_number_to_index(block_number)?)
189+
self.receipts.root_slow(self.block_number_to_index(_block_number)?)
191190
}
192191

193192
/// Returns the receipt root for all recorded receipts.

0 commit comments

Comments
 (0)
Please sign in to comment.