Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into alexey/blockchain-pro…
Browse files Browse the repository at this point in the history
…vider-changeset-reader
  • Loading branch information
shekhirin committed Aug 21, 2024
2 parents 9170eba + 1f6993d commit cdc246e
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 21 deletions.
125 changes: 108 additions & 17 deletions crates/storage/provider/src/providers/blockchain_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ where
blocks.append(&mut database_blocks);

// Advance the range iterator by the number of blocks fetched from the database
range.nth(database_blocks.len() - 1);
range.nth(blocks.len() - 1);

// Fetch the remaining blocks from the in-memory state
for num in range {
Expand Down Expand Up @@ -1495,19 +1495,22 @@ mod tests {
use reth_chainspec::ChainSpecProvider;
use reth_db::{models::AccountBeforeTx, test_utils::TempDatabase, DatabaseEnv};
use reth_execution_types::ExecutionOutcome;
use reth_primitives::{BlockHashOrNumber, BlockNumberOrTag, Header, SealedBlock, B256};
use reth_primitives::{
BlockHashOrNumber, BlockNumberOrTag, Header, Receipt, SealedBlock, StaticFileSegment, B256,
};
use reth_storage_api::{
BlockHashReader, BlockNumReader, BlockReader, BlockReaderIdExt, BlockSource,
ChangeSetReader, HeaderProvider,
ChangeSetReader, HeaderProvider, ReceiptProviderIdExt,
};
use reth_testing_utils::generators::{
self, random_block, random_block_range, random_changeset_range, random_eoa_accounts,
random_receipt,
};
use revm::db::BundleState;

use crate::{
providers::BlockchainProvider2, test_utils::create_test_provider_factory, BlockWriter,
CanonChainTracker,
CanonChainTracker, StaticFileWriter,
};

const TEST_BLOCKS_COUNT: usize = 5;
Expand All @@ -1532,33 +1535,52 @@ mod tests {
BlockchainProvider2<Arc<TempDatabase<DatabaseEnv>>>,
Vec<SealedBlock>,
Vec<SealedBlock>,
Vec<Vec<Receipt>>,
)> {
let (database_blocks, in_memory_blocks) =
random_blocks(rng, database_blocks, in_memory_blocks);
let receipts: Vec<Vec<_>> = database_blocks
.iter()
.chain(in_memory_blocks.iter())
.map(|block| block.body.iter())
.map(|tx| tx.map(|tx| random_receipt(rng, tx, Some(2))).collect())
.collect();

let factory = create_test_provider_factory();
let provider_rw = factory.provider_rw()?;

// Insert data blocks into the database
// Insert blocks and receipts into the database
for block in &database_blocks {
provider_rw.insert_historical_block(
block.clone().seal_with_senders().expect("failed to seal block with senders"),
)?;

// Insert the receipts into the database using the writer from the provider_rw
let mut writer =
provider_rw.static_file_provider().latest_writer(StaticFileSegment::Receipts)?;
let block_number = block.number as usize;
for receipt in receipts.get(block_number).unwrap() {
writer.append_receipt(block.number, receipt)?;
}
}
provider_rw.commit()?;

let provider = BlockchainProvider2::new(factory)?;

// Insert the rest of the blocks into the in-memory state
// Insert the rest of the blocks and receipts into the in-memory state
let chain = NewCanonicalChain::Commit {
new: in_memory_blocks
.iter()
.map(|block| {
let senders = block.senders().expect("failed to recover senders");
let block_receipts = receipts.get(block.number as usize).unwrap().clone();
let execution_outcome =
ExecutionOutcome { receipts: block_receipts.into(), ..Default::default() };

ExecutedBlock::new(
Arc::new(block.clone()),
Arc::new(senders),
Default::default(),
execution_outcome.into(),
Default::default(),
Default::default(),
)
Expand All @@ -1579,7 +1601,7 @@ mod tests {
provider.set_safe(safe_block.header.clone());
provider.set_finalized(finalized_block.header.clone());

Ok((provider, database_blocks, in_memory_blocks))
Ok((provider, database_blocks.to_vec(), in_memory_blocks.to_vec(), receipts))
}

#[test]
Expand Down Expand Up @@ -1747,8 +1769,8 @@ mod tests {
#[test]
fn test_block_reader_pending_block() -> eyre::Result<()> {
let mut rng = generators::rng();
let (provider, _, _) =
provider_with_random_blocks(&mut rng, TEST_BLOCKS_COUNT, TEST_BLOCKS_COUNT)?;
let (provider, _, _, _) =
provider_with_random_blocks(&mut rng, TEST_BLOCKS_COUNT, TEST_BLOCKS_COUNT).unwrap();

// Generate a random block
let mut rng = generators::rng();
Expand Down Expand Up @@ -1848,7 +1870,7 @@ mod tests {
#[test]
fn test_block_hash_reader() -> eyre::Result<()> {
let mut rng = generators::rng();
let (provider, database_blocks, in_memory_blocks) =
let (provider, database_blocks, in_memory_blocks, _) =
provider_with_random_blocks(&mut rng, TEST_BLOCKS_COUNT, TEST_BLOCKS_COUNT)?;

let database_block = database_blocks.first().unwrap().clone();
Expand All @@ -1872,7 +1894,7 @@ mod tests {
#[test]
fn test_header_provider() -> eyre::Result<()> {
let mut rng = generators::rng();
let (provider, database_blocks, in_memory_blocks) =
let (provider, database_blocks, in_memory_blocks, _) =
provider_with_random_blocks(&mut rng, TEST_BLOCKS_COUNT, TEST_BLOCKS_COUNT).unwrap();

let database_block = database_blocks.first().unwrap().clone();
Expand Down Expand Up @@ -1937,7 +1959,7 @@ mod tests {
#[test]
fn test_block_num_reader() -> eyre::Result<()> {
let mut rng = generators::rng();
let (provider, database_blocks, in_memory_blocks) =
let (provider, database_blocks, in_memory_blocks, _) =
provider_with_random_blocks(&mut rng, TEST_BLOCKS_COUNT, TEST_BLOCKS_COUNT).unwrap();

assert_eq!(provider.best_block_number()?, in_memory_blocks.last().unwrap().number);
Expand All @@ -1954,7 +1976,7 @@ mod tests {
#[test]
fn test_block_reader_id_ext_block_by_id() {
let mut rng = generators::rng();
let (provider, database_blocks, in_memory_blocks) =
let (provider, database_blocks, in_memory_blocks, _) =
provider_with_random_blocks(&mut rng, TEST_BLOCKS_COUNT, TEST_BLOCKS_COUNT).unwrap();

let database_block = database_blocks.first().unwrap().clone();
Expand Down Expand Up @@ -1983,7 +2005,7 @@ mod tests {
#[test]
fn test_block_reader_id_ext_header_by_number_or_tag() {
let mut rng = generators::rng();
let (provider, database_blocks, in_memory_blocks) =
let (provider, database_blocks, in_memory_blocks, _) =
provider_with_random_blocks(&mut rng, TEST_BLOCKS_COUNT, TEST_BLOCKS_COUNT).unwrap();

let database_block = database_blocks.first().unwrap().clone();
Expand Down Expand Up @@ -2034,7 +2056,7 @@ mod tests {
#[test]
fn test_block_reader_id_ext_header_by_id() {
let mut rng = generators::rng();
let (provider, database_blocks, in_memory_blocks) =
let (provider, database_blocks, in_memory_blocks, _) =
provider_with_random_blocks(&mut rng, TEST_BLOCKS_COUNT, TEST_BLOCKS_COUNT).unwrap();

let database_block = database_blocks.first().unwrap().clone();
Expand Down Expand Up @@ -2086,7 +2108,7 @@ mod tests {
#[test]
fn test_block_reader_id_ext_ommers_by_id() {
let mut rng = generators::rng();
let (provider, database_blocks, in_memory_blocks) =
let (provider, database_blocks, in_memory_blocks, _) =
provider_with_random_blocks(&mut rng, TEST_BLOCKS_COUNT, TEST_BLOCKS_COUNT).unwrap();

let database_block = database_blocks.first().unwrap().clone();
Expand Down Expand Up @@ -2117,6 +2139,75 @@ mod tests {
);
}

#[test]
fn test_receipt_provider_id_ext_receipts_by_block_id() -> eyre::Result<()> {
let mut rng = generators::rng();
let (provider, database_blocks, in_memory_blocks, receipts) =
provider_with_random_blocks(&mut rng, TEST_BLOCKS_COUNT, TEST_BLOCKS_COUNT)?;

let database_block = database_blocks.first().unwrap().clone();
let in_memory_block = in_memory_blocks.last().unwrap().clone();

let block_number = database_block.number;
let block_hash = database_block.header.hash();

assert_eq!(
provider.receipts_by_block_id(block_number.into())?.unwrap_or_default(),
receipts.get(block_number as usize).unwrap().clone()
);
assert_eq!(
provider.receipts_by_block_id(block_hash.into())?.unwrap_or_default(),
receipts.get(block_number as usize).unwrap().clone()
);

let block_number = in_memory_block.number;
let block_hash = in_memory_block.header.hash();

assert_eq!(
provider.receipts_by_block_id(block_number.into())?.unwrap_or_default(),
receipts.get(block_number as usize).unwrap().clone()
);
assert_eq!(
provider.receipts_by_block_id(block_hash.into())?.unwrap_or_default(),
receipts.get(block_number as usize).unwrap().clone()
);

Ok(())
}

#[test]
fn test_receipt_provider_id_ext_receipts_by_block_number_or_tag() -> eyre::Result<()> {
let mut rng = generators::rng();
let (provider, database_blocks, in_memory_blocks, receipts) =
provider_with_random_blocks(&mut rng, TEST_BLOCKS_COUNT, TEST_BLOCKS_COUNT)?;

let database_block = database_blocks.first().unwrap().clone();

let in_memory_block_count = in_memory_blocks.len();
let canonical_block = in_memory_blocks.get(in_memory_block_count - 1).unwrap().clone();
let safe_block = in_memory_blocks.get(in_memory_block_count - 2).unwrap().clone();
let finalized_block = in_memory_blocks.get(in_memory_block_count - 3).unwrap().clone();

assert_eq!(
provider.receipts_by_number_or_tag(database_block.number.into())?.unwrap_or_default(),
receipts.get(database_block.number as usize).unwrap().clone()
);
assert_eq!(
provider.receipts_by_number_or_tag(BlockNumberOrTag::Latest)?.unwrap_or_default(),
receipts.get(canonical_block.number as usize).unwrap().clone()
);
assert_eq!(
provider.receipts_by_number_or_tag(BlockNumberOrTag::Safe)?.unwrap_or_default(),
receipts.get(safe_block.number as usize).unwrap().clone()
);
assert_eq!(
provider.receipts_by_number_or_tag(BlockNumberOrTag::Finalized)?.unwrap_or_default(),
receipts.get(finalized_block.number as usize).unwrap().clone()
);

Ok(())
}

#[test]
fn test_changeset_reader() -> eyre::Result<()> {
let mut rng = generators::rng();
Expand Down
59 changes: 55 additions & 4 deletions crates/trie/db/tests/fuzz_in_memory_nodes.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use proptest::prelude::*;
use reth_db::{cursor::DbCursorRW, tables, transaction::DbTxMut};
use reth_primitives::{Account, B256, U256};
use reth_primitives::{Account, StorageEntry, B256, U256};
use reth_provider::test_utils::create_test_provider_factory;
use reth_trie::{
prefix_set::{PrefixSetMut, TriePrefixSets},
test_utils::state_root_prehashed,
test_utils::{state_root_prehashed, storage_root_prehashed},
trie_cursor::InMemoryTrieCursorFactory,
StateRoot,
updates::TrieUpdates,
StateRoot, StorageRoot,
};
use reth_trie_common::Nibbles;
use reth_trie_db::{DatabaseStateRoot, DatabaseTrieCursorFactory};
use reth_trie_db::{DatabaseStateRoot, DatabaseStorageRoot, DatabaseTrieCursorFactory};
use std::collections::BTreeMap;

proptest! {
Expand Down Expand Up @@ -60,7 +61,57 @@ proptest! {
);
assert_eq!(expected_root, state_root);
}
}

#[test]
fn fuzz_in_memory_storage_nodes(mut init_storage: BTreeMap<B256, U256>, storage_updates: [BTreeMap<B256, U256>; 10]) {
let hashed_address = B256::random();
let factory = create_test_provider_factory();
let provider = factory.provider_rw().unwrap();
let mut hashed_storage_cursor =
provider.tx_ref().cursor_write::<tables::HashedStorages>().unwrap();

// Insert init state into database
for (hashed_slot, value) in init_storage.clone() {
hashed_storage_cursor
.upsert(hashed_address, StorageEntry { key: hashed_slot, value })
.unwrap();
}

// Compute initial storage root and updates
let (_, _, mut storage_trie_nodes) =
StorageRoot::from_tx_hashed(provider.tx_ref(), hashed_address).root_with_updates().unwrap();

let mut storage = init_storage;
for mut storage_update in storage_updates {
// Insert state updates into database
let mut changes = PrefixSetMut::default();
for (hashed_slot, value) in storage_update.clone() {
hashed_storage_cursor
.upsert(hashed_address, StorageEntry { key: hashed_slot, value })
.unwrap();
changes.insert(Nibbles::unpack(hashed_slot));
}

// Compute root with in-memory trie nodes overlay
let mut trie_nodes = TrieUpdates::default();
trie_nodes.insert_storage_updates(hashed_address, storage_trie_nodes.clone());
let (storage_root, _, trie_updates) =
StorageRoot::from_tx_hashed(provider.tx_ref(), hashed_address)
.with_prefix_set(changes.freeze())
.with_trie_cursor_factory(InMemoryTrieCursorFactory::new(
DatabaseTrieCursorFactory::new(provider.tx_ref()),
&trie_nodes.into_sorted(),
))
.root_with_updates()
.unwrap();

storage_trie_nodes.extend(trie_updates);

// Verify the result
storage.append(&mut storage_update);
let expected_root = storage_root_prehashed(storage.clone());
assert_eq!(expected_root, storage_root);
}
}
}

0 comments on commit cdc246e

Please sign in to comment.