@@ -499,6 +499,34 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
499499 ret
500500 }
501501
502+ /// Helper function for recursion in `absolute timelocks`
503+ fn real_absolute_timelocks ( & self ) -> Vec < u32 > {
504+ match * self {
505+ Policy :: Unsatisfiable
506+ | Policy :: Trivial
507+ | Policy :: KeyHash ( ..)
508+ | Policy :: Sha256 ( ..)
509+ | Policy :: Hash256 ( ..)
510+ | Policy :: Ripemd160 ( ..)
511+ | Policy :: Hash160 ( ..) => vec ! [ ] ,
512+ Policy :: Older ( ..) => vec ! [ ] ,
513+ Policy :: After ( t) => vec ! [ t] ,
514+ Policy :: Threshold ( _, ref subs) => subs. iter ( ) . fold ( vec ! [ ] , |mut acc, x| {
515+ acc. extend ( x. real_absolute_timelocks ( ) ) ;
516+ acc
517+ } ) ,
518+ }
519+ }
520+
521+ /// Returns a list of all absolute timelocks, not including 0,
522+ /// which appear in the policy
523+ pub fn absolute_timelocks ( & self ) -> Vec < u32 > {
524+ let mut ret = self . real_absolute_timelocks ( ) ;
525+ ret. sort ( ) ;
526+ ret. dedup ( ) ;
527+ ret
528+ }
529+
502530 /// Filter a policy by eliminating relative timelock constraints
503531 /// that are not satisfied at the given age.
504532 pub fn at_age ( mut self , time : u32 ) -> Policy < Pk > {
@@ -518,6 +546,25 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
518546 self . normalized ( )
519547 }
520548
549+ /// Filter a policy by eliminating absolute timelock constraints
550+ /// that are not satisfied at the given age.
551+ pub fn at_height ( mut self , time : u32 ) -> Policy < Pk > {
552+ self = match self {
553+ Policy :: After ( t) => {
554+ if t > time {
555+ Policy :: Unsatisfiable
556+ } else {
557+ Policy :: After ( t)
558+ }
559+ }
560+ Policy :: Threshold ( k, subs) => {
561+ Policy :: Threshold ( k, subs. into_iter ( ) . map ( |sub| sub. at_height ( time) ) . collect ( ) )
562+ }
563+ x => x,
564+ } ;
565+ self . normalized ( )
566+ }
567+
521568 /// Count the number of public keys and keyhashes referenced in a policy.
522569 /// Duplicate keys will be double-counted.
523570 pub fn n_keys ( & self ) -> usize {
@@ -604,13 +651,15 @@ mod tests {
604651 let policy = StringPolicy :: from_str ( "pkh()" ) . unwrap ( ) ;
605652 assert_eq ! ( policy, Policy :: KeyHash ( "" . to_owned( ) ) ) ;
606653 assert_eq ! ( policy. relative_timelocks( ) , vec![ ] ) ;
654+ assert_eq ! ( policy. absolute_timelocks( ) , vec![ ] ) ;
607655 assert_eq ! ( policy. clone( ) . at_age( 0 ) , policy. clone( ) ) ;
608656 assert_eq ! ( policy. clone( ) . at_age( 10000 ) , policy. clone( ) ) ;
609657 assert_eq ! ( policy. n_keys( ) , 1 ) ;
610658 assert_eq ! ( policy. minimum_n_keys( ) , 1 ) ;
611659
612660 let policy = StringPolicy :: from_str ( "older(1000)" ) . unwrap ( ) ;
613661 assert_eq ! ( policy, Policy :: Older ( 1000 ) ) ;
662+ assert_eq ! ( policy. absolute_timelocks( ) , vec![ ] ) ;
614663 assert_eq ! ( policy. relative_timelocks( ) , vec![ 1000 ] ) ;
615664 assert_eq ! ( policy. clone( ) . at_age( 0 ) , Policy :: Unsatisfiable ) ;
616665 assert_eq ! ( policy. clone( ) . at_age( 999 ) , Policy :: Unsatisfiable ) ;
@@ -628,6 +677,7 @@ mod tests {
628677 )
629678 ) ;
630679 assert_eq ! ( policy. relative_timelocks( ) , vec![ 1000 ] ) ;
680+ assert_eq ! ( policy. absolute_timelocks( ) , vec![ ] ) ;
631681 assert_eq ! ( policy. clone( ) . at_age( 0 ) , Policy :: KeyHash ( "" . to_owned( ) ) ) ;
632682 assert_eq ! ( policy. clone( ) . at_age( 999 ) , Policy :: KeyHash ( "" . to_owned( ) ) ) ;
633683 assert_eq ! ( policy. clone( ) . at_age( 1000 ) , policy. clone( ) . normalized( ) ) ;
@@ -658,6 +708,17 @@ mod tests {
658708 policy. relative_timelocks( ) ,
659709 vec![ 1000 , 2000 , 10000 ] //sorted and dedup'd
660710 ) ;
711+
712+ let policy = StringPolicy :: from_str ( "after(1000)" ) . unwrap ( ) ;
713+ assert_eq ! ( policy, Policy :: After ( 1000 ) ) ;
714+ assert_eq ! ( policy. absolute_timelocks( ) , vec![ 1000 ] ) ;
715+ assert_eq ! ( policy. relative_timelocks( ) , vec![ ] ) ;
716+ assert_eq ! ( policy. clone( ) . at_height( 0 ) , Policy :: Unsatisfiable ) ;
717+ assert_eq ! ( policy. clone( ) . at_height( 999 ) , Policy :: Unsatisfiable ) ;
718+ assert_eq ! ( policy. clone( ) . at_height( 1000 ) , policy. clone( ) ) ;
719+ assert_eq ! ( policy. clone( ) . at_height( 10000 ) , policy. clone( ) ) ;
720+ assert_eq ! ( policy. n_keys( ) , 0 ) ;
721+ assert_eq ! ( policy. minimum_n_keys( ) , 0 ) ;
661722 }
662723
663724 #[ test]
0 commit comments