Skip to content

Commit 926c588

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 5f3a7f2 commit 926c588

File tree

4 files changed

+133
-4
lines changed

4 files changed

+133
-4
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
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 channels = nodes[0].node.list_channels();
54+
assert_eq!(channels.len(), 1, "expected one channel, not {}", channels.len());
55+
channels[0].channel_id
56+
};
57+
58+
nodes[0].set_channel_signer_available(&nodes[1].node.get_our_node_id(), &chan_id, true);
59+
nodes[0].node.signer_unblocked(Some((nodes[1].node.get_our_node_id(), chan_id)));
60+
61+
let mut funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
62+
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
63+
check_added_monitors(&nodes[1], 1);
64+
expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
65+
66+
// nodes[0] <-- funding_signed --- nodes[1]
67+
let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
68+
nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed_msg);
69+
check_added_monitors(&nodes[0], 1);
70+
expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id());
71+
}
72+
73+
#[test]
74+
fn test_async_commitment_signature_for_funding_signed() {
75+
// Simulate acquiring the signature for `funding_signed` asynchronously.
76+
let chanmon_cfgs = create_chanmon_cfgs(2);
77+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
78+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
79+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
80+
81+
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None).unwrap();
82+
83+
// nodes[0] --- open_channel --> nodes[1]
84+
let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
85+
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_chan_msg);
86+
87+
// nodes[0] <-- accept_channel --- nodes[1]
88+
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()));
89+
90+
// nodes[0] --- funding_created --> nodes[1]
91+
let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42);
92+
nodes[0].node.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), tx.clone()).unwrap();
93+
check_added_monitors(&nodes[0], 0);
94+
95+
let mut funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
96+
97+
// Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should
98+
// *not* broadcast a `funding_signed`...
99+
nodes[1].set_channel_signer_available(&nodes[0].node.get_our_node_id(), &temporary_channel_id, false);
100+
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
101+
check_added_monitors(&nodes[1], 1);
102+
103+
{
104+
let events = nodes[1].node.get_and_clear_pending_msg_events();
105+
let n = events.len();
106+
assert_eq!(n, 0, "expected no events generated from nodes[1], found {}", n);
107+
}
108+
109+
// Now re-enable the signer and simulate a retry. The temporary_channel_id won't work anymore so
110+
// we have to dig out the real channel ID.
111+
let chan_id = {
112+
let channels = nodes[0].node.list_channels();
113+
assert_eq!(channels.len(), 1, "expected one channel, not {}", channels.len());
114+
channels[0].channel_id
115+
};
116+
nodes[1].set_channel_signer_available(&nodes[0].node.get_our_node_id(), &chan_id, true);
117+
nodes[1].node.signer_unblocked(Some((nodes[0].node.get_our_node_id(), chan_id)));
118+
119+
expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
120+
121+
// nodes[0] <-- funding_signed --- nodes[1]
122+
let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
123+
nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed_msg);
124+
check_added_monitors(&nodes[0], 1);
125+
expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id());
126+
}

lightning/src/ln/channel.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2156,7 +2156,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
21562156
}
21572157
}
21582158
}
2159-
21602159
}
21612160

21622161
// 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
@@ -2106,12 +2106,13 @@ macro_rules! expect_channel_shutdown_state {
21062106
}
21072107

21082108
#[cfg(any(test, ldk_bench, feature = "_test_utils"))]
2109-
pub fn expect_channel_pending_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, expected_counterparty_node_id: &PublicKey) {
2109+
pub fn expect_channel_pending_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, expected_counterparty_node_id: &PublicKey) -> ChannelId {
21102110
let events = node.node.get_and_clear_pending_events();
21112111
assert_eq!(events.len(), 1);
2112-
match events[0] {
2113-
crate::events::Event::ChannelPending { ref counterparty_node_id, .. } => {
2112+
match &events[0] {
2113+
crate::events::Event::ChannelPending { channel_id, counterparty_node_id, .. } => {
21142114
assert_eq!(*expected_counterparty_node_id, *counterparty_node_id);
2115+
*channel_id
21152116
},
21162117
_ => panic!("Unexpected event"),
21172118
}

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)