Skip to content

Commit

Permalink
Correctly handle sending announcement sigs on public 0conf channels
Browse files Browse the repository at this point in the history
  • Loading branch information
TheBlueMatt committed Apr 2, 2022
1 parent 7cfddf6 commit 3083a30
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 4 deletions.
3 changes: 1 addition & 2 deletions lightning/src/ln/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4576,12 +4576,11 @@ impl<Signer: Sign> Channel<Signer> {
pub fn transactions_confirmed<L: Deref>(&mut self, block_hash: &BlockHash, height: u32,
txdata: &TransactionData, genesis_block_hash: BlockHash, node_pk: PublicKey, logger: &L)
-> Result<(Option<msgs::FundingLocked>, Option<msgs::AnnouncementSignatures>), ClosureReason> where L::Target: Logger {
let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS);
if let Some(funding_txo) = self.get_funding_txo() {
for &(index_in_block, tx) in txdata.iter() {
// If we haven't yet sent a funding_locked, but are in FundingSent (ignoring
// whether they've sent a funding_locked or not), check if we should send one.
if non_shutdown_state & !(ChannelState::TheirFundingLocked as u32) == ChannelState::FundingSent as u32 {
if self.funding_tx_confirmation_height == 0 {
if tx.txid() == funding_txo.txid {
let txo_idx = funding_txo.index as usize;
if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.get_funding_redeemscript().to_v0_p2wsh() ||
Expand Down
6 changes: 4 additions & 2 deletions lightning/src/ln/functional_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9052,7 +9052,9 @@ fn test_duplicate_chan_id() {

let funding_created = {
let mut a_channel_lock = nodes[0].node.channel_state.lock().unwrap();
let mut as_chan = a_channel_lock.by_id.get_mut(&open_chan_2_msg.temporary_channel_id).unwrap();
// Note that we drop the channel entirely here as its in a somewhat nonsense state (leaving
// the channelmanager in a possibly nonsense state instead).
let mut as_chan = a_channel_lock.by_id.remove(&open_chan_2_msg.temporary_channel_id).unwrap();
let logger = test_utils::TestLogger::new();
as_chan.get_outbound_funding_created(tx.clone(), funding_outpoint, &&logger).unwrap()
};
Expand Down Expand Up @@ -9090,7 +9092,7 @@ fn test_duplicate_chan_id() {
let events_4 = nodes[0].node.get_and_clear_pending_events();
assert_eq!(events_4.len(), 0);
assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1);
assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0].txid(), funding_output.txid);
assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0], tx);

let (funding_locked, _) = create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx);
let (announcement, as_update, bs_update) = create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &funding_locked);
Expand Down
106 changes: 106 additions & 0 deletions lightning/src/ln/priv_short_conf_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -767,3 +767,109 @@ fn test_0_conf_channel_with_async_monitor() {

send_payment(&nodes[0], &[&nodes[1]], 100_000);
}

#[test]
fn test_public_0_conf_channel() {
// Tests that we will announce a public channel (after confirmation) even if its 0conf.
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let mut chan_config = test_default_channel_config();
chan_config.manually_accept_inbound_channels = true;
chan_config.channel_options.announced_channel = true;

let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(chan_config)]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);

nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None).unwrap();
let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());

nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_channel);
let events = nodes[1].node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
match events[0] {
Event::OpenChannelRequest { temporary_channel_id, .. } => {
nodes[1].node.accept_inbound_channel_from_trusted_peer_0conf(&temporary_channel_id, 0).unwrap();
},
_ => panic!("Unexpected event"),
};

let mut accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
assert_eq!(accept_channel.minimum_depth, 0);
nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_channel);

let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], 100000, 42);
nodes[0].node.funding_transaction_generated(&temporary_channel_id, tx.clone()).unwrap();
let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());

nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created);
check_added_monitors!(nodes[1], 1);
let bs_signed_locked = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(bs_signed_locked.len(), 2);
let as_funding_locked;
match &bs_signed_locked[0] {
MessageSendEvent::SendFundingSigned { node_id, msg } => {
assert_eq!(*node_id, nodes[0].node.get_our_node_id());
nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &msg);
check_added_monitors!(nodes[0], 1);

assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1);
assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0)[0], tx);

as_funding_locked = get_event_msg!(nodes[0], MessageSendEvent::SendFundingLocked, nodes[1].node.get_our_node_id());
}
_ => panic!("Unexpected event"),
}
match &bs_signed_locked[1] {
MessageSendEvent::SendFundingLocked { node_id, msg } => {
assert_eq!(*node_id, nodes[0].node.get_our_node_id());
nodes[0].node.handle_funding_locked(&nodes[1].node.get_our_node_id(), &msg);
}
_ => panic!("Unexpected event"),
}

nodes[1].node.handle_funding_locked(&nodes[0].node.get_our_node_id(), &as_funding_locked);

let as_channel_update = get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id());
let bs_channel_update = get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[0].node.get_our_node_id());

nodes[0].node.handle_channel_update(&nodes[1].node.get_our_node_id(), &bs_channel_update);
nodes[1].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &as_channel_update);

assert_eq!(nodes[0].node.list_usable_channels().len(), 1);
assert_eq!(nodes[1].node.list_usable_channels().len(), 1);

// We can use the channel immediately, but we can't announce it until we get 6+ confirmations
send_payment(&nodes[0], &[&nodes[1]], 100_000);

confirm_transaction(&nodes[0], &tx);
let as_announcement_sigs = get_event_msg!(nodes[0], MessageSendEvent::SendAnnouncementSignatures, nodes[1].node.get_our_node_id());
confirm_transaction(&nodes[1], &tx);
let bs_announcement_sigs = get_event_msg!(nodes[1], MessageSendEvent::SendAnnouncementSignatures, nodes[0].node.get_our_node_id());

nodes[1].node.handle_announcement_signatures(&nodes[0].node.get_our_node_id(), &as_announcement_sigs);
nodes[0].node.handle_announcement_signatures(&nodes[1].node.get_our_node_id(), &bs_announcement_sigs);

let bs_announcement = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(bs_announcement.len(), 1);
let announcement;
let bs_update;
match bs_announcement[0] {
MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } => {
announcement = msg.clone();
bs_update = update_msg.clone();
},
_ => panic!("Unexpected event"),
};

let as_announcement = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(as_announcement.len(), 1);
match as_announcement[0] {
MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } => {
assert!(announcement == *msg);
assert_eq!(update_msg.contents.short_channel_id, announcement.contents.short_channel_id);
assert_eq!(update_msg.contents.short_channel_id, bs_update.contents.short_channel_id);
},
_ => panic!("Unexpected event"),
};

}

0 comments on commit 3083a30

Please sign in to comment.