Skip to content

Commit f99acc6

Browse files
authored
Merge pull request #297 from TheBlueMatt/2019-01-back-fail-privacy
Send back the actual received amount, not expected on HTLC fails
2 parents 4ccb1e4 + 74588b2 commit f99acc6

File tree

6 files changed

+42
-35
lines changed

6 files changed

+42
-35
lines changed

fuzz/fuzz_targets/chanmon_fail_consistency.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ pub fn do_test(data: &[u8]) {
439439
match event {
440440
events::Event::PaymentReceived { payment_hash, .. } => {
441441
if $fail {
442-
assert!(nodes[$node].fail_htlc_backwards(&payment_hash, 0));
442+
assert!(nodes[$node].fail_htlc_backwards(&payment_hash));
443443
} else {
444444
assert!(nodes[$node].claim_funds(PaymentPreimage(payment_hash.0)));
445445
}

fuzz/fuzz_targets/full_stack_target.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ pub fn do_test(data: &[u8], logger: &Arc<Logger>) {
451451
// fulfill this HTLC, but if they are, we can just take the first byte and
452452
// place that anywhere in our preimage.
453453
if &payment.0[1..] != &[0; 31] {
454-
channelmanager.fail_htlc_backwards(&payment, 0);
454+
channelmanager.fail_htlc_backwards(&payment);
455455
} else {
456456
let mut payment_preimage = PaymentPreimage([0; 32]);
457457
payment_preimage.0[0] = payment.0[0];
@@ -461,7 +461,7 @@ pub fn do_test(data: &[u8], logger: &Arc<Logger>) {
461461
},
462462
9 => {
463463
for payment in payments_received.drain(..) {
464-
channelmanager.fail_htlc_backwards(&payment, 0);
464+
channelmanager.fail_htlc_backwards(&payment);
465465
}
466466
},
467467
10 => {

src/ln/chanmon_update_fail_tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,7 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) {
674674
let (_, payment_hash_1) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000);
675675

676676
// Fail the payment backwards, failing the monitor update on nodes[1]'s receipt of the RAA
677-
assert!(nodes[2].node.fail_htlc_backwards(&payment_hash_1, 0));
677+
assert!(nodes[2].node.fail_htlc_backwards(&payment_hash_1));
678678
expect_pending_htlcs_forwardable!(nodes[2]);
679679
check_added_monitors!(nodes[2], 1);
680680

@@ -1451,7 +1451,7 @@ fn test_monitor_update_on_pending_forwards() {
14511451
send_payment(&nodes[0], &[&nodes[1], &nodes[2]], 5000000);
14521452

14531453
let (_, payment_hash_1) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000);
1454-
assert!(nodes[2].node.fail_htlc_backwards(&payment_hash_1, 1000000));
1454+
assert!(nodes[2].node.fail_htlc_backwards(&payment_hash_1));
14551455
expect_pending_htlcs_forwardable!(nodes[2]);
14561456
check_added_monitors!(nodes[2], 1);
14571457

src/ln/channelmanager.rs

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -252,10 +252,12 @@ pub(super) struct ChannelHolder {
252252
/// guarantees are made about the existence of a channel with the short id here, nor the short
253253
/// ids in the PendingForwardHTLCInfo!
254254
pub(super) forward_htlcs: HashMap<u64, Vec<HTLCForwardInfo>>,
255+
/// payment_hash -> Vec<(amount_received, htlc_source)> for tracking things that were to us and
256+
/// can be failed/claimed by the user
255257
/// Note that while this is held in the same mutex as the channels themselves, no consistency
256258
/// guarantees are made about the channels given here actually existing anymore by the time you
257259
/// go to read them!
258-
pub(super) claimable_htlcs: HashMap<PaymentHash, Vec<HTLCPreviousHopData>>,
260+
pub(super) claimable_htlcs: HashMap<PaymentHash, Vec<(u64, HTLCPreviousHopData)>>,
259261
/// Messages to send to peers - pushed to in the same lock that they are generated in (except
260262
/// for broadcast messages, where ordering isn't as strict).
261263
pub(super) pending_msg_events: Vec<events::MessageSendEvent>,
@@ -265,7 +267,7 @@ pub(super) struct MutChannelHolder<'a> {
265267
pub(super) short_to_id: &'a mut HashMap<u64, [u8; 32]>,
266268
pub(super) next_forward: &'a mut Instant,
267269
pub(super) forward_htlcs: &'a mut HashMap<u64, Vec<HTLCForwardInfo>>,
268-
pub(super) claimable_htlcs: &'a mut HashMap<PaymentHash, Vec<HTLCPreviousHopData>>,
270+
pub(super) claimable_htlcs: &'a mut HashMap<PaymentHash, Vec<(u64, HTLCPreviousHopData)>>,
269271
pub(super) pending_msg_events: &'a mut Vec<events::MessageSendEvent>,
270272
}
271273
impl ChannelHolder {
@@ -1308,8 +1310,8 @@ impl ChannelManager {
13081310
incoming_packet_shared_secret: forward_info.incoming_shared_secret,
13091311
};
13101312
match channel_state.claimable_htlcs.entry(forward_info.payment_hash) {
1311-
hash_map::Entry::Occupied(mut entry) => entry.get_mut().push(prev_hop_data),
1312-
hash_map::Entry::Vacant(entry) => { entry.insert(vec![prev_hop_data]); },
1313+
hash_map::Entry::Occupied(mut entry) => entry.get_mut().push((forward_info.amt_to_forward, prev_hop_data)),
1314+
hash_map::Entry::Vacant(entry) => { entry.insert(vec![(forward_info.amt_to_forward, prev_hop_data)]); },
13131315
};
13141316
new_events.push(events::Event::PaymentReceived {
13151317
payment_hash: forward_info.payment_hash,
@@ -1354,20 +1356,21 @@ impl ChannelManager {
13541356
}
13551357

13561358
/// Indicates that the preimage for payment_hash is unknown or the received amount is incorrect
1357-
/// after a PaymentReceived event.
1358-
/// expected_value is the value you expected the payment to be for (not the amount it actually
1359-
/// was for from the PaymentReceived event).
1360-
pub fn fail_htlc_backwards(&self, payment_hash: &PaymentHash, expected_value: u64) -> bool {
1359+
/// after a PaymentReceived event, failing the HTLC back to its origin and freeing resources
1360+
/// along the path (including in our own channel on which we received it).
1361+
/// Returns false if no payment was found to fail backwards, true if the process of failing the
1362+
/// HTLC backwards has been started.
1363+
pub fn fail_htlc_backwards(&self, payment_hash: &PaymentHash) -> bool {
13611364
let _ = self.total_consistency_lock.read().unwrap();
13621365

13631366
let mut channel_state = Some(self.channel_state.lock().unwrap());
13641367
let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(payment_hash);
13651368
if let Some(mut sources) = removed_source {
1366-
for htlc_with_hash in sources.drain(..) {
1369+
for (recvd_value, htlc_with_hash) in sources.drain(..) {
13671370
if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap()); }
13681371
self.fail_htlc_backwards_internal(channel_state.take().unwrap(),
13691372
HTLCSource::PreviousHopData(htlc_with_hash), payment_hash,
1370-
HTLCFailReason::Reason { failure_code: 0x4000 | 15, data: byte_utils::be64_to_array(expected_value).to_vec() });
1373+
HTLCFailReason::Reason { failure_code: 0x4000 | 15, data: byte_utils::be64_to_array(recvd_value).to_vec() });
13711374
}
13721375
true
13731376
} else { false }
@@ -1485,7 +1488,10 @@ impl ChannelManager {
14851488
let mut channel_state = Some(self.channel_state.lock().unwrap());
14861489
let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(&payment_hash);
14871490
if let Some(mut sources) = removed_source {
1488-
for htlc_with_hash in sources.drain(..) {
1491+
// TODO: We should require the user specify the expected amount so that we can claim
1492+
// only payments for the correct amount, and reject payments for incorrect amounts
1493+
// (which are probably middle nodes probing to break our privacy).
1494+
for (_, htlc_with_hash) in sources.drain(..) {
14891495
if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap()); }
14901496
self.claim_funds_internal(channel_state.take().unwrap(), HTLCSource::PreviousHopData(htlc_with_hash), payment_preimage);
14911497
}
@@ -2910,7 +2916,8 @@ impl Writeable for ChannelManager {
29102916
for (payment_hash, previous_hops) in channel_state.claimable_htlcs.iter() {
29112917
payment_hash.write(writer)?;
29122918
(previous_hops.len() as u64).write(writer)?;
2913-
for previous_hop in previous_hops {
2919+
for &(recvd_amt, ref previous_hop) in previous_hops.iter() {
2920+
recvd_amt.write(writer)?;
29142921
previous_hop.write(writer)?;
29152922
}
29162923
}
@@ -3047,7 +3054,7 @@ impl<'a, R : ::std::io::Read> ReadableArgs<R, ChannelManagerReadArgs<'a>> for (S
30473054
let previous_hops_len: u64 = Readable::read(reader)?;
30483055
let mut previous_hops = Vec::with_capacity(cmp::min(previous_hops_len as usize, 2));
30493056
for _ in 0..previous_hops_len {
3050-
previous_hops.push(Readable::read(reader)?);
3057+
previous_hops.push((Readable::read(reader)?, Readable::read(reader)?));
30513058
}
30523059
claimable_htlcs.insert(payment_hash, previous_hops);
30533060
}

src/ln/functional_test_utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ pub fn send_payment(origin: &Node, expected_route: &[&Node], recv_value: u64) {
713713
}
714714

715715
pub fn fail_payment_along_route(origin_node: &Node, expected_route: &[&Node], skip_last: bool, our_payment_hash: PaymentHash) {
716-
assert!(expected_route.last().unwrap().node.fail_htlc_backwards(&our_payment_hash, 0));
716+
assert!(expected_route.last().unwrap().node.fail_htlc_backwards(&our_payment_hash));
717717
expect_pending_htlcs_forwardable!(expected_route.last().unwrap());
718718
check_added_monitors!(expected_route.last().unwrap(), 1);
719719

src/ln/functional_tests.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2038,7 +2038,7 @@ fn test_htlc_on_chain_timeout() {
20382038
// Broadcast legit commitment tx from C on B's chain
20392039
let commitment_tx = nodes[2].node.channel_state.lock().unwrap().by_id.get(&chan_2.2).unwrap().last_local_commitment_txn.clone();
20402040
check_spends!(commitment_tx[0], chan_2.3.clone());
2041-
nodes[2].node.fail_htlc_backwards(&payment_hash, 0);
2041+
nodes[2].node.fail_htlc_backwards(&payment_hash);
20422042
check_added_monitors!(nodes[2], 0);
20432043
expect_pending_htlcs_forwardable!(nodes[2]);
20442044
check_added_monitors!(nodes[2], 1);
@@ -2219,7 +2219,7 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
22192219
let (_, second_payment_hash) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], value);
22202220
let (_, third_payment_hash) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], value);
22212221

2222-
assert!(nodes[2].node.fail_htlc_backwards(&first_payment_hash, 0));
2222+
assert!(nodes[2].node.fail_htlc_backwards(&first_payment_hash));
22232223
expect_pending_htlcs_forwardable!(nodes[2]);
22242224
check_added_monitors!(nodes[2], 1);
22252225
let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
@@ -2232,7 +2232,7 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
22322232
let bs_raa = commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false, true, false, true);
22332233
// Drop the last RAA from 3 -> 2
22342234

2235-
assert!(nodes[2].node.fail_htlc_backwards(&second_payment_hash, 0));
2235+
assert!(nodes[2].node.fail_htlc_backwards(&second_payment_hash));
22362236
expect_pending_htlcs_forwardable!(nodes[2]);
22372237
check_added_monitors!(nodes[2], 1);
22382238
let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
@@ -2249,7 +2249,7 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
22492249
nodes[2].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &as_raa).unwrap();
22502250
check_added_monitors!(nodes[2], 1);
22512251

2252-
assert!(nodes[2].node.fail_htlc_backwards(&third_payment_hash, 0));
2252+
assert!(nodes[2].node.fail_htlc_backwards(&third_payment_hash));
22532253
expect_pending_htlcs_forwardable!(nodes[2]);
22542254
check_added_monitors!(nodes[2], 1);
22552255
let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
@@ -3895,10 +3895,10 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
38953895

38963896
// Now fail back three of the over-dust-limit and three of the under-dust-limit payments in one go.
38973897
// Fail 0th below-dust, 4th above-dust, 8th above-dust, 10th below-dust HTLCs
3898-
assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_1, ds_dust_limit*1000));
3899-
assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_3, 1000000));
3900-
assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_5, 1000000));
3901-
assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_6, ds_dust_limit*1000));
3898+
assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_1));
3899+
assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_3));
3900+
assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_5));
3901+
assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_6));
39023902
check_added_monitors!(nodes[4], 0);
39033903
expect_pending_htlcs_forwardable!(nodes[4]);
39043904
check_added_monitors!(nodes[4], 1);
@@ -3911,8 +3911,8 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
39113911
commitment_signed_dance!(nodes[3], nodes[4], four_removes.commitment_signed, false);
39123912

