Skip to content

Commit

Permalink
Merge pull request #1856 from tnull/2022-10-expose-channel-id
Browse files Browse the repository at this point in the history
Expose the channel via which we received a payment
  • Loading branch information
TheBlueMatt authored Nov 29, 2022
2 parents 64b9e83 + b1b3666 commit 2c57878
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 31 deletions.
1 change: 1 addition & 0 deletions fuzz/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
user_channel_id: 0, inbound_capacity_msat: 0,
unspendable_punishment_reserve: None,
confirmations_required: None,
confirmations: None,
force_close_spend_delay: None,
is_outbound: true, is_channel_ready: true,
is_usable: true, is_public: true,
Expand Down
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 @@ -200,10 +200,11 @@ 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, receiver_node_id } => {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id, via_user_channel_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());
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 @@ -568,10 +569,11 @@ 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, receiver_node_id } => {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id, via_user_channel_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());
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 @@ -684,10 +686,11 @@ 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, receiver_node_id } => {
Event::PaymentReceived { payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id, via_user_channel_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());
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 @@ -1627,7 +1630,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 @@ -1648,10 +1652,12 @@ 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, receiver_node_id } => {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id, via_user_channel_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());
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 @@ -1663,10 +1669,11 @@ fn test_monitor_update_fail_claim() {
_ => panic!("Unexpected event"),
}
match events[1] {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat, receiver_node_id } => {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id, via_user_channel_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());
assert_eq!(via_channel_id, Some(channel_id));
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
assert!(payment_preimage.is_none());
Expand Down
10 changes: 10 additions & 0 deletions lightning/src/ln/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4495,6 +4495,16 @@ impl<Signer: Sign> Channel<Signer> {
self.funding_tx_confirmed_in
}

/// Returns the current number of confirmations on the funding transaction.
pub fn get_funding_tx_confirmations(&self, height: u32) -> u32 {
if self.funding_tx_confirmation_height == 0 {
// We either haven't seen any confirmation yet, or observed a reorg.
return 0;
}

height.checked_sub(self.funding_tx_confirmation_height).map_or(0, |c| c + 1)
}

fn get_holder_selected_contest_delay(&self) -> u16 {
self.channel_transaction_parameters.holder_selected_contest_delay
}
Expand Down
48 changes: 33 additions & 15 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ pub(super) struct PendingAddHTLCInfo {
prev_short_channel_id: u64,
prev_htlc_id: u64,
prev_funding_outpoint: OutPoint,
prev_user_channel_id: u128,
}

