@@ -94,10 +94,11 @@ pub enum Prevouts<'u> {
94
94
const KEY_VERSION_0 : u8 = 0u8 ;
95
95
96
96
/// Information related to the script path spending
97
+ ///
98
+ /// This can be hashed into a [`TapLeafHash`].
97
99
#[ derive( Clone , PartialEq , Eq , PartialOrd , Ord , Hash , Debug ) ]
98
100
pub struct ScriptPath < ' s > {
99
101
script : & ' s Script ,
100
- code_separator_pos : u32 ,
101
102
leaf_version : LeafVersion ,
102
103
}
103
104
@@ -220,16 +221,30 @@ impl<'u> Prevouts<'u> {
220
221
221
222
impl < ' s > ScriptPath < ' s > {
222
223
/// Create a new ScriptPath structure
223
- pub fn new ( script : & ' s Script , code_separator_pos : u32 , leaf_version : LeafVersion ) -> Self {
224
+ pub fn new ( script : & ' s Script , leaf_version : LeafVersion ) -> Self {
224
225
ScriptPath {
225
226
script,
226
- code_separator_pos,
227
227
leaf_version,
228
228
}
229
229
}
230
- /// Create a new ScriptPath structure using default values for `code_separator_pos` and `leaf_version`
230
+ /// Create a new ScriptPath structure using default leaf version value
231
231
pub fn with_defaults ( script : & ' s Script ) -> Self {
232
- Self :: new ( script, 0xFFFFFFFFu32 , LeafVersion :: default ( ) )
232
+ Self :: new ( script, LeafVersion :: default ( ) )
233
+ }
234
+ /// Compute the leaf hash
235
+ pub fn leaf_hash ( & self ) -> TapLeafHash {
236
+ let mut enc = TapLeafHash :: engine ( ) ;
237
+
238
+ self . leaf_version . as_u8 ( ) . consensus_encode ( & mut enc) . expect ( "Writing to hash enging should never fail" ) ;
239
+ self . script . consensus_encode ( & mut enc) . expect ( "Writing to hash enging should never fail" ) ;
240
+
241
+ TapLeafHash :: from_engine ( enc)
242
+ }
243
+ }
244
+
245
+ impl < ' s > From < ScriptPath < ' s > > for TapLeafHash {
246
+ fn from ( script_path : ScriptPath < ' s > ) -> TapLeafHash {
247
+ script_path. leaf_hash ( )
233
248
}
234
249
}
235
250
@@ -298,7 +313,7 @@ impl<R: Deref<Target = Transaction>> SigHashCache<R> {
298
313
input_index : usize ,
299
314
prevouts : & Prevouts ,
300
315
annex : Option < Annex > ,
301
- script_path : Option < ScriptPath > ,
316
+ leaf_hash_code_separator : Option < ( TapLeafHash , u32 ) > ,
302
317
sighash_type : SchnorrSigHashType ,
303
318
) -> Result < ( ) , Error > {
304
319
prevouts. check_all ( & self . tx ) ?;
@@ -350,7 +365,7 @@ impl<R: Deref<Target = Transaction>> SigHashCache<R> {
350
365
if annex. is_some ( ) {
351
366
spend_type |= 1u8 ;
352
367
}
353
- if script_path . is_some ( ) {
368
+ if leaf_hash_code_separator . is_some ( ) {
354
369
spend_type |= 2u8 ;
355
370
}
356
371
spend_type. consensus_encode ( & mut writer) ?;
@@ -412,17 +427,7 @@ impl<R: Deref<Target = Transaction>> SigHashCache<R> {
412
427
// ss += TaggedHash("TapLeaf", bytes([leaf_ver]) + ser_string(script))
413
428
// ss += bytes([0])
414
429
// ss += struct.pack("<i", codeseparator_pos)
415
- if let Some ( ScriptPath {
416
- script,
417
- leaf_version,
418
- code_separator_pos,
419
- } ) = script_path
420
- {
421
- let mut enc = TapLeafHash :: engine ( ) ;
422
- leaf_version. as_u8 ( ) . consensus_encode ( & mut enc) ?;
423
- script. consensus_encode ( & mut enc) ?;
424
- let hash = TapLeafHash :: from_engine ( enc) ;
425
-
430
+ if let Some ( ( hash, code_separator_pos) ) = leaf_hash_code_separator {
426
431
hash. into_inner ( ) . consensus_encode ( & mut writer) ?;
427
432
KEY_VERSION_0 . consensus_encode ( & mut writer) ?;
428
433
code_separator_pos. consensus_encode ( & mut writer) ?;
@@ -437,7 +442,7 @@ impl<R: Deref<Target = Transaction>> SigHashCache<R> {
437
442
input_index : usize ,
438
443
prevouts : & Prevouts ,
439
444
annex : Option < Annex > ,
440
- script_path : Option < ScriptPath > ,
445
+ leaf_hash_code_separator : Option < ( TapLeafHash , u32 ) > ,
441
446
sighash_type : SchnorrSigHashType ,
442
447
) -> Result < TapSighashHash , Error > {
443
448
let mut enc = TapSighashHash :: engine ( ) ;
@@ -446,7 +451,49 @@ impl<R: Deref<Target = Transaction>> SigHashCache<R> {
446
451
input_index,
447
452
prevouts,
448
453
annex,
449
- script_path,
454
+ leaf_hash_code_separator,
455
+ sighash_type,
456
+ ) ?;
457
+ Ok ( TapSighashHash :: from_engine ( enc) )
458
+ }
459
+
460
+ /// Compute the BIP341 sighash for a key spend
461
+ pub fn taproot_key_spend_signature_hash (
462
+ & mut self ,
463
+ input_index : usize ,
464
+ prevouts : & Prevouts ,
465
+ sighash_type : SchnorrSigHashType ,
466
+ ) -> Result < TapSighashHash , Error > {
467
+ let mut enc = TapSighashHash :: engine ( ) ;
468
+ self . taproot_encode_signing_data_to (
469
+ & mut enc,
470
+ input_index,
471
+ prevouts,
472
+ None ,
473
+ None ,
474
+ sighash_type,
475
+ ) ?;
476
+ Ok ( TapSighashHash :: from_engine ( enc) )
477
+ }
478
+
479
+ /// Compute the BIP341 sighash for a script spend
480
+ ///
481
+ /// Assumes the default `OP_CODESEPARATOR` position of `0xFFFFFFFF`. Custom values can be
482
+ /// provided through the more fine-grained API of [`SigHashCache::taproot_encode_signing_data_to`].
483
+ pub fn taproot_script_spend_signature_hash < S : Into < TapLeafHash > > (
484
+ & mut self ,
485
+ input_index : usize ,
486
+ prevouts : & Prevouts ,
487
+ leaf_hash : S ,
488
+ sighash_type : SchnorrSigHashType ,
489
+ ) -> Result < TapSighashHash , Error > {
490
+ let mut enc = TapSighashHash :: engine ( ) ;
491
+ self . taproot_encode_signing_data_to (
492
+ & mut enc,
493
+ input_index,
494
+ prevouts,
495
+ None ,
496
+ Some ( ( leaf_hash. into ( ) , 0xFFFFFFFF ) ) ,
450
497
sighash_type,
451
498
) ?;
452
499
Ok ( TapSighashHash :: from_engine ( enc) )
@@ -703,7 +750,7 @@ mod tests {
703
750
use consensus:: deserialize;
704
751
use hashes:: hex:: FromHex ;
705
752
use hashes:: { Hash , HashEngine } ;
706
- use util:: sighash:: { Annex , Error , Prevouts , ScriptPath , SigHashCache } ;
753
+ use util:: sighash:: { Annex , Error , Prevouts , ScriptPath , SigHashCache , TapLeafHash } ;
707
754
use util:: taproot:: TapSighashHash ;
708
755
use { Script , Transaction , TxIn , TxOut } ;
709
756
@@ -728,55 +775,55 @@ mod tests {
728
775
"01365724000000000023542156b39dab4f8f3508e0432cfb41fab110170acaa2d4c42539cb90a4dc7c093bc500" ,
729
776
0 ,
730
777
"33ca0ebfb4a945eeee9569fc0f5040221275f88690b7f8592ada88ce3bdf6703" ,
731
- SchnorrSigHashType :: Default , None , None ,
778
+ SchnorrSigHashType :: Default , None , None , None
732
779
) ;
733
780
734
781
test_taproot_sighash (
735
782
"0200000002fff49be59befe7566050737910f6ccdc5e749c7f8860ddc140386463d88c5ad0f3000000002cf68eb4a3d67f9d4c079249f7e4f27b8854815cb1ed13842d4fbf395f9e217fd605ee24090100000065235d9203f458520000000000160014b6d48333bb13b4c644e57c43a9a26df3a44b785e58020000000000001976a914eea9461a9e1e3f765d3af3e726162e0229fe3eb688ac58020000000000001976a9143a8869c9f2b5ea1d4ff3aeeb6a8fb2fffb1ad5fe88ac0ad7125c" ,
736
783
"02591f220000000000225120f25ad35583ea31998d968871d7de1abd2a52f6fe4178b54ea158274806ff4ece48fb310000000000225120f25ad35583ea31998d968871d7de1abd2a52f6fe4178b54ea158274806ff4ece" ,
737
784
1 ,
738
785
"626ab955d58c9a8a600a0c580549d06dc7da4e802eb2a531f62a588e430967a8" ,
739
- SchnorrSigHashType :: All , None , None ,
786
+ SchnorrSigHashType :: All , None , None , None
740
787
) ;
741
788
742
789
test_taproot_sighash (
743
790
"0200000001350005f65aa830ced2079df348e2d8c2bdb4f10e2dde6a161d8a07b40d1ad87dae000000001611d0d603d9dc0e000000000017a914459b6d7d6bbb4d8837b4bf7e9a4556f952da2f5c8758020000000000001976a9141dd70e1299ffc2d5b51f6f87de9dfe9398c33cbb88ac58020000000000001976a9141dd70e1299ffc2d5b51f6f87de9dfe9398c33cbb88aca71c1f4f" ,
744
791
"01c4811000000000002251201bf9297d0a2968ae6693aadd0fa514717afefd218087a239afb7418e2d22e65c" ,
745
792
0 ,
746
793
"dfa9437f9c9a1d1f9af271f79f2f5482f287cdb0d2e03fa92c8a9b216cc6061c" ,
747
- SchnorrSigHashType :: AllPlusAnyoneCanPay , None , None ,
794
+ SchnorrSigHashType :: AllPlusAnyoneCanPay , None , None , None
748
795
) ;
749
796
750
797
test_taproot_sighash (
751
798
"020000000185bed1a6da2bffbd60ec681a1bfb71c5111d6395b99b3f8b2bf90167111bcb18f5010000007c83ace802ded24a00000000001600142c4698f9f7a773866879755aa78c516fb332af8e5802000000000000160014d38639dfbac4259323b98a472405db0c461b31fa61073747" ,
752
799
"0144c84d0000000000225120e3f2107989c88e67296ab2faca930efa2e3a5bd3ff0904835a11c9e807458621" ,
753
800
0 ,
754
801
"3129de36a5d05fff97ffca31eb75fcccbbbc27b3147a7a36a9e4b45d8b625067" ,
755
- SchnorrSigHashType :: None , None , None ,
802
+ SchnorrSigHashType :: None , None , None , None
756
803
) ;
757
804
758
805
test_taproot_sighash (
759
806
"eb93dbb901028c8515589dac980b6e7f8e4088b77ed866ca0d6d210a7218b6fd0f6b22dd6d7300000000eb4740a9047efc0e0000000000160014913da2128d8fcf292b3691db0e187414aa1783825802000000000000160014913da2128d8fcf292b3691db0e187414aa178382580200000000000017a9143dd27f01c6f7ef9bb9159937b17f17065ed01a0c875802000000000000160014d7630e19df70ada9905ede1722b800c0005f246641000000" ,
760
807
"013fed110000000000225120eb536ae8c33580290630fc495046e998086a64f8f33b93b07967d9029b265c55" ,
761
808
0 ,
762
809
"2441e8b0e063a2083ee790f14f2045022f07258ddde5ee01de543c9e789d80ae" ,
763
- SchnorrSigHashType :: NonePlusAnyoneCanPay , None , None ,
810
+ SchnorrSigHashType :: NonePlusAnyoneCanPay , None , None , None
764
811
) ;
765
812
766
813
test_taproot_sighash (
767
814
"02000000017836b409a5fed32211407e44b971591f2032053f14701fb5b3a30c0ff382f2cc9c0100000061ac55f60288fb5600000000001976a9144ea02f6f182b082fb6ce47e36bbde390b6a41b5088ac58020000000000001976a9144ea02f6f182b082fb6ce47e36bbde390b6a41b5088ace4000000" ,
768
815
"01efa558000000000022512007071ea3dc7e331b0687d0193d1e6d6ed10e645ef36f10ef8831d5e522ac9e80" ,
769
816
0 ,
770
817
"30239345177cadd0e3ea413d49803580abb6cb27971b481b7788a78d35117a88" ,
771
- SchnorrSigHashType :: Single , None , None ,
818
+ SchnorrSigHashType :: Single , None , None , None
772
819
) ;
773
820
774
821
test_taproot_sighash (
775
822
"0100000001aa6deae89d5e0aaca58714fc76ef6f3c8284224888089232d4e663843ed3ab3eae010000008b6657a60450cb4c0000000000160014a3d42b5413ef0c0701c4702f3cd7d4df222c147058020000000000001976a91430b4ed8723a4ee8992aa2c8814cfe5c3ad0ab9d988ac5802000000000000160014365b1166a6ed0a5e8e9dff17a6d00bbb43454bc758020000000000001976a914bc98c51a84fe7fad5dc380eb8b39586eff47241688ac4f313247" ,
776
823
"0107af4e00000000002251202c36d243dfc06cb56a248e62df27ecba7417307511a81ae61aa41c597a929c69" ,
777
824
0 ,
778
825
"bf9c83f26c6dd16449e4921f813f551c4218e86f2ec906ca8611175b41b566df" ,
779
- SchnorrSigHashType :: SinglePlusAnyoneCanPay , None , None ,
826
+ SchnorrSigHashType :: SinglePlusAnyoneCanPay , None , None , None
780
827
) ;
781
828
}
782
829
@@ -790,6 +837,7 @@ mod tests {
790
837
SchnorrSigHashType :: SinglePlusAnyoneCanPay ,
791
838
Some ( "507b979802e62d397acb29f56743a791894b99372872fc5af06a4f6e8d242d0615cda53062bb20e6ec79756fe39183f0c128adfe85559a8fa042b042c018aa8010143799e44f0893c40e1e" ) ,
792
839
None ,
840
+ None ,
793
841
) ;
794
842
}
795
843
@@ -803,6 +851,21 @@ mod tests {
803
851
SchnorrSigHashType :: All ,
804
852
None ,
805
853
Some ( "20cc4e1107aea1d170c5ff5b6817e1303010049724fb3caa7941792ea9d29b3e2bacab" ) ,
854
+ None ,
855
+ ) ;
856
+ }
857
+
858
+ #[ test]
859
+ fn test_sighashes_with_script_path_raw_hash ( ) {
860
+ test_taproot_sighash (
861
+ "020000000189fc651483f9296b906455dd939813bf086b1bbe7c77635e157c8e14ae29062195010000004445b5c7044561320000000000160014331414dbdada7fb578f700f38fb69995fc9b5ab958020000000000001976a914268db0a8104cc6d8afd91233cc8b3d1ace8ac3ef88ac580200000000000017a914ec00dcb368d6a693e11986d265f659d2f59e8be2875802000000000000160014c715799a49a0bae3956df9c17cb4440a673ac0df6f010000" ,
862
+ "011bec34000000000022512028055142ea437db73382e991861446040b61dd2185c4891d7daf6893d79f7182" ,
863
+ 0 ,
864
+ "d66de5274a60400c7b08c86ba6b7f198f40660079edf53aca89d2a9501317f2e" ,
865
+ SchnorrSigHashType :: All ,
866
+ None ,
867
+ None ,
868
+ Some ( "15a2530514e399f8b5cf0b3d3112cf5b289eaa3e308ba2071b58392fdc6da68a" ) ,
806
869
) ;
807
870
}
808
871
@@ -816,6 +879,7 @@ mod tests {
816
879
SchnorrSigHashType :: All ,
817
880
Some ( "50a6272b470e1460e3332ade7bb14b81671c564fb6245761bd5bd531394b28860e0b3808ab229fb51791fb6ae6fa82d915b2efb8f6df83ae1f5ab3db13e30928875e2a22b749d89358de481f19286cd4caa792ce27f9559082d227a731c5486882cc707f83da361c51b7aadd9a0cf68fe7480c410fa137b454482d9a1ebf0f96d760b4d61426fc109c6e8e99a508372c45caa7b000a41f8251305da3f206c1849985ba03f3d9592832b4053afbd23ab25d0465df0bc25a36c223aacf8e04ec736a418c72dc319e4da3e972e349713ca600965e7c665f2090d5a70e241ac164115a1f5639f28b1773327715ca307ace64a2de7f0e3df70a2ffee3857689f909c0dad46d8a20fa373a4cc6eed6d4c9806bf146f0d76baae1" ) ,
818
881
Some ( "7520ab9160dd8299dc1367659be3e8f66781fe440d52940c7f8d314a89b9f2698d406ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac" ) ,
882
+ None ,
819
883
) ;
820
884
}
821
885
@@ -888,6 +952,7 @@ mod tests {
888
952
sighash_type : SchnorrSigHashType ,
889
953
annex_hex : Option < & str > ,
890
954
script_hex : Option < & str > ,
955
+ script_leaf_hash : Option < & str > ,
891
956
) {
892
957
let tx_bytes = Vec :: from_hex ( tx_hex) . unwrap ( ) ;
893
958
let tx: Transaction = deserialize ( & tx_bytes) . unwrap ( ) ;
@@ -902,14 +967,18 @@ mod tests {
902
967
None => None ,
903
968
} ;
904
969
905
- let script_inner;
906
- let script_path = match script_hex {
907
- Some ( script_hex) => {
908
- script_inner = Script :: from_hex ( script_hex) . unwrap ( ) ;
909
- Some ( ScriptPath :: with_defaults ( & script_inner) )
970
+ let leaf_hash = match ( script_hex, script_leaf_hash) {
971
+ ( Some ( script_hex) , _) => {
972
+ let script_inner = Script :: from_hex ( script_hex) . unwrap ( ) ;
973
+ Some ( ScriptPath :: with_defaults ( & script_inner) . leaf_hash ( ) )
910
974
}
911
- None => None ,
975
+ ( _, Some ( script_leaf_hash) ) => {
976
+ Some ( TapLeafHash :: from_hex ( script_leaf_hash) . unwrap ( ) )
977
+ }
978
+ _ => None ,
912
979
} ;
980
+ // All our tests use the default `0xFFFFFFFF` codeseparator value
981
+ let leaf_hash = leaf_hash. map ( |lh| ( lh, 0xFFFFFFFF ) ) ;
913
982
914
983
let prevouts = if sighash_type. split_anyonecanpay_flag ( ) . 1 && tx_bytes[ 0 ] % 2 == 0 {
915
984
// for anyonecanpay the `Prevouts::All` variant is good anyway, but sometimes we want to
@@ -922,7 +991,7 @@ mod tests {
922
991
let mut sig_hash_cache = SigHashCache :: new ( & tx) ;
923
992
924
993
let hash = sig_hash_cache
925
- . taproot_signature_hash ( input_index, & prevouts, annex, script_path , sighash_type)
994
+ . taproot_signature_hash ( input_index, & prevouts, annex, leaf_hash , sighash_type)
926
995
. unwrap ( ) ;
927
996
let expected = Vec :: from_hex ( expected_hash) . unwrap ( ) ;
928
997
assert_eq ! ( expected, hash. into_inner( ) ) ;
0 commit comments