feat: Use consistent pending block in RPC/Blockchaintree (#2767)

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
chirag-bgh
2023-05-24 15:03:30 +05:30
committed by GitHub
parent d7e013c4f2
commit 2ec97f34fe
4 changed files with 24 additions and 9 deletions

1
Cargo.lock generated
View File

@ -4681,6 +4681,7 @@ version = "0.1.0"
dependencies = [
"aquamarine",
"assert_matches",
"linked_hash_set",
"lru 0.10.0",
"parking_lot 0.12.1",
"reth-db",

View File

@ -19,6 +19,7 @@ reth-interfaces = { path = "../interfaces" }
reth-db = { path = "../storage/db" }
reth-provider = { path = "../storage/provider" }
# common
parking_lot = { version = "0.12"}
lru = "0.10"
@ -26,6 +27,7 @@ tracing = { workspace = true }
# mics
aquamarine = "0.3.0"
linked_hash_set = "0.1.4"
[dev-dependencies]

View File

@ -2,6 +2,7 @@
use super::chain::BlockChainId;
use crate::canonical_chain::CanonicalChain;
use linked_hash_set::LinkedHashSet;
use reth_primitives::{BlockHash, BlockNumHash, BlockNumber, SealedBlockWithSenders};
use reth_provider::Chain;
use std::collections::{btree_map, hash_map, BTreeMap, BTreeSet, HashMap, HashSet};
@ -21,8 +22,13 @@ pub struct BlockIndices {
/// `number_to_block` as those are chain specific indices.
canonical_chain: CanonicalChain,
/// Index needed when discarding the chain, so we can remove connected chains from tree.
///
/// This maintains insertion order for all child blocks, so
/// [BlockIndices::pending_block_num_hash] returns always the same block: the first child block
/// we inserted.
///
/// NOTE: It contains just blocks that are forks as a key and not all blocks.
fork_to_child: HashMap<BlockHash, HashSet<BlockHash>>,
fork_to_child: HashMap<BlockHash, LinkedHashSet<BlockHash>>,
/// Utility index for Block number to block hash(s).
///
/// This maps all blocks with same block number to their hash.
@ -60,7 +66,7 @@ impl BlockIndices {
}
/// Return fork to child indices
pub fn fork_to_child(&self) -> &HashMap<BlockHash, HashSet<BlockHash>> {
pub fn fork_to_child(&self) -> &HashMap<BlockHash, LinkedHashSet<BlockHash>> {
&self.fork_to_child
}
@ -69,11 +75,13 @@ impl BlockIndices {
&self.blocks_to_chain
}
/// Returns the hash and number of the pending block (the first block in the
/// [Self::pending_blocks]) set.
/// Returns the hash and number of the pending block.
///
/// It is possible that multiple child blocks for the canonical tip exist.
/// This will always return the _first_ child we recorded for the canonical tip.
pub(crate) fn pending_block_num_hash(&self) -> Option<BlockNumHash> {
let canonical_tip = self.canonical_tip();
let hash = self.fork_to_child.get(&canonical_tip.hash)?.iter().next().copied()?;
let hash = self.fork_to_child.get(&canonical_tip.hash)?.front().copied()?;
Some(BlockNumHash { number: canonical_tip.number + 1, hash })
}
@ -132,7 +140,7 @@ impl BlockIndices {
}
let first = chain.first();
// add parent block -> block index
self.fork_to_child.entry(first.parent_hash).or_default().insert(first.hash());
self.fork_to_child.entry(first.parent_hash).or_default().insert_if_absent(first.hash());
}
/// Get the chain ID the block belongs to

View File

@ -1021,10 +1021,10 @@ impl<DB: Database, C: Consensus, EF: ExecutorFactory> BlockchainTree<DB, C, EF>
#[cfg(test)]
mod tests {
use crate::block_buffer::BufferedBlocks;
use super::*;
use crate::block_buffer::BufferedBlocks;
use assert_matches::assert_matches;
use linked_hash_set::LinkedHashSet;
use reth_db::{
mdbx::{test_utils::create_test_rw_db, Env, WriteMap},
transaction::DbTxMut,
@ -1129,7 +1129,11 @@ mod tests {
assert_eq!(*tree.block_indices.blocks_to_chain(), block_to_chain);
}
if let Some(fork_to_child) = self.fork_to_child {
assert_eq!(*tree.block_indices.fork_to_child(), fork_to_child);
let mut x: HashMap<BlockHash, LinkedHashSet<BlockHash>> = HashMap::new();
for (key, hash_set) in fork_to_child.into_iter() {
x.insert(key, hash_set.into_iter().collect());
}
assert_eq!(*tree.block_indices.fork_to_child(), x);
}
if let Some(pending_blocks) = self.pending_blocks {
let (num, hashes) = tree.block_indices.pending_blocks();