Skip to content

Commit 7ea6d3f

Browse files
committed
Add test for async open and accept channel
1 parent 51ae0c4 commit 7ea6d3f

File tree

3 files changed

+98
-13
lines changed

3 files changed

+98
-13
lines changed

lightning/src/ln/async_signer_tests.rs

+87-13
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
//! Tests for asynchronous signing. These tests verify that the channel state machine behaves
1111
//! properly with a signer implementation that asynchronously derives signatures.
1212
13-
use std::collections::HashSet;
13+
use crate::prelude::*;
1414

1515
use bitcoin::{Transaction, TxOut, TxIn, Amount};
1616
use bitcoin::blockdata::locktime::absolute::LockTime;
@@ -27,7 +27,59 @@ use crate::util::test_channel_signer::SignerOp;
2727
use crate::util::logger::Logger;
2828

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

@@ -62,8 +116,10 @@ fn test_async_commitment_signature_for_funding_created() {
62116
channels[0].channel_id
63117
};
64118

65-
nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignCounterpartyCommitment);
66-
nodes[0].node.signer_unblocked(Some((nodes[1].node.get_our_node_id(), chan_id)));
119+
for op in signer_ops.iter() {
120+
nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, *op);
121+
nodes[0].node.signer_unblocked(Some((nodes[1].node.get_our_node_id(), chan_id)));
122+
}
67123

68124
let mut funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
69125
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
@@ -78,7 +134,12 @@ fn test_async_commitment_signature_for_funding_created() {
78134
}
79135

80136
#[test]
81-
fn test_async_commitment_signature_for_funding_signed() {
137+
fn test_funding_signed() {
138+
do_test_funding_signed(vec![SignerOp::SignCounterpartyCommitment, SignerOp::GetPerCommitmentPoint]);
139+
do_test_funding_signed(vec![SignerOp::GetPerCommitmentPoint, SignerOp::SignCounterpartyCommitment]);
140+
}
141+
142+
fn do_test_funding_signed(signer_ops: Vec<SignerOp>) {
82143
// Simulate acquiring the signature for `funding_signed` asynchronously.
83144
let chanmon_cfgs = create_chanmon_cfgs(2);
84145
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
@@ -103,7 +164,9 @@ fn test_async_commitment_signature_for_funding_signed() {
103164

104165
// Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should
105166
// *not* broadcast a `funding_signed`...
106-
nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &temporary_channel_id, SignerOp::SignCounterpartyCommitment);
167+
for op in signer_ops.iter() {
168+
nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &temporary_channel_id, *op);
169+
}
107170
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
108171
check_added_monitors(&nodes[1], 1);
109172

@@ -116,8 +179,10 @@ fn test_async_commitment_signature_for_funding_signed() {
116179
assert_eq!(channels.len(), 1, "expected one channel, not {}", channels.len());
117180
channels[0].channel_id
118181
};
119-
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, SignerOp::SignCounterpartyCommitment);
120-
nodes[1].node.signer_unblocked(Some((nodes[0].node.get_our_node_id(), chan_id)));
182+
for op in signer_ops.iter() {
183+
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, *op);
184+
nodes[1].node.signer_unblocked(Some((nodes[0].node.get_our_node_id(), chan_id)));
185+
}
121186

122187
expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
123188

@@ -200,7 +265,12 @@ fn do_test_async_commitment_signature_for_commitment_signed_revoke_and_ack(enabl
200265
}
201266

202267
#[test]
203-
fn test_async_commitment_signature_for_funding_signed_0conf() {
268+
fn test_funding_signed_0conf() {
269+
do_test_funding_signed_0conf(vec![SignerOp::GetPerCommitmentPoint, SignerOp::SignCounterpartyCommitment]);
270+
do_test_funding_signed_0conf(vec![SignerOp::SignCounterpartyCommitment, SignerOp::GetPerCommitmentPoint]);
271+
}
272+
273+
fn do_test_funding_signed_0conf(signer_ops: Vec<SignerOp>) {
204274
// Simulate acquiring the signature for `funding_signed` asynchronously for a zero-conf channel.
205275
let mut manually_accept_config = test_default_channel_config();
206276
manually_accept_config.manually_accept_inbound_channels = true;
@@ -243,7 +313,9 @@ fn test_async_commitment_signature_for_funding_signed_0conf() {
243313

244314
// Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should
245315
// *not* broadcast a `funding_signed`...
246-
nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &temporary_channel_id, SignerOp::SignCounterpartyCommitment);
316+
for op in signer_ops.iter() {
317+
nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &temporary_channel_id, *op);
318+
}
247319
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
248320
check_added_monitors(&nodes[1], 1);
249321

@@ -258,8 +330,10 @@ fn test_async_commitment_signature_for_funding_signed_0conf() {
258330
};
259331

260332
// At this point, we basically expect the channel to open like a normal zero-conf channel.
261-
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, SignerOp::SignCounterpartyCommitment);
262-
nodes[1].node.signer_unblocked(Some((nodes[0].node.get_our_node_id(), chan_id)));
333+
for op in signer_ops.iter() {
334+
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, *op);
335+
nodes[1].node.signer_unblocked(Some((nodes[0].node.get_our_node_id(), chan_id)));
336+
}
263337

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

lightning/src/ln/functional_test_utils.rs

+5
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,11 @@ impl<'a, 'b, 'c> Node<'a, 'b, 'c> {
570570
entry.insert(signer_op);
571571
};
572572
}
573+
574+
#[cfg(test)]
575+
pub fn disable_next_channel_signer_op(&self, signer_op: SignerOp) {
576+
self.keys_manager.next_signer_disabled_ops.lock().unwrap().insert(signer_op);
577+
}
573578
}
574579

575580
/// 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
@@ -1245,6 +1245,7 @@ pub struct TestKeysInterface {
12451245
enforcement_states: Mutex<HashMap<[u8;32], Arc<Mutex<EnforcementState>>>>,
12461246
expectations: Mutex<Option<VecDeque<OnGetShutdownScriptpubkey>>>,
12471247
pub unavailable_signers_ops: Mutex<HashMap<[u8; 32], HashSet<SignerOp>>>,
1248+
pub next_signer_disabled_ops: Mutex<HashSet<SignerOp>>,
12481249
}
12491250

12501251
impl EntropySource for TestKeysInterface {
@@ -1310,6 +1311,10 @@ impl SignerProvider for TestKeysInterface {
13101311
signer.disable_op(op);
13111312
}
13121313
}
1314+
#[cfg(test)]
1315+
for op in self.next_signer_disabled_ops.lock().unwrap().drain() {
1316+
signer.disable_op(op);
1317+
}
13131318
signer
13141319
}
13151320

@@ -1349,6 +1354,7 @@ impl TestKeysInterface {
13491354
enforcement_states: Mutex::new(new_hash_map()),
13501355
expectations: Mutex::new(None),
13511356
unavailable_signers_ops: Mutex::new(new_hash_map()),
1357+
next_signer_disabled_ops: Mutex::new(new_hash_set()),
13521358
}
13531359
}
13541360

0 commit comments

Comments
 (0)