Skip to content

Commit 6e803a5

Browse files
committed
Impl Base AMP in the receive pipeline and expose payment_secret
Sadly a huge diff here, but almost all of it is changing the method signatures for sending/receiving/failing HTLCs and the PaymentReceived event, which all now need to expose an Option<[u8; 32]> for the payment_secret. It doesn't yet properly fail back pending HTLCs when the full AMP payment is never received (which should result in accidental channel force-closures). Further, as sending AMP payments is not yet supported, the only test here is a simple single-path payment with a payment_secret in it.
1 parent a926073 commit 6e803a5

File tree

8 files changed

+257
-162
lines changed

8 files changed

+257
-162
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ pub fn do_test(data: &[u8]) {
419419
fee_msat: 5000000,
420420
cltv_expiry_delta: 200,
421421
}],
422-
}, PaymentHash(payment_hash.into_inner())) {
422+
}, PaymentHash(payment_hash.into_inner()), None) {
423423
// Probably ran out of funds
424424
test_return!();
425425
}
@@ -443,7 +443,7 @@ pub fn do_test(data: &[u8]) {
443443
fee_msat: 5000000,
444444
cltv_expiry_delta: 200,
445445
}],
446-
}, PaymentHash(payment_hash.into_inner())) {
446+
}, PaymentHash(payment_hash.into_inner()), None) {
447447
// Probably ran out of funds
448448
test_return!();
449449
}
@@ -604,9 +604,9 @@ pub fn do_test(data: &[u8]) {
604604
events::Event::PaymentReceived { payment_hash, .. } => {
605605
if claim_set.insert(payment_hash.0) {
606606
if $fail {
607-
assert!(nodes[$node].fail_htlc_backwards(&payment_hash));
607+
assert!(nodes[$node].fail_htlc_backwards(&payment_hash, &None));
608608
} else {
609-
assert!(nodes[$node].claim_funds(PaymentPreimage(payment_hash.0), 5_000_000));
609+
assert!(nodes[$node].claim_funds(PaymentPreimage(payment_hash.0), &None, 5_000_000));
610610
}
611611
}
612612
},

fuzz/src/full_stack.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
335335
}, our_network_key, &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0], Arc::clone(&logger)));
336336

