nodes[fwd_idx].node.process_pending_htlc_forwards();
let payment_preimage_opt = if user_generated_pmt_hash { None } else { Some(payment_preimage) };
- expect_payment_received!(&nodes[fwd_idx], payment_hash, payment_secret, payment_amt, payment_preimage_opt);
+ expect_payment_received!(&nodes[fwd_idx], payment_hash, payment_secret, payment_amt, payment_preimage_opt, route.paths[0].last().unwrap().pubkey);
do_claim_payment_along_route(&nodes[0], &vec!(&vec!(&nodes[fwd_idx])[..]), false, payment_preimage);
let events = nodes[0].node.get_and_clear_pending_events();
assert_eq!(events.len(), 2);
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, receiver_node_id } => {
assert_eq!(payment_hash_1, *payment_hash);
assert_eq!(amount_msat, 1_000_000);
+ assert_eq!(receiver_node_id.unwrap(), nodes[1].node.get_our_node_id());
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
assert!(payment_preimage.is_none());
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, receiver_node_id } => {
assert_eq!(payment_hash_2, *payment_hash);
assert_eq!(amount_msat, 1_000_000);
+ assert_eq!(receiver_node_id.unwrap(), nodes[1].node.get_our_node_id());
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
assert!(payment_preimage.is_none());
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, receiver_node_id } => {
assert_eq!(payment_hash, our_payment_hash);
assert_eq!(amount_msat, 1_000_000);
+ assert_eq!(receiver_node_id.unwrap(), nodes[1].node.get_our_node_id());
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
assert!(payment_preimage.is_none());
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, receiver_node_id } => {
assert_eq!(payment_hash_2, *payment_hash);
assert_eq!(1_000_000, amount_msat);
+ assert_eq!(receiver_node_id.unwrap(), nodes[0].node.get_our_node_id());
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
assert!(payment_preimage.is_none());
_ => panic!("Unexpected event"),
}
match events[1] {
- Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat } => {
+ Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat, receiver_node_id } => {
assert_eq!(payment_hash_3, *payment_hash);
assert_eq!(1_000_000, amount_msat);
+ assert_eq!(receiver_node_id.unwrap(), nodes[0].node.get_our_node_id());
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
assert!(payment_preimage.is_none());
));
}
}
+ let phantom_shared_secret = claimable_htlc.prev_hop.phantom_shared_secret;
+ let mut receiver_node_id = self.our_network_pubkey;
+ if phantom_shared_secret.is_some() {
+ receiver_node_id = self.keys_manager.get_node_id(Recipient::PhantomNode)
+ .expect("Failed to get node_id for phantom node recipient");
+ }
macro_rules! check_total_value {
($payment_data: expr, $payment_preimage: expr) => {{
} else if total_value == $payment_data.total_msat {
htlcs.push(claimable_htlc);
new_events.push(events::Event::PaymentReceived {
+ receiver_node_id: Some(receiver_node_id),
payment_hash,
purpose: purpose(),
amount_msat: total_value,
let purpose = events::PaymentPurpose::SpontaneousPayment(preimage);
e.insert((purpose.clone(), vec![claimable_htlc]));
new_events.push(events::Event::PaymentReceived {
+ receiver_node_id: Some(receiver_node_id),
payment_hash,
amount_msat: outgoing_amt_msat,
purpose,
let mut claimed_any_htlcs = false;
let mut channel_state_lock = self.channel_state.lock().unwrap();
let channel_state = &mut *channel_state_lock;
+ let mut receiver_node_id = Some(self.our_network_pubkey);
for htlc in sources.iter() {
let chan_id = match self.short_to_chan_info.read().unwrap().get(&htlc.prev_hop.short_channel_id) {
Some((_cp_id, chan_id)) => chan_id.clone(),
break;
}
}
+ let phantom_shared_secret = htlc.prev_hop.phantom_shared_secret;
+ if phantom_shared_secret.is_some() {
+ let phantom_pubkey = self.keys_manager.get_node_id(Recipient::PhantomNode)
+ .expect("Failed to get node_id for phantom node recipient");
+ receiver_node_id = Some(phantom_pubkey)
+ }
claimable_amt_msat += htlc.value;
}
if claimed_any_htlcs {
self.pending_events.lock().unwrap().push(events::Event::PaymentClaimed {
+ receiver_node_id,
payment_hash,
purpose: payment_purpose,
amount_msat: claimable_amt_msat,
if let Some((payment_purpose, claimable_htlcs)) = claimable_htlcs.remove(&payment_hash) {
log_info!(args.logger, "Re-claiming HTLCs with payment hash {} as we've released the preimage to a ChannelMonitor!", log_bytes!(payment_hash.0));
let mut claimable_amt_msat = 0;
+ let mut receiver_node_id = Some(our_network_pubkey);
+ let phantom_shared_secret = claimable_htlcs[0].prev_hop.phantom_shared_secret;
+ if phantom_shared_secret.is_some() {
+ let phantom_pubkey = args.keys_manager.get_node_id(Recipient::PhantomNode)
+ .expect("Failed to get node_id for phantom node recipient");
+ receiver_node_id = Some(phantom_pubkey)
+ }
for claimable_htlc in claimable_htlcs {
claimable_amt_msat += claimable_htlc.value;
}
}
pending_events_read.push(events::Event::PaymentClaimed {
+ receiver_node_id,
payment_hash,
purpose: payment_purpose,
amount_msat: claimable_amt_msat,
}
}}
}
-
#[macro_export]
#[cfg(any(test, feature = "_bench_unstable", feature = "_test_utils"))]
macro_rules! expect_payment_received {
($node: expr, $expected_payment_hash: expr, $expected_payment_secret: expr, $expected_recv_value: expr) => {
- expect_payment_received!($node, $expected_payment_hash, $expected_payment_secret, $expected_recv_value, None)
+ expect_payment_received!($node, $expected_payment_hash, $expected_payment_secret, $expected_recv_value, None, $node.node.get_our_node_id())
};
- ($node: expr, $expected_payment_hash: expr, $expected_payment_secret: expr, $expected_recv_value: expr, $expected_payment_preimage: expr) => {
+ ($node: expr, $expected_payment_hash: expr, $expected_payment_secret: expr, $expected_recv_value: expr, $expected_payment_preimage: expr, $expected_receiver_node_id: expr) => {
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, receiver_node_id } => {
assert_eq!($expected_payment_hash, *payment_hash);
assert_eq!($expected_recv_value, amount_msat);
+ assert_eq!($expected_receiver_node_id, receiver_node_id.unwrap());
match purpose {
$crate::util::events::PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
assert_eq!(&$expected_payment_preimage, payment_preimage);
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, receiver_node_id } => {
assert_eq!(our_payment_hash, *payment_hash);
+ assert_eq!(node.node.get_our_node_id(), receiver_node_id.unwrap());
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
assert_eq!(expected_preimage, *payment_preimage);
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, receiver_node_id } => {
assert_eq!(our_payment_hash_21, *payment_hash);
assert_eq!(recv_value_21, amount_msat);
+ assert_eq!(nodes[2].node.get_our_node_id(), receiver_node_id.unwrap());
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
assert!(payment_preimage.is_none());
_ => panic!("Unexpected event"),
}
match events[1] {
- Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat } => {
+ Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat, receiver_node_id } => {
assert_eq!(our_payment_hash_22, *payment_hash);
assert_eq!(recv_value_22, amount_msat);
+ assert_eq!(nodes[2].node.get_our_node_id(), receiver_node_id.unwrap());
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
assert!(payment_preimage.is_none());
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, receiver_node_id } => {
assert_eq!(payment_hash_1, *payment_hash);
assert_eq!(amount_msat, 1_000_000);
+ assert_eq!(receiver_node_id.unwrap(), nodes[1].node.get_our_node_id());
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
assert!(payment_preimage.is_none());
nodes[1].node.process_pending_htlc_forwards();
expect_pending_htlcs_forwardable_ignore!(nodes[1]);
nodes[1].node.process_pending_htlc_forwards();
- expect_payment_received!(nodes[1], payment_hash, payment_secret, recv_amt_msat);
+ expect_payment_received!(nodes[1], payment_hash, payment_secret, recv_amt_msat, None, route.paths[0].last().unwrap().pubkey);
nodes[1].node.fail_htlc_backwards(&payment_hash);
expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash }]);
nodes[1].node.process_pending_htlc_forwards();
/// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds
/// [`ChannelManager::fail_htlc_backwards`]: crate::ln::channelmanager::ChannelManager::fail_htlc_backwards
PaymentReceived {
+ /// The node that received the payment.
+ /// This is useful to identify payments which were received via [phantom node payments].
+ /// This field will always be filled in when the event was generated by LDK versions
+ /// 0.0.113 and above.
+ ///
+ /// [phantom node payments]: crate::chain::keysinterface::PhantomKeysManager
+ receiver_node_id: Option<PublicKey>,
/// The hash for which the preimage should be handed to the ChannelManager. Note that LDK will
/// not stop you from registering duplicate payment hashes for inbound payments.
payment_hash: PaymentHash,
///
/// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds
PaymentClaimed {
+ /// The node that received the payment.
+ /// This is useful to identify payments which were received via [phantom node payments].
+ /// This field will always be filled in when the event was generated by LDK versions
+ /// 0.0.113 and above.
+ ///
+ /// [phantom node payments]: crate::chain::keysinterface::PhantomKeysManager
+ receiver_node_id: Option<PublicKey>,
/// The payment hash of the claimed payment. Note that LDK will not stop you from
/// registering duplicate payment hashes for inbound payments.
payment_hash: PaymentHash,
// 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 receiver_node_id } => {
1u8.write(writer)?;
let mut payment_secret = None;
let payment_preimage;
}
write_tlv_fields!(writer, {
(0, payment_hash, required),
+ (1, receiver_node_id, option),
(2, payment_secret, option),
(4, amount_msat, required),
(6, 0u64, required), // user_payment_id required for compatibility with 0.0.103 and earlier
// We never write the OpenChannelRequest events as, upon disconnection, peers
// drop any channels which have not yet exchanged funding_signed.
},
- &Event::PaymentClaimed { ref payment_hash, ref amount_msat, ref purpose } => {
+ &Event::PaymentClaimed { ref payment_hash, ref amount_msat, ref purpose, ref receiver_node_id } => {
19u8.write(writer)?;
write_tlv_fields!(writer, {
(0, payment_hash, required),
+ (1, receiver_node_id, option),
(2, purpose, required),
(4, amount_msat, required),
});
let mut payment_preimage = None;
let mut payment_secret = None;
let mut amount_msat = 0;
+ let mut receiver_node_id = None;
let mut _user_payment_id = None::<u64>; // For compatibility with 0.0.103 and earlier
read_tlv_fields!(reader, {
(0, payment_hash, required),
+ (1, receiver_node_id, option),
(2, payment_secret, option),
(4, amount_msat, required),
(6, _user_payment_id, option),
None => return Err(msgs::DecodeError::InvalidValue),
};
Ok(Some(Event::PaymentReceived {
+ receiver_node_id,
payment_hash,
amount_msat,
purpose,
let mut payment_hash = PaymentHash([0; 32]);
let mut purpose = None;
let mut amount_msat = 0;
+ let mut receiver_node_id = None;
read_tlv_fields!(reader, {
(0, payment_hash, required),
+ (1, receiver_node_id, option),
(2, purpose, ignorable),
(4, amount_msat, required),
});
if purpose.is_none() { return Ok(None); }
Ok(Some(Event::PaymentClaimed {
+ receiver_node_id,
payment_hash,
purpose: purpose.unwrap(),
amount_msat,