Skip to content

Commit e3b969f

Browse files
Test serialization for malformed holding cell HTLCs
1 parent 025fdc1 commit e3b969f

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() {
@@ -571,13 +573,22 @@ fn high_prop_fees() {
571573

572574
#[test]
573575
fn fail_blinded_payment() {
576+
do_fail_blinded_payment(true);
577+
do_fail_blinded_payment(false);
578+
}
579+
580+
fn do_fail_blinded_payment(reload: bool) {
574581
let chanmon_cfgs = create_chanmon_cfgs(4);
575582
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
583+
let (new_persister, new_chain_monitor);
576584
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
577-
let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
585+
let node_3_deserialized;
586+
let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
578587
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
579588
create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0);
580-
let chan_upd = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0).0.contents;
589+
let (signed_chan_upd, _, chan_id_2_3, _) = create_announced_chan_between_nodes_with_value(
590+
&nodes, 2, 3, 1_000_000, 500_000_000);
591+
let chan_upd = signed_chan_upd.contents;
581592

582593
let amt_msat = 5000;
583594
let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[3], Some(amt_msat), None);
@@ -617,30 +628,54 @@ fn fail_blinded_payment() {
617628
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3]]], amt_msat, payment_hash,
618629
payment_secret);
619630

631+
if reload {
632+
nodes[3].node.peer_disconnected(&nodes[2].node.get_our_node_id());
633+
nodes[2].node.peer_disconnected(&nodes[3].node.get_our_node_id());
634+
}
635+
620636
nodes[3].node.fail_htlc_backwards(&payment_hash);
621637
expect_pending_htlcs_forwardable_conditions(nodes[3].node.get_and_clear_pending_events(),
622638
&[HTLCDestination::FailedPayment { payment_hash }]);
623639
nodes[3].node.process_pending_htlc_forwards();
624640

625-
// The last node should fail back with malformed since it's not the intro node.
626-
check_added_monitors!(nodes[3], 1);
627-
let (update_fail_malformed, commitment_signed) = {
628-
let msg_events = nodes[3].node.get_and_clear_pending_msg_events();
629-
assert_eq!(msg_events.len(), 1);
630-
match msg_events[0] {
631-
MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate {
632-
ref update_fail_malformed_htlcs, ref commitment_signed, ..
633-
}, .. } => {
641+
if reload {
642+
// We've just placed our malformed HTLC in the holding cell. Make sure we'll reload this holding
643+
// cell htlc on restart.
644+
let mon = get_monitor!(nodes[3], chan_id_2_3).encode();
645+
reload_node!(nodes[3], UserConfig::default(), &nodes[3].node.encode(), &[&mon],
646+
new_persister, new_chain_monitor, node_3_deserialized);
647+
648+
let mut reconnect_args = ReconnectArgs::new(&nodes[2], &nodes[3]);
649+
reconnect_args.pending_cell_htlc_malforms.0 = 1;
650+
reconnect_nodes(reconnect_args);
651+
expect_pending_htlcs_forwardable_conditions(nodes[2].node.get_and_clear_pending_events(),
652+
&[HTLCDestination::NextHopChannel {
653+
node_id: Some(nodes[3].node.get_our_node_id()),
654+
channel_id: chan_id_2_3,
655+
}]);
656+
nodes[2].node.process_pending_htlc_forwards();
657+
check_added_monitors(&nodes[2], 1);
658+
} else {
659+
// The last node should fail back with malformed since it's not the intro node.
660+
check_added_monitors!(nodes[3], 1);
661+
let (update_fail_malformed, commitment_signed) = {
662+
let msg_events = nodes[3].node.get_and_clear_pending_msg_events();
663+
assert_eq!(msg_events.len(), 1);
664+
match &msg_events[0] {
665+
MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate {
666+
ref update_fail_malformed_htlcs, ref commitment_signed, ..
667+
}, .. } => {
634668
assert_eq!(update_fail_malformed_htlcs.len(), 1);
635669
(update_fail_malformed_htlcs[0].clone(), commitment_signed.clone())
636670
},
637671
_ => panic!("Unexpected event"),
638-
}
639-
};
640-
assert_eq!(update_fail_malformed.sha256_of_onion, [0; 32]);
641-
assert_eq!(update_fail_malformed.failure_code, INVALID_ONION_BLINDING);
642-
nodes[2].node.handle_update_fail_malformed_htlc(&nodes[3].node.get_our_node_id(), &update_fail_malformed);
643-
do_commitment_signed_dance(&nodes[2], &nodes[3], &commitment_signed, true, false);
672+
}
673+
};
674+
assert_eq!(update_fail_malformed.sha256_of_onion, [0; 32]);
675+
assert_eq!(update_fail_malformed.failure_code, INVALID_ONION_BLINDING);
676+
nodes[2].node.handle_update_fail_malformed_htlc(&nodes[3].node.get_our_node_id(), &update_fail_malformed);
677+
do_commitment_signed_dance(&nodes[2], &nodes[3], &commitment_signed, true, false);
678+
}
644679

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