39133913
// Fail 3rd below-dust and 7th above-dust HTLCs
3914-
assert!(nodes[5].node.fail_htlc_backwards(&payment_hash_2, ds_dust_limit*1000));
3915-
assert!(nodes[5].node.fail_htlc_backwards(&payment_hash_4, 1000000));
3914+
assert!(nodes[5].node.fail_htlc_backwards(&payment_hash_2));
3915+
assert!(nodes[5].node.fail_htlc_backwards(&payment_hash_4));
39163916
check_added_monitors!(nodes[5], 0);
39173917
expect_pending_htlcs_forwardable!(nodes[5]);
39183918
check_added_monitors!(nodes[5], 1);
@@ -4205,7 +4205,7 @@ fn do_htlc_claim_previous_remote_commitment_only(use_dust: bool, check_revoke_no
42054205
// actually revoked.
42064206
let htlc_value = if use_dust { 50000 } else { 3000000 };
42074207
let (_, our_payment_hash) = route_payment(&nodes[0], &[&nodes[1]], htlc_value);
4208-
assert!(nodes[1].node.fail_htlc_backwards(&our_payment_hash, htlc_value));
4208+
assert!(nodes[1].node.fail_htlc_backwards(&our_payment_hash));
42094209
expect_pending_htlcs_forwardable!(nodes[1]);
42104210
check_added_monitors!(nodes[1], 1);
42114211

@@ -4531,7 +4531,7 @@ fn test_onion_failure() {
45314531
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
45324532
msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[1].shared_secret[..], NODE|2, &[0;0]);
45334533
}, ||{
4534-
nodes[2].node.fail_htlc_backwards(&payment_hash, 0);
4534+
nodes[2].node.fail_htlc_backwards(&payment_hash);
45354535
}, true, Some(NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.hops[1].pubkey, is_permanent: false}));
45364536

