Skip to content

Commit 3852c0a

Browse files
committed
Expose {prev,next}_user_channel_id fields in PaymentForwarded
This is useful for users that track channels by `user_channel_id`. For example, in `lightning-liquidity` we currently keep a full `HashMap<ChanelId, u128>` around *just* to be able to associate `PaymentForwarded` events with the channels otherwise tracked by `user_channel_id`.
1 parent 2c9dbb9 commit 3852c0a

File tree

3 files changed

+68
-22
lines changed

3 files changed

+68
-22
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: 14 additions & 7 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,6 +5759,7 @@ 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;
@@ -5845,12 +5846,14 @@ where
58455846
"skimmed_fee_msat must always be included in total_fee_earned_msat");
58465847
Some(MonitorUpdateCompletionAction::EmitEventAndFreeOtherChannel {
58475848
event: events::Event::PaymentForwarded {
5848-
total_fee_earned_msat,
5849-
claim_from_onchain_tx: from_onchain,
58505849
prev_channel_id: Some(prev_channel_id),
58515850
next_channel_id: Some(next_channel_id),
5852-
outbound_amount_forwarded_msat: forwarded_htlc_value_msat,
5851+
prev_user_channel_id,
5852+
next_user_channel_id,
5853+
total_fee_earned_msat,
58535854
skimmed_fee_msat,
5855+
claim_from_onchain_tx: from_onchain,
5856+
outbound_amount_forwarded_msat: forwarded_htlc_value_msat,
58545857
},
58555858
downstream_counterparty_and_funding_outpoint: chan_to_release,
58565859
})
@@ -6824,6 +6827,7 @@ where
68246827

68256828
fn internal_update_fulfill_htlc(&self, counterparty_node_id: &PublicKey, msg: &msgs::UpdateFulfillHTLC) -> Result<(), MsgHandleErrInternal> {
68266829
let funding_txo;
6830+
let next_user_channel_id;
68276831
let (htlc_source, forwarded_htlc_value, skimmed_fee_msat) = {
68286832
let per_peer_state = self.per_peer_state.read().unwrap();
68296833
let peer_state_mutex = per_peer_state.get(counterparty_node_id)
@@ -6853,6 +6857,7 @@ where
68536857
// outbound HTLC is claimed. This is guaranteed to all complete before we
68546858
// process the RAA as messages are processed from single peers serially.
68556859
funding_txo = chan.context.get_funding_txo().expect("We won't accept a fulfill until funded");
6860+
next_user_channel_id = chan.context.get_user_id();
68566861
res
68576862
} else {
68586863
return try_chan_phase_entry!(self, Err(ChannelError::Close(
@@ -6864,7 +6869,7 @@ where
68646869
};
68656870
self.claim_funds_internal(htlc_source, msg.payment_preimage.clone(),
68666871
Some(forwarded_htlc_value), skimmed_fee_msat, false, false, Some(*counterparty_node_id),
6867-
funding_txo, msg.channel_id
6872+
funding_txo, msg.channel_id, Some(next_user_channel_id),
68686873
);
68696874

68706875
Ok(())
@@ -7366,7 +7371,7 @@ where
73667371
log_trace!(logger, "Claiming HTLC with preimage {} from our monitor", preimage);
73677372
self.claim_funds_internal(htlc_update.source, preimage,
73687373
htlc_update.htlc_value_satoshis.map(|v| v * 1000), None, true,
7369-
false, counterparty_node_id, funding_outpoint, channel_id);
7374+
false, counterparty_node_id, funding_outpoint, channel_id, None);
73707375
} else {
73717376
log_trace!(logger, "Failing HTLC with hash {} from our monitor", &htlc_update.payment_hash);
73727377
let receiver = HTLCDestination::NextHopChannel { node_id: counterparty_node_id, channel_id };
@@ -11386,7 +11391,9 @@ where
1138611391
// don't remember in the `ChannelMonitor` where we got a preimage from, but if the
1138711392
// channel is closed we just assume that it probably came from an on-chain claim.
1138811393
channel_manager.claim_funds_internal(source, preimage, Some(downstream_value), None,
11389-
downstream_closed, true, downstream_node_id, downstream_funding, downstream_channel_id);
11394+
downstream_closed, true, downstream_node_id, downstream_funding,
11395+
downstream_channel_id, None
11396+
);
1139011397
}
1139111398

1139211399
//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)