Skip to content

Commit 8bcbd9e

Browse files
committed
Initial implementation of LDK Node
1 parent adfdc24 commit 8bcbd9e

File tree

11 files changed

+1568
-221
lines changed

11 files changed

+1568
-221
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: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,53 @@
11
[package]
2-
name = "ldk-lite"
2+
name = "ldk-node"
33
version = "0.1.0"
44
authors = ["Elias Rohrer <dev@tnull.de>"]
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+
#lightning-transaction-sync = { git = "https://github.com/lightningdevkit/rust-lightning", branch="main", features = ["esplora-async"] }
26+
27+
lightning = { git = "https://github.com/tnull/rust-lightning", branch="2022-11-add-transaction-sync-crate-pre-rebase", features = ["max_level_trace", "std"] }
28+
lightning-invoice = { git = "https://github.com/tnull/rust-lightning", branch="2022-11-add-transaction-sync-crate-pre-rebase" }
29+
lightning-net-tokio = { git = "https://github.com/tnull/rust-lightning", branch="2022-11-add-transaction-sync-crate-pre-rebase" }
30+
lightning-persister = { git = "https://github.com/tnull/rust-lightning", branch="2022-11-add-transaction-sync-crate-pre-rebase" }
31+
lightning-background-processor = { git = "https://github.com/tnull/rust-lightning", branch="2022-11-add-transaction-sync-crate-pre-rebase" }
32+
lightning-rapid-gossip-sync = { git = "https://github.com/tnull/rust-lightning", branch="2022-11-add-transaction-sync-crate-pre-rebase" }
33+
lightning-transaction-sync = { git = "https://github.com/tnull/rust-lightning", branch="2022-11-add-transaction-sync-crate-pre-rebase", features = ["esplora-async"] }
34+
35+
#lightning = { path = "../rust-lightning/lightning", features = ["max_level_trace", "std"] }
36+
#lightning-invoice = { path = "../rust-lightning/lightning-invoice" }
37+
#lightning-net-tokio = { path = "../rust-lightning/lightning-net-tokio" }
38+
#lightning-persister = { path = "../rust-lightning/lightning-persister" }
39+
#lightning-background-processor = { path = "../rust-lightning/lightning-background-processor" }
40+
#lightning-rapid-gossip-sync = { path = "../rust-lightning/lightning-rapid-gossip-sync" }
41+
#lightning-transaction-sync = { path = "../rust-lightning/lightning-transaction-sync", features = ["esplora-async"] }
42+
43+
bdk = { version = "0.26.0", default-features = false, features = ["async-interface", "use-esplora-async", "key-value-db"]}
44+
bitcoin = "0.29.2"
2145

2246
rand = "0.8.5"
2347
chrono = "0.4"
2448
futures = "0.3"
2549
serde_json = { version = "1.0" }
26-
tokio = { version = "1", features = [ "io-util", "macros", "rt", "rt-multi-thread", "sync", "net", "time" ] }
50+
tokio = { version = "1", features = [ "full" ] }
2751

2852

2953
[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: 30 additions & 19 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, Eq)]
3232
pub enum Event {
3333
/// A sent payment was successful.
@@ -324,7 +324,8 @@ where
324324
}
325325
}
326326
}
327-
Err(_err) => {
327+
Err(err) => {
328+
log_error!(self.logger, "Failed to create funding transaction: {}", err);
328329
self.channel_manager
329330
.force_close_without_broadcasting_txn(
330331
&temporary_channel_id,
@@ -480,17 +481,19 @@ where
480481
let output_descriptors = &outputs.iter().collect::<Vec<_>>();
481482
let tx_feerate =
482483
self.wallet.get_est_sat_per_1000_weight(ConfirmationTarget::Normal);
483-
let spending_tx = self
484-
.keys_manager
485-
.spend_spendable_outputs(
486-
output_descriptors,
487-
Vec::new(),
488-
destination_address.script_pubkey(),
489-
tx_feerate,
490-
&Secp256k1::new(),
491-
)
492-
.unwrap();
493-
self.wallet.broadcast_transaction(&spending_tx);
484+
let res = self.keys_manager.spend_spendable_outputs(
485+
output_descriptors,
486+
Vec::new(),
487+
destination_address.script_pubkey(),
488+
tx_feerate,
489+
&Secp256k1::new(),
490+
);
491+
match res {
492+
Ok(spending_tx) => self.wallet.broadcast_transaction(&spending_tx),
493+
Err(err) => {
494+
log_error!(self.logger, "Error spending outputs: {:?}", err);
495+
}
496+
}
494497
}
495498
LdkEvent::OpenChannelRequest { .. } => {}
496499
LdkEvent::PaymentForwarded {
@@ -588,21 +591,29 @@ mod tests {
588591

589592
#[test]
590593
fn event_queue_persistence() {
591-
let test_persister = Arc::new(TestPersister::new());
592-
let event_queue = EventQueue::new(Arc::clone(&test_persister));
594+
let persister = Arc::new(TestPersister::new());
595+
let event_queue = EventQueue::new(Arc::clone(&persister));
593596

594597
let expected_event = Event::ChannelReady { channel_id: [23u8; 32], user_channel_id: 2323 };
595598
event_queue.add_event(expected_event.clone()).unwrap();
596-
assert!(test_persister.get_and_clear_pending_persist());
599+
assert!(persister.get_and_clear_did_persist());
597600

598601
// Check we get the expected event and that it is returned until we mark it handled.
599602
for _ in 0..5 {
600603
assert_eq!(event_queue.next_event(), expected_event);
601-
assert_eq!(false, test_persister.get_and_clear_pending_persist());
604+
assert_eq!(false, persister.get_and_clear_did_persist());
602605
}
603606

607+
// Check we can read back what we persisted.
608+
let persisted_bytes = persister.get_persisted_bytes(EVENTS_PERSISTENCE_KEY).unwrap();
609+
let deser_event_queue =
610+
EventQueue::read(&mut &persisted_bytes[..], Arc::clone(&persister)).unwrap();
611+
assert_eq!(deser_event_queue.next_event(), expected_event);
612+
assert!(!persister.get_and_clear_did_persist());
613+
604614
// Check we persisted on `event_handled()`
605615
event_queue.event_handled().unwrap();
606-
assert!(test_persister.get_and_clear_pending_persist());
616+
617+
assert!(persister.get_and_clear_did_persist());
607618
}
608619
}

0 commit comments

Comments
 (0)