28
28
//! `bt listunspent`
29
29
//!
30
30
31
+ use std:: collections:: BTreeMap ;
31
32
use std:: fmt;
32
33
use std:: str:: FromStr ;
33
- use std:: collections:: BTreeMap ;
34
34
35
- use bitcoin:: { Address , Amount , Network , OutPoint , PublicKey , PrivateKey , Sequence , Script , Transaction , Txid , TxOut , TxIn , Witness } ;
36
35
use bitcoin:: consensus:: encode;
37
36
use bitcoin:: hashes:: hex:: { self , FromHex } ;
38
37
use bitcoin:: secp256k1:: { Secp256k1 , Signing , Verification } ;
39
38
use bitcoin:: util:: address;
40
39
use bitcoin:: util:: amount:: ParseAmountError ;
41
- use bitcoin:: util:: bip32:: { self , ChildNumber , DerivationPath , ExtendedPrivKey , ExtendedPubKey , Fingerprint , IntoDerivationPath } ;
40
+ use bitcoin:: util:: bip32:: {
41
+ self , ChildNumber , DerivationPath , ExtendedPrivKey , ExtendedPubKey , Fingerprint ,
42
+ IntoDerivationPath ,
43
+ } ;
42
44
use bitcoin:: util:: psbt:: { self , Input , Psbt , PsbtSighashType } ;
45
+ use bitcoin:: {
46
+ Address , Amount , Network , OutPoint , PrivateKey , PublicKey , Script , Sequence , Transaction , TxIn ,
47
+ TxOut , Txid , Witness ,
48
+ } ;
43
49
44
50
use self :: psbt_sign:: * ;
45
51
@@ -69,7 +75,8 @@ const NETWORK: Network = Network::Regtest;
69
75
fn main ( ) -> Result < ( ) > {
70
76
let secp = Secp256k1 :: new ( ) ;
71
77
72
- let ( offline, fingerprint, account_0_xpub, input_xpub) = ColdStorage :: new ( & secp, EXTENDED_MASTER_PRIVATE_KEY ) ?;
78
+ let ( offline, fingerprint, account_0_xpub, input_xpub) =
79
+ ColdStorage :: new ( & secp, EXTENDED_MASTER_PRIVATE_KEY ) ?;
73
80
74
81
let online = WatchOnly :: new ( account_0_xpub, input_xpub, fingerprint) ;
75
82
@@ -109,7 +116,7 @@ impl ColdStorage {
109
116
/// # Returns
110
117
///
111
118
/// The newly created signer along with the data needed to configure a watch-only wallet.
112
- fn new < C : Signing > ( secp : & Secp256k1 < C > , xpriv : & str ) -> Result < ExportData > {
119
+ fn new < C : Signing > ( secp : & Secp256k1 < C > , xpriv : & str ) -> Result < ExportData > {
113
120
let master_xpriv = ExtendedPrivKey :: from_str ( xpriv) ?;
114
121
let master_xpub = ExtendedPubKey :: from_priv ( secp, & master_xpriv) ;
115
122
@@ -123,19 +130,14 @@ impl ColdStorage {
123
130
let input_xpriv = master_xpriv. derive_priv ( secp, & path) ?;
124
131
let input_xpub = ExtendedPubKey :: from_priv ( secp, & input_xpriv) ;
125
132
126
- let wallet = ColdStorage {
127
- master_xpriv,
128
- master_xpub,
129
- } ;
133
+ let wallet = ColdStorage { master_xpriv, master_xpub } ;
130
134
let fingerprint = wallet. master_fingerprint ( ) ;
131
135
132
136
Ok ( ( wallet, fingerprint, account_0_xpub, input_xpub) )
133
137
}
134
138
135
139
/// Returns the fingerprint for the master extended public key.
136
- fn master_fingerprint ( & self ) -> Fingerprint {
137
- self . master_xpub . fingerprint ( )
138
- }
140
+ fn master_fingerprint ( & self ) -> Fingerprint { self . master_xpub . fingerprint ( ) }
139
141
140
142
/// Signs `psbt` with this signer.
141
143
fn sign_psbt < C : Signing > ( & self , secp : & Secp256k1 < C > , mut psbt : Psbt ) -> Result < Psbt > {
@@ -146,7 +148,11 @@ impl ColdStorage {
146
148
}
147
149
148
150
/// Returns the private key required to sign `input` if we have it.
149
- fn private_key_to_sign < C : Signing > ( & self , secp : & Secp256k1 < C > , input : & Input ) -> Result < PrivateKey > {
151
+ fn private_key_to_sign < C : Signing > (
152
+ & self ,
153
+ secp : & Secp256k1 < C > ,
154
+ input : & Input ,
155
+ ) -> Result < PrivateKey > {
150
156
match input. bip32_derivation . iter ( ) . next ( ) {
151
157
Some ( ( pk, ( fingerprint, path) ) ) => {
152
158
if * fingerprint != self . master_fingerprint ( ) {
@@ -159,8 +165,7 @@ impl ColdStorage {
159
165
}
160
166
161
167
Ok ( sk)
162
-
163
- } ,
168
+ }
164
169
None => Err ( Error :: MissingBip32Derivation ) ,
165
170
}
166
171
}
@@ -184,7 +189,11 @@ impl WatchOnly {
184
189
///
185
190
/// The reason for importing the `input_xpub` is so one can use bitcoind to grab a valid input
186
191
/// to verify the workflow presented in this file.
187
- fn new ( account_0_xpub : ExtendedPubKey , input_xpub : ExtendedPubKey , master_fingerprint : Fingerprint ) -> Self {
192
+ fn new (
193
+ account_0_xpub : ExtendedPubKey ,
194
+ input_xpub : ExtendedPubKey ,
195
+ master_fingerprint : Fingerprint ,
196
+ ) -> Self {
188
197
WatchOnly { account_0_xpub, input_xpub, master_fingerprint }
189
198
}
190
199
@@ -199,26 +208,21 @@ impl WatchOnly {
199
208
let tx = Transaction {
200
209
version : 2 ,
201
210
lock_time : 0 ,
202
- input : vec ! [
203
- TxIn {
204
- previous_output: OutPoint {
205
- txid: Txid :: from_hex( INPUT_UTXO_TXID ) ?,
206
- vout: INPUT_UTXO_VOUT ,
207
- } ,
208
- script_sig: Script :: new( ) ,
209
- sequence: Sequence :: MAX , // Disable LockTime and RBF.
210
- witness: Witness :: default ( ) ,
211
+ input : vec ! [ TxIn {
212
+ previous_output: OutPoint {
213
+ txid: Txid :: from_hex( INPUT_UTXO_TXID ) ?,
214
+ vout: INPUT_UTXO_VOUT ,
211
215
} ,
212
- ] ,
216
+ script_sig: Script :: new( ) ,
217
+ sequence: Sequence :: MAX , // Disable LockTime and RBF.
218
+ witness: Witness :: default ( ) ,
219
+ } ] ,
213
220
output : vec ! [
214
- TxOut {
215
- value: to_amount. to_sat( ) ,
216
- script_pubkey: to_address. script_pubkey( ) ,
217
- } ,
221
+ TxOut { value: to_amount. to_sat( ) , script_pubkey: to_address. script_pubkey( ) } ,
218
222
TxOut {
219
223
value: change_amount. to_sat( ) ,
220
224
script_pubkey: change_address. script_pubkey( ) ,
221
- }
225
+ } ,
222
226
] ,
223
227
} ;
224
228
@@ -281,7 +285,10 @@ impl WatchOnly {
281
285
/// "m/84h/0h/0h/1/0"). A real wallet would have access to the chain so could determine if an
282
286
/// address has been used or not. We ignore this detail and just re-use the first change address
283
287
/// without loss of generality.
284
- fn change_address < C : Verification > ( & self , secp : & Secp256k1 < C > ) -> Result < ( PublicKey , Address , DerivationPath ) > {
288
+ fn change_address < C : Verification > (
289
+ & self ,
290
+ secp : & Secp256k1 < C > ,
291
+ ) -> Result < ( PublicKey , Address , DerivationPath ) > {
285
292
let path = vec ! [ ChildNumber :: from_normal_idx( 1 ) ?, ChildNumber :: from_normal_idx( 0 ) ?] ;
286
293
let derived = self . account_0_xpub . derive_pub ( secp, & path) ?;
287
294
@@ -299,13 +306,11 @@ fn input_derivation_path() -> Result<DerivationPath> {
299
306
}
300
307
301
308
fn previous_output ( ) -> TxOut {
302
- let script_pubkey = Script :: from_hex ( INPUT_UTXO_SCRIPT_PUBKEY ) . expect ( "failed to parse input utxo scriptPubkey" ) ;
309
+ let script_pubkey = Script :: from_hex ( INPUT_UTXO_SCRIPT_PUBKEY )
310
+ . expect ( "failed to parse input utxo scriptPubkey" ) ;
303
311
let amount = Amount :: from_str ( INPUT_UTXO_VALUE ) . expect ( "failed to parse input utxo value" ) ;
304
312
305
- TxOut {
306
- value : amount. to_sat ( ) ,
307
- script_pubkey,
308
- }
313
+ TxOut { value : amount. to_sat ( ) , script_pubkey }
309
314
}
310
315
311
316
#[ derive( Clone , Debug , PartialEq , Eq ) ]
@@ -335,51 +340,35 @@ enum Error {
335
340
}
336
341
337
342
impl std:: error:: Error for Error {
338
- fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > {
339
- None
340
- }
343
+ fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > { None }
341
344
}
342
345
343
346
impl fmt:: Display for Error {
344
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
345
- write ! ( f, "{:?}" , self )
346
- }
347
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result { write ! ( f, "{:?}" , self ) }
347
348
}
348
349
349
350
impl From < bip32:: Error > for Error {
350
- fn from ( e : bip32:: Error ) -> Error {
351
- Error :: Bip32 ( e)
352
- }
351
+ fn from ( e : bip32:: Error ) -> Error { Error :: Bip32 ( e) }
353
352
}
354
353
355
354
impl From < psbt:: Error > for Error {
356
- fn from ( e : psbt:: Error ) -> Error {
357
- Error :: Psbt ( e)
358
- }
355
+ fn from ( e : psbt:: Error ) -> Error { Error :: Psbt ( e) }
359
356
}
360
357
361
358
impl From < SighashError > for Error {
362
- fn from ( e : SighashError ) -> Error {
363
- Error :: PsbtSighash ( e)
364
- }
359
+ fn from ( e : SighashError ) -> Error { Error :: PsbtSighash ( e) }
365
360
}
366
361
367
362
impl From < hex:: Error > for Error {
368
- fn from ( e : hex:: Error ) -> Error {
369
- Error :: Hex ( e)
370
- }
363
+ fn from ( e : hex:: Error ) -> Error { Error :: Hex ( e) }
371
364
}
372
365
373
366
impl From < address:: Error > for Error {
374
- fn from ( e : address:: Error ) -> Error {
375
- Error :: Address ( e)
376
- }
367
+ fn from ( e : address:: Error ) -> Error { Error :: Address ( e) }
377
368
}
378
369
379
370
impl From < ParseAmountError > for Error {
380
- fn from ( e : ParseAmountError ) -> Error {
381
- Error :: ParseAmount ( e)
382
- }
371
+ fn from ( e : ParseAmountError ) -> Error { Error :: ParseAmount ( e) }
383
372
}
384
373
385
374
/// This module implements signing a PSBT. It is based on code in `rust-miniscript` with a bit of a
@@ -392,15 +381,22 @@ mod psbt_sign {
392
381
use std:: fmt;
393
382
use std:: ops:: Deref ;
394
383
395
- use bitcoin:: { EcdsaSig , EcdsaSighashType , EcdsaSigError , PrivateKey , SchnorrSighashType , Script , Transaction , TxOut } ;
396
384
use bitcoin:: psbt:: { Input , Prevouts , Psbt , PsbtSighashType } ;
397
385
use bitcoin:: util:: sighash:: { self , SighashCache } ;
398
386
use bitcoin:: util:: taproot:: TapLeafHash ;
399
-
400
- use secp256k1:: { Message , Signing , Secp256k1 } ;
387
+ use bitcoin:: {
388
+ EcdsaSig , EcdsaSigError , EcdsaSighashType , PrivateKey , SchnorrSighashType , Script ,
389
+ Transaction , TxOut ,
390
+ } ;
391
+ use secp256k1:: { Message , Secp256k1 , Signing } ;
401
392
402
393
/// Signs the input at `input_index` with private key `sk`.
403
- pub fn sign < C : Signing > ( psbt : & mut Psbt , sk : & PrivateKey , input_index : usize , secp : & Secp256k1 < C > ) -> Result < ( ) , SighashError > {
394
+ pub fn sign < C : Signing > (
395
+ psbt : & mut Psbt ,
396
+ sk : & PrivateKey ,
397
+ input_index : usize ,
398
+ secp : & Secp256k1 < C > ,
399
+ ) -> Result < ( ) , SighashError > {
404
400
check_index_is_within_bounds ( psbt, input_index) ?;
405
401
406
402
let mut cache = SighashCache :: new ( & psbt. unsigned_tx ) ;
@@ -413,16 +409,13 @@ mod psbt_sign {
413
409
final_signature. push ( sighash_ty. to_u32 ( ) as u8 ) ;
414
410
415
411
let pk = sk. public_key ( secp) ;
416
- psbt. inputs [ input_index]
417
- . partial_sigs
418
- . insert ( pk, EcdsaSig :: from_slice ( & final_signature) ?) ;
412
+ psbt. inputs [ input_index] . partial_sigs . insert ( pk, EcdsaSig :: from_slice ( & final_signature) ?) ;
419
413
420
414
Ok ( ( ) )
421
-
422
415
}
423
416
424
417
/// Returns the sighash message to sign along with the sighash type.
425
- fn sighash < T : Deref < Target = Transaction > > (
418
+ fn sighash < T : Deref < Target = Transaction > > (
426
419
psbt : & Psbt ,
427
420
input_index : usize ,
428
421
cache : & mut SighashCache < T > ,
@@ -450,12 +443,10 @@ mod psbt_sign {
450
443
let is_wsh = script. is_v0_p2wsh ( ) ;
451
444
452
445
let is_nested_wpkh = script. is_p2sh ( )
453
- && input. redeem_script . as_ref ( )
454
- . map ( |s| s. is_v0_p2wpkh ( ) ) . unwrap_or ( false ) ;
446
+ && input. redeem_script . as_ref ( ) . map ( |s| s. is_v0_p2wpkh ( ) ) . unwrap_or ( false ) ;
455
447
456
448
let is_nested_wsh = script. is_p2sh ( )
457
- && input. redeem_script . as_ref ( )
458
- . map ( |x| x. is_v0_p2wsh ( ) ) . unwrap_or ( false ) ;
449
+ && input. redeem_script . as_ref ( ) . map ( |x| x. is_v0_p2wsh ( ) ) . unwrap_or ( false ) ;
459
450
460
451
let is_segwit = is_wpkh || is_wsh || is_nested_wpkh || is_nested_wsh;
461
452
@@ -468,9 +459,9 @@ mod psbt_sign {
468
459
. ok_or ( SighashError :: NotWpkh ) ?
469
460
} ;
470
461
cache. segwit_signature_hash ( input_index, & script_code, utxo. value , hash_ty) ?
471
-
472
462
} else {
473
- let script_code = input. witness_script . as_ref ( ) . ok_or ( SighashError :: MissingWitnessScript ) ?;
463
+ let script_code =
464
+ input. witness_script . as_ref ( ) . ok_or ( SighashError :: MissingWitnessScript ) ?;
474
465
cache. segwit_signature_hash ( input_index, script_code, utxo. value , hash_ty) ?
475
466
}
476
467
} else {
@@ -528,7 +519,7 @@ mod psbt_sign {
528
519
}
529
520
530
521
/// Returns the sighash message and sighash type for this `input`.
531
- fn taproot_sighash < T : Deref < Target = Transaction > > (
522
+ fn taproot_sighash < T : Deref < Target = Transaction > > (
532
523
input : & Input ,
533
524
prevouts : Vec < & TxOut > ,
534
525
input_index : usize ,
@@ -546,16 +537,16 @@ mod psbt_sign {
546
537
. map_err ( |_e| SighashError :: InvalidSighashType ) ?;
547
538
548
539
let sighash = match tapleaf_hash {
549
- Some ( leaf_hash) => {
550
- cache. taproot_script_spend_signature_hash ( input_index, & prevouts, leaf_hash, hash_ty) ?
551
- }
552
- None => {
553
- cache. taproot_key_spend_signature_hash ( input_index, & prevouts, hash_ty) ?
554
- }
540
+ Some ( leaf_hash) => cache. taproot_script_spend_signature_hash (
541
+ input_index,
542
+ & prevouts,
543
+ leaf_hash,
544
+ hash_ty,
545
+ ) ?,
546
+ None => cache. taproot_key_spend_signature_hash ( input_index, & prevouts, hash_ty) ?,
555
547
} ;
556
548
let msg = Message :: from_slice ( & sighash) . expect ( "sighashes are 32 bytes" ) ;
557
549
Ok ( ( msg, hash_ty. into ( ) ) )
558
-
559
550
}
560
551
561
552
/// Errors encountered while calculating the sighash message.
@@ -598,15 +589,11 @@ mod psbt_sign {
598
589
}
599
590
600
591
impl From < sighash:: Error > for SighashError {
601
- fn from ( e : sighash:: Error ) -> Self {
602
- SighashError :: SighashComputation ( e)
603
- }
592
+ fn from ( e : sighash:: Error ) -> Self { SighashError :: SighashComputation ( e) }
604
593
}
605
594
606
595
impl From < EcdsaSigError > for SighashError {
607
- fn from ( e : EcdsaSigError ) -> Self {
608
- SighashError :: EcdsaSig ( e)
609
- }
596
+ fn from ( e : EcdsaSigError ) -> Self { SighashError :: EcdsaSig ( e) }
610
597
}
611
598
612
599
#[ cfg( feature = "std" ) ]
@@ -616,11 +603,11 @@ mod psbt_sign {
616
603
617
604
match self {
618
605
IndexOutOfBounds ( _, _)
619
- | MissingSpendUtxo
620
- | MissingWitnessScript
621
- | MissingRedeemScript
622
- | InvalidSighashType
623
- | NotWpkh => None ,
606
+ | MissingSpendUtxo
607
+ | MissingWitnessScript
608
+ | MissingRedeemScript
609
+ | InvalidSighashType
610
+ | NotWpkh => None ,
624
611
SighashComputation ( e) => Some ( e) ,
625
612
EcdsaSig ( e) => Some ( e) ,
626
613
}
0 commit comments