diff --git a/chain/src/chain.rs b/chain/src/chain.rs index 1c94d85ef3..b83e8a8b76 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -138,7 +138,13 @@ impl ChainController { // Relay need this pub fn get_orphan_block(&self, hash: &Byte32) -> Option { - todo!("load orphan block") + if self.orphan_block_broker.exist(hash){ + // TODO we should store BlockView in memory when CKB node not in IBD mode (Relay protocol need load orphan block) + // store orphan blocks to RocksDB only when CKB node in IBD mode + todo!("load orphan block") + return Some(); + } + None } } diff --git a/chain/src/orphan_block_pool.rs b/chain/src/orphan_block_pool.rs index ead446d3ca..a4a8c2f234 100644 --- a/chain/src/orphan_block_pool.rs +++ b/chain/src/orphan_block_pool.rs @@ -1,10 +1,24 @@ use ckb_logger::debug; use ckb_types::core::EpochNumber; +use ckb_types::packed::Byte32; use ckb_types::{core, packed}; use ckb_util::{parking_lot::RwLock, shrink_to_fit}; use std::collections::{HashMap, HashSet, VecDeque}; pub type ParentHash = packed::Byte32; +pub struct OrphanBlockId(ParentHash, packed::Byte32); + +impl OrphanBlockId { + pub fn new(parent_hash: ParentHash, block_hash: Byte32) -> Self { + OrphanBlockId(parent_hash, block_hash) + } + pub fn parent_hash(&self) -> ParentHash { + self.0.clone() + } + pub fn block_hash(&self) -> ParentHash { + self.1.clone() + } +} const SHRINK_THRESHOLD: usize = 100; const EXPIRED_EPOCH: u64 = 6; @@ -12,7 +26,7 @@ const EXPIRED_EPOCH: u64 = 6; #[derive(Default)] struct InnerPool { // Group by blocks in the pool by the parent hash. - blocks: HashMap>, + blocks: HashMap>, // The map tells the parent hash when given the hash of a block in the pool. // // The block is in the orphan pool if and only if the block hash exists as a key in this map. @@ -30,13 +44,13 @@ impl InnerPool { } } - fn insert(&mut self, block: core::BlockView) { - let hash = block.header().hash(); - let parent_hash = block.data().header().raw().parent_hash(); + fn insert(&mut self, block: OrphanBlockId) { + let hash = block.hash(); + let parent_hash = block.parent_hash(); self.blocks .entry(parent_hash.clone()) .or_insert_with(HashMap::default) - .insert(hash.clone(), block); + .insert(hash.clone()); // Out-of-order insertion needs to be deduplicated self.leaders.remove(&hash); // It is a possible optimization to make the judgment in advance, @@ -50,7 +64,7 @@ impl InnerPool { self.parents.insert(hash, parent_hash); } - pub fn remove_blocks_by_parent(&mut self, parent_hash: &ParentHash) -> Vec { + pub fn remove_blocks_by_parent(&mut self, parent_hash: &ParentHash) -> Vec { // try remove leaders first if !self.leaders.remove(parent_hash) { return Vec::new(); @@ -59,7 +73,7 @@ impl InnerPool { let mut queue: VecDeque = VecDeque::new(); queue.push_back(parent_hash.to_owned()); - let mut removed: Vec = Vec::new(); + let mut removed: Vec = Vec::new(); while let Some(parent_hash) = queue.pop_front() { if let Some(orphaned) = self.blocks.remove(&parent_hash) { let (hashes, blocks): (Vec<_>, Vec<_>) = orphaned.into_iter().unzip(); @@ -84,14 +98,22 @@ impl InnerPool { removed } - pub fn get_block(&self, hash: &packed::Byte32) -> Option { + pub fn exist(&self, hash: &packed::Byte32) -> bool { self.parents.get(hash).and_then(|parent_hash| { self.blocks .get(parent_hash) - .and_then(|blocks| blocks.get(hash).cloned()) + .and_then(|blocks| blocks.get(hash).is_some()) }) } + // pub fn get_block(&self, hash: &packed::Byte32) -> Option { + // self.parents.get(hash).and_then(|parent_hash| { + // self.blocks + // .get(parent_hash) + // .and_then(|blocks| blocks.get(hash).cloned()) + // }) + // } + /// cleanup expired blocks(epoch + EXPIRED_EPOCH < tip_epoch) pub fn clean_expired_blocks(&mut self, tip_epoch: EpochNumber) -> Vec { let mut result = vec![]; @@ -100,7 +122,7 @@ impl InnerPool { if self.need_clean(hash, tip_epoch) { // remove items in orphan pool and return hash to callee(clean header map) let descendants = self.remove_blocks_by_parent(hash); - result.extend(descendants.iter().map(|block| block.hash())); + result.extend(descendants.iter().map(|block| block.block_hash())); } } result @@ -135,16 +157,20 @@ impl OrphanBlockPool { } /// Insert orphaned block, for which we have already requested its parent block - pub fn insert(&self, block: core::BlockView) { + pub fn insert(&self, block: OrphanBlockId) { self.inner.write().insert(block); } - pub fn remove_blocks_by_parent(&self, parent_hash: &ParentHash) -> Vec { + pub fn remove_blocks_by_parent(&self, parent_hash: &ParentHash) -> Vec { self.inner.write().remove_blocks_by_parent(parent_hash) } - pub fn get_block(&self, hash: &packed::Byte32) -> Option { - self.inner.read().get_block(hash) + // pub fn get_block(&self, hash: &packed::Byte32) -> Option { + // self.inner.read().get_block(hash) + // } + + pub fn exist(&self, hash: &packed::Byte32) -> bool { + self.inner.read().exist(hash) } pub fn clean_expired_blocks(&self, epoch: EpochNumber) -> Vec {