Skip to content

Commit 0ac4ad8

Browse files
committed
Add test for async open and accept channel
1 parent 1fcf4f1 commit 0ac4ad8

File tree

4 files changed

+110
-25
lines changed

4 files changed

+110
-25
lines changed

lightning/src/ln/async_signer_tests.rs

+86-12
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,59 @@ use crate::ln::channelmanager::{PaymentId, RAACommitmentOrder, RecipientOnionFie
2424
use crate::util::test_channel_signer::SignerOp;
2525

2626
#[test]
27-
fn test_async_commitment_signature_for_funding_created() {
27+
fn test_open_channel() {
28+
// Simulate acquiring the signature for `funding_created` asynchronously.
29+
let chanmon_cfgs = create_chanmon_cfgs(2);
30+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
31+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
32+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
33+
34+
// Open an outbound channel simulating an async signer.
35+
let channel_value_satoshis = 100000;
36+
let user_channel_id = 42;
37+
nodes[0].disable_next_channel_signer_op(SignerOp::GetPerCommitmentPoint);
38+
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();
39+
40+
{
41+
let msgs = nodes[0].node.get_and_clear_pending_msg_events();
42+
assert!(msgs.is_empty(), "Expected no message events; got {:?}", msgs);
43+
}
44+
45+
nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &channel_id_0, SignerOp::GetPerCommitmentPoint);
46+
nodes[0].node.signer_unblocked(None);
47+
48+
// nodes[0] --- open_channel --> nodes[1]
49+
let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
50+
51+
// Handle an inbound channel simulating an async signer.
52+
nodes[1].disable_next_channel_signer_op(SignerOp::GetPerCommitmentPoint);
53+
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_chan_msg);
54+
55+
{
56+
let msgs = nodes[1].node.get_and_clear_pending_msg_events();
57+
assert!(msgs.is_empty(), "Expected no message events; got {:?}", msgs);
58+
}
59+
60+
let channel_id_1 = {
61+
let channels = nodes[1].node.list_channels();
62+
assert_eq!(channels.len(), 1, "expected one channel, not {}", channels.len());
63+
channels[0].channel_id
64+
};
65+
66+
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &channel_id_1, SignerOp::GetPerCommitmentPoint);
67+
nodes[1].node.signer_unblocked(None);
68+
69+
// nodes[0] <-- accept_channel --- nodes[1]
70+
get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
71+
}
72+
73+
#[test]
74+
fn test_funding_created() {
75+
do_test_funding_created(vec![SignerOp::SignCounterpartyCommitment, SignerOp::GetPerCommitmentPoint]);
76+
do_test_funding_created(vec![SignerOp::GetPerCommitmentPoint, SignerOp::SignCounterpartyCommitment]);
77+
}
78+
79+
fn do_test_funding_created(signer_ops: Vec<SignerOp>) {
2880
// Simulate acquiring the signature for `funding_created` asynchronously.
2981
let chanmon_cfgs = create_chanmon_cfgs(2);
3082
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
@@ -45,7 +97,9 @@ fn test_async_commitment_signature_for_funding_created() {
4597
// But! Let's make node[0]'s signer be unavailable: we should *not* broadcast a funding_created
4698
// message...
4799
let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42);
48-
nodes[0].disable_channel_signer_op(&nodes[1].node.get_our_node_id(), &temporary_channel_id, SignerOp::SignCounterpartyCommitment);
100+
for op in signer_ops.iter() {
101+
nodes[0].disable_channel_signer_op(&nodes[1].node.get_our_node_id(), &temporary_channel_id, *op);
102+
}
49103
nodes[0].node.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), tx.clone()).unwrap();
50104
check_added_monitors(&nodes[0], 0);
51105

@@ -59,8 +113,10 @@ fn test_async_commitment_signature_for_funding_created() {
59113
channels[0].channel_id
60114
};
61115

