Skip to content

Commit 014a336

Browse files
committed
Add basic async signer tests
Adds a `get_signer` method to the context so that a test can get ahold of the channel signer. Adds a `set_available` method on the `TestChannelSigner` to allow a test to enable and disable the signer: when disabled some of the signer's methods will return `Err` which will typically activate the error handling case. Adds a `set_channel_signer_available` function on the test `Node` class to make it easy to enable and disable a specific signer. Adds a new `async_signer_tests` module: * Check for asynchronous handling of `funding_created` and `funding_signed`. * Check that we correctly resume processing after awaiting an asynchronous signature for a `commitment_signed` event. * Verify correct handling during peer disconnect. * Verify correct handling for inbound zero-conf.
1 parent 4278afc commit 014a336

File tree

6 files changed

+394
-11
lines changed

6 files changed

+394
-11
lines changed

fuzz/src/chanmon_consistency.rs

+1
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ impl SignerProvider for KeyProvider {
267267
inner,
268268
state,
269269
disable_revocation_policy_check: false,
270+
available: Arc::new(Mutex::new(true)),
270271
})
271272
}
272273

+323
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
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::{Event, MessageSendEvent, MessageSendEventsProvider};
14+
use crate::ln::functional_test_utils::*;
15+
use crate::ln::msgs::ChannelMessageHandler;
16+
use crate::ln::channelmanager::{PaymentId, RecipientOnionFields};
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+
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
45+
46+
// Now re-enable the signer and simulate a retry. The temporary_channel_id won't work anymore so
47+
// we have to dig out the real channel ID.
48+
let chan_id = {
49+
let channels = nodes[0].node.list_channels();
50+
assert_eq!(channels.len(), 1, "expected one channel, not {}", channels.len());
51+
channels[0].channel_id
52+
};
53+
54+
nodes[0].set_channel_signer_available(&nodes[1].node.get_our_node_id(), &chan_id, true);
55+
nodes[0].node.signer_unblocked(Some((nodes[1].node.get_our_node_id(), chan_id)));
56+
57+
let mut funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
58+
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
59+
check_added_monitors(&nodes[1], 1);
60+
expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
61+
62+
// nodes[0] <-- funding_signed --- nodes[1]
63+
let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
64+
nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed_msg);
65+
check_added_monitors(&nodes[0], 1);
66+
expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id());
67+
}
68+
69+
#[test]
70+
fn test_async_commitment_signature_for_funding_signed() {
71+
// Simulate acquiring the signature for `funding_signed` asynchronously.
72+
let chanmon_cfgs = create_chanmon_cfgs(2);
73+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
74+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
75+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
76+
77+
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None).unwrap();
78+
79+
// nodes[0] --- open_channel --> nodes[1]
80+
let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
81+
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_chan_msg);
82+
83+
// nodes[0] <-- accept_channel --- nodes[1]
84+
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()));
85+
86+
// nodes[0] --- funding_created --> nodes[1]
87+
let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42);
88+
nodes[0].node.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), tx.clone()).unwrap();
89+
check_added_monitors(&nodes[0], 0);
90+
91+
let mut funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
92+
93+
// Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should
94+
// *not* broadcast a `funding_signed`...
95+
nodes[1].set_channel_signer_available(&nodes[0].node.get_our_node_id(), &temporary_channel_id, false);
96+
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
97+
check_added_monitors(&nodes[1], 1);
98+
99+
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
100+
101+
// Now re-enable the signer and simulate a retry. The temporary_channel_id won't work anymore so
102+
// we have to dig out the real channel ID.
103+
let chan_id = {
104+
let channels = nodes[0].node.list_channels();
105+
assert_eq!(channels.len(), 1, "expected one channel, not {}", channels.len());
106+
channels[0].channel_id
107+
};
108+
nodes[1].set_channel_signer_available(&nodes[0].node.get_our_node_id(), &chan_id, true);
109+
nodes[1].node.signer_unblocked(Some((nodes[0].node.get_our_node_id(), chan_id)));
110+
111+
expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
112+
113+
// nodes[0] <-- funding_signed --- nodes[1]
114+
let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
115+
nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed_msg);
116+
check_added_monitors(&nodes[0], 1);
117+
expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id());
118+
}
119+
120+
#[test]
121+
fn test_async_commitment_signature_for_commitment_signed() {
122+
let chanmon_cfgs = create_chanmon_cfgs(2);
123+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
124+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
125+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
126+
let (_, _, chan_id, _) = create_announced_chan_between_nodes(&nodes, 0, 1);
127+
128+
// Send a payment.
129+
let src = &nodes[0];
130+
let dst = &nodes[1];
131+
let (route, our_payment_hash, _our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(src, dst, 8000000);
132+
src.node.send_payment_with_route(&route, our_payment_hash,
133+
RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap();
134+
check_added_monitors!(src, 1);
135+
136+
// Pass the payment along the route.
137+
let payment_event = {
138+
let mut events = src.node.get_and_clear_pending_msg_events();
139+
assert_eq!(events.len(), 1);
140+
SendEvent::from_event(events.remove(0))
141+
};
142+
assert_eq!(payment_event.node_id, dst.node.get_our_node_id());
143+
assert_eq!(payment_event.msgs.len(), 1);
144+
145+
dst.node.handle_update_add_htlc(&src.node.get_our_node_id(), &payment_event.msgs[0]);
146+
147+
// Mark dst's signer as unavailable and handle src's commitment_signed: while dst won't yet have a
148+
// `commitment_signed` of its own to offer, it should publish a `revoke_and_ack`.
149+
dst.set_channel_signer_available(&src.node.get_our_node_id(), &chan_id, false);
150+
dst.node.handle_commitment_signed(&src.node.get_our_node_id(), &payment_event.commitment_msg);
151+
check_added_monitors(dst, 1);
152+
153+
get_event_msg!(dst, MessageSendEvent::SendRevokeAndACK, src.node.get_our_node_id());
154+
155+
// Mark dst's signer as available and retry: we now expect to see dst's `commitment_signed`.
156+
dst.set_channel_signer_available(&src.node.get_our_node_id(), &chan_id, true);
157+
dst.node.signer_unblocked(Some((src.node.get_our_node_id(), chan_id)));
158+
159+
let events = dst.node.get_and_clear_pending_msg_events();
160+
assert_eq!(events.len(), 1, "expected one message, got {}", events.len());
161+
if let MessageSendEvent::UpdateHTLCs { ref node_id, .. } = events[0] {
162+
assert_eq!(node_id, &src.node.get_our_node_id());
163+
} else {
164+
panic!("expected UpdateHTLCs message, not {:?}", events[0]);
165+
};
166+
}
167+
168+
#[test]
169+
fn test_async_commitment_signature_for_funding_signed_0conf() {
170+
// Simulate acquiring the signature for `funding_signed` asynchronously for a zero-conf channel.
171+
let mut manually_accept_config = test_default_channel_config();
172+
manually_accept_config.manually_accept_inbound_channels = true;
173+
174+
let chanmon_cfgs = create_chanmon_cfgs(2);
175+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
176+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(manually_accept_config)]);
177+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
178+
179+
// nodes[0] --- open_channel --> nodes[1]
180+
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None).unwrap();
181+
let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
182+
183+
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel);
184+
185+
{
186+
let events = nodes[1].node.get_and_clear_pending_events();
187+
assert_eq!(events.len(), 1, "Expected one event, got {}", events.len());
188+
match &events[0] {
189+
Event::OpenChannelRequest { temporary_channel_id, .. } => {
190+
nodes[1].node.accept_inbound_channel_from_trusted_peer_0conf(
191+
temporary_channel_id, &nodes[0].node.get_our_node_id(), 0)
192+
.expect("Unable to accept inbound zero-conf channel");
193+
},
194+
ev => panic!("Expected OpenChannelRequest, not {:?}", ev)
195+
}
196+
}
197+
198+
// nodes[0] <-- accept_channel --- nodes[1]
199+
let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
200+
assert_eq!(accept_channel.minimum_depth, 0, "Expected minimum depth of 0");
201+
nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), &accept_channel);
202+
203+
// nodes[0] --- funding_created --> nodes[1]
204+
let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42);
205+
nodes[0].node.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), tx.clone()).unwrap();
206+
check_added_monitors(&nodes[0], 0);
207+
208+
let mut funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
209+
210+
// Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should
211+
// *not* broadcast a `funding_signed`...
212+
nodes[1].set_channel_signer_available(&nodes[0].node.get_our_node_id(), &temporary_channel_id, false);
213+
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
214+
check_added_monitors(&nodes[1], 1);
215+
216+
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
217+
218+
// Now re-enable the signer and simulate a retry. The temporary_channel_id won't work anymore so
219+
// we have to dig out the real channel ID.
220+
let chan_id = {
221+
let channels = nodes[0].node.list_channels();
222+
assert_eq!(channels.len(), 1, "expected one channel, not {}", channels.len());
223+
channels[0].channel_id
224+
};
225+
226+
// At this point, we basically expect the channel to open like a normal zero-conf channel.
227+
nodes[1].set_channel_signer_available(&nodes[0].node.get_our_node_id(), &chan_id, true);
228+
nodes[1].node.signer_unblocked(Some((nodes[0].node.get_our_node_id(), chan_id)));
229+
230+
let (funding_signed, channel_ready_1) = {
231+
let events = nodes[1].node.get_and_clear_pending_msg_events();
232+
assert_eq!(events.len(), 2);
233+
let funding_signed = match &events[0] {
234+
MessageSendEvent::SendFundingSigned { msg, .. } => msg.clone(),
235+
ev => panic!("Expected SendFundingSigned, not {:?}", ev)
236+
};
237+
let channel_ready = match &events[1] {
238+
MessageSendEvent::SendChannelReady { msg, .. } => msg.clone(),
239+
ev => panic!("Expected SendChannelReady, not {:?}", ev)
240+
};
241+
(funding_signed, channel_ready)
242+
};
243+
244+
nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed);
245+
expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id());
246+
expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
247+
check_added_monitors(&nodes[0], 1);
248+
249+
let channel_ready_0 = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, nodes[1].node.get_our_node_id());
250+
251+
nodes[0].node.handle_channel_ready(&nodes[1].node.get_our_node_id(), &channel_ready_1);
252+
expect_channel_ready_event(&nodes[0], &nodes[1].node.get_our_node_id());
253+
254+
nodes[1].node.handle_channel_ready(&nodes[0].node.get_our_node_id(), &channel_ready_0);
255+
expect_channel_ready_event(&nodes[1], &nodes[0].node.get_our_node_id());
256+
257+
let channel_update_0 = get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id());
258+
let channel_update_1 = get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[0].node.get_our_node_id());
259+
260+
nodes[0].node.handle_channel_update(&nodes[1].node.get_our_node_id(), &channel_update_1);
261+
nodes[1].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &channel_update_0);
262+
263+
assert_eq!(nodes[0].node.list_usable_channels().len(), 1);
264+
assert_eq!(nodes[1].node.list_usable_channels().len(), 1);
265+
}
266+
267+
#[test]
268+
fn test_async_commitment_signature_for_peer_disconnect() {
269+
let chanmon_cfgs = create_chanmon_cfgs(2);
270+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
271+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
272+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
273+
let (_, _, chan_id, _) = create_announced_chan_between_nodes(&nodes, 0, 1);
274+
275+
// Send a payment.
276+
let src = &nodes[0];
277+
let dst = &nodes[1];
278+
let (route, our_payment_hash, _our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(src, dst, 8000000);
279+
src.node.send_payment_with_route(&route, our_payment_hash,
280+
RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap();
281+
check_added_monitors!(src, 1);
282+
283+
// Pass the payment along the route.
284+
let payment_event = {
285+
let mut events = src.node.get_and_clear_pending_msg_events();
286+
assert_eq!(events.len(), 1);
287+
SendEvent::from_event(events.remove(0))
288+
};
289+
assert_eq!(payment_event.node_id, dst.node.get_our_node_id());
290+
assert_eq!(payment_event.msgs.len(), 1);
291+
292+
dst.node.handle_update_add_htlc(&src.node.get_our_node_id(), &payment_event.msgs[0]);
293+
294+
// Mark dst's signer as unavailable and handle src's commitment_signed: while dst won't yet have a
295+
// `commitment_signed` of its own to offer, it should publish a `revoke_and_ack`.
296+
dst.set_channel_signer_available(&src.node.get_our_node_id(), &chan_id, false);
297+
dst.node.handle_commitment_signed(&src.node.get_our_node_id(), &payment_event.commitment_msg);
298+
check_added_monitors(dst, 1);
299+
300+
get_event_msg!(dst, MessageSendEvent::SendRevokeAndACK, src.node.get_our_node_id());
301+
302+
// Now disconnect and reconnect the peers.
303+
src.node.peer_disconnected(&dst.node.get_our_node_id());
304+
dst.node.peer_disconnected(&src.node.get_our_node_id());
305+
let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]);
306+
reconnect_args.send_channel_ready = (false, false);
307+
reconnect_args.pending_raa = (true, false);
308+
reconnect_nodes(reconnect_args);
309+
310+
// Mark dst's signer as available and retry: we now expect to see dst's `commitment_signed`.
311+
dst.set_channel_signer_available(&src.node.get_our_node_id(), &chan_id, true);
312+
dst.node.signer_unblocked(Some((src.node.get_our_node_id(), chan_id)));
313+
314+
{
315+
let events = dst.node.get_and_clear_pending_msg_events();
316+
assert_eq!(events.len(), 1, "expected one message, got {}", events.len());
317+
if let MessageSendEvent::UpdateHTLCs { ref node_id, .. } = events[0] {
318+
assert_eq!(node_id, &src.node.get_our_node_id());
319+
} else {
320+
panic!("expected UpdateHTLCs message, not {:?}", events[0]);
321+
};
322+
}
323+
}

lightning/src/ln/channel.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,12 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
10771077
self.outbound_scid_alias
10781078
}
10791079

1080+
/// Returns the holder signer for this channel.
1081+
#[cfg(test)]
1082+
pub fn get_signer(&self) -> &ChannelSignerType<<SP::Target as SignerProvider>::Signer> {
1083+
return &self.holder_signer
1084+
}
1085+
10801086
/// Only allowed immediately after deserialization if get_outbound_scid_alias returns 0,
10811087
/// indicating we were written by LDK prior to 0.0.106 which did not set outbound SCID aliases
10821088
/// or prior to any channel actions during `Channel` initialization.
@@ -2165,7 +2171,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
21652171
}
21662172
}
21672173
}
2168-
21692174
}
21702175

21712176
// Internal utility functions for channels

0 commit comments

Comments
 (0)