Skip to content

Commit 50b1d88

Browse files
committed
Add test for async open and accept channel
1 parent de37adf commit 50b1d88

File tree

3 files changed

+99
-14
lines changed

3 files changed

+99
-14
lines changed

lightning/src/ln/async_signer_tests.rs

+88-14
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
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;
14-
use bitcoin::key::Secp256k1;
13+
use crate::prelude::*;
14+
use bitcoin::secp256k1::Secp256k1;
1515
use bitcoin::{Transaction, TxOut, TxIn, Amount};
1616
use bitcoin::locktime::absolute::LockTime;
1717
use bitcoin::transaction::Version;
@@ -31,7 +31,59 @@ use crate::util::test_channel_signer::SignerOp;
3131
use crate::util::logger::Logger;
3232

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

@@ -66,8 +120,10 @@ fn test_async_commitment_signature_for_funding_created() {
66120
channels[0].channel_id
67121
};
68122

69-
nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignCounterpartyCommitment);
70-
nodes[0].node.signer_unblocked(Some((nodes[1].node.get_our_node_id(), chan_id)));
123+
for op in signer_ops.iter() {
124+
nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, *op);
125+
nodes[0].node.signer_unblocked(Some((nodes[1].node.get_our_node_id(), chan_id)));
126+
}
71127

72128
let mut funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
73129
nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created_msg);
@@ -82,7 +138,12 @@ fn test_async_commitment_signature_for_funding_created() {
82138
}
83139

84140
#[test]
85-
fn test_async_commitment_signature_for_funding_signed() {
141+
fn test_funding_signed() {
142+
do_test_funding_signed(vec![SignerOp::SignCounterpartyCommitment, SignerOp::GetPerCommitmentPoint]);
143+
do_test_funding_signed(vec![SignerOp::GetPerCommitmentPoint, SignerOp::SignCounterpartyCommitment]);
144+
}
145+
146+
fn do_test_funding_signed(signer_ops: Vec<SignerOp>) {
86147
// Simulate acquiring the signature for `funding_signed` asynchronously.
87148
let chanmon_cfgs = create_chanmon_cfgs(2);
88149
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
@@ -107,7 +168,9 @@ fn test_async_commitment_signature_for_funding_signed() {
107168

108169
// Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should
109170
// *not* broadcast a `funding_signed`...
110-
nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &temporary_channel_id, SignerOp::SignCounterpartyCommitment);
171+
for op in signer_ops.iter() {
172+
nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &temporary_channel_id, *op);
173+
}
111174
nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created_msg);
112175
check_added_monitors(&nodes[1], 1);
113176

@@ -120,8 +183,10 @@ fn test_async_commitment_signature_for_funding_signed() {
120183
assert_eq!(channels.len(), 1, "expected one channel, not {}", channels.len());
121184
channels[0].channel_id
122185
};
123-
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, SignerOp::SignCounterpartyCommitment);
124-
nodes[1].node.signer_unblocked(Some((nodes[0].node.get_our_node_id(), chan_id)));
186+
for op in signer_ops.iter() {
187+
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, *op);
188+
nodes[1].node.signer_unblocked(Some((nodes[0].node.get_our_node_id(), chan_id)));
189+
}
125190

126191
expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
127192

@@ -204,7 +269,12 @@ fn do_test_async_commitment_signature_for_commitment_signed_revoke_and_ack(enabl
204269
}
205270

206271
#[test]
207-
fn test_async_commitment_signature_for_funding_signed_0conf() {
272+
fn test_funding_signed_0conf() {
273+
do_test_funding_signed_0conf(vec![SignerOp::GetPerCommitmentPoint, SignerOp::SignCounterpartyCommitment]);
274+
do_test_funding_signed_0conf(vec![SignerOp::SignCounterpartyCommitment, SignerOp::GetPerCommitmentPoint]);
275+
}
276+
277+
fn do_test_funding_signed_0conf(signer_ops: Vec<SignerOp>) {
208278
// Simulate acquiring the signature for `funding_signed` asynchronously for a zero-conf channel.
209279
let mut manually_accept_config = test_default_channel_config();
210280
manually_accept_config.manually_accept_inbound_channels = true;
@@ -247,7 +317,9 @@ fn test_async_commitment_signature_for_funding_signed_0conf() {
247317

248318
// Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should
249319
// *not* broadcast a `funding_signed`...
250-
nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &temporary_channel_id, SignerOp::SignCounterpartyCommitment);
320+
for op in signer_ops.iter() {
321+
nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &temporary_channel_id, *op);
322+
}
251323
nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created_msg);
252324
check_added_monitors(&nodes[1], 1);
253325

@@ -262,8 +334,10 @@ fn test_async_commitment_signature_for_funding_signed_0conf() {
262334
};
263335

264336
// At this point, we basically expect the channel to open like a normal zero-conf channel.
265-
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, SignerOp::SignCounterpartyCommitment);
266-
nodes[1].node.signer_unblocked(Some((nodes[0].node.get_our_node_id(), chan_id)));
337+
for op in signer_ops.iter() {
338+
nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, *op);
339+
nodes[1].node.signer_unblocked(Some((nodes[0].node.get_our_node_id(), chan_id)));
340+
}
267341

268342
let (funding_signed, channel_ready_1) = {
269343
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
@@ -559,6 +559,11 @@ impl<'a, 'b, 'c> Node<'a, 'b, 'c> {
559559
entry.insert(signer_op);
560560
};
561561
}
562+
563+
#[cfg(test)]
564+
pub fn disable_next_channel_signer_op(&self, signer_op: SignerOp) {
565+
self.keys_manager.next_signer_disabled_ops.lock().unwrap().insert(signer_op);
566+
}
562567
}
563568

564569
/// 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
@@ -1260,6 +1260,7 @@ pub struct TestKeysInterface {
12601260
enforcement_states: Mutex<HashMap<[u8;32], Arc<Mutex<EnforcementState>>>>,
12611261
expectations: Mutex<Option<VecDeque<OnGetShutdownScriptpubkey>>>,
12621262
pub unavailable_signers_ops: Mutex<HashMap<[u8; 32], HashSet<SignerOp>>>,
1263+
pub next_signer_disabled_ops: Mutex<HashSet<SignerOp>>,
12631264
}
12641265

12651266
impl EntropySource for TestKeysInterface {
@@ -1325,6 +1326,10 @@ impl SignerProvider for TestKeysInterface {
13251326
signer.disable_op(op);
13261327
}
13271328
}
1329+
#[cfg(test)]
1330+
for op in self.next_signer_disabled_ops.lock().unwrap().drain() {
1331+
signer.disable_op(op);
1332+
}
13281333
signer
13291334
}
13301335

@@ -1364,6 +1369,7 @@ impl TestKeysInterface {
13641369
enforcement_states: Mutex::new(new_hash_map()),
13651370
expectations: Mutex::new(None),
13661371
unavailable_signers_ops: Mutex::new(new_hash_map()),
1372+
next_signer_disabled_ops: Mutex::new(new_hash_set()),
13671373
}
13681374
}
13691375

0 commit comments

Comments
 (0)