@@ -892,6 +892,34 @@ pub struct Satisfaction<T> {
892
892
}
893
893
894
894
impl < Pk : MiniscriptKey + ToPublicKey > Satisfaction < Placeholder < Pk > > {
895
+ /// The empty satisfaction.
896
+ ///
897
+ /// This has the property that, when concatenated on either side with another satisfaction
898
+ /// X, the result will be X.
899
+ fn empty ( ) -> Self {
900
+ Satisfaction {
901
+ has_sig : false ,
902
+ relative_timelock : None ,
903
+ absolute_timelock : None ,
904
+ stack : Witness :: Stack ( vec ! [ ] ) ,
905
+ }
906
+ }
907
+
908
+ /// Forms a satisfaction which is the concatenation of two satisfactions, with `other`'s
909
+ /// stack before `self`'s.
910
+ ///
911
+ /// This order allows callers to write `left.concatenate_rev(right)` which feels more
912
+ /// natural than the opposite order, and more importantly, allows this method to be
913
+ /// used when folding over an iterator of multiple satisfactions.
914
+ fn concatenate_rev ( self , other : Self ) -> Self {
915
+ Satisfaction {
916
+ has_sig : self . has_sig || other. has_sig ,
917
+ relative_timelock : cmp:: max ( self . relative_timelock , other. relative_timelock ) ,
918
+ absolute_timelock : cmp:: max ( self . absolute_timelock , other. absolute_timelock ) ,
919
+ stack : Witness :: combine ( other. stack , self . stack ) ,
920
+ }
921
+ }
922
+
895
923
pub ( crate ) fn build_template < P , Ctx > (
896
924
term : & Terminal < Pk , Ctx > ,
897
925
provider : & P ,
@@ -1044,20 +1072,9 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
1044
1072
}
1045
1073
} else {
1046
1074
// Otherwise flatten everything out
1047
- Satisfaction {
1048
- has_sig : ret_stack. iter ( ) . any ( |sat| sat. has_sig ) ,
1049
- relative_timelock : ret_stack
1050
- . iter ( )
1051
- . filter_map ( |sat| sat. relative_timelock )
1052
- . max ( ) ,
1053
- absolute_timelock : ret_stack
1054
- . iter ( )
1055
- . filter_map ( |sat| sat. absolute_timelock )
1056
- . max ( ) ,
1057
- stack : ret_stack
1058
- . into_iter ( )
1059
- . fold ( Witness :: empty ( ) , |acc, next| Witness :: combine ( next. stack , acc) ) ,
1060
- }
1075
+ ret_stack
1076
+ . into_iter ( )
1077
+ . fold ( Satisfaction :: empty ( ) , Satisfaction :: concatenate_rev)
1061
1078
}
1062
1079
}
1063
1080
@@ -1128,20 +1145,9 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
1128
1145
1129
1146
// combine the witness
1130
1147
// no non-malleability checks needed
1131
- Satisfaction {
1132
- has_sig : ret_stack. iter ( ) . any ( |sat| sat. has_sig ) ,
1133
- relative_timelock : ret_stack
1134
- . iter ( )
1135
- . filter_map ( |sat| sat. relative_timelock )
1136
- . max ( ) ,
1137
- absolute_timelock : ret_stack
1138
- . iter ( )
1139
- . filter_map ( |sat| sat. absolute_timelock )
1140
- . max ( ) ,
1141
- stack : ret_stack
1142
- . into_iter ( )
1143
- . fold ( Witness :: empty ( ) , |acc, next| Witness :: combine ( next. stack , acc) ) ,
1144
- }
1148
+ ret_stack
1149
+ . into_iter ( )
1150
+ . fold ( Satisfaction :: empty ( ) , Satisfaction :: concatenate_rev)
1145
1151
}
1146
1152
1147
1153
fn minimum ( sat1 : Self , sat2 : Self ) -> Self {
@@ -1363,12 +1369,7 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
1363
1369
Self :: satisfy_helper ( & l. node , stfr, root_has_sig, leaf_hash, min_fn, thresh_fn) ;
1364
1370
let r_sat =
1365
1371
Self :: satisfy_helper ( & r. node , stfr, root_has_sig, leaf_hash, min_fn, thresh_fn) ;
1366
- Satisfaction {
1367
- stack : Witness :: combine ( r_sat. stack , l_sat. stack ) ,
1368
- has_sig : l_sat. has_sig || r_sat. has_sig ,
1369
- relative_timelock : cmp:: max ( l_sat. relative_timelock , r_sat. relative_timelock ) ,
1370
- absolute_timelock : cmp:: max ( l_sat. absolute_timelock , r_sat. absolute_timelock ) ,
1371
- }
1372
+ l_sat. concatenate_rev ( r_sat)
1372
1373
}
1373
1374
Terminal :: AndOr ( ref a, ref b, ref c) => {
1374
1375
let a_sat =
@@ -1386,27 +1387,7 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
1386
1387
let c_sat =
1387
1388
Self :: satisfy_helper ( & c. node , stfr, root_has_sig, leaf_hash, min_fn, thresh_fn) ;
1388
1389
1389
- min_fn (
1390
- Satisfaction {
1391
- stack : Witness :: combine ( b_sat. stack , a_sat. stack ) ,
1392
- has_sig : a_sat. has_sig || b_sat. has_sig ,
1393
- relative_timelock : cmp:: max (
1394
- a_sat. relative_timelock ,
1395
- b_sat. relative_timelock ,
1396
- ) ,
1397
- absolute_timelock : cmp:: max (
1398
- a_sat. absolute_timelock ,
1399
- b_sat. absolute_timelock ,
1400
- ) ,
1401
- } ,
1402
- Satisfaction {
1403
- stack : Witness :: combine ( c_sat. stack , a_nsat. stack ) ,
1404
- has_sig : a_nsat. has_sig || c_sat. has_sig ,
1405
- // timelocks can't be dissatisfied, so here we ignore a_nsat and only consider c_sat
1406
- relative_timelock : c_sat. relative_timelock ,
1407
- absolute_timelock : c_sat. absolute_timelock ,
1408
- } ,
1409
- )
1390
+ min_fn ( a_sat. concatenate_rev ( b_sat) , a_nsat. concatenate_rev ( c_sat) )
1410
1391
}
1411
1392
Terminal :: OrB ( ref l, ref r) => {
1412
1393
let l_sat =
@@ -1434,18 +1415,8 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
1434
1415
assert ! ( !r_nsat. has_sig) ;
1435
1416
1436
1417
min_fn (
1437
- Satisfaction {
1438
- stack : Witness :: combine ( r_sat. stack , l_nsat. stack ) ,
1439
- has_sig : r_sat. has_sig ,
1440
- relative_timelock : r_sat. relative_timelock ,
1441
- absolute_timelock : r_sat. absolute_timelock ,
1442
- } ,
1443
- Satisfaction {
1444
- stack : Witness :: combine ( r_nsat. stack , l_sat. stack ) ,
1445
- has_sig : l_sat. has_sig ,
1446
- relative_timelock : l_sat. relative_timelock ,
1447
- absolute_timelock : l_sat. absolute_timelock ,
1448
- } ,
1418
+ Satisfaction :: concatenate_rev ( l_nsat, r_sat) ,
1419
+ Satisfaction :: concatenate_rev ( l_sat, r_nsat) ,
1449
1420
)
1450
1421
}
1451
1422
Terminal :: OrD ( ref l, ref r) | Terminal :: OrC ( ref l, ref r) => {
@@ -1464,15 +1435,7 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
1464
1435
1465
1436
assert ! ( !l_nsat. has_sig) ;
1466
1437
1467
- min_fn (
1468
- l_sat,
1469
- Satisfaction {
1470
- stack : Witness :: combine ( r_sat. stack , l_nsat. stack ) ,
1471
- has_sig : r_sat. has_sig ,
1472
- relative_timelock : r_sat. relative_timelock ,
1473
- absolute_timelock : r_sat. absolute_timelock ,
1474
- } ,
1475
- )
1438
+ min_fn ( l_sat, Satisfaction :: concatenate_rev ( l_nsat, r_sat) )
1476
1439
}
1477
1440
Terminal :: OrI ( ref l, ref r) => {
1478
1441
let l_sat =
@@ -1495,7 +1458,24 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
1495
1458
)
1496
1459
}
1497
1460
Terminal :: Thresh ( ref thresh) => {
1498
- thresh_fn ( thresh, stfr, root_has_sig, leaf_hash, min_fn)
1461
+ if thresh. k ( ) == thresh. n ( ) {
1462
+ // this is just an and
1463
+ thresh
1464
+ . iter ( )
1465
+ . map ( |s| {
1466
+ Self :: satisfy_helper (
1467
+ & s. node ,
1468
+ stfr,
1469
+ root_has_sig,
1470
+ leaf_hash,
1471
+ min_fn,
1472
+ thresh_fn,
1473
+ )
1474
+ } )
1475
+ . fold ( Satisfaction :: empty ( ) , Satisfaction :: concatenate_rev)
1476
+ } else {
1477
+ thresh_fn ( thresh, stfr, root_has_sig, leaf_hash, min_fn)
1478
+ }
1499
1479
}
1500
1480
Terminal :: Multi ( ref thresh) => {
1501
1481
// Collect all available signatures
@@ -1685,12 +1665,7 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
1685
1665
min_fn,
1686
1666
thresh_fn,
1687
1667
) ;
1688
- Satisfaction {
1689
- stack : Witness :: combine ( odissat. stack , vsat. stack ) ,
1690
- has_sig : vsat. has_sig || odissat. has_sig ,
1691
- relative_timelock : None ,
1692
- absolute_timelock : None ,
1693
- }
1668
+ vsat. concatenate_rev ( odissat)
1694
1669
}
1695
1670
Terminal :: AndB ( ref l, ref r)
1696
1671
| Terminal :: OrB ( ref l, ref r)
@@ -1712,12 +1687,7 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
1712
1687
min_fn,
1713
1688
thresh_fn,
1714
1689
) ;
1715
- Satisfaction {
1716
- stack : Witness :: combine ( rnsat. stack , lnsat. stack ) ,
1717
- has_sig : rnsat. has_sig || lnsat. has_sig ,
1718
- relative_timelock : None ,
1719
- absolute_timelock : None ,
1720
- }
1690
+ lnsat. concatenate_rev ( rnsat)
1721
1691
}
1722
1692
Terminal :: OrI ( ref l, ref r) => {
1723
1693
let lnsat = Self :: dissatisfy_helper (
@@ -1753,23 +1723,19 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
1753
1723
// Dissatisfactions don't need to non-malleable. Use minimum_mall always
1754
1724
Satisfaction :: minimum_mall ( dissat_1, dissat_2)
1755
1725
}
1756
- Terminal :: Thresh ( ref thresh) => Satisfaction {
1757
- stack : thresh. iter ( ) . fold ( Witness :: empty ( ) , |acc, sub| {
1758
- let nsat = Self :: dissatisfy_helper (
1759
- & sub. node ,
1726
+ Terminal :: Thresh ( ref thresh) => thresh
1727
+ . iter ( )
1728
+ . map ( |s| {
1729
+ Self :: dissatisfy_helper (
1730
+ & s. node ,
1760
1731
stfr,
1761
1732
root_has_sig,
1762
1733
leaf_hash,
1763
1734
min_fn,
1764
1735
thresh_fn,
1765
- ) ;
1766
- assert ! ( !nsat. has_sig) ;
1767
- Witness :: combine ( nsat. stack , acc)
1768
- } ) ,
1769
- has_sig : false ,
1770
- relative_timelock : None ,
1771
- absolute_timelock : None ,
1772
- } ,
1736
+ )
1737
+ } )
1738
+ . fold ( Satisfaction :: empty ( ) , Satisfaction :: concatenate_rev) ,
1773
1739
Terminal :: Multi ( ref thresh) => Satisfaction {
1774
1740
stack : Witness :: Stack ( vec ! [ Placeholder :: PushZero ; thresh. k( ) + 1 ] ) ,
1775
1741
has_sig : false ,
0 commit comments