1+ use alloy_consensus:: BlockHeader ;
12use alloy_primitives:: { BlockHash , BlockNumber , U256 } ;
23use futures_util:: { Stream , StreamExt } ;
34use reth_db_api:: {
@@ -19,15 +20,15 @@ use reth_etl::Collector;
1920use reth_fs_util as fs;
2021use reth_primitives_traits:: { Block , FullBlockBody , FullBlockHeader , NodePrimitives } ;
2122use reth_provider:: {
22- providers:: StaticFileProviderRWRefMut , BlockWriter , ProviderError , StaticFileProviderFactory ,
23+ providers:: StaticFileProviderRWRefMut , BlockReader , BlockWriter , StaticFileProviderFactory ,
2324 StaticFileSegment , StaticFileWriter ,
2425} ;
2526use reth_stages_types:: {
2627 CheckpointBlockRange , EntitiesCheckpoint , HeadersCheckpoint , StageCheckpoint , StageId ,
2728} ;
2829use reth_storage_api:: {
29- errors:: ProviderResult , DBProvider , DatabaseProviderFactory , HeaderProvider ,
30- NodePrimitivesProvider , StageCheckpointWriter ,
30+ errors:: ProviderResult , DBProvider , DatabaseProviderFactory , NodePrimitivesProvider ,
31+ StageCheckpointWriter ,
3132} ;
3233use std:: {
3334 collections:: Bound ,
8283 . get_highest_static_file_block ( StaticFileSegment :: Headers )
8384 . unwrap_or_default ( ) ;
8485
85- // Find the latest total difficulty
86- let mut td = static_file_provider
87- . header_td_by_number ( height) ?
88- . ok_or ( ProviderError :: TotalDifficultyNotFound ( height) ) ?;
89-
9086 while let Some ( meta) = rx. recv ( ) ? {
9187 let from = height;
9288 let provider = provider_factory. database_provider_rw ( ) ?;
9692 & mut static_file_provider. latest_writer ( StaticFileSegment :: Headers ) ?,
9793 & provider,
9894 hash_collector,
99- & mut td,
10095 height..,
10196 ) ?;
10297
@@ -146,7 +141,7 @@ where
146141
147142/// Extracts block headers and bodies from `meta` and appends them using `writer` and `provider`.
148143///
149- /// Adds on to `total_difficulty` and collects hash to height using `hash_collector`.
144+ /// Collects hash to height using `hash_collector`.
150145///
151146/// Skips all blocks below the [`start_bound`] of `block_numbers` and stops when reaching past the
152147/// [`end_bound`] or the end of the file.
@@ -160,7 +155,6 @@ pub fn process<Era, P, B, BB, BH>(
160155 writer : & mut StaticFileProviderRWRefMut < ' _ , <P as NodePrimitivesProvider >:: Primitives > ,
161156 provider : & P ,
162157 hash_collector : & mut Collector < BlockHash , BlockNumber > ,
163- total_difficulty : & mut U256 ,
164158 block_numbers : impl RangeBounds < BlockNumber > ,
165159) -> eyre:: Result < BlockNumber >
166160where
@@ -182,7 +176,7 @@ where
182176 as Box < dyn Fn ( Result < BlockTuple , E2sError > ) -> eyre:: Result < ( BH , BB ) > > ) ;
183177 let iter = ProcessIter { iter, era : meta } ;
184178
185- process_iter ( iter, writer, provider, hash_collector, total_difficulty , block_numbers)
179+ process_iter ( iter, writer, provider, hash_collector, block_numbers)
186180}
187181
188182type ProcessInnerIter < R , BH , BB > =
@@ -271,7 +265,6 @@ pub fn process_iter<P, B, BB, BH>(
271265 writer : & mut StaticFileProviderRWRefMut < ' _ , <P as NodePrimitivesProvider >:: Primitives > ,
272266 provider : & P ,
273267 hash_collector : & mut Collector < BlockHash , BlockNumber > ,
274- total_difficulty : & mut U256 ,
275268 block_numbers : impl RangeBounds < BlockNumber > ,
276269) -> eyre:: Result < BlockNumber >
277270where
@@ -311,11 +304,8 @@ where
311304 let hash = header. hash_slow ( ) ;
312305 last_header_number = number;
313306
314- // Increase total difficulty
315- * total_difficulty += header. difficulty ( ) ;
316-
317307 // Append to Headers segment
318- writer. append_header ( & header, * total_difficulty , & hash) ?;
308+ writer. append_header ( & header, & hash) ?;
319309
320310 // Write bodies to database.
321311 provider. append_block_bodies ( vec ! [ ( header. number( ) , Some ( body) ) ] ) ?;
@@ -382,3 +372,28 @@ where
382372
383373 Ok ( ( ) )
384374}
375+
376+ /// Calculates the total difficulty for a given block number by summing the difficulty
377+ /// of all blocks from genesis to the given block.
378+ ///
379+ /// Very expensive - iterates through all blocks in batches of 1000.
380+ ///
381+ /// Returns an error if any block is missing.
382+ pub fn calculate_td_by_number < P > ( provider : & P , num : BlockNumber ) -> eyre:: Result < U256 >
383+ where
384+ P : BlockReader ,
385+ {
386+ let mut total_difficulty = U256 :: ZERO ;
387+ let mut start = 0 ;
388+
389+ while start <= num {
390+ let end = ( start + 1000 - 1 ) . min ( num) ;
391+
392+ total_difficulty +=
393+ provider. headers_range ( start..=end) ?. iter ( ) . map ( |h| h. difficulty ( ) ) . sum :: < U256 > ( ) ;
394+
395+ start = end + 1 ;
396+ }
397+
398+ Ok ( total_difficulty)
399+ }
0 commit comments