mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-04-30 03:01:58 -04:00
test: TransactionsProvider implementation of BlockchainProvider2<DB> (#10594)
This commit is contained in:
@@ -1435,7 +1435,11 @@ where
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{ops::Range, sync::Arc, time::Instant};
|
||||
use std::{
|
||||
ops::{Range, RangeBounds},
|
||||
sync::Arc,
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
providers::BlockchainProvider2,
|
||||
@@ -1458,36 +1462,51 @@ mod tests {
|
||||
};
|
||||
use reth_execution_types::{Chain, ExecutionOutcome};
|
||||
use reth_primitives::{
|
||||
BlockHashOrNumber, BlockNumHash, BlockNumberOrTag, BlockWithSenders, Header, Receipt,
|
||||
SealedBlock, SealedBlockWithSenders, StaticFileSegment, Withdrawals, B256,
|
||||
BlockHashOrNumber, BlockNumHash, BlockNumberOrTag, BlockWithSenders, Receipt, SealedBlock,
|
||||
SealedBlockWithSenders, StaticFileSegment, TransactionMeta, TransactionSignedNoHash,
|
||||
Withdrawals, B256,
|
||||
};
|
||||
use reth_storage_api::{
|
||||
BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt, BlockSource,
|
||||
ChangeSetReader, HeaderProvider, ReceiptProviderIdExt, RequestsProvider,
|
||||
TransactionVariant, WithdrawalsProvider,
|
||||
TransactionVariant, TransactionsProvider, WithdrawalsProvider,
|
||||
};
|
||||
use reth_testing_utils::generators::{
|
||||
self, random_block, random_block_range, random_changeset_range, random_eoa_accounts,
|
||||
random_receipt, random_signed_tx, BlockParams, BlockRangeParams,
|
||||
random_receipt, BlockParams, BlockRangeParams,
|
||||
};
|
||||
use revm::db::BundleState;
|
||||
use std::ops::Bound;
|
||||
|
||||
const TEST_BLOCKS_COUNT: usize = 5;
|
||||
|
||||
const TEST_TRANSACTIONS_COUNT: u8 = 4;
|
||||
|
||||
fn random_blocks(
|
||||
rng: &mut impl Rng,
|
||||
database_blocks: usize,
|
||||
in_memory_blocks: usize,
|
||||
requests_count: Option<Range<u8>>,
|
||||
withdrawals_count: Option<Range<u8>>,
|
||||
tx_count: impl RangeBounds<u8>,
|
||||
) -> (Vec<SealedBlock>, Vec<SealedBlock>) {
|
||||
let block_range = (database_blocks + in_memory_blocks - 1) as u64;
|
||||
|
||||
let tx_start = match tx_count.start_bound() {
|
||||
Bound::Included(&n) | Bound::Excluded(&n) => n,
|
||||
Bound::Unbounded => u8::MIN,
|
||||
};
|
||||
let tx_end = match tx_count.end_bound() {
|
||||
Bound::Included(&n) | Bound::Excluded(&n) => n + 1,
|
||||
Bound::Unbounded => u8::MAX,
|
||||
};
|
||||
|
||||
let blocks = random_block_range(
|
||||
rng,
|
||||
0..=block_range,
|
||||
BlockRangeParams {
|
||||
parent: Some(B256::ZERO),
|
||||
tx_count: 0..1,
|
||||
tx_count: tx_start..tx_end,
|
||||
requests_count,
|
||||
withdrawals_count,
|
||||
},
|
||||
@@ -1515,7 +1534,9 @@ mod tests {
|
||||
in_memory_blocks,
|
||||
block_range_params.requests_count,
|
||||
block_range_params.withdrawals_count,
|
||||
block_range_params.tx_count,
|
||||
);
|
||||
|
||||
let receipts: Vec<Vec<_>> = database_blocks
|
||||
.iter()
|
||||
.chain(in_memory_blocks.iter())
|
||||
@@ -1854,57 +1875,26 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_block_body_indices() -> eyre::Result<()> {
|
||||
// Initialize random number generator and provider factory
|
||||
let mut rng = generators::rng();
|
||||
let factory = create_test_provider_factory();
|
||||
|
||||
// Generate 10 random blocks and split them into database and in-memory blocks
|
||||
let mut blocks = random_block_range(
|
||||
&mut rng,
|
||||
0..=10,
|
||||
BlockRangeParams { parent: Some(B256::ZERO), tx_count: 0..1, ..Default::default() },
|
||||
);
|
||||
let (database_blocks, in_memory_blocks) = blocks.split_at_mut(5);
|
||||
|
||||
// Take the first in-memory block and add 7 ommers to it
|
||||
let first_in_mem_block = SealedBlock {
|
||||
ommers: vec![Header::default(); 7],
|
||||
body: vec![
|
||||
random_signed_tx(&mut rng),
|
||||
random_signed_tx(&mut rng),
|
||||
random_signed_tx(&mut rng),
|
||||
random_signed_tx(&mut rng),
|
||||
],
|
||||
..in_memory_blocks.first().unwrap().clone()
|
||||
};
|
||||
|
||||
// Insert the first 5 blocks into the database
|
||||
let provider_rw = factory.provider_rw()?;
|
||||
for block in database_blocks.iter_mut() {
|
||||
*block = SealedBlock {
|
||||
body: vec![
|
||||
random_signed_tx(&mut rng),
|
||||
random_signed_tx(&mut rng),
|
||||
random_signed_tx(&mut rng),
|
||||
random_signed_tx(&mut rng),
|
||||
],
|
||||
..block.clone()
|
||||
};
|
||||
provider_rw.insert_historical_block(
|
||||
block.clone().seal_with_senders().expect("failed to seal block with senders"),
|
||||
)?;
|
||||
}
|
||||
provider_rw.commit()?;
|
||||
|
||||
// Create a new provider
|
||||
let provider = BlockchainProvider2::new(factory)?;
|
||||
let mut rng = generators::rng();
|
||||
let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
|
||||
&mut rng,
|
||||
TEST_BLOCKS_COUNT,
|
||||
TEST_BLOCKS_COUNT,
|
||||
BlockRangeParams {
|
||||
tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
let first_in_mem_block = in_memory_blocks.first().unwrap();
|
||||
|
||||
// Insert the first block into the in-memory state
|
||||
let in_memory_block_senders =
|
||||
first_in_mem_block.senders().expect("failed to recover senders");
|
||||
let chain = NewCanonicalChain::Commit {
|
||||
new: vec![ExecutedBlock::new(
|
||||
Arc::new(first_in_mem_block),
|
||||
Arc::new(first_in_mem_block.clone()),
|
||||
Arc::new(in_memory_block_senders),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
@@ -2876,10 +2866,7 @@ mod tests {
|
||||
|
||||
let block_number = database_block.number;
|
||||
let block_hash = database_block.header.hash();
|
||||
let provider_block =
|
||||
provider.block_by_id(block_number.into()).unwrap().unwrap().withdrawals;
|
||||
println!("provider_block {:#?}", provider_block);
|
||||
println!("db block withdrawals {:#?}", database_block.withdrawals);
|
||||
|
||||
assert_eq!(
|
||||
provider.block_by_id(block_number.into()).unwrap(),
|
||||
Some(database_block.clone().unseal())
|
||||
@@ -3137,7 +3124,7 @@ mod tests {
|
||||
let mut rng = generators::rng();
|
||||
|
||||
let (database_blocks, in_memory_blocks) =
|
||||
random_blocks(&mut rng, TEST_BLOCKS_COUNT, 1, None, None);
|
||||
random_blocks(&mut rng, TEST_BLOCKS_COUNT, 1, None, None, 0..1);
|
||||
|
||||
let first_database_block = database_blocks.first().map(|block| block.number).unwrap();
|
||||
let last_database_block = database_blocks.last().map(|block| block.number).unwrap();
|
||||
@@ -3357,4 +3344,657 @@ mod tests {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transaction_id() -> eyre::Result<()> {
|
||||
let mut rng = generators::rng();
|
||||
let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
|
||||
&mut rng,
|
||||
TEST_BLOCKS_COUNT,
|
||||
TEST_BLOCKS_COUNT,
|
||||
BlockRangeParams {
|
||||
tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
// Database
|
||||
// Choose a random transaction from the database blocks
|
||||
let tx = &database_blocks[0].body[0];
|
||||
let tx_hash = tx.hash();
|
||||
|
||||
// Ensure the transaction ID can be found in the database
|
||||
let result = provider.transaction_id(tx_hash)?;
|
||||
assert_eq!(result, Some(0));
|
||||
|
||||
// In memory
|
||||
// Choose a random transaction from the in-memory blocks
|
||||
let tx = &in_memory_blocks[0].body[0];
|
||||
let tx_hash = tx.hash();
|
||||
|
||||
// Ensure the transaction ID can be found in the in-memory state
|
||||
let result = provider.transaction_id(tx_hash)?;
|
||||
assert!(result.is_some(), "Transaction ID should be found in the in-memory state");
|
||||
|
||||
// Check that the transaction ID is greater than the last database transaction ID
|
||||
let last_db_tx_id = provider.database.last_block_number()?;
|
||||
let last_db_tx_id =
|
||||
provider.database.block_body_indices(last_db_tx_id)?.unwrap().last_tx_num();
|
||||
|
||||
assert!(
|
||||
result.unwrap() > last_db_tx_id,
|
||||
"In-memory transaction ID should be greater than the last database transaction ID"
|
||||
);
|
||||
assert_eq!(result, Some(last_db_tx_id + 1));
|
||||
|
||||
// Generate a random hash not present in any transaction
|
||||
let random_tx_hash = B256::random();
|
||||
|
||||
// Ensure the transaction ID is not found
|
||||
let result = provider.transaction_id(random_tx_hash)?;
|
||||
assert!(result.is_none(), "Transaction ID should not be found");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transaction_by_id() -> eyre::Result<()> {
|
||||
let mut rng = generators::rng();
|
||||
let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
|
||||
&mut rng,
|
||||
TEST_BLOCKS_COUNT,
|
||||
TEST_BLOCKS_COUNT,
|
||||
BlockRangeParams {
|
||||
tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
// In memory
|
||||
// Choose a random transaction ID from in-memory blocks
|
||||
let tx = &in_memory_blocks[0].body[0];
|
||||
let tx_hash = tx.hash();
|
||||
|
||||
// Fetch the transaction ID
|
||||
let tx_id = provider.transaction_id(tx_hash)?.unwrap();
|
||||
|
||||
// Ensure the transaction can be retrieved by its ID
|
||||
let result = provider.transaction_by_id(tx_id)?;
|
||||
assert_eq!(
|
||||
result.unwrap(),
|
||||
*tx,
|
||||
"The retrieved transaction should match the expected transaction"
|
||||
);
|
||||
|
||||
// Database
|
||||
// Choose a random transaction ID from the database blocks
|
||||
let tx = &database_blocks[0].body[0];
|
||||
let tx_hash = tx.hash();
|
||||
|
||||
// Fetch the transaction ID
|
||||
let tx_id = provider.transaction_id(tx_hash)?.unwrap();
|
||||
|
||||
// Ensure the transaction can be retrieved by its ID
|
||||
let result = provider.transaction_by_id(tx_id)?;
|
||||
assert!(result.is_some(), "Transaction should be found in the database");
|
||||
assert_eq!(
|
||||
result.unwrap(),
|
||||
*tx,
|
||||
"The retrieved transaction should match the expected transaction"
|
||||
);
|
||||
|
||||
// Generate a random transaction ID not present in any block
|
||||
let random_tx_id = 999999;
|
||||
|
||||
// Ensure the transaction is not found
|
||||
let result = provider.transaction_by_id(random_tx_id)?;
|
||||
assert!(result.is_none(), "Transaction should not be found");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transaction_by_id_no_hash() -> eyre::Result<()> {
|
||||
let mut rng = generators::rng();
|
||||
let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
|
||||
&mut rng,
|
||||
TEST_BLOCKS_COUNT,
|
||||
TEST_BLOCKS_COUNT,
|
||||
BlockRangeParams {
|
||||
tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
// In memory
|
||||
// Choose a random transaction ID from in-memory blocks
|
||||
let tx = &in_memory_blocks[0].body[0];
|
||||
let tx_hash = tx.hash();
|
||||
|
||||
// Fetch the transaction ID
|
||||
let tx_id = provider.transaction_id(tx_hash)?.unwrap();
|
||||
|
||||
// Ensure the transaction can be retrieved by its ID without hash
|
||||
let result = provider.transaction_by_id_no_hash(tx_id)?;
|
||||
let expected_tx: TransactionSignedNoHash = tx.clone().into();
|
||||
assert_eq!(
|
||||
result.unwrap(),
|
||||
expected_tx,
|
||||
"The retrieved transaction without hash should match the expected transaction"
|
||||
);
|
||||
|
||||
// Database
|
||||
// Choose a random transaction ID from the database blocks
|
||||
let tx = &database_blocks[0].body[0];
|
||||
let tx_hash = tx.hash();
|
||||
|
||||
// Fetch the transaction ID
|
||||
let tx_id = provider.transaction_id(tx_hash)?.unwrap();
|
||||
|
||||
// Ensure the transaction can be retrieved by its ID without hash
|
||||
let result = provider.transaction_by_id_no_hash(tx_id)?;
|
||||
let expected_tx: TransactionSignedNoHash = tx.clone().into();
|
||||
assert_eq!(
|
||||
result.unwrap(),
|
||||
expected_tx,
|
||||
"The retrieved transaction without hash should match the expected transaction"
|
||||
);
|
||||
|
||||
// Generate a random transaction ID not present in any block
|
||||
let random_tx_id = 7656898;
|
||||
|
||||
// Ensure the transaction is not found without hash
|
||||
let result = provider.transaction_by_id_no_hash(random_tx_id)?;
|
||||
assert!(result.is_none(), "Transaction should not be found without hash");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transaction_by_hash() -> eyre::Result<()> {
|
||||
let mut rng = generators::rng();
|
||||
let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
|
||||
&mut rng,
|
||||
TEST_BLOCKS_COUNT,
|
||||
TEST_BLOCKS_COUNT,
|
||||
BlockRangeParams {
|
||||
tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
// In memory
|
||||
// Choose a random transaction hash from the in-memory blocks
|
||||
let tx = &in_memory_blocks[0].body[0];
|
||||
let tx_hash = tx.hash();
|
||||
|
||||
// Ensure the transaction can be retrieved by its hash from the in-memory state
|
||||
let result = provider.transaction_by_hash(tx_hash)?;
|
||||
assert_eq!(
|
||||
result.unwrap(),
|
||||
*tx,
|
||||
"The retrieved transaction should match the expected transaction"
|
||||
);
|
||||
|
||||
// Database
|
||||
// Choose a random transaction hash from the database blocks
|
||||
let tx = &database_blocks[0].body[0];
|
||||
let tx_hash = tx.hash();
|
||||
|
||||
// Ensure the transaction can be retrieved by its hash from the database
|
||||
let result = provider.transaction_by_hash(tx_hash)?;
|
||||
assert_eq!(
|
||||
result.unwrap(),
|
||||
*tx,
|
||||
"The retrieved transaction should match the expected transaction"
|
||||
);
|
||||
|
||||
// Generate a random hash not present in any transaction
|
||||
let random_tx_hash = B256::random();
|
||||
|
||||
// Ensure the transaction is not found by the random hash
|
||||
let result = provider.transaction_by_hash(random_tx_hash)?;
|
||||
assert!(result.is_none(), "Transaction should not be found");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transaction_by_hash_with_meta() -> eyre::Result<()> {
|
||||
let mut rng = generators::rng();
|
||||
let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
|
||||
&mut rng,
|
||||
TEST_BLOCKS_COUNT,
|
||||
TEST_BLOCKS_COUNT,
|
||||
BlockRangeParams {
|
||||
tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
// In memory
|
||||
// Choose a random transaction from the in-memory block
|
||||
let tx = &in_memory_blocks[0].body[0];
|
||||
let tx_hash = tx.hash();
|
||||
|
||||
// Create the expected metadata for this transaction
|
||||
let meta = TransactionMeta {
|
||||
tx_hash,
|
||||
index: 0,
|
||||
block_hash: in_memory_blocks[0].header.hash(),
|
||||
block_number: in_memory_blocks[0].header.number,
|
||||
base_fee: in_memory_blocks[0].header.base_fee_per_gas,
|
||||
excess_blob_gas: None,
|
||||
timestamp: in_memory_blocks[0].header.timestamp,
|
||||
};
|
||||
|
||||
// Ensure the transaction and its metadata can be retrieved from the in-memory state
|
||||
let result = provider.transaction_by_hash_with_meta(tx_hash)?;
|
||||
let (retrieved_tx, retrieved_meta) = result.unwrap();
|
||||
assert_eq!(
|
||||
retrieved_tx, *tx,
|
||||
"The retrieved transaction should match the expected transaction"
|
||||
);
|
||||
assert_eq!(
|
||||
retrieved_meta, meta,
|
||||
"The retrieved metadata should match the expected metadata"
|
||||
);
|
||||
|
||||
// Database
|
||||
// Choose a random transaction from the database blocks
|
||||
let tx = &database_blocks[0].body[0];
|
||||
let tx_hash = tx.hash();
|
||||
|
||||
// Create the expected metadata for this transaction
|
||||
let meta = TransactionMeta {
|
||||
tx_hash,
|
||||
index: 0,
|
||||
block_hash: database_blocks[0].header.hash(),
|
||||
block_number: database_blocks[0].header.number,
|
||||
base_fee: database_blocks[0].header.base_fee_per_gas,
|
||||
excess_blob_gas: None,
|
||||
timestamp: database_blocks[0].header.timestamp,
|
||||
};
|
||||
|
||||
// Ensure the transaction and its metadata can be retrieved from the database
|
||||
let result = provider.transaction_by_hash_with_meta(tx_hash)?;
|
||||
let (retrieved_tx, retrieved_meta) = result.unwrap();
|
||||
assert_eq!(
|
||||
retrieved_tx, *tx,
|
||||
"The retrieved transaction should match the expected transaction"
|
||||
);
|
||||
assert_eq!(
|
||||
retrieved_meta, meta,
|
||||
"The retrieved metadata should match the expected metadata"
|
||||
);
|
||||
|
||||
// Generate a random hash not present in any transaction
|
||||
let random_tx_hash = B256::random();
|
||||
|
||||
// Ensure the transaction with metadata is not found by the random hash
|
||||
let result = provider.transaction_by_hash_with_meta(random_tx_hash)?;
|
||||
assert!(result.is_none(), "Transaction with metadata should not be found");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transaction_block() -> eyre::Result<()> {
|
||||
let mut rng = generators::rng();
|
||||
let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
|
||||
&mut rng,
|
||||
TEST_BLOCKS_COUNT,
|
||||
TEST_BLOCKS_COUNT,
|
||||
BlockRangeParams {
|
||||
tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
// In memory
|
||||
// Choose a random transaction ID from in-memory blocks
|
||||
let tx = &in_memory_blocks[0].body[0];
|
||||
let tx_hash = tx.hash();
|
||||
|
||||
// Fetch the transaction ID
|
||||
let tx_id = provider.transaction_id(tx_hash)?.unwrap();
|
||||
|
||||
// Retrieve the block number for this transaction
|
||||
let result = provider.transaction_block(tx_id)?;
|
||||
let block_number = result.unwrap();
|
||||
|
||||
// Ensure the block number matches the expected block number
|
||||
assert_eq!(
|
||||
block_number, in_memory_blocks[0].header.number,
|
||||
"The block number should match the in-memory block number"
|
||||
);
|
||||
|
||||
// Database
|
||||
// Choose a random transaction from the database block
|
||||
let tx = &database_blocks[0].body[0];
|
||||
let tx_hash = tx.hash();
|
||||
|
||||
// Fetch the transaction ID
|
||||
let tx_id = provider.transaction_id(tx_hash)?.unwrap();
|
||||
|
||||
// Retrieve the block number for this transaction
|
||||
let result = provider.transaction_block(tx_id)?;
|
||||
assert!(
|
||||
result.is_none(),
|
||||
"`block_state_by_tx_id` should be None if the block is in database"
|
||||
);
|
||||
|
||||
// Ensure that invalid transaction ID returns None
|
||||
let result = provider.transaction_block(67675657)?;
|
||||
|
||||
assert!(result.is_none(), "Block number should not be found for an invalid transaction ID");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transactions_found_by_block_hash() -> eyre::Result<()> {
|
||||
let mut rng = generators::rng();
|
||||
let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
|
||||
&mut rng,
|
||||
TEST_BLOCKS_COUNT,
|
||||
TEST_BLOCKS_COUNT,
|
||||
BlockRangeParams {
|
||||
tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
// In memory
|
||||
// Choose a random block hash from in-memory blocks
|
||||
let block_hash = in_memory_blocks[0].header.hash();
|
||||
|
||||
// Retrieve the transactions for this block using the block hash
|
||||
let result = provider.transactions_by_block(BlockHashOrNumber::Hash(block_hash))?;
|
||||
let transactions = result.unwrap();
|
||||
|
||||
// Ensure the transactions match the expected transactions in the block
|
||||
assert_eq!(
|
||||
transactions, in_memory_blocks[0].body,
|
||||
"The transactions should match the in-memory block transactions"
|
||||
);
|
||||
|
||||
// Database
|
||||
// Choose a random block hash from the database blocks
|
||||
let block_hash = database_blocks[0].header.hash();
|
||||
|
||||
// Retrieve the transactions for this block using the block hash
|
||||
let result = provider.transactions_by_block(BlockHashOrNumber::Hash(block_hash))?;
|
||||
let transactions = result.unwrap();
|
||||
|
||||
// Ensure the transactions match the expected transactions in the block
|
||||
assert_eq!(
|
||||
transactions, database_blocks[0].body,
|
||||
"The transactions should match the database block transactions"
|
||||
);
|
||||
|
||||
// Generate a random block hash that does not exist
|
||||
let random_block_hash = B256::random();
|
||||
|
||||
// Try to retrieve transactions for a non-existent block hash
|
||||
let result = provider.transactions_by_block(BlockHashOrNumber::Hash(random_block_hash))?;
|
||||
|
||||
// Ensure no transactions are found
|
||||
assert!(result.is_none(), "No transactions should be found for a non-existent block hash");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transactions_found_by_block_number() -> eyre::Result<()> {
|
||||
let mut rng = generators::rng();
|
||||
let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
|
||||
&mut rng,
|
||||
TEST_BLOCKS_COUNT,
|
||||
TEST_BLOCKS_COUNT,
|
||||
BlockRangeParams {
|
||||
tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
// In memory
|
||||
// Choose a random block number from in-memory blocks
|
||||
let block_number = in_memory_blocks[0].header.number;
|
||||
|
||||
// Retrieve the transactions for this block using the block number
|
||||
let result = provider.transactions_by_block(BlockHashOrNumber::Number(block_number))?;
|
||||
let transactions = result.unwrap();
|
||||
|
||||
// Ensure the transactions match the expected transactions in the block
|
||||
assert_eq!(
|
||||
transactions, in_memory_blocks[0].body,
|
||||
"The transactions should match the in-memory block transactions"
|
||||
);
|
||||
|
||||
// Database
|
||||
// Choose a random block number from the database blocks
|
||||
let block_number = database_blocks[0].header.number;
|
||||
|
||||
// Retrieve the transactions for this block using the block number
|
||||
let result = provider.transactions_by_block(BlockHashOrNumber::Number(block_number))?;
|
||||
let transactions = result.unwrap();
|
||||
|
||||
// Ensure the transactions match the expected transactions in the block
|
||||
assert_eq!(
|
||||
transactions, database_blocks[0].body,
|
||||
"The transactions should match the database block transactions"
|
||||
);
|
||||
|
||||
// Generate a block number that is out of range (non-existent)
|
||||
let non_existent_block_number = u64::MAX;
|
||||
|
||||
// Try to retrieve transactions for a non-existent block number
|
||||
let result =
|
||||
provider.transactions_by_block(BlockHashOrNumber::Number(non_existent_block_number))?;
|
||||
|
||||
// Ensure no transactions are found
|
||||
assert!(
|
||||
result.is_none(),
|
||||
"No transactions should be found for a non-existent block number"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transactions_found_entirely_in_memory() -> eyre::Result<()> {
|
||||
let mut rng = generators::rng();
|
||||
let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
|
||||
&mut rng,
|
||||
TEST_BLOCKS_COUNT,
|
||||
TEST_BLOCKS_COUNT,
|
||||
BlockRangeParams {
|
||||
tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
// In memory
|
||||
// Define a block range entirely within in-memory blocks
|
||||
let start_block = in_memory_blocks[0].header.number;
|
||||
let end_block = in_memory_blocks[1].header.number;
|
||||
|
||||
// Retrieve the transactions for this block range
|
||||
let result = provider.transactions_by_block_range(start_block..=end_block)?;
|
||||
|
||||
// Ensure the transactions match the expected transactions in the in-memory blocks
|
||||
assert_eq!(result.len(), 2);
|
||||
assert_eq!(result[0], in_memory_blocks[0].body);
|
||||
assert_eq!(result[1], in_memory_blocks[1].body);
|
||||
|
||||
// Database
|
||||
// Define a block range entirely within database blocks
|
||||
let start_block = database_blocks[0].header.number;
|
||||
let end_block = database_blocks[1].header.number;
|
||||
|
||||
// Retrieve the transactions for this block range
|
||||
let result = provider.transactions_by_block_range(start_block..=end_block)?;
|
||||
|
||||
// Ensure the transactions match the expected transactions in the database blocks
|
||||
assert_eq!(result.len(), 2);
|
||||
assert_eq!(result[0], database_blocks[0].body);
|
||||
assert_eq!(result[1], database_blocks[1].body);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transactions_by_tx_range() -> eyre::Result<()> {
|
||||
let mut rng = generators::rng();
|
||||
let (provider, database_blocks, _, _) = provider_with_random_blocks(
|
||||
&mut rng,
|
||||
TEST_BLOCKS_COUNT,
|
||||
0,
|
||||
BlockRangeParams {
|
||||
tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
// Define a valid transaction range within the database
|
||||
let start_tx_num = 0;
|
||||
let end_tx_num = 1;
|
||||
|
||||
// Retrieve the transactions for this transaction number range
|
||||
let result = provider.transactions_by_tx_range(start_tx_num..=end_tx_num)?;
|
||||
|
||||
// Ensure the transactions match the expected transactions in the database
|
||||
assert_eq!(result.len(), 2);
|
||||
assert_eq!(result[0], database_blocks[0].body[0].clone().into());
|
||||
assert_eq!(result[1], database_blocks[0].body[1].clone().into());
|
||||
|
||||
// Define an empty range that should return no transactions
|
||||
let start_tx_num = u64::MAX;
|
||||
let end_tx_num = u64::MAX;
|
||||
|
||||
// Retrieve the transactions for this range
|
||||
let result = provider.transactions_by_tx_range(start_tx_num..end_tx_num)?;
|
||||
|
||||
// Ensure no transactions are returned
|
||||
assert!(
|
||||
result.is_empty(),
|
||||
"No transactions should be found for an empty transaction range"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_senders_by_tx_range() -> eyre::Result<()> {
|
||||
let mut rng = generators::rng();
|
||||
let (provider, database_blocks, _, _) = provider_with_random_blocks(
|
||||
&mut rng,
|
||||
TEST_BLOCKS_COUNT,
|
||||
0,
|
||||
BlockRangeParams {
|
||||
tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
// Define a valid transaction range within the database
|
||||
let start_tx_num = 0;
|
||||
let end_tx_num = 1;
|
||||
|
||||
// Retrieve the senders for this transaction number range
|
||||
let result = provider.senders_by_tx_range(start_tx_num..=end_tx_num)?;
|
||||
|
||||
// Ensure the sender addresses match the expected addresses in the database
|
||||
assert_eq!(result.len(), 2);
|
||||
assert_eq!(
|
||||
result[0],
|
||||
database_blocks[0].senders().unwrap()[0],
|
||||
"The sender address should match the expected sender address"
|
||||
);
|
||||
assert_eq!(
|
||||
result[1],
|
||||
database_blocks[0].senders().unwrap()[1],
|
||||
"The sender address should match the expected sender address"
|
||||
);
|
||||
|
||||
// Define an empty range that should return no sender addresses
|
||||
let start_tx_num = u64::MAX;
|
||||
let end_tx_num = u64::MAX;
|
||||
|
||||
// Retrieve the senders for this range
|
||||
let result = provider.senders_by_tx_range(start_tx_num..end_tx_num)?;
|
||||
|
||||
// Ensure no sender addresses are returned
|
||||
assert!(
|
||||
result.is_empty(),
|
||||
"No sender addresses should be found for an empty transaction range"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transaction_sender_found_in_memory() -> eyre::Result<()> {
|
||||
let mut rng = generators::rng();
|
||||
let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
|
||||
&mut rng,
|
||||
TEST_BLOCKS_COUNT,
|
||||
TEST_BLOCKS_COUNT,
|
||||
BlockRangeParams {
|
||||
tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
// In memory
|
||||
// Choose a random transaction from the in-memory block
|
||||
let tx = &in_memory_blocks[0].body[0];
|
||||
|
||||
// Retrieve the transaction ID
|
||||
let tx_id = provider.transaction_id(tx.hash())?.unwrap();
|
||||
|
||||
// Retrieve the sender address for this transaction
|
||||
let result = provider.transaction_sender(tx_id)?;
|
||||
|
||||
// Ensure the sender address matches the expected sender address
|
||||
let expected_sender = tx.recover_signer().unwrap();
|
||||
assert_eq!(
|
||||
result,
|
||||
Some(expected_sender),
|
||||
"The sender address should match the expected sender address"
|
||||
);
|
||||
|
||||
// Database
|
||||
// Choose a random transaction from the database block
|
||||
let tx = &database_blocks[0].body[0];
|
||||
|
||||
// Retrieve the transaction ID
|
||||
let tx_id = provider.transaction_id(tx.hash())?.unwrap();
|
||||
|
||||
// Retrieve the sender address for this transaction
|
||||
let result = provider.transaction_sender(tx_id)?;
|
||||
|
||||
// Ensure the sender address matches the expected sender address
|
||||
let expected_sender = tx.recover_signer().unwrap();
|
||||
assert_eq!(
|
||||
result,
|
||||
Some(expected_sender),
|
||||
"The sender address should match the expected sender address"
|
||||
);
|
||||
|
||||
// Generate a random transaction ID that does not exist
|
||||
let invalid_tx_id = u64::MAX;
|
||||
|
||||
// Attempt to retrieve the sender address for this invalid transaction ID
|
||||
let result = provider.transaction_sender(invalid_tx_id)?;
|
||||
|
||||
// Ensure no sender address is found
|
||||
assert!(
|
||||
result.is_none(),
|
||||
"No sender address should be found for an invalid transaction ID"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user