Skip to content

Commit 9683545

Browse files
Test serialization for malformed holding cell HTLCs
1 parent ec58ced commit 9683545

File tree

2 files changed

+81
-26
lines changed

2 files changed

+81
-26
lines changed

lightning/src/ln/blinded_payment_tests.rs

+52-17
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ use crate::ln::outbound_payment::Retry;
2222
use crate::prelude::*;
2323
use crate::routing::router::{PaymentParameters, RouteParameters};
2424
use crate::util::config::UserConfig;
25+
use crate::util::ser::Writeable;
26+
use crate::util::test_utils;
2527

2628
#[test]
2729
fn simple_blinded_payment() {
@@ -444,13 +446,22 @@ fn high_prop_fees() {
444446

445447
#[test]
446448
fn fail_blinded_payment() {
449+
do_fail_blinded_payment(true);
450+
do_fail_blinded_payment(false);
451+
}
452+
453+
fn do_fail_blinded_payment(reload: bool) {
447454
let chanmon_cfgs = create_chanmon_cfgs(4);
448455
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
456+
let (new_persister, new_chain_monitor);
449457
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
450-
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
458+
let node_3_deserialized;
459+
let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
451460
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
452461
create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0);
453-
let chan_upd = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0).0.contents;
462+
let (signed_chan_upd, _, chan_id_2_3, _) = create_announced_chan_between_nodes_with_value(
463+
&nodes, 2, 3, 1_000_000, 500_000_000);
464+
let chan_upd = signed_chan_upd.contents;
454465

455466
let amt_msat = 5000;
456467
let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[3], Some(amt_msat), None);
@@ -490,30 +501,54 @@ fn fail_blinded_payment() {
490501
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3]]], amt_msat, payment_hash,
491502
payment_secret);
492503

504+
if reload {
505+
nodes[3].node.peer_disconnected(&nodes[2].node.get_our_node_id());
506+
nodes[2].node.peer_disconnected(&nodes[3].node.get_our_node_id());
507+
}
508+
493509
nodes[3].node.fail_htlc_backwards(&payment_hash);
494510
expect_pending_htlcs_forwardable_conditions(nodes[3].node.get_and_clear_pending_events(),
495511
&[HTLCDestination::FailedPayment { payment_hash }]);
496512
nodes[3].node.process_pending_htlc_forwards();
497513

498-
// The last node should fail back with malformed since it's not the intro node.
499-
check_added_monitors!(nodes[3], 1);
500-
let (update_fail_malformed, commitment_signed) = {
501-
let msg_events = nodes[3].node.get_and_clear_pending_msg_events();
502-
assert_eq!(msg_events.len(), 1);
503-
match msg_events[0] {
504-
MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate {
505-
ref update_fail_malformed_htlcs, ref commitment_signed, ..
506-
}, .. } => {
514+
if reload {
515+
// We've just placed our malformed HTLC in the holding cell. Make sure we'll reload this holding
516+
// cell htlc on restart.
517+
let mon = get_monitor!(nodes[3], chan_id_2_3).encode();
518+
reload_node!(nodes[3], UserConfig::default(), &nodes[3].node.encode(), &[&mon],
519+
new_persister, new_chain_monitor, node_3_deserialized);
520+
521+
let mut reconnect_args = ReconnectArgs::new(&nodes[2], &nodes[3]);
522+
reconnect_args.pending_cell_htlc_malforms.0 = 1;
523+
reconnect_nodes(reconnect_args);
524+
expect_pending_htlcs_forwardable_conditions(nodes[2].node.get_and_clear_pending_events(),
525+
&[HTLCDestination::NextHopChannel {
526+
node_id: Some(nodes[3].node.get_our_node_id()),
527+
channel_id: chan_id_2_3,
528+
}]);
529+
nodes[2].node.process_pending_htlc_forwards();
530+
check_added_monitors(&nodes[2], 1);
531+
} else {
532+
// The last node should fail back with malformed since it's not the intro node.
533+
check_added_monitors!(nodes[3], 1);
534+
let (update_fail_malformed, commitment_signed) = {
535+
let msg_events = nodes[3].node.get_and_clear_pending_msg_events();
536+
assert_eq!(msg_events.len(), 1);
537+
match &msg_events[0] {
538+
MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate {
539+
ref update_fail_malformed_htlcs, ref commitment_signed, ..
540+
}, .. } => {
507541
assert_eq!(update_fail_malformed_htlcs.len(), 1);
508542
(update_fail_malformed_htlcs[0].clone(), commitment_signed.clone())
509543
},
510544
_ => panic!("Unexpected event"),
511-
}
512-
};
513-
assert_eq!(update_fail_malformed.sha256_of_onion, [0; 32]);
514-
assert_eq!(update_fail_malformed.failure_code, INVALID_ONION_BLINDING);
515-
nodes[2].node.handle_update_fail_malformed_htlc(&nodes[3].node.get_our_node_id(), &update_fail_malformed);
516-
do_commitment_signed_dance(&nodes[2], &nodes[3], &commitment_signed, true, false);
545+
}
546+
};
547+
assert_eq!(update_fail_malformed.sha256_of_onion, [0; 32]);
548+
assert_eq!(update_fail_malformed.failure_code, INVALID_ONION_BLINDING);
549+
nodes[2].node.handle_update_fail_malformed_htlc(&nodes[3].node.get_our_node_id(), &update_fail_malformed);
550+
do_commitment_signed_dance(&nodes[2], &nodes[3], &commitment_signed, true, false);
551+
}
517552

