11extern crate alloc;
22use std:: {
33 collections:: { BTreeMap , HashSet } ,
4- ops:: Range ,
54 sync:: Arc ,
65} ;
76
@@ -18,37 +17,33 @@ use super::{
1817 error:: { CFHeaderSyncError , CFilterSyncError , HeaderSyncError } ,
1918 graph:: { AcceptHeaderChanges , BlockTree , HeaderRejection } ,
2019 CFHeaderChanges , Filter , FilterCheck , FilterHeaderRequest , FilterRequest , FilterRequestState ,
21- HeaderChainChanges , HeightExt , HeightMonitor , PeerId ,
20+ HeaderChainChanges , HeightMonitor , PeerId ,
2221} ;
2322#[ cfg( feature = "filter-control" ) ]
2423use crate :: IndexedFilter ;
2524use crate :: {
2625 chain:: header_batch:: HeadersBatch ,
27- db:: { traits:: HeaderStore , BlockHeaderChanges } ,
2826 dialog:: Dialog ,
29- error:: HeaderPersistenceError ,
3027 messages:: { Event , Warning } ,
3128 Info , Progress ,
3229} ;
3330
34- const REORG_LOOKBACK : u32 = 7 ;
3531const FILTER_BASIC : u8 = 0x00 ;
3632const CF_HEADER_BATCH_SIZE : u32 = 1_999 ;
3733const FILTER_BATCH_SIZE : u32 = 999 ;
3834
3935#[ derive( Debug ) ]
40- pub ( crate ) struct Chain < H : HeaderStore > {
36+ pub ( crate ) struct Chain {
4137 pub ( crate ) header_chain : BlockTree ,
4238 request_state : FilterRequestState ,
4339 checkpoints : HeaderCheckpoints ,
4440 network : Network ,
45- db : Arc < Mutex < H > > ,
4641 heights : Arc < Mutex < HeightMonitor > > ,
4742 scripts : HashSet < ScriptBuf > ,
4843 dialog : Arc < Dialog > ,
4944}
5045
51- impl < H : HeaderStore > Chain < H > {
46+ impl Chain {
5247 #[ allow( clippy:: too_many_arguments) ]
5348 pub ( crate ) fn new (
5449 network : Network ,
@@ -57,7 +52,6 @@ impl<H: HeaderStore> Chain<H> {
5752 checkpoints : HeaderCheckpoints ,
5853 dialog : Arc < Dialog > ,
5954 height_monitor : Arc < Mutex < HeightMonitor > > ,
60- db : H ,
6155 quorum_required : u8 ,
6256 ) -> Self {
6357 let header_chain = BlockTree :: new ( anchor, network) ;
@@ -66,7 +60,6 @@ impl<H: HeaderStore> Chain<H> {
6660 checkpoints,
6761 request_state : FilterRequestState :: new ( quorum_required) ,
6862 network,
69- db : Arc :: new ( Mutex :: new ( db) ) ,
7063 heights : height_monitor,
7164 scripts,
7265 dialog,
@@ -93,76 +86,6 @@ impl<H: HeaderStore> Chain<H> {
9386 }
9487 }
9588
96- // Load in headers, ideally allowing the difficulty adjustment to be audited and
97- // reorganizations to be handled gracefully.
98- pub ( crate ) async fn load_headers ( & mut self ) -> Result < ( ) , HeaderPersistenceError < H :: Error > > {
99- let mut db = self . db . lock ( ) . await ;
100- // The original height the user requested a scan after
101- let scan_height = self . header_chain . height ( ) ;
102- // The header relevant to compute the next adjustment
103- let last_adjustment = scan_height. last_epoch_start ( self . network ) ;
104- // Seven blocks ago
105- let reorg = scan_height. saturating_sub ( REORG_LOOKBACK ) ;
106- // To handle adjustments and reorgs, we would have the minimum of each of these heights
107- let min_interesting_height = last_adjustment. min ( reorg) ;
108- let max_interesting_height = last_adjustment. max ( reorg) ;
109- // Get the maximum of the two interesting heights. In case the minimum is not available
110- if let Some ( header) = db. header_at ( max_interesting_height) . await . ok ( ) . flatten ( ) {
111- self . header_chain =
112- BlockTree :: from_header ( max_interesting_height, header, self . network ) ;
113- }
114- // If this succeeds, both reorgs and difficulty adjustments can be handled gracefully.
115- if let Some ( header) = db. header_at ( min_interesting_height) . await . ok ( ) . flatten ( ) {
116- self . header_chain =
117- BlockTree :: from_header ( min_interesting_height, header, self . network ) ;
118- }
119- // Now that the block tree is updated to the appropriate start, load in the rest of
120- // the history from this point onward. This is either: from the user start height,
121- // from the last difficulty adjustment, or seven blocks ago, depending on what the
122- // header store was able to provide.
123- let loaded_headers = db
124- . load ( self . header_chain . height ( ) . increment ( ) ..)
125- . await
126- . map_err ( HeaderPersistenceError :: Database ) ?;
127- for ( height, header) in loaded_headers {
128- let apply_header_changes = self . header_chain . accept_header ( header) ;
129- match apply_header_changes {
130- AcceptHeaderChanges :: Accepted { connected_at } => {
131- if height. ne ( & connected_at. height ) {
132- self . dialog . send_warning ( Warning :: CorruptedHeaders ) ;
133- return Err ( HeaderPersistenceError :: HeadersDoNotLink ) ;
134- }
135- if let Some ( checkpoint) = self . checkpoints . next ( ) {
136- if connected_at. header . block_hash ( ) . eq ( & checkpoint. hash ) {
137- self . checkpoints . advance ( )
138- }
139- }
140- }
141- AcceptHeaderChanges :: Rejected ( reject_reason) => match reject_reason {
142- HeaderRejection :: UnknownPrevHash ( _) => {
143- return Err ( HeaderPersistenceError :: CannotLocateHistory ) ;
144- }
145- HeaderRejection :: InvalidPow { expected, got } => {
146- crate :: log!(
147- self . dialog,
148- format!(
149- "Unexpected invalid proof of work when importing a block header. expected {}, got: {}" ,
150- expected. to_consensus( ) ,
151- got. to_consensus( )
152- )
153- ) ;
154- }
155- } ,
156- _ => ( ) ,
157- }
158- }
159- // Because the user requested a scan after the `scan_height`, the filters below this point
160- // may be assumed as checked. Note that in a reorg, filters below this height may still be
161- // retrieved, as this only considers the canonical chain as checked.
162- self . header_chain . assume_checked_to ( scan_height) ;
163- Ok ( ( ) )
164- }
165-
16689 // Sync the chain with headers from a peer, adjusting to reorgs if needed
16790 pub ( crate ) async fn sync_chain (
16891 & mut self ,
@@ -176,7 +99,6 @@ impl<H: HeaderStore> Chain<H> {
17699 // We check first if the peer is sending us nonsense
177100 self . sanity_check ( & header_batch) ?;
178101 let next_checkpoint = self . checkpoints . next ( ) . copied ( ) ;
179- let mut db = self . db . lock ( ) . await ;
180102 let mut reorged_hashes = None ;
181103 let mut fork_added = None ;
182104 for header in header_batch. into_iter ( ) {
@@ -191,7 +113,6 @@ impl<H: HeaderStore> Chain<H> {
191113 connected_at. header. block_hash( )
192114 )
193115 ) ;
194- db. stage ( BlockHeaderChanges :: Connected ( connected_at) ) ;
195116 if let Some ( checkpoint) = next_checkpoint {
196117 if connected_at. height . eq ( & checkpoint. height ) {
197118 if connected_at. header . block_hash ( ) . eq ( & checkpoint. hash ) {
@@ -238,10 +159,6 @@ impl<H: HeaderStore> Chain<H> {
238159 . map ( |index| index. header . block_hash ( ) )
239160 . collect ( ) ;
240161 reorged_hashes = Some ( removed_hashes) ;
241- db. stage ( BlockHeaderChanges :: Reorganized {
242- accepted : accepted. clone ( ) ,
243- reorganized : disconnected. clone ( ) ,
244- } ) ;
245162 let disconnected_event = Event :: BlocksDisconnected {
246163 accepted,
247164 disconnected,
@@ -260,12 +177,6 @@ impl<H: HeaderStore> Chain<H> {
260177 } ,
261178 }
262179 }
263- if let Err ( e) = db. write ( ) . await {
264- self . dialog . send_warning ( Warning :: FailedPersistence {
265- warning : format ! ( "Could not save headers to disk: {e}" ) ,
266- } ) ;
267- }
268- drop ( db) ;
269180 match reorged_hashes {
270181 Some ( reorgs) => {
271182 self . clear_compact_filter_queue ( ) ;
@@ -530,44 +441,6 @@ impl<H: HeaderStore> Chain<H> {
530441 self . scripts . insert ( script) ;
531442 }
532443
533- // Fetch a header from the cache or disk.
534- pub ( crate ) async fn fetch_header (
535- & mut self ,
536- height : u32 ,
537- ) -> Result < Option < Header > , HeaderPersistenceError < H :: Error > > {
538- match self . header_chain . header_at_height ( height) {
539- Some ( header) => Ok ( Some ( header) ) ,
540- None => {
541- let mut db = self . db . lock ( ) . await ;
542- let header_opt = db. header_at ( height) . await ;
543- if header_opt. is_err ( ) {
544- self . dialog
545- . send_warning ( Warning :: FailedPersistence {
546- warning : format ! (
547- "Unexpected error fetching a header from the header store at height {height}"
548- ) ,
549- } ) ;
550- }
551- header_opt. map_err ( HeaderPersistenceError :: Database )
552- }
553- }
554- }
555-
556- pub ( crate ) async fn fetch_header_range (
557- & self ,
558- range : Range < u32 > ,
559- ) -> Result < BTreeMap < u32 , Header > , HeaderPersistenceError < H :: Error > > {
560- let mut db = self . db . lock ( ) . await ;
561- let range_opt = db. load ( range) . await ;
562- if range_opt. is_err ( ) {
563- self . dialog . send_warning ( Warning :: FailedPersistence {
564- warning : "Unexpected error fetching a range of headers from the header store"
565- . to_string ( ) ,
566- } ) ;
567- }
568- range_opt. map_err ( HeaderPersistenceError :: Database )
569- }
570-
571444 // Reset the compact filter queue because we received a new block
572445 pub ( crate ) fn clear_compact_filter_queue ( & mut self ) {
573446 self . request_state . agreement_state . reset_agreements ( ) ;
@@ -638,7 +511,7 @@ mod tests {
638511 anchor : HeaderCheckpoint ,
639512 height_monitor : Arc < Mutex < HeightMonitor > > ,
640513 peers : u8 ,
641- ) -> Chain < ( ) > {
514+ ) -> Chain {
642515 let ( log_tx, _) = tokio:: sync:: mpsc:: channel :: < String > ( 1 ) ;
643516 let ( info_tx, _) = tokio:: sync:: mpsc:: channel :: < Info > ( 1 ) ;
644517 let ( warn_tx, _) = tokio:: sync:: mpsc:: unbounded_channel :: < Warning > ( ) ;
@@ -658,7 +531,6 @@ mod tests {
658531 event_tx,
659532 ) ) ,
660533 height_monitor,
661- ( ) ,
662534 peers,
663535 )
664536 }
0 commit comments