mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-01-19 05:43:55 +01:00
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.
This commit is contained in:
parent
e4b516dd8a
commit
9860646e73
38
.github/workflows/build.yml
vendored
38
.github/workflows/build.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
||||
1.30.0,
|
||||
# 1.34.2 is Debian stable
|
||||
1.34.2,
|
||||
# 1.45.2 is MSRV for lightning-net-tokio and generates coverage
|
||||
# 1.45.2 is MSRV for lightning-net-tokio, lightning-block-sync, and coverage generation
|
||||
1.45.2]
|
||||
include:
|
||||
- toolchain: stable
|
||||
@ -48,6 +48,24 @@ jobs:
|
||||
- name: Build on Rust ${{ matrix.toolchain }}
|
||||
if: "! matrix.build-net-tokio"
|
||||
run: cargo build --verbose --color always -p lightning
|
||||
- name: Build Block Sync Clients on Rust ${{ matrix.toolchain }} with features
|
||||
if: "matrix.build-net-tokio && !matrix.coverage"
|
||||
run: |
|
||||
cd lightning-block-sync
|
||||
cargo build --verbose --color always --features rest-client
|
||||
cargo build --verbose --color always --features rpc-client
|
||||
cargo build --verbose --color always --features rpc-client,rest-client
|
||||
cargo build --verbose --color always --features rpc-client,rest-client,tokio
|
||||
cd ..
|
||||
- name: Build Block Sync Clients on Rust ${{ matrix.toolchain }} with features and full code-linking for coverage generation
|
||||
if: matrix.coverage
|
||||
run: |
|
||||
cd lightning-block-sync
|
||||
RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always --features rest-client
|
||||
RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always --features rpc-client
|
||||
RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always --features rpc-client,rest-client
|
||||
RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always --features rpc-client,rest-client,tokio
|
||||
cd ..
|
||||
- name: Test on Rust ${{ matrix.toolchain }} with net-tokio
|
||||
if: "matrix.build-net-tokio && !matrix.coverage"
|
||||
run: cargo test --verbose --color always
|
||||
@ -57,6 +75,24 @@ jobs:
|
||||
- name: Test on Rust ${{ matrix.toolchain }}
|
||||
if: "! matrix.build-net-tokio"
|
||||
run: cargo test --verbose --color always -p lightning
|
||||
- name: Test Block Sync Clients on Rust ${{ matrix.toolchain }} with features
|
||||
if: "matrix.build-net-tokio && !matrix.coverage"
|
||||
run: |
|
||||
cd lightning-block-sync
|
||||
cargo test --verbose --color always --features rest-client
|
||||
cargo test --verbose --color always --features rpc-client
|
||||
cargo test --verbose --color always --features rpc-client,rest-client
|
||||
cargo test --verbose --color always --features rpc-client,rest-client,tokio
|
||||
cd ..
|
||||
- name: Test Block Sync Clients on Rust ${{ matrix.toolchain }} with features and full code-linking for coverage generation
|
||||
if: matrix.coverage
|
||||
run: |
|
||||
cd lightning-block-sync
|
||||
RUSTFLAGS="-C link-dead-code" cargo test --verbose --color always --features rest-client
|
||||
RUSTFLAGS="-C link-dead-code" cargo test --verbose --color always --features rpc-client
|
||||
RUSTFLAGS="-C link-dead-code" cargo test --verbose --color always --features rpc-client,rest-client
|
||||
RUSTFLAGS="-C link-dead-code" cargo test --verbose --color always --features rpc-client,rest-client,tokio
|
||||
cd ..
|
||||
- name: Install deps for kcov
|
||||
if: matrix.coverage
|
||||
run: |
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
members = [
|
||||
"lightning",
|
||||
"lightning-block-sync",
|
||||
"lightning-net-tokio",
|
||||
"lightning-persister",
|
||||
]
|
||||
|
13
lightning-block-sync/Cargo.toml
Normal file
13
lightning-block-sync/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "lightning-block-sync"
|
||||
version = "0.0.1"
|
||||
authors = ["Jeffrey Czyz", "Matt Corallo"]
|
||||
license = "Apache-2.0"
|
||||
edition = "2018"
|
||||
description = """
|
||||
Utilities to fetch the chain data from a block source and feed them into Rust Lightning.
|
||||
"""
|
||||
|
||||
[dependencies]
|
||||
bitcoin = "0.24"
|
||||
lightning = { version = "0.0.12", path = "../lightning" }
|
105
lightning-block-sync/src/lib.rs
Normal file
105
lightning-block-sync/src/lib.rs
Normal file
@ -0,0 +1,105 @@
|
||||
//! A lightweight client for keeping in sync with chain activity.
|
||||
//!
|
||||
//! Defines a [`BlockSource`] trait, which is an asynchronous interface for retrieving block headers
|
||||
//! and data.
|
||||
//!
|
||||
//! [`BlockSource`]: trait.BlockSource.html
|
||||
|
||||
use bitcoin::blockdata::block::{Block, BlockHeader};
|
||||
use bitcoin::hash_types::BlockHash;
|
||||
use bitcoin::util::uint::Uint256;
|
||||
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Abstract type for retrieving block headers and data.
|
||||
pub trait BlockSource : Sync + Send {
|
||||
/// Returns the header for a given hash. A height hint may be provided in case a block source
|
||||
/// cannot easily find headers based on a hash. This is merely a hint and thus the returned
|
||||
/// header must have the same hash as was requested. Otherwise, an error must be returned.
|
||||
///
|
||||
/// Implementations that cannot find headers based on the hash should return a `Transient` error
|
||||
/// when `height_hint` is `None`.
|
||||
fn get_header<'a>(&'a mut self, header_hash: &'a BlockHash, height_hint: Option<u32>) -> AsyncBlockSourceResult<'a, BlockHeaderData>;
|
||||
|
||||
/// Returns the block for a given hash. A headers-only block source should return a `Transient`
|
||||
/// error.
|
||||
fn get_block<'a>(&'a mut self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, Block>;
|
||||
|
||||
// TODO: Phrase in terms of `Poll` once added.
|
||||
/// Returns the hash of the best block and, optionally, its height. When polling a block source,
|
||||
/// the height is passed to `get_header` to allow for a more efficient lookup.
|
||||
fn get_best_block<'a>(&'a mut self) -> AsyncBlockSourceResult<(BlockHash, Option<u32>)>;
|
||||
}
|
||||
|
||||
/// Result type for `BlockSource` requests.
|
||||
type BlockSourceResult<T> = Result<T, BlockSourceError>;
|
||||
|
||||
// TODO: Replace with BlockSourceResult once `async` trait functions are supported. For details,
|
||||
// see: https://areweasyncyet.rs.
|
||||
/// Result type for asynchronous `BlockSource` requests.
|
||||
type AsyncBlockSourceResult<'a, T> = Pin<Box<dyn Future<Output = BlockSourceResult<T>> + 'a + Send>>;
|
||||
|
||||
/// Error type for `BlockSource` requests.
|
||||
///
|
||||
/// Transient errors may be resolved when re-polling, but no attempt will be made to re-poll on
|
||||
/// persistent errors.
|
||||
pub struct BlockSourceError {
|
||||
kind: BlockSourceErrorKind,
|
||||
error: Box<dyn std::error::Error + Send + Sync>,
|
||||
}
|
||||
|
||||
/// The kind of `BlockSourceError`, either persistent or transient.
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum BlockSourceErrorKind {
|
||||
/// Indicates an error that won't resolve when retrying a request (e.g., invalid data).
|
||||
Persistent,
|
||||
|
||||
/// Indicates an error that may resolve when retrying a request (e.g., unresponsive).
|
||||
Transient,
|
||||
}
|
||||
|
||||
impl BlockSourceError {
|
||||
/// Creates a new persistent error originated from the given error.
|
||||
pub fn persistent<E>(error: E) -> Self
|
||||
where E: Into<Box<dyn std::error::Error + Send + Sync>> {
|
||||
Self {
|
||||
kind: BlockSourceErrorKind::Persistent,
|
||||
error: error.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new transient error originated from the given error.
|
||||
pub fn transient<E>(error: E) -> Self
|
||||
where E: Into<Box<dyn std::error::Error + Send + Sync>> {
|
||||
Self {
|
||||
kind: BlockSourceErrorKind::Transient,
|
||||
error: error.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the kind of error.
|
||||
pub fn kind(&self) -> BlockSourceErrorKind {
|
||||
self.kind
|
||||
}
|
||||
|
||||
/// Converts the error into the underlying error.
|
||||
pub fn into_inner(self) -> Box<dyn std::error::Error + Send + Sync> {
|
||||
self.error
|
||||
}
|
||||
}
|
||||
|
||||
/// A block header and some associated data. This information should be available from most block
|
||||
/// sources (and, notably, is available in Bitcoin Core's RPC and REST interfaces).
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct BlockHeaderData {
|
||||
/// The block header itself.
|
||||
pub header: BlockHeader,
|
||||
|
||||
/// The block height where the genesis block has height 0.
|
||||
pub height: u32,
|
||||
|
||||
/// The total chain work in expected number of double-SHA256 hashes required to build a chain
|
||||
/// of equivalent weight.
|
||||
pub chainwork: Uint256,
|
||||
}
|
Loading…
Reference in New Issue
Block a user