From 130a27bedddec2c3e1747f0330880da80148cf30 Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Tue, 24 Mar 2026 09:24:17 -0400 Subject: [PATCH] Update rust-lightning with changes to PaymentForwarded In preparation for trampoline, rust-lightning has been updated to report multiple HTLCs incoming and outgoing in PaymentForwarded. Support is not yet complete, so we can still expect that we only get a single HTLC in/out for now. This change writes the first entry of the new fields to our PaymentForwarded event, because we don't yet have the serialization macros we need to persist a vec with a default value (as the trait and the type Vec are not owned by this crate). We're not losing any information here, as we only expect regular forwards with this version of LDK. We'll follow with a change that writes the full vec once upstream changes are made to LDK's serialization macros. --- Cargo.toml | 26 ++++++++--------- src/event.rs | 81 +++++++++++++++++++++++++++++----------------------- 2 files changed, 59 insertions(+), 48 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 07cabe33f..2fb63f88e 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,17 +39,17 @@ default = [] #lightning-liquidity = { version = "0.2.0", features = ["std"] } #lightning-macros = { version = "0.2.0" } -lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "98393b3de3d8aec897e9ab783cb2418da504e204", features = ["std"] } -lightning-types = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "98393b3de3d8aec897e9ab783cb2418da504e204" } -lightning-invoice = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "98393b3de3d8aec897e9ab783cb2418da504e204", features = ["std"] } -lightning-net-tokio = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "98393b3de3d8aec897e9ab783cb2418da504e204" } -lightning-persister = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "98393b3de3d8aec897e9ab783cb2418da504e204", features = ["tokio"] } -lightning-background-processor = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "98393b3de3d8aec897e9ab783cb2418da504e204" } -lightning-rapid-gossip-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "98393b3de3d8aec897e9ab783cb2418da504e204" } -lightning-block-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "98393b3de3d8aec897e9ab783cb2418da504e204", features = ["rest-client", "rpc-client", "tokio"] } -lightning-transaction-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "98393b3de3d8aec897e9ab783cb2418da504e204", features = ["esplora-async-https", "time", "electrum-rustls-ring"] } -lightning-liquidity = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "98393b3de3d8aec897e9ab783cb2418da504e204", features = ["std"] } -lightning-macros = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "98393b3de3d8aec897e9ab783cb2418da504e204" } +lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "128ead25e8d62b0262b71711631220983c48756a", features = ["std"] } +lightning-types = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "128ead25e8d62b0262b71711631220983c48756a" } +lightning-invoice = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "128ead25e8d62b0262b71711631220983c48756a", features = ["std"] } +lightning-net-tokio = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "128ead25e8d62b0262b71711631220983c48756a" } +lightning-persister = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "128ead25e8d62b0262b71711631220983c48756a", features = ["tokio"] } +lightning-background-processor = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "128ead25e8d62b0262b71711631220983c48756a" } +lightning-rapid-gossip-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "128ead25e8d62b0262b71711631220983c48756a" } +lightning-block-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "128ead25e8d62b0262b71711631220983c48756a", features = ["rest-client", "rpc-client", "tokio"] } +lightning-transaction-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "128ead25e8d62b0262b71711631220983c48756a", features = ["esplora-async-https", "time", "electrum-rustls-ring"] } +lightning-liquidity = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "128ead25e8d62b0262b71711631220983c48756a", features = ["std"] } +lightning-macros = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "128ead25e8d62b0262b71711631220983c48756a" } bdk_chain = { version = "0.23.0", default-features = false, features = ["std"] } bdk_esplora = { version = "0.22.0", default-features = false, features = ["async-https-rustls", "tokio"]} @@ -79,13 +79,13 @@ async-trait = { version = "0.1", default-features = false } vss-client = { package = "vss-client-ng", version = "0.5" } prost = { version = "0.11.6", default-features = false} #bitcoin-payment-instructions = { version = "0.6" } -bitcoin-payment-instructions = { git = "https://github.com/jkczyz/bitcoin-payment-instructions", rev = "0138feb7acefb1e49102a6fb46d7b776bf43265e" } +bitcoin-payment-instructions = { git = "https://github.com/carlaKC/bitcoin-payment-instructions", rev = "c22c9b836b70d4c915dd28701e11083a8b558d56" } [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["winbase"] } [dev-dependencies] -lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "98393b3de3d8aec897e9ab783cb2418da504e204", features = ["std", "_test_utils"] } +lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "128ead25e8d62b0262b71711631220983c48756a", features = ["std", "_test_utils"] } 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/event.rs b/src/event.rs index c4949a5ac..ccee8e50b 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1306,12 +1306,8 @@ where } }, LdkEvent::PaymentForwarded { - prev_channel_id, - next_channel_id, - prev_user_channel_id, - next_user_channel_id, - prev_node_id, - next_node_id, + prev_htlcs, + next_htlcs, total_fee_earned_msat, skimmed_fee_msat, claim_from_onchain_tx, @@ -1322,11 +1318,10 @@ where let nodes = read_only_network_graph.nodes(); let channels = self.channel_manager.list_channels(); - let node_str = |channel_id: &Option| { - channel_id - .and_then(|channel_id| { - channels.iter().find(|c| c.channel_id == channel_id) - }) + let node_str = |channel_id: &ChannelId| { + channels + .iter() + .find(|c| c.channel_id == *channel_id) .and_then(|channel| { nodes.get(&NodeId::from_pubkey(&channel.counterparty.node_id)) }) @@ -1338,28 +1333,30 @@ where }) }) }; - let channel_str = |channel_id: &Option| { - channel_id - .map(|channel_id| format!(" with channel {}", channel_id)) - .unwrap_or_default() - }; - let from_prev_str = format!( - " from {}{}", - node_str(&prev_channel_id), - channel_str(&prev_channel_id) - ); - let to_next_str = format!( - " to {}{}", - node_str(&next_channel_id), - channel_str(&next_channel_id) - ); + let from_prev_str: String = prev_htlcs + .iter() + .map(|htlc| { + format!("with {} on {}", node_str(&htlc.channel_id), htlc.channel_id) + }) + .collect::>() + .join(", "); + + let to_next_str: String = next_htlcs + .iter() + .map(|htlc| { + format!("with {} on {}", node_str(&htlc.channel_id), htlc.channel_id) + }) + .collect::>() + .join(", "); let fee_earned = total_fee_earned_msat.unwrap_or(0); if claim_from_onchain_tx { log_info!( self.logger, - "Forwarded payment{}{} of {}msat, earning {}msat in fees from claiming onchain.", + "Forwarded payment with {} inbound HTLC(s) ({}) and {} outbound HTLC(s) ({}) of {}msat, earning {}msat in fees from claiming onchain.", + prev_htlcs.len(), from_prev_str, + next_htlcs.len(), to_next_str, outbound_amount_forwarded_msat.unwrap_or(0), fee_earned, @@ -1367,8 +1364,10 @@ where } else { log_info!( self.logger, - "Forwarded payment{}{} of {}msat, earning {}msat in fees.", + "Forwarded payment with {} inbound HTLC(s) ({}) and {} outbound HTLC(s) ({}) of {}msat, earning {}msat in fees.", + prev_htlcs.len(), from_prev_str, + next_htlcs.len(), to_next_str, outbound_amount_forwarded_msat.unwrap_or(0), fee_earned, @@ -1376,20 +1375,32 @@ where } } + // We only allow multiple HTLCs in/out for trampoline forwards, which have not yet + // been fully implemented in LDK, so we do not lose any information by just + // reporting the first HTLC in each vec. + debug_assert_eq!(prev_htlcs.len(), 1, "unexpected number of prev_htlcs"); + debug_assert_eq!(next_htlcs.len(), 1, "unexpected number of next_htlcs"); + let prev_htlc = prev_htlcs + .first() + .expect("we expect at least one prev_htlc for PaymentForwarded"); + let next_htlc = next_htlcs + .first() + .expect("we expect at least one next_htlc for PaymentForwarded"); + if let Some(liquidity_source) = self.liquidity_source.as_ref() { let skimmed_fee_msat = skimmed_fee_msat.unwrap_or(0); liquidity_source - .handle_payment_forwarded(next_channel_id, skimmed_fee_msat) + .handle_payment_forwarded(Some(next_htlc.channel_id), skimmed_fee_msat) .await; } let event = Event::PaymentForwarded { - prev_channel_id: prev_channel_id.expect("prev_channel_id expected for events generated by LDK versions greater than 0.0.107."), - next_channel_id: next_channel_id.expect("next_channel_id expected for events generated by LDK versions greater than 0.0.107."), - prev_user_channel_id: prev_user_channel_id.map(UserChannelId), - next_user_channel_id: next_user_channel_id.map(UserChannelId), - prev_node_id, - next_node_id, + prev_channel_id: prev_htlc.channel_id, + next_channel_id: next_htlc.channel_id, + prev_user_channel_id: prev_htlc.user_channel_id.map(UserChannelId), + next_user_channel_id: next_htlc.user_channel_id.map(UserChannelId), + prev_node_id: prev_htlc.node_id, + next_node_id: next_htlc.node_id, total_fee_earned_msat, skimmed_fee_msat, claim_from_onchain_tx,