Skip to content

Commit a36b529

Browse files
Merge pull request #2924 from tnull/2024-03-add-user-channel-id-to-payment-forwarded
Expose `{prev,next}_user_channel_id` fields in `PaymentForwarded`
2 parents e4b6a50 + ab4b872 commit a36b529

File tree

3 files changed

+69
-25
lines changed

3 files changed

+69
-25
lines changed

lightning/src/events/mod.rs

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -797,12 +797,24 @@ pub enum Event {
797797
/// This event is generated when a payment has been successfully forwarded through us and a
798798
/// forwarding fee earned.
799799
PaymentForwarded {
800-
/// The incoming channel between the previous node and us. This is only `None` for events
801-
/// generated or serialized by versions prior to 0.0.107.
800+
/// The channel id of the incoming channel between the previous node and us.
801+
///
802+
/// This is only `None` for events generated or serialized by versions prior to 0.0.107.
802803
prev_channel_id: Option<ChannelId>,
803-
/// The outgoing channel between the next node and us. This is only `None` for events
804-
/// generated or serialized by versions prior to 0.0.107.
804+
/// The channel id of the outgoing channel between the next node and us.
805+
///
806+
/// This is only `None` for events generated or serialized by versions prior to 0.0.107.
805807
next_channel_id: Option<ChannelId>,
808+
/// The `user_channel_id` of the incoming channel between the previous node and us.
809+
///
810+
/// This is only `None` for events generated or serialized by versions prior to 0.0.122.
811+
prev_user_channel_id: Option<u128>,
812+
/// The `user_channel_id` of the outgoing channel between the next node and us.
813+
///
814+
/// This will be `None` if the payment was settled via an on-chain transaction. See the
815+
/// caveat described for the `total_fee_earned_msat` field. Moreover it will be `None` for
816+
/// events generated or serialized by versions prior to 0.0.122.
817+
next_user_channel_id: Option<u128>,
806818
/// The total fee, in milli-satoshis, which was earned as a result of the payment.
807819
///
808820
/// Note that if we force-closed the channel over which we forwarded an HTLC while the HTLC
@@ -1121,8 +1133,9 @@ impl Writeable for Event {
11211133
});
11221134
}
11231135
&Event::PaymentForwarded {
1124-
total_fee_earned_msat, prev_channel_id, claim_from_onchain_tx,
1125-
next_channel_id, outbound_amount_forwarded_msat, skimmed_fee_msat,
1136+
prev_channel_id, next_channel_id, prev_user_channel_id, next_user_channel_id,
1137+
total_fee_earned_msat, skimmed_fee_msat, claim_from_onchain_tx,
1138+
outbound_amount_forwarded_msat,
11261139
} => {
11271140
7u8.write(writer)?;
11281141
write_tlv_fields!(writer, {
@@ -1132,6 +1145,8 @@ impl Writeable for Event {
11321145
(3, next_channel_id, option),
11331146
(5, outbound_amount_forwarded_msat, option),
11341147
(7, skimmed_fee_msat, option),
1148+
(9, prev_user_channel_id, option),
1149+
(11, next_user_channel_id, option),
11351150
});
11361151
},
11371152
&Event::ChannelClosed { ref channel_id, ref user_channel_id, ref reason,
@@ -1427,23 +1442,28 @@ impl MaybeReadable for Event {
14271442
},
14281443
7u8 => {
14291444
let f = || {
1430-
let mut total_fee_earned_msat = None;
14311445
let mut prev_channel_id = None;
1432-
let mut claim_from_onchain_tx = false;
14331446
let mut next_channel_id = None;
1434-
let mut outbound_amount_forwarded_msat = None;
1447+
let mut prev_user_channel_id = None;
1448+
let mut next_user_channel_id = None;
1449+
let mut total_fee_earned_msat = None;
14351450
let mut skimmed_fee_msat = None;
1451+
let mut claim_from_onchain_tx = false;
1452+
let mut outbound_amount_forwarded_msat = None;
14361453
read_tlv_fields!(reader, {
14371454
(0, total_fee_earned_msat, option),
14381455
(1, prev_channel_id, option),
14391456
(2, claim_from_onchain_tx, required),
14401457
(3, next_channel_id, option),
14411458
(5, outbound_amount_forwarded_msat, option),
14421459
(7, skimmed_fee_msat, option),
1460+
(9, prev_user_channel_id, option),
1461+
(11, next_user_channel_id, option),
14431462
});
14441463
Ok(Some(Event::PaymentForwarded {
1445-
total_fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id,
1446-
outbound_amount_forwarded_msat, skimmed_fee_msat,
1464+
prev_channel_id, next_channel_id, prev_user_channel_id,
1465+
next_user_channel_id, total_fee_earned_msat, skimmed_fee_msat,
1466+
claim_from_onchain_tx, outbound_amount_forwarded_msat,
14471467
}))
14481468
};
14491469
f()

lightning/src/ln/channelmanager.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5740,7 +5740,7 @@ where
57405740
fn claim_funds_internal(&self, source: HTLCSource, payment_preimage: PaymentPreimage,
57415741
forwarded_htlc_value_msat: Option<u64>, skimmed_fee_msat: Option<u64>, from_onchain: bool,
57425742
startup_replay: bool, next_channel_counterparty_node_id: Option<PublicKey>,
5743-
next_channel_outpoint: OutPoint, next_channel_id: ChannelId,
5743+
next_channel_outpoint: OutPoint, next_channel_id: ChannelId, next_user_channel_id: Option<u128>,
57445744
) {
57455745
match source {
57465746
HTLCSource::OutboundRoute { session_priv, payment_id, path, .. } => {
@@ -5759,11 +5759,10 @@ where
57595759
},
57605760
HTLCSource::PreviousHopData(hop_data) => {
57615761
let prev_channel_id = hop_data.channel_id;
5762+
let prev_user_channel_id = hop_data.user_channel_id;
57625763
let completed_blocker = RAAMonitorUpdateBlockingAction::from_prev_hop_data(&hop_data);
57635764
#[cfg(debug_assertions)]
57645765
let claiming_chan_funding_outpoint = hop_data.outpoint;
5765-
#[cfg(debug_assertions)]
5766-
let claiming_channel_id = hop_data.channel_id;
57675766
let res = self.claim_funds_from_hop(hop_data, payment_preimage,
57685767
|htlc_claim_value_msat, definitely_duplicate| {
57695768
let chan_to_release =
@@ -5821,7 +5820,7 @@ where
58215820
BackgroundEvent::MonitorUpdatesComplete {
58225821
channel_id, ..
58235822
} =>
5824-
*channel_id == claiming_channel_id,
5823+
*channel_id == prev_channel_id,
58255824
}
58265825
}), "{:?}", *background_events);
58275826
}
@@ -5845,12 +5844,14 @@ where
58455844
"skimmed_fee_msat must always be included in total_fee_earned_msat");
58465845
Some(MonitorUpdateCompletionAction::EmitEventAndFreeOtherChannel {
58475846
event: events::Event::PaymentForwarded {
5848-
total_fee_earned_msat,
5849-
claim_from_onchain_tx: from_onchain,
58505847
prev_channel_id: Some(prev_channel_id),
58515848
next_channel_id: Some(next_channel_id),
5852-
outbound_amount_forwarded_msat: forwarded_htlc_value_msat,
5849+
prev_user_channel_id,
5850+
next_user_channel_id,
5851+
total_fee_earned_msat,
58535852
skimmed_fee_msat,
5853+
claim_from_onchain_tx: from_onchain,
5854+
outbound_amount_forwarded_msat: forwarded_htlc_value_msat,
58545855
},
58555856
downstream_counterparty_and_funding_outpoint: chan_to_release,
58565857
})
@@ -6824,6 +6825,7 @@ where
68246825

68256826
fn internal_update_fulfill_htlc(&self, counterparty_node_id: &PublicKey, msg: &msgs::UpdateFulfillHTLC) -> Result<(), MsgHandleErrInternal> {
68266827
let funding_txo;
6828+
let next_user_channel_id;
68276829
let (htlc_source, forwarded_htlc_value, skimmed_fee_msat) = {
68286830
let per_peer_state = self.per_peer_state.read().unwrap();
68296831
let peer_state_mutex = per_peer_state.get(counterparty_node_id)
@@ -6853,6 +6855,7 @@ where
68536855
// outbound HTLC is claimed. This is guaranteed to all complete before we
68546856
// process the RAA as messages are processed from single peers serially.
68556857
funding_txo = chan.context.get_funding_txo().expect("We won't accept a fulfill until funded");
6858+
next_user_channel_id = chan.context.get_user_id();
68566859
res
68576860
} else {
68586861
return try_chan_phase_entry!(self, Err(ChannelError::Close(
@@ -6864,7 +6867,7 @@ where
68646867
};
68656868
self.claim_funds_internal(htlc_source, msg.payment_preimage.clone(),
68666869
Some(forwarded_htlc_value), skimmed_fee_msat, false, false, Some(*counterparty_node_id),
6867-
funding_txo, msg.channel_id
6870+
funding_txo, msg.channel_id, Some(next_user_channel_id),
68686871
);
68696872

68706873
Ok(())
@@ -7366,7 +7369,7 @@ where
73667369
log_trace!(logger, "Claiming HTLC with preimage {} from our monitor", preimage);
73677370
self.claim_funds_internal(htlc_update.source, preimage,
73687371
htlc_update.htlc_value_satoshis.map(|v| v * 1000), None, true,
7369-
false, counterparty_node_id, funding_outpoint, channel_id);
7372+
false, counterparty_node_id, funding_outpoint, channel_id, None);
73707373
} else {
73717374
log_trace!(logger, "Failing HTLC with hash {} from our monitor", &htlc_update.payment_hash);
73727375
let receiver = HTLCDestination::NextHopChannel { node_id: counterparty_node_id, channel_id };
@@ -11386,7 +11389,9 @@ where
1138611389
// don't remember in the `ChannelMonitor` where we got a preimage from, but if the
1138711390
// channel is closed we just assume that it probably came from an on-chain claim.
1138811391
channel_manager.claim_funds_internal(source, preimage, Some(downstream_value), None,
11389-
downstream_closed, true, downstream_node_id, downstream_funding, downstream_channel_id);
11392+
downstream_closed, true, downstream_node_id, downstream_funding,
11393+
downstream_channel_id, None
11394+
);
1139011395
}
1139111396

1139211397
//TODO: Broadcast channel update for closed channels, but only after we've made a

lightning/src/ln/functional_test_utils.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2231,8 +2231,8 @@ pub fn expect_payment_forwarded<CM: AChannelManager, H: NodeHolder<CM=CM>>(
22312231
) -> Option<u64> {
22322232
match event {
22332233
Event::PaymentForwarded {
2234-
total_fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id,
2235-
outbound_amount_forwarded_msat: _, skimmed_fee_msat
2234+
prev_channel_id, next_channel_id, prev_user_channel_id, next_user_channel_id,
2235+
total_fee_earned_msat, skimmed_fee_msat, claim_from_onchain_tx, ..
22362236
} => {
22372237
if allow_1_msat_fee_overpay {
22382238
// Aggregating fees for blinded paths may result in a rounding error, causing slight
@@ -2249,12 +2249,31 @@ pub fn expect_payment_forwarded<CM: AChannelManager, H: NodeHolder<CM=CM>>(
22492249
assert!(skimmed_fee_msat == expected_extra_fees_msat);
22502250
if !upstream_force_closed {
22512251
// Is the event prev_channel_id in one of the channels between the two nodes?
2252-
assert!(node.node().list_channels().iter().any(|x| x.counterparty.node_id == prev_node.node().get_our_node_id() && x.channel_id == prev_channel_id.unwrap()));
2252+
assert!(node.node().list_channels().iter().any(|x|
2253+
x.counterparty.node_id == prev_node.node().get_our_node_id() &&
2254+
x.channel_id == prev_channel_id.unwrap() &&
2255+
x.user_channel_id == prev_user_channel_id.unwrap()
2256+
));
22532257
}
22542258
// We check for force closures since a force closed channel is removed from the
22552259
// node's channel list
22562260
if !downstream_force_closed {
2257-
assert!(node.node().list_channels().iter().any(|x| x.counterparty.node_id == next_node.node().get_our_node_id() && x.channel_id == next_channel_id.unwrap()));
2261+
// As documented, `next_user_channel_id` will only be `Some` if we didn't settle via an
2262+
// onchain transaction, just as the `total_fee_earned_msat` field. Rather than
2263+
// introducing yet another variable, we use the latter's state as a flag to detect
2264+
// this and only check if it's `Some`.
2265+
if total_fee_earned_msat.is_none() {
2266+
assert!(node.node().list_channels().iter().any(|x|
2267+
x.counterparty.node_id == next_node.node().get_our_node_id() &&
2268+
x.channel_id == next_channel_id.unwrap()
2269+
));
2270+
} else {
2271+
assert!(node.node().list_channels().iter().any(|x|
2272+
x.counterparty.node_id == next_node.node().get_our_node_id() &&
2273+
x.channel_id == next_channel_id.unwrap() &&
2274+
x.user_channel_id == next_user_channel_id.unwrap()
2275+
));
2276+
}
22582277
}
22592278
assert_eq!(claim_from_onchain_tx, downstream_force_closed);
22602279
total_fee_earned_msat

0 commit comments

Comments
 (0)