@@ -517,57 +517,80 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
517517
518518 /// Filters a policy by eliminating relative timelock constraints
519519 /// that are not satisfied at the given `age`.
520- pub fn at_age ( mut self , age : Sequence ) -> Policy < Pk > {
521- self = match self {
522- Policy :: Older ( t) => {
523- if t. is_height_locked ( ) && age. is_time_locked ( )
524- || t. is_time_locked ( ) && age. is_height_locked ( )
525- || t. to_consensus_u32 ( ) > age. to_consensus_u32 ( )
526- {
527- Policy :: Unsatisfiable
528- } else {
529- Policy :: Older ( t)
520+ pub fn at_age ( self , age : Sequence ) -> Policy < Pk > {
521+ use Policy :: * ;
522+
523+ let mut at_age = vec ! [ ] ;
524+ for data in Arc :: new ( self ) . post_order_iter ( ) {
525+ let child_n = |n| Arc :: clone ( & at_age[ data. child_indices [ n] ] ) ;
526+
527+ let new_policy = match data. node . as_ref ( ) {
528+ Older ( ref t) => {
529+ if t. is_height_locked ( ) && age. is_time_locked ( )
530+ || t. is_time_locked ( ) && age. is_height_locked ( )
531+ || t. to_consensus_u32 ( ) > age. to_consensus_u32 ( )
532+ {
533+ Some ( Policy :: Unsatisfiable )
534+ } else {
535+ Some ( Policy :: Older ( * t) )
536+ }
537+ }
538+ Threshold ( k, ref subs) => {
539+ Some ( Threshold ( * k, ( 0 ..subs. len ( ) ) . map ( child_n) . collect ( ) ) )
530540 }
541+ _ => None ,
542+ } ;
543+ match new_policy {
544+ Some ( new_policy) => at_age. push ( Arc :: new ( new_policy) ) ,
545+ None => at_age. push ( Arc :: clone ( & data. node ) ) ,
531546 }
532- Policy :: Threshold ( k, subs) => Policy :: Threshold (
533- k,
534- subs. into_iter ( )
535- . map ( |sub| Arc :: new ( sub. as_ref ( ) . clone ( ) . at_age ( age) ) )
536- . collect ( ) ,
537- ) ,
538- x => x,
539- } ;
540- self . normalized ( )
547+ }
548+ // Unwrap is ok because we know we processed at least one node.
549+ let root_node = at_age. pop ( ) . unwrap ( ) ;
550+ // Unwrap is ok because we know `root_node` is the only strong reference.
551+ let policy = Arc :: try_unwrap ( root_node) . unwrap ( ) ;
552+ policy. normalized ( )
541553 }
542554
543555 /// Filters a policy by eliminating absolute timelock constraints
544556 /// that are not satisfied at the given `n` (`n OP_CHECKLOCKTIMEVERIFY`).
545- pub fn at_lock_time ( mut self , n : absolute:: LockTime ) -> Policy < Pk > {
557+ pub fn at_lock_time ( self , n : absolute:: LockTime ) -> Policy < Pk > {
546558 use absolute:: LockTime :: * ;
559+ use Policy :: * ;
547560
548- self = match self {
549- Policy :: After ( t) => {
550- let t = absolute:: LockTime :: from ( t) ;
551- let is_satisfied_by = match ( t, n) {
552- ( Blocks ( t) , Blocks ( n) ) => t <= n,
553- ( Seconds ( t) , Seconds ( n) ) => t <= n,
554- _ => false ,
555- } ;
556- if !is_satisfied_by {
557- Policy :: Unsatisfiable
558- } else {
559- Policy :: After ( t. into ( ) )
561+ let mut at_age = vec ! [ ] ;
562+ for data in Arc :: new ( self ) . post_order_iter ( ) {
563+ let child_n = |n| Arc :: clone ( & at_age[ data. child_indices [ n] ] ) ;
564+
565+ let new_policy = match data. node . as_ref ( ) {
566+ After ( t) => {
567+ let t = absolute:: LockTime :: from ( * t) ;
568+ let is_satisfied_by = match ( t, n) {
569+ ( Blocks ( t) , Blocks ( n) ) => t <= n,
570+ ( Seconds ( t) , Seconds ( n) ) => t <= n,
571+ _ => false ,
572+ } ;
573+ if !is_satisfied_by {
574+ Some ( Unsatisfiable )
575+ } else {
576+ Some ( After ( t. into ( ) ) )
577+ }
578+ }
579+ Threshold ( k, ref subs) => {
580+ Some ( Threshold ( * k, ( 0 ..subs. len ( ) ) . map ( child_n) . collect ( ) ) )
560581 }
582+ _ => None ,
583+ } ;
584+ match new_policy {
585+ Some ( new_policy) => at_age. push ( Arc :: new ( new_policy) ) ,
586+ None => at_age. push ( Arc :: clone ( & data. node ) ) ,
561587 }
562- Policy :: Threshold ( k, subs) => Policy :: Threshold (
563- k,
564- subs. into_iter ( )
565- . map ( |sub| Arc :: new ( sub. as_ref ( ) . clone ( ) . at_lock_time ( n) ) )
566- . collect ( ) ,
567- ) ,
568- x => x,
569- } ;
570- self . normalized ( )
588+ }
589+ // Unwrap is ok because we know we processed at least one node.
590+ let root_node = at_age. pop ( ) . unwrap ( ) ;
591+ // Unwrap is ok because we know `root_node` is the only strong reference.
592+ let policy = Arc :: try_unwrap ( root_node) . unwrap ( ) ;
593+ policy. normalized ( )
571594 }
572595
573596 /// Counts the number of public keys and keyhashes referenced in a policy.
0 commit comments