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

feat(primitives): add Receipts to encapsulate Vec<Vec<Option<Receipt>> #4626

Merged
merged 25 commits into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
fb2c736
receipts to encapsulate Vec<Vec<Option<Receipt>>
tcoratger Sep 16, 2023
23e7603
small fix
tcoratger Sep 16, 2023
03911fb
fix lint
tcoratger Sep 16, 2023
84bceb2
add is_empty for Receipts
tcoratger Sep 16, 2023
3008624
fix doc test
tcoratger Sep 16, 2023
7dab31d
add push function to Receipts
tcoratger Sep 18, 2023
0557ad4
add Deref and DerefMut impl for Receipts
tcoratger Sep 18, 2023
c68c9b0
add root_slow impl to Receipts
tcoratger Sep 18, 2023
0a6a90d
add gas_spent_by_tx in Receipts
tcoratger Sep 18, 2023
2f90e76
add error in gas_spent_by_tx
tcoratger Sep 18, 2023
0c26cc6
fix lint
tcoratger Sep 18, 2023
ef280ff
fix error
tcoratger Sep 19, 2023
63c0e3b
Merge branch 'main' into receipts
tcoratger Sep 20, 2023
ac7bfc8
add IntoIterator and FromIterator impl for Receipts
tcoratger Sep 20, 2023
a6c0efa
Merge branch 'receipts' of https://github.com/tcoratger/reth into rec…
tcoratger Sep 20, 2023
d594c70
fix root_slow
tcoratger Sep 20, 2023
0708567
Merge branch 'main' into receipts
tcoratger Sep 21, 2023
c3ce126
fix lint
tcoratger Sep 21, 2023
250c62b
Merge branch 'main' into receipts
tcoratger Sep 21, 2023
932e3a1
solve conflicts
tcoratger Sep 21, 2023
f9d6485
change error in gas_spent_by_tx to PrunePartError
tcoratger Sep 22, 2023
dbdd667
Merge branch 'main' into receipts
tcoratger Sep 23, 2023
960cacc
update merge
tcoratger Sep 23, 2023
60dc1aa
Merge branch 'main' into receipts
tcoratger Sep 25, 2023
3c55fb8
Merge branch 'main' into receipts
mattsse Sep 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions bin/reth/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ use reth_db::{
tables,
transaction::{DbTx, DbTxMut},
};
use reth_primitives::{stage::StageId, Account, Bytecode, ChainSpec, StorageEntry, H256, U256};
use reth_primitives::{
stage::StageId, Account, Bytecode, ChainSpec, Receipts, StorageEntry, H256, U256,
};
use reth_provider::{
bundle_state::{BundleStateInit, RevertsInit},
BundleStateWithReceipts, DatabaseProviderRW, HashingWriter, HistoryWriter, OriginalValuesKnown,
Expand Down Expand Up @@ -144,7 +146,7 @@ pub fn insert_genesis_state<DB: Database>(
state_init,
all_reverts_init,
contracts.into_iter().collect(),
vec![],
Receipts::new(),
0,
);

Expand Down
11 changes: 8 additions & 3 deletions crates/payload/basic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use reth_primitives::{
EMPTY_WITHDRAWALS, ETHEREUM_BLOCK_GAS_LIMIT, RETH_CLIENT_VERSION, SLOT_DURATION,
},
proofs, Block, BlockNumberOrTag, ChainSpec, Header, IntoRecoveredTransaction, Receipt,
SealedBlock, Withdrawal, EMPTY_OMMER_ROOT, H256, U256,
Receipts, SealedBlock, Withdrawal, EMPTY_OMMER_ROOT, H256, U256,
};
use reth_provider::{BlockReaderIdExt, BlockSource, BundleStateWithReceipts, StateProviderFactory};
use reth_revm::{
Expand Down Expand Up @@ -774,7 +774,11 @@ where
// merge all transitions into bundle state.
db.merge_transitions(BundleRetention::PlainState);

let bundle = BundleStateWithReceipts::new(db.take_bundle(), vec![receipts], block_number);
let bundle = BundleStateWithReceipts::new(
db.take_bundle(),
Receipts::from_vec(vec![receipts]),
block_number,
);
let receipts_root = bundle.receipts_root_slow(block_number).expect("Number is in range");
let logs_bloom = bundle.block_logs_bloom(block_number).expect("Number is in range");

Expand Down Expand Up @@ -883,7 +887,8 @@ where
db.merge_transitions(BundleRetention::PlainState);

// calculate the state root
let bundle_state = BundleStateWithReceipts::new(db.take_bundle(), vec![], block_number);
let bundle_state =
BundleStateWithReceipts::new(db.take_bundle(), Receipts::new(), block_number);
let state_root = state.state_root(bundle_state)?;

let header = Header {
Expand Down
2 changes: 1 addition & 1 deletion crates/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ pub use prune::{
PruneBatchSizes, PruneCheckpoint, PruneMode, PruneModes, PrunePart, PrunePartError,
ReceiptsLogPruneConfig, MINIMUM_PRUNING_DISTANCE,
};
pub use receipt::{Receipt, ReceiptWithBloom, ReceiptWithBloomRef};
pub use receipt::{Receipt, ReceiptWithBloom, ReceiptWithBloomRef, Receipts};
pub use revm_primitives::JumpMap;
pub use serde_helper::JsonU256;
pub use storage::StorageEntry;
Expand Down
29 changes: 29 additions & 0 deletions crates/primitives/src/receipt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,35 @@ impl Receipt {
}
}

/// A collection of receipts organized as a two-dimensional vector.
#[derive(Clone, Debug, PartialEq, Eq, Default)]
pub struct Receipts {
tcoratger marked this conversation as resolved.
Show resolved Hide resolved
/// A two-dimensional vector of optional `Receipt` instances.
pub receipt_vec: Vec<Vec<Option<Receipt>>>,
tcoratger marked this conversation as resolved.
Show resolved Hide resolved
}

impl Receipts {
/// Create a new `Receipts` instance with an empty vector.
pub fn new() -> Self {
Self { receipt_vec: vec![] }
}

/// Create a new `Receipts` instance from an existing vector.
pub fn from_vec(vec: Vec<Vec<Option<Receipt>>>) -> Self {
Self { receipt_vec: vec }
}

/// Returns the length of the `Receipts` vector.
pub fn len(&self) -> usize {
self.receipt_vec.len()
}
tcoratger marked this conversation as resolved.
Show resolved Hide resolved

/// Returns `true` if the `Receipts` vector is empty.
pub fn is_empty(&self) -> bool {
self.receipt_vec.is_empty()
}
}

impl From<Receipt> for ReceiptWithBloom {
fn from(receipt: Receipt) -> Self {
let bloom = receipt.bloom_slow();
Expand Down
15 changes: 8 additions & 7 deletions crates/revm/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use reth_interfaces::{
};
use reth_primitives::{
Address, Block, BlockNumber, Bloom, ChainSpec, Hardfork, Header, PruneMode, PruneModes,
PrunePartError, Receipt, ReceiptWithBloom, TransactionSigned, H256, MINIMUM_PRUNING_DISTANCE,
U256,
PrunePartError, Receipt, ReceiptWithBloom, Receipts, TransactionSigned, H256,
MINIMUM_PRUNING_DISTANCE, U256,
};
use reth_provider::{
BlockExecutor, BlockExecutorStats, BundleStateWithReceipts, PrunableBlockExecutor,
Expand Down Expand Up @@ -53,8 +53,8 @@ pub struct EVMProcessor<'a> {
/// Outer vector stores receipts for each block sequentially.
/// The inner vector stores receipts ordered by transaction number.
///
/// If receipt is None it means it is pruned.
receipts: Vec<Vec<Option<Receipt>>>,
/// If receipt is None it means it is pruned.
receipts: Receipts,
/// First block will be initialized to `None`
/// and be set to the block number of first block executed.
first_block: Option<BlockNumber>,
Expand Down Expand Up @@ -83,7 +83,7 @@ impl<'a> EVMProcessor<'a> {
chain_spec,
evm,
stack: InspectorStack::new(InspectorStackConfig::default()),
receipts: Vec::new(),
receipts: Receipts::new(),
first_block: None,
tip: None,
prune_modes: PruneModes::none(),
Expand Down Expand Up @@ -113,7 +113,7 @@ impl<'a> EVMProcessor<'a> {
chain_spec,
evm,
stack: InspectorStack::new(InspectorStackConfig::default()),
receipts: Vec::new(),
receipts: Receipts::new(),
first_block: None,
tip: None,
prune_modes: PruneModes::none(),
Expand Down Expand Up @@ -328,6 +328,7 @@ impl<'a> EVMProcessor<'a> {
expected: block.gas_used,
gas_spent_by_tx: self
.receipts
.receipt_vec
.last()
.map(|block_r| {
block_r
Expand Down Expand Up @@ -376,7 +377,7 @@ impl<'a> EVMProcessor<'a> {
// Prune receipts if necessary.
self.prune_receipts(&mut receipts)?;
// Save receipts.
self.receipts.push(receipts);
self.receipts.receipt_vec.push(receipts);
tcoratger marked this conversation as resolved.
Show resolved Hide resolved
Ok(())
}

Expand Down
8 changes: 6 additions & 2 deletions crates/rpc/rpc/src/eth/api/pending_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use crate::eth::error::EthResult;
use reth_primitives::{
constants::{BEACON_NONCE, EMPTY_WITHDRAWALS},
proofs, Block, Header, IntoRecoveredTransaction, Receipt, SealedBlock, SealedHeader,
proofs, Block, Header, IntoRecoveredTransaction, Receipt, Receipts, SealedBlock, SealedHeader,
EMPTY_OMMER_ROOT, H256, U256,
};
use reth_provider::{BundleStateWithReceipts, StateProviderFactory};
Expand Down Expand Up @@ -115,7 +115,11 @@ impl PendingBlockEnv {
// merge all transitions into bundle state.
db.merge_transitions(BundleRetention::PlainState);

let bundle = BundleStateWithReceipts::new(db.take_bundle(), vec![receipts], block_number);
let bundle = BundleStateWithReceipts::new(
db.take_bundle(),
Receipts::from_vec(vec![receipts]),
block_number,
);

let receipts_root = bundle.receipts_root_slow(block_number).expect("Block is present");
let logs_bloom = bundle.block_logs_bloom(block_number).expect("Block is present");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use reth_db::{
use reth_interfaces::db::DatabaseError;
use reth_primitives::{
bloom::logs_bloom, keccak256, proofs::calculate_receipt_root_ref, Account, Address,
BlockNumber, Bloom, Bytecode, Log, Receipt, StorageEntry, H256, U256,
BlockNumber, Bloom, Bytecode, Log, Receipt, Receipts, StorageEntry, H256, U256,
};
use reth_revm_primitives::{
db::states::BundleState, into_reth_acc, into_revm_acc, primitives::AccountInfo,
Expand All @@ -30,8 +30,8 @@ pub struct BundleStateWithReceipts {
/// Outer vector stores receipts for each block sequentially.
/// The inner vector stores receipts ordered by transaction number.
///
/// If receipt is None it means it is pruned.
receipts: Vec<Vec<Option<Receipt>>>,
/// If receipt is None it means it is pruned.
receipts: Receipts,
/// First block of bundle state.
first_block: BlockNumber,
}
Expand All @@ -48,11 +48,7 @@ pub type RevertsInit = HashMap<BlockNumber, HashMap<Address, AccountRevertInit>>

impl BundleStateWithReceipts {
/// Create Bundle State.
pub fn new(
bundle: BundleState,
receipts: Vec<Vec<Option<Receipt>>>,
first_block: BlockNumber,
) -> Self {
pub fn new(bundle: BundleState, receipts: Receipts, first_block: BlockNumber) -> Self {
Self { bundle, receipts, first_block }
}

Expand All @@ -61,7 +57,7 @@ impl BundleStateWithReceipts {
state_init: BundleStateInit,
revert_init: RevertsInit,
contracts_init: Vec<(H256, Bytecode)>,
receipts: Vec<Vec<Option<Receipt>>>,
receipts: Receipts,
first_block: BlockNumber,
) -> Self {
// sort reverts by block number
Expand Down Expand Up @@ -167,7 +163,7 @@ impl BundleStateWithReceipts {
/// # Example
///
/// ```
/// use reth_primitives::{Account, U256};
/// use reth_primitives::{Account, U256, Receipts};
/// use reth_provider::BundleStateWithReceipts;
/// use reth_db::{test_utils::create_test_rw_db, database::Database};
/// use std::collections::HashMap;
Expand All @@ -187,7 +183,7 @@ impl BundleStateWithReceipts {
/// )]),
/// HashMap::from([]),
/// vec![],
/// vec![],
/// Receipts::new(),
/// 0,
/// );
///
Expand Down Expand Up @@ -228,7 +224,12 @@ impl BundleStateWithReceipts {
/// Returns an iterator over all block logs.
pub fn logs(&self, block_number: BlockNumber) -> Option<impl Iterator<Item = &Log>> {
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.receipt_vec[index]
.iter()
.filter_map(|r| Some(r.as_ref()?.logs.iter()))
.flatten(),
)
}

/// Return blocks logs bloom
Expand All @@ -241,20 +242,22 @@ impl BundleStateWithReceipts {
/// of receipt. This is a expensive operation.
pub fn receipts_root_slow(&self, block_number: BlockNumber) -> Option<H256> {
let index = self.block_number_to_index(block_number)?;
let block_receipts =
self.receipts[index].iter().map(Option::as_ref).collect::<Option<Vec<_>>>()?;
let block_receipts = self.receipts.receipt_vec[index]
.iter()
.map(Option::as_ref)
.collect::<Option<Vec<_>>>()?;
tcoratger marked this conversation as resolved.
Show resolved Hide resolved
Some(calculate_receipt_root_ref(&block_receipts))
}

/// Return reference to receipts.
pub fn receipts(&self) -> &Vec<Vec<Option<Receipt>>> {
pub fn receipts(&self) -> &Receipts {
&self.receipts
}

/// Return all block receipts
pub fn receipts_by_block(&self, block_number: BlockNumber) -> &[Option<Receipt>] {
let Some(index) = self.block_number_to_index(block_number) else { return &[] };
&self.receipts[index]
&self.receipts.receipt_vec[index]
}

/// Is bundle state empty of blocks.
Expand Down Expand Up @@ -290,7 +293,7 @@ impl BundleStateWithReceipts {
let rm_trx: usize = self.len() - new_len;

// remove receipts
self.receipts.truncate(new_len);
self.receipts.receipt_vec.truncate(new_len);
// Revert last n reverts.
self.bundle.revert(rm_trx);

Expand Down Expand Up @@ -323,9 +326,9 @@ impl BundleStateWithReceipts {
detached_bundle_state.revert_to(block_number);

// split is done as [0, num) and [num, len]
let (_, this) = self.receipts.split_at(num_of_detached_block as usize);
let (_, this) = self.receipts.receipt_vec.split_at(num_of_detached_block as usize);

self.receipts = this.to_vec().clone();
self.receipts = Receipts::from_vec(this.to_vec().clone());
self.bundle.take_n_reverts(num_of_detached_block as usize);

self.first_block = block_number + 1;
Expand All @@ -340,7 +343,7 @@ impl BundleStateWithReceipts {
/// In most cases this would be true.
pub fn extend(&mut self, other: Self) {
self.bundle.extend(other.bundle);
self.receipts.extend(other.receipts);
self.receipts.receipt_vec.extend(other.receipts.receipt_vec);
}

/// Write bundle state to database.
Expand All @@ -360,7 +363,7 @@ impl BundleStateWithReceipts {
let mut bodies_cursor = tx.cursor_read::<tables::BlockBodyIndices>()?;
let mut receipts_cursor = tx.cursor_write::<tables::Receipts>()?;

for (idx, receipts) in self.receipts.into_iter().enumerate() {
for (idx, receipts) in self.receipts.receipt_vec.into_iter().enumerate() {
tcoratger marked this conversation as resolved.
Show resolved Hide resolved
if !receipts.is_empty() {
let (_, body_indices) = bodies_cursor
.seek_exact(self.first_block + idx as u64)?
Expand Down Expand Up @@ -393,7 +396,7 @@ mod tests {
transaction::DbTx,
DatabaseEnv,
};
use reth_primitives::{Address, Receipt, StorageEntry, H256, MAINNET, U256};
use reth_primitives::{Address, Receipt, Receipts, StorageEntry, H256, MAINNET, U256};
use reth_revm_primitives::{into_reth_acc, primitives::HashMap};
use revm::{
db::{
Expand Down Expand Up @@ -612,7 +615,7 @@ mod tests {

state.merge_transitions(BundleRetention::Reverts);

BundleStateWithReceipts::new(state.take_bundle(), Vec::new(), 1)
BundleStateWithReceipts::new(state.take_bundle(), Receipts::new(), 1)
.write_to_db(provider.tx_ref(), OriginalValuesKnown::Yes)
.expect("Could not write bundle state to DB");

Expand Down Expand Up @@ -712,7 +715,7 @@ mod tests {
)]));

state.merge_transitions(BundleRetention::Reverts);
BundleStateWithReceipts::new(state.take_bundle(), Vec::new(), 2)
BundleStateWithReceipts::new(state.take_bundle(), Receipts::new(), 2)
.write_to_db(provider.tx_ref(), OriginalValuesKnown::Yes)
.expect("Could not write bundle state to DB");

Expand Down Expand Up @@ -779,7 +782,7 @@ mod tests {
},
)]));
init_state.merge_transitions(BundleRetention::Reverts);
BundleStateWithReceipts::new(init_state.take_bundle(), Vec::new(), 0)
BundleStateWithReceipts::new(init_state.take_bundle(), Receipts::new(), 0)
.write_to_db(provider.tx_ref(), OriginalValuesKnown::Yes)
.expect("Could not write init bundle state to DB");

Expand Down Expand Up @@ -926,7 +929,7 @@ mod tests {

let bundle = state.take_bundle();

BundleStateWithReceipts::new(bundle, Vec::new(), 1)
BundleStateWithReceipts::new(bundle, Receipts::new(), 1)
.write_to_db(provider.tx_ref(), OriginalValuesKnown::Yes)
.expect("Could not write bundle state to DB");

Expand Down Expand Up @@ -1092,7 +1095,7 @@ mod tests {
},
)]));
init_state.merge_transitions(BundleRetention::Reverts);
BundleStateWithReceipts::new(init_state.take_bundle(), Vec::new(), 0)
BundleStateWithReceipts::new(init_state.take_bundle(), Receipts::new(), 0)
.write_to_db(provider.tx_ref(), OriginalValuesKnown::Yes)
.expect("Could not write init bundle state to DB");

Expand Down Expand Up @@ -1139,7 +1142,7 @@ mod tests {

// Commit block #1 changes to the database.
state.merge_transitions(BundleRetention::Reverts);
BundleStateWithReceipts::new(state.take_bundle(), Vec::new(), 1)
BundleStateWithReceipts::new(state.take_bundle(), Receipts::new(), 1)
.write_to_db(provider.tx_ref(), OriginalValuesKnown::Yes)
.expect("Could not write bundle state to DB");

Expand Down Expand Up @@ -1171,7 +1174,7 @@ mod tests {
fn revert_to_indices() {
let base = BundleStateWithReceipts {
bundle: BundleState::default(),
receipts: vec![vec![Some(Receipt::default()); 2]; 7],
receipts: Receipts::from_vec(vec![vec![Some(Receipt::default()); 2]; 7]),
first_block: 10,
};

Expand Down
Loading
Loading