Skip to content

Commit c16a292

Browse files
committed
Expose per-HTLC forwarded amounts
Preserve LDK's per-HTLC amount when forwarding events cross the LDK Node API boundary. This lets callers attribute multi-HTLC forwards to individual channels. Store the amount in an optional TLV so previously serialized events continue to decode without it. Co-Authored-By: HAL 9000
1 parent 48b76b4 commit c16a292

1 file changed

Lines changed: 60 additions & 0 deletions

File tree

src/event.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ use crate::{
6868
pub struct HTLCLocator {
6969
/// The channel that the HTLC was sent or received on.
7070
pub channel_id: ChannelId,
71+
/// The amount, in milli-satoshis, of the HTLC that was sent or received, if known.
72+
///
73+
/// This will be `None` for events serialized by LDK Node v0.7.0 and prior.
74+
pub amount_msat: Option<u64>,
7175
/// The `user_channel_id` for the channel.
7276
///
7377
/// Will only be `None` for events serialized with LDK Node v0.3.0 or prior, or if the
@@ -84,12 +88,14 @@ impl_writeable_tlv_based!(HTLCLocator, {
8488
(1, channel_id, required),
8589
(3, user_channel_id, option),
8690
(5, node_id, option),
91+
(7, amount_msat, option),
8792
});
8893

8994
impl From<LdkHtlcLocator> for HTLCLocator {
9095
fn from(value: LdkHtlcLocator) -> Self {
9196
HTLCLocator {
9297
channel_id: value.channel_id,
98+
amount_msat: value.amount_msat,
9399
user_channel_id: value.user_channel_id.map(|u| UserChannelId(u)),
94100
node_id: value.node_id,
95101
}
@@ -355,11 +361,13 @@ impl_writeable_tlv_based_enum!(Event,
355361
(14, outbound_amount_forwarded_msat, (default_value, 0)),
356362
(15, prev_htlcs, (default_value_vec, vec![HTLCLocator {
357363
channel_id: legacy_prev_channel_id.ok_or(lightning::ln::msgs::DecodeError::InvalidValue)?,
364+
amount_msat: None,
358365
user_channel_id: legacy_prev_user_channel_id.map(UserChannelId),
359366
node_id: legacy_prev_node_id,
360367
}])),
361368
(17, next_htlcs, (default_value_vec, vec![HTLCLocator {
362369
channel_id: legacy_next_channel_id.ok_or(lightning::ln::msgs::DecodeError::InvalidValue)?,
370+
amount_msat: None,
363371
user_channel_id: legacy_next_user_channel_id.map(UserChannelId),
364372
node_id: legacy_next_node_id,
365373
}])),
@@ -2027,6 +2035,56 @@ mod tests {
20272035
use crate::payment::store::LSPS2Parameters;
20282036
use crate::types::DynStoreWrapper;
20292037

2038+
#[derive(Clone, Debug, PartialEq, Eq)]
2039+
struct LegacyHTLCLocator {
2040+
channel_id: ChannelId,
2041+
user_channel_id: Option<UserChannelId>,
2042+
node_id: Option<PublicKey>,
2043+
}
2044+
2045+
impl_writeable_tlv_based!(LegacyHTLCLocator, {
2046+
(1, channel_id, required),
2047+
(3, user_channel_id, option),
2048+
(5, node_id, option),
2049+
});
2050+
2051+
#[test]
2052+
fn htlc_locator_conversion_preserves_amount() {
2053+
let ldk_locator = LdkHtlcLocator {
2054+
channel_id: ChannelId([42; 32]),
2055+
amount_msat: Some(100_000),
2056+
user_channel_id: None,
2057+
node_id: None,
2058+
};
2059+
let expected_encoding = ldk_locator.encode();
2060+
2061+
assert_eq!(
2062+
HTLCLocator::from(ldk_locator).encode(),
2063+
expected_encoding,
2064+
"converted HTLC locator should preserve its amount"
2065+
);
2066+
}
2067+
2068+
#[test]
2069+
fn htlc_locator_defaults_amount_for_legacy_encoding() {
2070+
let legacy_locator = LegacyHTLCLocator {
2071+
channel_id: ChannelId([42; 32]),
2072+
user_channel_id: Some(UserChannelId(43)),
2073+
node_id: None,
2074+
};
2075+
let encoded_locator = legacy_locator.encode();
2076+
2077+
let locator = HTLCLocator::read(&mut &encoded_locator[..]).unwrap();
2078+
2079+
assert_eq!(locator.channel_id, legacy_locator.channel_id);
2080+
assert_eq!(locator.user_channel_id, legacy_locator.user_channel_id);
2081+
assert_eq!(locator.node_id, legacy_locator.node_id);
2082+
assert_eq!(
2083+
locator.amount_msat, None,
2084+
"legacy HTLC locator should default its amount to None"
2085+
);
2086+
}
2087+
20302088
#[test]
20312089
fn lsps2_payment_metadata_decodes_total_fee_limit() {
20322090
let metadata = PaymentMetadata {
@@ -2214,11 +2272,13 @@ mod tests {
22142272
let logger = Arc::new(TestLogger::new());
22152273
let prev_htlcs = vec![HTLCLocator {
22162274
channel_id: ChannelId([1; 32]),
2275+
amount_msat: None,
22172276
user_channel_id: None,
22182277
node_id: None,
22192278
}];
22202279
let next_htlcs = vec![HTLCLocator {
22212280
channel_id: ChannelId([2; 32]),
2281+
amount_msat: None,
22222282
user_channel_id: None,
22232283
node_id: None,
22242284
}];

0 commit comments

Comments
 (0)