1use alloy_consensus::{BlockHeader, Header};
2use alloy_eips::BlockHashOrNumber;
3use alloy_primitives::{BlockNumber, Sealable, B256};
4use reth_network_p2p::headers::downloader::SyncTarget;
5use reth_primitives::SealedHeader;
6use reth_storage_errors::provider::ProviderResult;
7use tokio::sync::watch;
89/// Represents a gap to sync: from `local_head` to `target`
10#[derive(Clone, Debug)]
11pub struct HeaderSyncGap<H = Header> {
12/// The local head block. Represents lower bound of sync range.
13pub local_head: SealedHeader<H>,
1415/// The sync target. Represents upper bound of sync range.
16pub target: SyncTarget,
17}
1819impl<H: BlockHeader + Sealable> HeaderSyncGap<H> {
20/// Returns `true` if the gap from the head to the target was closed
21#[inline]
22pub fn is_closed(&self) -> bool {
23match self.target.tip() {
24 BlockHashOrNumber::Hash(hash) => self.local_head.hash() == hash,
25 BlockHashOrNumber::Number(num) => self.local_head.number() == num,
26 }
27 }
28}
2930/// Client trait for determining the current headers sync gap.
31#[auto_impl::auto_impl(&, Arc)]
32pub trait HeaderSyncGapProvider: Send + Sync {
33/// The header type.
34type Header: Send + Sync;
3536/// Find a current sync gap for the headers depending on the last
37 /// uninterrupted block number. Last uninterrupted block represents the block number before
38 /// which there are no gaps. It's up to the caller to ensure that last uninterrupted block is
39 /// determined correctly.
40fn sync_gap(
41&self,
42 tip: watch::Receiver<B256>,
43 highest_uninterrupted_block: BlockNumber,
44 ) -> ProviderResult<HeaderSyncGap<Self::Header>>;
45}