62-
nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignCounterpartyCommitment);
63-
nodes[0].node.signer_unblocked(Some((nodes[1].node.get_our_node_id(), chan_id)));
116+
for op in signer_ops.iter() {
117+
nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, *op);
118+
nodes[0].node.signer_unblocked(Some((nodes[1].node.get_our_node_id(), chan_id)));
119+
}
64120

65121
let mut funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
66122
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
@@ -75,7 +131,12 @@ fn test_async_commitment_signature_for_funding_created() {
75131
}
76132

77133
#[test]
78-
fn test_async_commitment_signature_for_funding_signed() {
134+
fn test_funding_signed() {
135+
do_test_funding_signed(vec![SignerOp::SignCounterpartyCommitment, SignerOp::GetPerCommitmentPoint]);
136+
do_test_funding_signed(vec![SignerOp::GetPerCommitmentPoint, SignerOp::SignCounterpartyCommitment]);
137+
}
138+
139+
fn do_test_funding_signed(signer_ops: Vec<SignerOp>) {
79140
// Simulate acquiring the signature for `funding_signed` asynchronously.
80141
let chanmon_cfgs = create_chanmon_cfgs(2);
81142
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
@@ -100,7 +161,9 @@ fn test_async_commitment_signature_for_funding_signed() {
100161

101162
// Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should
102163
// *not* broadcast a `funding_signed`...
103-
nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &temporary_channel_id, SignerOp::SignCounterpartyCommitment);
164+
for op in signer_ops.iter() {
165+
nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &temporary_channel_id, *op);
166+
}
104167
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
105168
check_added_monitors(&nodes[1], 1);
106169

@@ -113,8 +176,10 @@ fn test_async_commitment_signature_for_funding_signed() {
113176
assert_eq!(channels.len(), 1, "expected one channel, not {}", channels.len());
114177
channels[0].channel_id
115178
};
116-
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, SignerOp::SignCounterpartyCommitment);
117-
nodes[1].node.signer_unblocked(Some((nodes[0].node.get_our_node_id(), chan_id)));
179+
for op in signer_ops.iter() {
180+
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, *op);
181+
nodes[1].node.signer_unblocked(Some((nodes[0].node.get_our_node_id(), chan_id)));
182+
}
118183

119184
expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
120185

@@ -189,7 +254,12 @@ fn do_test_async_commitment_signature_for_commitment_signed_revoke_and_ack(test_
189254
}
190255

191256
#[test]
192-
fn test_async_commitment_signature_for_funding_signed_0conf() {
257+
fn test_funding_signed_0conf() {
258+
do_test_funding_signed_0conf(vec![SignerOp::SignCounterpartyCommitment, SignerOp::SignCounterpartyCommitment]);
259+
do_test_funding_signed_0conf(vec![SignerOp::SignCounterpartyCommitment, SignerOp::GetPerCommitmentPoint]);
260+
}
261+
262+
fn do_test_funding_signed_0conf(signer_ops: Vec<SignerOp>) {
193263
// Simulate acquiring the signature for `funding_signed` asynchronously for a zero-conf channel.
194264
let mut manually_accept_config = test_default_channel_config();
195265
manually_accept_config.manually_accept_inbound_channels = true;
@@ -232,7 +302,9 @@ fn test_async_commitment_signature_for_funding_signed_0conf() {
232302

233303
// Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should
234304
// *not* broadcast a `funding_signed`...
235-
nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &temporary_channel_id, SignerOp::SignCounterpartyCommitment);
305+
for op in signer_ops.iter() {
306+
nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &temporary_channel_id, *op);
307+
}
236308
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
237309
check_added_monitors(&nodes[1], 1);
238310

@@ -247,8 +319,10 @@ fn test_async_commitment_signature_for_funding_signed_0conf() {
247319
};
248320

249321
// At this point, we basically expect the channel to open like a normal zero-conf channel.
250-
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, SignerOp::SignCounterpartyCommitment);
251-
nodes[1].node.signer_unblocked(Some((nodes[0].node.get_our_node_id(), chan_id)));
322+
for op in signer_ops.iter() {
323+
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, *op);
324+
nodes[1].node.signer_unblocked(Some((nodes[0].node.get_our_node_id(), chan_id)));
325+
}
252326

