Skip to content

Commit a8bc8fb

Browse files
authored
Merge pull request #893 from TheBlueMatt/2021-04-features-chanman
Require payment secrets and track them in ChannelManager
2 parents affefb6 + 615ef7d commit a8bc8fb

File tree

12 files changed

+1240
-889
lines changed

12 files changed

+1240
-889
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 36 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -261,45 +261,58 @@ fn check_payment_err(send_err: PaymentSendFailure) {
261261

262262
type ChanMan = ChannelManager<EnforcingSigner, Arc<TestChainMonitor>, Arc<TestBroadcaster>, Arc<KeyProvider>, Arc<FuzzEstimator>, Arc<dyn Logger>>;
263263

264+
#[inline]
265+
fn get_payment_secret_hash(dest: &ChanMan, payment_id: &mut u8) -> Option<(PaymentSecret, PaymentHash)> {
266+
let mut payment_hash;
267+
for _ in 0..256 {
268+
payment_hash = PaymentHash(Sha256::hash(&[*payment_id; 1]).into_inner());
269+
if let Ok(payment_secret) = dest.create_inbound_payment_for_hash(payment_hash, None, 7200, 0) {
270+
return Some((payment_secret, payment_hash));
271+
}
272+
*payment_id = payment_id.wrapping_add(1);
273+
}
274+
None
275+
}
276+
264277
#[inline]
265278
fn send_payment(source: &ChanMan, dest: &ChanMan, dest_chan_id: u64, amt: u64, payment_id: &mut u8) -> bool {
266-
let payment_hash = Sha256::hash(&[*payment_id; 1]);
267-
*payment_id = payment_id.wrapping_add(1);
279+
let (payment_secret, payment_hash) =
280+
if let Some((secret, hash)) = get_payment_secret_hash(dest, payment_id) { (secret, hash) } else { return true; };
268281
if let Err(err) = source.send_payment(&Route {
269282
paths: vec![vec![RouteHop {
270283
pubkey: dest.get_our_node_id(),
271-
node_features: NodeFeatures::empty(),
284+
node_features: NodeFeatures::known(),
272285
short_channel_id: dest_chan_id,
273-
channel_features: ChannelFeatures::empty(),
286+
channel_features: ChannelFeatures::known(),
274287
fee_msat: amt,
275288
cltv_expiry_delta: 200,
276289
}]],
277-
}, PaymentHash(payment_hash.into_inner()), &None) {
290+
}, payment_hash, &Some(payment_secret)) {
278291
check_payment_err(err);
279292
false
280293
} else { true }
281294
}
282295
#[inline]
283296
fn send_hop_payment(source: &ChanMan, middle: &ChanMan, middle_chan_id: u64, dest: &ChanMan, dest_chan_id: u64, amt: u64, payment_id: &mut u8) -> bool {
284-
let payment_hash = Sha256::hash(&[*payment_id; 1]);
285-
*payment_id = payment_id.wrapping_add(1);
297+
let (payment_secret, payment_hash) =
298+
if let Some((secret, hash)) = get_payment_secret_hash(dest, payment_id) { (secret, hash) } else { return true; };
286299
if let Err(err) = source.send_payment(&Route {
287300
paths: vec![vec![RouteHop {
288301
pubkey: middle.get_our_node_id(),
289-
node_features: NodeFeatures::empty(),
302+
node_features: NodeFeatures::known(),
290303
short_channel_id: middle_chan_id,
291-
channel_features: ChannelFeatures::empty(),
304+
channel_features: ChannelFeatures::known(),
292305
fee_msat: 50000,
293306
cltv_expiry_delta: 100,
294307
},RouteHop {
295308
pubkey: dest.get_our_node_id(),
296-
node_features: NodeFeatures::empty(),
309+
node_features: NodeFeatures::known(),
297310
short_channel_id: dest_chan_id,
298-
channel_features: ChannelFeatures::empty(),
311+
channel_features: ChannelFeatures::known(),
299312
fee_msat: amt,
300313
cltv_expiry_delta: 200,
301314
}]],
302-
}, PaymentHash(payment_hash.into_inner()), &None) {
315+
}, payment_hash, &Some(payment_secret)) {
303316
check_payment_err(err);
304317
false
305318
} else { true }
@@ -523,48 +536,6 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
523536
}
524537

