Merge pull request #3109 from alecchendev/2024-06-async-commit-point-funding

Handle fallible per commitment point in channel establishment
This commit is contained in:
Matt Corallo 2024-12-15 23:08:17 +00:00 committed by GitHub
commit c62cd1551a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 602 additions and 333 deletions

View File

@ -10,14 +10,15 @@
//! Tests for asynchronous signing. These tests verify that the channel state machine behaves
//! properly with a signer implementation that asynchronously derives signatures.
use std::collections::HashSet;
use bitcoin::key::Secp256k1;
use crate::prelude::*;
use bitcoin::secp256k1::Secp256k1;
use bitcoin::{Transaction, TxOut, TxIn, Amount};
use bitcoin::locktime::absolute::LockTime;
use bitcoin::transaction::Version;
use crate::chain::channelmonitor::LATENCY_GRACE_PERIOD_BLOCKS;
use crate::chain::ChannelMonitorUpdateStatus;
use crate::chain::transaction::OutPoint;
use crate::events::bump_transaction::WalletSource;
use crate::events::{ClosureReason, Event, MessageSendEvent, MessageSendEventsProvider};
use crate::ln::chan_utils::ClosingTransaction;
@ -31,7 +32,78 @@ use crate::util::test_channel_signer::SignerOp;
use crate::util::logger::Logger;
#[test]
fn test_async_commitment_signature_for_funding_created() {
fn test_open_channel() {
do_test_open_channel(false);
do_test_open_channel(true);
}
fn do_test_open_channel(zero_conf: bool) {
// Simulate acquiring the commitment point for `open_channel` and `accept_channel` asynchronously.
let mut manually_accept_config = test_default_channel_config();
manually_accept_config.manually_accept_inbound_channels = zero_conf;
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(manually_accept_config)]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
// Open an outbound channel simulating an async signer.
let channel_value_satoshis = 100000;
let user_channel_id = 42;
nodes[0].disable_next_channel_signer_op(SignerOp::GetPerCommitmentPoint);
let channel_id_0 = nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, 10001, user_channel_id, None, None).unwrap();
{
let msgs = nodes[0].node.get_and_clear_pending_msg_events();
assert!(msgs.is_empty(), "Expected no message events; got {:?}", msgs);
}
nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &channel_id_0, SignerOp::GetPerCommitmentPoint);
nodes[0].node.signer_unblocked(None);
// nodes[0] --- open_channel --> nodes[1]
let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
// Handle an inbound channel simulating an async signer.
nodes[1].disable_next_channel_signer_op(SignerOp::GetPerCommitmentPoint);
nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_chan_msg);
if zero_conf {
let events = nodes[1].node.get_and_clear_pending_events();
assert_eq!(events.len(), 1, "Expected one event, got {}", events.len());
match &events[0] {
Event::OpenChannelRequest { temporary_channel_id, .. } => {
nodes[1].node.accept_inbound_channel_from_trusted_peer_0conf(
temporary_channel_id, &nodes[0].node.get_our_node_id(), 0)
.expect("Unable to accept inbound zero-conf channel");
},
ev => panic!("Expected OpenChannelRequest, not {:?}", ev)
}
} else {
let msgs = nodes[1].node.get_and_clear_pending_msg_events();
assert!(msgs.is_empty(), "Expected no message events; got {:?}", msgs);
}
let channel_id_1 = {
let channels = nodes[1].node.list_channels();
assert_eq!(channels.len(), 1, "expected one channel, not {}", channels.len());
channels[0].channel_id
};
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &channel_id_1, SignerOp::GetPerCommitmentPoint);
nodes[1].node.signer_unblocked(None);
// nodes[0] <-- accept_channel --- nodes[1]
get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
}
#[test]
fn test_funding_created() {
do_test_funding_created(vec![SignerOp::SignCounterpartyCommitment, SignerOp::GetPerCommitmentPoint]);
do_test_funding_created(vec![SignerOp::GetPerCommitmentPoint, SignerOp::SignCounterpartyCommitment]);
}
fn do_test_funding_created(signer_ops: Vec<SignerOp>) {
// Simulate acquiring the signature for `funding_created` asynchronously.
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
@ -52,7 +124,9 @@ fn test_async_commitment_signature_for_funding_created() {
// But! Let's make node[0]'s signer be unavailable: we should *not* broadcast a funding_created
// message...
let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42);
nodes[0].disable_channel_signer_op(&nodes[1].node.get_our_node_id(), &temporary_channel_id, SignerOp::SignCounterpartyCommitment);
for op in signer_ops.iter() {
nodes[0].disable_channel_signer_op(&nodes[1].node.get_our_node_id(), &temporary_channel_id, *op);
}
nodes[0].node.funding_transaction_generated(temporary_channel_id, nodes[1].node.get_our_node_id(), tx.clone()).unwrap();
check_added_monitors(&nodes[0], 0);
@ -66,8 +140,10 @@ fn test_async_commitment_signature_for_funding_created() {
channels[0].channel_id
};
nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignCounterpartyCommitment);
for op in signer_ops.iter() {
nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, *op);
nodes[0].node.signer_unblocked(Some((nodes[1].node.get_our_node_id(), chan_id)));
}
let mut funding_created_msg = 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_msg);
@ -82,7 +158,12 @@ fn test_async_commitment_signature_for_funding_created() {
}
#[test]
fn test_async_commitment_signature_for_funding_signed() {
fn test_funding_signed() {
do_test_funding_signed(vec![SignerOp::SignCounterpartyCommitment, SignerOp::GetPerCommitmentPoint]);
do_test_funding_signed(vec![SignerOp::GetPerCommitmentPoint, SignerOp::SignCounterpartyCommitment]);
}
fn do_test_funding_signed(signer_ops: Vec<SignerOp>) {
// Simulate acquiring the signature for `funding_signed` asynchronously.
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
@ -107,7 +188,9 @@ fn test_async_commitment_signature_for_funding_signed() {
// Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should
// *not* broadcast a `funding_signed`...
nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &temporary_channel_id, SignerOp::SignCounterpartyCommitment);
for op in signer_ops.iter() {
nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &temporary_channel_id, *op);
}
nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created_msg);
check_added_monitors(&nodes[1], 1);
@ -120,9 +203,10 @@ fn test_async_commitment_signature_for_funding_signed() {
assert_eq!(channels.len(), 1, "expected one channel, not {}", channels.len());
channels[0].channel_id
};
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, SignerOp::SignCounterpartyCommitment);
for op in signer_ops.iter() {
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, *op);
nodes[1].node.signer_unblocked(Some((nodes[0].node.get_our_node_id(), chan_id)));
if *op == SignerOp::SignCounterpartyCommitment {
expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
// nodes[0] <-- funding_signed --- nodes[1]
@ -130,6 +214,10 @@ fn test_async_commitment_signature_for_funding_signed() {
nodes[0].node.handle_funding_signed(nodes[1].node.get_our_node_id(), &funding_signed_msg);
check_added_monitors(&nodes[0], 1);
expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id());
} else {
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
}
}
}
#[test]
@ -178,7 +266,7 @@ fn do_test_async_commitment_signature_for_commitment_signed_revoke_and_ack(enabl
dst.node.handle_commitment_signed(src.node.get_our_node_id(), &payment_event.commitment_msg);
check_added_monitors(dst, 1);
let mut enabled_signer_ops = HashSet::new();
let mut enabled_signer_ops = new_hash_set();
log_trace!(dst.logger, "enable_signer_op_order={:?}", enable_signer_op_order);
for op in enable_signer_op_order {
enabled_signer_ops.insert(op);
@ -204,7 +292,12 @@ fn do_test_async_commitment_signature_for_commitment_signed_revoke_and_ack(enabl
}
#[test]
fn test_async_commitment_signature_for_funding_signed_0conf() {
fn test_funding_signed_0conf() {
do_test_funding_signed_0conf(vec![SignerOp::GetPerCommitmentPoint, SignerOp::SignCounterpartyCommitment]);
do_test_funding_signed_0conf(vec![SignerOp::SignCounterpartyCommitment, SignerOp::GetPerCommitmentPoint]);
}
fn do_test_funding_signed_0conf(signer_ops: Vec<SignerOp>) {
// Simulate acquiring the signature for `funding_signed` asynchronously for a zero-conf channel.
let mut manually_accept_config = test_default_channel_config();
manually_accept_config.manually_accept_inbound_channels = true;
@ -247,7 +340,9 @@ fn test_async_commitment_signature_for_funding_signed_0conf() {
// Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should
// *not* broadcast a `funding_signed`...
nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &temporary_channel_id, SignerOp::SignCounterpartyCommitment);
for op in signer_ops.iter() {
nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &temporary_channel_id, *op);
}
nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created_msg);
check_added_monitors(&nodes[1], 1);
@ -262,8 +357,10 @@ fn test_async_commitment_signature_for_funding_signed_0conf() {
};
// At this point, we basically expect the channel to open like a normal zero-conf channel.
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, SignerOp::SignCounterpartyCommitment);
for op in signer_ops.iter() {
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, *op);
nodes[1].node.signer_unblocked(Some((nodes[0].node.get_our_node_id(), chan_id)));
}
let (funding_signed, channel_ready_1) = {
let events = nodes[1].node.get_and_clear_pending_msg_events();
@ -867,65 +964,65 @@ fn do_test_closing_signed(extra_closing_signed: bool, reconnect: bool) {
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1);
// Avoid extra channel ready message upon reestablish later
send_payment(&nodes[0], &vec![&nodes[1]][..], 8_000_000);
expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::NotShuttingDown);
expect_channel_shutdown_state!(nodes[0], chan_id, ChannelShutdownState::NotShuttingDown);
nodes[0].node.close_channel(&chan_1.2, &nodes[1].node.get_our_node_id()).unwrap();
nodes[0].node.close_channel(&chan_id, &nodes[1].node.get_our_node_id()).unwrap();
expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::ShutdownInitiated);
expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::NotShuttingDown);
expect_channel_shutdown_state!(nodes[0], chan_id, ChannelShutdownState::ShutdownInitiated);
expect_channel_shutdown_state!(nodes[1], chan_id, ChannelShutdownState::NotShuttingDown);
let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
nodes[1].node.handle_shutdown(nodes[0].node.get_our_node_id(), &node_0_shutdown);
expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::ShutdownInitiated);
expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::NegotiatingClosingFee);
expect_channel_shutdown_state!(nodes[0], chan_id, ChannelShutdownState::ShutdownInitiated);
expect_channel_shutdown_state!(nodes[1], chan_id, ChannelShutdownState::NegotiatingClosingFee);
let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
nodes[0].disable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_1.2, SignerOp::SignClosingTransaction);
nodes[0].disable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignClosingTransaction);
nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_1_shutdown);
expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::NegotiatingClosingFee);
expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::NegotiatingClosingFee);
expect_channel_shutdown_state!(nodes[0], chan_id, ChannelShutdownState::NegotiatingClosingFee);
expect_channel_shutdown_state!(nodes[1], chan_id, ChannelShutdownState::NegotiatingClosingFee);
let events = nodes[0].node.get_and_clear_pending_msg_events();
assert!(events.is_empty(), "Expected no events, got {:?}", events);
nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_1.2, SignerOp::SignClosingTransaction);
nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignClosingTransaction);
nodes[0].node.signer_unblocked(None);
let node_0_closing_signed = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id());
nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_1.2, SignerOp::SignClosingTransaction);
nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, SignerOp::SignClosingTransaction);
nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_closing_signed);
let events = nodes[1].node.get_and_clear_pending_msg_events();
assert!(events.is_empty(), "Expected no events, got {:?}", events);
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_1.2, SignerOp::SignClosingTransaction);
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, SignerOp::SignClosingTransaction);
nodes[1].node.signer_unblocked(None);
let node_1_closing_signed = get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id());
nodes[0].disable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_1.2, SignerOp::SignClosingTransaction);
nodes[0].disable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignClosingTransaction);
nodes[0].node.handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed);
let events = nodes[0].node.get_and_clear_pending_msg_events();
assert!(events.is_empty(), "Expected no events, got {:?}", events);
nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_1.2, SignerOp::SignClosingTransaction);
nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignClosingTransaction);
if extra_closing_signed {
let node_1_closing_signed_2_bad = {
let mut node_1_closing_signed_2 = node_1_closing_signed.clone();
let holder_script = nodes[0].keys_manager.get_shutdown_scriptpubkey().unwrap();
let counterparty_script = nodes[1].keys_manager.get_shutdown_scriptpubkey().unwrap();
let funding_outpoint = bitcoin::OutPoint { txid: chan_1.3.compute_txid(), vout: 0 };
let funding_outpoint = bitcoin::OutPoint { txid: funding_tx.compute_txid(), vout: 0 };
let closing_tx_2 = ClosingTransaction::new(50000, 0, holder_script.into(),
counterparty_script.into(), funding_outpoint);
let per_peer_state = nodes[1].node.per_peer_state.read().unwrap();
let mut chan_lock = per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap();
let chan = chan_lock.channel_by_id.get_mut(&chan_1.2).map(|phase| phase.context_mut()).unwrap();
let chan = chan_lock.channel_by_id.get_mut(&chan_id).map(|phase| phase.context_mut()).unwrap();
let signer = chan.get_mut_signer().as_mut_ecdsa().unwrap();
let signature = signer.sign_closing_transaction(&closing_tx_2, &Secp256k1::new()).unwrap();
@ -994,4 +1091,8 @@ fn do_test_closing_signed(extra_closing_signed: bool, reconnect: bool) {
check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000);
check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000);
// Check that our maps have been updated after async signing channel closure.
let funding_outpoint = OutPoint { txid: funding_tx.compute_txid(), index: 0 };
assert!(nodes[0].node().outpoint_to_peer.lock().unwrap().get(&funding_outpoint).is_none());
assert!(nodes[1].node().outpoint_to_peer.lock().unwrap().get(&funding_outpoint).is_none());
}

