10
10
//! Tests for asynchronous signing. These tests verify that the channel state machine behaves
11
11
//! properly with a signer implementation that asynchronously derives signatures.
12
12
13
+ use bitcoin:: secp256k1:: PublicKey ;
13
14
use bitcoin:: { Transaction , TxOut , TxIn , Amount } ;
14
15
use bitcoin:: blockdata:: locktime:: absolute:: LockTime ;
15
16
use bitcoin:: transaction:: Version ;
16
17
17
18
use crate :: chain:: channelmonitor:: LATENCY_GRACE_PERIOD_BLOCKS ;
18
19
use crate :: events:: bump_transaction:: WalletSource ;
19
20
use crate :: events:: { Event , MessageSendEvent , MessageSendEventsProvider , ClosureReason } ;
21
+ use crate :: ln:: ChannelId ;
20
22
use crate :: ln:: functional_test_utils:: * ;
21
23
use crate :: ln:: msgs:: ChannelMessageHandler ;
22
24
use crate :: ln:: channelmanager:: { PaymentId , RecipientOnionFields } ;
25
+ use crate :: util:: test_channel_signer:: ops;
26
+
27
+ /// Helper to run operations with a simulated asynchronous signer.
28
+ ///
29
+ /// Disables the signer for the specified channel and then runs `do_fn`, then re-enables the signer
30
+ /// and calls `signer_unblocked`.
31
+ #[ cfg( test) ]
32
+ pub fn with_async_signer < DoFn , T > ( node : & Node , peer_id : & PublicKey , channel_id : & ChannelId , masks : Vec < u32 > , do_fn : DoFn ) -> T
33
+ where DoFn : Fn ( ) -> T
34
+ {
35
+ let mask = masks. iter ( ) . fold ( 0 , |acc, m| ( acc | m) ) ;
36
+ eprintln ! ( "disabling {}" , ops:: string_from( mask) ) ;
37
+ node. set_channel_signer_ops_available ( peer_id, channel_id, mask, false ) ;
38
+ let res = do_fn ( ) ;
39
+
40
+ // Recompute the channel ID just in case the original ID was temporary.
41
+ let new_channel_id = {
42
+ let channels = node. node . list_channels ( ) ;
43
+ assert_eq ! ( channels. len( ) , 1 , "expected one channel, not {}" , channels. len( ) ) ;
44
+ channels[ 0 ] . channel_id
45
+ } ;
46
+
47
+ for mask in masks {
48
+ eprintln ! ( "enabling {} and calling signer_unblocked" , ops:: string_from( mask) ) ;
49
+ node. set_channel_signer_ops_available ( peer_id, & new_channel_id, mask, true ) ;
50
+ node. node . signer_unblocked ( Some ( ( * peer_id, new_channel_id) ) ) ;
51
+ }
52
+ res
53
+ }
23
54
24
55
#[ test]
25
56
fn test_async_commitment_signature_for_funding_created ( ) {
57
+ do_test_async_funding_created ( vec ! [ ops:: SIGN_COUNTERPARTY_COMMITMENT ] ) ;
58
+ }
59
+
60
+ fn do_test_async_funding_created ( masks : Vec < u32 > ) {
26
61
// Simulate acquiring the signature for `funding_created` asynchronously.
27
62
let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
28
63
let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
@@ -43,23 +78,15 @@ fn test_async_commitment_signature_for_funding_created() {
43
78
// But! Let's make node[0]'s signer be unavailable: we should *not* broadcast a funding_created
44
79
// message...
45
80
let ( temporary_channel_id, tx, _) = create_funding_transaction ( & nodes[ 0 ] , & nodes[ 1 ] . node . get_our_node_id ( ) , 100000 , 42 ) ;
46
- nodes[ 0 ] . set_channel_signer_available ( & nodes[ 1 ] . node . get_our_node_id ( ) , & temporary_channel_id, false ) ;
47
- nodes[ 0 ] . node . funding_transaction_generated ( & temporary_channel_id, & nodes[ 1 ] . node . get_our_node_id ( ) , tx. clone ( ) ) . unwrap ( ) ;
48
- check_added_monitors ( & nodes[ 0 ] , 0 ) ;
49
-
50
- assert ! ( nodes[ 0 ] . node. get_and_clear_pending_msg_events( ) . is_empty( ) ) ;
51
-
52
- // Now re-enable the signer and simulate a retry. The temporary_channel_id won't work anymore so
53
- // we have to dig out the real channel ID.
54
- let chan_id = {
55
- let channels = nodes[ 0 ] . node . list_channels ( ) ;
56
- assert_eq ! ( channels. len( ) , 1 , "expected one channel, not {}" , channels. len( ) ) ;
57
- channels[ 0 ] . channel_id
58
- } ;
59
-
60
- nodes[ 0 ] . set_channel_signer_available ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_id, true ) ;
61
- nodes[ 0 ] . node . signer_unblocked ( Some ( ( nodes[ 1 ] . node . get_our_node_id ( ) , chan_id) ) ) ;
62
-
81
+ with_async_signer ( & nodes[ 0 ] , & nodes[ 1 ] . node . get_our_node_id ( ) , & temporary_channel_id, masks, || {
82
+ nodes[ 0 ] . node . funding_transaction_generated ( & temporary_channel_id, & nodes[ 1 ] . node . get_our_node_id ( ) , tx. clone ( ) ) . unwrap ( ) ;
83
+ check_added_monitors ( & nodes[ 0 ] , 0 ) ;
84
+ let events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
85
+ assert ! ( events. is_empty( ) , "expected no message, got {:?}" , events) ;
86
+ } ) ;
87
+
88
+ //// Now that we've re-enabled the signer, simulate a retry. The temporary_channel_id won't work anymore so
89
+ //// we have to dig out the real channel ID.
63
90
let mut funding_created_msg = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendFundingCreated , nodes[ 1 ] . node. get_our_node_id( ) ) ;
64
91
nodes[ 1 ] . node . handle_funding_created ( & nodes[ 0 ] . node . get_our_node_id ( ) , & funding_created_msg) ;
65
92
check_added_monitors ( & nodes[ 1 ] , 1 ) ;
@@ -74,6 +101,10 @@ fn test_async_commitment_signature_for_funding_created() {
74
101
75
102
#[ test]
76
103
fn test_async_commitment_signature_for_funding_signed ( ) {
104
+ do_test_async_funding_signed ( vec ! [ ops:: SIGN_COUNTERPARTY_COMMITMENT ] ) ;
105
+ }
106
+
107
+ fn do_test_async_funding_signed ( masks : Vec < u32 > ) {
77
108
// Simulate acquiring the signature for `funding_signed` asynchronously.
78
109
let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
79
110
let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
@@ -98,22 +129,14 @@ fn test_async_commitment_signature_for_funding_signed() {
98
129
99
130
// Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should
100
131
// *not* broadcast a `funding_signed`...
101
- nodes[ 1 ] . set_channel_signer_available ( & nodes[ 0 ] . node . get_our_node_id ( ) , & temporary_channel_id, false ) ;
102
- nodes[ 1 ] . node . handle_funding_created ( & nodes[ 0 ] . node . get_our_node_id ( ) , & funding_created_msg) ;
103
- check_added_monitors ( & nodes[ 1 ] , 1 ) ;
104
-
105
- assert ! ( nodes [ 1 ] . node . get_and_clear_pending_msg_events ( ) . is_empty ( ) ) ;
132
+ with_async_signer ( & nodes[ 1 ] , & nodes[ 0 ] . node . get_our_node_id ( ) , & temporary_channel_id, masks , || {
133
+ nodes[ 1 ] . node . handle_funding_created ( & nodes[ 0 ] . node . get_our_node_id ( ) , & funding_created_msg) ;
134
+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
135
+ assert ! ( nodes [ 1 ] . node . get_and_clear_pending_msg_events ( ) . is_empty ( ) ) ;
136
+ } ) ;
106
137
107
- // Now re-enable the signer and simulate a retry. The temporary_channel_id won't work anymore so
138
+ // Now that we've re-enabled the signer, simulate a retry. The temporary_channel_id won't work anymore so
108
139
// we have to dig out the real channel ID.
109
- let chan_id = {
110
- let channels = nodes[ 0 ] . node . list_channels ( ) ;
111
- assert_eq ! ( channels. len( ) , 1 , "expected one channel, not {}" , channels. len( ) ) ;
112
- channels[ 0 ] . channel_id
113
- } ;
114
- nodes[ 1 ] . set_channel_signer_available ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_id, true ) ;
115
- nodes[ 1 ] . node . signer_unblocked ( Some ( ( nodes[ 0 ] . node . get_our_node_id ( ) , chan_id) ) ) ;
116
-
117
140
expect_channel_pending_event ( & nodes[ 1 ] , & nodes[ 0 ] . node . get_our_node_id ( ) ) ;
118
141
119
142
// nodes[0] <-- funding_signed --- nodes[1]
@@ -125,6 +148,10 @@ fn test_async_commitment_signature_for_funding_signed() {
125
148
126
149
#[ test]
127
150
fn test_async_commitment_signature_for_commitment_signed ( ) {
151
+ do_test_async_commitment_signed ( vec ! [ ops:: SIGN_COUNTERPARTY_COMMITMENT ] ) ;
152
+ }
153
+
154
+ fn do_test_async_commitment_signed ( masks : Vec < u32 > ) {
128
155
let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
129
156
let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
130
157
let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
@@ -150,18 +177,15 @@ fn test_async_commitment_signature_for_commitment_signed() {
150
177
151
178
dst. node . handle_update_add_htlc ( & src. node . get_our_node_id ( ) , & payment_event. msgs [ 0 ] ) ;
152
179
153
- // Mark dst's signer as unavailable and handle src's commitment_signed: while dst won't yet have a
154
- // `commitment_signed` of its own to offer, it should publish a `revoke_and_ack`.
155
- dst. set_channel_signer_available ( & src. node . get_our_node_id ( ) , & chan_id, false ) ;
156
- dst. node . handle_commitment_signed ( & src. node . get_our_node_id ( ) , & payment_event. commitment_msg ) ;
157
- check_added_monitors ( dst, 1 ) ;
158
-
159
- get_event_msg ! ( dst, MessageSendEvent :: SendRevokeAndACK , src. node. get_our_node_id( ) ) ;
160
-
161
- // Mark dst's signer as available and retry: we now expect to see dst's `commitment_signed`.
162
- dst. set_channel_signer_available ( & src. node . get_our_node_id ( ) , & chan_id, true ) ;
163
- dst. node . signer_unblocked ( Some ( ( src. node . get_our_node_id ( ) , chan_id) ) ) ;
180
+ // Mark dst's signer as unavailable and handle src's commitment_signed. If dst's signer is
181
+ // offline, it oughtn't yet respond with any updates.
182
+ with_async_signer ( dst, & src. node . get_our_node_id ( ) , & chan_id, masks, & || {
183
+ dst. node . handle_commitment_signed ( & src. node . get_our_node_id ( ) , & payment_event. commitment_msg ) ;
184
+ check_added_monitors ( dst, 1 ) ;
185
+ get_event_msg ! ( dst, MessageSendEvent :: SendRevokeAndACK , src. node. get_our_node_id( ) ) ;
186
+ } ) ;
164
187
188
+ // Now that we marked dst's signer as available, retry: we now expect to see dst's `commitment_signed`.
165
189
let events = dst. node . get_and_clear_pending_msg_events ( ) ;
166
190
assert_eq ! ( events. len( ) , 1 , "expected one message, got {}" , events. len( ) ) ;
167
191
if let MessageSendEvent :: UpdateHTLCs { ref node_id, .. } = events[ 0 ] {
@@ -173,6 +197,10 @@ fn test_async_commitment_signature_for_commitment_signed() {
173
197
174
198
#[ test]
175
199
fn test_async_commitment_signature_for_funding_signed_0conf ( ) {
200
+ do_test_async_funding_signed_0conf ( vec ! [ ops:: SIGN_COUNTERPARTY_COMMITMENT ] ) ;
201
+ }
202
+
203
+ fn do_test_async_funding_signed_0conf ( masks : Vec < u32 > ) {
176
204
// Simulate acquiring the signature for `funding_signed` asynchronously for a zero-conf channel.
177
205
let mut manually_accept_config = test_default_channel_config ( ) ;
178
206
manually_accept_config. manually_accept_inbound_channels = true ;
@@ -215,24 +243,13 @@ fn test_async_commitment_signature_for_funding_signed_0conf() {
215
243
216
244
// Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should
217
245
// *not* broadcast a `funding_signed`...
218
- nodes[ 1 ] . set_channel_signer_available ( & nodes[ 0 ] . node . get_our_node_id ( ) , & temporary_channel_id, false ) ;
219
- nodes[ 1 ] . node . handle_funding_created ( & nodes[ 0 ] . node . get_our_node_id ( ) , & funding_created_msg) ;
220
- check_added_monitors ( & nodes[ 1 ] , 1 ) ;
221
-
222
- assert ! ( nodes[ 1 ] . node. get_and_clear_pending_msg_events( ) . is_empty( ) ) ;
223
-
224
- // Now re-enable the signer and simulate a retry. The temporary_channel_id won't work anymore so
225
- // we have to dig out the real channel ID.
226
- let chan_id = {
227
- let channels = nodes[ 0 ] . node . list_channels ( ) ;
228
- assert_eq ! ( channels. len( ) , 1 , "expected one channel, not {}" , channels. len( ) ) ;
229
- channels[ 0 ] . channel_id
230
- } ;
246
+ with_async_signer ( & nodes[ 1 ] , & nodes[ 0 ] . node . get_our_node_id ( ) , & temporary_channel_id, masks, || {
247
+ nodes[ 1 ] . node . handle_funding_created ( & nodes[ 0 ] . node . get_our_node_id ( ) , & funding_created_msg) ;
248
+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
249
+ assert ! ( nodes[ 1 ] . node. get_and_clear_pending_msg_events( ) . is_empty( ) ) ;
250
+ } ) ;
231
251
232
252
// At this point, we basically expect the channel to open like a normal zero-conf channel.
233
- nodes[ 1 ] . set_channel_signer_available ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_id, true ) ;
234
- nodes[ 1 ] . node . signer_unblocked ( Some ( ( nodes[ 0 ] . node . get_our_node_id ( ) , chan_id) ) ) ;
235
-
236
253
let ( funding_signed, channel_ready_1) = {
237
254
let events = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
238
255
assert_eq ! ( events. len( ) , 2 ) ;
@@ -299,24 +316,22 @@ fn test_async_commitment_signature_for_peer_disconnect() {
299
316
300
317
// Mark dst's signer as unavailable and handle src's commitment_signed: while dst won't yet have a
301
318
// `commitment_signed` of its own to offer, it should publish a `revoke_and_ack`.
302
- dst. set_channel_signer_available ( & src. node . get_our_node_id ( ) , & chan_id, false ) ;
303
- dst. node . handle_commitment_signed ( & src. node . get_our_node_id ( ) , & payment_event. commitment_msg ) ;
304
- check_added_monitors ( dst, 1 ) ;
305
-
306
- get_event_msg ! ( dst, MessageSendEvent :: SendRevokeAndACK , src. node. get_our_node_id( ) ) ;
307
-
308
- // Now disconnect and reconnect the peers.
309
- src. node . peer_disconnected ( & dst. node . get_our_node_id ( ) ) ;
310
- dst. node . peer_disconnected ( & src. node . get_our_node_id ( ) ) ;
311
- let mut reconnect_args = ReconnectArgs :: new ( & nodes[ 0 ] , & nodes[ 1 ] ) ;
312
- reconnect_args. send_channel_ready = ( false , false ) ;
313
- reconnect_args. pending_raa = ( true , false ) ;
314
- reconnect_nodes ( reconnect_args) ;
315
-
316
- // Mark dst's signer as available and retry: we now expect to see dst's `commitment_signed`.
317
- dst. set_channel_signer_available ( & src. node . get_our_node_id ( ) , & chan_id, true ) ;
318
- dst. node . signer_unblocked ( Some ( ( src. node . get_our_node_id ( ) , chan_id) ) ) ;
319
-
319
+ with_async_signer ( dst, & src. node . get_our_node_id ( ) , & chan_id, vec ! [ ops:: SIGN_COUNTERPARTY_COMMITMENT ] , & || {
320
+ dst. node . handle_commitment_signed ( & src. node . get_our_node_id ( ) , & payment_event. commitment_msg ) ;
321
+ check_added_monitors ( dst, 1 ) ;
322
+
323
+ get_event_msg ! ( dst, MessageSendEvent :: SendRevokeAndACK , src. node. get_our_node_id( ) ) ;
324
+
325
+ // Now disconnect and reconnect the peers.
326
+ src. node . peer_disconnected ( & dst. node . get_our_node_id ( ) ) ;
327
+ dst. node . peer_disconnected ( & src. node . get_our_node_id ( ) ) ;
328
+ let mut reconnect_args = ReconnectArgs :: new ( & nodes[ 0 ] , & nodes[ 1 ] ) ;
329
+ reconnect_args. send_channel_ready = ( false , false ) ;
330
+ reconnect_args. pending_raa = ( true , false ) ;
331
+ reconnect_nodes ( reconnect_args) ;
332
+ } ) ;
333
+
334
+ // Now that dst's signer is available, retry: we now expect to see dst's `commitment_signed`.
320
335
{
321
336
let events = dst. node . get_and_clear_pending_msg_events ( ) ;
322
337
assert_eq ! ( events. len( ) , 1 , "expected one message, got {}" , events. len( ) ) ;
0 commit comments