nakamoto_client/
handle.rs1use std::net;
4use std::ops::{RangeBounds, RangeInclusive};
5
6use crossbeam_channel as chan;
7use thiserror::Error;
8
9use nakamoto_common::bitcoin::network::constants::ServiceFlags;
10use nakamoto_common::bitcoin::network::Address;
11use nakamoto_common::bitcoin::Script;
12
13use nakamoto_common::bitcoin::network::message::NetworkMessage;
14use nakamoto_common::block::filter::BlockFilter;
15use nakamoto_common::block::tree::{BlockReader, ImportResult};
16use nakamoto_common::block::{self, Block, BlockHash, BlockHeader, Height, Transaction};
17use nakamoto_common::nonempty::NonEmpty;
18use nakamoto_p2p::fsm::Link;
19use nakamoto_p2p::fsm::{self, Command, CommandError, GetFiltersError, Peer};
20
21use crate::client::Event;
22
23#[derive(Error, Debug)]
25pub enum Error {
26 #[error("command channel disconnected")]
28 Disconnected,
29 #[error("command failed: {0}")]
31 Command(#[from] CommandError),
32 #[error("failed to get filters: {0}")]
34 GetFilters(#[from] GetFiltersError),
35 #[error("the operation timed out")]
37 Timeout,
38 #[error(transparent)]
40 Io(#[from] std::io::Error),
41}
42
43impl From<chan::RecvError> for Error {
44 fn from(_: chan::RecvError) -> Self {
45 Self::Disconnected
46 }
47}
48
49impl From<chan::RecvTimeoutError> for Error {
50 fn from(err: chan::RecvTimeoutError) -> Self {
51 match err {
52 chan::RecvTimeoutError::Timeout => Self::Timeout,
53 chan::RecvTimeoutError::Disconnected => Self::Disconnected,
54 }
55 }
56}
57
58impl<T> From<chan::SendError<T>> for Error {
59 fn from(_: chan::SendError<T>) -> Self {
60 Self::Disconnected
61 }
62}
63
64pub trait Handle: Sized + Send + Sync + Clone {
66 fn get_tip(&self) -> Result<(Height, BlockHeader), Error>;
68 fn get_block(&self, hash: &BlockHash) -> Result<(), Error>;
70 fn get_filters(&self, range: RangeInclusive<Height>) -> Result<(), Error>;
72 fn query_tree(
75 &self,
76 query: impl Fn(&dyn BlockReader) + Send + Sync + 'static,
77 ) -> Result<(), Error>;
78 fn find_branch(&self, to: &BlockHash)
82 -> Result<Option<(Height, NonEmpty<BlockHeader>)>, Error>;
83 fn blocks(&self) -> chan::Receiver<(Block, Height)>;
85 fn filters(&self) -> chan::Receiver<(BlockFilter, BlockHash, Height)>;
87 fn events(&self) -> chan::Receiver<Event>;
89 fn command(&self, cmd: Command) -> Result<(), Error>;
91 fn rescan(
96 &self,
97 range: impl RangeBounds<Height>,
98 watch: impl Iterator<Item = Script>,
99 ) -> Result<(), Error> {
100 let from = range.start_bound().cloned();
103 let to = range.end_bound().cloned();
104
105 self.command(Command::Rescan {
106 from,
107 to,
108 watch: watch.collect(),
109 })?;
110
111 Ok(())
112 }
113 fn watch(&self, watch: impl Iterator<Item = Script>) -> Result<(), Error> {
119 self.command(Command::Watch {
120 watch: watch.collect(),
121 })?;
122
123 Ok(())
124 }
125 fn broadcast(
128 &self,
129 msg: NetworkMessage,
130 predicate: fn(Peer) -> bool,
131 ) -> Result<Vec<net::SocketAddr>, Error>;
132 fn query(&self, msg: NetworkMessage) -> Result<Option<net::SocketAddr>, Error>;
135 fn connect(&self, addr: net::SocketAddr) -> Result<Link, Error>;
137 fn disconnect(&self, addr: net::SocketAddr) -> Result<(), Error>;
139 fn submit_transaction(&self, tx: Transaction) -> Result<NonEmpty<net::SocketAddr>, Error>;
143 fn import_headers(
146 &self,
147 headers: Vec<BlockHeader>,
148 ) -> Result<Result<ImportResult, block::tree::Error>, Error>;
149 fn import_addresses(&self, addrs: Vec<Address>) -> Result<(), Error>;
151 fn wait<F: FnMut(fsm::Event) -> Option<T>, T>(&self, f: F) -> Result<T, Error>;
153 fn wait_for_peers(
155 &self,
156 count: usize,
157 required_services: impl Into<ServiceFlags>,
158 ) -> Result<Vec<(net::SocketAddr, Height, ServiceFlags)>, Error>;
159 fn wait_for_height(&self, h: Height) -> Result<BlockHash, Error>;
162 fn shutdown(self) -> Result<(), Error>;
164}