diff --git a/src/lib.rs b/src/lib.rs index 40760bc4..1046a91b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -146,7 +146,7 @@ pub use { crate::error::{ClientError, NodeError}, crate::messages::{Event, Log, Progress, RejectPayload, SyncUpdate, Warning}, crate::network::PeerTimeoutConfig, - crate::node::{Node, NodeState}, + crate::node::Node, }; #[doc(inline)] @@ -468,6 +468,39 @@ pub enum FilterSyncPolicy { Continue, } +/// The state of the node with respect to connected peers. +#[derive(Debug, Clone, Copy)] +pub enum NodeState { + /// We are behind on block headers according to our peers. + Behind, + /// We may start downloading compact block filter headers. + HeadersSynced, + /// We may start scanning compact block filters. + FilterHeadersSynced, + /// We may start asking for blocks with matches. + FiltersSynced, + /// We found all known transactions to the wallet. + TransactionsSynced, +} + +impl core::fmt::Display for NodeState { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + NodeState::Behind => { + write!(f, "Requesting block headers.") + } + NodeState::HeadersSynced => { + write!(f, "Requesting compact filter headers.") + } + NodeState::FilterHeadersSynced => { + write!(f, "Requesting compact block filters.") + } + NodeState::FiltersSynced => write!(f, "Downloading blocks with relevant transactions."), + NodeState::TransactionsSynced => write!(f, "Fully synced to the highest block."), + } + } +} + macro_rules! log { ($dialog:expr, $expr:expr) => { match $dialog.log_level { diff --git a/src/messages.rs b/src/messages.rs index 63205dc0..8e631d3a 100644 --- a/src/messages.rs +++ b/src/messages.rs @@ -7,14 +7,11 @@ use bitcoin::{block::Header, p2p::message_network::RejectReason, FeeRate, Script #[cfg(feature = "filter-control")] use crate::IndexedFilter; use crate::{ - chain::checkpoints::HeaderCheckpoint, DisconnectedHeader, IndexedBlock, TrustedPeer, + chain::checkpoints::HeaderCheckpoint, DisconnectedHeader, IndexedBlock, NodeState, TrustedPeer, TxBroadcast, }; -use super::{ - error::{FetchBlockError, FetchHeaderError}, - node::NodeState, -}; +use super::error::{FetchBlockError, FetchHeaderError}; /// Informational messages emitted by a node #[derive(Debug, Clone)] diff --git a/src/network/mod.rs b/src/network/mod.rs index 710c32fd..60e3ebb1 100644 --- a/src/network/mod.rs +++ b/src/network/mod.rs @@ -4,6 +4,7 @@ use bitcoin::{ p2p::{message::CommandString, Magic}, }; use std::time::Duration; +use tokio::time::Instant; pub(crate) mod counter; pub(crate) mod dns; @@ -19,6 +20,11 @@ pub(crate) mod reader; pub(crate) mod tor; pub(crate) mod traits; +pub const PROTOCOL_VERSION: u32 = 70016; +pub const KYOTO_VERSION: &str = "0.8.0"; +pub const RUST_BITCOIN_VERSION: &str = "0.32.4"; +const THIRTY_MINS: u64 = 60 * 30; + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub(crate) struct PeerId(pub(crate) u32); @@ -59,9 +65,26 @@ impl PeerTimeoutConfig { } } -pub const PROTOCOL_VERSION: u32 = 70016; -pub const KYOTO_VERSION: &str = "0.8.0"; -pub const RUST_BITCOIN_VERSION: &str = "0.32.4"; +pub(crate) struct LastBlockMonitor { + last_block: Option, +} + +impl LastBlockMonitor { + pub(crate) fn new() -> Self { + Self { last_block: None } + } + + pub(crate) fn reset(&mut self) { + self.last_block = Some(Instant::now()) + } + + pub(crate) fn stale(&self) -> bool { + if let Some(time) = self.last_block { + return Instant::now().duration_since(time) > Duration::from_secs(THIRTY_MINS); + } + false + } +} pub(crate) struct V1Header { magic: Magic, diff --git a/src/node.rs b/src/node.rs index 42aa77db..91e8d4fc 100644 --- a/src/node.rs +++ b/src/node.rs @@ -9,14 +9,11 @@ use bitcoin::{ }, Block, BlockHash, Network, ScriptBuf, }; +use tokio::sync::{mpsc::Receiver, Mutex, RwLock}; use tokio::{ select, sync::mpsc::{self}, }; -use tokio::{ - sync::{mpsc::Receiver, Mutex, RwLock}, - time::Instant, -}; use crate::{ chain::{ @@ -28,8 +25,8 @@ use crate::{ db::traits::{HeaderStore, PeerStore}, error::FetchHeaderError, filters::{cfheader_chain::AppendAttempt, error::CFilterSyncError}, - network::{peer_map::PeerMap, PeerId, PeerTimeoutConfig}, - FilterSyncPolicy, RejectPayload, TxBroadcastPolicy, + network::{peer_map::PeerMap, LastBlockMonitor, PeerId, PeerTimeoutConfig}, + FilterSyncPolicy, NodeState, RejectPayload, TxBroadcastPolicy, }; use super::{ @@ -47,47 +44,9 @@ use super::{ pub(crate) const WTXID_VERSION: u32 = 70016; const LOOP_TIMEOUT: u64 = 1; -const THIRTY_MINS: u64 = 60 * 30; type PeerRequirement = usize; -// This struct detects for stale tips and requests headers if no blocks were found after 30 minutes of wait time. -pub(crate) struct LastBlockMonitor { - last_block: Option, -} - -impl LastBlockMonitor { - pub(crate) fn new() -> Self { - Self { last_block: None } - } - - pub(crate) fn reset(&mut self) { - self.last_block = Some(Instant::now()) - } - - pub(crate) fn stale(&self) -> bool { - if let Some(time) = self.last_block { - return Instant::now().duration_since(time) > Duration::from_secs(THIRTY_MINS); - } - false - } -} - -/// The state of the node with respect to connected peers. -#[derive(Debug, Clone, Copy)] -pub enum NodeState { - /// We are behind on block headers according to our peers. - Behind, - /// We may start downloading compact block filter headers. - HeadersSynced, - /// We may start scanning compact block filters. - FilterHeadersSynced, - /// We may start asking for blocks with matches. - FiltersSynced, - /// We found all known transactions to the wallet. - TransactionsSynced, -} - /// A compact block filter node. Nodes download Bitcoin block headers, block filters, and blocks to send relevant events to a client. #[derive(Debug)] pub struct Node { @@ -801,21 +760,3 @@ impl Node { .map_err(NodeError::HeaderDatabase) } } - -impl core::fmt::Display for NodeState { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - NodeState::Behind => { - write!(f, "Requesting block headers.") - } - NodeState::HeadersSynced => { - write!(f, "Requesting compact filter headers.") - } - NodeState::FilterHeadersSynced => { - write!(f, "Requesting compact block filters.") - } - NodeState::FiltersSynced => write!(f, "Downloading blocks with relevant transactions."), - NodeState::TransactionsSynced => write!(f, "Fully synced to the highest block."), - } - } -}