Skip to content

Commit e23ff0a

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 ee0a406 commit e23ff0a

File tree

9 files changed

+266
-165
lines changed

9 files changed

+266
-165
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ pub fn do_test(data: &[u8]) {
417417
fee_msat: 5000000,
418418
cltv_expiry_delta: 200,
419419
}],
420-
}, PaymentHash(payment_hash.into_inner())) {
420+
}, PaymentHash(payment_hash.into_inner()), None) {
421421
// Probably ran out of funds
422422
test_return!();
423423
}
@@ -441,7 +441,7 @@ pub fn do_test(data: &[u8]) {
441441
fee_msat: 5000000,
442442
cltv_expiry_delta: 200,
443443
}],
444-
}, PaymentHash(payment_hash.into_inner())) {
444+
}, PaymentHash(payment_hash.into_inner()), None) {
445445
// Probably ran out of funds
446446
test_return!();
447447
}
@@ -602,9 +602,9 @@ pub fn do_test(data: &[u8]) {
602602
events::Event::PaymentReceived { payment_hash, .. } => {
603603
if claim_set.insert(payment_hash.0) {
604604
if $fail {
605-
assert!(nodes[$node].fail_htlc_backwards(&payment_hash));
605+
assert!(nodes[$node].fail_htlc_backwards(&payment_hash, &None));
606606
} else {
607-
assert!(nodes[$node].claim_funds(PaymentPreimage(payment_hash.0), 5_000_000));
607+
assert!(nodes[$node].claim_funds(PaymentPreimage(payment_hash.0), &None, 5_000_000));
608608
}
609609
}
610610
},

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 HTLCs that were to us and can be failed/claimed by the user
287+
/// (payment_hash, payment_secret) -> Vec<HTLCs> for tracking HTLCs 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>,
@@ -1191,7 +1194,14 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref> ChannelMan
11911194
/// In case of APIError::MonitorUpdateFailed, the commitment update has been irrevocably
11921195
/// committed on our end and we're just waiting for a monitor update to send it. Do NOT retry
11931196
/// the payment via a different route unless you intend to pay twice!
1194-
pub fn send_payment(&self, route: Route, payment_hash: PaymentHash) -> Result<(), APIError> {
1197+
///
1198+
/// payment_secret is unrelated to payment_hash (or PaymentPreimage) and exists to authenticate
1199+
/// the sender to the recipient and prevent payment-probing (deanonymization) attacks. For
1200+
/// newer nodes, it will be provided to you in the invoice. If you do not have one, the Route
1201+
/// must not contain multiple paths as otherwise the multipath data cannot be sent.
1202+
/// If a payment_secret *is* provided, we assume that the invoice had the basic_mpp feature bit
1203+
/// set (either as required or as available).
1204+
pub fn send_payment(&self, route: Route, payment_hash: PaymentHash, payment_secret: Option<&[u8; 32]>) -> Result<(), APIError> {
11951205
if route.hops.len() < 1 || route.hops.len() > 20 {
11961206
return Err(APIError::RouteError{err: "Route didn't go anywhere/had bogus size"});
11971207
}
@@ -1208,7 +1218,7 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref> ChannelMan
12081218

12091219
let onion_keys = secp_call!(onion_utils::construct_onion_keys(&self.secp_ctx, &route, &session_priv),
12101220
APIError::RouteError{err: "Pubkey along hop was maliciously selected"});
1211-
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route, cur_height)?;
1221+
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route, payment_secret, cur_height)?;
12121222
if onion_utils::route_size_insane(&onion_payloads) {
12131223
return Err(APIError::RouteError{err: "Route size too large considering onion data"});
12141224
}
@@ -1442,7 +1452,9 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref> ChannelMan
14421452
htlc_id: prev_htlc_id,
14431453
incoming_packet_shared_secret: forward_info.incoming_shared_secret,
14441454
});
1445-
failed_forwards.push((htlc_source, forward_info.payment_hash, 0x4000 | 10, None));
1455+
failed_forwards.push((htlc_source, forward_info.payment_hash,
1456+
HTLCFailReason::Reason { failure_code: 0x1000 | 7, data: Vec::new() }
1457+
));
14461458
},
14471459
HTLCForwardInfo::FailHTLC { .. } => {
14481460
// Channel went away before we could fail it. This implies
@@ -1478,7 +1490,9 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref> ChannelMan
14781490
panic!("Stated return value requirements in send_htlc() were not met");
14791491
}
14801492
let chan_update = self.get_channel_update(chan.get()).unwrap();
1481-
failed_forwards.push((htlc_source, payment_hash, 0x1000 | 7, Some(chan_update)));
1493+
failed_forwards.push((htlc_source, payment_hash,
1494+
HTLCFailReason::Reason { failure_code: 0x1000 | 7, data: chan_update.encode_with_len() }
1495+
));
14821496
continue;
14831497
},
14841498
Ok(update_add) => {
@@ -1587,15 +1601,48 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref> ChannelMan
15871601
htlc_id: prev_htlc_id,
15881602
incoming_packet_shared_secret: incoming_shared_secret,
15891603
};
1590-
channel_state.claimable_htlcs.entry(payment_hash).or_insert(Vec::new()).push(ClaimableHTLC {
1604+
1605+
let mut total_value = 0;
1606+
let htlcs = channel_state.claimable_htlcs.entry((payment_hash, if let &Some(ref data) = &payment_data {
1607+
Some(data.payment_secret.clone()) } else { None }))
1608+
.or_insert(Vec::new());
1609+
htlcs.push(ClaimableHTLC {
15911610
prev_hop,
15921611
value: amt_to_forward,
1593-
payment_data,
1594-
});
1595-
new_events.push(events::Event::PaymentReceived {
1596-
payment_hash: payment_hash,
1597-
amt: amt_to_forward,
1612+
payment_data: payment_data.clone(),
15981613
});
1614+
if let &Some(ref data) = &payment_data {
1615+
for htlc in htlcs.iter() {
1616+
total_value += htlc.value;
1617+
if htlc.payment_data.as_ref().unwrap().total_msat != data.total_msat {
1618+
total_value = msgs::MAX_VALUE_MSAT;
1619+
}
1620+
if total_value >= msgs::MAX_VALUE_MSAT { break; }
1621+
}
1622+
if total_value >= msgs::MAX_VALUE_MSAT {
1623+
for htlc in htlcs.iter() {
1624+
failed_forwards.push((HTLCSource::PreviousHopData(HTLCPreviousHopData {
1625+
short_channel_id: htlc.prev_hop.short_channel_id,
1626+
htlc_id: htlc.prev_hop.htlc_id,
1627+
incoming_packet_shared_secret: htlc.prev_hop.incoming_packet_shared_secret,
1628+
}), payment_hash,
1629+
HTLCFailReason::Reason { failure_code: 0x4000 | 15, data: byte_utils::be64_to_array(htlc.value).to_vec() }
1630+
));
1631+
}
1632+
} else if total_value >= data.total_msat {
1633+
new_events.push(events::Event::PaymentReceived {
1634+
payment_hash: payment_hash,
1635+
payment_secret: Some(data.payment_secret),
1636+
amt: total_value,
1637+
});
1638+
}
1639+
} else {
1640+
new_events.push(events::Event::PaymentReceived {
1641+
payment_hash: payment_hash,
1642+
payment_secret: None,
1643+
amt: amt_to_forward,
1644+
});
1645+
}
15991646
},
16001647
HTLCForwardInfo::AddHTLC { .. } => {
16011648
panic!("short_channel_id == 0 should imply any pending_forward entries are of type Receive");
@@ -1609,11 +1656,8 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref> ChannelMan
16091656
}
16101657
}
16111658

