test: BlockReaderIdExt implementation for BlockchainProvider2 (#10376)

This commit is contained in:
greged93
2024-08-20 08:16:43 -07:00
committed by GitHub
parent 5470574bf2
commit 9c71fa8485
2 changed files with 225 additions and 97 deletions

View File

@ -858,7 +858,7 @@ where
transactions.push(block_state.block().block().body.clone());
last_in_memory_block = Some(number);
} else {
break;
break
}
}
@ -1491,26 +1491,37 @@ mod tests {
use std::sync::Arc;
use reth_chain_state::{ExecutedBlock, NewCanonicalChain};
use reth_primitives::B256;
use reth_storage_api::{BlockHashReader, BlockNumReader, HeaderProvider};
use reth_db::{test_utils::TempDatabase, DatabaseEnv};
use reth_primitives::{BlockNumberOrTag, SealedBlock, B256};
use reth_storage_api::{BlockHashReader, BlockNumReader, BlockReaderIdExt, HeaderProvider};
use reth_testing_utils::generators::{self, random_block_range};
use crate::{providers::BlockchainProvider2, test_utils::create_test_provider_factory};
use crate::{
providers::BlockchainProvider2, test_utils::create_test_provider_factory, CanonChainTracker,
};
#[test]
fn test_block_hash_reader() -> eyre::Result<()> {
const TEST_BLOCKS_COUNT: usize = 5;
#[allow(clippy::type_complexity)]
fn provider_with_random_blocks(
database_blocks: usize,
in_memory_blocks: usize,
) -> eyre::Result<(
BlockchainProvider2<Arc<TempDatabase<DatabaseEnv>>>,
Vec<SealedBlock>,
Vec<SealedBlock>,
)> {
let mut rng = generators::rng();
let block_range = (database_blocks + in_memory_blocks - 1) as u64;
let blocks = random_block_range(&mut rng, 0..=block_range, B256::ZERO, 0..1);
let factory = create_test_provider_factory();
// Generate 10 random blocks
let blocks = random_block_range(&mut rng, 0..=10, B256::ZERO, 0..1);
let provider_rw = factory.provider_rw()?;
let mut blocks_iter = blocks.clone().into_iter();
// Insert first 5 blocks into the database
let provider_rw = factory.provider_rw()?;
for block in (0..5).map_while(|_| blocks_iter.next()) {
// Insert data blocks into the database
for block in (0..database_blocks).map_while(|_| blocks_iter.next()) {
provider_rw.insert_historical_block(
block.seal_with_senders().expect("failed to seal block with senders"),
)?;
@ -1536,15 +1547,39 @@ mod tests {
};
provider.canonical_in_memory_state.update_chain(chain);
let database_block = blocks.first().unwrap().clone();
let in_memory_block = blocks.last().unwrap().clone();
// Get canonical, safe, and finalized blocks
let block_count = database_blocks + in_memory_blocks;
let canonical_block = blocks.get(block_count - 1).unwrap().clone();
let safe_block = blocks.get(block_count - 2).unwrap().clone();
let finalized_block = blocks.get(block_count - 3).unwrap().clone();
// Set the canonical head, safe, and finalized blocks
provider.set_canonical_head(canonical_block.header);
provider.set_safe(safe_block.header);
provider.set_finalized(finalized_block.header);
let (database_blocks, in_memory_blocks) = blocks.split_at(database_blocks);
Ok((provider, database_blocks.to_vec(), in_memory_blocks.to_vec()))
}
#[test]
fn test_block_hash_reader() -> eyre::Result<()> {
let (provider, database_blocks, in_memory_blocks) =
provider_with_random_blocks(TEST_BLOCKS_COUNT, TEST_BLOCKS_COUNT)?;
let database_block = database_blocks.first().unwrap().clone();
let in_memory_block = in_memory_blocks.last().unwrap().clone();
assert_eq!(provider.block_hash(database_block.number)?, Some(database_block.hash()));
assert_eq!(provider.block_hash(in_memory_block.number)?, Some(in_memory_block.hash()));
assert_eq!(
provider.canonical_hashes_range(0, 10)?,
blocks.iter().map(|block| block.hash()).collect::<Vec<_>>()
[database_blocks, in_memory_blocks]
.concat()
.iter()
.map(|block| block.hash())
.collect::<Vec<_>>()
);
Ok(())
@ -1552,45 +1587,12 @@ mod tests {
#[test]
fn test_header_provider() -> eyre::Result<()> {
let mut rng = generators::rng();
let (provider, database_blocks, in_memory_blocks) =
provider_with_random_blocks(TEST_BLOCKS_COUNT, TEST_BLOCKS_COUNT).unwrap();
let factory = create_test_provider_factory();
// Generate 10 random blocks
let blocks = random_block_range(&mut rng, 0..=10, B256::ZERO, 0..1);
let mut blocks_iter = blocks.clone().into_iter();
// Insert first 5 blocks into the database
let provider_rw = factory.provider_rw()?;
for block in (0..5).map_while(|_| blocks_iter.next()) {
provider_rw.insert_historical_block(
block.seal_with_senders().expect("failed to seal block with senders"),
)?;
}
provider_rw.commit()?;
let provider = BlockchainProvider2::new(factory)?;
// Insert the rest of the blocks into the in-memory state
let chain = NewCanonicalChain::Commit {
new: blocks_iter
.map(|block| {
let senders = block.senders().expect("failed to recover senders");
ExecutedBlock::new(
Arc::new(block),
Arc::new(senders),
Default::default(),
Default::default(),
Default::default(),
)
})
.collect(),
};
provider.canonical_in_memory_state.update_chain(chain);
let database_block = blocks.first().unwrap().clone();
let in_memory_block = blocks.last().unwrap().clone();
let database_block = database_blocks.first().unwrap().clone();
let in_memory_block = in_memory_blocks.last().unwrap().clone();
let blocks = [database_blocks, in_memory_blocks].concat();
assert_eq!(provider.header(&database_block.hash())?, Some(database_block.header().clone()));
assert_eq!(
@ -1649,57 +1651,179 @@ mod tests {
#[test]
fn test_block_num_reader() -> eyre::Result<()> {
let mut rng = generators::rng();
let factory = create_test_provider_factory();
// Generate 10 random blocks
let blocks = random_block_range(&mut rng, 0..=10, B256::ZERO, 0..1);
let database_blocks = blocks[0..5].to_vec();
let in_memory_blocks = blocks[5..].to_vec();
let mut blocks_iter = blocks.into_iter();
// Insert first 5 blocks into the database
let provider_rw = factory.provider_rw()?;
for block in (0..5).map_while(|_| blocks_iter.next()) {
provider_rw.insert_historical_block(
block.seal_with_senders().expect("failed to seal block with senders"),
)?;
}
provider_rw.commit()?;
let provider = BlockchainProvider2::new(factory)?;
// Insert the rest of the blocks into the in-memory state
let chain = NewCanonicalChain::Commit {
new: blocks_iter
.map(|block| {
let senders = block.senders().expect("failed to recover senders");
ExecutedBlock::new(
Arc::new(block),
Arc::new(senders),
Default::default(),
Default::default(),
Default::default(),
)
})
.collect(),
};
provider.canonical_in_memory_state.update_chain(chain);
provider
.canonical_in_memory_state
.set_canonical_head(in_memory_blocks.last().unwrap().clone().header);
let database_block = database_blocks.first().unwrap().clone();
let in_memory_block = in_memory_blocks.last().unwrap().clone();
let (provider, database_blocks, in_memory_blocks) =
provider_with_random_blocks(TEST_BLOCKS_COUNT, TEST_BLOCKS_COUNT).unwrap();
assert_eq!(provider.best_block_number()?, in_memory_blocks.last().unwrap().number);
assert_eq!(provider.last_block_number()?, database_blocks.last().unwrap().number);
let database_block = database_blocks.first().unwrap().clone();
let in_memory_block = in_memory_blocks.first().unwrap().clone();
assert_eq!(provider.block_number(database_block.hash())?, Some(database_block.number));
assert_eq!(provider.block_number(in_memory_block.hash())?, Some(in_memory_block.number));
Ok(())
}
#[test]
fn test_block_reader_id_ext_block_by_id() {
let (provider, database_blocks, in_memory_blocks) =
provider_with_random_blocks(TEST_BLOCKS_COUNT, TEST_BLOCKS_COUNT).unwrap();
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.block_by_id(block_number.into()).unwrap(),
Some(database_block.clone().unseal())
);
assert_eq!(provider.block_by_id(block_hash.into()).unwrap(), Some(database_block.unseal()));
let block_number = in_memory_block.number;
let block_hash = in_memory_block.header.hash();
assert_eq!(
provider.block_by_id(block_number.into()).unwrap(),
Some(in_memory_block.clone().unseal())
);
assert_eq!(
provider.block_by_id(block_hash.into()).unwrap(),
Some(in_memory_block.unseal())
);
}
#[test]
fn test_block_reader_id_ext_header_by_number_or_tag() {
let (provider, database_blocks, in_memory_blocks) =
provider_with_random_blocks(TEST_BLOCKS_COUNT, TEST_BLOCKS_COUNT).unwrap();
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();
let block_number = database_block.number;
assert_eq!(
provider.header_by_number_or_tag(block_number.into()).unwrap(),
Some(database_block.header.clone().unseal())
);
assert_eq!(
provider.sealed_header_by_number_or_tag(block_number.into()).unwrap(),
Some(database_block.header)
);
assert_eq!(
provider.header_by_number_or_tag(BlockNumberOrTag::Latest).unwrap(),
Some(canonical_block.header.clone().unseal())
);
assert_eq!(
provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Latest).unwrap(),
Some(canonical_block.header)
);
assert_eq!(
provider.header_by_number_or_tag(BlockNumberOrTag::Safe).unwrap(),
Some(safe_block.header.clone().unseal())
);
assert_eq!(
provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Safe).unwrap(),
Some(safe_block.header)
);
assert_eq!(
provider.header_by_number_or_tag(BlockNumberOrTag::Finalized).unwrap(),
Some(finalized_block.header.clone().unseal())
);
assert_eq!(
provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Finalized).unwrap(),
Some(finalized_block.header)
);
}
#[test]
fn test_block_reader_id_ext_header_by_id() {
let (provider, database_blocks, in_memory_blocks) =
provider_with_random_blocks(TEST_BLOCKS_COUNT, TEST_BLOCKS_COUNT).unwrap();
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.header_by_id(block_number.into()).unwrap(),
Some(database_block.header.clone().unseal())
);
assert_eq!(
provider.sealed_header_by_id(block_number.into()).unwrap(),
Some(database_block.header.clone())
);
assert_eq!(
provider.header_by_id(block_hash.into()).unwrap(),
Some(database_block.header.clone().unseal())
);
assert_eq!(
provider.sealed_header_by_id(block_hash.into()).unwrap(),
Some(database_block.header)
);
let block_number = in_memory_block.number;
let block_hash = in_memory_block.header.hash();
assert_eq!(
provider.header_by_id(block_number.into()).unwrap(),
Some(in_memory_block.header.clone().unseal())
);
assert_eq!(
provider.sealed_header_by_id(block_number.into()).unwrap(),
Some(in_memory_block.header.clone())
);
assert_eq!(
provider.header_by_id(block_hash.into()).unwrap(),
Some(in_memory_block.header.clone().unseal())
);
assert_eq!(
provider.sealed_header_by_id(block_hash.into()).unwrap(),
Some(in_memory_block.header)
);
}
#[test]
fn test_block_reader_id_ext_ommers_by_id() {
let (provider, database_blocks, in_memory_blocks) =
provider_with_random_blocks(TEST_BLOCKS_COUNT, TEST_BLOCKS_COUNT).unwrap();
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.ommers_by_id(block_number.into()).unwrap().unwrap_or_default(),
database_block.ommers
);
assert_eq!(
provider.ommers_by_id(block_hash.into()).unwrap().unwrap_or_default(),
database_block.ommers
);
let block_number = in_memory_block.number;
let block_hash = in_memory_block.header.hash();
assert_eq!(
provider.ommers_by_id(block_number.into()).unwrap().unwrap_or_default(),
in_memory_block.ommers
);
assert_eq!(
provider.ommers_by_id(block_hash.into()).unwrap().unwrap_or_default(),
in_memory_block.ommers
);
}
}

View File

@ -2002,6 +2002,10 @@ impl<TX: DbTx> BlockReader for DatabaseProvider<TX> {
Ok(None)
}
/// Returns the ommers for the block with matching id from the database.
///
/// If the block is not found, this returns `None`.
/// If the block exists, but doesn't contain ommers, this returns `None`.
fn ommers(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Header>>> {
if let Some(number) = self.convert_hash_or_number(id)? {
// If the Paris (Merge) hardfork block is known and block is after it, return empty