Skip to content

Commit 795b46e

Browse files
committed
Do not generate a channel-closed mon update for never-signed chans
The full_stack_target managed to find a bug where, if we receive a funding_created message which has a channel_id identical to an existing channel, we'll end up (a) having the monitor update for the new channel fail (due to duplicate outpoint), (b) creating a monitor update for the new channel as we force-close it, (c) panicing due to the force-close monitor update is applied to the original channel and is considered out-of-order. Obviously we shouldn't be creating a force-close monitor update for a channel which can never appear on chain, so we do that here and add a test which previously failed and checks a few duplicate-channel-id cases.
1 parent 23a1d7a commit 795b46e

File tree

4 files changed

+162
-11
lines changed

4 files changed

+162
-11
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,6 +1424,13 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
14241424
/// May panic if the funding_txo is duplicative with some other channel (note that this should
14251425
/// be trivially prevented by using unique funding transaction keys per-channel).
14261426
pub fn funding_transaction_generated(&self, temporary_channel_id: &[u8; 32], funding_txo: OutPoint) {
1427+
self.internal_funding_transaction_generated(temporary_channel_id, funding_txo, true);
1428+
}
1429+
#[cfg(test)]
1430+
pub(crate) fn funding_transaction_generated_dup_funding_id(&self, temporary_channel_id: &[u8; 32], funding_txo: OutPoint) {
1431+
self.internal_funding_transaction_generated(temporary_channel_id, funding_txo, false);
1432+
}
1433+
fn internal_funding_transaction_generated(&self, temporary_channel_id: &[u8; 32], funding_txo: OutPoint, panic_on_dup: bool) {
14271434
let _consistency_lock = self.total_consistency_lock.read().unwrap();
14281435

14291436
let (chan, msg) = {
@@ -1452,7 +1459,7 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
14521459
});
14531460
match channel_state.by_id.entry(chan.channel_id()) {
14541461
hash_map::Entry::Occupied(_) => {
1455-
panic!("Generated duplicate funding txid?");
1462+
if panic_on_dup { panic!("Generated duplicate funding txid?"); }
14561463
},
14571464
hash_map::Entry::Vacant(e) => {
14581465
e.insert(chan);
@@ -2334,7 +2341,12 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
23342341
// channel, not the temporary_channel_id. This is compatible with ourselves, but the
23352342
// spec is somewhat ambiguous here. Not a huge deal since we'll send error messages for
23362343
// any messages referencing a previously-closed channel anyway.
2337-
return Err(MsgHandleErrInternal::from_finish_shutdown("ChannelMonitor storage failure".to_owned(), funding_msg.channel_id, chan.force_shutdown(true), None));
2344+
// We do not do a force-close here as that would generate a monitor update for
2345+
// a monitor that we didn't manage to store (and that we don't care about - we
2346+
// don't respond with the funding_signed so the channel can never go on chain).
2347+
let (_funding_txo_option, _monitor_update, failed_htlcs) = chan.force_shutdown(true);
2348+
assert!(failed_htlcs.is_empty());
2349+
return Err(MsgHandleErrInternal::send_err_msg_no_close("ChannelMonitor storage failure".to_owned(), funding_msg.channel_id));
23382350
},
23392351
ChannelMonitorUpdateErr::TemporaryFailure => {
23402352
// There's no problem signing a counterparty's funding transaction if our monitor

lightning/src/ln/functional_test_utils.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,11 @@ pub fn create_announced_chan_between_nodes<'a, 'b, 'c, 'd>(nodes: &'a Vec<Node<'
487487

488488
pub fn create_announced_chan_between_nodes_with_value<'a, 'b, 'c, 'd>(nodes: &'a Vec<Node<'b, 'c, 'd>>, a: usize, b: usize, channel_value: u64, push_msat: u64, a_flags: InitFeatures, b_flags: InitFeatures) -> (msgs::ChannelUpdate, msgs::ChannelUpdate, [u8; 32], Transaction) {
489489
let chan_announcement = create_chan_between_nodes_with_value(&nodes[a], &nodes[b], channel_value, push_msat, a_flags, b_flags);
490+
update_nodes_with_chan_announce(nodes, a, b, &chan_announcement.0, &chan_announcement.1, &chan_announcement.2);
491+
(chan_announcement.1, chan_announcement.2, chan_announcement.3, chan_announcement.4)
492+
}
490493

494+
pub fn update_nodes_with_chan_announce<'a, 'b, 'c, 'd>(nodes: &'a Vec<Node<'b, 'c, 'd>>, a: usize, b: usize, ann: &msgs::ChannelAnnouncement, upd_1: &msgs::ChannelUpdate, upd_2: &msgs::ChannelUpdate) {
491495
nodes[a].node.broadcast_node_announcement([0, 0, 0], [0; 32], Vec::new());
492496
let a_events = nodes[a].node.get_and_clear_pending_msg_events();
493497
assert_eq!(a_events.len(), 1);
@@ -509,13 +513,12 @@ pub fn create_announced_chan_between_nodes_with_value<'a, 'b, 'c, 'd>(nodes: &'a
509513
};
510514

511515
for node in nodes {
512-
assert!(node.net_graph_msg_handler.handle_channel_announcement(&chan_announcement.0).unwrap());
513-
node.net_graph_msg_handler.handle_channel_update(&chan_announcement.1).unwrap();
514-
node.net_graph_msg_handler.handle_channel_update(&chan_announcement.2).unwrap();
516+
assert!(node.net_graph_msg_handler.handle_channel_announcement(ann).unwrap());
517+
node.net_graph_msg_handler.handle_channel_update(upd_1).unwrap();
518+
node.net_graph_msg_handler.handle_channel_update(upd_2).unwrap();
515519
node.net_graph_msg_handler.handle_node_announcement(&a_node_announcement).unwrap();
516520
node.net_graph_msg_handler.handle_node_announcement(&b_node_announcement).unwrap();
517521
}
518-
(chan_announcement.1, chan_announcement.2, chan_announcement.3, chan_announcement.4)
519522
}
520523

521524
macro_rules! check_spends {

lightning/src/ln/onion_route_tests.rs renamed to lightning/src/ln/general_unit_tests.rs

Lines changed: 140 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,16 @@
77
// You may not use this file except in accordance with one or both of these
88
// licenses.
99

10-
//! Tests of the onion error messages/codes which are returned when routing a payment fails.
11-
//! These tests work by standing up full nodes and route payments across the network, checking the
12-
//! returned errors decode to the correct thing.
10+
// General unit tests that cross several files. Basically functions as an overflow for taking
11+
// smaller tests out of functional_tests.rs to avoid making it any larger.
1312

1413
use chain::channelmonitor::{CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS};
1514
use ln::channelmanager::{HTLCForwardInfo, PaymentPreimage, PaymentHash};
1615
use ln::onion_utils;
1716
use routing::router::{Route, get_route};
1817
use ln::features::InitFeatures;
1918
use ln::msgs;
20-
use ln::msgs::{ChannelMessageHandler, HTLCFailChannelUpdate, OptionalField};
19+
use ln::msgs::{ChannelMessageHandler, ErrorAction, HTLCFailChannelUpdate, OptionalField};
2120
use util::test_utils;
2221
use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsProvider};
2322
use util::ser::{Writeable, Writer};
@@ -38,6 +37,11 @@ use std::io;
3837

3938
use ln::functional_test_utils::*;
4039

40+
41+
// Tests of the onion error messages/codes which are returned when routing a payment fails.
42+
// These tests work by standing up full nodes and route payments across the network, checking the
43+
// returned errors decode to the correct thing.
44+
4145
fn run_onion_failure_test<F1,F2>(_name: &str, test_case: u8, nodes: &Vec<Node>, route: &Route, payment_hash: &PaymentHash, callback_msg: F1, callback_node: F2, expected_retryable: bool, expected_error_code: Option<u16>, expected_channel_update: Option<HTLCFailChannelUpdate>)
4246
where F1: for <'a> FnMut(&'a mut msgs::UpdateAddHTLC),
4347
F2: FnMut(),
@@ -511,3 +515,135 @@ fn test_onion_failure() {
511515
}
512516

513517

518+
#[test]
519+
fn test_duplicate_chan_id() {
520+
// Test that if a given peer tries to open a channel with the same channel_id as one that is
521+
// already open we reject it and keep the old channel.
522+
//
523+
// Previously, full_stack_target managed to figure out that if you tried to open two channels
524+
// with the same funding output (ie post-funding channel_id), we'd create a monitor update for
525+
// the existing channel when we detect the duplicate new channel, screwing up our monitor
526+
// updating logic for the existing channel.
527+
let chanmon_cfgs = create_chanmon_cfgs(2);
528+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
529+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
530+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
531+
532+
// Create an initial channel
533+
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None).unwrap();
534+
let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
535+
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_chan_msg);
536+
let accept_chan_msg = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
537+
nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_chan_msg);
538+
539+
// Try to create a second channel with the same temporary_channel_id as the first and check
540+
// that it is rejected.
541+
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_chan_msg);
542+
{
543+
let events = nodes[1].node.get_and_clear_pending_msg_events();
544+
assert_eq!(events.len(), 1);
545+
match events[0] {
546+
MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id } => {
547+
// Technically, at this point, nodes[1] would be justified in thinking both
548+
// channels are closed, but currently we do not, so we just move forward with it.
549+
assert_eq!(msg.channel_id, open_chan_msg.temporary_channel_id);
550+
assert_eq!(node_id, nodes[0].node.get_our_node_id());
551+
},
552+
_ => panic!("Unexpected event"),
553+
}
554+
}
555+
556+
// Move the first channel through the funding flow...
557+
let (temporary_channel_id, tx, funding_output) = create_funding_transaction(&nodes[0], 100000, 42);
558+
559+
nodes[0].node.funding_transaction_generated(&temporary_channel_id, funding_output);
560+
check_added_monitors!(nodes[0], 0);
561+
562+
let mut funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
563+
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
564+
{
565+
let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap();
566+
assert_eq!(added_monitors.len(), 1);
567+
assert_eq!(added_monitors[0].0, funding_output);
568+
added_monitors.clear();
569+
}
570+
let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
571+
572+
let channel_id = ::chain::transaction::OutPoint { txid: funding_created_msg.funding_txid, index: funding_created_msg.funding_output_index }.to_channel_id();
573+
574+
// Now we have the first channel past funding_created (ie it has a txid-based channel_id, not a
575+
// temporary one).
576+
577+
// First try to open a second channel with a temporary channel id equal to the txid-based one.
578+
// Technically this is allowed by the spec, but we don't support it and there's little reason
579+
// to. Still, it shouldn't cause any other issues.
580+
open_chan_msg.temporary_channel_id = channel_id;
581+
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_chan_msg);
582+
{
583+
let events = nodes[1].node.get_and_clear_pending_msg_events();
584+
assert_eq!(events.len(), 1);
585+
match events[0] {
586+
MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id } => {
587+
// Technically, at this point, nodes[1] would be justified in thinking both
588+
// channels are closed, but currently we do not, so we just move forward with it.
589+
assert_eq!(msg.channel_id, open_chan_msg.temporary_channel_id);
590+
assert_eq!(node_id, nodes[0].node.get_our_node_id());
591+
},
592+
_ => panic!("Unexpected event"),
593+
}
594+
}
595+
596+
// Now try to create a second channel which has a duplicate funding output.
597+
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None).unwrap();
598+
let open_chan_2_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
599+
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_chan_2_msg);
600+
nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()));
601+
create_funding_transaction(&nodes[0], 100000, 42); // Get and check the FundingGenerationReady event
602+
603+
nodes[0].node.funding_transaction_generated_dup_funding_id(&open_chan_2_msg.temporary_channel_id, funding_output);
604+
check_added_monitors!(nodes[0], 0);
605+
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()));
606+
// At this point we'll try to add a duplicate channel monitor, which will be rejected, but
607+
// still needs to be cleared here.
608+
check_added_monitors!(nodes[1], 1);
609+
610+
// ...still, nodes[1] will reject the duplicate channel.
611+
{
612+
let events = nodes[1].node.get_and_clear_pending_msg_events();
613+
assert_eq!(events.len(), 1);
614+
match events[0] {
615+
MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id } => {
616+
// Technically, at this point, nodes[1] would be justified in thinking both
617+
// channels are closed, but currently we do not, so we just move forward with it.
618+
assert_eq!(msg.channel_id, channel_id);
619+
assert_eq!(node_id, nodes[0].node.get_our_node_id());
620+
},
621+
_ => panic!("Unexpected event"),
622+
}
623+
}
624+
625+
// finally, finish creating the original channel and send a payment over it to make sure
626+
// everything is functional.
627+
nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed_msg);
628+
{
629+
let mut added_monitors = nodes[0].chain_monitor.added_monitors.lock().unwrap();
630+
assert_eq!(added_monitors.len(), 1);
631+
assert_eq!(added_monitors[0].0, funding_output);
632+
added_monitors.clear();
633+
}
634+
635+
let events_4 = nodes[0].node.get_and_clear_pending_events();
636+
assert_eq!(events_4.len(), 1);
637+
match events_4[0] {
638+
Event::FundingBroadcastSafe { ref funding_txo, user_channel_id } => {
639+
assert_eq!(user_channel_id, 42);
640+
assert_eq!(*funding_txo, funding_output);
641+
},
642+
_ => panic!("Unexpected event"),
643+
};
644+
645+
let (funding_locked, _) = create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx);
646+
let (announcement, as_update, bs_update) = create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &funding_locked);
647+
update_nodes_with_chan_announce(&nodes, 0, 1, &announcement, &as_update, &bs_update);
648+
send_payment(&nodes[0], &[&nodes[1]], 8000000, 8_000_000);
649+
}

lightning/src/ln/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,6 @@ mod chanmon_update_fail_tests;
5151
mod reorg_tests;
5252
#[cfg(test)]
5353
#[allow(unused_mut)]
54-
mod onion_route_tests;
54+
mod general_unit_tests;
5555

5656
pub use self::peer_channel_encryptor::LN_MAX_MSG_LEN;

0 commit comments

Comments
 (0)