1612-
for (htlc_source, payment_hash, failure_code, update) in failed_forwards.drain(..) {
1613-
match update {
1614-
None => self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), htlc_source, &payment_hash, HTLCFailReason::Reason { failure_code, data: Vec::new() }),
1615-
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() }),
1616-
};
1659+
for (htlc_source, payment_hash, failure_reason) in failed_forwards.drain(..) {
1660+
self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), htlc_source, &payment_hash, failure_reason);
16171661
}
16181662

16191663
if handle_errors.len() > 0 {
@@ -1658,11 +1702,11 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref> ChannelMan
16581702
/// along the path (including in our own channel on which we received it).
16591703
/// Returns false if no payment was found to fail backwards, true if the process of failing the
16601704
/// HTLC backwards has been started.
1661-
pub fn fail_htlc_backwards(&self, payment_hash: &PaymentHash) -> bool {
1705+
pub fn fail_htlc_backwards(&self, payment_hash: &PaymentHash, payment_secret: &Option<[u8; 32]>) -> bool {
16621706
let _ = self.total_consistency_lock.read().unwrap();
16631707

16641708
let mut channel_state = Some(self.channel_state.lock().unwrap());
1665-
let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(payment_hash);
1709+
let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(&(*payment_hash, *payment_secret));
16661710
if let Some(mut sources) = removed_source {
16671711
for htlc in sources.drain(..) {
16681712
if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap()); }
@@ -1784,13 +1828,13 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref> ChannelMan
17841828
/// motivated attackers.
17851829
///
17861830
/// May panic if called except in response to a PaymentReceived event.
1787-
pub fn claim_funds(&self, payment_preimage: PaymentPreimage, expected_amount: u64) -> bool {
1831+
pub fn claim_funds(&self, payment_preimage: PaymentPreimage, payment_secret: &Option<[u8; 32]>, expected_amount: u64) -> bool {
17881832
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
17891833

17901834
let _ = self.total_consistency_lock.read().unwrap();
17911835

17921836
let mut channel_state = Some(self.channel_state.lock().unwrap());
1793-
let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(&payment_hash);
1837+
let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(&(payment_hash, *payment_secret));
17941838
if let Some(mut sources) = removed_source {
17951839
for htlc in sources.drain(..) {
17961840
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
@@ -717,8 +717,9 @@ macro_rules! expect_payment_received {
717717
let events = $node.node.get_and_clear_pending_events();
718718
assert_eq!(events.len(), 1);
719719
match events[0] {
720-
Event::PaymentReceived { ref payment_hash, amt } => {
720+
Event::PaymentReceived { ref payment_hash, ref payment_secret, amt } => {
721721
assert_eq!($expected_payment_hash, *payment_hash);
722+
assert_eq!(*payment_secret, None);
722723
assert_eq!($expected_recv_value, amt);
723724
},
724725
_ => panic!("Unexpected event"),
@@ -753,9 +754,9 @@ macro_rules! expect_payment_failed {
753754
}
754755
}
755756

756-
pub fn send_along_route_with_hash<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64, our_payment_hash: PaymentHash) {
757+
pub fn send_along_route_with_secret<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: Option<[u8; 32]>) {
757758
let mut payment_event = {
758-
origin_node.node.send_payment(route, our_payment_hash).unwrap();
759+
origin_node.node.send_payment(route, our_payment_hash, our_payment_secret.as_ref()).unwrap();
759760
check_added_monitors!(origin_node, 1);
760761

761762
let mut events = origin_node.node.get_and_clear_pending_msg_events();
@@ -777,8 +778,9 @@ pub fn send_along_route_with_hash<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, ro
777778
let events_2 = node.node.get_and_clear_pending_events();
778779
assert_eq!(events_2.len(), 1);
779780
match events_2[0] {
780-
Event::PaymentReceived { ref payment_hash, amt } => {
781+
Event::PaymentReceived { ref payment_hash, ref payment_secret, amt } => {
781782
assert_eq!(our_payment_hash, *payment_hash);
783+
assert_eq!(our_payment_secret, *payment_secret);
782784
assert_eq!(amt, recv_value);
783785
},
784786
_ => panic!("Unexpected event"),
@@ -795,14 +797,18 @@ pub fn send_along_route_with_hash<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, ro
795797
}
796798
}
797799

800+
pub fn send_along_route_with_hash<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64, our_payment_hash: PaymentHash) {
801+
send_along_route_with_secret(origin_node, route, expected_route, recv_value, our_payment_hash, None);
802+
}
803+
798804
pub fn send_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) -> (PaymentPreimage, PaymentHash) {
799805
let (our_payment_preimage, our_payment_hash) = get_payment_preimage_hash!(origin_node);
800806
send_along_route_with_hash(origin_node, route, expected_route, recv_value, our_payment_hash);
801807
(our_payment_preimage, our_payment_hash)
802808
}
803809

804-
pub fn claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], skip_last: bool, our_payment_preimage: PaymentPreimage, expected_amount: u64) {
805-
assert!(expected_route.last().unwrap().node.claim_funds(our_payment_preimage, expected_amount));
810+
pub fn claim_payment_along_route_with_secret<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], skip_last: bool, our_payment_preimage: PaymentPreimage, our_payment_secret: Option<[u8; 32]>, expected_amount: u64) {
811+
assert!(expected_route.last().unwrap().node.claim_funds(our_payment_preimage, &our_payment_secret, expected_amount));
806812
check_added_monitors!(expected_route.last().unwrap(), 1);
807813

808814
let mut next_msgs: Option<(msgs::UpdateFulfillHTLC, msgs::CommitmentSigned)> = None;
@@ -879,6 +885,10 @@ pub fn claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, exp
879885
}
880886
}
881887

888+
pub fn claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], skip_last: bool, our_payment_preimage: PaymentPreimage, expected_amount: u64) {
889+
claim_payment_along_route_with_secret(origin_node, expected_route, skip_last, our_payment_preimage, None, expected_amount);
890+
}
891+
882892
pub fn claim_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], our_payment_preimage: PaymentPreimage, expected_amount: u64) {
883893
claim_payment_along_route(origin_node, expected_route, false, our_payment_preimage, expected_amount);
884894
}
@@ -904,7 +914,7 @@ pub fn route_over_limit<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_rou
904914

905915
let (_, our_payment_hash) = get_payment_preimage_hash!(origin_node);
906916

907-
let err = origin_node.node.send_payment(route, our_payment_hash).err().unwrap();
917+
let err = origin_node.node.send_payment(route, our_payment_hash, None).err().unwrap();
908918
match err {
909919
APIError::ChannelUnavailable{err} => assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept"),
910920
_ => panic!("Unknown error variants"),
@@ -917,7 +927,7 @@ pub fn send_payment<'a, 'b, 'c>(origin: &Node<'a, 'b, 'c>, expected_route: &[&No
917927
}
918928

919929
pub fn fail_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], skip_last: bool, our_payment_hash: PaymentHash) {
920-
assert!(expected_route.last().unwrap().node.fail_htlc_backwards(&our_payment_hash));
930+
assert!(expected_route.last().unwrap().node.fail_htlc_backwards(&our_payment_hash, &None));
921931
expect_pending_htlcs_forwardable!(expected_route.last().unwrap());
922932
check_added_monitors!(expected_route.last().unwrap(), 1);
923933

0 commit comments

Comments
 (0)