pub(super) enum HTLCForwardInfo {
Expand Down Expand Up @@ -1145,6 +1146,10 @@ pub struct ChannelDetails {
/// [`ChannelHandshakeConfig::minimum_depth`]: crate::util::config::ChannelHandshakeConfig::minimum_depth
/// [`ChannelHandshakeLimits::max_minimum_depth`]: crate::util::config::ChannelHandshakeLimits::max_minimum_depth
pub confirmations_required: Option<u32>,
/// The current number of confirmations on the funding transaction.
///
/// This value will be `None` for objects serialized with LDK versions prior to 0.0.113.
pub confirmations: Option<u32>,
/// The number of blocks (after our commitment transaction confirms) that we will need to wait
/// until we can claim our funds after we force-close the channel. During this time our
/// counterparty is allowed to punish us if we broadcasted a stale state. If our counterparty
Expand Down Expand Up @@ -1693,6 +1698,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
let mut res = Vec::new();
{
let channel_state = self.channel_state.lock().unwrap();
let best_block_height = self.best_block.read().unwrap().height();
res.reserve(channel_state.by_id.len());
for (channel_id, channel) in channel_state.by_id.iter().filter(f) {
let balance = channel.get_available_balances();
Expand Down Expand Up @@ -1729,6 +1735,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
next_outbound_htlc_limit_msat: balance.next_outbound_htlc_limit_msat,
user_channel_id: channel.get_user_id(),
confirmations_required: channel.minimum_depth(),
confirmations: Some(channel.get_funding_tx_confirmations(best_block_height)),
force_close_spend_delay: channel.get_counterparty_selected_contest_delay(),
is_outbound: channel.is_outbound(),
is_channel_ready: channel.is_usable(),
Expand Down Expand Up @@ -3025,7 +3032,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F

let mut new_events = Vec::new();
let mut failed_forwards = Vec::new();
let mut phantom_receives: Vec<(u64, OutPoint, Vec<(PendingHTLCInfo, u64)>)> = Vec::new();
let mut phantom_receives: Vec<(u64, OutPoint, u128, Vec<(PendingHTLCInfo, u64)>)> = Vec::new();
let mut handle_errors = Vec::new();
{
let mut forward_htlcs = HashMap::new();
Expand All @@ -3038,7 +3045,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
for forward_info in pending_forwards.drain(..) {
match forward_info {
HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo {
prev_short_channel_id, prev_htlc_id, prev_funding_outpoint,
prev_short_channel_id, prev_htlc_id, prev_funding_outpoint, prev_user_channel_id,
forward_info: PendingHTLCInfo {
routing, incoming_shared_secret, payment_hash, outgoing_amt_msat,
outgoing_cltv_value, incoming_amt_msat: _
Expand Down Expand Up @@ -3104,7 +3111,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
match next_hop {
onion_utils::Hop::Receive(hop_data) => {
match self.construct_recv_pending_htlc_info(hop_data, incoming_shared_secret, payment_hash, outgoing_amt_msat, outgoing_cltv_value, Some(phantom_shared_secret)) {
Ok(info) => phantom_receives.push((prev_short_channel_id, prev_funding_outpoint, vec![(info, prev_htlc_id)])),
Ok(info) => phantom_receives.push((prev_short_channel_id, prev_funding_outpoint, prev_user_channel_id, vec![(info, prev_htlc_id)])),
Err(ReceiveError { err_code, err_data, msg }) => failed_payment!(msg, err_code, err_data, Some(phantom_shared_secret))
}
},
Expand Down Expand Up @@ -3147,7 +3154,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
for forward_info in pending_forwards.drain(..) {
match forward_info {
HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo {
prev_short_channel_id, prev_htlc_id, prev_funding_outpoint ,
prev_short_channel_id, prev_htlc_id, prev_funding_outpoint, prev_user_channel_id: _,
forward_info: PendingHTLCInfo {
incoming_shared_secret, payment_hash, outgoing_amt_msat, outgoing_cltv_value,
routing: PendingHTLCRouting::Forward { onion_packet, .. }, incoming_amt_msat: _,
Expand Down Expand Up @@ -3274,7 +3281,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
for forward_info in pending_forwards.drain(..) {
match forward_info {
HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo {
prev_short_channel_id, prev_htlc_id, prev_funding_outpoint,
prev_short_channel_id, prev_htlc_id, prev_funding_outpoint, prev_user_channel_id,
forward_info: PendingHTLCInfo {
routing, incoming_shared_secret, payment_hash, outgoing_amt_msat, ..
}
Expand Down Expand Up @@ -3369,12 +3376,15 @@ 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 prev_channel_id = prev_funding_outpoint.to_channel_id();
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,
via_channel_id: Some(prev_channel_id),
via_user_channel_id: Some(prev_user_channel_id),
});
payment_received_generated = true;
} else {
Expand Down Expand Up @@ -3413,11 +3423,14 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
hash_map::Entry::Vacant(e) => {
let purpose = events::PaymentPurpose::SpontaneousPayment(preimage);
e.insert((purpose.clone(), vec![claimable_htlc]));
let prev_channel_id = prev_funding_outpoint.to_channel_id();
new_events.push(events::Event::PaymentReceived {
receiver_node_id: Some(receiver_node_id),
payment_hash,
amount_msat: outgoing_amt_msat,
purpose,
via_channel_id: Some(prev_channel_id),
via_user_channel_id: Some(prev_user_channel_id),
});
},
hash_map::Entry::Occupied(_) => {
Expand Down Expand Up @@ -4389,13 +4402,13 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
commitment_update: Option<msgs::CommitmentUpdate>, order: RAACommitmentOrder,
pending_forwards: Vec<(PendingHTLCInfo, u64)>, funding_broadcastable: Option<Transaction>,
channel_ready: Option<msgs::ChannelReady>, announcement_sigs: Option<msgs::AnnouncementSignatures>)
-> Option<(u64, OutPoint, Vec<(PendingHTLCInfo, u64)>)> {
-> Option<(u64, OutPoint, u128, Vec<(PendingHTLCInfo, u64)>)> {
let mut htlc_forwards = None;

let counterparty_node_id = channel.get_counterparty_node_id();
if !pending_forwards.is_empty() {
htlc_forwards = Some((channel.get_short_channel_id().unwrap_or(channel.outbound_scid_alias()),
channel.get_funding_txo().unwrap(), pending_forwards));
channel.get_funding_txo().unwrap(), channel.get_user_id(), pending_forwards));
}

if let Some(msg) = channel_ready {
Expand Down Expand Up @@ -5056,8 +5069,8 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
}

#[inline]
fn forward_htlcs(&self, per_source_pending_forwards: &mut [(u64, OutPoint, Vec<(PendingHTLCInfo, u64)>)]) {
for &mut (prev_short_channel_id, prev_funding_outpoint, ref mut pending_forwards) in per_source_pending_forwards {
fn forward_htlcs(&self, per_source_pending_forwards: &mut [(u64, OutPoint, u128, Vec<(PendingHTLCInfo, u64)>)]) {
for &mut (prev_short_channel_id, prev_funding_outpoint, prev_user_channel_id, ref mut pending_forwards) in per_source_pending_forwards {
let mut forward_event = None;
if !pending_forwards.is_empty() {
let mut forward_htlcs = self.forward_htlcs.lock().unwrap();
Expand All @@ -5072,11 +5085,11 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
}) {
hash_map::Entry::Occupied(mut entry) => {
entry.get_mut().push(HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo {
prev_short_channel_id, prev_funding_outpoint, prev_htlc_id, forward_info }));
prev_short_channel_id, prev_funding_outpoint, prev_htlc_id, prev_user_channel_id, forward_info }));
},
hash_map::Entry::Vacant(entry) => {
entry.insert(vec!(HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo {
prev_short_channel_id, prev_funding_outpoint, prev_htlc_id, forward_info })));
prev_short_channel_id, prev_funding_outpoint, prev_htlc_id, prev_user_channel_id, forward_info })));
}
}
}
Expand Down Expand Up @@ -5135,21 +5148,22 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
raa_updates.finalized_claimed_htlcs,
chan.get().get_short_channel_id()
.unwrap_or(chan.get().outbound_scid_alias()),
chan.get().get_funding_txo().unwrap()))
chan.get().get_funding_txo().unwrap(),
chan.get().get_user_id()))
},
hash_map::Entry::Vacant(_) => break Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id))
}
};
self.fail_holding_cell_htlcs(htlcs_to_fail, msg.channel_id, counterparty_node_id);
match res {
Ok((pending_forwards, mut pending_failures, finalized_claim_htlcs,
short_channel_id, channel_outpoint)) =>
short_channel_id, channel_outpoint, user_channel_id)) =>
{
for failure in pending_failures.drain(..) {
let receiver = HTLCDestination::NextHopChannel { node_id: Some(*counterparty_node_id), channel_id: channel_outpoint.to_channel_id() };
self.fail_htlc_backwards_internal(failure.0, &failure.1, failure.2, receiver);
}
self.forward_htlcs(&mut [(short_channel_id, channel_outpoint, pending_forwards)]);
self.forward_htlcs(&mut [(short_channel_id, channel_outpoint, user_channel_id, pending_forwards)]);
self.finalize_claims(finalized_claim_htlcs);
Ok(())
},
Expand Down Expand Up @@ -6127,7 +6141,7 @@ where
}
}

