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 std :: collections :: HashSet ;
14
- use bitcoin:: key :: Secp256k1 ;
13
+ use crate :: prelude :: * ;
14
+ use bitcoin:: secp256k1 :: Secp256k1 ;
15
15
use bitcoin:: { Transaction , TxOut , TxIn , Amount } ;
16
16
use bitcoin:: locktime:: absolute:: LockTime ;
17
17
use bitcoin:: transaction:: Version ;
@@ -31,7 +31,78 @@ use crate::util::test_channel_signer::SignerOp;
31
31
use crate :: util:: logger:: Logger ;
32
32
33
33
#[ test]
34
- fn test_async_commitment_signature_for_funding_created ( ) {
34
+ fn test_open_channel ( ) {
35
+ do_test_open_channel ( false ) ;
36
+ do_test_open_channel ( true ) ;
37
+ }
38
+
39
+ fn do_test_open_channel ( zero_conf : bool ) {
40
+ // Simulate acquiring the commitment point for `open_channel` and `accept_channel` asynchronously.
41
+ let mut manually_accept_config = test_default_channel_config ( ) ;
42
+ manually_accept_config. manually_accept_inbound_channels = zero_conf;
43
+
44
+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
45
+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
46
+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , Some ( manually_accept_config) ] ) ;
47
+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
48
+
49
+ // Open an outbound channel simulating an async signer.
50
+ let channel_value_satoshis = 100000 ;
51
+ let user_channel_id = 42 ;
52
+ nodes[ 0 ] . disable_next_channel_signer_op ( SignerOp :: GetPerCommitmentPoint ) ;
53
+ let channel_id_0 = nodes[ 0 ] . node . create_channel ( nodes[ 1 ] . node . get_our_node_id ( ) , channel_value_satoshis, 10001 , user_channel_id, None , None ) . unwrap ( ) ;
54
+
55
+ {
56
+ let msgs = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
57
+ assert ! ( msgs. is_empty( ) , "Expected no message events; got {:?}" , msgs) ;
58
+ }
59
+
60
+ nodes[ 0 ] . enable_channel_signer_op ( & nodes[ 1 ] . node . get_our_node_id ( ) , & channel_id_0, SignerOp :: GetPerCommitmentPoint ) ;
61
+ nodes[ 0 ] . node . signer_unblocked ( None ) ;
62
+
63
+ // nodes[0] --- open_channel --> nodes[1]
64
+ let mut open_chan_msg = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendOpenChannel , nodes[ 1 ] . node. get_our_node_id( ) ) ;
65
+
66
+ // Handle an inbound channel simulating an async signer.
67
+ nodes[ 1 ] . disable_next_channel_signer_op ( SignerOp :: GetPerCommitmentPoint ) ;
68
+ nodes[ 1 ] . node . handle_open_channel ( nodes[ 0 ] . node . get_our_node_id ( ) , & open_chan_msg) ;
69
+
70
+ if zero_conf {
71
+ let events = nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
72
+ assert_eq ! ( events. len( ) , 1 , "Expected one event, got {}" , events. len( ) ) ;
73
+ match & events[ 0 ] {
74
+ Event :: OpenChannelRequest { temporary_channel_id, .. } => {
75
+ nodes[ 1 ] . node . accept_inbound_channel_from_trusted_peer_0conf (
76
+ temporary_channel_id, & nodes[ 0 ] . node . get_our_node_id ( ) , 0 )
77
+ . expect ( "Unable to accept inbound zero-conf channel" ) ;
78
+ } ,
79
+ ev => panic ! ( "Expected OpenChannelRequest, not {:?}" , ev)
80
+ }
81
+ } else {
82
+ let msgs = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
83
+ assert ! ( msgs. is_empty( ) , "Expected no message events; got {:?}" , msgs) ;
84
+ }
85
+
86
+ let channel_id_1 = {
87
+ let channels = nodes[ 1 ] . node . list_channels ( ) ;
88
+ assert_eq ! ( channels. len( ) , 1 , "expected one channel, not {}" , channels. len( ) ) ;
89
+ channels[ 0 ] . channel_id
90
+ } ;
91
+
92
+ nodes[ 1 ] . enable_channel_signer_op ( & nodes[ 0 ] . node . get_our_node_id ( ) , & channel_id_1, SignerOp :: GetPerCommitmentPoint ) ;
93
+ nodes[ 1 ] . node . signer_unblocked ( None ) ;
94
+
95
+ // nodes[0] <-- accept_channel --- nodes[1]
96
+ get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendAcceptChannel , nodes[ 0 ] . node. get_our_node_id( ) ) ;
97
+ }
98
+
99
+ #[ test]
100
+ fn test_funding_created ( ) {
101
+ do_test_funding_created ( vec ! [ SignerOp :: SignCounterpartyCommitment , SignerOp :: GetPerCommitmentPoint ] ) ;
102
+ do_test_funding_created ( vec ! [ SignerOp :: GetPerCommitmentPoint , SignerOp :: SignCounterpartyCommitment ] ) ;
103
+ }
104
+
105
+ fn do_test_funding_created ( signer_ops : Vec < SignerOp > ) {
35
106
// Simulate acquiring the signature for `funding_created` asynchronously.
36
107
let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
37
108
let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
@@ -52,7 +123,9 @@ fn test_async_commitment_signature_for_funding_created() {
52
123
// But! Let's make node[0]'s signer be unavailable: we should *not* broadcast a funding_created
53
124
// message...
54
125
let ( temporary_channel_id, tx, _) = create_funding_transaction ( & nodes[ 0 ] , & nodes[ 1 ] . node . get_our_node_id ( ) , 100000 , 42 ) ;
55
- nodes[ 0 ] . disable_channel_signer_op ( & nodes[ 1 ] . node . get_our_node_id ( ) , & temporary_channel_id, SignerOp :: SignCounterpartyCommitment ) ;
126
+ for op in signer_ops. iter ( ) {
127
+ nodes[ 0 ] . disable_channel_signer_op ( & nodes[ 1 ] . node . get_our_node_id ( ) , & temporary_channel_id, * op) ;
128
+ }
56
129
nodes[ 0 ] . node . funding_transaction_generated ( temporary_channel_id, nodes[ 1 ] . node . get_our_node_id ( ) , tx. clone ( ) ) . unwrap ( ) ;
57
130
check_added_monitors ( & nodes[ 0 ] , 0 ) ;
58
131
@@ -66,8 +139,10 @@ fn test_async_commitment_signature_for_funding_created() {
66
139
channels[ 0 ] . channel_id
67
140
} ;
68
141
69
- nodes[ 0 ] . enable_channel_signer_op ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_id, SignerOp :: SignCounterpartyCommitment ) ;
70
- nodes[ 0 ] . node . signer_unblocked ( Some ( ( nodes[ 1 ] . node . get_our_node_id ( ) , chan_id) ) ) ;
142
+ for op in signer_ops. iter ( ) {
143
+ nodes[ 0 ] . enable_channel_signer_op ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_id, * op) ;
144
+ nodes[ 0 ] . node . signer_unblocked ( Some ( ( nodes[ 1 ] . node . get_our_node_id ( ) , chan_id) ) ) ;
145
+ }
71
146
72
147
let mut funding_created_msg = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendFundingCreated , nodes[ 1 ] . node. get_our_node_id( ) ) ;
73
148
nodes[ 1 ] . node . handle_funding_created ( nodes[ 0 ] . node . get_our_node_id ( ) , & funding_created_msg) ;
@@ -82,7 +157,12 @@ fn test_async_commitment_signature_for_funding_created() {
82
157
}
83
158
84
159
#[ test]
85
- fn test_async_commitment_signature_for_funding_signed ( ) {
160
+ fn test_funding_signed ( ) {
161
+ do_test_funding_signed ( vec ! [ SignerOp :: SignCounterpartyCommitment , SignerOp :: GetPerCommitmentPoint ] ) ;
162
+ do_test_funding_signed ( vec ! [ SignerOp :: GetPerCommitmentPoint , SignerOp :: SignCounterpartyCommitment ] ) ;
163
+ }
164
+
165
+ fn do_test_funding_signed ( signer_ops : Vec < SignerOp > ) {
86
166
// Simulate acquiring the signature for `funding_signed` asynchronously.
87
167
let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
88
168
let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
@@ -107,7 +187,9 @@ fn test_async_commitment_signature_for_funding_signed() {
107
187
108
188
// Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should
109
189
// *not* broadcast a `funding_signed`...
110
- nodes[ 1 ] . disable_channel_signer_op ( & nodes[ 0 ] . node . get_our_node_id ( ) , & temporary_channel_id, SignerOp :: SignCounterpartyCommitment ) ;
190
+ for op in signer_ops. iter ( ) {
191
+ nodes[ 1 ] . disable_channel_signer_op ( & nodes[ 0 ] . node . get_our_node_id ( ) , & temporary_channel_id, * op) ;
192
+ }
111
193
nodes[ 1 ] . node . handle_funding_created ( nodes[ 0 ] . node . get_our_node_id ( ) , & funding_created_msg) ;
112
194
check_added_monitors ( & nodes[ 1 ] , 1 ) ;
113
195
@@ -120,16 +202,21 @@ fn test_async_commitment_signature_for_funding_signed() {
120
202
assert_eq ! ( channels. len( ) , 1 , "expected one channel, not {}" , channels. len( ) ) ;
121
203
channels[ 0 ] . channel_id
122
204
} ;
123
- nodes[ 1 ] . enable_channel_signer_op ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_id, SignerOp :: SignCounterpartyCommitment ) ;
124
- nodes[ 1 ] . node . signer_unblocked ( Some ( ( nodes[ 0 ] . node . get_our_node_id ( ) , chan_id) ) ) ;
125
-
126
- expect_channel_pending_event ( & nodes[ 1 ] , & nodes[ 0 ] . node . get_our_node_id ( ) ) ;
127
-
128
- // nodes[0] <-- funding_signed --- nodes[1]
129
- let funding_signed_msg = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendFundingSigned , nodes[ 0 ] . node. get_our_node_id( ) ) ;
130
- nodes[ 0 ] . node . handle_funding_signed ( nodes[ 1 ] . node . get_our_node_id ( ) , & funding_signed_msg) ;
131
- check_added_monitors ( & nodes[ 0 ] , 1 ) ;
132
- expect_channel_pending_event ( & nodes[ 0 ] , & nodes[ 1 ] . node . get_our_node_id ( ) ) ;
205
+ for op in signer_ops. iter ( ) {
206
+ nodes[ 1 ] . enable_channel_signer_op ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_id, * op) ;
207
+ nodes[ 1 ] . node . signer_unblocked ( Some ( ( nodes[ 0 ] . node . get_our_node_id ( ) , chan_id) ) ) ;
208
+ if * op == SignerOp :: SignCounterpartyCommitment {
209
+ expect_channel_pending_event ( & nodes[ 1 ] , & nodes[ 0 ] . node . get_our_node_id ( ) ) ;
210
+
211
+ // nodes[0] <-- funding_signed --- nodes[1]
212
+ let funding_signed_msg = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendFundingSigned , nodes[ 0 ] . node. get_our_node_id( ) ) ;
213
+ nodes[ 0 ] . node . handle_funding_signed ( nodes[ 1 ] . node . get_our_node_id ( ) , & funding_signed_msg) ;
214
+ check_added_monitors ( & nodes[ 0 ] , 1 ) ;
215
+ expect_channel_pending_event ( & nodes[ 0 ] , & nodes[ 1 ] . node . get_our_node_id ( ) ) ;
216
+ } else {
217
+ assert ! ( nodes[ 1 ] . node. get_and_clear_pending_msg_events( ) . is_empty( ) ) ;
218
+ }
219
+ }
133
220
}
134
221
135
222
#[ test]
@@ -178,7 +265,7 @@ fn do_test_async_commitment_signature_for_commitment_signed_revoke_and_ack(enabl
178
265
dst. node . handle_commitment_signed ( src. node . get_our_node_id ( ) , & payment_event. commitment_msg ) ;
179
266
check_added_monitors ( dst, 1 ) ;
180
267
181
- let mut enabled_signer_ops = HashSet :: new ( ) ;
268
+ let mut enabled_signer_ops = new_hash_set ( ) ;
182
269
log_trace ! ( dst. logger, "enable_signer_op_order={:?}" , enable_signer_op_order) ;
183
270
for op in enable_signer_op_order {
184
271
enabled_signer_ops. insert ( op) ;
@@ -204,7 +291,12 @@ fn do_test_async_commitment_signature_for_commitment_signed_revoke_and_ack(enabl
204
291
}
205
292
206
293
#[ test]
207
- fn test_async_commitment_signature_for_funding_signed_0conf ( ) {
294
+ fn test_funding_signed_0conf ( ) {
295
+ do_test_funding_signed_0conf ( vec ! [ SignerOp :: GetPerCommitmentPoint , SignerOp :: SignCounterpartyCommitment ] ) ;
296
+ do_test_funding_signed_0conf ( vec ! [ SignerOp :: SignCounterpartyCommitment , SignerOp :: GetPerCommitmentPoint ] ) ;
297
+ }
298
+
299
+ fn do_test_funding_signed_0conf ( signer_ops : Vec < SignerOp > ) {
208
300
// Simulate acquiring the signature for `funding_signed` asynchronously for a zero-conf channel.
209
301
let mut manually_accept_config = test_default_channel_config ( ) ;
210
302
manually_accept_config. manually_accept_inbound_channels = true ;
@@ -247,7 +339,9 @@ fn test_async_commitment_signature_for_funding_signed_0conf() {
247
339
248
340
// Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should
249
341
// *not* broadcast a `funding_signed`...
250
- nodes[ 1 ] . disable_channel_signer_op ( & nodes[ 0 ] . node . get_our_node_id ( ) , & temporary_channel_id, SignerOp :: SignCounterpartyCommitment ) ;
342
+ for op in signer_ops. iter ( ) {
343
+ nodes[ 1 ] . disable_channel_signer_op ( & nodes[ 0 ] . node . get_our_node_id ( ) , & temporary_channel_id, * op) ;
344
+ }
251
345
nodes[ 1 ] . node . handle_funding_created ( nodes[ 0 ] . node . get_our_node_id ( ) , & funding_created_msg) ;
252
346
check_added_monitors ( & nodes[ 1 ] , 1 ) ;
253
347
@@ -262,8 +356,10 @@ fn test_async_commitment_signature_for_funding_signed_0conf() {
262
356
} ;
263
357
264
358
// At this point, we basically expect the channel to open like a normal zero-conf channel.
265
- nodes[ 1 ] . enable_channel_signer_op ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_id, SignerOp :: SignCounterpartyCommitment ) ;
266
- nodes[ 1 ] . node . signer_unblocked ( Some ( ( nodes[ 0 ] . node . get_our_node_id ( ) , chan_id) ) ) ;
359
+ for op in signer_ops. iter ( ) {
360
+ nodes[ 1 ] . enable_channel_signer_op ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_id, * op) ;
361
+ nodes[ 1 ] . node . signer_unblocked ( Some ( ( nodes[ 0 ] . node . get_our_node_id ( ) , chan_id) ) ) ;
362
+ }
267
363
268
364
let ( funding_signed, channel_ready_1) = {
269
365
let events = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
0 commit comments