refactor: store plain receipts instead Options in Receipts (#14010)

This commit is contained in:
Arsenii Kulikov
2025-01-27 20:05:48 +04:00
committed by GitHub
parent 0fa79c6c65
commit cde951732e
22 changed files with 88 additions and 128 deletions

2
Cargo.lock generated
View File

@ -8688,9 +8688,7 @@ dependencies = [
"alloy-eips", "alloy-eips",
"alloy-primitives", "alloy-primitives",
"reth-ethereum-forks", "reth-ethereum-forks",
"reth-execution-errors",
"reth-primitives", "reth-primitives",
"reth-primitives-traits",
"reth-prune-types", "reth-prune-types",
"reth-storage-api", "reth-storage-api",
"reth-storage-errors", "reth-storage-errors",

View File

@ -675,13 +675,7 @@ impl<N: NodePrimitives> BlockState<N> {
receipts.receipt_vec.len() receipts.receipt_vec.len()
); );
receipts receipts.receipt_vec.first().cloned().unwrap_or_default()
.receipt_vec
.first()
.map(|block_receipts| {
block_receipts.iter().filter_map(|opt_receipt| opt_receipt.clone()).collect()
})
.unwrap_or_default()
} }
/// Returns a vector of __parent__ `BlockStates`. /// Returns a vector of __parent__ `BlockStates`.
@ -1272,7 +1266,7 @@ mod tests {
#[test] #[test]
fn test_state_receipts() { fn test_state_receipts() {
let receipts = Receipts { receipt_vec: vec![vec![Some(Receipt::default())]] }; let receipts = Receipts { receipt_vec: vec![vec![Receipt::default()]] };
let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default(); let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
let block = let block =
test_block_builder.get_executed_block_with_receipts(receipts.clone(), B256::random()); test_block_builder.get_executed_block_with_receipts(receipts.clone(), B256::random());

View File

@ -334,7 +334,7 @@ mod tests {
}; };
// Wrap the receipt in a `Receipts` structure, as expected in the `ExecutionOutcome`. // Wrap the receipt in a `Receipts` structure, as expected in the `ExecutionOutcome`.
let receipts = Receipts { receipt_vec: vec![vec![Some(receipt1.clone())]] }; let receipts = Receipts { receipt_vec: vec![vec![receipt1.clone()]] };
// Define an `ExecutionOutcome` with the created receipts. // Define an `ExecutionOutcome` with the created receipts.
let execution_outcome = ExecutionOutcome { receipts, ..Default::default() }; let execution_outcome = ExecutionOutcome { receipts, ..Default::default() };
@ -393,7 +393,7 @@ mod tests {
success: false, success: false,
..Default::default() ..Default::default()
}; };
let old_receipts = Receipts { receipt_vec: vec![vec![Some(old_receipt.clone())]] }; let old_receipts = Receipts { receipt_vec: vec![vec![old_receipt.clone()]] };
let old_execution_outcome = let old_execution_outcome =
ExecutionOutcome { receipts: old_receipts, ..Default::default() }; ExecutionOutcome { receipts: old_receipts, ..Default::default() };
@ -424,7 +424,7 @@ mod tests {
success: true, success: true,
..Default::default() ..Default::default()
}; };
let new_receipts = Receipts { receipt_vec: vec![vec![Some(new_receipt.clone())]] }; let new_receipts = Receipts { receipt_vec: vec![vec![new_receipt.clone()]] };
let new_execution_outcome = let new_execution_outcome =
ExecutionOutcome { receipts: new_receipts, ..Default::default() }; ExecutionOutcome { receipts: new_receipts, ..Default::default() };

View File

