15
15
//!
16
16
//! This module provides support for taproot tagged hashes.
17
17
//!
18
+
18
19
use prelude:: * ;
19
20
use io;
20
21
use secp256k1:: { self , Secp256k1 } ;
@@ -120,7 +121,7 @@ impl TapLeafHash {
120
121
/// function to compute leaf hash from components
121
122
pub fn from_script ( script : & Script , ver : LeafVersion ) -> TapLeafHash {
122
123
let mut eng = TapLeafHash :: engine ( ) ;
123
- ver. as_u8 ( )
124
+ ver. into_consensus ( )
124
125
. consensus_encode ( & mut eng)
125
126
. expect ( "engines don't error" ) ;
126
127
script
@@ -142,6 +143,8 @@ pub const TAPROOT_LEAF_MASK: u8 = 0xfe;
142
143
/// Tapscript leaf version
143
144
// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L226
144
145
pub const TAPROOT_LEAF_TAPSCRIPT : u8 = 0xc0 ;
146
+ /// Taproot annex prefix
147
+ pub const TAPROOT_ANNEX_PREFIX : u8 = 0x50 ;
145
148
/// Tapscript control base size
146
149
// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L227
147
150
pub const TAPROOT_CONTROL_BASE_SIZE : usize = 33 ;
@@ -152,6 +155,7 @@ pub const TAPROOT_CONTROL_MAX_SIZE: usize =
152
155
153
156
// type alias for versioned tap script corresponding merkle proof
154
157
type ScriptMerkleProofMap = BTreeMap < ( Script , LeafVersion ) , BTreeSet < TaprootMerkleBranch > > ;
158
+
155
159
/// Data structure for representing Taproot spending information.
156
160
/// Taproot output corresponds to a combination of a
157
161
/// single public key condition (known the internal key), and zero or more
@@ -216,7 +220,7 @@ impl TaprootSpendInfo {
216
220
{
217
221
let mut node_weights = BinaryHeap :: < ( Reverse < u64 > , NodeInfo ) > :: new ( ) ;
218
222
for ( p, leaf) in script_weights {
219
- node_weights. push ( ( Reverse ( p as u64 ) , NodeInfo :: new_leaf_with_ver ( leaf, LeafVersion :: default ( ) ) ) ) ;
223
+ node_weights. push ( ( Reverse ( p as u64 ) , NodeInfo :: new_leaf_with_ver ( leaf, LeafVersion :: TapScript ) ) ) ;
220
224
}
221
225
if node_weights. is_empty ( ) {
222
226
return Err ( TaprootBuilderError :: IncompleteTree ) ;
@@ -409,7 +413,7 @@ impl TaprootBuilder {
409
413
/// See [`TaprootBuilder::add_leaf_with_ver`] for adding a leaf with specific version
410
414
/// See [Uncyclopedia](https://en.wikipedia.org/wiki/Depth-first_search) for more details
411
415
pub fn add_leaf ( self , depth : usize , script : Script ) -> Result < Self , TaprootBuilderError > {
412
- self . add_leaf_with_ver ( depth, script, LeafVersion :: default ( ) )
416
+ self . add_leaf_with_ver ( depth, script, LeafVersion :: TapScript )
413
417
}
414
418
415
419
/// Add a hidden/omitted node at a depth `depth` to the builder.
@@ -680,7 +684,7 @@ impl ControlBlock {
680
684
return Err ( TaprootError :: InvalidControlBlockSize ( sl. len ( ) ) ) ;
681
685
}
682
686
let output_key_parity = secp256k1:: Parity :: from ( ( sl[ 0 ] & 1 ) as i32 ) ;
683
- let leaf_version = LeafVersion :: from_u8 ( sl[ 0 ] & TAPROOT_LEAF_MASK ) ?;
687
+ let leaf_version = LeafVersion :: from_consensus ( sl[ 0 ] & TAPROOT_LEAF_MASK ) ?;
684
688
let internal_key = UntweakedPublicKey :: from_slice ( & sl[ 1 ..TAPROOT_CONTROL_BASE_SIZE ] )
685
689
. map_err ( TaprootError :: InvalidInternalKey ) ?;
686
690
let merkle_branch = TaprootMerkleBranch :: from_slice ( & sl[ TAPROOT_CONTROL_BASE_SIZE ..] ) ?;
@@ -700,7 +704,7 @@ impl ControlBlock {
700
704
701
705
/// Serialize to a writer. Returns the number of bytes written
702
706
pub fn encode < Write : io:: Write > ( & self , mut writer : Write ) -> io:: Result < usize > {
703
- let first_byte: u8 = i32:: from ( self . output_key_parity ) as u8 | self . leaf_version . as_u8 ( ) ;
707
+ let first_byte: u8 = i32:: from ( self . output_key_parity ) as u8 | self . leaf_version . into_consensus ( ) ;
704
708
let mut bytes_written = 0 ;
705
709
bytes_written += writer. write ( & [ first_byte] ) ?;
706
710
bytes_written += writer. write ( & self . internal_key . serialize ( ) ) ?;
@@ -759,16 +763,16 @@ impl ControlBlock {
759
763
/// The leaf version for tapleafs
760
764
#[ derive( Debug , Clone , Copy , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
761
765
#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
762
- pub struct LeafVersion ( u8 ) ;
766
+ pub enum LeafVersion {
767
+ /// BIP-342 tapscript
768
+ TapScript ,
763
769
764
- impl Default for LeafVersion {
765
- fn default ( ) -> Self {
766
- LeafVersion ( TAPROOT_LEAF_TAPSCRIPT )
767
- }
770
+ /// Future leaf version
771
+ Future ( u8 )
768
772
}
769
773
770
774
impl LeafVersion {
771
- /// Obtain LeafVersion from u8, will error when last bit of ver is even or
775
+ /// Obtain LeafVersion from u8, will error when last bit of ver is odd or
772
776
/// when ver is 0x50 (ANNEX_TAG)
773
777
// Text from BIP341:
774
778
// In order to support some forms of static analysis that rely on
@@ -779,23 +783,32 @@ impl LeafVersion {
779
783
// or an opcode that is not valid as the first opcode).
780
784
// The values that comply to this rule are the 32 even values between
781
785
// 0xc0 and 0xfe and also 0x66, 0x7e, 0x80, 0x84, 0x96, 0x98, 0xba, 0xbc, 0xbe
782
- pub fn from_u8 ( ver : u8 ) -> Result < Self , TaprootError > {
783
- if ver & TAPROOT_LEAF_MASK == ver && ver != 0x50 {
784
- Ok ( LeafVersion ( ver) )
785
- } else {
786
- Err ( TaprootError :: InvalidTaprootLeafVersion ( ver) )
786
+ pub fn from_consensus ( version : u8 ) -> Result < Self , TaprootError > {
787
+ match version {
788
+ TAPROOT_LEAF_TAPSCRIPT => Ok ( LeafVersion :: TapScript ) ,
789
+ TAPROOT_ANNEX_PREFIX => Err ( TaprootError :: InvalidTaprootLeafVersion ( TAPROOT_ANNEX_PREFIX ) ) ,
790
+ odd if odd & TAPROOT_LEAF_MASK != odd => Err ( TaprootError :: InvalidTaprootLeafVersion ( odd) ) ,
791
+ future => Ok ( LeafVersion :: Future ( future) ) ,
787
792
}
788
793
}
789
794
790
795
/// Get the inner version from LeafVersion
791
- pub fn as_u8 ( & self ) -> u8 {
792
- self . 0
796
+ pub fn into_consensus ( self ) -> u8 {
797
+ match self {
798
+ LeafVersion :: TapScript => TAPROOT_LEAF_TAPSCRIPT ,
799
+ LeafVersion :: Future ( version) => version,
800
+ }
793
801
}
794
802
}
795
803
796
- impl Into < u8 > for LeafVersion {
797
- fn into ( self ) -> u8 {
798
- self . 0
804
+ impl fmt:: Display for LeafVersion {
805
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
806
+ match ( self , f. alternate ( ) ) {
807
+ ( LeafVersion :: TapScript , false ) => f. write_str ( "tapscript" ) ,
808
+ ( LeafVersion :: TapScript , true ) => fmt:: Display :: fmt ( & TAPROOT_LEAF_TAPSCRIPT , f) ,
809
+ ( LeafVersion :: Future ( version) , false ) => write ! ( f, "future_script_{:#02x}" , version) ,
810
+ ( LeafVersion :: Future ( version) , true ) => fmt:: Display :: fmt ( version, f) ,
811
+ }
799
812
}
800
813
}
801
814
@@ -1063,7 +1076,7 @@ mod test {
1063
1076
length,
1064
1077
tree_info
1065
1078
. script_map
1066
- . get( & ( Script :: from_hex( script) . unwrap( ) , LeafVersion :: default ( ) ) )
1079
+ . get( & ( Script :: from_hex( script) . unwrap( ) , LeafVersion :: TapScript ) )
1067
1080
. expect( "Present Key" )
1068
1081
. iter( )
1069
1082
. next( )
@@ -1078,7 +1091,7 @@ mod test {
1078
1091
1079
1092
// Try to create and verify a control block from each path
1080
1093
for ( _weights, script) in script_weights {
1081
- let ver_script = ( script, LeafVersion :: default ( ) ) ;
1094
+ let ver_script = ( script, LeafVersion :: TapScript ) ;
1082
1095
let ctrl_block = tree_info. control_block ( & ver_script) . unwrap ( ) ;
1083
1096
assert ! ( ctrl_block. verify_taproot_commitment( & secp, & output_key, & ver_script. 0 ) )
1084
1097
}
@@ -1114,7 +1127,7 @@ mod test {
1114
1127
let output_key = tree_info. output_key ( ) ;
1115
1128
1116
1129
for script in vec ! [ a, b, c, d, e] {
1117
- let ver_script = ( script, LeafVersion :: default ( ) ) ;
1130
+ let ver_script = ( script, LeafVersion :: TapScript ) ;
1118
1131
let ctrl_block = tree_info. control_block ( & ver_script) . unwrap ( ) ;
1119
1132
assert ! ( ctrl_block. verify_taproot_commitment( & secp, & output_key, & ver_script. 0 ) )
1120
1133
}
@@ -1137,7 +1150,7 @@ mod test {
1137
1150
}
1138
1151
} else {
1139
1152
let script = Script :: from_str ( v[ "script" ] . as_str ( ) . unwrap ( ) ) . unwrap ( ) ;
1140
- let ver = LeafVersion :: from_u8 ( v[ "leafVersion" ] . as_u64 ( ) . unwrap ( ) as u8 ) . unwrap ( ) ;
1153
+ let ver = LeafVersion :: from_consensus ( v[ "leafVersion" ] . as_u64 ( ) . unwrap ( ) as u8 ) . unwrap ( ) ;
1141
1154
leaves. push ( ( script. clone ( ) , ver) ) ;
1142
1155
builder = builder. add_leaf_with_ver ( depth, script, ver) . unwrap ( ) ;
1143
1156
}
0 commit comments