@@ -579,13 +579,13 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
579579 Hash160 ( ref h) => t. hash160 ( h) . map ( Hash160 ) ?,
580580 Older ( ref n) => Older ( * n) ,
581581 After ( ref n) => After ( * n) ,
582- Threshold ( ref k, ref subs) => Threshold ( * k, ( 0 ..subs. len ( ) ) . map ( child_n) . collect ( ) ) ,
583582 And ( ref subs) => And ( ( 0 ..subs. len ( ) ) . map ( child_n) . collect ( ) ) ,
584583 Or ( ref subs) => Or ( subs
585584 . iter ( )
586585 . enumerate ( )
587586 . map ( |( i, ( prob, _) ) | ( * prob, child_n ( i) ) )
588587 . collect ( ) ) ,
588+ Threshold ( ref k, ref subs) => Threshold ( * k, ( 0 ..subs. len ( ) ) . map ( child_n) . collect ( ) ) ,
589589 } ;
590590 translated. push ( Arc :: new ( new_policy) ) ;
591591 }
@@ -605,15 +605,15 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
605605
606606 let new_policy = match data. node . as_ref ( ) {
607607 Policy :: Key ( ref k) if k. clone ( ) == * key => Some ( Policy :: Unsatisfiable ) ,
608- Threshold ( k, ref subs) => {
609- Some ( Threshold ( * k, ( 0 ..subs. len ( ) ) . map ( child_n) . collect ( ) ) )
610- }
611608 And ( ref subs) => Some ( And ( ( 0 ..subs. len ( ) ) . map ( child_n) . collect ( ) ) ) ,
612609 Or ( ref subs) => Some ( Or ( subs
613610 . iter ( )
614611 . enumerate ( )
615612 . map ( |( i, ( prob, _) ) | ( * prob, child_n ( i) ) )
616613 . collect ( ) ) ) ,
614+ Threshold ( k, ref subs) => {
615+ Some ( Threshold ( * k, ( 0 ..subs. len ( ) ) . map ( child_n) . collect ( ) ) )
616+ }
617617 _ => None ,
618618 } ;
619619 match new_policy {
@@ -724,10 +724,6 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
724724 cltv_with_time : false ,
725725 contains_combination : false ,
726726 } ,
727- Threshold ( ref k, subs) => {
728- let iter = ( 0 ..subs. len ( ) ) . map ( info_for_child_n) ;
729- TimelockInfo :: combine_threshold ( * k, iter)
730- }
731727 And ( ref subs) => {
732728 let iter = ( 0 ..subs. len ( ) ) . map ( info_for_child_n) ;
733729 TimelockInfo :: combine_threshold ( subs. len ( ) , iter)
@@ -736,6 +732,10 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
736732 let iter = ( 0 ..subs. len ( ) ) . map ( info_for_child_n) ;
737733 TimelockInfo :: combine_threshold ( 1 , iter)
738734 }
735+ Threshold ( ref k, subs) => {
736+ let iter = ( 0 ..subs. len ( ) ) . map ( info_for_child_n) ;
737+ TimelockInfo :: combine_threshold ( * k, iter)
738+ }
739739 _ => TimelockInfo :: default ( ) ,
740740 } ;
741741 infos. push ( info) ;
@@ -749,59 +749,46 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
749749 /// Validity condition also checks whether there is a possible satisfaction
750750 /// combination of timelocks and heightlocks
751751 pub fn is_valid ( & self ) -> Result < ( ) , PolicyError > {
752+ use Policy :: * ;
753+
752754 self . check_timelocks ( ) ?;
753755 self . check_duplicate_keys ( ) ?;
754- match * self {
755- Policy :: And ( ref subs ) => {
756- if subs . len ( ) != 2 {
757- Err ( PolicyError :: NonBinaryArgAnd )
758- } else {
759- subs . iter ( )
760- . map ( |sub| sub . is_valid ( ) )
761- . collect :: < Result < Vec < ( ) > , PolicyError > > ( ) ? ;
762- Ok ( ( ) )
756+
757+ for policy in self . pre_order_iter ( ) {
758+ match * policy {
759+ After ( n ) => {
760+ if n == absolute :: LockTime :: ZERO . into ( ) {
761+ return Err ( PolicyError :: ZeroTime ) ;
762+ } else if n . to_u32 ( ) > 2u32 . pow ( 31 ) {
763+ return Err ( PolicyError :: TimeTooFar ) ;
764+ }
763765 }
764- }
765- Policy :: Or ( ref subs) => {
766- if subs. len ( ) != 2 {
767- Err ( PolicyError :: NonBinaryArgOr )
768- } else {
769- subs. iter ( )
770- . map ( |( _prob, sub) | sub. is_valid ( ) )
771- . collect :: < Result < Vec < ( ) > , PolicyError > > ( ) ?;
772- Ok ( ( ) )
766+ Older ( n) => {
767+ if n == Sequence :: ZERO {
768+ return Err ( PolicyError :: ZeroTime ) ;
769+ } else if n. to_consensus_u32 ( ) > 2u32 . pow ( 31 ) {
770+ return Err ( PolicyError :: TimeTooFar ) ;
771+ }
773772 }
774- }
775- Policy :: Threshold ( k, ref subs) => {
776- if k == 0 || k > subs. len ( ) {
777- Err ( PolicyError :: IncorrectThresh )
778- } else {
779- subs. iter ( )
780- . map ( |sub| sub. is_valid ( ) )
781- . collect :: < Result < Vec < ( ) > , PolicyError > > ( ) ?;
782- Ok ( ( ) )
773+ And ( ref subs) => {
774+ if subs. len ( ) != 2 {
775+ return Err ( PolicyError :: NonBinaryArgAnd ) ;
776+ }
783777 }
784- }
785- Policy :: After ( n) => {
786- if n == absolute:: LockTime :: ZERO . into ( ) {
787- Err ( PolicyError :: ZeroTime )
788- } else if n. to_u32 ( ) > 2u32 . pow ( 31 ) {
789- Err ( PolicyError :: TimeTooFar )
790- } else {
791- Ok ( ( ) )
778+ Or ( ref subs) => {
779+ if subs. len ( ) != 2 {
780+ return Err ( PolicyError :: NonBinaryArgOr ) ;
781+ }
792782 }
793- }
794- Policy :: Older ( n) => {
795- if n == Sequence :: ZERO {
796- Err ( PolicyError :: ZeroTime )
797- } else if n. to_consensus_u32 ( ) > 2u32 . pow ( 31 ) {
798- Err ( PolicyError :: TimeTooFar )
799- } else {
800- Ok ( ( ) )
783+ Threshold ( k, ref subs) => {
784+ if k == 0 || k > subs. len ( ) {
785+ return Err ( PolicyError :: IncorrectThresh ) ;
786+ }
801787 }
788+ _ => { }
802789 }
803- _ => Ok ( ( ) ) ,
804790 }
791+ Ok ( ( ) )
805792 }
806793
807794 /// Checks if any possible compilation of the policy could be compiled
@@ -812,43 +799,48 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
812799 /// Returns a tuple `(safe, non-malleable)` to avoid the fact that
813800 /// non-malleability depends on safety and we would like to cache results.
814801 pub fn is_safe_nonmalleable ( & self ) -> ( bool , bool ) {
815- match * self {
816- Policy :: Unsatisfiable | Policy :: Trivial => ( true , true ) ,
817- Policy :: Key ( _) => ( true , true ) ,
818- Policy :: Sha256 ( _)
819- | Policy :: Hash256 ( _)
820- | Policy :: Ripemd160 ( _)
821- | Policy :: Hash160 ( _)
822- | Policy :: After ( _)
823- | Policy :: Older ( _) => ( false , true ) ,
824- Policy :: Threshold ( k, ref subs) => {
825- let ( safe_count, non_mall_count) = subs
826- . iter ( )
827- . map ( |sub| sub. is_safe_nonmalleable ( ) )
828- . fold ( ( 0 , 0 ) , |( safe_count, non_mall_count) , ( safe, non_mall) | {
829- ( safe_count + safe as usize , non_mall_count + non_mall as usize )
830- } ) ;
831- (
832- safe_count >= ( subs. len ( ) - k + 1 ) ,
833- non_mall_count == subs. len ( ) && safe_count >= ( subs. len ( ) - k) ,
834- )
835- }
836- Policy :: And ( ref subs) => {
837- let ( atleast_one_safe, all_non_mall) = subs
838- . iter ( )
839- . map ( |sub| sub. is_safe_nonmalleable ( ) )
840- . fold ( ( false , true ) , |acc, x| ( acc. 0 || x. 0 , acc. 1 && x. 1 ) ) ;
841- ( atleast_one_safe, all_non_mall)
842- }
802+ use Policy :: * ;
843803
844- Policy :: Or ( ref subs) => {
845- let ( all_safe, atleast_one_safe, all_non_mall) = subs
846- . iter ( )
847- . map ( |( _, sub) | sub. is_safe_nonmalleable ( ) )
848- . fold ( ( true , false , true ) , |acc, x| ( acc. 0 && x. 0 , acc. 1 || x. 0 , acc. 2 && x. 1 ) ) ;
849- ( all_safe, atleast_one_safe && all_non_mall)
850- }
804+ let mut acc = vec ! [ ] ;
805+ for data in Arc :: new ( self ) . post_order_iter ( ) {
806+ let acc_for_child_n = |n| acc[ data. child_indices [ n] ] ;
807+
808+ let new = match data. node {
809+ Unsatisfiable | Trivial | Key ( _) => ( true , true ) ,
810+ Sha256 ( _) | Hash256 ( _) | Ripemd160 ( _) | Hash160 ( _) | After ( _) | Older ( _) => {
811+ ( false , true )
812+ }
813+ And ( ref subs) => {
814+ let ( atleast_one_safe, all_non_mall) = ( 0 ..subs. len ( ) )
815+ . map ( acc_for_child_n)
816+ . fold ( ( false , true ) , |acc, x : ( bool , bool ) | ( acc. 0 || x. 0 , acc. 1 && x. 1 ) ) ;
817+ ( atleast_one_safe, all_non_mall)
818+ }
819+ Or ( ref subs) => {
820+ let ( all_safe, atleast_one_safe, all_non_mall) = ( 0 ..subs. len ( ) )
821+ . map ( acc_for_child_n)
822+ . fold ( ( true , false , true ) , |acc, x| {
823+ ( acc. 0 && x. 0 , acc. 1 || x. 0 , acc. 2 && x. 1 )
824+ } ) ;
825+ ( all_safe, atleast_one_safe && all_non_mall)
826+ }
827+ Threshold ( k, ref subs) => {
828+ let ( safe_count, non_mall_count) = ( 0 ..subs. len ( ) ) . map ( acc_for_child_n) . fold (
829+ ( 0 , 0 ) ,
830+ |( safe_count, non_mall_count) , ( safe, non_mall) | {
831+ ( safe_count + safe as usize , non_mall_count + non_mall as usize )
832+ } ,
833+ ) ;
834+ (
835+ safe_count >= ( subs. len ( ) - k + 1 ) ,
836+ non_mall_count == subs. len ( ) && safe_count >= ( subs. len ( ) - k) ,
837+ )
838+ }
839+ } ;
840+ acc. push ( new) ;
851841 }
842+ // Ok to unwrap because we know we processed at least one node.
843+ acc. pop ( ) . unwrap ( )
852844 }
853845}
854846
0 commit comments