Skip to content

Commit 884ca16

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 ba2f6cb commit 884ca16

File tree

8 files changed

+259
-161
lines changed

8 files changed

+259
-161
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ pub fn do_test(data: &[u8]) {
422422
fee_msat: 5000000,
423423
cltv_expiry_delta: 200,
424424
}],
425-
}, PaymentHash(payment_hash.into_inner())) {
425+
}, PaymentHash(payment_hash.into_inner()), None) {
426426
// Probably ran out of funds
427427
test_return!();
428428
}
@@ -446,7 +446,7 @@ pub fn do_test(data: &[u8]) {
446446
fee_msat: 5000000,
447447
cltv_expiry_delta: 200,
448448
}],
449-
}, PaymentHash(payment_hash.into_inner())) {
449+
}, PaymentHash(payment_hash.into_inner()), None) {
450450
// Probably ran out of funds
451451
test_return!();
452452
}
@@ -607,9 +607,9 @@ pub fn do_test(data: &[u8]) {
607607
events::Event::PaymentReceived { payment_hash, .. } => {
608608
if claim_set.insert(payment_hash.0) {
609609
if $fail {
610-
assert!(nodes[$node].fail_htlc_backwards(&payment_hash));
610+
assert!(nodes[$node].fail_htlc_backwards(&payment_hash, &None));
611611
} else {
612-
assert!(nodes[$node].claim_funds(PaymentPreimage(payment_hash.0), 5_000_000));
612+
assert!(nodes[$node].claim_funds(PaymentPreimage(payment_hash.0), &None, 5_000_000));
613613
}
614614
}
615615
},

fuzz/src/full_stack.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
343343
}, 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)));
344344

