Skip to content

Commit e210483

Browse files
authored
chore: remove total difficulty from HeaderProvider (#19151)
1 parent f0c0b3d commit e210483

File tree

28 files changed

+87
-315
lines changed

28 files changed

+87
-315
lines changed

crates/cli/commands/src/init_state/without_evm.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use alloy_consensus::BlockHeader;
2-
use alloy_primitives::{BlockNumber, B256, U256};
2+
use alloy_primitives::{BlockNumber, B256};
33
use alloy_rlp::Decodable;
44
use reth_codecs::Compact;
55
use reth_node_builder::NodePrimitives;
@@ -133,7 +133,7 @@ where
133133
for block_num in 1..=target_height {
134134
// TODO: should we fill with real parent_hash?
135135
let header = header_factory(block_num);
136-
writer.append_header(&header, U256::ZERO, &B256::ZERO)?;
136+
writer.append_header(&header, &B256::ZERO)?;
137137
}
138138
Ok(())
139139
});

crates/era-utils/src/export.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Logic to export from database era1 block history
22
//! and injecting them into era1 files with `Era1Writer`.
33
4+
use crate::calculate_td_by_number;
45
use alloy_consensus::BlockHeader;
56
use alloy_primitives::{BlockNumber, B256, U256};
67
use eyre::{eyre, Result};
@@ -114,9 +115,7 @@ where
114115

115116
let mut total_difficulty = if config.first_block_number > 0 {
116117
let prev_block_number = config.first_block_number - 1;
117-
provider
118-
.header_td_by_number(prev_block_number)?
119-
.ok_or_else(|| eyre!("Total difficulty not found for block {prev_block_number}"))?
118+
calculate_td_by_number(provider, prev_block_number)?
120119
} else {
121120
U256::ZERO
122121
};

crates/era-utils/src/history.rs

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use alloy_consensus::BlockHeader;
12
use alloy_primitives::{BlockHash, BlockNumber, U256};
23
use futures_util::{Stream, StreamExt};
34
use reth_db_api::{
@@ -19,15 +20,15 @@ use reth_etl::Collector;
1920
use reth_fs_util as fs;
2021
use reth_primitives_traits::{Block, FullBlockBody, FullBlockHeader, NodePrimitives};
2122
use reth_provider::{
22-
providers::StaticFileProviderRWRefMut, BlockWriter, ProviderError, StaticFileProviderFactory,
23+
providers::StaticFileProviderRWRefMut, BlockReader, BlockWriter, StaticFileProviderFactory,
2324
StaticFileSegment, StaticFileWriter,
2425
};
2526
use reth_stages_types::{
2627
CheckpointBlockRange, EntitiesCheckpoint, HeadersCheckpoint, StageCheckpoint, StageId,
2728
};
2829
use reth_storage_api::{
29-
errors::ProviderResult, DBProvider, DatabaseProviderFactory, HeaderProvider,
30-
NodePrimitivesProvider, StageCheckpointWriter,
30+
errors::ProviderResult, DBProvider, DatabaseProviderFactory, NodePrimitivesProvider,
31+
StageCheckpointWriter,
3132
};
3233
use std::{
3334
collections::Bound,
@@ -82,11 +83,6 @@ where
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()?;
@@ -96,7 +92,6 @@ where
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>
166160
where
@@ -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

188182
type 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>
277270
where
@@ -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+
}

crates/era-utils/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ pub use export::{export, ExportConfig};
1414

1515
/// Imports history from ERA files.
1616
pub use history::{
17-
build_index, decode, import, open, process, process_iter, save_stage_checkpoints, ProcessIter,
17+
build_index, calculate_td_by_number, decode, import, open, process, process_iter,
18+
save_stage_checkpoints, ProcessIter,
1819
};

crates/net/downloaders/src/bodies/test_utils.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#![allow(dead_code)]
44

55
use alloy_consensus::BlockHeader;
6-
use alloy_primitives::{B256, U256};
6+
use alloy_primitives::B256;
77
use reth_ethereum_primitives::BlockBody;
88
use reth_network_p2p::bodies::response::BlockResponse;
99
use reth_primitives_traits::{Block, SealedBlock, SealedHeader};
@@ -55,9 +55,7 @@ pub(crate) fn insert_headers(
5555
.expect("failed to create writer");
5656

5757
for header in headers {
58-
writer
59-
.append_header(header.header(), U256::ZERO, &header.hash())
60-
.expect("failed to append header");
58+
writer.append_header(header.header(), &header.hash()).expect("failed to append header");
6159
}
6260
drop(writer);
6361
provider_rw.commit().expect("failed to commit");

crates/node/core/src/node_config.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
};
1111
use alloy_consensus::BlockHeader;
1212
use alloy_eips::BlockHashOrNumber;
13-
use alloy_primitives::{BlockNumber, B256};
13+
use alloy_primitives::{BlockNumber, B256, U256};
1414
use eyre::eyre;
1515
use reth_chainspec::{ChainSpec, EthChainSpec, MAINNET};
1616
use reth_config::config::PruneConfig;
@@ -346,12 +346,6 @@ impl<ChainSpec> NodeConfig<ChainSpec> {
346346
.header_by_number(head)?
347347
.expect("the header for the latest block is missing, database is corrupt");
348348

349-
let total_difficulty = provider
350-
.header_td_by_number(head)?
351-
// total difficulty is effectively deprecated, but still required in some places, e.g.
352-
// p2p
353-
.unwrap_or_default();
354-
355349
let hash = provider
356350
.block_hash(head)?
357351
.expect("the hash for the latest block is missing, database is corrupt");
@@ -360,7 +354,7 @@ impl<ChainSpec> NodeConfig<ChainSpec> {
360354
number: head,
361355
hash,
362356
difficulty: header.difficulty(),
363-
total_difficulty,
357+
total_difficulty: U256::ZERO,
364358
timestamp: header.timestamp(),
365359
})
366360
}

