@@ -579,13 +579,13 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
579
579
Hash160 ( ref h) => t. hash160 ( h) . map ( Hash160 ) ?,
580
580
Older ( ref n) => Older ( * n) ,
581
581
After ( ref n) => After ( * n) ,
582
- Threshold ( ref k, ref subs) => Threshold ( * k, ( 0 ..subs. len ( ) ) . map ( child_n) . collect ( ) ) ,
583
582
And ( ref subs) => And ( ( 0 ..subs. len ( ) ) . map ( child_n) . collect ( ) ) ,
584
583
Or ( ref subs) => Or ( subs
585
584
. iter ( )
586
585
. enumerate ( )
587
586
. map ( |( i, ( prob, _) ) | ( * prob, child_n ( i) ) )
588
587
. collect ( ) ) ,
588
+ Threshold ( ref k, ref subs) => Threshold ( * k, ( 0 ..subs. len ( ) ) . map ( child_n) . collect ( ) ) ,
589
589
} ;
590
590
translated. push ( Arc :: new ( new_policy) ) ;
591
591
}
@@ -605,15 +605,15 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
605
605
606
606
let new_policy = match data. node . as_ref ( ) {
607
607
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
- }
611
608
And ( ref subs) => Some ( And ( ( 0 ..subs. len ( ) ) . map ( child_n) . collect ( ) ) ) ,
612
609
Or ( ref subs) => Some ( Or ( subs
613
610
. iter ( )
614
611
. enumerate ( )
615
612
. map ( |( i, ( prob, _) ) | ( * prob, child_n ( i) ) )
616
613
. collect ( ) ) ) ,
614
+ Threshold ( k, ref subs) => {
615
+ Some ( Threshold ( * k, ( 0 ..subs. len ( ) ) . map ( child_n) . collect ( ) ) )
616
+ }
617
617
_ => None ,
618
618
} ;
619
619
match new_policy {
@@ -724,10 +724,6 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
724
724
cltv_with_time : false ,
725
725
contains_combination : false ,
726
726
} ,
727
- Threshold ( ref k, subs) => {
728
- let iter = ( 0 ..subs. len ( ) ) . map ( info_for_child_n) ;
729
- TimelockInfo :: combine_threshold ( * k, iter)
730
- }
731
727
And ( ref subs) => {
732
728
let iter = ( 0 ..subs. len ( ) ) . map ( info_for_child_n) ;
733
729
TimelockInfo :: combine_threshold ( subs. len ( ) , iter)
@@ -736,6 +732,10 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
736
732
let iter = ( 0 ..subs. len ( ) ) . map ( info_for_child_n) ;
737
733
TimelockInfo :: combine_threshold ( 1 , iter)
738
734
}
735
+ Threshold ( ref k, subs) => {
736
+ let iter = ( 0 ..subs. len ( ) ) . map ( info_for_child_n) ;
737
+ TimelockInfo :: combine_threshold ( * k, iter)
738
+ }
739
739
_ => TimelockInfo :: default ( ) ,
740
740
} ;
741
741
infos. push ( info) ;
@@ -749,59 +749,46 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
749
749
/// Validity condition also checks whether there is a possible satisfaction
750
750
/// combination of timelocks and heightlocks
751
751
pub fn is_valid ( & self ) -> Result < ( ) , PolicyError > {
752
+ use Policy :: * ;
753
+
752
754
self . check_timelocks ( ) ?;
753
755
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
+ }
763
765
}
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
+ }
773
772
}
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
+ }
783
777
}
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
+ }
792
782
}
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
+ }
801
787
}
788
+ _ => { }
802
789
}
803
- _ => Ok ( ( ) ) ,
804
790
}
791
+ Ok ( ( ) )
805
792
}
806
793
807
794
/// Checks if any possible compilation of the policy could be compiled
@@ -812,43 +799,48 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
812
799
/// Returns a tuple `(safe, non-malleable)` to avoid the fact that
813
800
/// non-malleability depends on safety and we would like to cache results.
814
801
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 :: * ;
843
803
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) ;
851
841
}
842
+ // Ok to unwrap because we know we processed at least one node.
843
+ acc. pop ( ) . unwrap ( )
852
844
}
853
845
}
854
846
0 commit comments