Skip to content

Commit

Permalink
Expose the channel via which we received a payment
Browse files Browse the repository at this point in the history
We expose the `channel_id` and `user_channel_id` via which we received a
payment in the `PaymentReceived` event.
  • Loading branch information
tnull committed Nov 16, 2022
1 parent 6acf4d2 commit 0fb6e3e
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 16 deletions.
19 changes: 13 additions & 6 deletions lightning/src/ln/chanmon_update_fail_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,10 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) {
let events_3 = nodes[1].node.get_and_clear_pending_events();
assert_eq!(events_3.len(), 1);
match events_3[0] {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat } => {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat, via_channel_id, .. } => {
assert_eq!(payment_hash_1, *payment_hash);
assert_eq!(amount_msat, 1_000_000);
assert_eq!(via_channel_id, Some(channel_id));
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
assert!(payment_preimage.is_none());
Expand Down Expand Up @@ -569,9 +570,10 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) {
let events_5 = nodes[1].node.get_and_clear_pending_events();
assert_eq!(events_5.len(), 1);
match events_5[0] {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat } => {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat, via_channel_id, .. } => {
assert_eq!(payment_hash_2, *payment_hash);
assert_eq!(amount_msat, 1_000_000);
assert_eq!(via_channel_id, Some(channel_id));
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
assert!(payment_preimage.is_none());
Expand Down Expand Up @@ -686,9 +688,10 @@ fn test_monitor_update_fail_cs() {
let events = nodes[1].node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
match events[0] {
Event::PaymentReceived { payment_hash, ref purpose, amount_msat } => {
Event::PaymentReceived { payment_hash, ref purpose, amount_msat, via_channel_id, .. } => {
assert_eq!(payment_hash, our_payment_hash);
assert_eq!(amount_msat, 1_000_000);
assert_eq!(via_channel_id, Some(channel_id));
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
assert!(payment_preimage.is_none());
Expand Down Expand Up @@ -1639,7 +1642,8 @@ fn test_monitor_update_fail_claim() {
commitment_signed_dance!(nodes[1], nodes[2], payment_event.commitment_msg, false, true);

// Now restore monitor updating on the 0<->1 channel and claim the funds on B.
let (outpoint, latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_1.2).unwrap().clone();
let channel_id = chan_1.2;
let (outpoint, latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(outpoint, latest_update);
check_added_monitors!(nodes[1], 0);

Expand All @@ -1660,9 +1664,11 @@ fn test_monitor_update_fail_claim() {
let events = nodes[0].node.get_and_clear_pending_events();
assert_eq!(events.len(), 2);
match events[0] {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat } => {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat, via_channel_id, via_user_channel_id } => {
assert_eq!(payment_hash_2, *payment_hash);
assert_eq!(1_000_000, amount_msat);
assert_eq!(via_channel_id, Some(channel_id));
assert_eq!(via_user_channel_id, Some(42));
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
assert!(payment_preimage.is_none());
Expand All @@ -1674,9 +1680,10 @@ fn test_monitor_update_fail_claim() {
_ => panic!("Unexpected event"),
}
match events[1] {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat } => {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat, via_channel_id, .. } => {
assert_eq!(payment_hash_3, *payment_hash);
assert_eq!(1_000_000, amount_msat);
assert_eq!(via_channel_id, Some(channel_id));
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
assert!(payment_preimage.is_none());
Expand Down
26 changes: 26 additions & 0 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3470,11 +3470,24 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
log_bytes!(payment_hash.0), total_value, $payment_data.total_msat);
fail_htlc!(claimable_htlc, payment_hash);
} else if total_value == $payment_data.total_msat {
let (via_channel_id, via_user_channel_id) =
if let Some((_, chan_id)) = self.short_to_chan_info.read().unwrap().get(&prev_short_channel_id) {
match channel_state.by_id.entry(*chan_id) {
hash_map::Entry::Occupied(prev_chan) =>
(Some(chan_id.clone()), Some(prev_chan.get().get_user_id())),
_ => (None, None),
}
} else {
(None, None)
};

htlcs.push(claimable_htlc);
new_events.push(events::Event::PaymentReceived {
payment_hash,
purpose: purpose(),
amount_msat: total_value,
via_channel_id,
via_user_channel_id,
});
payment_received_generated = true;
} else {
Expand Down Expand Up @@ -3506,17 +3519,30 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
continue
}
};

check_total_value!(payment_data, payment_preimage);
},
OnionPayload::Spontaneous(preimage) => {
match channel_state.claimable_htlcs.entry(payment_hash) {
hash_map::Entry::Vacant(e) => {
let purpose = events::PaymentPurpose::SpontaneousPayment(preimage);
e.insert((purpose.clone(), vec![claimable_htlc]));
let (via_channel_id, via_user_channel_id) =
if let Some((_, chan_id)) = self.short_to_chan_info.read().unwrap().get(&prev_short_channel_id) {
match channel_state.by_id.entry(*chan_id) {
hash_map::Entry::Occupied(prev_chan) =>
(Some(chan_id.clone()), Some(prev_chan.get().get_user_id())),
_ => (None, None),
}
} else {
(None, None)
};
new_events.push(events::Event::PaymentReceived {
payment_hash,
amount_msat: outgoing_amt_msat,
purpose,
via_channel_id,
via_user_channel_id,
});
},
hash_map::Entry::Occupied(_) => {
Expand Down
6 changes: 4 additions & 2 deletions lightning/src/ln/functional_test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1387,7 +1387,7 @@ macro_rules! expect_payment_received {
let events = $node.node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
match events[0] {
$crate::util::events::Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat } => {
$crate::util::events::Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat, .. } => {
assert_eq!($expected_payment_hash, *payment_hash);
assert_eq!($expected_recv_value, amount_msat);
match purpose {
Expand Down Expand Up @@ -1681,7 +1681,7 @@ pub fn do_pass_along_path<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_p
if payment_received_expected {
assert_eq!(events_2.len(), 1);
match events_2[0] {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat } => {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat, ref via_channel_id, ref via_user_channel_id } => {
assert_eq!(our_payment_hash, *payment_hash);
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
Expand All @@ -1694,6 +1694,8 @@ pub fn do_pass_along_path<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_p
},
}
assert_eq!(amount_msat, recv_value);
assert!(node.node.list_channels().iter().any(|details| details.channel_id == via_channel_id.unwrap()));
assert!(node.node.list_channels().iter().any(|details| details.user_channel_id == via_user_channel_id.unwrap()));
},
_ => panic!("Unexpected event"),
}
Expand Down
18 changes: 11 additions & 7 deletions lightning/src/ln/functional_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1956,9 +1956,10 @@ fn test_channel_reserve_holding_cell_htlcs() {
let events = nodes[2].node.get_and_clear_pending_events();
assert_eq!(events.len(), 2);
match events[0] {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat } => {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat, via_channel_id, .. } => {
assert_eq!(our_payment_hash_21, *payment_hash);
assert_eq!(recv_value_21, amount_msat);
assert_eq!(via_channel_id, Some(chan_2.2));
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
assert!(payment_preimage.is_none());
Expand All @@ -1970,9 +1971,10 @@ fn test_channel_reserve_holding_cell_htlcs() {
_ => panic!("Unexpected event"),
}
match events[1] {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat } => {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat, via_channel_id, .. } => {
assert_eq!(our_payment_hash_22, *payment_hash);
assert_eq!(recv_value_22, amount_msat);
assert_eq!(via_channel_id, Some(chan_2.2));
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
assert!(payment_preimage.is_none());
Expand Down Expand Up @@ -3612,15 +3614,16 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);

let mut as_channel_ready = None;
if messages_delivered == 0 {
let (channel_ready, _, _) = create_chan_between_nodes_with_value_a(&nodes[0], &nodes[1], 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
let channel_id = if messages_delivered == 0 {
let (channel_ready, chan_id, _) = create_chan_between_nodes_with_value_a(&nodes[0], &nodes[1], 100000, 10001, channelmanager::provided_init_features(), channelmanager::provided_init_features());
as_channel_ready = Some(channel_ready);
// nodes[1] doesn't receive the channel_ready message (it'll be re-sent on reconnect)
// Note that we store it so that if we're running with `simulate_broken_lnd` we can deliver
// it before the channel_reestablish message.
chan_id
} else {
create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
}
create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2
};

let (route, payment_hash_1, payment_preimage_1, payment_secret_1) = get_route_and_payment_hash!(nodes[0], nodes[1], 1_000_000);

Expand Down Expand Up @@ -3723,9 +3726,10 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken
let events_2 = nodes[1].node.get_and_clear_pending_events();
assert_eq!(events_2.len(), 1);
match events_2[0] {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat } => {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat, via_channel_id, .. } => {
assert_eq!(payment_hash_1, *payment_hash);
assert_eq!(amount_msat, 1_000_000);
assert_eq!(via_channel_id, Some(channel_id));
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
assert!(payment_preimage.is_none());
Expand Down
14 changes: 13 additions & 1 deletion lightning/src/util/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,10 @@ pub enum Event {
/// Information for claiming this received payment, based on whether the purpose of the
/// payment is to pay an invoice or to send a spontaneous payment.
purpose: PaymentPurpose,
/// The `channel_id` indicating over which channel we received the payment.
via_channel_id: Option<[u8; 32]>,
/// The `user_channel_id` indicating over which channel we received the payment.
via_user_channel_id: Option<u128>,
},
/// Indicates a payment has been claimed and we've received money!
///
Expand Down Expand Up @@ -739,7 +743,7 @@ impl Writeable for Event {
// We never write out FundingGenerationReady events as, upon disconnection, peers
// drop any channels which have not yet exchanged funding_signed.
},
&Event::PaymentReceived { ref payment_hash, ref amount_msat, ref purpose } => {
&Event::PaymentReceived { ref payment_hash, ref amount_msat, ref purpose, ref via_channel_id, ref via_user_channel_id } => {
1u8.write(writer)?;
let mut payment_secret = None;
let payment_preimage;
Expand All @@ -754,7 +758,9 @@ impl Writeable for Event {
}
write_tlv_fields!(writer, {
(0, payment_hash, required),
(1, via_channel_id, option),
(2, payment_secret, option),
(3, via_user_channel_id, option),
(4, amount_msat, required),
(6, 0u64, required), // user_payment_id required for compatibility with 0.0.103 and earlier
(8, payment_preimage, option),
Expand Down Expand Up @@ -924,9 +930,13 @@ impl MaybeReadable for Event {
let mut payment_secret = None;
let mut amount_msat = 0;
let mut _user_payment_id = None::<u64>; // For compatibility with 0.0.103 and earlier
let mut via_channel_id = None;
let mut via_user_channel_id = None;
read_tlv_fields!(reader, {
(0, payment_hash, required),
(1, via_channel_id, option),
(2, payment_secret, option),
(3, via_user_channel_id, option),
(4, amount_msat, required),
(6, _user_payment_id, option),
(8, payment_preimage, option),
Expand All @@ -943,6 +953,8 @@ impl MaybeReadable for Event {
payment_hash,
amount_msat,
purpose,
via_channel_id,
via_user_channel_id,
}))
};
f()
Expand Down

0 comments on commit 0fb6e3e

Please sign in to comment.