@ -296,7 +296,7 @@ impl<N: NodePrimitives> TestBlockBuilder<N> {
let execution_outcome = ExecutionOutcome::new( let execution_outcome = ExecutionOutcome::new(
bundle_state_builder.build(), bundle_state_builder.build(),
vec![vec![None]].into(), vec![vec![]].into(),
block.number, block.number,
Vec::new(), Vec::new(),
); );

View File

@ -348,13 +348,13 @@ where
cumulative_gas_used += exec_result.result.gas_used(); cumulative_gas_used += exec_result.result.gas_used();
#[allow(clippy::needless_update)] // side-effect of optimism fields #[allow(clippy::needless_update)] // side-effect of optimism fields
receipts.push(Some(Receipt { receipts.push(Receipt {
tx_type: tx.tx_type(), tx_type: tx.tx_type(),
success: exec_result.result.is_success(), success: exec_result.result.is_success(),
cumulative_gas_used, cumulative_gas_used,
logs: exec_result.result.into_logs().into_iter().collect(), logs: exec_result.result.into_logs().into_iter().collect(),
..Default::default() ..Default::default()
})); });
// append transaction to the list of executed transactions // append transaction to the list of executed transactions
transactions.push(tx); transactions.push(tx);

View File

@ -327,13 +327,13 @@ where
// Push transaction changeset and calculate header bloom filter for receipt. // Push transaction changeset and calculate header bloom filter for receipt.
#[allow(clippy::needless_update)] // side-effect of optimism fields #[allow(clippy::needless_update)] // side-effect of optimism fields
receipts.push(Some(Receipt { receipts.push(Receipt {
tx_type: tx.tx_type(), tx_type: tx.tx_type(),
success: result.is_success(), success: result.is_success(),
cumulative_gas_used, cumulative_gas_used,
logs: result.into_logs().into_iter().collect(), logs: result.into_logs().into_iter().collect(),
..Default::default() ..Default::default()
})); });
// update add to total fees // update add to total fees
let miner_fee = let miner_fee =
@ -356,7 +356,7 @@ where
// calculate the requests and the requests root // calculate the requests and the requests root
let requests = if chain_spec.is_prague_active_at_timestamp(attributes.timestamp) { let requests = if chain_spec.is_prague_active_at_timestamp(attributes.timestamp) {
let deposit_requests = parse_deposits_from_receipts(&chain_spec, receipts.iter().flatten()) let deposit_requests = parse_deposits_from_receipts(&chain_spec, receipts.iter())
.map_err(|err| PayloadBuilderError::Internal(RethError::Execution(err.into())))?; .map_err(|err| PayloadBuilderError::Internal(RethError::Execution(err.into())))?;
let mut requests = Requests::default(); let mut requests = Requests::default();

View File

@ -170,7 +170,7 @@ impl<N: NodePrimitives> Chain<N> {
} }
/// Returns an iterator over all the receipts of the blocks in the chain. /// Returns an iterator over all the receipts of the blocks in the chain.
pub fn block_receipts_iter(&self) -> impl Iterator<Item = &Vec<Option<N::Receipt>>> + '_ { pub fn block_receipts_iter(&self) -> impl Iterator<Item = &Vec<N::Receipt>> + '_ {
self.execution_outcome.receipts().iter() self.execution_outcome.receipts().iter()
} }
@ -182,7 +182,7 @@ impl<N: NodePrimitives> Chain<N> {
/// Returns an iterator over all blocks and their receipts in the chain. /// Returns an iterator over all blocks and their receipts in the chain.
pub fn blocks_and_receipts( pub fn blocks_and_receipts(
&self, &self,
) -> impl Iterator<Item = (&RecoveredBlock<N::Block>, &Vec<Option<N::Receipt>>)> + '_ { ) -> impl Iterator<Item = (&RecoveredBlock<N::Block>, &Vec<N::Receipt>)> + '_ {
self.blocks_iter().zip(self.block_receipts_iter()) self.blocks_iter().zip(self.block_receipts_iter())
} }
@ -233,7 +233,7 @@ impl<N: NodePrimitives> Chain<N> {
/// Get all receipts for the given block. /// Get all receipts for the given block.
pub fn receipts_by_block_hash(&self, block_hash: BlockHash) -> Option<Vec<&N::Receipt>> { pub fn receipts_by_block_hash(&self, block_hash: BlockHash) -> Option<Vec<&N::Receipt>> {
let num = self.block_number(block_hash)?; let num = self.block_number(block_hash)?;
self.execution_outcome.receipts_by_block(num).iter().map(Option::as_ref).collect() Some(self.execution_outcome.receipts_by_block(num).iter().collect())
} }
/// Get all receipts with attachment. /// Get all receipts with attachment.
@ -248,11 +248,8 @@ impl<N: NodePrimitives> Chain<N> {
self.blocks().iter().zip(self.execution_outcome.receipts().iter()) self.blocks().iter().zip(self.execution_outcome.receipts().iter())
{ {
let mut tx_receipts = Vec::with_capacity(receipts.len()); let mut tx_receipts = Vec::with_capacity(receipts.len());
for (tx, receipt) in block.body().transactions_iter().zip(receipts.iter()) { for (tx, receipt) in block.body().transactions().iter().zip(receipts.iter()) {
tx_receipts.push(( tx_receipts.push((tx.trie_hash(), receipt.clone()));
tx.trie_hash(),
receipt.as_ref().expect("receipts have not been pruned").clone(),
));
} }
let block_num_hash = BlockNumHash::new(*block_num, block.hash()); let block_num_hash = BlockNumHash::new(*block_num, block.hash());
receipt_attach.push(BlockReceipts { block: block_num_hash, tx_receipts }); receipt_attach.push(BlockReceipts { block: block_num_hash, tx_receipts });
@ -887,8 +884,7 @@ mod tests {
}; };
// Create a Receipts object with a vector of receipt vectors // Create a Receipts object with a vector of receipt vectors
let receipts = let receipts = Receipts { receipt_vec: vec![vec![receipt1.clone()], vec![receipt2]] };
Receipts { receipt_vec: vec![vec![Some(receipt1.clone())], vec![Some(receipt2)]] };
// Create an ExecutionOutcome object with the created bundle, receipts, an empty requests // Create an ExecutionOutcome object with the created bundle, receipts, an empty requests
// vector, and first_block set to 10 // vector, and first_block set to 10
@ -913,7 +909,7 @@ mod tests {
// Create an ExecutionOutcome object with a single receipt vector containing receipt1 // Create an ExecutionOutcome object with a single receipt vector containing receipt1
let execution_outcome1 = ExecutionOutcome { let execution_outcome1 = ExecutionOutcome {
bundle: Default::default(), bundle: Default::default(),
receipts: Receipts { receipt_vec: vec![vec![Some(receipt1)]] }, receipts: Receipts { receipt_vec: vec![vec![receipt1]] },
requests: vec![], requests: vec![],
first_block: 10, first_block: 10,
}; };

View File

@ -199,7 +199,7 @@ impl<T> ExecutionOutcome<T> {
block_number: BlockNumber, block_number: BlockNumber,
f: impl FnOnce(&[&T]) -> B256, f: impl FnOnce(&[&T]) -> B256,
) -> Option<B256> { ) -> Option<B256> {
self.receipts.root_slow(self.block_number_to_index(block_number)?, f) Some(self.receipts.root_slow(self.block_number_to_index(block_number)?, f))
} }
/// Returns reference to receipts. /// Returns reference to receipts.
@ -213,7 +213,7 @@ impl<T> ExecutionOutcome<T> {
} }
/// Return all block receipts /// Return all block receipts
pub fn receipts_by_block(&self, block_number: BlockNumber) -> &[Option<T>] { pub fn receipts_by_block(&self, block_number: BlockNumber) -> &[T] {
let Some(index) = self.block_number_to_index(block_number) else { return &[] }; let Some(index) = self.block_number_to_index(block_number) else { return &[] };
&self.receipts[index] &self.receipts[index]
} }
@ -352,7 +352,7 @@ impl<T: Receipt<Log = Log>> ExecutionOutcome<T> {
/// Returns an iterator over all block logs. /// Returns an iterator over all block logs.
pub fn logs(&self, block_number: BlockNumber) -> Option<impl Iterator<Item = &Log>> { pub fn logs(&self, block_number: BlockNumber) -> Option<impl Iterator<Item = &Log>> {
let index = self.block_number_to_index(block_number)?; let index = self.block_number_to_index(block_number)?;
Some(self.receipts[index].iter().filter_map(|r| Some(r.as_ref()?.logs().iter())).flatten()) Some(self.receipts[index].iter().flat_map(|r| r.logs()))
} }
/// Return blocks logs bloom /// Return blocks logs bloom
@ -367,9 +367,9 @@ impl ExecutionOutcome {
/// Note: this function calculated Bloom filters for every receipt and created merkle trees /// Note: this function calculated Bloom filters for every receipt and created merkle trees
/// of receipt. This is a expensive operation. /// of receipt. This is a expensive operation.
pub fn ethereum_receipts_root(&self, _block_number: BlockNumber) -> Option<B256> { pub fn ethereum_receipts_root(&self, _block_number: BlockNumber) -> Option<B256> {
self.receipts.root_slow(self.block_number_to_index(_block_number)?, |receipts| { Some(self.receipts.root_slow(self.block_number_to_index(_block_number)?, |receipts| {
reth_primitives::Receipt::calculate_receipt_root_no_memo(receipts) reth_primitives::Receipt::calculate_receipt_root_no_memo(receipts)
}) }))
} }
} }
@ -497,12 +497,12 @@ mod tests {
fn test_get_logs() { fn test_get_logs() {
// Create a Receipts object with a vector of receipt vectors // Create a Receipts object with a vector of receipt vectors
let receipts = Receipts { let receipts = Receipts {
receipt_vec: vec![vec![Some(reth_ethereum_primitives::Receipt { receipt_vec: vec![vec![reth_ethereum_primitives::Receipt {
tx_type: TxType::Legacy, tx_type: TxType::Legacy,
cumulative_gas_used: 46913, cumulative_gas_used: 46913,
logs: vec![Log::<LogData>::default()], logs: vec![Log::<LogData>::default()],
success: true, success: true,
})]], }]],
}; };
// Define the first block number // Define the first block number

View File

@ -434,7 +434,7 @@ where
self.strategy.state_mut().merge_transitions(retention); self.strategy.state_mut().merge_transitions(retention);
// store receipts in the set // store receipts in the set
self.batch_record.save_receipts(receipts)?; self.batch_record.save_receipts(receipts);
// store requests in the set // store requests in the set
self.batch_record.save_requests(requests); self.batch_record.save_requests(requests);

View File

@ -64,7 +64,7 @@ impl<DB> Executor<DB> for MockExecutorProvider {
self.exec_results.lock().pop().unwrap(); self.exec_results.lock().pop().unwrap();
Ok(BlockExecutionOutput { Ok(BlockExecutionOutput {
state: bundle, state: bundle,
receipts: receipts.into_iter().flatten().flatten().collect(), receipts: receipts.into_iter().flatten().collect(),
requests: requests.into_iter().fold(Requests::default(), |mut reqs, req| { requests: requests.into_iter().fold(Requests::default(), |mut reqs, req| {
reqs.extend(req); reqs.extend(req);
reqs reqs

View File

@ -121,13 +121,13 @@ where
} }
if block_number == number { if block_number == number {
receipts_for_block.push(Some(receipt)); receipts_for_block.push(receipt);
} else { } else {
receipts.push(receipts_for_block); receipts.push(receipts_for_block);
// next block // next block
block_number = number; block_number = number;
receipts_for_block = vec![Some(receipt)]; receipts_for_block = vec![receipt];
} }
} }
None => { None => {
@ -585,8 +585,8 @@ mod test {
assert_eq!(2, total_receipts); assert_eq!(2, total_receipts);
assert_eq!(0, first_block); assert_eq!(0, first_block);
assert!(receipts[0].is_empty()); assert!(receipts[0].is_empty());
assert_eq!(receipt_block_1().receipt, receipts[1][0].clone().unwrap()); assert_eq!(receipt_block_1().receipt, receipts[1][0].clone());
assert_eq!(receipt_block_2().receipt, receipts[2][0].clone().unwrap()); assert_eq!(receipt_block_2().receipt, receipts[2][0].clone());
assert!(receipts[3].is_empty()); assert!(receipts[3].is_empty());
} }
@ -621,9 +621,9 @@ mod test {
assert_eq!(2, total_receipts); assert_eq!(2, total_receipts);
assert_eq!(0, first_block); assert_eq!(0, first_block);
assert!(receipts[0].is_empty()); assert!(receipts[0].is_empty());
assert_eq!(receipt_block_1().receipt, receipts[1][0].clone().unwrap()); assert_eq!(receipt_block_1().receipt, receipts[1][0].clone());
assert!(receipts[2].is_empty()); assert!(receipts[2].is_empty());
assert_eq!(receipt_block_3().receipt, receipts[3][0].clone().unwrap()); assert_eq!(receipt_block_3().receipt, receipts[3][0].clone());
} }
#[tokio::test] #[tokio::test]
@ -658,9 +658,9 @@ mod test {
assert_eq!(4, total_receipts); assert_eq!(4, total_receipts);
assert_eq!(0, first_block); assert_eq!(0, first_block);
assert!(receipts[0].is_empty()); assert!(receipts[0].is_empty());
assert_eq!(receipt_block_1().receipt, receipts[1][0].clone().unwrap()); assert_eq!(receipt_block_1().receipt, receipts[1][0].clone());
assert_eq!(receipt_block_2().receipt, receipts[2][0].clone().unwrap()); assert_eq!(receipt_block_2().receipt, receipts[2][0].clone());
assert_eq!(receipt_block_2().receipt, receipts[2][1].clone().unwrap()); assert_eq!(receipt_block_2().receipt, receipts[2][1].clone());
assert_eq!(receipt_block_3().receipt, receipts[3][0].clone().unwrap()); assert_eq!(receipt_block_3().receipt, receipts[3][0].clone());
} }
} }

View File

@ -442,8 +442,8 @@ mod tests {
.unwrap(); .unwrap();
let receipts = executor.receipts(); let receipts = executor.receipts();
let tx_receipt = receipts[0][0].as_ref().unwrap(); let tx_receipt = &receipts[0][0];
let deposit_receipt = receipts[0][1].as_ref().unwrap(); let deposit_receipt = &receipts[0][1];
assert!(!matches!(tx_receipt, OpReceipt::Deposit(_))); assert!(!matches!(tx_receipt, OpReceipt::Deposit(_)));
// deposit_nonce is present only in deposit transactions // deposit_nonce is present only in deposit transactions
@ -518,8 +518,8 @@ mod tests {
.expect("Executing a block while canyon is active should not fail"); .expect("Executing a block while canyon is active should not fail");
let receipts = executor.receipts(); let receipts = executor.receipts();
let tx_receipt = receipts[0][0].as_ref().unwrap(); let tx_receipt = &receipts[0][0];
let deposit_receipt = receipts[0][1].as_ref().unwrap(); let deposit_receipt = &receipts[0][1];
// deposit_receipt_version is set to 1 for post canyon deposit transactions // deposit_receipt_version is set to 1 for post canyon deposit transactions
assert!(!matches!(tx_receipt, OpReceipt::Deposit(_))); assert!(!matches!(tx_receipt, OpReceipt::Deposit(_)));

View File

@ -528,8 +528,7 @@ mod tests {
}); });
// Create a Receipts object with a vector of receipt vectors // Create a Receipts object with a vector of receipt vectors
let receipts = let receipts = Receipts { receipt_vec: vec![vec![receipt1.clone()], vec![receipt2]] };
Receipts { receipt_vec: vec![vec![Some(receipt1.clone())], vec![Some(receipt2)]] };
// Create an ExecutionOutcome object with the created bundle, receipts, an empty requests // Create an ExecutionOutcome object with the created bundle, receipts, an empty requests
// vector, and first_block set to 10 // vector, and first_block set to 10
@ -551,7 +550,7 @@ mod tests {
// Create an ExecutionOutcome object with a single receipt vector containing receipt1 // Create an ExecutionOutcome object with a single receipt vector containing receipt1
let execution_outcome1 = ExecutionOutcome { let execution_outcome1 = ExecutionOutcome {
bundle: Default::default(), bundle: Default::default(),
receipts: Receipts { receipt_vec: vec![vec![Some(receipt1)]] }, receipts: Receipts { receipt_vec: vec![vec![receipt1]] },
requests: vec![], requests: vec![],
first_block: 10, first_block: 10,
}; };
@ -667,11 +666,11 @@ mod tests {
fn test_get_logs() { fn test_get_logs() {
// Create a Receipts object with a vector of receipt vectors // Create a Receipts object with a vector of receipt vectors
let receipts = Receipts { let receipts = Receipts {
receipt_vec: vec![vec![Some(OpReceipt::Legacy(Receipt { receipt_vec: vec![vec![OpReceipt::Legacy(Receipt {
cumulative_gas_used: 46913, cumulative_gas_used: 46913,
logs: vec![Log::<LogData>::default()], logs: vec![Log::<LogData>::default()],
status: true.into(), status: true.into(),
}))]], })]],
}; };
// Define the first block number // Define the first block number

View File

@ -24,7 +24,7 @@ pub use reth_ethereum_primitives::Receipt;
)] )]
pub struct Receipts<T = Receipt> { pub struct Receipts<T = Receipt> {
/// A two-dimensional vector of optional `Receipt` instances. /// A two-dimensional vector of optional `Receipt` instances.
pub receipt_vec: Vec<Vec<Option<T>>>, pub receipt_vec: Vec<Vec<T>>,
} }
impl<T> Receipts<T> { impl<T> Receipts<T> {
@ -39,26 +39,25 @@ impl<T> Receipts<T> {
} }
/// Push a new vector of receipts into the `Receipts` collection. /// Push a new vector of receipts into the `Receipts` collection.
pub fn push(&mut self, receipts: Vec<Option<T>>) { pub fn push(&mut self, receipts: Vec<T>) {
self.receipt_vec.push(receipts); self.receipt_vec.push(receipts);
} }
/// Retrieves all recorded receipts from index and calculates the root using the given closure. /// Retrieves all recorded receipts from index and calculates the root using the given closure.
pub fn root_slow(&self, index: usize, f: impl FnOnce(&[&T]) -> B256) -> Option<B256> { pub fn root_slow(&self, index: usize, f: impl FnOnce(&[&T]) -> B256) -> B256 {
let receipts = let receipts = self.receipt_vec[index].iter().collect::<Vec<_>>();
self.receipt_vec[index].iter().map(Option::as_ref).collect::<Option<Vec<_>>>()?; f(receipts.as_slice())
Some(f(receipts.as_slice()))
} }
} }
impl<T> From<Vec<T>> for Receipts<T> { impl<T> From<Vec<T>> for Receipts<T> {
fn from(block_receipts: Vec<T>) -> Self { fn from(block_receipts: Vec<T>) -> Self {
Self { receipt_vec: vec![block_receipts.into_iter().map(Option::Some).collect()] } Self { receipt_vec: vec![block_receipts.into_iter().collect()] }
} }
} }
impl<T> FromIterator<Vec<Option<T>>> for Receipts<T> { impl<T> FromIterator<Vec<T>> for Receipts<T> {
fn from_iter<I: IntoIterator<Item = Vec<Option<T>>>>(iter: I) -> Self { fn from_iter<I: IntoIterator<Item = Vec<T>>>(iter: I) -> Self {
iter.into_iter().collect::<Vec<_>>().into() iter.into_iter().collect::<Vec<_>>().into()
} }
} }

View File

@ -15,11 +15,9 @@ workspace = true
# reth # reth
reth-primitives.workspace = true reth-primitives.workspace = true
reth-storage-errors.workspace = true reth-storage-errors.workspace = true
reth-execution-errors.workspace = true
reth-prune-types.workspace = true reth-prune-types.workspace = true
reth-storage-api.workspace = true reth-storage-api.workspace = true
reth-trie = { workspace = true, optional = true } reth-trie = { workspace = true, optional = true }
reth-primitives-traits.workspace = true
# alloy # alloy
alloy-eips.workspace = true alloy-eips.workspace = true
@ -42,7 +40,6 @@ std = [
"revm/std", "revm/std",
"alloy-eips/std", "alloy-eips/std",
"alloy-consensus/std", "alloy-consensus/std",
"reth-primitives-traits/std",
"reth-ethereum-forks/std" "reth-ethereum-forks/std"
] ]
witness = ["dep:reth-trie"] witness = ["dep:reth-trie"]
@ -52,14 +49,12 @@ test-utils = [
"reth-trie?/test-utils", "reth-trie?/test-utils",
"revm/test-utils", "revm/test-utils",
"reth-prune-types/test-utils", "reth-prune-types/test-utils",
"reth-primitives-traits/test-utils",
] ]
serde = [ serde = [
"revm/serde", "revm/serde",
"alloy-eips/serde", "alloy-eips/serde",
"alloy-primitives/serde", "alloy-primitives/serde",
"alloy-consensus/serde", "alloy-consensus/serde",
"reth-primitives-traits/serde",
"reth-trie?/serde", "reth-trie?/serde",
"reth-ethereum-forks/serde" "reth-ethereum-forks/serde"
] ]

View File

@ -3,10 +3,8 @@
use alloc::vec::Vec; use alloc::vec::Vec;
use alloy_eips::eip7685::Requests; use alloy_eips::eip7685::Requests;
use alloy_primitives::{BlockNumber, Log}; use alloy_primitives::BlockNumber;
use reth_execution_errors::BlockExecutionError;
use reth_primitives::Receipts; use reth_primitives::Receipts;
use reth_primitives_traits::Receipt;
use reth_prune_types::PruneModes; use reth_prune_types::PruneModes;
use revm::db::states::bundle_state::BundleRetention; use revm::db::states::bundle_state::BundleRetention;
@ -120,14 +118,8 @@ impl<T> BlockBatchRecord<T> {
} }
/// Save receipts to the executor. /// Save receipts to the executor.
pub fn save_receipts(&mut self, receipts: Vec<T>) -> Result<(), BlockExecutionError> pub fn save_receipts(&mut self, receipts: Vec<T>) {
where
T: Receipt<Log = Log>,
{
let receipts = receipts.into_iter().map(Some).collect();
// Save receipts.
self.receipts.push(receipts); self.receipts.push(receipts);
Ok(())
} }
/// Save EIP-7685 requests to the executor. /// Save EIP-7685 requests to the executor.
@ -146,8 +138,7 @@ mod tests {
// Create an empty vector of receipts // Create an empty vector of receipts
let receipts = vec![]; let receipts = vec![];
// Verify that saving receipts completes without error recorder.save_receipts(receipts);
assert!(recorder.save_receipts(receipts).is_ok());
// Verify that the saved receipts are equal to a nested empty vector // Verify that the saved receipts are equal to a nested empty vector
assert_eq!(*recorder.receipts(), vec![vec![]].into()); assert_eq!(*recorder.receipts(), vec![vec![]].into());
} }

View File

@ -516,9 +516,7 @@ where
for block_receipts in chain_change.receipts { for block_receipts in chain_change.receipts {
this.on_new_receipts( this.on_new_receipts(
block_receipts.block_hash, block_receipts.block_hash,
Ok(Some(Arc::new( Ok(Some(Arc::new(block_receipts.receipts))),
block_receipts.receipts.into_iter().flatten().collect(),
))),
); );
} }
} }
@ -530,9 +528,7 @@ where
for block_receipts in chain_change.receipts { for block_receipts in chain_change.receipts {
this.on_reorg_receipts( this.on_reorg_receipts(
block_receipts.block_hash, block_receipts.block_hash,
Ok(Some(Arc::new( Ok(Some(Arc::new(block_receipts.receipts))),
block_receipts.receipts.into_iter().flatten().collect(),
))),
); );
} }
} }
@ -558,7 +554,7 @@ enum CacheAction<B: Block, R> {
struct BlockReceipts<R> { struct BlockReceipts<R> {
block_hash: B256, block_hash: B256,
receipts: Vec<Option<R>>, receipts: Vec<R>,
} }
/// A change of the canonical chain /// A change of the canonical chain

View File

@ -250,7 +250,7 @@ pub async fn fee_history_cache_new_blocks_task<St, Provider, N>(
let (blocks, receipts): (Vec<_>, Vec<_>) = committed let (blocks, receipts): (Vec<_>, Vec<_>) = committed
.blocks_and_receipts() .blocks_and_receipts()
.map(|(block, receipts)| { .map(|(block, receipts)| {
(block.clone_sealed_block(), Arc::new(receipts.iter().flatten().cloned().collect::<Vec<_>>())) (block.clone_sealed_block(), Arc::new(receipts.clone()))
}) })
.unzip(); .unzip();
fee_history_cache.insert_blocks(blocks.iter().zip(receipts)).await; fee_history_cache.insert_blocks(blocks.iter().zip(receipts)).await;

View File

@ -198,7 +198,7 @@ impl<N: ProviderNodeTypes> ConsistentProvider<N> {
let receipt = receipt_iter let receipt = receipt_iter
.next() .next()
.ok_or_else(|| ProviderError::ReceiptNotFound(tx_num.into()))?; .ok_or_else(|| ProviderError::ReceiptNotFound(tx_num.into()))?;
block_receipts.push(Some(receipt)); block_receipts.push(receipt);
} }
receipts.push(block_receipts); receipts.push(block_receipts);
} }

