From 528b61155e7d8335869cb456f770ebdee08ce915 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jul 2026 14:07:45 +0200 Subject: [PATCH] Bump LDK to 0.3.0-beta1 Track the first LDK 0.3 beta and its matching payment-instructions revision. Preserve Esplora configuration across the client versions and expose splice negotiation only to local contributors, as defined by the beta API. Co-Authored-By: HAL 9000 --- Cargo.toml | 31 ++++++++++++++++--------------- src/chain/esplora.rs | 10 +++++++++- src/event.rs | 12 +++++++----- tests/common/mod.rs | 3 --- tests/integration_tests_rust.rs | 16 +++++----------- 5 files changed, 37 insertions(+), 35 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7fc945833..8c793fb78 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,18 +41,18 @@ postgres = ["dep:tokio-postgres", "dep:native-tls", "dep:postgres-native-tls"] #lightning-macros = { version = "0.2.0" } #lightning-dns-resolver = { version = "0.3.0" } -lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "506cb91f2e0fb87906188b79777bcf42595d3623", features = ["std"] } -lightning-types = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "506cb91f2e0fb87906188b79777bcf42595d3623" } -lightning-invoice = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "506cb91f2e0fb87906188b79777bcf42595d3623", features = ["std"] } -lightning-net-tokio = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "506cb91f2e0fb87906188b79777bcf42595d3623" } -lightning-persister = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "506cb91f2e0fb87906188b79777bcf42595d3623", features = ["tokio"] } -lightning-background-processor = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "506cb91f2e0fb87906188b79777bcf42595d3623" } -lightning-rapid-gossip-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "506cb91f2e0fb87906188b79777bcf42595d3623" } -lightning-block-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "506cb91f2e0fb87906188b79777bcf42595d3623", features = ["rest-client", "rpc-client", "tokio"] } -lightning-transaction-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "506cb91f2e0fb87906188b79777bcf42595d3623", features = ["esplora-async-https", "time", "electrum-rustls-ring"] } -lightning-liquidity = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "506cb91f2e0fb87906188b79777bcf42595d3623", features = ["std"] } -lightning-macros = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "506cb91f2e0fb87906188b79777bcf42595d3623" } -lightning-dns-resolver = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "506cb91f2e0fb87906188b79777bcf42595d3623" } +lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "9174965af9437196c527a9aa0df36bbcf050c8bb", features = ["std"] } +lightning-types = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "9174965af9437196c527a9aa0df36bbcf050c8bb" } +lightning-invoice = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "9174965af9437196c527a9aa0df36bbcf050c8bb", features = ["std"] } +lightning-net-tokio = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "9174965af9437196c527a9aa0df36bbcf050c8bb" } +lightning-persister = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "9174965af9437196c527a9aa0df36bbcf050c8bb", features = ["tokio"] } +lightning-background-processor = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "9174965af9437196c527a9aa0df36bbcf050c8bb" } +lightning-rapid-gossip-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "9174965af9437196c527a9aa0df36bbcf050c8bb" } +lightning-block-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "9174965af9437196c527a9aa0df36bbcf050c8bb", features = ["rest-client", "rpc-client", "tokio"] } +lightning-transaction-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "9174965af9437196c527a9aa0df36bbcf050c8bb", features = ["esplora-async-https", "time", "electrum-rustls-ring"] } +lightning-liquidity = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "9174965af9437196c527a9aa0df36bbcf050c8bb", features = ["std"] } +lightning-macros = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "9174965af9437196c527a9aa0df36bbcf050c8bb" } +lightning-dns-resolver = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "9174965af9437196c527a9aa0df36bbcf050c8bb" } bdk_chain = { version = "0.23.3", default-features = false, features = ["std"] } bdk_esplora = { version = "0.22.2", default-features = false, features = ["async-https-rustls", "tokio"]} @@ -71,6 +71,7 @@ getrandom = { version = "0.3", default-features = false } chrono = { version = "0.4", default-features = false, features = ["clock"] } tokio = { version = "1.39", default-features = false, features = [ "rt-multi-thread", "time", "sync", "macros", "net" ] } esplora-client = { version = "0.12", default-features = false, features = ["tokio", "async-https-rustls"] } +ldk-esplora-client = { package = "esplora-client", version = "0.13", default-features = false, features = ["tokio", "async-https-rustls"] } electrum-client = { version = "0.25", default-features = false, features = ["proxy", "use-rustls-ring"] } libc = "0.2" uniffi = { version = "0.29.5", features = ["build"], optional = true } @@ -85,14 +86,14 @@ postgres-native-tls = { version = "0.5", default-features = false, features = [" vss-client = { package = "vss-client-ng", version = "0.6" } prost = { version = "0.11.6", default-features = false} #bitcoin-payment-instructions = { version = "0.6" } -bitcoin-payment-instructions = { git = "https://github.com/tnull/bitcoin-payment-instructions", rev = "0e430be98c09540624a68a68022ee0551e86d1be" } +bitcoin-payment-instructions = { git = "https://github.com/tnull/bitcoin-payment-instructions", rev = "1d6ffaa8962391ddc84aeef98bd7439e55ccae9d" } [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["winbase"] } [dev-dependencies] -lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "506cb91f2e0fb87906188b79777bcf42595d3623", features = ["std", "_test_utils"] } -lightning-persister = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "506cb91f2e0fb87906188b79777bcf42595d3623", features = ["tokio"] } +lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "9174965af9437196c527a9aa0df36bbcf050c8bb", features = ["std", "_test_utils"] } +lightning-persister = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "9174965af9437196c527a9aa0df36bbcf050c8bb", features = ["tokio"] } rand = { version = "0.9.2", default-features = false, features = ["std", "thread_rng", "os_rng"] } proptest = "1.0.0" regex = "1.5.6" diff --git a/src/chain/esplora.rs b/src/chain/esplora.rs index 21205bd25..f4aaea4c9 100644 --- a/src/chain/esplora.rs +++ b/src/chain/esplora.rs @@ -56,16 +56,24 @@ impl EsploraChainSource { let mut client_builder = esplora_client::Builder::new(&server_url); client_builder = client_builder.timeout(sync_config.timeouts_config.per_request_timeout_secs as u64); + let mut ldk_client_builder = ldk_esplora_client::Builder::new(&server_url); + ldk_client_builder = ldk_client_builder.timeout(Duration::from_secs( + sync_config.timeouts_config.per_request_timeout_secs as u64, + )); for (header_name, header_value) in &headers { client_builder = client_builder.header(header_name, header_value); + ldk_client_builder = ldk_client_builder.header(header_name, header_value); } let esplora_client = client_builder.build_async().map_err(|e| { log_error!(logger, "Failed to build Esplora client: {}", e); })?; + let ldk_esplora_client = ldk_client_builder.build_async().map_err(|e| { + log_error!(logger, "Failed to build LDK Esplora client: {}", e); + })?; let tx_sync = - Arc::new(EsploraSyncClient::from_client(esplora_client.clone(), Arc::clone(&logger))); + Arc::new(EsploraSyncClient::from_client(ldk_esplora_client, Arc::clone(&logger))); let onchain_wallet_sync_status = Mutex::new(WalletSyncStatus::Completed); let lightning_wallet_sync_status = Mutex::new(WalletSyncStatus::Completed); diff --git a/src/event.rs b/src/event.rs index b8ca73519..72f31d5cb 100644 --- a/src/event.rs +++ b/src/event.rs @@ -271,8 +271,10 @@ pub enum Event { /// This will be `None` for events serialized by LDK Node v0.2.1 and prior. reason: Option, }, - /// A channel splice has been negotiated and the funding transaction is pending - /// confirmation on-chain. + /// A channel splice with local inputs or outputs has been negotiated and the funding + /// transaction is pending confirmation on-chain. + /// + /// This event is not emitted when only the counterparty contributes to a splice. SpliceNegotiated { /// The `channel_id` of the channel. channel_id: ChannelId, @@ -1500,7 +1502,7 @@ where from_prev_str, next_htlcs.len(), to_next_str, - outbound_amount_forwarded_msat.unwrap_or(0), + outbound_amount_forwarded_msat, fee_earned, ); } else { @@ -1511,7 +1513,7 @@ where from_prev_str, next_htlcs.len(), to_next_str, - outbound_amount_forwarded_msat.unwrap_or(0), + outbound_amount_forwarded_msat, fee_earned, ); } @@ -1545,7 +1547,7 @@ where total_fee_earned_msat, skimmed_fee_msat, claim_from_onchain_tx, - outbound_amount_forwarded_msat, + outbound_amount_forwarded_msat: Some(outbound_amount_forwarded_msat), }; self.event_queue.add_event(event).await.map_err(|e| { log_error!(self.logger, "Failed to push to event queue: {}", e); diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 50e2b993c..40f3794fc 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -1063,7 +1063,6 @@ pub async fn splice_in_with_all( node_a.splice_in_with_all(user_channel_id, node_b.node_id()).unwrap(); let splice_txo = expect_splice_negotiated_event!(node_a, node_b.node_id()); - expect_splice_negotiated_event!(node_b, node_a.node_id()); wait_for_tx(&electrsd.client, splice_txo.txid).await; } @@ -1537,7 +1536,6 @@ pub(crate) async fn do_channel_full_cycle( assert!(splice_out_sat > 500_000); node_b.splice_out(&user_channel_id_b, node_a.node_id(), &addr_a, splice_out_sat).unwrap(); - expect_splice_negotiated_event!(node_a, node_b.node_id()); expect_splice_negotiated_event!(node_b, node_a.node_id()); generate_blocks_and_wait(&bitcoind, electrsd, 6).await; @@ -1560,7 +1558,6 @@ pub(crate) async fn do_channel_full_cycle( node_a.splice_in(&user_channel_id_a, node_b.node_id(), splice_in_sat).unwrap(); expect_splice_negotiated_event!(node_a, node_b.node_id()); - expect_splice_negotiated_event!(node_b, node_a.node_id()); generate_blocks_and_wait(&bitcoind, electrsd, 6).await; node_a.sync_wallets().unwrap(); diff --git a/tests/integration_tests_rust.rs b/tests/integration_tests_rust.rs index e401c8218..7508f5915 100644 --- a/tests/integration_tests_rust.rs +++ b/tests/integration_tests_rust.rs @@ -1752,8 +1752,7 @@ async fn splice_channel() { // Splice-in funds for Node B so that it has outbound liquidity to make a payment node_b.splice_in(&user_channel_id_b, node_a.node_id(), 4_000_000).unwrap(); - let txo = expect_splice_negotiated_event!(node_a, node_b.node_id()); - expect_splice_negotiated_event!(node_b, node_a.node_id()); + let txo = expect_splice_negotiated_event!(node_b, node_a.node_id()); // Node B contributed to this splice, so wait for its funding broadcast to be classified before // syncing — otherwise a sync racing the broadcaster's queue records a generic on-chain payment. @@ -1813,7 +1812,6 @@ async fn splice_channel() { node_a.splice_out(&user_channel_id_a, node_b.node_id(), &address, amount_msat / 1000).unwrap(); let txo = expect_splice_negotiated_event!(node_a, node_b.node_id()); - expect_splice_negotiated_event!(node_b, node_a.node_id()); // Node A contributed to this splice, so wait for its funding broadcast to be classified before // syncing — otherwise a sync racing the broadcaster's queue records a generic on-chain payment. @@ -1926,8 +1924,7 @@ async fn run_rbf_splice_channel_test(confirm_original: bool) { // Initiate a splice-in to create a pending splice node_b.splice_in(&user_channel_id_b, node_a.node_id(), 1_000_000).unwrap(); - let original_txo = expect_splice_negotiated_event!(node_a, node_b.node_id()); - expect_splice_negotiated_event!(node_b, node_a.node_id()); + let original_txo = expect_splice_negotiated_event!(node_b, node_a.node_id()); // Sync so the original splice candidate is recorded as a canonical wallet transaction before // the RBF below replaces it. The post-RBF sync then observes the original candidate being @@ -1964,8 +1961,7 @@ async fn run_rbf_splice_channel_test(confirm_original: bool) { // bump_channel_funding_fee should succeed when there's a pending splice node_b.bump_channel_funding_fee(&user_channel_id_b, node_a.node_id()).unwrap(); - let rbf_txo = expect_splice_negotiated_event!(node_a, node_b.node_id()); - expect_splice_negotiated_event!(node_b, node_a.node_id()); + let rbf_txo = expect_splice_negotiated_event!(node_b, node_a.node_id()); assert_ne!(original_txo, rbf_txo, "RBF should produce a different funding txo"); @@ -2170,8 +2166,7 @@ async fn splice_payment_reorged_to_unconfirmed() { // node_b splices in, recording a funding payment it contributed to. node_b.splice_in(&user_channel_id_b, node_a.node_id(), 1_000_000).unwrap(); - let splice_txo = expect_splice_negotiated_event!(node_a, node_b.node_id()); - expect_splice_negotiated_event!(node_b, node_a.node_id()); + let splice_txo = expect_splice_negotiated_event!(node_b, node_a.node_id()); wait_for_tx(&electrsd.client, splice_txo.txid).await; // Ensure node_b classified the splice before syncing so the test exercises a funding payment's // reorg rather than a generic on-chain payment's. @@ -2248,8 +2243,7 @@ async fn splice_in_rbf_joins_counterparty_splice() { // node_b (which didn't fund the channel open, so holds the on-chain balance) initiates a // splice-in; node_a does not contribute to this first candidate. node_b.splice_in(&user_channel_id_b, node_a.node_id(), 1_000_000).unwrap(); - let counterparty_txo = expect_splice_negotiated_event!(node_a, node_b.node_id()); - expect_splice_negotiated_event!(node_b, node_a.node_id()); + let counterparty_txo = expect_splice_negotiated_event!(node_b, node_a.node_id()); wait_for_tx(&electrsd.client, counterparty_txo.txid).await; node_a.sync_wallets().unwrap(); node_b.sync_wallets().unwrap();