Skip to content

Commit 2135718

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 3cc98e3 commit 2135718

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
@@ -2056,7 +2056,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
20562056
}
20572057
}
20582058
}
2059-
20602059
}
20612060

20622061
// 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
@@ -2084,12 +2084,13 @@ macro_rules! expect_channel_shutdown_state {
20842084
}
20852085

20862086
#[cfg(any(test, ldk_bench, feature = "_test_utils"))]
2087-
pub fn expect_channel_pending_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, expected_counterparty_node_id: &PublicKey) {
2087+
pub fn expect_channel_pending_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, expected_counterparty_node_id: &PublicKey) -> ChannelId {
20882088
let events = node.node.get_and_clear_pending_events();
20892089
assert_eq!(events.len(), 1);
2090-
match events[0] {
2091-
crate::events::Event::ChannelPending { ref counterparty_node_id, .. } => {
2090+
match &events[0] {
2091+
crate::events::Event::ChannelPending { channel_id, counterparty_node_id, .. } => {
20922092
assert_eq!(*expected_counterparty_node_id, *counterparty_node_id);
2093+
*channel_id
20932094
},
20942095
_ => panic!("Unexpected event"),
20952096
}

lightning/src/ln/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ mod monitor_tests;
7070
#[cfg(test)]
7171
#[allow(unused_mut)]
7272
mod shutdown_tests;
73+
#[cfg(test)]
74+
#[allow(unused_mut)]
75+
mod async_signer_tests;
7376

7477
pub use self::peer_channel_encryptor::LN_MAX_MSG_LEN;
7578

0 commit comments

Comments
 (0)