253327
let (funding_signed, channel_ready_1) = {
254328
let events = nodes[1].node.get_and_clear_pending_msg_events();

lightning/src/ln/channel.rs

+13-13
Original file line numberDiff line numberDiff line change
@@ -7640,7 +7640,19 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
76407640
// TODO (taproot|arik): move match into calling method for Taproot
76417641
ChannelSignerType::Ecdsa(ecdsa) => {
76427642
ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), Vec::new(), &self.context.secp_ctx)
7643-
.map(|(sig, _)| sig).ok()?
7643+
.map(|(sig, _)| sig)
7644+
.map_err(|()| {
7645+
#[cfg(not(async_signing))] {
7646+
panic!("Failed to get signature for new funding creation");
7647+
}
7648+
#[cfg(async_signing)] {
7649+
if !self.context.signer_pending_funding {
7650+
log_trace!(logger, "funding_created awaiting signer; setting signer_pending_funding");
7651+
self.context.signer_pending_funding = true;
7652+
}
7653+
}
7654+
})
7655+
.ok()?
76447656
},
76457657
// TODO (taproot|arik)
76467658
#[cfg(taproot)]
@@ -7708,18 +7720,6 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
77087720
self.context.is_batch_funding = Some(()).filter(|_| is_batch_funding);
77097721

77107722
let funding_created = self.get_funding_created_msg(logger);
7711-
if funding_created.is_none() {
7712-
#[cfg(not(async_signing))] {
7713-
panic!("Failed to get signature for new funding creation");
7714-
}
7715-
#[cfg(async_signing)] {
7716-
if !self.context.signer_pending_funding {
7717-
log_trace!(logger, "funding_created awaiting signer; setting signer_pending_funding");
7718-
self.context.signer_pending_funding = true;
7719-
}
7720-
}
7721-
}
7722-
77237723
Ok(funding_created)
77247724
}
77257725

lightning/src/ln/functional_test_utils.rs

+5
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,11 @@ impl<'a, 'b, 'c> Node<'a, 'b, 'c> {
554554
entry.insert(signer_op);
555555
};
556556
}
557+
558+
#[cfg(test)]
559+
pub fn disable_next_channel_signer_op(&self, signer_op: SignerOp) {
560+
self.keys_manager.next_signer_disabled_ops.lock().unwrap().insert(signer_op);
561+
}
557562
}
558563

559564
/// If we need an unsafe pointer to a `Node` (ie to reference it in a thread

lightning/src/util/test_utils.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1225,6 +1225,7 @@ pub struct TestKeysInterface {
12251225
expectations: Mutex<Option<VecDeque<OnGetShutdownScriptpubkey>>>,
12261226
pub unavailable_signers: Mutex<HashSet<[u8; 32]>>,
12271227
pub unavailable_signers_ops: Mutex<HashMap<[u8; 32], HashSet<SignerOp>>>,
1228+
pub next_signer_disabled_ops: Mutex<HashSet<SignerOp>>,
12281229
}
12291230

12301231
impl EntropySource for TestKeysInterface {
@@ -1289,6 +1290,10 @@ impl SignerProvider for TestKeysInterface {
12891290
signer.disable_op(op);
12901291
}
12911292
}
1293+
#[cfg(test)]
1294+
for op in self.next_signer_disabled_ops.lock().unwrap().drain() {
1295+
signer.disable_op(op);
1296+
}
12921297
signer
12931298
}
12941299

@@ -1329,6 +1334,7 @@ impl TestKeysInterface {
13291334
expectations: Mutex::new(None),
13301335
unavailable_signers: Mutex::new(new_hash_set()),
13311336
unavailable_signers_ops: Mutex::new(new_hash_map()),
1337+
next_signer_disabled_ops: Mutex::new(new_hash_set()),
13321338
}
13331339
}
13341340

0 commit comments

Comments
 (0)