View File

@ -1810,8 +1810,7 @@ impl<TX: DbTxMut + DbTx + 'static, N: NodeTypesForProvider> StateWriter
)); ));
} }
let has_receipts_pruning = self.prune_modes.has_receipts_pruning() || let has_receipts_pruning = self.prune_modes.has_receipts_pruning();
execution_outcome.receipts.iter().flatten().any(|receipt| receipt.is_none());
// Prepare receipts cursor if we are going to write receipts to the database // Prepare receipts cursor if we are going to write receipts to the database
// //
@ -1869,26 +1868,21 @@ impl<TX: DbTxMut + DbTx + 'static, N: NodeTypesForProvider> StateWriter
for (idx, receipt) in receipts.iter().enumerate() { for (idx, receipt) in receipts.iter().enumerate() {
let receipt_idx = first_tx_index + idx as u64; let receipt_idx = first_tx_index + idx as u64;
if let Some(receipt) = receipt { // Skip writing receipt if log filter is active and it does not have any logs to
// Skip writing receipt if log filter is active and it does not have any logs to // retain
// retain if prunable_receipts &&
if prunable_receipts && has_contract_log_filter &&
has_contract_log_filter && !receipt.logs().iter().any(|log| allowed_addresses.contains(&log.address))
!receipt {
.logs() continue
.iter() }
.any(|log| allowed_addresses.contains(&log.address))
{
continue
}
if let Some(writer) = &mut receipts_static_writer { if let Some(writer) = &mut receipts_static_writer {
writer.append_receipt(receipt_idx, receipt)?; writer.append_receipt(receipt_idx, receipt)?;
} }
if let Some(cursor) = &mut receipts_cursor { if let Some(cursor) = &mut receipts_cursor {
cursor.append(receipt_idx, receipt)?; cursor.append(receipt_idx, receipt)?;
}
} }
} }
} }
@ -2283,9 +2277,7 @@ impl<TX: DbTxMut + DbTx + 'static, N: NodeTypesForProvider> StateWriter
let mut block_receipts = Vec::with_capacity(block_body.tx_count as usize); let mut block_receipts = Vec::with_capacity(block_body.tx_count as usize);
for num in block_body.tx_num_range() { for num in block_body.tx_num_range() {
if receipts_iter.peek().is_some_and(|(n, _)| *n == num) { if receipts_iter.peek().is_some_and(|(n, _)| *n == num) {
block_receipts.push(receipts_iter.next().map(|(_, r)| r)); block_receipts.push(receipts_iter.next().unwrap().1);
} else {
block_receipts.push(None);
} }
} }
receipts.push(block_receipts); receipts.push(block_receipts);

