Skip to content

Commit 838c32c

Browse files
Test serialization for malformed holding cell HTLCs
1 parent 93e718f commit 838c32c

File tree

2 files changed

+80
-26
lines changed

2 files changed

+80
-26
lines changed

lightning/src/ln/blinded_payment_tests.rs

+51-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() {
@@ -364,13 +366,21 @@ fn min_htlc() {
364366

365367
#[test]
366368
fn fail_blinded_payment() {
369+
do_fail_blinded_payment(true);
370+
do_fail_blinded_payment(false);
371+
}
372+
373+
fn do_fail_blinded_payment(reload: bool) {
374+
let (new_persister, new_chain_monitor, node_3_deserialized);
367375
let chanmon_cfgs = create_chanmon_cfgs(4);
368376
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
369377
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
370-
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
378+
let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
371379
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
372380
create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0);
373-
let chan_upd = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0).0.contents;
381+
let (signed_chan_upd, _, chan_id_2_3, _) = create_announced_chan_between_nodes_with_value(
382+
&nodes, 2, 3, 1_000_000, 500_000_000);
383+
let chan_upd = signed_chan_upd.contents;
374384

375385
let amt_msat = 5000;
376386
let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[3], Some(amt_msat), None);
@@ -410,30 +420,54 @@ fn fail_blinded_payment() {
410420
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3]]], amt_msat, payment_hash,
411421
payment_secret);
412422

423+
if reload {
424+
nodes[3].node.peer_disconnected(&nodes[2].node.get_our_node_id());
425+
nodes[2].node.peer_disconnected(&nodes[3].node.get_our_node_id());
426+
}
427+
413428
nodes[3].node.fail_htlc_backwards(&payment_hash);
414429
expect_pending_htlcs_forwardable_conditions(nodes[3].node.get_and_clear_pending_events(),
415430
&[HTLCDestination::FailedPayment { payment_hash }]);
416431
nodes[3].node.process_pending_htlc_forwards();
417432

418-
// The last node should fail back with malformed since it's not the intro node.
419-
check_added_monitors!(nodes[3], 1);
420-
let (update_fail_malformed, commitment_signed) = {
421-
let msg_events = nodes[3].node.get_and_clear_pending_msg_events();
422-
assert_eq!(msg_events.len(), 1);
423-
match msg_events[0] {
424-
MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate {
425-
ref update_fail_malformed_htlcs, ref commitment_signed, ..
426-
}, .. } => {
433+
if reload {
434+
// We've just placed our malformed HTLC in the holding cell. Make sure we'll reload this holding
435+
// cell htlc on restart.
436+
let mon = get_monitor!(nodes[3], chan_id_2_3).encode();
437+
reload_node!(nodes[3], UserConfig::default(), &nodes[3].node.encode(), &[&mon],
438+
new_persister, new_chain_monitor, node_3_deserialized);
439+
440+
let mut reconnect_args = ReconnectArgs::new(&nodes[2], &nodes[3]);
441+
reconnect_args.pending_cell_htlc_malforms.0 = 1;
442+
reconnect_nodes(reconnect_args);
443+
expect_pending_htlcs_forwardable_conditions(nodes[2].node.get_and_clear_pending_events(),
444+
&[HTLCDestination::NextHopChannel {
445+
node_id: Some(nodes[3].node.get_our_node_id()),
446+
channel_id: chan_id_2_3,
447+
}]);
448+
nodes[2].node.process_pending_htlc_forwards();
449+
check_added_monitors(&nodes[2], 1);
450+
} else {
451+
// The last node should fail back with malformed since it's not the intro node.
452+
check_added_monitors!(nodes[3], 1);
453+
let (update_fail_malformed, commitment_signed) = {
454+
let msg_events = nodes[3].node.get_and_clear_pending_msg_events();
455+
assert_eq!(msg_events.len(), 1);
456+
match &msg_events[0] {
457+
MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate {
458+
ref update_fail_malformed_htlcs, ref commitment_signed, ..
459+
}, .. } => {
427460
assert_eq!(update_fail_malformed_htlcs.len(), 1);
428461
(update_fail_malformed_htlcs[0].clone(), commitment_signed.clone())
429462
},
430463
_ => panic!("Unexpected event"),
431-
}
432-
};
433-
assert_eq!(update_fail_malformed.sha256_of_onion, [0; 32]);
434-
assert_eq!(update_fail_malformed.failure_code, INVALID_ONION_BLINDING);
435-
nodes[2].node.handle_update_fail_malformed_htlc(&nodes[3].node.get_our_node_id(), &update_fail_malformed);
436-
do_commitment_signed_dance(&nodes[2], &nodes[3], &commitment_signed, true, false);
464+
}
465+
};
466+
assert_eq!(update_fail_malformed.sha256_of_onion, [0; 32]);
467+
assert_eq!(update_fail_malformed.failure_code, INVALID_ONION_BLINDING);
468+
nodes[2].node.handle_update_fail_malformed_htlc(&nodes[3].node.get_our_node_id(), &update_fail_malformed);
469+
do_commitment_signed_dance(&nodes[2], &nodes[3], &commitment_signed, true, false);
470+
}
437471

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

