reth_network/session/
types.rs

1//! Shared types for network sessions.
2
3use alloy_primitives::B256;
4use parking_lot::RwLock;
5use reth_eth_wire::BlockRangeUpdate;
6use std::{
7    ops::RangeInclusive,
8    sync::{
9        atomic::{AtomicU64, Ordering},
10        Arc,
11    },
12};
13
14/// Information about the range of full blocks available from a peer.
15///
16/// This represents the announced `eth69`
17/// [`BlockRangeUpdate`] of a peer.
18#[derive(Debug, Clone)]
19pub struct BlockRangeInfo {
20    /// The inner range information.
21    inner: Arc<BlockRangeInfoInner>,
22}
23
24impl BlockRangeInfo {
25    /// Creates a new range information.
26    pub fn new(earliest: u64, latest: u64, latest_hash: B256) -> Self {
27        Self {
28            inner: Arc::new(BlockRangeInfoInner {
29                earliest: AtomicU64::new(earliest),
30                latest: AtomicU64::new(latest),
31                latest_hash: RwLock::new(latest_hash),
32            }),
33        }
34    }
35
36    /// Returns true if the block number is within the range of blocks available from the peer.
37    pub fn contains(&self, block_number: u64) -> bool {
38        self.range().contains(&block_number)
39    }
40
41    /// Returns the range of blocks available from the peer.
42    pub fn range(&self) -> RangeInclusive<u64> {
43        let earliest = self.earliest();
44        let latest = self.latest();
45        RangeInclusive::new(earliest, latest)
46    }
47
48    /// Returns the earliest full block number available from the peer.
49    pub fn earliest(&self) -> u64 {
50        self.inner.earliest.load(Ordering::Relaxed)
51    }
52
53    /// Returns the latest full block number available from the peer.
54    pub fn latest(&self) -> u64 {
55        self.inner.latest.load(Ordering::Relaxed)
56    }
57
58    /// Returns the latest block hash available from the peer.
59    pub fn latest_hash(&self) -> B256 {
60        *self.inner.latest_hash.read()
61    }
62
63    /// Returns true if the peer has the full history available.
64    pub fn has_full_history(&self) -> bool {
65        self.earliest() == 0
66    }
67
68    /// Updates the range information.
69    pub fn update(&self, earliest: u64, latest: u64, latest_hash: B256) {
70        self.inner.earliest.store(earliest, Ordering::Relaxed);
71        self.inner.latest.store(latest, Ordering::Relaxed);
72        *self.inner.latest_hash.write() = latest_hash;
73    }
74
75    /// Converts the current range information to an Eth69 [`BlockRangeUpdate`] message.
76    pub fn to_message(&self) -> BlockRangeUpdate {
77        BlockRangeUpdate {
78            earliest: self.earliest(),
79            latest: self.latest(),
80            latest_hash: self.latest_hash(),
81        }
82    }
83}
84
85/// Inner structure containing the range information with atomic and thread-safe fields.
86#[derive(Debug)]
87pub(crate) struct BlockRangeInfoInner {
88    /// The earliest block which is available.
89    earliest: AtomicU64,
90    /// The latest block which is available.
91    latest: AtomicU64,
92    /// Latest available block's hash.
93    latest_hash: RwLock<B256>,
94}