1010//! Tests for asynchronous signing. These tests verify that the channel state machine behaves
1111//! properly with a signer implementation that asynchronously derives signatures.
1212
13- use std :: collections :: HashSet ;
14- use bitcoin:: key :: Secp256k1 ;
13+ use crate :: prelude :: * ;
14+ use bitcoin:: secp256k1 :: Secp256k1 ;
1515use bitcoin:: { Transaction , TxOut , TxIn , Amount } ;
1616use bitcoin:: locktime:: absolute:: LockTime ;
1717use bitcoin:: transaction:: Version ;
@@ -31,7 +31,59 @@ use crate::util::test_channel_signer::SignerOp;
3131use crate :: util:: logger:: Logger ;
3232
3333#[ test]
34- fn test_async_commitment_signature_for_funding_created ( ) {
34+ fn test_open_channel ( ) {
35+ // Simulate acquiring the commitment point for `open_channel` and `accept_channel` asynchronously.
36+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
37+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
38+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
39+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
40+
41+ // Open an outbound channel simulating an async signer.
42+ let channel_value_satoshis = 100000 ;
43+ let user_channel_id = 42 ;
44+ nodes[ 0 ] . disable_next_channel_signer_op ( SignerOp :: GetPerCommitmentPoint ) ;
45+ 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 ( ) ;
46+
47+ {
48+ let msgs = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
49+ assert ! ( msgs. is_empty( ) , "Expected no message events; got {:?}" , msgs) ;
50+ }
51+
52+ nodes[ 0 ] . enable_channel_signer_op ( & nodes[ 1 ] . node . get_our_node_id ( ) , & channel_id_0, SignerOp :: GetPerCommitmentPoint ) ;
53+ nodes[ 0 ] . node . signer_unblocked ( None ) ;
54+
55+ // nodes[0] --- open_channel --> nodes[1]
56+ let mut open_chan_msg = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendOpenChannel , nodes[ 1 ] . node. get_our_node_id( ) ) ;
57+
58+ // Handle an inbound channel simulating an async signer.
59+ nodes[ 1 ] . disable_next_channel_signer_op ( SignerOp :: GetPerCommitmentPoint ) ;
60+ nodes[ 1 ] . node . handle_open_channel ( nodes[ 0 ] . node . get_our_node_id ( ) , & open_chan_msg) ;
61+
62+ {
63+ let msgs = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
64+ assert ! ( msgs. is_empty( ) , "Expected no message events; got {:?}" , msgs) ;
65+ }
66+
67+ let channel_id_1 = {
68+ let channels = nodes[ 1 ] . node . list_channels ( ) ;
69+ assert_eq ! ( channels. len( ) , 1 , "expected one channel, not {}" , channels. len( ) ) ;
70+ channels[ 0 ] . channel_id
71+ } ;
72+
73+ nodes[ 1 ] . enable_channel_signer_op ( & nodes[ 0 ] . node . get_our_node_id ( ) , & channel_id_1, SignerOp :: GetPerCommitmentPoint ) ;
74+ nodes[ 1 ] . node . signer_unblocked ( None ) ;
75+
76+ // nodes[0] <-- accept_channel --- nodes[1]
77+ get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendAcceptChannel , nodes[ 0 ] . node. get_our_node_id( ) ) ;
78+ }
79+
80+ #[ test]
81+ fn test_funding_created ( ) {
82+ do_test_funding_created ( vec ! [ SignerOp :: SignCounterpartyCommitment , SignerOp :: GetPerCommitmentPoint ] ) ;
83+ do_test_funding_created ( vec ! [ SignerOp :: GetPerCommitmentPoint , SignerOp :: SignCounterpartyCommitment ] ) ;
84+ }
85+
86+ fn do_test_funding_created ( signer_ops : Vec < SignerOp > ) {
3587 // Simulate acquiring the signature for `funding_created` asynchronously.
3688 let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
3789 let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
@@ -52,7 +104,9 @@ fn test_async_commitment_signature_for_funding_created() {
52104 // But! Let's make node[0]'s signer be unavailable: we should *not* broadcast a funding_created
53105 // message...
54106 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 ) ;
107+ for op in signer_ops. iter ( ) {
108+ nodes[ 0 ] . disable_channel_signer_op ( & nodes[ 1 ] . node . get_our_node_id ( ) , & temporary_channel_id, * op) ;
109+ }
56110 nodes[ 0 ] . node . funding_transaction_generated ( temporary_channel_id, nodes[ 1 ] . node . get_our_node_id ( ) , tx. clone ( ) ) . unwrap ( ) ;
57111 check_added_monitors ( & nodes[ 0 ] , 0 ) ;
58112
@@ -66,8 +120,10 @@ fn test_async_commitment_signature_for_funding_created() {
66120 channels[ 0 ] . channel_id
67121 } ;
68122
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) ) ) ;
123+ for op in signer_ops. iter ( ) {
124+ nodes[ 0 ] . enable_channel_signer_op ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_id, * op) ;
125+ nodes[ 0 ] . node . signer_unblocked ( Some ( ( nodes[ 1 ] . node . get_our_node_id ( ) , chan_id) ) ) ;
126+ }
71127
72128 let mut funding_created_msg = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendFundingCreated , nodes[ 1 ] . node. get_our_node_id( ) ) ;
73129 nodes[ 1 ] . node . handle_funding_created ( nodes[ 0 ] . node . get_our_node_id ( ) , & funding_created_msg) ;
@@ -82,7 +138,12 @@ fn test_async_commitment_signature_for_funding_created() {
82138}
83139
84140#[ test]
85- fn test_async_commitment_signature_for_funding_signed ( ) {
141+ fn test_funding_signed ( ) {
142+ do_test_funding_signed ( vec ! [ SignerOp :: SignCounterpartyCommitment , SignerOp :: GetPerCommitmentPoint ] ) ;
143+ do_test_funding_signed ( vec ! [ SignerOp :: GetPerCommitmentPoint , SignerOp :: SignCounterpartyCommitment ] ) ;
144+ }
145+
146+ fn do_test_funding_signed ( signer_ops : Vec < SignerOp > ) {
86147 // Simulate acquiring the signature for `funding_signed` asynchronously.
87148 let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
88149 let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
@@ -107,7 +168,9 @@ fn test_async_commitment_signature_for_funding_signed() {
107168
108169 // Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should
109170 // *not* broadcast a `funding_signed`...
110- nodes[ 1 ] . disable_channel_signer_op ( & nodes[ 0 ] . node . get_our_node_id ( ) , & temporary_channel_id, SignerOp :: SignCounterpartyCommitment ) ;
171+ for op in signer_ops. iter ( ) {
172+ nodes[ 1 ] . disable_channel_signer_op ( & nodes[ 0 ] . node . get_our_node_id ( ) , & temporary_channel_id, * op) ;
173+ }
111174 nodes[ 1 ] . node . handle_funding_created ( nodes[ 0 ] . node . get_our_node_id ( ) , & funding_created_msg) ;
112175 check_added_monitors ( & nodes[ 1 ] , 1 ) ;
113176
@@ -120,8 +183,10 @@ fn test_async_commitment_signature_for_funding_signed() {
120183 assert_eq ! ( channels. len( ) , 1 , "expected one channel, not {}" , channels. len( ) ) ;
121184 channels[ 0 ] . channel_id
122185 } ;
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) ) ) ;
186+ for op in signer_ops. iter ( ) {
187+ nodes[ 1 ] . enable_channel_signer_op ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_id, * op) ;
188+ nodes[ 1 ] . node . signer_unblocked ( Some ( ( nodes[ 0 ] . node . get_our_node_id ( ) , chan_id) ) ) ;
189+ }
125190
126191 expect_channel_pending_event ( & nodes[ 1 ] , & nodes[ 0 ] . node . get_our_node_id ( ) ) ;
127192
@@ -204,7 +269,12 @@ fn do_test_async_commitment_signature_for_commitment_signed_revoke_and_ack(enabl
204269}
205270
206271#[ test]
207- fn test_async_commitment_signature_for_funding_signed_0conf ( ) {
272+ fn test_funding_signed_0conf ( ) {
273+ do_test_funding_signed_0conf ( vec ! [ SignerOp :: GetPerCommitmentPoint , SignerOp :: SignCounterpartyCommitment ] ) ;
274+ do_test_funding_signed_0conf ( vec ! [ SignerOp :: SignCounterpartyCommitment , SignerOp :: GetPerCommitmentPoint ] ) ;
275+ }
276+
277+ fn do_test_funding_signed_0conf ( signer_ops : Vec < SignerOp > ) {
208278 // Simulate acquiring the signature for `funding_signed` asynchronously for a zero-conf channel.
209279 let mut manually_accept_config = test_default_channel_config ( ) ;
210280 manually_accept_config. manually_accept_inbound_channels = true ;
@@ -247,7 +317,9 @@ fn test_async_commitment_signature_for_funding_signed_0conf() {
247317
248318 // Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should
249319 // *not* broadcast a `funding_signed`...
250- nodes[ 1 ] . disable_channel_signer_op ( & nodes[ 0 ] . node . get_our_node_id ( ) , & temporary_channel_id, SignerOp :: SignCounterpartyCommitment ) ;
320+ for op in signer_ops. iter ( ) {
321+ nodes[ 1 ] . disable_channel_signer_op ( & nodes[ 0 ] . node . get_our_node_id ( ) , & temporary_channel_id, * op) ;
322+ }
251323 nodes[ 1 ] . node . handle_funding_created ( nodes[ 0 ] . node . get_our_node_id ( ) , & funding_created_msg) ;
252324 check_added_monitors ( & nodes[ 1 ] , 1 ) ;
253325
@@ -262,8 +334,10 @@ fn test_async_commitment_signature_for_funding_signed_0conf() {
262334 } ;
263335
264336 // 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) ) ) ;
337+ for op in signer_ops. iter ( ) {
338+ nodes[ 1 ] . enable_channel_signer_op ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_id, * op) ;
339+ nodes[ 1 ] . node . signer_unblocked ( Some ( ( nodes[ 0 ] . node . get_our_node_id ( ) , chan_id) ) ) ;
340+ }
267341
268342 let ( funding_signed, channel_ready_1) = {
269343 let events = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
0 commit comments