337337
let mut should_forward = false;
338-
let mut payments_received: Vec<(PaymentHash, u64)> = Vec::new();
338+
let mut payments_received: Vec<(PaymentHash, Option<[u8; 32]>, u64)> = Vec::new();
339339
let mut payments_sent = 0;
340340
let mut pending_funding_generation: Vec<([u8; 32], u64, Script)> = Vec::new();
341341
let mut pending_funding_signatures = HashMap::new();
@@ -393,7 +393,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
393393
sha.input(&payment_hash.0[..]);
394394
payment_hash.0 = Sha256::from_engine(sha).into_inner();
395395
payments_sent += 1;
396-
match channelmanager.send_payment(route, payment_hash) {
396+
match channelmanager.send_payment(route, payment_hash, None) {
397397
Ok(_) => {},
398398
Err(_) => return,
399399
}
@@ -420,23 +420,23 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
420420
}
421421
},
422422
8 => {
423-
for (payment, amt) in payments_received.drain(..) {
423+
for (payment, payment_secret, amt) in payments_received.drain(..) {
424424
// SHA256 is defined as XOR of all input bytes placed in the first byte, and 0s
425425
// for the remaining bytes. Thus, if not all remaining bytes are 0s we cannot
426426
// fulfill this HTLC, but if they are, we can just take the first byte and
427427
// place that anywhere in our preimage.
428428
if &payment.0[1..] != &[0; 31] {
429-
channelmanager.fail_htlc_backwards(&payment);
429+
channelmanager.fail_htlc_backwards(&payment, &payment_secret);
430430
} else {
431431
let mut payment_preimage = PaymentPreimage([0; 32]);
432432
payment_preimage.0[0] = payment.0[0];
433-
channelmanager.claim_funds(payment_preimage, amt);
433+
channelmanager.claim_funds(payment_preimage, &payment_secret, amt);
434434
}
435435
}
436436
},
437437
9 => {
438-
for (payment, _) in payments_received.drain(..) {
439-
channelmanager.fail_htlc_backwards(&payment);
438+
for (payment, payment_secret, _) in payments_received.drain(..) {
439+
channelmanager.fail_htlc_backwards(&payment, &payment_secret);
440440
}
441441
},
442442
10 => {
@@ -510,9 +510,9 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
510510
Event::FundingBroadcastSafe { funding_txo, .. } => {
511511
pending_funding_relay.push(pending_funding_signatures.remove(&funding_txo).unwrap());
512512
},
513-
Event::PaymentReceived { payment_hash, amt } => {
513+
Event::PaymentReceived { payment_hash, payment_secret, amt } => {
514514
//TODO: enhance by fetching random amounts from fuzz input?
515-
payments_received.push((payment_hash, amt));
515+
payments_received.push((payment_hash, payment_secret, amt));
516516
},
517517
Event::PaymentSent {..} => {},
518518
Event::PaymentFailed {..} => {},

lightning/src/ln/chanmon_update_fail_tests.rs

Lines changed: 34 additions & 31 deletions
Large diffs are not rendered by default.

lightning/src/ln/channelmanager.rs

Lines changed: 66 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -282,11 +282,14 @@ pub(super) struct ChannelHolder<ChanSigner: ChannelKeys> {
282282
/// guarantees are made about the existence of a channel with the short id here, nor the short
283283
/// ids in the PendingHTLCInfo!
284284
pub(super) forward_htlcs: HashMap<u64, Vec<HTLCForwardInfo>>,
285-
/// Tracks things that were to us and can be failed/claimed by the user
285+
/// (payment_hash, payment_secret) -> Vec<HTLCs> for tracking things that
286+
/// were to us and can be failed/claimed by the user
286287
/// Note that while this is held in the same mutex as the channels themselves, no consistency
287288
/// guarantees are made about the channels given here actually existing anymore by the time you
288289
/// go to read them!
289-
claimable_htlcs: HashMap<PaymentHash, Vec<ClaimableHTLC>>,
290+
/// TODO: We need to time out HTLCs sitting here which are waiting on other AMP HTLCs to
291+
/// arrive.
292+
claimable_htlcs: HashMap<(PaymentHash, Option<[u8; 32]>), Vec<ClaimableHTLC>>,
290293
/// Messages to send to peers - pushed to in the same lock that they are generated in (except
291294
/// for broadcast messages, where ordering isn't as strict).
292295
pub(super) pending_msg_events: Vec<events::MessageSendEvent>,
@@ -295,7 +298,7 @@ pub(super) struct MutChannelHolder<'a, ChanSigner: ChannelKeys + 'a> {
295298
pub(super) by_id: &'a mut HashMap<[u8; 32], Channel<ChanSigner>>,
296299
pub(super) short_to_id: &'a mut HashMap<u64, [u8; 32]>,
297300
pub(super) forward_htlcs: &'a mut HashMap<u64, Vec<HTLCForwardInfo>>,
298-
claimable_htlcs: &'a mut HashMap<PaymentHash, Vec<ClaimableHTLC>>,
301+
claimable_htlcs: &'a mut HashMap<(PaymentHash, Option<[u8; 32]>), Vec<ClaimableHTLC>>,
299302
pub(super) pending_msg_events: &'a mut Vec<events::MessageSendEvent>,
300303
}
301304
impl<ChanSigner: ChannelKeys> ChannelHolder<ChanSigner> {
@@ -1195,7 +1198,14 @@ impl<ChanSigner: ChannelKeys> ChannelManager<ChanSigner> {
11951198
/// In case of APIError::MonitorUpdateFailed, the commitment update has been irrevocably
11961199
/// committed on our end and we're just waiting for a monitor update to send it. Do NOT retry
11971200
/// the payment via a different route unless you intend to pay twice!
1198-
pub fn send_payment(&self, route: Route, payment_hash: PaymentHash) -> Result<(), APIError> {
1201+
///
1202+
/// payment_secret is unrelated to payment_hash (or PaymentPreimage) and exists to authenticate
1203+
/// the sender to the recipient and prevent payment-probing (deanonymization) attacks. For
1204+
/// newer nodes, it will be provided to you in the invoice. If you do not have one, the Route
1205+
/// must not contain multiple paths as otherwise the multipath data cannot be sent.
1206+
/// If a payment_secret *is* provided, we assume that the invoice had the basic_mpp feature bit
1207+
/// set (either as required or as available).
1208+
pub fn send_payment(&self, route: Route, payment_hash: PaymentHash, payment_secret: Option<&[u8; 32]>) -> Result<(), APIError> {
11991209
if route.hops.len() < 1 || route.hops.len() > 20 {
12001210
return Err(APIError::RouteError{err: "Route didn't go anywhere/had bogus size"});
12011211
}
@@ -1212,7 +1222,7 @@ impl<ChanSigner: ChannelKeys> ChannelManager<ChanSigner> {
12121222

12131223
let onion_keys = secp_call!(onion_utils::construct_onion_keys(&self.secp_ctx, &route, &session_priv),
12141224
APIError::RouteError{err: "Pubkey along hop was maliciously selected"});
1215-
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route, cur_height)?;
1225+
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route, payment_secret, cur_height)?;
12161226
if onion_utils::route_size_insane(&onion_payloads) {
12171227
return Err(APIError::RouteError{err: "Route had too large size once"});
12181228
}
@@ -1423,7 +1433,9 @@ impl<ChanSigner: ChannelKeys> ChannelManager<ChanSigner> {
14231433
htlc_id: prev_htlc_id,
14241434
incoming_packet_shared_secret: forward_info.incoming_shared_secret,
14251435
});
1426-
failed_forwards.push((htlc_source, forward_info.payment_hash, 0x4000 | 10, None));
1436+
failed_forwards.push((htlc_source, forward_info.payment_hash,
1437+
HTLCFailReason::Reason { failure_code: 0x1000 | 7, data: Vec::new() }
1438+
));
14271439
},
14281440
HTLCForwardInfo::FailHTLC { .. } => {
14291441
// Channel went away before we could fail it. This implies
@@ -1459,7 +1471,9 @@ impl<ChanSigner: ChannelKeys> ChannelManager<ChanSigner> {
14591471
panic!("Stated return value requirements in send_htlc() were not met");
14601472
}
14611473
let chan_update = self.get_channel_update(chan.get()).unwrap();
1462-
failed_forwards.push((htlc_source, payment_hash, 0x1000 | 7, Some(chan_update)));
1474+
failed_forwards.push((htlc_source, payment_hash,
1475+
HTLCFailReason::Reason { failure_code: 0x1000 | 7, data: chan_update.encode_with_len() }
1476+
));
14631477
continue;
14641478
},
14651479
Ok(update_add) => {
@@ -1568,15 +1582,48 @@ impl<ChanSigner: ChannelKeys> ChannelManager<ChanSigner> {
15681582
htlc_id: prev_htlc_id,
15691583
incoming_packet_shared_secret: incoming_shared_secret,
15701584
};
1571-
channel_state.claimable_htlcs.entry(payment_hash).or_insert(Vec::new()).push(ClaimableHTLC {
1585+
1586+
let mut total_value = 0;
1587+
let htlcs = channel_state.claimable_htlcs.entry((payment_hash, if let &Some(ref data) = &payment_data {
1588+
Some(data.payment_secret.clone()) } else { None }))
1589+
.or_insert(Vec::new());
1590+
htlcs.push(ClaimableHTLC {
15721591
src: prev_hop_data,
15731592
value: amt_to_forward,
1574-
payment_data,
1575-
});
1576-
new_events.push(events::Event::PaymentReceived {
1577-
payment_hash: payment_hash,
1578-
amt: amt_to_forward,
1593+
payment_data: payment_data.clone(),
15791594
});
1595+
if let &Some(ref data) = &payment_data {
1596+
for htlc in htlcs.iter() {
1597+
total_value += htlc.value;
1598+
if htlc.payment_data.as_ref().unwrap().total_msat != data.total_msat {
1599+
total_value = msgs::MAX_VALUE_MSAT;
1600+
}
1601+
if total_value >= msgs::MAX_VALUE_MSAT { break; }
1602+
}
1603+
if total_value >= msgs::MAX_VALUE_MSAT {
1604+
for htlc in htlcs.iter() {
1605+
failed_forwards.push((HTLCSource::PreviousHopData(HTLCPreviousHopData {
1606+
short_channel_id: htlc.src.short_channel_id,
1607+
htlc_id: htlc.src.htlc_id,
1608+
incoming_packet_shared_secret: htlc.src.incoming_packet_shared_secret,
1609+
}), payment_hash,
1610+
HTLCFailReason::Reason { failure_code: 0x4000 | 15, data: byte_utils::be64_to_array(htlc.value).to_vec() }
1611+
));
1612+
}
1613+
} else if total_value >= data.total_msat {
1614+
new_events.push(events::Event::PaymentReceived {
1615+
payment_hash: payment_hash,
1616+
payment_secret: Some(data.payment_secret),
1617+
amt: total_value,
1618+
});
1619+
}
1620+
} else {
1621+
new_events.push(events::Event::PaymentReceived {
1622+
payment_hash: payment_hash,
1623+
payment_secret: None,
1624+
amt: amt_to_forward,
1625+
});
1626+
}
15801627
},
15811628
HTLCForwardInfo::AddHTLC { .. } => {
15821629
panic!("short_channel_id == 0 should imply any pending_forward entries are of type Receive");
@@ -1590,11 +1637,8 @@ impl<ChanSigner: ChannelKeys> ChannelManager<ChanSigner> {
15901637
}
15911638
}
15921639

1593-
for (htlc_source, payment_hash, failure_code, update) in failed_forwards.drain(..) {
1594-
match update {
1595-
None => self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), htlc_source, &payment_hash, HTLCFailReason::Reason { failure_code, data: Vec::new() }),
1596-
Some(chan_update) => self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), htlc_source, &payment_hash, HTLCFailReason::Reason { failure_code, data: chan_update.encode_with_len() }),
1597-
};
1640+
for (htlc_source, payment_hash, failure_reason) in failed_forwards.drain(..) {
1641+
self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), htlc_source, &payment_hash, failure_reason);
15981642
}
15991643

16001644
if handle_errors.len() > 0 {
@@ -1639,11 +1683,11 @@ impl<ChanSigner: ChannelKeys> ChannelManager<ChanSigner> {
16391683
/// along the path (including in our own channel on which we received it).
16401684
/// Returns false if no payment was found to fail backwards, true if the process of failing the
16411685
/// HTLC backwards has been started.
1642-
pub fn fail_htlc_backwards(&self, payment_hash: &PaymentHash) -> bool {
1686+
pub fn fail_htlc_backwards(&self, payment_hash: &PaymentHash, payment_secret: &Option<[u8; 32]>) -> bool {
16431687
let _ = self.total_consistency_lock.read().unwrap();
16441688

16451689
let mut channel_state = Some(self.channel_state.lock().unwrap());
1646-
let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(payment_hash);
1690+
let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(&(*payment_hash, *payment_secret));
16471691
if let Some(mut sources) = removed_source {
16481692
for htlc in sources.drain(..) {
16491693
if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap()); }
@@ -1765,13 +1809,13 @@ impl<ChanSigner: ChannelKeys> ChannelManager<ChanSigner> {
17651809
/// motivated attackers.
17661810
///
17671811
/// May panic if called except in response to a PaymentReceived event.
1768-
pub fn claim_funds(&self, payment_preimage: PaymentPreimage, expected_amount: u64) -> bool {
1812+
pub fn claim_funds(&self, payment_preimage: PaymentPreimage, payment_secret: &Option<[u8; 32]>, expected_amount: u64) -> bool {
17691813
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
17701814

17711815
let _ = self.total_consistency_lock.read().unwrap();
17721816

17731817
let mut channel_state = Some(self.channel_state.lock().unwrap());
1774-
let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(&payment_hash);
1818+
let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(&(payment_hash, *payment_secret));
17751819
if let Some(mut sources) = removed_source {
17761820
for htlc in sources.drain(..) {
17771821
if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap()); }

lightning/src/ln/functional_test_utils.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -602,8 +602,9 @@ macro_rules! expect_payment_received {
602602
let events = $node.node.get_and_clear_pending_events();
603603
assert_eq!(events.len(), 1);
604604
match events[0] {
605-
Event::PaymentReceived { ref payment_hash, amt } => {
605+
Event::PaymentReceived { ref payment_hash, ref payment_secret, amt } => {
606606
assert_eq!($expected_payment_hash, *payment_hash);
607+
assert_eq!(*payment_secret, None);
607608
assert_eq!($expected_recv_value, amt);
608609
},
609610
_ => panic!("Unexpected event"),
@@ -624,9 +625,9 @@ macro_rules! expect_payment_sent {
624625
}
625626
}
626627

627-
pub fn send_along_route_with_hash(origin_node: &Node, route: Route, expected_route: &[&Node], recv_value: u64, our_payment_hash: PaymentHash) {
628+
pub fn send_along_route_with_secret(origin_node: &Node, route: Route, expected_route: &[&Node], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: Option<[u8; 32]>) {
628629
let mut payment_event = {
629-
origin_node.node.send_payment(route, our_payment_hash).unwrap();
630+
origin_node.node.send_payment(route, our_payment_hash, our_payment_secret.as_ref()).unwrap();
630631
check_added_monitors!(origin_node, 1);
631632

632633
let mut events = origin_node.node.get_and_clear_pending_msg_events();
@@ -648,8 +649,9 @@ pub fn send_along_route_with_hash(origin_node: &Node, route: Route, expected_rou
648649
let events_2 = node.node.get_and_clear_pending_events();
649650
assert_eq!(events_2.len(), 1);
650651
match events_2[0] {
651-
Event::PaymentReceived { ref payment_hash, amt } => {
652+
Event::PaymentReceived { ref payment_hash, ref payment_secret, amt } => {
652653
assert_eq!(our_payment_hash, *payment_hash);
654+
assert_eq!(our_payment_secret, *payment_secret);
653655
assert_eq!(amt, recv_value);
654656
},
655657
_ => panic!("Unexpected event"),
@@ -666,14 +668,18 @@ pub fn send_along_route_with_hash(origin_node: &Node, route: Route, expected_rou
666668
}
667669
}
668670

671+
pub fn send_along_route_with_hash(origin_node: &Node, route: Route, expected_route: &[&Node], recv_value: u64, our_payment_hash: PaymentHash) {
672+
send_along_route_with_secret(origin_node, route, expected_route, recv_value, our_payment_hash, None);
673+
}
674+
669675
pub fn send_along_route(origin_node: &Node, route: Route, expected_route: &[&Node], recv_value: u64) -> (PaymentPreimage, PaymentHash) {
670676
let (our_payment_preimage, our_payment_hash) = get_payment_preimage_hash!(origin_node);
671677
send_along_route_with_hash(origin_node, route, expected_route, recv_value, our_payment_hash);
672678
(our_payment_preimage, our_payment_hash)
673679
}
674680

675-
pub fn claim_payment_along_route(origin_node: &Node, expected_route: &[&Node], skip_last: bool, our_payment_preimage: PaymentPreimage, expected_amount: u64) {
676-
assert!(expected_route.last().unwrap().node.claim_funds(our_payment_preimage, expected_amount));
681+
pub fn claim_payment_along_route_with_secret(origin_node: &Node, expected_route: &[&Node], skip_last: bool, our_payment_preimage: PaymentPreimage, our_payment_secret: Option<[u8; 32]>, expected_amount: u64) {
682+
assert!(expected_route.last().unwrap().node.claim_funds(our_payment_preimage, &our_payment_secret, expected_amount));
677683
check_added_monitors!(expected_route.last().unwrap(), 1);
678684

679685
let mut next_msgs: Option<(msgs::UpdateFulfillHTLC, msgs::CommitmentSigned)> = None;
@@ -750,6 +756,10 @@ pub fn claim_payment_along_route(origin_node: &Node, expected_route: &[&Node], s
750756
}
751757
}
752758

759+
pub fn claim_payment_along_route(origin_node: &Node, expected_route: &[&Node], skip_last: bool, our_payment_preimage: PaymentPreimage, expected_amount: u64) {
760+
claim_payment_along_route_with_secret(origin_node, expected_route, skip_last, our_payment_preimage, None, expected_amount);
761+
}
762+
753763
pub fn claim_payment(origin_node: &Node, expected_route: &[&Node], our_payment_preimage: PaymentPreimage, expected_amount: u64) {
754764
claim_payment_along_route(origin_node, expected_route, false, our_payment_preimage, expected_amount);
755765
}
@@ -775,7 +785,7 @@ pub fn route_over_limit(origin_node: &Node, expected_route: &[&Node], recv_value
775785

776786
let (_, our_payment_hash) = get_payment_preimage_hash!(origin_node);
777787

778-
let err = origin_node.node.send_payment(route, our_payment_hash).err().unwrap();
788+
let err = origin_node.node.send_payment(route, our_payment_hash, None).err().unwrap();
779789
match err {
780790
APIError::ChannelUnavailable{err} => assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept"),
781791
_ => panic!("Unknown error variants"),
@@ -788,7 +798,7 @@ pub fn send_payment(origin: &Node, expected_route: &[&Node], recv_value: u64, ex
788798
}
789799

790800
pub fn fail_payment_along_route(origin_node: &Node, expected_route: &[&Node], skip_last: bool, our_payment_hash: PaymentHash) {
791-
assert!(expected_route.last().unwrap().node.fail_htlc_backwards(&our_payment_hash));
801+
assert!(expected_route.last().unwrap().node.fail_htlc_backwards(&our_payment_hash, &None));
792802
expect_pending_htlcs_forwardable!(expected_route.last().unwrap());
793803
check_added_monitors!(expected_route.last().unwrap(), 1);
794804

0 commit comments

Comments
 (0)