345345
let mut should_forward = false;
346-
let mut payments_received: Vec<(PaymentHash, u64)> = Vec::new();
346+
let mut payments_received: Vec<(PaymentHash, Option<[u8; 32]>, u64)> = Vec::new();
347347
let mut payments_sent = 0;
348348
let mut pending_funding_generation: Vec<([u8; 32], u64, Script)> = Vec::new();
349349
let mut pending_funding_signatures = HashMap::new();
@@ -401,7 +401,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
401401
sha.input(&payment_hash.0[..]);
402402
payment_hash.0 = Sha256::from_engine(sha).into_inner();
403403
payments_sent += 1;
404-
match channelmanager.send_payment(route, payment_hash) {
404+
match channelmanager.send_payment(route, payment_hash, None) {
405405
Ok(_) => {},
406406
Err(_) => return,
407407
}
@@ -428,23 +428,23 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
428428
}
429429
},
430430
8 => {
431-
for (payment, amt) in payments_received.drain(..) {
431+
for (payment, payment_secret, amt) in payments_received.drain(..) {
432432
// SHA256 is defined as XOR of all input bytes placed in the first byte, and 0s
433433
// for the remaining bytes. Thus, if not all remaining bytes are 0s we cannot
434434
// fulfill this HTLC, but if they are, we can just take the first byte and
435435
// place that anywhere in our preimage.
436436
if &payment.0[1..] != &[0; 31] {
437-
channelmanager.fail_htlc_backwards(&payment);
437+
channelmanager.fail_htlc_backwards(&payment, &payment_secret);
438438
} else {
439439
let mut payment_preimage = PaymentPreimage([0; 32]);
440440
payment_preimage.0[0] = payment.0[0];
441-
channelmanager.claim_funds(payment_preimage, amt);
441+
channelmanager.claim_funds(payment_preimage, &payment_secret, amt);
442442
}
443443
}
444444
},
445445
9 => {
446-
for (payment, _) in payments_received.drain(..) {
447-
channelmanager.fail_htlc_backwards(&payment);
446+
for (payment, payment_secret, _) in payments_received.drain(..) {
447+
channelmanager.fail_htlc_backwards(&payment, &payment_secret);
448448
}
449449
},
450450
10 => {
@@ -524,9 +524,9 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
524524
Event::FundingBroadcastSafe { funding_txo, .. } => {
525525
pending_funding_relay.push(pending_funding_signatures.remove(&funding_txo).unwrap());
526526
},
527-
Event::PaymentReceived { payment_hash, amt } => {
527+
Event::PaymentReceived { payment_hash, payment_secret, amt } => {
528528
//TODO: enhance by fetching random amounts from fuzz input?
529-
payments_received.push((payment_hash, amt));
529+
payments_received.push((payment_hash, payment_secret, amt));
530530
},
531531
Event::PaymentSent {..} => {},
532532
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: 65 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -284,11 +284,14 @@ pub(super) struct ChannelHolder<ChanSigner: ChannelKeys> {
284284
/// guarantees are made about the existence of a channel with the short id here, nor the short
285285
/// ids in the PendingHTLCInfo!
286286
pub(super) forward_htlcs: HashMap<u64, Vec<HTLCForwardInfo>>,
287-
/// Tracks things that were to us and can be failed/claimed by the user
287+
/// (payment_hash, payment_secret) -> Vec<HTLCs> for tracking things that
288+
/// were to us and can be failed/claimed by the user
288289
/// Note that while this is held in the same mutex as the channels themselves, no consistency
289290
/// guarantees are made about the channels given here actually existing anymore by the time you
290291
/// go to read them!
291-
claimable_htlcs: HashMap<PaymentHash, Vec<ClaimableHTLC>>,
292+
/// TODO: We need to time out HTLCs sitting here which are waiting on other AMP HTLCs to
293+
/// arrive.
294+
claimable_htlcs: HashMap<(PaymentHash, Option<[u8; 32]>), Vec<ClaimableHTLC>>,
292295
/// Messages to send to peers - pushed to in the same lock that they are generated in (except
293296
/// for broadcast messages, where ordering isn't as strict).
294297
pub(super) pending_msg_events: Vec<events::MessageSendEvent>,
@@ -1180,7 +1183,14 @@ impl<ChanSigner: ChannelKeys, M: Deref> ChannelManager<ChanSigner, M> where M::T
11801183
/// In case of APIError::MonitorUpdateFailed, the commitment update has been irrevocably
11811184
/// committed on our end and we're just waiting for a monitor update to send it. Do NOT retry
11821185
/// the payment via a different route unless you intend to pay twice!
1183-
pub fn send_payment(&self, route: Route, payment_hash: PaymentHash) -> Result<(), APIError> {
1186+
///
1187+
/// payment_secret is unrelated to payment_hash (or PaymentPreimage) and exists to authenticate
1188+
/// the sender to the recipient and prevent payment-probing (deanonymization) attacks. For
1189+
/// newer nodes, it will be provided to you in the invoice. If you do not have one, the Route
1190+
/// must not contain multiple paths as otherwise the multipath data cannot be sent.
1191+
/// If a payment_secret *is* provided, we assume that the invoice had the basic_mpp feature bit
1192+
/// set (either as required or as available).
1193+
pub fn send_payment(&self, route: Route, payment_hash: PaymentHash, payment_secret: Option<&[u8; 32]>) -> Result<(), APIError> {
11841194
if route.hops.len() < 1 || route.hops.len() > 20 {
11851195
return Err(APIError::RouteError{err: "Route didn't go anywhere/had bogus size"});
11861196
}
@@ -1197,7 +1207,7 @@ impl<ChanSigner: ChannelKeys, M: Deref> ChannelManager<ChanSigner, M> where M::T
11971207

11981208
let onion_keys = secp_call!(onion_utils::construct_onion_keys(&self.secp_ctx, &route, &session_priv),
11991209
APIError::RouteError{err: "Pubkey along hop was maliciously selected"});
1200-
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route, cur_height)?;
1210+
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route, payment_secret, cur_height)?;
12011211
if onion_utils::route_size_insane(&onion_payloads) {
12021212
return Err(APIError::RouteError{err: "Route size too large considering onion data"});
12031213
}
@@ -1413,7 +1423,9 @@ impl<ChanSigner: ChannelKeys, M: Deref> ChannelManager<ChanSigner, M> where M::T
14131423
htlc_id: prev_htlc_id,
14141424
incoming_packet_shared_secret: forward_info.incoming_shared_secret,
14151425
});
1416-
failed_forwards.push((htlc_source, forward_info.payment_hash, 0x4000 | 10, None));
1426+
failed_forwards.push((htlc_source, forward_info.payment_hash,
1427+
HTLCFailReason::Reason { failure_code: 0x1000 | 7, data: Vec::new() }
1428+
));
14171429
},
14181430
HTLCForwardInfo::FailHTLC { .. } => {
14191431
// Channel went away before we could fail it. This implies
@@ -1449,7 +1461,9 @@ impl<ChanSigner: ChannelKeys, M: Deref> ChannelManager<ChanSigner, M> where M::T
14491461
panic!("Stated return value requirements in send_htlc() were not met");
14501462
}
14511463
let chan_update = self.get_channel_update(chan.get()).unwrap();
1452-
failed_forwards.push((htlc_source, payment_hash, 0x1000 | 7, Some(chan_update)));
1464+
failed_forwards.push((htlc_source, payment_hash,
1465+
HTLCFailReason::Reason { failure_code: 0x1000 | 7, data: chan_update.encode_with_len() }
1466+
));
14531467
continue;
14541468
},
14551469
Ok(update_add) => {
@@ -1558,15 +1572,48 @@ impl<ChanSigner: ChannelKeys, M: Deref> ChannelManager<ChanSigner, M> where M::T
15581572
htlc_id: prev_htlc_id,
15591573
incoming_packet_shared_secret: incoming_shared_secret,
15601574
};
1561-
channel_state.claimable_htlcs.entry(payment_hash).or_insert(Vec::new()).push(ClaimableHTLC {
1575+
1576+
let mut total_value = 0;
1577+
let htlcs = channel_state.claimable_htlcs.entry((payment_hash, if let &Some(ref data) = &payment_data {
1578+
Some(data.payment_secret.clone()) } else { None }))
1579+
.or_insert(Vec::new());
1580+
htlcs.push(ClaimableHTLC {
15621581
src: prev_hop_data,
15631582
value: amt_to_forward,
1564-
payment_data,
1565-
});
1566-
new_events.push(events::Event::PaymentReceived {
1567-
payment_hash: payment_hash,
1568-
amt: amt_to_forward,
1583+
payment_data: payment_data.clone(),
15691584
});
1585+
if let &Some(ref data) = &payment_data {
1586+
for htlc in htlcs.iter() {
1587+
total_value += htlc.value;
1588+
if htlc.payment_data.as_ref().unwrap().total_msat != data.total_msat {
1589+
total_value = msgs::MAX_VALUE_MSAT;
1590+
}
1591+
if total_value >= msgs::MAX_VALUE_MSAT { break; }
1592+
}
1593+
if total_value >= msgs::MAX_VALUE_MSAT {
1594+
for htlc in htlcs.iter() {
1595+
failed_forwards.push((HTLCSource::PreviousHopData(HTLCPreviousHopData {
1596+
short_channel_id: htlc.src.short_channel_id,
1597+
htlc_id: htlc.src.htlc_id,
1598+
incoming_packet_shared_secret: htlc.src.incoming_packet_shared_secret,
1599+
}), payment_hash,
1600+
HTLCFailReason::Reason { failure_code: 0x4000 | 15, data: byte_utils::be64_to_array(htlc.value).to_vec() }
1601+
));
1602+
}
1603+
} else if total_value >= data.total_msat {
1604+
new_events.push(events::Event::PaymentReceived {
1605+
payment_hash: payment_hash,
1606+
payment_secret: Some(data.payment_secret),
1607+
amt: total_value,
1608+
});
1609+
}
1610+
} else {
1611+
new_events.push(events::Event::PaymentReceived {
1612+
payment_hash: payment_hash,
1613+
payment_secret: None,
1614+
amt: amt_to_forward,
1615+
});
1616+
}
15701617
},
15711618
HTLCForwardInfo::AddHTLC { .. } => {
15721619
panic!("short_channel_id == 0 should imply any pending_forward entries are of type Receive");
@@ -1580,11 +1627,8 @@ impl<ChanSigner: ChannelKeys, M: Deref> ChannelManager<ChanSigner, M> where M::T
15801627
}
15811628
}
15821629

1583-
for (htlc_source, payment_hash, failure_code, update) in failed_forwards.drain(..) {
1584-
match update {
1585-
None => self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), htlc_source, &payment_hash, HTLCFailReason::Reason { failure_code, data: Vec::new() }),
1586-
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() }),
1587-
};
1630+
for (htlc_source, payment_hash, failure_reason) in failed_forwards.drain(..) {
1631+
self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), htlc_source, &payment_hash, failure_reason);
15881632
}
15891633