File diff suppressed because it is too large Load Diff

View File

@ -3642,7 +3642,7 @@ where
}
}
let channel = {
let mut channel = {
let outbound_scid_alias = self.create_and_insert_outbound_scid_alias();
let their_features = &peer_state.latest_features;
let config = if override_config.is_some() { override_config.as_ref().unwrap() } else { &self.default_configuration };
@ -3657,7 +3657,8 @@ where
},
}
};
let res = channel.get_open_channel(self.chain_hash);
let logger = WithChannelContext::from(&self.logger, &channel.context, None);
let res = channel.get_open_channel(self.chain_hash, &&logger);
let temporary_channel_id = channel.context.channel_id();
match peer_state.channel_by_id.entry(temporary_channel_id) {
@ -3671,10 +3672,12 @@ where
hash_map::Entry::Vacant(entry) => { entry.insert(ChannelPhase::UnfundedOutboundV1(channel)); }
}
if let Some(msg) = res {
peer_state.pending_msg_events.push(events::MessageSendEvent::SendOpenChannel {
node_id: their_network_key,
msg: res,
msg,
});
}
Ok(temporary_channel_id)
}
@ -7733,11 +7736,14 @@ where
&self.channel_type_features(), &peer_state.latest_features, &open_channel_msg,
user_channel_id, &self.default_configuration, best_block_height, &self.logger, accept_0conf
).map_err(|err| MsgHandleErrInternal::from_chan_no_close(err, *temporary_channel_id)
).map(|channel| {
let message_send_event = events::MessageSendEvent::SendAcceptChannel {
).map(|mut channel| {
let logger = WithChannelContext::from(&self.logger, &channel.context, None);
let message_send_event = channel.accept_inbound_channel(&&logger).map(|msg| {
events::MessageSendEvent::SendAcceptChannel {
node_id: *counterparty_node_id,
msg: channel.accept_inbound_channel(),
};
msg,
}
});
(*temporary_channel_id, ChannelPhase::UnfundedInboundV1(channel), message_send_event)
})
},
@ -7758,7 +7764,7 @@ where
node_id: channel.context.get_counterparty_node_id(),
msg: channel.accept_inbound_dual_funded_channel()
};
(channel.context.channel_id(), ChannelPhase::UnfundedInboundV2(channel), message_send_event)
(channel.context.channel_id(), ChannelPhase::UnfundedInboundV2(channel), Some(message_send_event))
})
},
}
@ -7826,7 +7832,9 @@ where
let outbound_scid_alias = self.create_and_insert_outbound_scid_alias();
channel_phase.context_mut().set_outbound_scid_alias(outbound_scid_alias);
if let Some(message_send_event) = message_send_event {
peer_state.pending_msg_events.push(message_send_event);
}
peer_state.channel_by_id.insert(channel_id, channel_phase);
Ok(())
@ -8002,15 +8010,18 @@ where
let (mut channel_phase, message_send_event) = match msg {
OpenChannelMessageRef::V1(msg) => {
let channel = InboundV1Channel::new(
let mut channel = InboundV1Channel::new(
&self.fee_estimator, &self.entropy_source, &self.signer_provider, *counterparty_node_id,
&self.channel_type_features(), &peer_state.latest_features, msg, user_channel_id,
&self.default_configuration, best_block_height, &self.logger, /*is_0conf=*/false
).map_err(|e| MsgHandleErrInternal::from_chan_no_close(e, msg.common_fields.temporary_channel_id))?;
let message_send_event = events::MessageSendEvent::SendAcceptChannel {
let logger = WithChannelContext::from(&self.logger, &channel.context, None);
let message_send_event = channel.accept_inbound_channel(&&logger).map(|msg| {
events::MessageSendEvent::SendAcceptChannel {
node_id: *counterparty_node_id,
msg: channel.accept_inbound_channel(),
};
msg,
}
});
(ChannelPhase::UnfundedInboundV1(channel), message_send_event)
},
OpenChannelMessageRef::V2(msg) => {
@ -8023,14 +8034,16 @@ where
node_id: *counterparty_node_id,
msg: channel.accept_inbound_dual_funded_channel(),
};
(ChannelPhase::UnfundedInboundV2(channel), message_send_event)
(ChannelPhase::UnfundedInboundV2(channel), Some(message_send_event))
},
};
let outbound_scid_alias = self.create_and_insert_outbound_scid_alias();
channel_phase.context_mut().set_outbound_scid_alias(outbound_scid_alias);
if let Some(message_send_event) = message_send_event {
peer_state.pending_msg_events.push(message_send_event);
}
peer_state.channel_by_id.insert(channel_phase.context().channel_id(), channel_phase);
Ok(())
@ -9561,7 +9574,14 @@ where
msgs.shutdown_result
}
ChannelPhase::UnfundedOutboundV1(chan) => {
if let Some(msg) = chan.signer_maybe_unblocked(&self.logger) {
let (open_channel, funding_created) = chan.signer_maybe_unblocked(self.chain_hash.clone(), &self.logger);
if let Some(msg) = open_channel {
pending_msg_events.push(events::MessageSendEvent::SendOpenChannel {
node_id,
msg,
});
}
if let Some(msg) = funding_created {
pending_msg_events.push(events::MessageSendEvent::SendFundingCreated {
node_id,
msg,
@ -9569,7 +9589,17 @@ where
}
None
}
ChannelPhase::UnfundedInboundV1(_) | ChannelPhase::UnfundedInboundV2(_) | ChannelPhase::UnfundedOutboundV2(_) => None,
ChannelPhase::UnfundedInboundV1(chan) => {
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
if let Some(msg) = chan.signer_maybe_unblocked(&&logger) {
pending_msg_events.push(events::MessageSendEvent::SendAcceptChannel {
node_id,
msg,
});
}
None
},
ChannelPhase::UnfundedInboundV2(_) | ChannelPhase::UnfundedOutboundV2(_) => None,
}
};
@ -11688,11 +11718,14 @@ where
}
ChannelPhase::UnfundedOutboundV1(chan) => {
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
if let Some(msg) = chan.get_open_channel(self.chain_hash, &&logger) {
pending_msg_events.push(events::MessageSendEvent::SendOpenChannel {
node_id: chan.context.get_counterparty_node_id(),
msg: chan.get_open_channel(self.chain_hash),
msg,
});
}
}
ChannelPhase::UnfundedOutboundV2(chan) => {
pending_msg_events.push(events::MessageSendEvent::SendOpenChannelV2 {
@ -11795,7 +11828,8 @@ where
let peer_state = &mut *peer_state_lock;
match peer_state.channel_by_id.get_mut(&msg.channel_id) {
Some(ChannelPhase::UnfundedOutboundV1(ref mut chan)) => {
if let Ok(msg) = chan.maybe_handle_error_without_close(self.chain_hash, &self.fee_estimator) {
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
if let Ok(msg) = chan.maybe_handle_error_without_close(self.chain_hash, &self.fee_estimator, &&logger) {
peer_state.pending_msg_events.push(events::MessageSendEvent::SendOpenChannel {
node_id: counterparty_node_id,
msg,

View File

@ -580,6 +580,11 @@ impl<'a, 'b, 'c> Node<'a, 'b, 'c> {
entry.insert(signer_op);
};
}
#[cfg(test)]
pub fn disable_next_channel_signer_op(&self, signer_op: SignerOp) {
self.keys_manager.next_signer_disabled_ops.lock().unwrap().insert(signer_op);
}
}
/// If we need an unsafe pointer to a `Node` (ie to reference it in a thread

View File

@ -1234,6 +1234,7 @@ pub struct TestKeysInterface {
enforcement_states: Mutex<HashMap<[u8;32], Arc<Mutex<EnforcementState>>>>,
expectations: Mutex<Option<VecDeque<OnGetShutdownScriptpubkey>>>,
pub unavailable_signers_ops: Mutex<HashMap<[u8; 32], HashSet<SignerOp>>>,
pub next_signer_disabled_ops: Mutex<HashSet<SignerOp>>,
}
impl EntropySource for TestKeysInterface {
@ -1293,6 +1294,10 @@ impl SignerProvider for TestKeysInterface {
signer.disable_op(op);
}
}
#[cfg(test)]
for op in self.next_signer_disabled_ops.lock().unwrap().drain() {
signer.disable_op(op);
}
signer
}
@ -1332,6 +1337,7 @@ impl TestKeysInterface {
enforcement_states: Mutex::new(new_hash_map()),
expectations: Mutex::new(None),
unavailable_signers_ops: Mutex::new(new_hash_map()),
next_signer_disabled_ops: Mutex::new(new_hash_set()),
}
}