lightning/src/ln/functional_test_utils.rs

+29-9
Original file line numberDiff line numberDiff line change
@@ -3026,6 +3026,7 @@ pub struct ReconnectArgs<'a, 'b, 'c, 'd> {
30263026
pub pending_htlc_fails: (usize, usize),
30273027
pub pending_cell_htlc_claims: (usize, usize),
30283028
pub pending_cell_htlc_fails: (usize, usize),
3029+
pub pending_cell_htlc_malforms: (usize, usize),
30293030
pub pending_raa: (bool, bool),
30303031
}
30313032

@@ -3040,6 +3041,7 @@ impl<'a, 'b, 'c, 'd> ReconnectArgs<'a, 'b, 'c, 'd> {
30403041
pending_htlc_fails: (0, 0),
30413042
pending_cell_htlc_claims: (0, 0),
30423043
pending_cell_htlc_fails: (0, 0),
3044+
pending_cell_htlc_malforms: (0, 0),
30433045
pending_raa: (false, false),
30443046
}
30453047
}
@@ -3050,7 +3052,7 @@ impl<'a, 'b, 'c, 'd> ReconnectArgs<'a, 'b, 'c, 'd> {
30503052
pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
30513053
let ReconnectArgs {
30523054
node_a, node_b, send_channel_ready, pending_htlc_adds, pending_htlc_claims, pending_htlc_fails,
3053-
pending_cell_htlc_claims, pending_cell_htlc_fails, pending_raa
3055+
pending_cell_htlc_claims, pending_cell_htlc_fails, pending_cell_htlc_malforms, pending_raa
30543056
} = args;
30553057
node_a.node.peer_connected(&node_b.node.get_our_node_id(), &msgs::Init {
30563058
features: node_b.node.init_features(), networks: None, remote_network_address: None
@@ -3091,7 +3093,9 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
30913093
node_b.node.handle_channel_reestablish(&node_a.node.get_our_node_id(), &msg);
30923094
resp_1.push(handle_chan_reestablish_msgs!(node_b, node_a));
30933095
}
3094-
if pending_cell_htlc_claims.0 != 0 || pending_cell_htlc_fails.0 != 0 {
3096+
if pending_cell_htlc_claims.0 != 0 || pending_cell_htlc_fails.0 != 0 ||
3097+
pending_cell_htlc_malforms.0 != 0
3098+
{
30953099
check_added_monitors!(node_b, 1);
30963100
} else {
30973101
check_added_monitors!(node_b, 0);
@@ -3102,17 +3106,21 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
31023106
node_a.node.handle_channel_reestablish(&node_b.node.get_our_node_id(), &msg);
31033107
resp_2.push(handle_chan_reestablish_msgs!(node_a, node_b));
31043108
}
3105-
if pending_cell_htlc_claims.1 != 0 || pending_cell_htlc_fails.1 != 0 {
3109+
if pending_cell_htlc_claims.1 != 0 || pending_cell_htlc_fails.1 != 0 ||
3110+
pending_cell_htlc_malforms.1 != 0
3111+
{
31063112
check_added_monitors!(node_a, 1);
31073113
} else {
31083114
check_added_monitors!(node_a, 0);
31093115
}
31103116

31113117
// We don't yet support both needing updates, as that would require a different commitment dance:
31123118
assert!((pending_htlc_adds.0 == 0 && pending_htlc_claims.0 == 0 && pending_htlc_fails.0 == 0 &&
3113-
pending_cell_htlc_claims.0 == 0 && pending_cell_htlc_fails.0 == 0) ||
3119+
pending_cell_htlc_claims.0 == 0 && pending_cell_htlc_fails.0 == 0 &&
3120+
pending_cell_htlc_malforms.0 == 0) ||
31143121
(pending_htlc_adds.1 == 0 && pending_htlc_claims.1 == 0 && pending_htlc_fails.1 == 0 &&
3115-
pending_cell_htlc_claims.1 == 0 && pending_cell_htlc_fails.1 == 0));
3122+
pending_cell_htlc_claims.1 == 0 && pending_cell_htlc_fails.1 == 0 &&
3123+
pending_cell_htlc_malforms.1 == 0));
31163124

31173125
for chan_msgs in resp_1.drain(..) {
31183126
if send_channel_ready.0 {
@@ -3135,7 +3143,10 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
31353143
} else {
31363144
assert!(chan_msgs.1.is_none());
31373145
}
3138-
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 {
3146+
if pending_htlc_adds.0 != 0 || pending_htlc_claims.0 != 0 || pending_htlc_fails.0 != 0 ||
3147+
pending_cell_htlc_claims.0 != 0 || pending_cell_htlc_fails.0 != 0 ||
3148+
pending_cell_htlc_malforms.0 != 0
3149+
{
31393150
let commitment_update = chan_msgs.2.unwrap();
31403151
if pending_htlc_adds.0 != -1 { // We use -1 to denote a response commitment_signed
31413152
assert_eq!(commitment_update.update_add_htlcs.len(), pending_htlc_adds.0 as usize);
@@ -3144,7 +3155,7 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
31443155
}
31453156
assert_eq!(commitment_update.update_fulfill_htlcs.len(), pending_htlc_claims.0 + pending_cell_htlc_claims.0);
31463157
assert_eq!(commitment_update.update_fail_htlcs.len(), pending_htlc_fails.0 + pending_cell_htlc_fails.0);
3147-
assert!(commitment_update.update_fail_malformed_htlcs.is_empty());
3158+
assert_eq!(commitment_update.update_fail_malformed_htlcs.len(), pending_cell_htlc_malforms.0);
31483159
for update_add in commitment_update.update_add_htlcs {
31493160
node_a.node.handle_update_add_htlc(&node_b.node.get_our_node_id(), &update_add);
31503161
}
@@ -3154,6 +3165,9 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
31543165
for update_fail in commitment_update.update_fail_htlcs {
31553166
node_a.node.handle_update_fail_htlc(&node_b.node.get_our_node_id(), &update_fail);
31563167
}
3168+
for update_malformed in commitment_update.update_fail_malformed_htlcs {
3169+
node_a.node.handle_update_fail_malformed_htlc(&node_b.node.get_our_node_id(), &update_malformed);
3170+
}
31573171

31583172
if pending_htlc_adds.0 != -1 { // We use -1 to denote a response commitment_signed
31593173
commitment_signed_dance!(node_a, node_b, commitment_update.commitment_signed, false);
@@ -3194,14 +3208,17 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
31943208
} else {
31953209
assert!(chan_msgs.1.is_none());
31963210
}
3197-
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 {
3211+
if pending_htlc_adds.1 != 0 || pending_htlc_claims.1 != 0 || pending_htlc_fails.1 != 0 ||
3212+
pending_cell_htlc_claims.1 != 0 || pending_cell_htlc_fails.1 != 0 ||
3213+
pending_cell_htlc_malforms.1 != 0
3214+
{
31983215
let commitment_update = chan_msgs.2.unwrap();
31993216
if pending_htlc_adds.1 != -1 { // We use -1 to denote a response commitment_signed
32003217
assert_eq!(commitment_update.update_add_htlcs.len(), pending_htlc_adds.1 as usize);
32013218
}
32023219
assert_eq!(commitment_update.update_fulfill_htlcs.len(), pending_htlc_claims.1 + pending_cell_htlc_claims.1);
32033220
assert_eq!(commitment_update.update_fail_htlcs.len(), pending_htlc_fails.1 + pending_cell_htlc_fails.1);
3204-
assert!(commitment_update.update_fail_malformed_htlcs.is_empty());
3221+
assert_eq!(commitment_update.update_fail_malformed_htlcs.len(), pending_cell_htlc_malforms.1);
32053222
for update_add in commitment_update.update_add_htlcs {
32063223
node_b.node.handle_update_add_htlc(&node_a.node.get_our_node_id(), &update_add);
32073224
}
@@ -3211,6 +3228,9 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
32113228
for update_fail in commitment_update.update_fail_htlcs {
32123229
node_b.node.handle_update_fail_htlc(&node_a.node.get_our_node_id(), &update_fail);
32133230
}
3231+
for update_malformed in commitment_update.update_fail_malformed_htlcs {
3232+
node_b.node.handle_update_fail_malformed_htlc(&node_a.node.get_our_node_id(), &update_malformed);
3233+
}
32143234

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

0 commit comments

Comments
 (0)