Skip to content

Commit dd1489d

Browse files
committed
Add lightning-block-sync package and library
Defines an interface and related types for fetching block headers and data from a block source (e.g., Bitcoin Core). Used to keep lightning in sync with chain activity.
1 parent 9c9c881 commit dd1489d

File tree

4 files changed

+94
-1
lines changed

4 files changed

+94
-1
lines changed

.github/workflows/build.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
1.30.0,
1414
# 1.34.2 is Debian stable
1515
1.34.2,
16-
# 1.39.0 is MSRV for lightning-net-tokio and generates coverage
16+
# 1.39.0 is MSRV for lightning-net-tokio and lightning-block-sync and generates coverage
1717
1.39.0]
1818
include:
1919
- toolchain: stable
@@ -48,6 +48,15 @@ jobs:
4848
- name: Build on Rust ${{ matrix.toolchain }}
4949
if: "! matrix.build-net-tokio"
5050
run: cargo build --verbose --color always -p lightning
51+
- name: Build Block Sync Clients on Rust ${{ matrix.toolchain }} with features
52+
if: matrix.build-net-tokio
53+
run: |
54+
cd lightning-block-sync
55+
RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always --features rest-client
56+
RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always --features rpc-client
57+
RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always --features rpc-client,rest-client
58+
RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always --features rpc-client,rest-client,tokio
59+
cd ..
5160
- name: Test on Rust ${{ matrix.toolchain }} with net-tokio
5261
if: "matrix.build-net-tokio && !matrix.coverage"
5362
run: cargo test --verbose --color always

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
members = [
44
"lightning",
5+
"lightning-block-sync",
56
"lightning-net-tokio",
67
"lightning-persister",
78
]

lightning-block-sync/Cargo.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "lightning-block-sync"
3+
version = "0.0.1"
4+
authors = ["Jeffrey Czyz", "Matt Corallo"]
5+
license = "Apache-2.0"
6+
edition = "2018"
7+
description = """
8+
Utilities to fetch the chain data from a block source and feed them into Rust Lightning.
9+
"""
10+
11+
[dependencies]
12+
bitcoin = "0.24"
13+
lightning = { version = "0.0.12", path = "../lightning" }

lightning-block-sync/src/lib.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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 source cannot
18+
/// easily find headers based on a hash. This is merely a hint and thus the returned header must
19+
/// 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`. In such a case, `get_best_block` should never return `None`
23+
/// for the height. Otherwise, the source could not be used independently for an initial sync.
24+
fn get_header<'a>(&'a mut self, header_hash: &'a BlockHash, height_hint: Option<u32>) -> AsyncBlockSourceResult<'a, BlockHeaderData>;
25+
26+
/// Returns the block for a given hash. A headers-only block source should return a `Transient`
27+
/// error.
28+
fn get_block<'a>(&'a mut self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, Block>;
29+
30+
/// Returns the hash of the best block and, optionally, its height. The height is passed to
31+
/// `get_header` to allow a more efficient lookup on some block sources.
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+
/// Result type for asynchronous `BlockSource` requests.
39+
///
40+
/// TODO: Replace with BlockSourceResult once `async` trait functions are supported. For details,
41+
/// see: https://areweasyncyet.rs.
42+
type AsyncBlockSourceResult<'a, T> = Pin<Box<dyn Future<Output = BlockSourceResult<T>> + 'a + Send>>;
43+
44+
/// Error type for `BlockSource` requests.
45+
///
46+
/// Transient errors may be resolved when re-polling, but no attempt will be made to re-poll on
47+
/// persistent errors.
48+
#[derive(Clone, Copy, Debug, PartialEq)]
49+
pub enum BlockSourceError {
50+
/// Indicates an error that won't resolve when retrying a request (e.g., invalid data).
51+
Persistent,
52+
53+
/// Indicates an error that may resolve when retrying a request (e.g., unresponsive).
54+
Transient,
55+
}
56+
57+
/// A block header and some associated data. This information should be available from most block
58+
/// sources (and, notably, is available in Bitcoin Core's RPC and REST interfaces).
59+
#[derive(Clone, Copy, Debug, PartialEq)]
60+
pub struct BlockHeaderData {
61+
/// The block header itself.
62+
pub header: BlockHeader,
63+
64+
/// The block height where the genesis block has height 0.
65+
pub height: u32,
66+
67+
/// The total chain work in expected number of double-SHA256 hashes required to build a chain
68+
/// of equivalent weight.
69+
pub chainwork: Uint256,
70+
}

0 commit comments

Comments
 (0)