@@ -8,15 +8,19 @@ use alloc::sync::Arc;
88use bitcoin:: BlockHash ;
99
1010/// A structure that represents changes to [`LocalChain`].
11+ ///
12+ /// The key represents the block height, and the value either represents added a new [`CheckPoint`]
13+ /// (if [`Some`]), or removing a [`CheckPoint`] (if [`None`]).
1114pub type ChangeSet = BTreeMap < u32 , Option < BlockHash > > ;
1215
1316/// A [`LocalChain`] checkpoint is used to find the agreement point between two chains and as a
1417/// transaction anchor.
1518///
1619/// Each checkpoint contains the height and hash of a block ([`BlockId`]).
1720///
18- /// Internaly, checkpoints are nodes of a linked-list. This allows the caller to view the entire
19- /// chain without holding a lock to [`LocalChain`].
21+ /// Internaly, checkpoints are nodes of a reference-counted linked-list. This allows the caller to
22+ /// cheaply clone a [`CheckPoint`] without copying the whole list and to view the entire chain
23+ /// without holding a lock on [`LocalChain`].
2024#[ derive( Debug , Clone ) ]
2125pub struct CheckPoint ( Arc < CPInner > ) ;
2226
@@ -54,10 +58,7 @@ impl CheckPoint {
5458 ///
5559 /// Returns an `Err(self)` if there is block which does not have a greater height than the
5660 /// previous one.
57- pub fn extend_with_blocks (
58- self ,
59- blocks : impl IntoIterator < Item = BlockId > ,
60- ) -> Result < Self , Self > {
61+ pub fn extend ( self , blocks : impl IntoIterator < Item = BlockId > ) -> Result < Self , Self > {
6162 let mut curr = self . clone ( ) ;
6263 for block in blocks {
6364 curr = curr. push ( block) . map_err ( |_| self . clone ( ) ) ?;
@@ -120,12 +121,15 @@ impl IntoIterator for CheckPoint {
120121/// A struct to update [`LocalChain`].
121122///
122123/// This is used as input for [`LocalChain::apply_update`]. It contains the update's chain `tip` and
123- /// a `bool` which signals whether this update can introduce blocks below the original chain's tip
124- /// without invalidating blocks residing on the original chain. Block-by-block syncing mechanisms
125- /// would typically create updates that builds upon the previous tip. In this case, this paramater
126- /// would be `false`. Script-pubkey based syncing mechanisms may not introduce transactions in a
127- /// chronological order so some updates require introducing older blocks (to anchor older
128- /// transactions). For script-pubkey based syncing, this parameter would typically be `true`.
124+ /// a flag `introduce_older_blocks` which signals whether this update intends to introduce missing
125+ /// blocks to the original chain.
126+ ///
127+ /// Block-by-block syncing mechanisms would typically create updates that builds upon the previous
128+ /// tip. In this case, `introduce_older_blocks` would be `false`.
129+ ///
130+ /// Script-pubkey based syncing mechanisms may not introduce transactions in a chronological order
131+ /// so some updates require introducing older blocks (to anchor older transactions). For
132+ /// script-pubkey based syncing, `introduce_older_blocks` would typically be `true`.
129133#[ derive( Debug , Clone ) ]
130134pub struct Update {
131135 /// The update chain's new tip.
@@ -205,13 +209,13 @@ impl LocalChain {
205209
206210 /// Construct a [`LocalChain`] from a given `checkpoint` tip.
207211 pub fn from_tip ( tip : CheckPoint ) -> Self {
208- let mut _self = Self {
212+ let mut chain = Self {
209213 tip : Some ( tip) ,
210214 ..Default :: default ( )
211215 } ;
212- _self . reindex ( 0 ) ;
213- debug_assert ! ( _self . _check_index_is_consistent_with_tip( ) ) ;
214- _self
216+ chain . reindex ( 0 ) ;
217+ debug_assert ! ( chain . _check_index_is_consistent_with_tip( ) ) ;
218+ chain
215219 }
216220
217221 /// Constructs a [`LocalChain`] from a [`BTreeMap`] of height to [`BlockHash`].
@@ -247,26 +251,23 @@ impl LocalChain {
247251
248252 /// Returns whether the [`LocalChain`] is empty (has no checkpoints).
249253 pub fn is_empty ( & self ) -> bool {
250- self . tip . is_none ( )
254+ let res = self . tip . is_none ( ) ;
255+ debug_assert_eq ! ( res, self . index. is_empty( ) ) ;
256+ res
251257 }
252258
253259 /// Applies the given `update` to the chain.
254260 ///
255261 /// The method returns [`ChangeSet`] on success. This represents the applied changes to `self`.
256262 ///
257- /// To update, the `update_tip` must *connect* with `self`. If `self` and `update_tip` has a
258- /// mutual checkpoint (same height and hash), it can connect if:
259- /// * The mutual checkpoint is the tip of `self`.
260- /// * An ancestor of `update_tip` has a height which is of the checkpoint one higher than the
261- /// mutual checkpoint from `self`.
262- ///
263- /// Additionally:
264- /// * If `self` is empty, `update_tip` will always connect.
265- /// * If `self` only has one checkpoint, `update_tip` must have an ancestor checkpoint with the
266- /// same height as it.
263+ /// There must be no ambiguity about which of the existing chain's blocks are still valid and
264+ /// which are now invalid. That is, the new chain must implicitly connect to a definite block in
265+ /// the existing chain and invalidate the block after it (if it exists) by including a block at
266+ /// the same height but with a different hash to explicitly exclude it as a connection point.
267267 ///
268- /// To invalidate from a given checkpoint, `update_tip` must contain an ancestor checkpoint with
269- /// the same height but different hash.
268+ /// Additionally, an empty chain can be updated with any chain, and a chain with a single block
269+ /// can have it's block invalidated by an update chain with a block at the same height but
270+ /// different hash.
270271 ///
271272 /// # Errors
272273 ///
@@ -325,7 +326,7 @@ impl LocalChain {
325326 }
326327 let new_tip = match base {
327328 Some ( base) => Some (
328- base. extend_with_blocks ( extension. into_iter ( ) . map ( BlockId :: from) )
329+ base. extend ( extension. into_iter ( ) . map ( BlockId :: from) )
329330 . expect ( "extension is strictly greater than base" ) ,
330331 ) ,
331332 None => LocalChain :: from_blocks ( extension) . tip ( ) ,
@@ -379,15 +380,15 @@ impl LocalChain {
379380 self . index . iter ( ) . map ( |( k, v) | ( * k, Some ( * v) ) ) . collect ( )
380381 }
381382
382- /// Iterate over checkpoints in decending height order.
383+ /// Iterate over checkpoints in descending height order.
383384 pub fn iter_checkpoints ( & self ) -> CheckPointIter {
384385 CheckPointIter {
385386 current : self . tip . as_ref ( ) . map ( |tip| tip. 0 . clone ( ) ) ,
386387 }
387388 }
388389
389390 /// Get a reference to the internal index mapping the height to block hash.
390- pub fn heights ( & self ) -> & BTreeMap < u32 , BlockHash > {
391+ pub fn blocks ( & self ) -> & BTreeMap < u32 , BlockHash > {
391392 & self . index
392393 }
393394
0 commit comments