15901634
if handle_errors.len() > 0 {
@@ -1629,11 +1673,11 @@ impl<ChanSigner: ChannelKeys, M: Deref> ChannelManager<ChanSigner, M> where M::T
16291673
/// along the path (including in our own channel on which we received it).
16301674
/// Returns false if no payment was found to fail backwards, true if the process of failing the
16311675
/// HTLC backwards has been started.
1632-
pub fn fail_htlc_backwards(&self, payment_hash: &PaymentHash) -> bool {
1676+
pub fn fail_htlc_backwards(&self, payment_hash: &PaymentHash, payment_secret: &Option<[u8; 32]>) -> bool {
16331677
let _ = self.total_consistency_lock.read().unwrap();
16341678

16351679
let mut channel_state = Some(self.channel_state.lock().unwrap());
1636-
let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(payment_hash);
1680+
let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(&(*payment_hash, *payment_secret));
16371681
if let Some(mut sources) = removed_source {
16381682
for htlc in sources.drain(..) {
16391683
if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap()); }
@@ -1755,13 +1799,13 @@ impl<ChanSigner: ChannelKeys, M: Deref> ChannelManager<ChanSigner, M> where M::T
17551799
/// motivated attackers.
17561800
///
17571801
/// May panic if called except in response to a PaymentReceived event.
1758-
pub fn claim_funds(&self, payment_preimage: PaymentPreimage, expected_amount: u64) -> bool {
1802+
pub fn claim_funds(&self, payment_preimage: PaymentPreimage, payment_secret: &Option<[u8; 32]>, expected_amount: u64) -> bool {
17591803
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
17601804

17611805
let _ = self.total_consistency_lock.read().unwrap();
17621806

17631807
let mut channel_state = Some(self.channel_state.lock().unwrap());
1764-
let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(&payment_hash);
1808+
let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(&(payment_hash, *payment_secret));
17651809
if let Some(mut sources) = removed_source {
17661810
for htlc in sources.drain(..) {
17671811
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
@@ -614,8 +614,9 @@ macro_rules! expect_payment_received {
614614
let events = $node.node.get_and_clear_pending_events();
615615
assert_eq!(events.len(), 1);
616616
match events[0] {
617-
Event::PaymentReceived { ref payment_hash, amt } => {
617+
Event::PaymentReceived { ref payment_hash, ref payment_secret, amt } => {
618618
assert_eq!($expected_payment_hash, *payment_hash);
619+
assert_eq!(*payment_secret, None);
619620
assert_eq!($expected_recv_value, amt);
620621
},
621622
_ => panic!("Unexpected event"),
@@ -636,9 +637,9 @@ macro_rules! expect_payment_sent {
636637
}
637638
}
638639

639-
pub fn send_along_route_with_hash<'a, 'b>(origin_node: &Node<'a, 'b>, route: Route, expected_route: &[&Node<'a, 'b>], recv_value: u64, our_payment_hash: PaymentHash) {
640+
pub fn send_along_route_with_secret<'a, 'b>(origin_node: &Node<'a, 'b>, route: Route, expected_route: &[&Node<'a, 'b>], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: Option<[u8; 32]>) {
640641
let mut payment_event = {
641-
origin_node.node.send_payment(route, our_payment_hash).unwrap();
642+
origin_node.node.send_payment(route, our_payment_hash, our_payment_secret.as_ref()).unwrap();
642643
check_added_monitors!(origin_node, 1);
643644

644645
let mut events = origin_node.node.get_and_clear_pending_msg_events();
@@ -660,8 +661,9 @@ pub fn send_along_route_with_hash<'a, 'b>(origin_node: &Node<'a, 'b>, route: Rou
660661
let events_2 = node.node.get_and_clear_pending_events();
661662
assert_eq!(events_2.len(), 1);
662663
match events_2[0] {
663-
Event::PaymentReceived { ref payment_hash, amt } => {
664+
Event::PaymentReceived { ref payment_hash, ref payment_secret, amt } => {
664665
assert_eq!(our_payment_hash, *payment_hash);
666+
assert_eq!(our_payment_secret, *payment_secret);
665667
assert_eq!(amt, recv_value);
666668
},
667669
_ => panic!("Unexpected event"),
@@ -678,14 +680,18 @@ pub fn send_along_route_with_hash<'a, 'b>(origin_node: &Node<'a, 'b>, route: Rou
678680
}
679681
}
680682

683+
pub fn send_along_route_with_hash<'a, 'b>(origin_node: &Node<'a, 'b>, route: Route, expected_route: &[&Node<'a, 'b>], recv_value: u64, our_payment_hash: PaymentHash) {
684+
send_along_route_with_secret(origin_node, route, expected_route, recv_value, our_payment_hash, None);
685+
}
686+
681687
pub fn send_along_route<'a, 'b>(origin_node: &Node<'a, 'b>, route: Route, expected_route: &[&Node<'a, 'b>], recv_value: u64) -> (PaymentPreimage, PaymentHash) {
682688
let (our_payment_preimage, our_payment_hash) = get_payment_preimage_hash!(origin_node);
683689
send_along_route_with_hash(origin_node, route, expected_route, recv_value, our_payment_hash);
684690
(our_payment_preimage, our_payment_hash)
685691
}
686692

687-
pub fn claim_payment_along_route<'a, 'b>(origin_node: &Node<'a, 'b>, expected_route: &[&Node<'a, 'b>], skip_last: bool, our_payment_preimage: PaymentPreimage, expected_amount: u64) {
688-
assert!(expected_route.last().unwrap().node.claim_funds(our_payment_preimage, expected_amount));
693+
pub fn claim_payment_along_route_with_secret<'a, 'b>(origin_node: &Node<'a, 'b>, expected_route: &[&Node<'a, 'b>], skip_last: bool, our_payment_preimage: PaymentPreimage, our_payment_secret: Option<[u8; 32]>, expected_amount: u64) {
694+
assert!(expected_route.last().unwrap().node.claim_funds(our_payment_preimage, &our_payment_secret, expected_amount));
689695
check_added_monitors!(expected_route.last().unwrap(), 1);
690696

691697
let mut next_msgs: Option<(msgs::UpdateFulfillHTLC, msgs::CommitmentSigned)> = None;
@@ -762,6 +768,10 @@ pub fn claim_payment_along_route<'a, 'b>(origin_node: &Node<'a, 'b>, expected_ro
762768
}
763769
}
764770

771+
pub fn claim_payment_along_route<'a, 'b>(origin_node: &Node<'a, 'b>, expected_route: &[&Node<'a, 'b>], skip_last: bool, our_payment_preimage: PaymentPreimage, expected_amount: u64) {
772+
claim_payment_along_route_with_secret(origin_node, expected_route, skip_last, our_payment_preimage, None, expected_amount);
773+
}
774+
765775
pub fn claim_payment<'a, 'b>(origin_node: &Node<'a, 'b>, expected_route: &[&Node<'a, 'b>], our_payment_preimage: PaymentPreimage, expected_amount: u64) {
766776
claim_payment_along_route(origin_node, expected_route, false, our_payment_preimage, expected_amount);
767777
}
@@ -787,7 +797,7 @@ pub fn route_over_limit<'a, 'b>(origin_node: &Node<'a, 'b>, expected_route: &[&N
787797

788798
let (_, our_payment_hash) = get_payment_preimage_hash!(origin_node);
789799

790-
let err = origin_node.node.send_payment(route, our_payment_hash).err().unwrap();
800+
let err = origin_node.node.send_payment(route, our_payment_hash, None).err().unwrap();
791801
match err {
792802
APIError::ChannelUnavailable{err} => assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept"),
793803
_ => panic!("Unknown error variants"),
@@ -800,7 +810,7 @@ pub fn send_payment<'a, 'b>(origin: &Node<'a, 'b>, expected_route: &[&Node<'a, '
800810
}
801811

802812
pub fn fail_payment_along_route<'a, 'b>(origin_node: &Node<'a, 'b>, expected_route: &[&Node<'a, 'b>], skip_last: bool, our_payment_hash: PaymentHash) {
803-
assert!(expected_route.last().unwrap().node.fail_htlc_backwards(&our_payment_hash));
813+
assert!(expected_route.last().unwrap().node.fail_htlc_backwards(&our_payment_hash, &None));
804814
expect_pending_htlcs_forwardable!(expected_route.last().unwrap());
805815
check_added_monitors!(expected_route.last().unwrap(), 1);
806816

0 commit comments

Comments
 (0)