@@ -430,62 +430,71 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
430
430
( m, n)
431
431
}
432
432
433
- match self {
434
- Policy :: Threshold ( k, subs) => {
435
- let mut ret_subs = Vec :: with_capacity ( subs. len ( ) ) ;
436
-
437
- let subs: Vec < _ > = subs
438
- . into_iter ( )
439
- . map ( |sub| Arc :: new ( sub. as_ref ( ) . clone ( ) . normalized ( ) ) )
440
- . collect ( ) ;
441
-
442
- let ( m, n) = normalized_threshold_values ( k, & subs) ;
433
+ use Policy :: * ;
443
434
444
- // Call the current threshold "parent" to differentiate it from its "child" threshold below.
445
- let parent_is_and = m == n ; // (n, n)-thresh is an AND
446
- let parent_is_or = m == 1 ; // (1, n)-thresh is an OR
435
+ let mut normalized : Vec < Arc < Policy < Pk > > > = vec ! [ ] ;
436
+ for data in Arc :: new ( self ) . post_order_iter ( ) {
437
+ let child_n = |n| Arc :: clone ( & normalized [ data . child_indices [ n ] ] ) ;
447
438
448
- for sub in subs {
449
- match sub. as_ref ( ) {
450
- Policy :: Trivial | Policy :: Unsatisfiable => { }
451
- Policy :: Threshold ( ref k, ref subs) => {
452
- let child_is_and = * k == subs. len ( ) ;
453
- let child_is_or = * k == 1 ;
454
-
455
- if parent_is_and && parent_is_or {
456
- // m = n = 1, child must be the non-trivial, non-unsatisfiable node.
457
- ret_subs. push ( Arc :: clone ( & sub) ) ;
458
- } else if parent_is_and && child_is_and {
459
- // If both parent and child are ANDs we can flatten them.
460
- subs. iter ( ) . for_each ( |sub| ret_subs. push ( Arc :: clone ( sub) ) ) ;
461
- } else if parent_is_or && child_is_or {
462
- // If both parent and child are ORs we can flatten them.
463
- subs. iter ( ) . for_each ( |sub| ret_subs. push ( Arc :: clone ( sub) ) ) ;
464
- } else {
465
- ret_subs. push ( Arc :: clone ( & sub) ) ;
439
+ let new_policy = match data. node . as_ref ( ) {
440
+ Threshold ( k, ref subs) => {
441
+ let mut ret_subs = Vec :: with_capacity ( subs. len ( ) ) ;
442
+ let ( m, n) = normalized_threshold_values ( * k, & subs) ;
443
+
444
+ // Call the current threshold "parent" to differentiate it from its "child" threshold below.
445
+ let parent_is_and = m == n; // (n, n)-thresh is an AND
446
+ let parent_is_or = m == 1 ; // (1, n)-thresh is an OR
447
+
448
+ for sub in ( 0 ..subs. len ( ) ) . map ( child_n) {
449
+ match sub. as_ref ( ) {
450
+ Trivial | Unsatisfiable => { }
451
+ Threshold ( ref k, ref subs) => {
452
+ let child_is_and = * k == subs. len ( ) ;
453
+ let child_is_or = * k == 1 ;
454
+
455
+ if parent_is_and && parent_is_or {
456
+ // m = n = 1, child must be the non-trivial, non-unsatisfiable node.
457
+ ret_subs. push ( Arc :: clone ( & sub) ) ;
458
+ } else if parent_is_and && child_is_and {
459
+ // If both parent and child are ANDs we can flatten them.
460
+ subs. iter ( ) . for_each ( |sub| ret_subs. push ( Arc :: clone ( sub) ) ) ;
461
+ } else if parent_is_or && child_is_or {
462
+ // If both parent and child are ORs we can flatten them.
463
+ subs. iter ( ) . for_each ( |sub| ret_subs. push ( Arc :: clone ( sub) ) ) ;
464
+ } else {
465
+ ret_subs. push ( Arc :: clone ( & sub) ) ;
466
+ }
466
467
}
468
+ _ => ret_subs. push ( Arc :: clone ( & sub) ) ,
467
469
}
468
- _ => ret_subs. push ( Arc :: clone ( & sub) ) ,
470
+ }
471
+ // Now reason about m of n threshold
472
+ if m == 0 {
473
+ Some ( Trivial )
474
+ } else if m > ret_subs. len ( ) {
475
+ Some ( Unsatisfiable )
476
+ } else if ret_subs. len ( ) == 1 {
477
+ let policy = ret_subs. pop ( ) . unwrap ( ) ;
478
+ Some ( ( * policy) . clone ( ) ) // I'm lost now, can we try_unwrap still?
479
+ } else if parent_is_and {
480
+ Some ( Threshold ( ret_subs. len ( ) , ret_subs) )
481
+ } else if parent_is_or {
482
+ Some ( Threshold ( 1 , ret_subs) )
483
+ } else {
484
+ Some ( Threshold ( m, ret_subs) )
469
485
}
470
486
}
471
- // Now reason about m of n threshold
472
- if m == 0 {
473
- Policy :: Trivial
474
- } else if m > ret_subs. len ( ) {
475
- Policy :: Unsatisfiable
476
- } else if ret_subs. len ( ) == 1 {
477
- let policy = ret_subs. pop ( ) . unwrap ( ) ;
478
- ( * policy) . clone ( ) // I'm lost now, can we try_unwrap still?
479
- } else if parent_is_and {
480
- Policy :: Threshold ( ret_subs. len ( ) , ret_subs)
481
- } else if parent_is_or {
482
- Policy :: Threshold ( 1 , ret_subs)
483
- } else {
484
- Policy :: Threshold ( m, ret_subs)
485
- }
487
+ _ => None ,
488
+ } ;
489
+ match new_policy {
490
+ Some ( new_policy) => normalized. push ( Arc :: new ( new_policy) ) ,
491
+ None => normalized. push ( Arc :: clone ( & data. node ) ) ,
486
492
}
487
- x => x,
488
493
}
494
+ // Unwrap is ok because we know we processed at least one node.
495
+ let root_node = normalized. pop ( ) . unwrap ( ) ;
496
+ // Unwrap is ok because we know `root_node` is the only strong reference.
497
+ Arc :: try_unwrap ( root_node) . unwrap ( )
489
498
}
490
499
491
500
/// Detects a true/trivial policy.
0 commit comments