@@ -6,7 +6,7 @@ use crate::{
6
6
7
7
use revault_net:: {
8
8
message:: {
9
- watchtower:: { Signatures , Sigs , SigsResult } ,
9
+ watchtower:: { CancelFeerate , Signatures , Sigs , SigsResult } ,
10
10
RequestParams , ResponseResult ,
11
11
} ,
12
12
noise:: SecretKey as NoisePrivkey ,
@@ -16,7 +16,7 @@ use revault_tx::{
16
16
transactions:: { transaction_chain, RevaultPresignedTransaction , RevaultTransaction } ,
17
17
} ;
18
18
19
- use std:: { collections :: BTreeMap , io, net:: TcpListener , path, sync} ;
19
+ use std:: { io, net:: TcpListener , path, sync} ;
20
20
21
21
#[ derive( Debug ) ]
22
22
pub enum ListenerError {
@@ -92,7 +92,6 @@ fn process_sigs_message<C: secp256k1::Verification>(
92
92
scripts_config. emergency_address . clone ( ) ,
93
93
secp,
94
94
) ?;
95
- let mut cancel_tx = cancel_batch. into_feerate_20 ( ) ;
96
95
97
96
// If we already have it, just acknowledge it.
98
97
if db_vault ( db_path, & msg. deposit_outpoint ) ?. is_some ( ) {
@@ -103,7 +102,8 @@ fn process_sigs_message<C: secp256k1::Verification>(
103
102
return Ok ( SigsResult { ack : true } ) ;
104
103
}
105
104
106
- // Otherwise, check the sigs they gave us are valid
105
+ // Otherwise, check the sigs they gave us are valid and they provided all the expected feerates
106
+ // for the Cancel transaction.
107
107
let Sigs {
108
108
signatures :
109
109
Signatures {
@@ -113,19 +113,27 @@ fn process_sigs_message<C: secp256k1::Verification>(
113
113
} ,
114
114
..
115
115
} = msg;
116
- let cancel_sigs = cancel
117
- . values ( )
118
- . cloned ( )
119
- . next ( )
120
- . unwrap_or_else ( || BTreeMap :: new ( ) ) ; // FIXME
116
+
121
117
for ( key, sig) in emergency. iter ( ) {
122
118
emer_tx. add_sig ( * key, * sig, secp) ?;
123
119
}
124
120
emer_tx. finalize ( secp) ?;
125
- for ( key, sig) in cancel_sigs. iter ( ) {
126
- cancel_tx. add_sig ( * key, * sig, secp) ?;
121
+
122
+ for ( feerate, mut cancel_tx) in cancel_batch. feerates_map ( ) {
123
+ if let Some ( sigs) = cancel. get ( & CancelFeerate ( feerate) ) {
124
+ for ( key, sig) in sigs {
125
+ cancel_tx. add_sig ( * key, * sig, secp) ?;
126
+ }
127
+ cancel_tx. finalize ( secp) ?;
128
+ } else {
129
+ eprintln ! (
130
+ "'sig' message is missing Cancel signature at {} sat/vb" ,
131
+ feerate
132
+ ) ;
133
+ return Ok ( SigsResult { ack : false } ) ;
134
+ }
127
135
}
128
- cancel_tx . finalize ( secp ) ? ;
136
+
129
137
for ( key, sig) in unvault_emergency. iter ( ) {
130
138
unemer_tx. add_sig ( * key, * sig, secp) ?;
131
139
}
@@ -462,7 +470,7 @@ mod tests {
462
470
& secp_ctx,
463
471
)
464
472
. unwrap ( ) ;
465
- let cancel_tx = cancel_batch. into_feerate_20 ( ) ;
473
+ let cancel_feerates_map = cancel_batch. feerates_map ( ) ;
466
474
467
475
// This starts a dummy server to answer our gettxout requests
468
476
let bitcoind = sync:: Arc :: from ( dummy_bitcoind ( deposit_value) ) ;
@@ -534,7 +542,7 @@ mod tests {
534
542
. contains( "Invalid signature" ) ,
535
543
) ;
536
544
537
- // Enough invalid emergency sigs
545
+ // Enough valid emergency sigs, but not for the right key
538
546
let emergency: BTreeMap < secp256k1:: PublicKey , secp256k1:: Signature > = stakeholders_priv
539
547
. iter ( )
540
548
. map ( |xpriv| {
@@ -581,24 +589,70 @@ mod tests {
581
589
} )
582
590
. collect ( ) ;
583
591
584
- // Now do the same dance with Cancel signatures.
592
+ // Now do a similar dance with Cancel signatures.
593
+
594
+ // Cancel signatures are missing one required feerate. It will NACK it.
595
+ let mut cancel = BTreeMap :: new ( ) ;
596
+ for ( feerate, cancel_tx) in cancel_feerates_map. iter ( ) {
597
+ if feerate == & Amount :: from_sat ( 500 ) {
598
+ continue ;
599
+ }
600
+
601
+ let sighash = cancel_tx. sig_hash ( ) . unwrap ( ) ;
602
+ let sighash = secp256k1:: Message :: from_slice ( & sighash) . unwrap ( ) ;
603
+ let cancel_sigs: BTreeMap < secp256k1:: PublicKey , secp256k1:: Signature > =
604
+ stakeholders_priv
605
+ . iter ( )
606
+ . map ( |xpriv| {
607
+ let privkey = xpriv. derive_priv ( & secp_ctx, & [ derivation_index] ) . unwrap ( ) ;
608
+ (
609
+ privkey. private_key . public_key ( & secp_ctx) . key ,
610
+ secp_ctx. sign ( & sighash, & privkey. private_key . key ) ,
611
+ )
612
+ } )
613
+ . collect ( ) ;
614
+ cancel. insert ( CancelFeerate ( * feerate) , cancel_sigs) ;
615
+ }
616
+ let unvault_emergency: BTreeMap < secp256k1:: PublicKey , secp256k1:: Signature > =
617
+ BTreeMap :: new ( ) ;
618
+ let signatures = Signatures {
619
+ emergency : emergency_valid. clone ( ) ,
620
+ cancel,
621
+ unvault_emergency,
622
+ } ;
623
+ let msg = Sigs {
624
+ signatures,
625
+ deposit_outpoint,
626
+ derivation_index,
627
+ } ;
628
+ assert ! (
629
+ !process_sigs_message( & db_path, & scripts_config, & bitcoind, msg, & secp_ctx)
630
+ . unwrap( )
631
+ . ack
632
+ ) ;
585
633
586
634
// Not enough Cancel signatures
587
- let sighash = cancel_tx. sig_hash ( ) . unwrap ( ) ;
588
- let sighash = secp256k1:: Message :: from_slice ( & sighash) . unwrap ( ) ;
589
- let cancel_sigs: BTreeMap < secp256k1:: PublicKey , secp256k1:: Signature > = stakeholders_priv
590
- [ ..2 ]
591
- . iter ( )
592
- . map ( |xpriv| {
593
- let privkey = xpriv. derive_priv ( & secp_ctx, & [ derivation_index] ) . unwrap ( ) ;
594
- (
595
- privkey. private_key . public_key ( & secp_ctx) . key ,
596
- secp_ctx. sign ( & sighash, & privkey. private_key . key ) ,
597
- )
598
- } )
599
- . collect ( ) ;
600
- let cancel =
601
- IntoIterator :: into_iter ( [ ( CancelFeerate ( Amount :: from_sat ( 20 ) ) , cancel_sigs) ] ) . collect ( ) ;
635
+ let mut cancel = BTreeMap :: new ( ) ;
636
+ for ( feerate, cancel_tx) in cancel_feerates_map. iter ( ) {
637
+ let sighash = cancel_tx. sig_hash ( ) . unwrap ( ) ;
638
+ let sighash = secp256k1:: Message :: from_slice ( & sighash) . unwrap ( ) ;
639
+ let privs = if feerate == & Amount :: from_sat ( 20 ) {
640
+ & stakeholders_priv[ ..2 ]
641
+ } else {
642
+ & stakeholders_priv
643
+ } ;
644
+ let cancel_sigs: BTreeMap < secp256k1:: PublicKey , secp256k1:: Signature > = privs
645
+ . iter ( )
646
+ . map ( |xpriv| {
647
+ let privkey = xpriv. derive_priv ( & secp_ctx, & [ derivation_index] ) . unwrap ( ) ;
648
+ (
649
+ privkey. private_key . public_key ( & secp_ctx) . key ,
650
+ secp_ctx. sign ( & sighash, & privkey. private_key . key ) ,
651
+ )
652
+ } )
653
+ . collect ( ) ;
654
+ cancel. insert ( CancelFeerate ( * feerate) , cancel_sigs) ;
655
+ }
602
656
let unvault_emergency: BTreeMap < secp256k1:: PublicKey , secp256k1:: Signature > =
603
657
BTreeMap :: new ( ) ;
604
658
let signatures = Signatures {
@@ -618,21 +672,24 @@ mod tests {
618
672
. contains( "Revault transaction finalisation error" ) ,
619
673
) ;
620
674
621
- // Enough Cancel sigs, but invalid signature
622
- let bad_sighash = [ 0 ; 32 ] ;
623
- let bad_sighash = secp256k1:: Message :: from_slice ( & bad_sighash) . unwrap ( ) ;
624
- let cancel_sigs: BTreeMap < secp256k1:: PublicKey , secp256k1:: Signature > = stakeholders_priv
625
- . iter ( )
626
- . map ( |xpriv| {
627
- let privkey = xpriv. derive_priv ( & secp_ctx, & [ derivation_index] ) . unwrap ( ) ;
628
- (
629
- privkey. private_key . public_key ( & secp_ctx) . key ,
630
- secp_ctx. sign ( & bad_sighash, & privkey. private_key . key ) ,
631
- )
632
- } )
633
- . collect ( ) ;
634
- let cancel =
635
- IntoIterator :: into_iter ( [ ( CancelFeerate ( Amount :: from_sat ( 20 ) ) , cancel_sigs) ] ) . collect ( ) ;
675
+ // Enough Cancel sigs, but invalid signatures
676
+ let mut cancel = BTreeMap :: new ( ) ;
677
+ let sighash = [ 0 ; 32 ] ;
678
+ let sighash = secp256k1:: Message :: from_slice ( & sighash) . unwrap ( ) ;
679
+ for ( feerate, _) in cancel_feerates_map. iter ( ) {
680
+ let cancel_sigs: BTreeMap < secp256k1:: PublicKey , secp256k1:: Signature > =
681
+ stakeholders_priv
682
+ . iter ( )
683
+ . map ( |xpriv| {
684
+ let privkey = xpriv. derive_priv ( & secp_ctx, & [ derivation_index] ) . unwrap ( ) ;
685
+ (
686
+ privkey. private_key . public_key ( & secp_ctx) . key ,
687
+ secp_ctx. sign ( & sighash, & privkey. private_key . key ) ,
688
+ )
689
+ } )
690
+ . collect ( ) ;
691
+ cancel. insert ( CancelFeerate ( * feerate) , cancel_sigs) ;
692
+ }
636
693
let unvault_emergency: BTreeMap < secp256k1:: PublicKey , secp256k1:: Signature > =
637
694
BTreeMap :: new ( ) ;
638
695
let signatures = Signatures {
@@ -652,22 +709,26 @@ mod tests {
652
709
. contains( "Invalid signature" )
653
710
) ;
654
711
655
- // Enough invalid Cancel sigs
656
- let cancel_sigs: BTreeMap < secp256k1:: PublicKey , secp256k1:: Signature > = stakeholders_priv
657
- . iter ( )
658
- . map ( |xpriv| {
659
- // Note the derivation index increment
660
- let privkey = xpriv
661
- . derive_priv ( & secp_ctx, & [ derivation_index. increment ( ) . unwrap ( ) ] )
662
- . unwrap ( ) ;
663
- (
664
- privkey. private_key . public_key ( & secp_ctx) . key ,
665
- secp_ctx. sign ( & sighash, & privkey. private_key . key ) ,
666
- )
667
- } )
668
- . collect ( ) ;
669
- let cancel =
670
- IntoIterator :: into_iter ( [ ( CancelFeerate ( Amount :: from_sat ( 20 ) ) , cancel_sigs) ] ) . collect ( ) ;
712
+ // Enough Cancel sigs, but invalid pubkeys
713
+ let mut cancel = BTreeMap :: new ( ) ;
714
+ for ( feerate, cancel_tx) in cancel_feerates_map. iter ( ) {
715
+ let sighash = cancel_tx. sig_hash ( ) . unwrap ( ) ;
716
+ let sighash = secp256k1:: Message :: from_slice ( & sighash) . unwrap ( ) ;
717
+ let cancel_sigs: BTreeMap < secp256k1:: PublicKey , secp256k1:: Signature > =
718
+ stakeholders_priv
719
+ . iter ( )
720
+ . map ( |xpriv| {
721
+ let privkey = xpriv
722
+ . derive_priv ( & secp_ctx, & [ derivation_index. increment ( ) . unwrap ( ) ] )
723
+ . unwrap ( ) ;
724
+ (
725
+ privkey. private_key . public_key ( & secp_ctx) . key ,
726
+ secp_ctx. sign ( & sighash, & privkey. private_key . key ) ,
727
+ )
728
+ } )
729
+ . collect ( ) ;
730
+ cancel. insert ( CancelFeerate ( * feerate) , cancel_sigs) ;
731
+ }
671
732
let unvault_emergency: BTreeMap < secp256k1:: PublicKey , secp256k1:: Signature > =
672
733
BTreeMap :: new ( ) ;
673
734
let signatures = Signatures {
@@ -688,20 +749,23 @@ mod tests {
688
749
) ;
689
750
690
751
// Valid Cancel signatures.
691
- let cancel_valid_sigs: BTreeMap < secp256k1:: PublicKey , secp256k1:: Signature > =
692
- stakeholders_priv
693
- . iter ( )
694
- . map ( |xpriv| {
695
- let privkey = xpriv. derive_priv ( & secp_ctx, & [ derivation_index] ) . unwrap ( ) ;
696
- (
697
- privkey. private_key . public_key ( & secp_ctx) . key ,
698
- secp_ctx. sign ( & sighash, & privkey. private_key . key ) ,
699
- )
700
- } )
701
- . collect ( ) ;
702
- let cancel_valid: BTreeMap < _ , _ > =
703
- IntoIterator :: into_iter ( [ ( CancelFeerate ( Amount :: from_sat ( 20 ) ) , cancel_valid_sigs) ] )
704
- . collect ( ) ;
752
+ let mut cancel_valid = BTreeMap :: new ( ) ;
753
+ for ( feerate, cancel_tx) in cancel_feerates_map. iter ( ) {
754
+ let sighash = cancel_tx. sig_hash ( ) . unwrap ( ) ;
755
+ let sighash = secp256k1:: Message :: from_slice ( & sighash) . unwrap ( ) ;
756
+ let cancel_sigs: BTreeMap < secp256k1:: PublicKey , secp256k1:: Signature > =
757
+ stakeholders_priv
758
+ . iter ( )
759
+ . map ( |xpriv| {
760
+ let privkey = xpriv. derive_priv ( & secp_ctx, & [ derivation_index] ) . unwrap ( ) ;
761
+ (
762
+ privkey. private_key . public_key ( & secp_ctx) . key ,
763
+ secp_ctx. sign ( & sighash, & privkey. private_key . key ) ,
764
+ )
765
+ } )
766
+ . collect ( ) ;
767
+ cancel_valid. insert ( CancelFeerate ( * feerate) , cancel_sigs) ;
768
+ }
705
769
706
770
// Now do the same dance with Unvault Emergency signatures.
707
771
0 commit comments