View File

@ -207,7 +207,7 @@ fn block1(number: BlockNumber) -> (RecoveredBlock<reth_primitives::Block>, Execu
.revert_account_info(number, account2, Some(None)) .revert_account_info(number, account2, Some(None))
.state_storage(account1, HashMap::from_iter([(slot, (U256::ZERO, U256::from(10)))])) .state_storage(account1, HashMap::from_iter([(slot, (U256::ZERO, U256::from(10)))]))
.build(), .build(),
vec![vec![Some( vec![vec![
#[allow(clippy::needless_update)] // side-effect of optimism fields #[allow(clippy::needless_update)] // side-effect of optimism fields
Receipt { Receipt {
tx_type: TxType::Eip2930, tx_type: TxType::Eip2930,
@ -220,7 +220,7 @@ fn block1(number: BlockNumber) -> (RecoveredBlock<reth_primitives::Block>, Execu
)], )],
..Default::default() ..Default::default()
}, },
)]] ]]
.into(), .into(),
number, number,
Vec::new(), Vec::new(),
@ -266,7 +266,7 @@ fn block2(
) )
.revert_storage(number, account, Vec::from([(slot, U256::from(10))])) .revert_storage(number, account, Vec::from([(slot, U256::from(10))]))
.build(), .build(),
vec![vec![Some( vec![vec![
#[allow(clippy::needless_update)] // side-effect of optimism fields #[allow(clippy::needless_update)] // side-effect of optimism fields
Receipt { Receipt {
tx_type: TxType::Eip1559, tx_type: TxType::Eip1559,
@ -279,7 +279,7 @@ fn block2(
)], )],
..Default::default() ..Default::default()
}, },
)]] ]]
.into(), .into(),
number, number,
Vec::new(), Vec::new(),
@ -334,7 +334,7 @@ fn block3(
} }
let execution_outcome = ExecutionOutcome::new( let execution_outcome = ExecutionOutcome::new(
bundle_state_builder.build(), bundle_state_builder.build(),
vec![vec![Some( vec![vec![
#[allow(clippy::needless_update)] // side-effect of optimism fields #[allow(clippy::needless_update)] // side-effect of optimism fields
Receipt { Receipt {
tx_type: TxType::Eip1559, tx_type: TxType::Eip1559,
@ -347,7 +347,7 @@ fn block3(
)], )],
..Default::default() ..Default::default()
}, },
)]] ]]
.into(), .into(),
number, number,
Vec::new(), Vec::new(),
@ -422,7 +422,7 @@ fn block4(
} }
let execution_outcome = ExecutionOutcome::new( let execution_outcome = ExecutionOutcome::new(
bundle_state_builder.build(), bundle_state_builder.build(),
vec![vec![Some( vec![vec![
#[allow(clippy::needless_update)] // side-effect of optimism fields #[allow(clippy::needless_update)] // side-effect of optimism fields
Receipt { Receipt {
tx_type: TxType::Eip1559, tx_type: TxType::Eip1559,
@ -435,7 +435,7 @@ fn block4(
)], )],
..Default::default() ..Default::default()
}, },
)]] ]]
.into(), .into(),
number, number,
Vec::new(), Vec::new(),
@ -507,7 +507,7 @@ fn block5(
} }
let execution_outcome = ExecutionOutcome::new( let execution_outcome = ExecutionOutcome::new(
bundle_state_builder.build(), bundle_state_builder.build(),
vec![vec![Some( vec![vec![
#[allow(clippy::needless_update)] // side-effect of optimism fields #[allow(clippy::needless_update)] // side-effect of optimism fields
Receipt { Receipt {
tx_type: TxType::Eip1559, tx_type: TxType::Eip1559,
@ -520,7 +520,7 @@ fn block5(
)], )],
..Default::default() ..Default::default()
}, },
)]] ]]
.into(), .into(),
number, number,
Vec::new(), Vec::new(),

View File

@ -1059,7 +1059,7 @@ mod tests {
fn revert_to_indices() { fn revert_to_indices() {
let base: ExecutionOutcome = ExecutionOutcome { let base: ExecutionOutcome = ExecutionOutcome {
bundle: BundleState::default(), bundle: BundleState::default(),
receipts: vec![vec![Some(Receipt::default()); 2]; 7].into(), receipts: vec![vec![Receipt::default(); 2]; 7].into(),
first_block: 10, first_block: 10,
requests: Vec::new(), requests: Vec::new(),
}; };
@ -1270,7 +1270,7 @@ mod tests {
let mut test: ExecutionOutcome = ExecutionOutcome { let mut test: ExecutionOutcome = ExecutionOutcome {
bundle: present_state, bundle: present_state,
receipts: vec![vec![Some(Receipt::default()); 2]; 1].into(), receipts: vec![vec![Receipt::default(); 2]; 1].into(),
first_block: 2, first_block: 2,
requests: Vec::new(), requests: Vec::new(),
}; };