518553
// The intro node fails back with the invalid_onion_blinding error.
519554
let (update_fail, commitment_signed) = {

lightning/src/ln/functional_test_utils.rs

+29-9
Original file line numberDiff line numberDiff line change
@@ -3035,6 +3035,7 @@ pub struct ReconnectArgs<'a, 'b, 'c, 'd> {
30353035
pub pending_htlc_fails: (usize, usize),
30363036
pub pending_cell_htlc_claims: (usize, usize),
30373037
pub pending_cell_htlc_fails: (usize, usize),
3038+
pub pending_cell_htlc_malforms: (usize, usize),
30383039
pub pending_raa: (bool, bool),
30393040
}
30403041

@@ -3049,6 +3050,7 @@ impl<'a, 'b, 'c, 'd> ReconnectArgs<'a, 'b, 'c, 'd> {
30493050
pending_htlc_fails: (0, 0),
30503051
pending_cell_htlc_claims: (0, 0),
30513052
pending_cell_htlc_fails: (0, 0),
3053+
pending_cell_htlc_malforms: (0, 0),
30523054
pending_raa: (false, false),
30533055
}
30543056
}
@@ -3059,7 +3061,7 @@ impl<'a, 'b, 'c, 'd> ReconnectArgs<'a, 'b, 'c, 'd> {
30593061
pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
30603062
let ReconnectArgs {
30613063
node_a, node_b, send_channel_ready, pending_htlc_adds, pending_htlc_claims, pending_htlc_fails,
3062-
pending_cell_htlc_claims, pending_cell_htlc_fails, pending_raa
3064+
pending_cell_htlc_claims, pending_cell_htlc_fails, pending_cell_htlc_malforms, pending_raa
30633065
} = args;
30643066
node_a.node.peer_connected(&node_b.node.get_our_node_id(), &msgs::Init {
30653067
features: node_b.node.init_features(), networks: None, remote_network_address: None
@@ -3100,7 +3102,9 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
31003102
node_b.node.handle_channel_reestablish(&node_a.node.get_our_node_id(), &msg);
31013103
resp_1.push(handle_chan_reestablish_msgs!(node_b, node_a));
31023104
}
3103-
if pending_cell_htlc_claims.0 != 0 || pending_cell_htlc_fails.0 != 0 {
3105+
if pending_cell_htlc_claims.0 != 0 || pending_cell_htlc_fails.0 != 0 ||
3106+
pending_cell_htlc_malforms.0 != 0
3107+
{
31043108
check_added_monitors!(node_b, 1);
31053109
} else {
31063110
check_added_monitors!(node_b, 0);
@@ -3111,17 +3115,21 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
31113115
node_a.node.handle_channel_reestablish(&node_b.node.get_our_node_id(), &msg);
31123116
resp_2.push(handle_chan_reestablish_msgs!(node_a, node_b));
31133117
}
3114-
if pending_cell_htlc_claims.1 != 0 || pending_cell_htlc_fails.1 != 0 {
3118+
if pending_cell_htlc_claims.1 != 0 || pending_cell_htlc_fails.1 != 0 ||
3119+
pending_cell_htlc_malforms.1 != 0
3120+
{
31153121
check_added_monitors!(node_a, 1);
31163122
} else {
31173123
check_added_monitors!(node_a, 0);
31183124
}
31193125

31203126
// We don't yet support both needing updates, as that would require a different commitment dance:
31213127
assert!((pending_htlc_adds.0 == 0 && pending_htlc_claims.0 == 0 && pending_htlc_fails.0 == 0 &&
3122-
pending_cell_htlc_claims.0 == 0 && pending_cell_htlc_fails.0 == 0) ||
3128+
pending_cell_htlc_claims.0 == 0 && pending_cell_htlc_fails.0 == 0 &&
3129+
pending_cell_htlc_malforms.0 == 0) ||
31233130
(pending_htlc_adds.1 == 0 && pending_htlc_claims.1 == 0 && pending_htlc_fails.1 == 0 &&
3124-
pending_cell_htlc_claims.1 == 0 && pending_cell_htlc_fails.1 == 0));
3131+
pending_cell_htlc_claims.1 == 0 && pending_cell_htlc_fails.1 == 0 &&
3132+
pending_cell_htlc_malforms.1 == 0));
31253133

31263134
for chan_msgs in resp_1.drain(..) {
31273135
if send_channel_ready.0 {
@@ -3144,7 +3152,10 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
31443152
} else {
31453153
assert!(chan_msgs.1.is_none());
31463154
}
3147-
if pending_htlc_adds.0 != 0 || pending_htlc_claims.0 != 0 || pending_htlc_fails.0 != 0 || pending_cell_htlc_claims.0 != 0 || pending_cell_htlc_fails.0 != 0 {
3155+
if pending_htlc_adds.0 != 0 || pending_htlc_claims.0 != 0 || pending_htlc_fails.0 != 0 ||
3156+
pending_cell_htlc_claims.0 != 0 || pending_cell_htlc_fails.0 != 0 ||
3157+
pending_cell_htlc_malforms.0 != 0
3158+
{
31483159
let commitment_update = chan_msgs.2.unwrap();
31493160
if pending_htlc_adds.0 != -1 { // We use -1 to denote a response commitment_signed
31503161
assert_eq!(commitment_update.update_add_htlcs.len(), pending_htlc_adds.0 as usize);
@@ -3153,7 +3164,7 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
31533164
}
31543165
assert_eq!(commitment_update.update_fulfill_htlcs.len(), pending_htlc_claims.0 + pending_cell_htlc_claims.0);
31553166
assert_eq!(commitment_update.update_fail_htlcs.len(), pending_htlc_fails.0 + pending_cell_htlc_fails.0);
3156-
assert!(commitment_update.update_fail_malformed_htlcs.is_empty());
3167+
assert_eq!(commitment_update.update_fail_malformed_htlcs.len(), pending_cell_htlc_malforms.0);
31573168
for update_add in commitment_update.update_add_htlcs {
31583169
node_a.node.handle_update_add_htlc(&node_b.node.get_our_node_id(), &update_add);
31593170
}
@@ -3163,6 +3174,9 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
31633174
for update_fail in commitment_update.update_fail_htlcs {
31643175
node_a.node.handle_update_fail_htlc(&node_b.node.get_our_node_id(), &update_fail);
31653176
}
3177+
for update_malformed in commitment_update.update_fail_malformed_htlcs {
3178+
node_a.node.handle_update_fail_malformed_htlc(&node_b.node.get_our_node_id(), &update_malformed);
3179+
}
31663180

31673181
if pending_htlc_adds.0 != -1 { // We use -1 to denote a response commitment_signed
31683182
commitment_signed_dance!(node_a, node_b, commitment_update.commitment_signed, false);
@@ -3203,14 +3217,17 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
32033217
} else {
32043218
assert!(chan_msgs.1.is_none());
32053219
}
3206-
if pending_htlc_adds.1 != 0 || pending_htlc_claims.1 != 0 || pending_htlc_fails.1 != 0 || pending_cell_htlc_claims.1 != 0 || pending_cell_htlc_fails.1 != 0 {
3220+
if pending_htlc_adds.1 != 0 || pending_htlc_claims.1 != 0 || pending_htlc_fails.1 != 0 ||
3221+
pending_cell_htlc_claims.1 != 0 || pending_cell_htlc_fails.1 != 0 ||
3222+
pending_cell_htlc_malforms.1 != 0
3223+
{
32073224
let commitment_update = chan_msgs.2.unwrap();
32083225
if pending_htlc_adds.1 != -1 { // We use -1 to denote a response commitment_signed
32093226
assert_eq!(commitment_update.update_add_htlcs.len(), pending_htlc_adds.1 as usize);
32103227
}
32113228
assert_eq!(commitment_update.update_fulfill_htlcs.len(), pending_htlc_claims.1 + pending_cell_htlc_claims.1);
32123229
assert_eq!(commitment_update.update_fail_htlcs.len(), pending_htlc_fails.1 + pending_cell_htlc_fails.1);
3213-
assert!(commitment_update.update_fail_malformed_htlcs.is_empty());
3230+
assert_eq!(commitment_update.update_fail_malformed_htlcs.len(), pending_cell_htlc_malforms.1);
32143231
for update_add in commitment_update.update_add_htlcs {
32153232
node_b.node.handle_update_add_htlc(&node_a.node.get_our_node_id(), &update_add);
32163233
}
@@ -3220,6 +3237,9 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
32203237
for update_fail in commitment_update.update_fail_htlcs {
32213238
node_b.node.handle_update_fail_htlc(&node_a.node.get_our_node_id(), &update_fail);
32223239
}
3240+
for update_malformed in commitment_update.update_fail_malformed_htlcs {
3241+
node_b.node.handle_update_fail_malformed_htlc(&node_a.node.get_our_node_id(), &update_malformed);
3242+
}
32233243

32243244
if pending_htlc_adds.1 != -1 { // We use -1 to denote a response commitment_signed
32253245
commitment_signed_dance!(node_b, node_a, commitment_update.commitment_signed, false);

0 commit comments

Comments
 (0)