45374537
// intermediate node failure
@@ -4549,7 +4549,7 @@ fn test_onion_failure() {
45494549
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
45504550
msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[1].shared_secret[..], PERM|NODE|2, &[0;0]);
45514551
}, ||{
4552-
nodes[2].node.fail_htlc_backwards(&payment_hash, 0);
4552+
nodes[2].node.fail_htlc_backwards(&payment_hash);
45534553
}, false, Some(PERM|NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.hops[1].pubkey, is_permanent: true}));
45544554

45554555
// intermediate node failure
@@ -4560,7 +4560,7 @@ fn test_onion_failure() {
45604560
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
45614561
msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[0].shared_secret[..], PERM|NODE|3, &[0;0]);
45624562
}, ||{
4563-
nodes[2].node.fail_htlc_backwards(&payment_hash, 0);
4563+
nodes[2].node.fail_htlc_backwards(&payment_hash);
45644564
}, true, Some(PERM|NODE|3), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.hops[0].pubkey, is_permanent: true}));
45654565

45664566
// final node failure
@@ -4569,7 +4569,7 @@ fn test_onion_failure() {
45694569
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
45704570
msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[1].shared_secret[..], PERM|NODE|3, &[0;0]);
45714571
}, ||{
4572-
nodes[2].node.fail_htlc_backwards(&payment_hash, 0);
4572+
nodes[2].node.fail_htlc_backwards(&payment_hash);
45734573
}, false, Some(PERM|NODE|3), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.hops[1].pubkey, is_permanent: true}));
45744574

45754575
run_onion_failure_test("invalid_onion_version", 0, &nodes, &route, &payment_hash, |msg| { msg.onion_routing_packet.version = 1; }, ||{}, true,
@@ -4636,7 +4636,7 @@ fn test_onion_failure() {
46364636
}, ||{}, true, Some(UPDATE|14), Some(msgs::HTLCFailChannelUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy()}));
46374637

46384638
run_onion_failure_test("unknown_payment_hash", 2, &nodes, &route, &payment_hash, |_| {}, || {
4639-
nodes[2].node.fail_htlc_backwards(&payment_hash, 0);
4639+
nodes[2].node.fail_htlc_backwards(&payment_hash);
46404640
}, false, Some(PERM|15), None);
46414641

46424642
run_onion_failure_test("final_expiry_too_soon", 1, &nodes, &route, &payment_hash, |msg| {

0 commit comments

Comments
 (0)