lightning/src/ln/functional_test_utils.rs

+29-9
Original file line numberDiff line numberDiff line change
@@ -3084,6 +3084,7 @@ pub struct ReconnectArgs<'a, 'b, 'c, 'd> {
30843084
pub pending_htlc_fails: (usize, usize),
30853085
pub pending_cell_htlc_claims: (usize, usize),
30863086
pub pending_cell_htlc_fails: (usize, usize),
3087+
pub pending_cell_htlc_malforms: (usize, usize),
30873088
pub pending_raa: (bool, bool),
30883089
}
30893090

@@ -3098,6 +3099,7 @@ impl<'a, 'b, 'c, 'd> ReconnectArgs<'a, 'b, 'c, 'd> {
30983099
pending_htlc_fails: (0, 0),
30993100
pending_cell_htlc_claims: (0, 0),
31003101
pending_cell_htlc_fails: (0, 0),
3102+
pending_cell_htlc_malforms: (0, 0),
31013103
pending_raa: (false, false),
31023104
}
31033105
}
@@ -3108,7 +3110,7 @@ impl<'a, 'b, 'c, 'd> ReconnectArgs<'a, 'b, 'c, 'd> {
31083110
pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
31093111
let ReconnectArgs {
31103112
node_a, node_b, send_channel_ready, pending_htlc_adds, pending_htlc_claims, pending_htlc_fails,
3111-
pending_cell_htlc_claims, pending_cell_htlc_fails, pending_raa
3113+
pending_cell_htlc_claims, pending_cell_htlc_fails, pending_cell_htlc_malforms, pending_raa
31123114
} = args;
31133115
node_a.node.peer_connected(&node_b.node.get_our_node_id(), &msgs::Init {
31143116
features: node_b.node.init_features(), networks: None, remote_network_address: None
@@ -3149,7 +3151,9 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
31493151
node_b.node.handle_channel_reestablish(&node_a.node.get_our_node_id(), &msg);
31503152
resp_1.push(handle_chan_reestablish_msgs!(node_b, node_a));
31513153
}
3152-
if pending_cell_htlc_claims.0 != 0 || pending_cell_htlc_fails.0 != 0 {
3154+
if pending_cell_htlc_claims.0 != 0 || pending_cell_htlc_fails.0 != 0 ||
3155+
pending_cell_htlc_malforms.0 != 0
3156+
{
31533157
check_added_monitors!(node_b, 1);
31543158
} else {
31553159
check_added_monitors!(node_b, 0);
@@ -3160,17 +3164,21 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
31603164
node_a.node.handle_channel_reestablish(&node_b.node.get_our_node_id(), &msg);
31613165
resp_2.push(handle_chan_reestablish_msgs!(node_a, node_b));
31623166
}
3163-
if pending_cell_htlc_claims.1 != 0 || pending_cell_htlc_fails.1 != 0 {
3167+
if pending_cell_htlc_claims.1 != 0 || pending_cell_htlc_fails.1 != 0 ||
3168+
pending_cell_htlc_malforms.1 != 0
3169+
{
31643170
check_added_monitors!(node_a, 1);
31653171
} else {
31663172
check_added_monitors!(node_a, 0);
31673173
}
31683174

31693175
// We don't yet support both needing updates, as that would require a different commitment dance:
31703176
assert!((pending_htlc_adds.0 == 0 && pending_htlc_claims.0 == 0 && pending_htlc_fails.0 == 0 &&
3171-
pending_cell_htlc_claims.0 == 0 && pending_cell_htlc_fails.0 == 0) ||
3177+
pending_cell_htlc_claims.0 == 0 && pending_cell_htlc_fails.0 == 0 &&
3178+
pending_cell_htlc_malforms.0 == 0) ||
31723179
(pending_htlc_adds.1 == 0 && pending_htlc_claims.1 == 0 && pending_htlc_fails.1 == 0 &&
3173-
pending_cell_htlc_claims.1 == 0 && pending_cell_htlc_fails.1 == 0));
3180+
pending_cell_htlc_claims.1 == 0 && pending_cell_htlc_fails.1 == 0 &&
3181+
pending_cell_htlc_malforms.1 == 0));
31743182

31753183
for chan_msgs in resp_1.drain(..) {
31763184
if send_channel_ready.0 {
@@ -3193,7 +3201,10 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
31933201
} else {
31943202
assert!(chan_msgs.1.is_none());
31953203
}
3196-
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 {
3204+
if pending_htlc_adds.0 != 0 || pending_htlc_claims.0 != 0 || pending_htlc_fails.0 != 0 ||
3205+
pending_cell_htlc_claims.0 != 0 || pending_cell_htlc_fails.0 != 0 ||
3206+
pending_cell_htlc_malforms.0 != 0
3207+
{
31973208
let commitment_update = chan_msgs.2.unwrap();
31983209
if pending_htlc_adds.0 != -1 { // We use -1 to denote a response commitment_signed
31993210
assert_eq!(commitment_update.update_add_htlcs.len(), pending_htlc_adds.0 as usize);
@@ -3202,7 +3213,7 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
32023213
}
32033214
assert_eq!(commitment_update.update_fulfill_htlcs.len(), pending_htlc_claims.0 + pending_cell_htlc_claims.0);
32043215
assert_eq!(commitment_update.update_fail_htlcs.len(), pending_htlc_fails.0 + pending_cell_htlc_fails.0);
3205-
assert!(commitment_update.update_fail_malformed_htlcs.is_empty());
3216+
assert_eq!(commitment_update.update_fail_malformed_htlcs.len(), pending_cell_htlc_malforms.0);
32063217
for update_add in commitment_update.update_add_htlcs {
32073218
node_a.node.handle_update_add_htlc(&node_b.node.get_our_node_id(), &update_add);
32083219
}
@@ -3212,6 +3223,9 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
32123223
for update_fail in commitment_update.update_fail_htlcs {
32133224
node_a.node.handle_update_fail_htlc(&node_b.node.get_our_node_id(), &update_fail);
32143225
}
3226+
for update_malformed in commitment_update.update_fail_malformed_htlcs {
3227+
node_a.node.handle_update_fail_malformed_htlc(&node_b.node.get_our_node_id(), &update_malformed);
3228+
}
32153229

32163230
if pending_htlc_adds.0 != -1 { // We use -1 to denote a response commitment_signed
32173231
commitment_signed_dance!(node_a, node_b, commitment_update.commitment_signed, false);
@@ -3252,14 +3266,17 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
32523266
} else {
32533267
assert!(chan_msgs.1.is_none());
32543268
}
3255-
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 {
3269+
if pending_htlc_adds.1 != 0 || pending_htlc_claims.1 != 0 || pending_htlc_fails.1 != 0 ||
3270+
pending_cell_htlc_claims.1 != 0 || pending_cell_htlc_fails.1 != 0 ||
3271+
pending_cell_htlc_malforms.1 != 0
3272+
{
32563273
let commitment_update = chan_msgs.2.unwrap();
32573274
if pending_htlc_adds.1 != -1 { // We use -1 to denote a response commitment_signed
32583275
assert_eq!(commitment_update.update_add_htlcs.len(), pending_htlc_adds.1 as usize);
32593276
}
32603277
assert_eq!(commitment_update.update_fulfill_htlcs.len(), pending_htlc_claims.1 + pending_cell_htlc_claims.1);
32613278
assert_eq!(commitment_update.update_fail_htlcs.len(), pending_htlc_fails.1 + pending_cell_htlc_fails.1);
3262-
assert!(commitment_update.update_fail_malformed_htlcs.is_empty());
3279+
assert_eq!(commitment_update.update_fail_malformed_htlcs.len(), pending_cell_htlc_malforms.1);
32633280
for update_add in commitment_update.update_add_htlcs {
32643281
node_b.node.handle_update_add_htlc(&node_a.node.get_our_node_id(), &update_add);
32653282
}
@@ -3269,6 +3286,9 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
32693286
for update_fail in commitment_update.update_fail_htlcs {
32703287
node_b.node.handle_update_fail_htlc(&node_a.node.get_our_node_id(), &update_fail);
32713288
}
3289+
for update_malformed in commitment_update.update_fail_malformed_htlcs {
3290+
node_b.node.handle_update_fail_malformed_htlc(&node_a.node.get_our_node_id(), &update_malformed);
3291+
}
32723292

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

0 commit comments

Comments
 (0)