Skip to content

Commit f916490

Browse files
committed
Initial implementation of LDK Node
1 parent e27774e commit f916490

File tree

8 files changed

+1429
-186
lines changed

8 files changed

+1429
-186
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,5 @@ jobs:
2525
- name: Check formatting
2626
if: matrix.check-fmt
2727
run: rustup component add rustfmt && cargo fmt --all -- --check
28+
- name: Test on Rust ${{ matrix.toolchain }}
29+
run: cargo test

Cargo.toml

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,52 @@
11
[package]
2-
name = "ldk-lite"
2+
name = "ldk-node"
33
version = "0.1.0"
44
authors = ["Elias Rohrer <[email protected]>"]
55
license = "MIT OR Apache-2.0"
66
edition = "2018"
7+
description = "A ready-to-go node implementation based on LDK."
78

89
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
910

1011
[dependencies]
11-
lightning = { version = "0.0.110", features = ["max_level_trace", "std"] }
12-
lightning-invoice = { version = "0.18" }
13-
lightning-net-tokio = { version = "0.0.110" }
14-
lightning-persister = { version = "0.0.110" }
15-
lightning-background-processor = { version = "0.0.110" }
16-
lightning-rapid-gossip-sync = { version = "0.0.110" }
12+
#lightning = { version = "0.0.112", features = ["max_level_trace", "std"] }
13+
#lightning-invoice = { version = "0.20" }
14+
#lightning-net-tokio = { version = "0.0.112" }
15+
#lightning-persister = { version = "0.0.112" }
16+
#lightning-background-processor = { version = "0.0.112" }
17+
#lightning-rapid-gossip-sync = { version = "0.0.112" }
1718

18-
#bdk = "0.20.0"
19-
bdk = { git = "https://github.com/tnull/bdk", branch="feat/use-external-esplora-client", features = ["use-esplora-ureq", "key-value-db"]}
20-
bitcoin = "0.28.1"
19+
#lightning = { git = "https://github.com/lightningdevkit/rust-lightning", branch="main", features = ["max_level_trace", "std"] }
20+
#lightning-invoice = { git = "https://github.com/lightningdevkit/rust-lightning", branch="main" }
21+
#lightning-net-tokio = { git = "https://github.com/lightningdevkit/rust-lightning", branch="main" }
22+
#lightning-persister = { git = "https://github.com/lightningdevkit/rust-lightning", branch="main" }
23+
#lightning-background-processor = { git = "https://github.com/lightningdevkit/rust-lightning", branch="main" }
24+
#lightning-rapid-gossip-sync = { git = "https://github.com/lightningdevkit/rust-lightning", branch="main" }
25+
26+
lightning = { git = "https://github.com/tnull/rust-lightning", branch="2022-11-add-transaction-sync-crate", features = ["max_level_trace", "std"] }
27+
lightning-invoice = { git = "https://github.com/tnull/rust-lightning", branch="2022-11-add-transaction-sync-crate" }
28+
lightning-net-tokio = { git = "https://github.com/tnull/rust-lightning", branch="2022-11-add-transaction-sync-crate" }
29+
lightning-persister = { git = "https://github.com/tnull/rust-lightning", branch="2022-11-add-transaction-sync-crate" }
30+
lightning-background-processor = { git = "https://github.com/tnull/rust-lightning", branch="2022-11-add-transaction-sync-crate" }
31+
lightning-rapid-gossip-sync = { git = "https://github.com/tnull/rust-lightning", branch="2022-11-add-transaction-sync-crate" }
32+
lightning-transaction-sync = { git = "https://github.com/tnull/rust-lightning", branch="2022-11-add-transaction-sync-crate", features = ["esplora-async"] }
33+
34+
#lightning = { path = "../rust-lightning/lightning", features = ["max_level_trace", "std"] }
35+
#lightning-invoice = { path = "../rust-lightning/lightning-invoice" }
36+
#lightning-net-tokio = { path = "../rust-lightning/lightning-net-tokio" }
37+
#lightning-persister = { path = "../rust-lightning/lightning-persister" }
38+
#lightning-background-processor = { path = "../rust-lightning/lightning-background-processor" }
39+
#lightning-rapid-gossip-sync = { path = "../rust-lightning/lightning-rapid-gossip-sync" }
40+
#lightning-transaction-sync = { path = "../rust-lightning/lightning-transaction-sync", features = ["esplora-async"] }
41+
42+
bdk = { version = "0.26.0", default-features = false, features = ["async-interface", "use-esplora-async", "key-value-db"]}
43+
bitcoin = "0.29.2"
2144