525538
loop {
526-
macro_rules! send_payment_with_secret {
527-
($source: expr, $middle: expr, $dest: expr) => { {
528-
let payment_hash = Sha256::hash(&[payment_id; 1]);
529-
payment_id = payment_id.wrapping_add(1);
530-
let payment_secret = Sha256::hash(&[payment_id; 1]);
531-
payment_id = payment_id.wrapping_add(1);
532-
if let Err(err) = $source.send_payment(&Route {
533-
paths: vec![vec![RouteHop {
534-
pubkey: $middle.0.get_our_node_id(),
535-
node_features: NodeFeatures::empty(),
536-
short_channel_id: $middle.1,
537-
channel_features: ChannelFeatures::empty(),
538-
fee_msat: 50_000,
539-
cltv_expiry_delta: 100,
540-
},RouteHop {
541-
pubkey: $dest.0.get_our_node_id(),
542-
node_features: NodeFeatures::empty(),
543-
short_channel_id: $dest.1,
544-
channel_features: ChannelFeatures::empty(),
545-
fee_msat: 10_000_000,
546-
cltv_expiry_delta: 200,
547-
}],vec![RouteHop {
548-
pubkey: $middle.0.get_our_node_id(),
549-
node_features: NodeFeatures::empty(),
550-
short_channel_id: $middle.1,
551-
channel_features: ChannelFeatures::empty(),
552-
fee_msat: 50_000,
553-
cltv_expiry_delta: 100,
554-
},RouteHop {
555-
pubkey: $dest.0.get_our_node_id(),
556-
node_features: NodeFeatures::empty(),
557-
short_channel_id: $dest.1,
558-
channel_features: ChannelFeatures::empty(),
559-
fee_msat: 10_000_000,
560-
cltv_expiry_delta: 200,
561-
}]],
562-
}, PaymentHash(payment_hash.into_inner()), &Some(PaymentSecret(payment_secret.into_inner()))) {
563-
check_payment_err(err);
564-
}
565-
} }
566-
}
567-
568539
macro_rules! process_msg_events {
569540
($node: expr, $corrupt_forward: expr) => { {
570541
let events = if $node == 1 {
@@ -716,12 +687,12 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
716687
let had_events = !events.is_empty();
717688
for event in events.drain(..) {
718689
match event {
719-
events::Event::PaymentReceived { payment_hash, payment_secret, amt } => {
690+
events::Event::PaymentReceived { payment_hash, .. } => {
720691
if claim_set.insert(payment_hash.0) {
721692
if $fail {
722-
assert!(nodes[$node].fail_htlc_backwards(&payment_hash, &payment_secret));
693+
assert!(nodes[$node].fail_htlc_backwards(&payment_hash));
723694
} else {
724-
assert!(nodes[$node].claim_funds(PaymentPreimage(payment_hash.0), &payment_secret, amt));
695+
assert!(nodes[$node].claim_funds(PaymentPreimage(payment_hash.0)));
725696
}
726697
}
727698
},
@@ -788,15 +759,15 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
788759
},
789760
0x0e => {
790761
if chan_a_disconnected {
791-
nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::empty() });
792-
nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: InitFeatures::empty() });
762+
nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::known() });
763+
nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: InitFeatures::known() });
793764
chan_a_disconnected = false;
794765
}
795766
},
796767
0x0f => {
797768
if chan_b_disconnected {
798-
nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: InitFeatures::empty() });
799-
nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::empty() });
769+
nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: InitFeatures::known() });
770+
nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::known() });
800771
chan_b_disconnected = false;
801772
}
802773
},
@@ -860,9 +831,6 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
860831
0x24 => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 10_000_000, &mut payment_id); },
861832
0x25 => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 10_000_000, &mut payment_id); },
862833

863-
0x26 => { send_payment_with_secret!(nodes[0], (&nodes[1], chan_a), (&nodes[2], chan_b)); },
864-
0x27 => { send_payment_with_secret!(nodes[2], (&nodes[1], chan_b), (&nodes[0], chan_a)); },
865-
866834
0x28 => { send_payment(&nodes[0], &nodes[1], chan_a, 1_000_000, &mut payment_id); },
867835
0x29 => { send_payment(&nodes[1], &nodes[0], chan_a, 1_000_000, &mut payment_id); },
868836
0x2a => { send_payment(&nodes[1], &nodes[2], chan_b, 1_000_000, &mut payment_id); },
@@ -936,13 +904,13 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
936904

