@@ -40,6 +40,7 @@ use core::num::ParseIntError;
40
40
use core:: str:: FromStr ;
41
41
#[ cfg( feature = "std" ) ] use std:: error;
42
42
43
+ use secp256k1:: schnorrsig;
43
44
use bech32;
44
45
use hashes:: Hash ;
45
46
use hash_types:: { PubkeyHash , WPubkeyHash , ScriptHash , WScriptHash } ;
@@ -59,6 +60,13 @@ pub enum Error {
59
60
Bech32 ( bech32:: Error ) ,
60
61
/// The bech32 payload was empty
61
62
EmptyBech32Payload ,
63
+ /// The wrong checksum algorithm was used. See BIP-0350.
64
+ InvalidBech32Variant {
65
+ /// Bech32 variant that is required by the used Witness version
66
+ expected : bech32:: Variant ,
67
+ /// The actual Bech32 variant encoded in the address representation
68
+ found : bech32:: Variant
69
+ } ,
62
70
/// Script version must be 0 to 16 inclusive
63
71
InvalidWitnessVersion ( u8 ) ,
64
72
/// Unable to parse witness version from string
@@ -78,11 +86,12 @@ pub enum Error {
78
86
impl fmt:: Display for Error {
79
87
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
80
88
match * self {
81
- Error :: Base58 ( ref e ) => write ! ( f, "base58: {}" , e ) ,
82
- Error :: Bech32 ( ref e ) => write ! ( f, "bech32: {}" , e ) ,
89
+ Error :: Base58 ( _ ) => write ! ( f, "base58 address encoding error" ) ,
90
+ Error :: Bech32 ( _ ) => write ! ( f, "bech32 address encoding error" ) ,
83
91
Error :: EmptyBech32Payload => write ! ( f, "the bech32 payload was empty" ) ,
92
+ Error :: InvalidBech32Variant { expected, found } => write ! ( f, "invalid bech32 checksum variant found {:?} when {:?} was expected" , found, expected) ,
84
93
Error :: InvalidWitnessVersion ( v) => write ! ( f, "invalid witness script version: {}" , v) ,
85
- Error :: UnparsableWitnessVersion ( ref e ) => write ! ( f, "Incorrect format of a witness version byte: {}" , e ) ,
94
+ Error :: UnparsableWitnessVersion ( _ ) => write ! ( f, "incorrect format of a witness version byte" ) ,
86
95
Error :: MalformedWitnessVersion => f. write_str ( "bitcoin script opcode does not match any known witness version, the script is malformed" ) ,
87
96
Error :: InvalidWitnessProgramLength ( l) => write ! ( f,
88
97
"the witness program must be between 2 and 40 bytes in length: length={}" , l,
@@ -137,6 +146,8 @@ pub enum AddressType {
137
146
P2wpkh ,
138
147
/// pay-to-witness-script-hash
139
148
P2wsh ,
149
+ /// pay-to-taproot
150
+ P2tr ,
140
151
}
141
152
142
153
impl fmt:: Display for AddressType {
@@ -146,6 +157,7 @@ impl fmt::Display for AddressType {
146
157
AddressType :: P2sh => "p2sh" ,
147
158
AddressType :: P2wpkh => "p2wpkh" ,
148
159
AddressType :: P2wsh => "p2wsh" ,
160
+ AddressType :: P2tr => "p2tr" ,
149
161
} )
150
162
}
151
163
}
@@ -158,6 +170,7 @@ impl FromStr for AddressType {
158
170
"p2sh" => Ok ( AddressType :: P2sh ) ,
159
171
"p2wpkh" => Ok ( AddressType :: P2wpkh ) ,
160
172
"p2wsh" => Ok ( AddressType :: P2wsh ) ,
173
+ "p2tr" => Ok ( AddressType :: P2tr ) ,
161
174
_ => Err ( ( ) ) ,
162
175
}
163
176
}
@@ -314,6 +327,14 @@ impl WitnessVersion {
314
327
pub fn into_num ( self ) -> u8 {
315
328
self as u8
316
329
}
330
+
331
+ /// Determine the checksum variant. See BIP-0350 for specification.
332
+ pub fn bech32_variant ( & self ) -> bech32:: Variant {
333
+ match self {
334
+ WitnessVersion :: V0 => bech32:: Variant :: Bech32 ,
335
+ _ => bech32:: Variant :: Bech32m ,
336
+ }
337
+ }
317
338
}
318
339
319
340
impl From < WitnessVersion > for :: bech32:: u5 {
@@ -490,6 +511,17 @@ impl Address {
490
511
}
491
512
}
492
513
514
+ /// Create a pay to taproot address
515
+ pub fn p2tr ( taptweaked_key : schnorrsig:: PublicKey , network : Network ) -> Address {
516
+ Address {
517
+ network : network,
518
+ payload : Payload :: WitnessProgram {
519
+ version : WitnessVersion :: V1 ,
520
+ program : taptweaked_key. serialize ( ) . to_vec ( )
521
+ }
522
+ }
523
+ }
524
+
493
525
/// Get the address type of the address.
494
526
/// None if unknown, non-standard or related to the future witness version.
495
527
pub fn address_type ( & self ) -> Option < AddressType > {
@@ -507,6 +539,7 @@ impl Address {
507
539
32 => Some ( AddressType :: P2wsh ) ,
508
540
_ => None ,
509
541
} ,
542
+ WitnessVersion :: V1 if prog. len ( ) == 32 => Some ( AddressType :: P2tr ) ,
510
543
_ => None ,
511
544
}
512
545
}
@@ -617,15 +650,14 @@ impl fmt::Display for Address {
617
650
Network :: Testnet | Network :: Signet => "tb" ,
618
651
Network :: Regtest => "bcrt" ,
619
652
} ;
620
- let bech_ver = if version. into_num ( ) > 0 { bech32:: Variant :: Bech32m } else { bech32:: Variant :: Bech32 } ;
621
653
let mut upper_writer;
622
654
let writer = if fmt. alternate ( ) {
623
655
upper_writer = UpperWriter ( fmt) ;
624
656
& mut upper_writer as & mut dyn fmt:: Write
625
657
} else {
626
658
fmt as & mut dyn fmt:: Write
627
659
} ;
628
- let mut bech32_writer = bech32:: Bech32Writer :: new ( hrp, bech_ver , writer) ?;
660
+ let mut bech32_writer = bech32:: Bech32Writer :: new ( hrp, version . bech32_variant ( ) , writer) ?;
629
661
bech32:: WriteBase32 :: write_u5 ( & mut bech32_writer, version. into ( ) ) ?;
630
662
bech32:: ToBase32 :: write_base32 ( & prog, & mut bech32_writer)
631
663
}
@@ -688,10 +720,10 @@ impl FromStr for Address {
688
720
return Err ( Error :: InvalidSegwitV0ProgramLength ( program. len ( ) ) ) ;
689
721
}
690
722
691
- // Bech32 encoding check
692
- if ( version. into_num ( ) > 0 && variant != bech32 :: Variant :: Bech32m ) ||
693
- ( version . into_num ( ) == 0 && variant != bech32 :: Variant :: Bech32 ) {
694
- return Err ( Error :: InvalidWitnessVersion ( version . into_num ( ) ) )
723
+ // Encoding check
724
+ let expected = version. bech32_variant ( ) ;
725
+ if expected != variant {
726
+ return Err ( Error :: InvalidBech32Variant { expected , found : variant } ) ;
695
727
}
696
728
697
729
return Ok ( Address {
0 commit comments