2245
rand = "0.8.5"
2346
chrono = "0.4"
2447
futures = "0.3"
2548
serde_json = { version = "1.0" }
26-
tokio = { version = "1", features = [ "io-util", "macros", "rt", "rt-multi-thread", "sync", "net", "time" ] }
49+
tokio = { version = "1", features = [ "full" ] }
2750

2851

2952
[profile.release]

src/error.rs

Lines changed: 50 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,130 +1,79 @@
1-
use bdk::blockchain::esplora;
2-
use lightning::ln::msgs;
3-
use lightning::util::errors;
4-
use lightning_invoice::payment;
51
use std::fmt;
6-
use std::io;
7-
use std::time;
82

93
#[derive(Debug)]
104
/// An error that possibly needs to be handled by the user.
11-
pub enum LdkLiteError {
12-
/// Returned when trying to start LdkLite while it is already running.
5+
pub enum Error {
6+
/// Returned when trying to start [`crate::Node`] while it is already running.
137
AlreadyRunning,
14-
/// Returned when trying to stop LdkLite while it is not running.
8+
/// Returned when trying to stop [`crate::Node`] while it is not running.
159
NotRunning,
1610
/// The funding transaction could not be created.
1711
FundingTxCreationFailed,
1812
/// A network connection has been closed.
1913
ConnectionFailed,
2014
/// Payment of the given invoice has already been intiated.
2115
NonUniquePaymentHash,
16+
/// The given invoice is invalid.
17+
InvoiceInvalid,
18+
/// Invoice creation failed.
19+
InvoiceCreationFailed,
20+
/// No route for the given target could be found.
21+
RoutingFailed,
2222
/// A given peer info could not be parsed.
23-
PeerInfoParse(&'static str),
24-
/// A wrapped LDK `APIError`
25-
LdkApi(errors::APIError),
26-
/// A wrapped LDK `DecodeError`
27-
LdkDecode(msgs::DecodeError),
28-
/// A wrapped LDK `PaymentError`
29-
LdkPayment(payment::PaymentError),
30-
/// A wrapped LDK `SignOrCreationError`
31-
LdkInvoiceCreation(lightning_invoice::SignOrCreationError),
32-
/// A wrapped BDK error
33-
Bdk(bdk::Error),
34-
/// A wrapped `EsploraError`
35-
Esplora(esplora::EsploraError),
36-
/// A wrapped `Bip32` error
37-
Bip32(bitcoin::util::bip32::Error),
38-
/// A wrapped `std::io::Error`
39-
StdIo(io::Error),
40-
/// A wrapped `SystemTimeError`
41-
StdTime(time::SystemTimeError),
23+
PeerInfoParseFailed,
24+
/// A channel could not be opened.
25+
ChannelCreationFailed,
26+
/// A channel could not be closed.
27+
ChannelClosingFailed,
28+
/// Persistence failed.
29+
PersistenceFailed,
30+
/// A wallet operation failed.
31+
WalletOperationFailed,
32+
/// A siging operation failed.
33+
WalletSigningFailed,
34+
/// A transaction sync operation failed.
35+
TxSyncFailed,
4236
}
4337

44-
impl fmt::Display for LdkLiteError {
38+
impl fmt::Display for Error {
4539
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4640
match *self {
47-
LdkLiteError::AlreadyRunning => write!(f, "LDKLite is already running."),
48-
LdkLiteError::NotRunning => write!(f, "LDKLite is not running."),
49-
LdkLiteError::FundingTxCreationFailed => {
50-
write!(f, "the funding transaction could not be created")
41+
Self::AlreadyRunning => write!(f, "Node is already running."),
42+
Self::NotRunning => write!(f, "Node is not running."),
43+
Self::FundingTxCreationFailed => {
44+
write!(f, "Funding transaction could not be created.")
5145
}
52-
LdkLiteError::ConnectionFailed => write!(f, "network connection closed"),
53-
LdkLiteError::NonUniquePaymentHash => write!(f, "an invoice must not get payed twice."),
54-
LdkLiteError::PeerInfoParse(ref e) => {
55-
write!(f, "given peer info could not be parsed: {}", e)
56-
}
57-
LdkLiteError::LdkDecode(ref e) => write!(f, "LDK decode error: {}", e),
58-
LdkLiteError::LdkApi(ref e) => write!(f, "LDK API error: {:?}", e),
59-
LdkLiteError::LdkPayment(ref e) => write!(f, "LDK payment error: {:?}", e),
60-
LdkLiteError::LdkInvoiceCreation(ref e) => {
61-
write!(f, "LDK invoice sign or creation error: {:?}", e)
62-
}
63-
LdkLiteError::Bdk(ref e) => write!(f, "BDK error: {}", e),
64-
LdkLiteError::Esplora(ref e) => write!(f, "Esplora error: {}", e),
65-
LdkLiteError::Bip32(ref e) => write!(f, "Bitcoin error: {}", e),
66-
LdkLiteError::StdIo(ref e) => write!(f, "IO error: {}", e),
67-
LdkLiteError::StdTime(ref e) => write!(f, "time error: {}", e),
46+
Self::ConnectionFailed => write!(f, "Network connection closed."),
47+
Self::NonUniquePaymentHash => write!(f, "An invoice must not get payed twice."),
48+
Self::InvoiceInvalid => write!(f, "The given invoice is invalid."),
49+
Self::InvoiceCreationFailed => write!(f, "Failed to create invoice."),
50+
Self::RoutingFailed => write!(f, "Failed to find route."),
51+
Self::PeerInfoParseFailed => write!(f, "Failed to parse the given peer information."),
52+
Self::ChannelCreationFailed => write!(f, "Failed to create channel."),
53+
Self::ChannelClosingFailed => write!(f, "Failed to close channel."),
54+
Self::PersistenceFailed => write!(f, "Failed to persist data."),
55+
Self::WalletOperationFailed => write!(f, "Failed to conduct wallet operation."),
56+
Self::WalletSigningFailed => write!(f, "Failed to sign given transaction."),
57+
Self::TxSyncFailed => write!(f, "Failed to sync transactions."),
6858
}
6959
}
7060
}
7161

72-
impl From<errors::APIError> for LdkLiteError {
73-
fn from(e: errors::APIError) -> Self {
74-
Self::LdkApi(e)
75-
}
76-
}
77-
78-
impl From<msgs::DecodeError> for LdkLiteError {
79-
fn from(e: msgs::DecodeError) -> Self {
80-
Self::LdkDecode(e)
81-
}
82-
}
83-
84-
impl From<payment::PaymentError> for LdkLiteError {
85-
fn from(e: payment::PaymentError) -> Self {
86-
Self::LdkPayment(e)
87-
}
88-
}
62+
impl std::error::Error for Error {}
8963

90-
impl From<lightning_invoice::SignOrCreationError> for LdkLiteError {
91-
fn from(e: lightning_invoice::SignOrCreationError) -> Self {
92-
Self::LdkInvoiceCreation(e)
93-
}
94-
}
95-
96-
impl From<bdk::Error> for LdkLiteError {
64+
impl From<bdk::Error> for Error {
9765
fn from(e: bdk::Error) -> Self {
98-
Self::Bdk(e)
99-
}
100-
}
101-
102-
impl From<bdk::sled::Error> for LdkLiteError {
103-
fn from(e: bdk::sled::Error) -> Self {
104-
Self::Bdk(bdk::Error::Sled(e))
105-
}
106-
}
107-
108-
impl From<bitcoin::util::bip32::Error> for LdkLiteError {
109-
fn from(e: bitcoin::util::bip32::Error) -> Self {
110-
Self::Bip32(e)
111-
}
112-
}
113-
114-
impl From<io::Error> for LdkLiteError {
115-
fn from(e: io::Error) -> Self {
116-
Self::StdIo(e)
117-
}
118-
}
119-
120-
impl From<time::SystemTimeError> for LdkLiteError {
121-
fn from(e: time::SystemTimeError) -> Self {
122-
Self::StdTime(e)
66+
match e {
67+
bdk::Error::Signer(_) => Self::WalletSigningFailed,
68+
_ => Self::WalletOperationFailed,
69+
}
12370
}
12471
}
12572

126-
impl From<esplora::EsploraError> for LdkLiteError {
127-
fn from(e: esplora::EsploraError) -> Self {
128-
Self::Esplora(e)
73+
impl From<lightning_transaction_sync::TxSyncError> for Error {
74+
fn from(e: lightning_transaction_sync::TxSyncError) -> Self {
75+
match e {
76+
_ => Self::TxSyncFailed,
77+
}
12978
}
13079
}

src/event.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ use std::time::Duration;
2525
/// The event queue will be persisted under this key.
2626
pub(crate) const EVENTS_PERSISTENCE_KEY: &str = "events";
2727

28-
/// An event emitted by [`LdkLite`], which should be handled by the user.
28+
/// An event emitted by [`Node`], which should be handled by the user.
2929
///
30-
/// [`LdkLite`]: [`crate::LdkLite`]
30+
/// [`Node`]: [`crate::Node`]
3131
#[derive(Debug, Clone, PartialEq)]
3232
pub enum Event {
3333
/// A sent payment was successful.
@@ -332,7 +332,8 @@ where
332332
}
333333
}
334334
}
335-
Err(_err) => {
335+
Err(err) => {
336+
log_error!(self.logger, "Failed to create funding transaction: {}", err);
336337
self.channel_manager
337338
.force_close_without_broadcasting_txn(
338339
&temporary_channel_id,

src/io_utils.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use crate::{Config, Error, FilesystemLogger, NetworkGraph, Scorer};
2+
3+
use lightning::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringParameters};
4+
use lightning::util::ser::ReadableArgs;
5+
6+
use rand::{thread_rng, RngCore};
7+
8+
use std::fs;
9+
use std::io::{BufReader, Write};
10+
use std::path::Path;
11+
use std::sync::Arc;
12+
13+
pub(crate) fn read_or_generate_seed_file(config: Arc<Config>) -> [u8; 32] {
14+
let keys_seed_path = format!("{}/keys_seed", config.storage_dir_path);
15+
let keys_seed = if Path::new(&keys_seed_path).exists() {
16+
let seed = fs::read(keys_seed_path.clone()).expect("Failed to read keys seed file");
17+
assert_eq!(seed.len(), 32);
18+
let mut key = [0; 32];
19+
key.copy_from_slice(&seed);
20+
key
21+
} else {
22+
let mut key = [0; 32];
23+
thread_rng().fill_bytes(&mut key);
24+
25+
let mut f =
26+
fs::File::create(keys_seed_path.clone()).expect("Failed to create keys seed file");
27+
f.write_all(&key).expect("Failed to write node keys seed to disk");
28+
f.sync_all().expect("Failed to sync node keys seed to disk");
29+
key
30+
};
31+
32+
keys_seed
33+
}
34+
35+
pub(crate) fn read_network_graph(
36+
config: Arc<Config>, logger: Arc<FilesystemLogger>,
37+
) -> Result<NetworkGraph, Error> {
38+
let ldk_data_dir = format!("{}/ldk", &config.storage_dir_path.clone());
39+
let network_graph_path = format!("{}/network_graph", ldk_data_dir.clone());
40+
41+
if let Ok(file) = fs::File::open(network_graph_path) {
42+
if let Ok(graph) = NetworkGraph::read(&mut BufReader::new(file), Arc::clone(&logger)) {
43+
return Ok(graph);
44+
}
45+
}
46+
47+
let genesis_hash =
48+
bitcoin::blockdata::constants::genesis_block(config.network).header.block_hash();
49+
Ok(NetworkGraph::new(genesis_hash, logger))
50+
}
51+
52+
pub(crate) fn read_scorer(
53+
config: Arc<Config>, network_graph: Arc<NetworkGraph>, logger: Arc<FilesystemLogger>,
54+
) -> Scorer {
55+
let ldk_data_dir = format!("{}/ldk", &config.storage_dir_path.clone());
56+
let scorer_path = format!("{}/scorer", ldk_data_dir.clone());
57+
58+
let params = ProbabilisticScoringParameters::default();
59+
if let Ok(file) = fs::File::open(scorer_path) {
60+
let args = (params.clone(), Arc::clone(&network_graph), Arc::clone(&logger));
61+
if let Ok(scorer) = ProbabilisticScorer::read(&mut BufReader::new(file), args) {
62+
return scorer;
63+
}
64+
}
65+
ProbabilisticScorer::new(params, network_graph, logger)
66+
}

0 commit comments

Comments
 (0)