impl<M: Deref , T: Deref , K: Deref , F: Deref , L: Deref >
impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref >
ChannelMessageHandler for ChannelManager<M, T, K, F, L>
where M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
T::Target: BroadcasterInterface,
Expand Down Expand Up @@ -6459,6 +6473,7 @@ impl Writeable for ChannelDetails {
(6, self.funding_txo, option),
(7, self.config, option),
(8, self.short_channel_id, option),
(9, self.confirmations, option),
(10, self.channel_value_satoshis, required),
(12, self.unspendable_punishment_reserve, option),
(14, user_channel_id_low, required),
Expand Down Expand Up @@ -6493,6 +6508,7 @@ impl Readable for ChannelDetails {
(6, funding_txo, option),
(7, config, option),
(8, short_channel_id, option),
(9, confirmations, option),
(10, channel_value_satoshis, required),
(12, unspendable_punishment_reserve, option),
(14, user_channel_id_low, required),
Expand Down Expand Up @@ -6536,6 +6552,7 @@ impl Readable for ChannelDetails {
next_outbound_htlc_limit_msat: next_outbound_htlc_limit_msat.0.unwrap(),
inbound_capacity_msat: inbound_capacity_msat.0.unwrap(),
confirmations_required,
confirmations,
force_close_spend_delay,
is_outbound: is_outbound.0.unwrap(),
is_channel_ready: is_channel_ready.0.unwrap(),
Expand Down Expand Up @@ -6799,6 +6816,7 @@ impl_writeable_tlv_based_enum!(HTLCFailReason,

impl_writeable_tlv_based!(PendingAddHTLCInfo, {
(0, forward_info, required),
(1, prev_user_channel_id, (default_value, 0)),
(2, prev_short_channel_id, required),
(4, prev_htlc_id, required),
(6, prev_funding_outpoint, required),
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 @@ -1479,7 +1479,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, receiver_node_id } => {
$crate::util::events::Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id: _, via_user_channel_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());
Expand Down Expand Up @@ -1774,7 +1774,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, receiver_node_id } => {
Event::PaymentReceived { ref payment_hash, ref purpose, amount_msat, receiver_node_id, ref via_channel_id, ref via_user_channel_id } => {
assert_eq!(our_payment_hash, *payment_hash);
assert_eq!(node.node.get_our_node_id(), receiver_node_id.unwrap());
match &purpose {
Expand All @@ -1788,6 +1788,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
Loading

0 comments on commit 2c57878

Please sign in to comment.