b2315e907d25d6411c908950a13f6dabfb76a5e6
[rust-lightning] / lightning-block-sync / src / lib.rs
1 //! A lightweight client for keeping in sync with chain activity.
2 //!
3 //! Defines a [`BlockSource`] trait, which is an asynchronous interface for retrieving block headers
4 //! and data.
5 //!
6 //! [`BlockSource`]: trait.BlockSource.html
7
8 use bitcoin::blockdata::block::{Block, BlockHeader};
9 use bitcoin::hash_types::BlockHash;
10 use bitcoin::util::uint::Uint256;
11
12 use std::future::Future;
13 use std::pin::Pin;
14
15 /// Abstract type for retrieving block headers and data.
16 pub trait BlockSource : Sync + Send {
17         /// Returns the header for a given hash. A height hint may be provided in case a block source
18         /// cannot easily find headers based on a hash. This is merely a hint and thus the returned
19         /// header must have the same hash as was requested. Otherwise, an error must be returned.
20         ///
21         /// Implementations that cannot find headers based on the hash should return a `Transient` error
22         /// when `height_hint` is `None`.
23         fn get_header<'a>(&'a mut self, header_hash: &'a BlockHash, height_hint: Option<u32>) -> AsyncBlockSourceResult<'a, BlockHeaderData>;
24
25         /// Returns the block for a given hash. A headers-only block source should return a `Transient`
26         /// error.
27         fn get_block<'a>(&'a mut self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, Block>;
28
29         // TODO: Phrase in terms of `Poll` once added.
30         /// Returns the hash of the best block and, optionally, its height. When polling a block source,
31         /// the height is passed to `get_header` to allow for a more efficient lookup.
32         fn get_best_block<'a>(&'a mut self) -> AsyncBlockSourceResult<(BlockHash, Option<u32>)>;
33 }
34
35 /// Result type for `BlockSource` requests.
36 type BlockSourceResult<T> = Result<T, BlockSourceError>;
37
38 // TODO: Replace with BlockSourceResult once `async` trait functions are supported. For details,
39 // see: https://areweasyncyet.rs.
40 /// Result type for asynchronous `BlockSource` requests.
41 type AsyncBlockSourceResult<'a, T> = Pin<Box<dyn Future<Output = BlockSourceResult<T>> + 'a + Send>>;
42
43 /// Error type for `BlockSource` requests.
44 ///
45 /// Transient errors may be resolved when re-polling, but no attempt will be made to re-poll on
46 /// persistent errors.
47 pub struct BlockSourceError {
48         kind: BlockSourceErrorKind,
49         error: Box<dyn std::error::Error + Send + Sync>,
50 }
51
52 /// The kind of `BlockSourceError`, either persistent or transient.
53 #[derive(Clone, Copy)]
54 pub enum BlockSourceErrorKind {
55         /// Indicates an error that won't resolve when retrying a request (e.g., invalid data).
56         Persistent,
57
58         /// Indicates an error that may resolve when retrying a request (e.g., unresponsive).
59         Transient,
60 }
61
62 impl BlockSourceError {
63         /// Creates a new persistent error originated from the given error.
64         pub fn persistent<E>(error: E) -> Self
65         where E: Into<Box<dyn std::error::Error + Send + Sync>> {
66                 Self {
67                         kind: BlockSourceErrorKind::Persistent,
68                         error: error.into(),
69                 }
70         }
71
72         /// Creates a new transient error originated from the given error.
73         pub fn transient<E>(error: E) -> Self
74         where E: Into<Box<dyn std::error::Error + Send + Sync>> {
75                 Self {
76                         kind: BlockSourceErrorKind::Transient,
77                         error: error.into(),
78                 }
79         }
80
81         /// Returns the kind of error.
82         pub fn kind(&self) -> BlockSourceErrorKind {
83                 self.kind
84         }
85
86         /// Converts the error into the underlying error.
87         pub fn into_inner(self) -> Box<dyn std::error::Error + Send + Sync> {
88                 self.error
89         }
90 }
91
92 /// A block header and some associated data. This information should be available from most block
93 /// sources (and, notably, is available in Bitcoin Core's RPC and REST interfaces).
94 #[derive(Clone, Copy, Debug, PartialEq)]
95 pub struct BlockHeaderData {
96         /// The block header itself.
97         pub header: BlockHeader,
98
99         /// The block height where the genesis block has height 0.
100         pub height: u32,
101
102         /// The total chain work in expected number of double-SHA256 hashes required to build a chain
103         /// of equivalent weight.
104         pub chainwork: Uint256,
105 }