diff --git a/crates/chain/src/local_chain.rs b/crates/chain/src/local_chain.rs index 9be62dee38..f1e4b02113 100644 --- a/crates/chain/src/local_chain.rs +++ b/crates/chain/src/local_chain.rs @@ -4,6 +4,7 @@ use core::convert::Infallible; use crate::collections::BTreeMap; use crate::{BlockId, ChainOracle}; +use alloc::collections::BTreeSet; use alloc::sync::Arc; use bitcoin::block::Header; use bitcoin::BlockHash; @@ -148,6 +149,33 @@ impl CheckPoint { pub fn iter(&self) -> CheckPointIter { self.clone().into_iter() } + + /// Find checkpoint at `height`. + /// + /// Returns `None` if checkpoint at `height` does not exist`. + pub fn query(&self, height: u32) -> Option { + self.iter() + .take_while(|cp| cp.height() >= height) + .find(|cp| cp.height() == height) + } + + /// Find checkpoints of the given `heights`. + /// + /// This returns an iterator which iterates over the requested heights and whether a + /// corresponding checkpoint is found. + pub fn query_multi(&self, heights: BTreeSet) -> impl Iterator)> { + let mut cp_iter = self.iter(); + let mut current_cp = cp_iter.next(); + heights.into_iter().rev().map(move |h| { + loop { + match current_cp.as_ref() { + Some(cp) if cp.height() > h => current_cp = cp_iter.next(), + Some(cp) if cp.height() == h => return (h, Some(cp.clone())), + _ => return (h, None), + } + } + }) + } } /// Iterates over checkpoints backwards.