Skip to content

Commit 07209ce

Browse files
committed
Add basic async signer tests
This adds a new `async_signer_tests` module and populates it with some simple checks for asynchronous handling of `funding_created` and `funding_signed`.
1 parent 0983db1 commit 07209ce

File tree

4 files changed

+139
-4
lines changed

4 files changed

+139
-4
lines changed
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
// This file is Copyright its original authors, visible in version control
2+
// history.
3+
//
4+
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5+
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7+
// You may not use this file except in accordance with one or both of these
8+
// licenses.
9+
10+
//! Tests for asynchronous signing. These tests verify that the channel state machine behaves
11+
//! properly with a signer implementation that asynchronously derives signatures.
12+
13+
use crate::events::{MessageSendEvent, MessageSendEventsProvider};
14+
use crate::ln::msgs::ChannelMessageHandler;
15+
16+
use crate::ln::functional_test_utils::*;
17+
18+
#[test]
19+
fn test_async_commitment_signature_for_funding_created() {
20+
// Simulate acquiring the signature for `funding_created` asynchronously.
21+
let chanmon_cfgs = create_chanmon_cfgs(2);
22+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
23+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
24+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
25+
26+
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None).unwrap();
27+
28+
// nodes[0] --- open_channel --> nodes[1]
29+
let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
30+
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_chan_msg);
31+
32+
// nodes[0] <-- accept_channel --- nodes[1]
33+
nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()));
34+
35+
// nodes[0] --- funding_created --> nodes[1]
36+
//
37+
// But! Let's make node[0]'s signer be unavailable: we should *not* broadcast a funding_created
38+
// message...
39+
let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42);
40+
nodes[0].set_channel_signer_available(&nodes[1].node.get_our_node_id(), &temporary_channel_id, false);
41+
nodes[0].node.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), tx.clone()).unwrap();
42+
check_added_monitors(&nodes[0], 0);
43+
44+
{
45+
let events = nodes[0].node.get_and_clear_pending_msg_events();
46+
let n = events.len();
47+
assert_eq!(n, 0, "expected no events generated from nodes[0], found {}", n);
48+
}
49+
50+
// Now re-enable the signer and simulate a retry. The temporary_channel_id won't work anymore so
51+
// we have to dig out the real channel ID.
52+
let chan_id = {
53+
let per_peer_state = nodes[0].node.per_peer_state.read().unwrap();
54+
let chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap();
55+
let chan_ids = chan_lock.channel_by_id.keys().collect::<Vec<_>>();
56+
let n = chan_ids.len();
57+
assert_eq!(n, 1, "expected one channel, not {}", n);
58+
*chan_ids[0]
59+
};
60+
61+
nodes[0].set_channel_signer_available(&nodes[1].node.get_our_node_id(), &chan_id, true);
62+
nodes[0].node.signer_unblocked(Some((nodes[1].node.get_our_node_id(), chan_id)));
63+
64+
let mut funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
65+
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
66+
check_added_monitors(&nodes[1], 1);
67+
expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
68+
69+
// nodes[0] <-- funding_signed --- nodes[1]
70+
let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
71+
nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed_msg);
72+
check_added_monitors(&nodes[0], 1);
73+
expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id());
74+
}
75+
76+
#[test]
77+
fn test_async_commitment_signature_for_funding_signed() {
78+
// Simulate acquiring the signature for `funding_signed` asynchronously.
79+
let chanmon_cfgs = create_chanmon_cfgs(2);
80+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
81+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
82+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
83+
84+
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None).unwrap();
85+
86+
// nodes[0] --- open_channel --> nodes[1]
87+
let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
88+
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_chan_msg);
89+
90+
// nodes[0] <-- accept_channel --- nodes[1]
91+
nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()));
92+
93+
// nodes[0] --- funding_created --> nodes[1]
94+
let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42);
95+
nodes[0].node.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), tx.clone()).unwrap();
96+
check_added_monitors(&nodes[0], 0);
97+
98+
let mut funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
99+
100+
// Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should
101+
// *not* broadcast a `funding_signed`...
102+
nodes[1].set_channel_signer_available(&nodes[0].node.get_our_node_id(), &temporary_channel_id, false);
103+
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
104+
check_added_monitors(&nodes[1], 1);
105+
106+
{
107+
let events = nodes[1].node.get_and_clear_pending_msg_events();
108+
let n = events.len();
109+
assert_eq!(n, 0, "expected no events generated from nodes[1], found {}", n);
110+
}
111+
112+
// Now re-enable the signer and simulate a retry. The temporary_channel_id won't work anymore so
113+
// we have to dig out the real channel ID.
114+
let chan_id = {
115+
let per_peer_state = nodes[1].node.per_peer_state.read().unwrap();
116+
let chan_lock = per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap();
117+
let chan_ids = chan_lock.channel_by_id.keys().collect::<Vec<_>>();
118+
let n = chan_ids.len();
119+
assert_eq!(n, 1, "expected one channel, not {}", n);
120+
*chan_ids[0]
121+
};
122+
nodes[1].set_channel_signer_available(&nodes[0].node.get_our_node_id(), &chan_id, true);
123+
nodes[1].node.signer_unblocked(Some((nodes[0].node.get_our_node_id(), chan_id)));
124+
125+
expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
126+
127+
// nodes[0] <-- funding_signed --- nodes[1]
128+
let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
129+
nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed_msg);
130+
check_added_monitors(&nodes[0], 1);
131+
expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id());
132+
}

lightning/src/ln/channel.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2085,7 +2085,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
20852085
}
20862086
}
20872087
}
2088-
20892088
}
20902089

20912090
// Internal utility functions for channels

lightning/src/ln/functional_test_utils.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2072,12 +2072,13 @@ macro_rules! expect_channel_shutdown_state {
20722072
}
20732073

20742074
#[cfg(any(test, ldk_bench, feature = "_test_utils"))]
2075-
pub fn expect_channel_pending_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, expected_counterparty_node_id: &PublicKey) {
2075+
pub fn expect_channel_pending_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, expected_counterparty_node_id: &PublicKey) -> ChannelId {
20762076
let events = node.node.get_and_clear_pending_events();
20772077
assert_eq!(events.len(), 1);
2078-
match events[0] {
2079-
crate::events::Event::ChannelPending { ref counterparty_node_id, .. } => {
2078+
match &events[0] {
2079+
crate::events::Event::ChannelPending { channel_id, counterparty_node_id, .. } => {
20802080
assert_eq!(*expected_counterparty_node_id, *counterparty_node_id);
2081+
*channel_id
20812082
},
20822083
_ => panic!("Unexpected event"),
20832084
}

lightning/src/ln/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ mod monitor_tests;
7373
#[cfg(test)]
7474
#[allow(unused_mut)]
7575
mod shutdown_tests;
76+
#[cfg(test)]
77+
#[allow(unused_mut)]
78+
mod async_signer_tests;
7679

7780
pub use self::peer_channel_encryptor::LN_MAX_MSG_LEN;
7881

0 commit comments

Comments
 (0)