11use core:: { convert:: Infallible , ops:: Deref } ;
22
3- use alloc:: {
4- collections:: { BTreeMap , BTreeSet } ,
5- vec:: Vec ,
6- } ;
3+ use alloc:: collections:: { BTreeMap , BTreeSet } ;
74use bitcoin:: BlockHash ;
85
9- use crate :: { BlockId , ChainOracle } ;
6+ use crate :: { Append , BlockId , ChainOracle } ;
107
118#[ derive( Debug , Default , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
129pub struct LocalChain {
@@ -56,6 +53,12 @@ impl From<LocalChain> for BTreeMap<u32, BlockHash> {
5653 }
5754}
5855
56+ impl From < BTreeMap < u32 , BlockHash > > for LocalChain {
57+ fn from ( value : BTreeMap < u32 , BlockHash > ) -> Self {
58+ Self { blocks : value }
59+ }
60+ }
61+
5962impl LocalChain {
6063 pub fn tip ( & self ) -> Option < BlockId > {
6164 self . blocks
@@ -66,10 +69,7 @@ impl LocalChain {
6669
6770 /// This is like the sparsechain's logic, expect we must guarantee that all invalidated heights
6871 /// are to be re-filled.
69- pub fn determine_changeset < U > ( & self , update : & U ) -> Result < ChangeSet , UpdateError >
70- where
71- U : AsRef < BTreeMap < u32 , BlockHash > > ,
72- {
72+ pub fn determine_changeset ( & self , update : & Self ) -> Result < ChangeSet , UpdateNotConnectedError > {
7373 let update = update. as_ref ( ) ;
7474 let update_tip = match update. keys ( ) . last ( ) . cloned ( ) {
7575 Some ( tip) => tip,
@@ -96,24 +96,9 @@ impl LocalChain {
9696 // the first block of height to invalidate (if any) should be represented in the update
9797 if let Some ( first_invalid_height) = invalidate_from_height {
9898 if !update. contains_key ( & first_invalid_height) {
99- return Err ( UpdateError :: NotConnected ( first_invalid_height) ) ;
100- }
101- }
102-
103- let invalidated_heights = invalidate_from_height
104- . into_iter ( )
105- . flat_map ( |from_height| self . blocks . range ( from_height..) . map ( |( h, _) | h) ) ;
106-
107- // invalidated heights must all exist in the update
108- let mut missing_heights = Vec :: < u32 > :: new ( ) ;
109- for invalidated_height in invalidated_heights {
110- if !update. contains_key ( invalidated_height) {
111- missing_heights. push ( * invalidated_height) ;
99+ return Err ( UpdateNotConnectedError ( first_invalid_height) ) ;
112100 }
113101 }
114- if !missing_heights. is_empty ( ) {
115- return Err ( UpdateError :: MissingHeightsInUpdate ( missing_heights) ) ;
116- }
117102
118103 let mut changeset = BTreeMap :: < u32 , BlockHash > :: new ( ) ;
119104 for ( height, new_hash) in update {
@@ -136,7 +121,7 @@ impl LocalChain {
136121 ///
137122 /// [`determine_changeset`]: Self::determine_changeset
138123 /// [`apply_changeset`]: Self::apply_changeset
139- pub fn apply_update ( & mut self , update : Self ) -> Result < ChangeSet , UpdateError > {
124+ pub fn apply_update ( & mut self , update : Self ) -> Result < ChangeSet , UpdateNotConnectedError > {
140125 let changeset = self . determine_changeset ( & update) ?;
141126 self . apply_changeset ( changeset. clone ( ) ) ;
142127 Ok ( changeset)
@@ -160,7 +145,7 @@ impl LocalChain {
160145 derive( serde:: Deserialize , serde:: Serialize ) ,
161146 serde( crate = "serde_crate" )
162147) ]
163- pub struct ChangeSet ( pub BTreeMap < u32 , BlockHash > ) ;
148+ pub struct ChangeSet ( pub ( crate ) BTreeMap < u32 , BlockHash > ) ;
164149
165150impl Deref for ChangeSet {
166151 type Target = BTreeMap < u32 , BlockHash > ;
@@ -170,32 +155,30 @@ impl Deref for ChangeSet {
170155 }
171156}
172157
173- /// Represents an update failure of [`LocalChain`].
174- #[ derive( Clone , Debug , PartialEq ) ]
175- pub enum UpdateError {
176- /// The update cannot be applied to the chain because the chain suffix it represents did not
177- /// connect to the existing chain. This error case contains the checkpoint height to include so
178- /// that the chains can connect.
179- NotConnected ( u32 ) ,
180- /// If the update results in displacements of original blocks, the update should include all new
181- /// block hashes that have displaced the original block hashes. This error case contains the
182- /// heights of all missing block hashes in the update.
183- MissingHeightsInUpdate ( Vec < u32 > ) ,
158+ impl Append for ChangeSet {
159+ fn append ( & mut self , mut other : Self ) {
160+ BTreeMap :: append ( & mut self . 0 , & mut other. 0 )
161+ }
184162}
185163
186- impl core:: fmt:: Display for UpdateError {
164+ /// Represents an update failure of [`LocalChain`] due to the update not connecting to the original
165+ /// chain.
166+ ///
167+ /// The update cannot be applied to the chain because the chain suffix it represents did not
168+ /// connect to the existing chain. This error case contains the checkpoint height to include so
169+ /// that the chains can connect.
170+ #[ derive( Clone , Debug , PartialEq ) ]
171+ pub struct UpdateNotConnectedError ( u32 ) ;
172+
173+ impl core:: fmt:: Display for UpdateNotConnectedError {
187174 fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
188- match self {
189- UpdateError :: NotConnected ( heights) => write ! (
190- f,
191- "the update cannot connect with the chain, try include blockhash at height {}" ,
192- heights
193- ) ,
194- UpdateError :: MissingHeightsInUpdate ( missing_heights) => write ! (
195- f,
196- "block hashes of these heights must be included in the update to succeed: {:?}" ,
197- missing_heights
198- ) ,
199- }
175+ write ! (
176+ f,
177+ "the update cannot connect with the chain, try include block at height {}" ,
178+ self . 0
179+ )
200180 }
201181}
182+
183+ #[ cfg( feature = "std" ) ]
184+ impl std:: error:: Error for UpdateNotConnectedError { }
0 commit comments