937905
// Next, make sure peers are all connected to each other
938906
if chan_a_disconnected {
939-
nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::empty() });
940-
nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: InitFeatures::empty() });
907+
nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::known() });
908+
nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: InitFeatures::known() });
941909
chan_a_disconnected = false;
942910
}
943911
if chan_b_disconnected {
944-
nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: InitFeatures::empty() });
945-
nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::empty() });
912+
nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: InitFeatures::known() });
913+
nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::known() });
946914
chan_b_disconnected = false;
947915
}
948916

fuzz/src/full_stack.rs

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

373373
let mut should_forward = false;
374-
let mut payments_received: Vec<(PaymentHash, Option<PaymentSecret>, u64)> = Vec::new();
374+
let mut payments_received: Vec<PaymentHash> = Vec::new();
375375
let mut payments_sent = 0;
376376
let mut pending_funding_generation: Vec<([u8; 32], u64, Script)> = Vec::new();
377377
let mut pending_funding_signatures = HashMap::new();
@@ -476,23 +476,32 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
476476
}
477477
},
478478
8 => {
479-
for (payment, payment_secret, amt) in payments_received.drain(..) {
479+
for payment in payments_received.drain(..) {
480480
// SHA256 is defined as XOR of all input bytes placed in the first byte, and 0s
481481
// for the remaining bytes. Thus, if not all remaining bytes are 0s we cannot
482482
// fulfill this HTLC, but if they are, we can just take the first byte and
483483
// place that anywhere in our preimage.
484484
if &payment.0[1..] != &[0; 31] {
485-
channelmanager.fail_htlc_backwards(&payment, &payment_secret);
485+
channelmanager.fail_htlc_backwards(&payment);
486486
} else {
487487
let mut payment_preimage = PaymentPreimage([0; 32]);
488488
payment_preimage.0[0] = payment.0[0];
489-
channelmanager.claim_funds(payment_preimage, &payment_secret, amt);
489+
channelmanager.claim_funds(payment_preimage);
490490
}
491491
}
492492
},
493+
16 => {
494+
let payment_preimage = PaymentPreimage(keys_manager.get_secure_random_bytes());
495+
let mut sha = Sha256::engine();
496+
sha.input(&payment_preimage.0[..]);
497+
let payment_hash = PaymentHash(Sha256::from_engine(sha).into_inner());
498+
// Note that this may fail - our hashes may collide and we'll end up trying to
499+
// double-register the same payment_hash.
500+
let _ = channelmanager.create_inbound_payment_for_hash(payment_hash, None, 1, 0);
501+
},
493502
9 => {
494-
for (payment, payment_secret, _) in payments_received.drain(..) {
495-
channelmanager.fail_htlc_backwards(&payment, &payment_secret);
503+
for payment in payments_received.drain(..) {
504+
channelmanager.fail_htlc_backwards(&payment);
496505
}
497506
},
498507
10 => {
@@ -571,9 +580,9 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
571580
Event::FundingGenerationReady { temporary_channel_id, channel_value_satoshis, output_script, .. } => {
572581
pending_funding_generation.push((temporary_channel_id, channel_value_satoshis, output_script));
573582
},
574-
Event::PaymentReceived { payment_hash, payment_secret, amt } => {
583+
Event::PaymentReceived { payment_hash, .. } => {
575584
//TODO: enhance by fetching random amounts from fuzz input?
576-
payments_received.push((payment_hash, payment_secret, amt));
585+
payments_received.push(payment_hash);
577586
},
578587
Event::PaymentSent {..} => {},
579588
Event::PaymentFailed {..} => {},

lightning-persister/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,9 @@ mod tests {
251251
check_persisted_data!(0);
252252

253253
// Send a few payments and make sure the monitors are updated to the latest.
254-
send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000, 8_000_000);
254+
send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
255255
check_persisted_data!(5);
256-
send_payment(&nodes[1], &vec!(&nodes[0])[..], 4000000, 4_000_000);
256+
send_payment(&nodes[1], &vec!(&nodes[0])[..], 4000000);
257257
check_persisted_data!(10);
258258

259259
// Force close because cooperative close doesn't result in any persisted

lightning/src/chain/chainmonitor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ mod tests {
344344
let (commitment_tx, htlc_tx) = {
345345
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 5_000_000).0;
346346
let mut txn = get_local_commitment_txn!(nodes[0], channel.2);
347-
claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage, 5_000_000);
347+
claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage);
348348

349349
assert_eq!(txn.len(), 2);
350350
(txn.remove(0), txn.remove(0))

0 commit comments

Comments
 (0)