Skip to content

Commit e8a9303

Browse files
authored
Merge pull request #4300 from TheBlueMatt/2025-12-full-interception
Support generic HTLC interception
2 parents 9e91b2e + ce91315 commit e8a9303

File tree

13 files changed

+748
-312
lines changed

13 files changed

+748
-312
lines changed

lightning-liquidity/tests/lsps2_integration_tests.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ use lightning::ln::peer_handler::CustomMessageHandler;
3838
use lightning::log_error;
3939
use lightning::routing::router::{RouteHint, RouteHintHop};
4040
use lightning::sign::NodeSigner;
41+
use lightning::util::config::HTLCInterceptionFlags;
4142
use lightning::util::errors::APIError;
4243
use lightning::util::logger::Logger;
4344
use lightning::util::test_utils::{TestBroadcaster, TestStore};
@@ -1157,7 +1158,7 @@ fn client_trusts_lsp_end_to_end_test() {
11571158
let chanmon_cfgs = create_chanmon_cfgs(3);
11581159
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
11591160
let mut service_node_config = test_default_channel_config();
1160-
service_node_config.accept_intercept_htlcs = true;
1161+
service_node_config.htlc_interception_flags = HTLCInterceptionFlags::ToInterceptSCIDs as u8;
11611162

11621163
let mut client_node_config = test_default_channel_config();
11631164
client_node_config.manually_accept_inbound_channels = true;
@@ -1630,7 +1631,7 @@ fn late_payment_forwarded_and_safe_after_force_close_does_not_broadcast() {
16301631
let chanmon_cfgs = create_chanmon_cfgs(3);
16311632
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
16321633
let mut service_node_config = test_default_channel_config();
1633-
service_node_config.accept_intercept_htlcs = true;
1634+
service_node_config.htlc_interception_flags = HTLCInterceptionFlags::ToInterceptSCIDs as u8;
16341635

16351636
let mut client_node_config = test_default_channel_config();
16361637
client_node_config.manually_accept_inbound_channels = true;
@@ -1821,7 +1822,7 @@ fn htlc_timeout_before_client_claim_results_in_handling_failed() {
18211822
let chanmon_cfgs = create_chanmon_cfgs(3);
18221823
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
18231824
let mut service_node_config = test_default_channel_config();
1824-
service_node_config.accept_intercept_htlcs = true;
1825+
service_node_config.htlc_interception_flags = HTLCInterceptionFlags::ToInterceptSCIDs as u8;
18251826

18261827
let mut client_node_config = test_default_channel_config();
18271828
client_node_config.manually_accept_inbound_channels = true;
@@ -2157,7 +2158,7 @@ fn client_trusts_lsp_partial_fee_does_not_trigger_broadcast() {
21572158
let chanmon_cfgs = create_chanmon_cfgs(3);
21582159
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
21592160
let mut service_node_config = test_default_channel_config();
2160-
service_node_config.accept_intercept_htlcs = true;
2161+
service_node_config.htlc_interception_flags = HTLCInterceptionFlags::ToInterceptSCIDs as u8;
21612162

21622163
let mut client_node_config = test_default_channel_config();
21632164
client_node_config.manually_accept_inbound_channels = true;

lightning/src/events/mod.rs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,28 +1250,29 @@ pub enum Event {
12501250
short_channel_id: Option<u64>,
12511251
},
12521252
/// Used to indicate that we've intercepted an HTLC forward. This event will only be generated if
1253-
/// you've encoded an intercept scid in the receiver's invoice route hints using
1254-
/// [`ChannelManager::get_intercept_scid`] and have set [`UserConfig::accept_intercept_htlcs`].
1253+
/// you've set some flags on [`UserConfig::htlc_interception_flags`].
12551254
///
12561255
/// [`ChannelManager::forward_intercepted_htlc`] or
1257-
/// [`ChannelManager::fail_intercepted_htlc`] MUST be called in response to this event. See
1258-
/// their docs for more information.
1256+
/// [`ChannelManager::fail_intercepted_htlc`] MUST be called in response to this event in a
1257+
/// timely manner (i.e. within some number of seconds, not minutes). See their docs for more
1258+
/// information.
12591259
///
12601260
/// # Failure Behavior and Persistence
12611261
/// This event will eventually be replayed after failures-to-handle (i.e., the event handler
12621262
/// returning `Err(ReplayEvent ())`) and will be persisted across restarts.
12631263
///
1264-
/// [`ChannelManager::get_intercept_scid`]: crate::ln::channelmanager::ChannelManager::get_intercept_scid
1265-
/// [`UserConfig::accept_intercept_htlcs`]: crate::util::config::UserConfig::accept_intercept_htlcs
1264+
/// [`UserConfig::htlc_interception_flags`]: crate::util::config::UserConfig::htlc_interception_flags
12661265
/// [`ChannelManager::forward_intercepted_htlc`]: crate::ln::channelmanager::ChannelManager::forward_intercepted_htlc
12671266
/// [`ChannelManager::fail_intercepted_htlc`]: crate::ln::channelmanager::ChannelManager::fail_intercepted_htlc
12681267
HTLCIntercepted {
12691268
/// An id to help LDK identify which HTLC is being forwarded or failed.
12701269
intercept_id: InterceptId,
1271-
/// The fake scid that was programmed as the next hop's scid, generated using
1272-
/// [`ChannelManager::get_intercept_scid`].
1270+
/// The SCID which was selected by the sender as the next hop. It may point to one of our
1271+
/// channels, an intercept SCID generated with [`ChannelManager::get_intercept_scid`], or
1272+
/// an unknown SCID if [`HTLCInterceptionFlags::ToUnknownSCIDs`] was selected.
12731273
///
12741274
/// [`ChannelManager::get_intercept_scid`]: crate::ln::channelmanager::ChannelManager::get_intercept_scid
1275+
/// [`HTLCInterceptionFlags::ToUnknownSCIDs`]: crate::util::config::HTLCInterceptionFlags::ToUnknownSCIDs
12751276
requested_next_hop_scid: u64,
12761277
/// The payment hash used for this HTLC.
12771278
payment_hash: PaymentHash,
@@ -1282,9 +1283,17 @@ pub enum Event {
12821283
/// Forwarding less than this amount may break compatibility with LDK versions prior to 0.0.116.
12831284
///
12841285
/// Note that LDK will NOT check that expected fees were factored into this value. You MUST
1285-
/// check that whatever fee you want has been included here or subtract it as required. Further,
1286+
/// check that whatever fee you want has been included here (by comparing with
1287+
/// [`Self::HTLCIntercepted::inbound_amount_msat`]) or subtract it as required. Further,
12861288
/// LDK will not stop you from forwarding more than you received.
12871289
expected_outbound_amount_msat: u64,
1290+
/// The block height at which the forwarded HTLC sent to our peer will time out. In
1291+
/// practice, LDK will refuse to forward an HTLC several blocks before this height (as if
1292+
/// we attempted to forward an HTLC at this height we'd run some risk that our peer
1293+
/// force-closes the channel immediately).
1294+
///
1295+
/// This will only be `None` for events generated or serialized by LDK 0.2 or prior.
1296+
outgoing_htlc_expiry_block_height: Option<u32>,
12881297
},
12891298
/// Used to indicate that an output which you should know how to spend was confirmed on chain
12901299
/// and is now spendable.
@@ -2015,11 +2024,13 @@ impl Writeable for Event {
20152024
inbound_amount_msat,
20162025
expected_outbound_amount_msat,
20172026
intercept_id,
2027+
outgoing_htlc_expiry_block_height,
20182028
} => {
20192029
6u8.write(writer)?;
20202030
let intercept_scid = InterceptNextHop::FakeScid { requested_next_hop_scid };
20212031
write_tlv_fields!(writer, {
20222032
(0, intercept_id, required),
2033+
(1, outgoing_htlc_expiry_block_height, option),
20232034
(2, intercept_scid, required),
20242035
(4, payment_hash, required),
20252036
(6, inbound_amount_msat, required),
@@ -2524,8 +2535,10 @@ impl MaybeReadable for Event {
25242535
InterceptNextHop::FakeScid { requested_next_hop_scid: 0 };
25252536
let mut inbound_amount_msat = 0;
25262537
let mut expected_outbound_amount_msat = 0;
2538+
let mut outgoing_htlc_expiry_block_height = None;
25272539
read_tlv_fields!(reader, {
25282540
(0, intercept_id, required),
2541+
(1, outgoing_htlc_expiry_block_height, option),
25292542
(2, requested_next_hop_scid, required),
25302543
(4, payment_hash, required),
25312544
(6, inbound_amount_msat, required),
@@ -2540,6 +2553,7 @@ impl MaybeReadable for Event {
25402553
inbound_amount_msat,
25412554
expected_outbound_amount_msat,
25422555
intercept_id,
2556+
outgoing_htlc_expiry_block_height,
25432557
}))
25442558
},
25452559
7u8 => {

lightning/src/ln/async_payments_tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ use crate::sign::NodeSigner;
6060
use crate::sync::Mutex;
6161
use crate::types::features::Bolt12InvoiceFeatures;
6262
use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
63-
use crate::util::config::UserConfig;
63+
use crate::util::config::{HTLCInterceptionFlags, UserConfig};
6464
use crate::util::ser::Writeable;
6565
use bitcoin::constants::ChainHash;
6666
use bitcoin::network::Network;
@@ -3063,7 +3063,7 @@ fn intercepted_hold_htlc() {
30633063
recipient_cfg.channel_handshake_limits.force_announced_channel_preference = false;
30643064

30653065
let mut lsp_cfg = test_default_channel_config();
3066-
lsp_cfg.accept_intercept_htlcs = true;
3066+
lsp_cfg.htlc_interception_flags = HTLCInterceptionFlags::ToInterceptSCIDs as u8;
30673067
lsp_cfg.accept_forwards_to_priv_channels = true;
30683068
lsp_cfg.enable_htlc_hold = true;
30693069

lightning/src/ln/blinded_payment_tests.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use crate::routing::router::{
3232
use crate::sign::{NodeSigner, PeerStorageKey, ReceiveAuthKey, Recipient};
3333
use crate::types::features::{BlindedHopFeatures, ChannelFeatures, NodeFeatures};
3434
use crate::types::payment::{PaymentHash, PaymentSecret};
35-
use crate::util::config::UserConfig;
35+
use crate::util::config::{HTLCInterceptionFlags, UserConfig};
3636
use crate::util::ser::{WithoutLength, Writeable};
3737
use crate::util::test_utils::{self, bytes_from_hex, pubkey_from_hex, secret_from_hex};
3838
use bitcoin::hex::DisplayHex;
@@ -769,7 +769,8 @@ fn do_blinded_intercept_payment(intercept_node_fails: bool) {
769769
let chanmon_cfgs = create_chanmon_cfgs(3);
770770
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
771771
let mut intercept_forwards_config = test_default_channel_config();
772-
intercept_forwards_config.accept_intercept_htlcs = true;
772+
intercept_forwards_config.htlc_interception_flags =
773+
HTLCInterceptionFlags::ToInterceptSCIDs as u8;
773774
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(intercept_forwards_config), None]);
774775
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
775776
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);

0 commit comments

Comments
 (0)