crates/rpc/rpc-eth-types/src/error/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,6 @@ impl From<reth_errors::ProviderError> for EthApiError {
462462
}
463463
ProviderError::BestBlockNotFound => Self::HeaderNotFound(BlockId::latest()),
464464
ProviderError::BlockNumberForTransactionIndexNotFound => Self::UnknownBlockOrTxIndex,
465-
ProviderError::TotalDifficultyNotFound(num) => Self::HeaderNotFound(num.into()),
466465
ProviderError::FinalizedBlockNotFound => Self::HeaderNotFound(BlockId::finalized()),
467466
ProviderError::SafeBlockNotFound => Self::HeaderNotFound(BlockId::safe()),
468467
err => Self::Internal(err.into()),

crates/stages/stages/src/stages/era.rs

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,11 @@ use reth_era_utils as era;
1010
use reth_etl::Collector;
1111
use reth_primitives_traits::{FullBlockBody, FullBlockHeader, NodePrimitives};
1212
use reth_provider::{
13-
BlockReader, BlockWriter, DBProvider, HeaderProvider, StageCheckpointWriter,
14-
StaticFileProviderFactory, StaticFileWriter,
13+
BlockReader, BlockWriter, DBProvider, StageCheckpointWriter, StaticFileProviderFactory,
14+
StaticFileWriter,
1515
};
1616
use reth_stages_api::{ExecInput, ExecOutput, Stage, StageError, UnwindInput, UnwindOutput};
1717
use reth_static_file_types::StaticFileSegment;
18-
use reth_storage_errors::ProviderError;
1918
use std::{
2019
fmt::{Debug, Formatter},
2120
iter,
@@ -176,11 +175,6 @@ where
176175
.get_highest_static_file_block(StaticFileSegment::Headers)
177176
.unwrap_or_default();
178177

179-
// Find the latest total difficulty
180-
let mut td = static_file_provider
181-
.header_td_by_number(last_header_number)?
182-
.ok_or(ProviderError::TotalDifficultyNotFound(last_header_number))?;
183-
184178
// Although headers were downloaded in reverse order, the collector iterates it in
185179
// ascending order
186180
let mut writer = static_file_provider.latest_writer(StaticFileSegment::Headers)?;
@@ -190,7 +184,6 @@ where
190184
&mut writer,
191185
provider,
192186
&mut self.hash_collector,
193-
&mut td,
194187
last_header_number..=input.target(),
195188
)
196189
.map_err(|e| StageError::Fatal(e.into()))?;
@@ -336,7 +329,7 @@ mod tests {
336329
};
337330
use reth_ethereum_primitives::TransactionSigned;
338331
use reth_primitives_traits::{SealedBlock, SealedHeader};
339-
use reth_provider::{BlockNumReader, TransactionsProvider};
332+
use reth_provider::{BlockNumReader, HeaderProvider, TransactionsProvider};
340333
use reth_testing_utils::generators::{
341334
random_block_range, random_signed_tx, BlockRangeParams,
342335
};
@@ -447,9 +440,6 @@ mod tests {
447440
match output {
448441
Some(output) if output.checkpoint.block_number > initial_checkpoint => {
449442
let provider = self.db.factory.provider()?;
450-
let mut td = provider
451-
.header_td_by_number(initial_checkpoint.saturating_sub(1))?
452-
.unwrap_or_default();
453443

454444
for block_num in initial_checkpoint..
455445
output
@@ -469,10 +459,6 @@ mod tests {
469459
assert!(header.is_some());
470460
let header = SealedHeader::seal_slow(header.unwrap());
471461
assert_eq!(header.hash(), hash);
472-
473-
// validate the header total difficulty
474-
td += header.difficulty;
475-
assert_eq!(provider.header_td_by_number(block_num)?, Some(td));
476462
}
477463

478464
self.validate_db_blocks(

crates/stages/stages/src/stages/headers.rs

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,14 @@ use reth_network_p2p::headers::{
1616
};
1717
use reth_primitives_traits::{serde_bincode_compat, FullBlockHeader, NodePrimitives, SealedHeader};
1818
use reth_provider::{
19-
providers::StaticFileWriter, BlockHashReader, DBProvider, HeaderProvider,
20-
HeaderSyncGapProvider, StaticFileProviderFactory,
19+
providers::StaticFileWriter, BlockHashReader, DBProvider, HeaderSyncGapProvider,
20+
StaticFileProviderFactory,
2121
};
2222
use reth_stages_api::{
2323
CheckpointBlockRange, EntitiesCheckpoint, ExecInput, ExecOutput, HeadersCheckpoint, Stage,
2424
StageCheckpoint, StageError, StageId, UnwindInput, UnwindOutput,
2525
};
2626
use reth_static_file_types::StaticFileSegment;
27-
use reth_storage_errors::provider::ProviderError;
2827
use std::task::{ready, Context, Poll};
2928

3029
use tokio::sync::watch;
@@ -107,11 +106,6 @@ where
107106
.get_highest_static_file_block(StaticFileSegment::Headers)
108107
.unwrap_or_default();
109108

110-
// Find the latest total difficulty
111-
let mut td = static_file_provider
112-
.header_td_by_number(last_header_number)?
113-
.ok_or(ProviderError::TotalDifficultyNotFound(last_header_number))?;
114-
115109
// Although headers were downloaded in reverse order, the collector iterates it in ascending
116110
// order
117111
let mut writer = static_file_provider.latest_writer(StaticFileSegment::Headers)?;
@@ -134,11 +128,8 @@ where
134128
}
135129
last_header_number = header.number();
136130

137-
// Increase total difficulty
138-
td += header.difficulty();
139-
140131
// Append to Headers segment
141-
writer.append_header(header, td, header_hash)?;
132+
writer.append_header(header, header_hash)?;
142133
}
143134

144135
info!(target: "sync::stages::headers", total = total_headers, "Writing headers hash index");
@@ -415,7 +406,7 @@ mod tests {
415406
ReverseHeadersDownloader, ReverseHeadersDownloaderBuilder,
416407
};
417408
use reth_network_p2p::test_utils::{TestHeaderDownloader, TestHeadersClient};
418-
use reth_provider::{test_utils::MockNodeTypesWithDB, BlockNumReader};
409+
use reth_provider::{test_utils::MockNodeTypesWithDB, BlockNumReader, HeaderProvider};
419410
use tokio::sync::watch;
420411

421412
pub(crate) struct HeadersTestRunner<D: HeaderDownloader> {
@@ -493,9 +484,6 @@ mod tests {
493484
match output {
494485
Some(output) if output.checkpoint.block_number > initial_checkpoint => {
495486
let provider = self.db.factory.provider()?;
496-
let mut td = provider
497-
.header_td_by_number(initial_checkpoint.saturating_sub(1))?
498-
.unwrap_or_default();
499487

500488
for block_num in initial_checkpoint..output.checkpoint.block_number {
501489
// look up the header hash
@@ -509,10 +497,6 @@ mod tests {
509497
assert!(header.is_some());
510498
let header = SealedHeader::seal_slow(header.unwrap());
511499
assert_eq!(header.hash(), hash);
512-
513-
// validate the header total difficulty
514-
td += header.difficulty;
515-
assert_eq!(provider.header_td_by_number(block_num)?, Some(td));
516500
}
517501
}
518502
_ => self.check_no_header_entry_above(initial_checkpoint)?,
@@ -635,16 +619,7 @@ mod tests {
635619
let static_file_provider = provider.static_file_provider();
636620
let mut writer = static_file_provider.latest_writer(StaticFileSegment::Headers).unwrap();
637621
for header in sealed_headers {
638-
let ttd = if header.number() == 0 {
639-
header.difficulty()
640-
} else {
641-
let parent_block_number = header.number() - 1;
642-
let parent_ttd =
643-
provider.header_td_by_number(parent_block_number).unwrap().unwrap_or_default();
644-
parent_ttd + header.difficulty()
645-
};
646-
647-
writer.append_header(header.header(), ttd, &header.hash()).unwrap();
622+
writer.append_header(header.header(), &header.hash()).unwrap();
648623
}
649624
drop(writer);
650625

crates/stages/stages/src/stages/merkle.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,7 @@ mod tests {
738738
let hash = last_header.hash_slow();
739739
writer.prune_headers(1).unwrap();
740740
writer.commit().unwrap();
741-
writer.append_header(&last_header, U256::ZERO, &hash).unwrap();
741+
writer.append_header(&last_header, &hash).unwrap();
742742
writer.commit().unwrap();
743743

744744
Ok(blocks)

0 commit comments

Comments
 (0)