@@ -86,9 +86,7 @@ mod private {
8686 /// and they can call `Miniscript::clone`.
8787 fn clone ( & self ) -> Self {
8888 let mut stack = vec ! [ ] ;
89- for item in self . post_order_iter ( ) {
90- let child_n = |n| Arc :: clone ( & stack[ item. child_indices [ n] ] ) ;
91-
89+ for item in self . rtl_post_order_iter ( ) {
9290 let new_term = match item. node . node {
9391 Terminal :: PkK ( ref p) => Terminal :: PkK ( p. clone ( ) ) ,
9492 Terminal :: PkH ( ref p) => Terminal :: PkH ( p. clone ( ) ) ,
@@ -101,23 +99,31 @@ mod private {
10199 Terminal :: Hash160 ( ref x) => Terminal :: Hash160 ( x. clone ( ) ) ,
102100 Terminal :: True => Terminal :: True ,
103101 Terminal :: False => Terminal :: False ,
104- Terminal :: Alt ( ..) => Terminal :: Alt ( child_n ( 0 ) ) ,
105- Terminal :: Swap ( ..) => Terminal :: Swap ( child_n ( 0 ) ) ,
106- Terminal :: Check ( ..) => Terminal :: Check ( child_n ( 0 ) ) ,
107- Terminal :: DupIf ( ..) => Terminal :: DupIf ( child_n ( 0 ) ) ,
108- Terminal :: Verify ( ..) => Terminal :: Verify ( child_n ( 0 ) ) ,
109- Terminal :: NonZero ( ..) => Terminal :: NonZero ( child_n ( 0 ) ) ,
110- Terminal :: ZeroNotEqual ( ..) => Terminal :: ZeroNotEqual ( child_n ( 0 ) ) ,
111- Terminal :: AndV ( ..) => Terminal :: AndV ( child_n ( 0 ) , child_n ( 1 ) ) ,
112- Terminal :: AndB ( ..) => Terminal :: AndB ( child_n ( 0 ) , child_n ( 1 ) ) ,
113- Terminal :: AndOr ( ..) => Terminal :: AndOr ( child_n ( 0 ) , child_n ( 1 ) , child_n ( 2 ) ) ,
114- Terminal :: OrB ( ..) => Terminal :: OrB ( child_n ( 0 ) , child_n ( 1 ) ) ,
115- Terminal :: OrD ( ..) => Terminal :: OrD ( child_n ( 0 ) , child_n ( 1 ) ) ,
116- Terminal :: OrC ( ..) => Terminal :: OrC ( child_n ( 0 ) , child_n ( 1 ) ) ,
117- Terminal :: OrI ( ..) => Terminal :: OrI ( child_n ( 0 ) , child_n ( 1 ) ) ,
118- Terminal :: Thresh ( ref thresh) => Terminal :: Thresh (
119- thresh. map_from_post_order_iter ( & item. child_indices , & stack) ,
102+ Terminal :: Alt ( ..) => Terminal :: Alt ( stack. pop ( ) . unwrap ( ) ) ,
103+ Terminal :: Swap ( ..) => Terminal :: Swap ( stack. pop ( ) . unwrap ( ) ) ,
104+ Terminal :: Check ( ..) => Terminal :: Check ( stack. pop ( ) . unwrap ( ) ) ,
105+ Terminal :: DupIf ( ..) => Terminal :: DupIf ( stack. pop ( ) . unwrap ( ) ) ,
106+ Terminal :: Verify ( ..) => Terminal :: Verify ( stack. pop ( ) . unwrap ( ) ) ,
107+ Terminal :: NonZero ( ..) => Terminal :: NonZero ( stack. pop ( ) . unwrap ( ) ) ,
108+ Terminal :: ZeroNotEqual ( ..) => Terminal :: ZeroNotEqual ( stack. pop ( ) . unwrap ( ) ) ,
109+ Terminal :: AndV ( ..) => {
110+ Terminal :: AndV ( stack. pop ( ) . unwrap ( ) , stack. pop ( ) . unwrap ( ) )
111+ }
112+ Terminal :: AndB ( ..) => {
113+ Terminal :: AndB ( stack. pop ( ) . unwrap ( ) , stack. pop ( ) . unwrap ( ) )
114+ }
115+ Terminal :: AndOr ( ..) => Terminal :: AndOr (
116+ stack. pop ( ) . unwrap ( ) ,
117+ stack. pop ( ) . unwrap ( ) ,
118+ stack. pop ( ) . unwrap ( ) ,
120119 ) ,
120+ Terminal :: OrB ( ..) => Terminal :: OrB ( stack. pop ( ) . unwrap ( ) , stack. pop ( ) . unwrap ( ) ) ,
121+ Terminal :: OrD ( ..) => Terminal :: OrD ( stack. pop ( ) . unwrap ( ) , stack. pop ( ) . unwrap ( ) ) ,
122+ Terminal :: OrC ( ..) => Terminal :: OrC ( stack. pop ( ) . unwrap ( ) , stack. pop ( ) . unwrap ( ) ) ,
123+ Terminal :: OrI ( ..) => Terminal :: OrI ( stack. pop ( ) . unwrap ( ) , stack. pop ( ) . unwrap ( ) ) ,
124+ Terminal :: Thresh ( ref thresh) => {
125+ Terminal :: Thresh ( thresh. map_ref ( |_| stack. pop ( ) . unwrap ( ) ) )
126+ }
121127 Terminal :: Multi ( ref thresh) => Terminal :: Multi ( thresh. clone ( ) ) ,
122128 Terminal :: MultiA ( ref thresh) => Terminal :: MultiA ( thresh. clone ( ) ) ,
123129 } ;
@@ -130,6 +136,7 @@ mod private {
130136 } ) ) ;
131137 }
132138
139+ assert_eq ! ( stack. len( ) , 1 ) ;
133140 Arc :: try_unwrap ( stack. pop ( ) . unwrap ( ) ) . unwrap ( )
134141 }
135142 }
@@ -536,9 +543,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
536543 T : Translator < Pk , Q , FuncError > ,
537544 {
538545 let mut translated = vec ! [ ] ;
539- for data in Arc :: new ( self . clone ( ) ) . post_order_iter ( ) {
540- let child_n = |n| Arc :: clone ( & translated[ data. child_indices [ n] ] ) ;
541-
546+ for data in self . rtl_post_order_iter ( ) {
542547 let new_term = match data. node . node {
543548 Terminal :: PkK ( ref p) => Terminal :: PkK ( t. pk ( p) ?) ,
544549 Terminal :: PkH ( ref p) => Terminal :: PkH ( t. pk ( p) ?) ,
@@ -551,23 +556,39 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
551556 Terminal :: Hash160 ( ref x) => Terminal :: Hash160 ( t. hash160 ( x) ?) ,
552557 Terminal :: True => Terminal :: True ,
553558 Terminal :: False => Terminal :: False ,
554- Terminal :: Alt ( ..) => Terminal :: Alt ( child_n ( 0 ) ) ,
555- Terminal :: Swap ( ..) => Terminal :: Swap ( child_n ( 0 ) ) ,
556- Terminal :: Check ( ..) => Terminal :: Check ( child_n ( 0 ) ) ,
557- Terminal :: DupIf ( ..) => Terminal :: DupIf ( child_n ( 0 ) ) ,
558- Terminal :: Verify ( ..) => Terminal :: Verify ( child_n ( 0 ) ) ,
559- Terminal :: NonZero ( ..) => Terminal :: NonZero ( child_n ( 0 ) ) ,
560- Terminal :: ZeroNotEqual ( ..) => Terminal :: ZeroNotEqual ( child_n ( 0 ) ) ,
561- Terminal :: AndV ( ..) => Terminal :: AndV ( child_n ( 0 ) , child_n ( 1 ) ) ,
562- Terminal :: AndB ( ..) => Terminal :: AndB ( child_n ( 0 ) , child_n ( 1 ) ) ,
563- Terminal :: AndOr ( ..) => Terminal :: AndOr ( child_n ( 0 ) , child_n ( 1 ) , child_n ( 2 ) ) ,
564- Terminal :: OrB ( ..) => Terminal :: OrB ( child_n ( 0 ) , child_n ( 1 ) ) ,
565- Terminal :: OrD ( ..) => Terminal :: OrD ( child_n ( 0 ) , child_n ( 1 ) ) ,
566- Terminal :: OrC ( ..) => Terminal :: OrC ( child_n ( 0 ) , child_n ( 1 ) ) ,
567- Terminal :: OrI ( ..) => Terminal :: OrI ( child_n ( 0 ) , child_n ( 1 ) ) ,
568- Terminal :: Thresh ( ref thresh) => Terminal :: Thresh (
569- thresh. map_from_post_order_iter ( & data. child_indices , & translated) ,
559+ Terminal :: Alt ( ..) => Terminal :: Alt ( translated. pop ( ) . unwrap ( ) ) ,
560+ Terminal :: Swap ( ..) => Terminal :: Swap ( translated. pop ( ) . unwrap ( ) ) ,
561+ Terminal :: Check ( ..) => Terminal :: Check ( translated. pop ( ) . unwrap ( ) ) ,
562+ Terminal :: DupIf ( ..) => Terminal :: DupIf ( translated. pop ( ) . unwrap ( ) ) ,
563+ Terminal :: Verify ( ..) => Terminal :: Verify ( translated. pop ( ) . unwrap ( ) ) ,
564+ Terminal :: NonZero ( ..) => Terminal :: NonZero ( translated. pop ( ) . unwrap ( ) ) ,
565+ Terminal :: ZeroNotEqual ( ..) => Terminal :: ZeroNotEqual ( translated. pop ( ) . unwrap ( ) ) ,
566+ Terminal :: AndV ( ..) => {
567+ Terminal :: AndV ( translated. pop ( ) . unwrap ( ) , translated. pop ( ) . unwrap ( ) )
568+ }
569+ Terminal :: AndB ( ..) => {
570+ Terminal :: AndB ( translated. pop ( ) . unwrap ( ) , translated. pop ( ) . unwrap ( ) )
571+ }
572+ Terminal :: AndOr ( ..) => Terminal :: AndOr (
573+ translated. pop ( ) . unwrap ( ) ,
574+ translated. pop ( ) . unwrap ( ) ,
575+ translated. pop ( ) . unwrap ( ) ,
570576 ) ,
577+ Terminal :: OrB ( ..) => {
578+ Terminal :: OrB ( translated. pop ( ) . unwrap ( ) , translated. pop ( ) . unwrap ( ) )
579+ }
580+ Terminal :: OrD ( ..) => {
581+ Terminal :: OrD ( translated. pop ( ) . unwrap ( ) , translated. pop ( ) . unwrap ( ) )
582+ }
583+ Terminal :: OrC ( ..) => {
584+ Terminal :: OrC ( translated. pop ( ) . unwrap ( ) , translated. pop ( ) . unwrap ( ) )
585+ }
586+ Terminal :: OrI ( ..) => {
587+ Terminal :: OrI ( translated. pop ( ) . unwrap ( ) , translated. pop ( ) . unwrap ( ) )
588+ }
589+ Terminal :: Thresh ( ref thresh) => {
590+ Terminal :: Thresh ( thresh. map_ref ( |_| translated. pop ( ) . unwrap ( ) ) )
591+ }
571592 Terminal :: Multi ( ref thresh) => Terminal :: Multi ( thresh. translate_ref ( |k| t. pk ( k) ) ?) ,
572593 Terminal :: MultiA ( ref thresh) => {
573594 Terminal :: MultiA ( thresh. translate_ref ( |k| t. pk ( k) ) ?)
@@ -582,22 +603,58 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
582603
583604 /// Substitutes raw public keys hashes with the public keys as provided by map.
584605 pub fn substitute_raw_pkh ( & self , pk_map : & BTreeMap < hash160:: Hash , Pk > ) -> Miniscript < Pk , Ctx > {
585- let mut translated = vec ! [ ] ;
586- for data in Arc :: new ( self . clone ( ) ) . post_order_iter ( ) {
587- let new_term = if let Terminal :: RawPkH ( ref p) = data. node . node {
588- match pk_map. get ( p) {
589- Some ( pk) => Terminal :: PkH ( pk. clone ( ) ) ,
590- None => Terminal :: RawPkH ( * p) ,
606+ let mut stack = vec ! [ ] ;
607+ for item in self . rtl_post_order_iter ( ) {
608+ let new_term = match item. node . node {
609+ Terminal :: PkK ( ref p) => Terminal :: PkK ( p. clone ( ) ) ,
610+ Terminal :: PkH ( ref p) => Terminal :: PkH ( p. clone ( ) ) ,
611+ // This algorithm is identical to Clone::clone except for this line.
612+ Terminal :: RawPkH ( ref hash) => match pk_map. get ( hash) {
613+ Some ( p) => Terminal :: PkH ( p. clone ( ) ) ,
614+ None => Terminal :: RawPkH ( * hash) ,
615+ } ,
616+ Terminal :: After ( ref n) => Terminal :: After ( * n) ,
617+ Terminal :: Older ( ref n) => Terminal :: Older ( * n) ,
618+ Terminal :: Sha256 ( ref x) => Terminal :: Sha256 ( x. clone ( ) ) ,
619+ Terminal :: Hash256 ( ref x) => Terminal :: Hash256 ( x. clone ( ) ) ,
620+ Terminal :: Ripemd160 ( ref x) => Terminal :: Ripemd160 ( x. clone ( ) ) ,
621+ Terminal :: Hash160 ( ref x) => Terminal :: Hash160 ( x. clone ( ) ) ,
622+ Terminal :: True => Terminal :: True ,
623+ Terminal :: False => Terminal :: False ,
624+ Terminal :: Alt ( ..) => Terminal :: Alt ( stack. pop ( ) . unwrap ( ) ) ,
625+ Terminal :: Swap ( ..) => Terminal :: Swap ( stack. pop ( ) . unwrap ( ) ) ,
626+ Terminal :: Check ( ..) => Terminal :: Check ( stack. pop ( ) . unwrap ( ) ) ,
627+ Terminal :: DupIf ( ..) => Terminal :: DupIf ( stack. pop ( ) . unwrap ( ) ) ,
628+ Terminal :: Verify ( ..) => Terminal :: Verify ( stack. pop ( ) . unwrap ( ) ) ,
629+ Terminal :: NonZero ( ..) => Terminal :: NonZero ( stack. pop ( ) . unwrap ( ) ) ,
630+ Terminal :: ZeroNotEqual ( ..) => Terminal :: ZeroNotEqual ( stack. pop ( ) . unwrap ( ) ) ,
631+ Terminal :: AndV ( ..) => Terminal :: AndV ( stack. pop ( ) . unwrap ( ) , stack. pop ( ) . unwrap ( ) ) ,
632+ Terminal :: AndB ( ..) => Terminal :: AndB ( stack. pop ( ) . unwrap ( ) , stack. pop ( ) . unwrap ( ) ) ,
633+ Terminal :: AndOr ( ..) => Terminal :: AndOr (
634+ stack. pop ( ) . unwrap ( ) ,
635+ stack. pop ( ) . unwrap ( ) ,
636+ stack. pop ( ) . unwrap ( ) ,
637+ ) ,
638+ Terminal :: OrB ( ..) => Terminal :: OrB ( stack. pop ( ) . unwrap ( ) , stack. pop ( ) . unwrap ( ) ) ,
639+ Terminal :: OrD ( ..) => Terminal :: OrD ( stack. pop ( ) . unwrap ( ) , stack. pop ( ) . unwrap ( ) ) ,
640+ Terminal :: OrC ( ..) => Terminal :: OrC ( stack. pop ( ) . unwrap ( ) , stack. pop ( ) . unwrap ( ) ) ,
641+ Terminal :: OrI ( ..) => Terminal :: OrI ( stack. pop ( ) . unwrap ( ) , stack. pop ( ) . unwrap ( ) ) ,
642+ Terminal :: Thresh ( ref thresh) => {
643+ Terminal :: Thresh ( thresh. map_ref ( |_| stack. pop ( ) . unwrap ( ) ) )
591644 }
592- } else {
593- data . node . node . clone ( )
645+ Terminal :: Multi ( ref thresh ) => Terminal :: Multi ( thresh . clone ( ) ) ,
646+ Terminal :: MultiA ( ref thresh ) => Terminal :: MultiA ( thresh . clone ( ) ) ,
594647 } ;
595648
596- let new_ms = Miniscript :: from_ast ( new_term) . expect ( "typeck" ) ;
597- translated. push ( Arc :: new ( new_ms) ) ;
649+ stack. push ( Arc :: new ( Miniscript :: from_components_unchecked (
650+ new_term,
651+ item. node . ty ,
652+ item. node . ext ,
653+ ) ) ) ;
598654 }
599655
600- Arc :: try_unwrap ( translated. pop ( ) . unwrap ( ) ) . unwrap ( )
656+ assert_eq ! ( stack. len( ) , 1 ) ;
657+ Arc :: try_unwrap ( stack. pop ( ) . unwrap ( ) ) . unwrap ( )
601658 }
602659}
603660
@@ -822,6 +879,7 @@ mod tests {
822879 }
823880 let roundtrip = Miniscript :: from_str ( & display) . expect ( "parse string serialization" ) ;
824881 assert_eq ! ( roundtrip, script) ;
882+ assert_eq ! ( roundtrip. clone( ) , script) ;
825883 }
826884
827885 fn string_display_debug_test < Ctx : ScriptContext > (
0 commit comments