@@ -20,7 +20,7 @@ use bitcoin::util::taproot::{ControlBlock, TAPROOT_ANNEX_PREFIX};
2020
2121use { BareCtx , Legacy , Segwitv0 , Tap } ;
2222
23- use super :: { stack, BitcoinKey , Error , Stack , TaggedHash160 } ;
23+ use super :: { stack, BitcoinKey , Error , Stack , TypedHash160 } ;
2424use miniscript:: context:: { NoChecks , ScriptContext } ;
2525use { Miniscript , MiniscriptKey } ;
2626
@@ -186,7 +186,7 @@ pub(super) fn from_txdata<'txin>(
186186 Some ( elem) => {
187187 let miniscript = script_from_stackelem :: < Segwitv0 > ( & elem) ?;
188188 let script = miniscript. encode ( ) ;
189- let miniscript = pre_taproot_to_no_checks ( & miniscript) ;
189+ let miniscript = miniscript. to_no_checks_ms ( ) ;
190190 let scripthash = sha256:: Hash :: hash ( & script[ ..] ) ;
191191 if * spk == bitcoin:: Script :: new_v0_p2wsh ( & scripthash. into ( ) ) {
192192 Ok ( (
@@ -230,7 +230,7 @@ pub(super) fn from_txdata<'txin>(
230230 let ctrl_blk = ControlBlock :: from_slice ( ctrl_blk)
231231 . map_err ( |e| Error :: ControlBlockParse ( e) ) ?;
232232 let tap_script = script_from_stackelem :: < Tap > ( & tap_script) ?;
233- let ms = taproot_to_no_checks ( & tap_script) ;
233+ let ms = tap_script. to_no_checks_ms ( ) ;
234234 // Creating new contexts is cheap
235235 let secp = bitcoin:: secp256k1:: Secp256k1 :: verification_only ( ) ;
236236 let tap_script = tap_script. encode ( ) ;
@@ -306,7 +306,7 @@ pub(super) fn from_txdata<'txin>(
306306 // parse wsh with Segwitv0 context
307307 let miniscript = script_from_stackelem :: < Segwitv0 > ( & elem) ?;
308308 let script = miniscript. encode ( ) ;
309- let miniscript = pre_taproot_to_no_checks ( & miniscript) ;
309+ let miniscript = miniscript. to_no_checks_ms ( ) ;
310310 let scripthash = sha256:: Hash :: hash ( & script[ ..] ) ;
311311 if slice
312312 == & bitcoin:: Script :: new_v0_p2wsh ( & scripthash. into ( ) ) [ ..]
@@ -328,7 +328,7 @@ pub(super) fn from_txdata<'txin>(
328328 // normal p2sh parsed in Legacy context
329329 let miniscript = script_from_stackelem :: < Legacy > ( & elem) ?;
330330 let script = miniscript. encode ( ) ;
331- let miniscript = pre_taproot_to_no_checks ( & miniscript) ;
331+ let miniscript = miniscript. to_no_checks_ms ( ) ;
332332 if wit_stack. is_empty ( ) {
333333 let scripthash = hash160:: Hash :: hash ( & script[ ..] ) ;
334334 if * spk == bitcoin:: Script :: new_p2sh ( & scripthash. into ( ) ) {
@@ -351,7 +351,7 @@ pub(super) fn from_txdata<'txin>(
351351 if wit_stack. is_empty ( ) {
352352 // Bare script parsed in BareCtx
353353 let miniscript = Miniscript :: < bitcoin:: PublicKey , BareCtx > :: parse_insane ( spk) ?;
354- let miniscript = pre_taproot_to_no_checks ( & miniscript) ;
354+ let miniscript = miniscript. to_no_checks_ms ( ) ;
355355 Ok ( (
356356 Inner :: Script ( miniscript, ScriptType :: Bare ) ,
357357 ssig_stack,
@@ -363,29 +363,39 @@ pub(super) fn from_txdata<'txin>(
363363 }
364364}
365365
366- // Convert a miniscript from a specified context into an insane miniscript
367- // We need to remember how the hash160 was translated because while doing a checksig
368- // we need to know whether to parse the public key provided in witness as x-only or full
369- pub ( super ) fn pre_taproot_to_no_checks < Ctx : ScriptContext > (
370- ms : & Miniscript < bitcoin :: PublicKey , Ctx > ,
371- ) -> Miniscript < BitcoinKey , NoChecks > {
372- // specify the () error type as this cannot error
373- ms . real_translate_pk :: < _ , _ , _ , ( ) , _ > ( & mut |pk| Ok ( BitcoinKey :: Fullkey ( * pk ) ) , & mut |pkh| {
374- Ok ( TaggedHash160 :: FullKey ( * pkh ) )
375- } )
376- . expect ( "Translation should succeed" )
366+ // Convert a miniscript from a well-defined context to a no checks context.
367+ // We need to parse insane scripts because these scripts are obtained from already
368+ // created transaction possibly already confirmed in a block.
369+ // In order to avoid code duplication for various contexts related interpreter checks,
370+ // we convert all the scripts to from a well-defined context to NoContexts.
371+ //
372+ // While executing Pkh(<hash>) in NoChecks, we need to pop a public key from stack
373+ // However, NoChecks context does not know whether to parse the key as 33 bytes or 32 bytes
374+ // While converting into NoChecks we store explicitly in TypedHash160 enum.
375+ pub ( super ) trait ToNoChecks {
376+ fn to_no_checks_ms ( & self ) -> Miniscript < BitcoinKey , NoChecks > ;
377377}
378378
379- // Convert a miniscript from a specified context into an insane miniscript
380- pub ( super ) fn taproot_to_no_checks < Ctx : ScriptContext > (
381- ms : & Miniscript < bitcoin:: XOnlyPublicKey , Ctx > ,
382- ) -> Miniscript < BitcoinKey , NoChecks > {
383- // specify the () error type as this cannot error
384- ms. real_translate_pk :: < _ , _ , _ , ( ) , _ > (
385- & mut |xpk| Ok ( BitcoinKey :: XOnlyPublicKey ( * xpk) ) ,
386- & mut |pkh| Ok ( TaggedHash160 :: XonlyKey ( * pkh) ) ,
387- )
388- . expect ( "Translation should succeed" )
379+ impl < Ctx : ScriptContext > ToNoChecks for Miniscript < bitcoin:: PublicKey , Ctx > {
380+ fn to_no_checks_ms ( & self ) -> Miniscript < BitcoinKey , NoChecks > {
381+ // specify the () error type as this cannot error
382+ self . real_translate_pk :: < _ , _ , _ , ( ) , _ > (
383+ & mut |pk| Ok ( BitcoinKey :: Fullkey ( * pk) ) ,
384+ & mut |pkh| Ok ( TypedHash160 :: FullKey ( * pkh) ) ,
385+ )
386+ . expect ( "Translation should succeed" )
387+ }
388+ }
389+
390+ impl < Ctx : ScriptContext > ToNoChecks for Miniscript < bitcoin:: XOnlyPublicKey , Ctx > {
391+ fn to_no_checks_ms ( & self ) -> Miniscript < BitcoinKey , NoChecks > {
392+ // specify the () error type as this cannot error
393+ self . real_translate_pk :: < _ , _ , _ , ( ) , _ > (
394+ & mut |xpk| Ok ( BitcoinKey :: XOnlyPublicKey ( * xpk) ) ,
395+ & mut |pkh| Ok ( TypedHash160 :: XonlyKey ( * pkh) ) ,
396+ )
397+ . expect ( "Translation should succeed" )
398+ }
389399}
390400
391401#[ cfg( test) ]
@@ -737,7 +747,7 @@ mod tests {
737747 fn ms_inner_script ( ms : & str ) -> ( Miniscript < BitcoinKey , NoChecks > , bitcoin:: Script ) {
738748 let ms = Miniscript :: < bitcoin:: PublicKey , Segwitv0 > :: from_str_insane ( ms) . unwrap ( ) ;
739749 let spk = ms. encode ( ) ;
740- let miniscript = pre_taproot_to_no_checks ( & ms ) ;
750+ let miniscript = ms . to_no_checks_ms ( ) ;
741751 ( miniscript, spk)
742752 }
743753 #[ test]
0 commit comments