@@ -889,6 +889,34 @@ pub struct Satisfaction<T> {
889889}
890890
891891impl < Pk : MiniscriptKey + ToPublicKey > Satisfaction < Placeholder < Pk > > {
892+ /// The empty satisfaction.
893+ ///
894+ /// This has the property that, when concatenated on either side with another satisfaction
895+ /// X, the result will be X.
896+ fn empty ( ) -> Self {
897+ Satisfaction {
898+ has_sig : false ,
899+ relative_timelock : None ,
900+ absolute_timelock : None ,
901+ stack : Witness :: Stack ( vec ! [ ] ) ,
902+ }
903+ }
904+
905+ /// Forms a satisfaction which is the concatenation of two satisfactions, with `other`'s
906+ /// stack before `self`'s.
907+ ///
908+ /// This order allows callers to write `left.concatenate_rev(right)` which feels more
909+ /// natural than the opposite order, and more importantly, allows this method to be
910+ /// used when folding over an iterator of multiple satisfactions.
911+ fn concatenate_rev ( self , other : Self ) -> Self {
912+ Satisfaction {
913+ has_sig : self . has_sig || other. has_sig ,
914+ relative_timelock : cmp:: max ( self . relative_timelock , other. relative_timelock ) ,
915+ absolute_timelock : cmp:: max ( self . absolute_timelock , other. absolute_timelock ) ,
916+ stack : Witness :: combine ( other. stack , self . stack ) ,
917+ }
918+ }
919+
892920 pub ( crate ) fn build_template < P , Ctx > (
893921 term : & Terminal < Pk , Ctx > ,
894922 provider : & P ,
@@ -1041,20 +1069,9 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
10411069 }
10421070 } else {
10431071 // Otherwise flatten everything out
1044- Satisfaction {
1045- has_sig : ret_stack. iter ( ) . any ( |sat| sat. has_sig ) ,
1046- relative_timelock : ret_stack
1047- . iter ( )
1048- . filter_map ( |sat| sat. relative_timelock )
1049- . max ( ) ,
1050- absolute_timelock : ret_stack
1051- . iter ( )
1052- . filter_map ( |sat| sat. absolute_timelock )
1053- . max ( ) ,
1054- stack : ret_stack
1055- . into_iter ( )
1056- . fold ( Witness :: empty ( ) , |acc, next| Witness :: combine ( next. stack , acc) ) ,
1057- }
1072+ ret_stack
1073+ . into_iter ( )
1074+ . fold ( Satisfaction :: empty ( ) , Satisfaction :: concatenate_rev)
10581075 }
10591076 }
10601077
@@ -1125,20 +1142,9 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
11251142
11261143 // combine the witness
11271144 // no non-malleability checks needed
1128- Satisfaction {
1129- has_sig : ret_stack. iter ( ) . any ( |sat| sat. has_sig ) ,
1130- relative_timelock : ret_stack
1131- . iter ( )
1132- . filter_map ( |sat| sat. relative_timelock )
1133- . max ( ) ,
1134- absolute_timelock : ret_stack
1135- . iter ( )
1136- . filter_map ( |sat| sat. absolute_timelock )
1137- . max ( ) ,
1138- stack : ret_stack
1139- . into_iter ( )
1140- . fold ( Witness :: empty ( ) , |acc, next| Witness :: combine ( next. stack , acc) ) ,
1141- }
1145+ ret_stack
1146+ . into_iter ( )
1147+ . fold ( Satisfaction :: empty ( ) , Satisfaction :: concatenate_rev)
11421148 }
11431149
11441150 fn minimum ( sat1 : Self , sat2 : Self ) -> Self {
@@ -1360,12 +1366,7 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
13601366 Self :: satisfy_helper ( & l. node , stfr, root_has_sig, leaf_hash, min_fn, thresh_fn) ;
13611367 let r_sat =
13621368 Self :: satisfy_helper ( & r. node , stfr, root_has_sig, leaf_hash, min_fn, thresh_fn) ;
1363- Satisfaction {
1364- stack : Witness :: combine ( r_sat. stack , l_sat. stack ) ,
1365- has_sig : l_sat. has_sig || r_sat. has_sig ,
1366- relative_timelock : cmp:: max ( l_sat. relative_timelock , r_sat. relative_timelock ) ,
1367- absolute_timelock : cmp:: max ( l_sat. absolute_timelock , r_sat. absolute_timelock ) ,
1368- }
1369+ l_sat. concatenate_rev ( r_sat)
13691370 }
13701371 Terminal :: AndOr ( ref a, ref b, ref c) => {
13711372 let a_sat =
@@ -1383,27 +1384,7 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
13831384 let c_sat =
13841385 Self :: satisfy_helper ( & c. node , stfr, root_has_sig, leaf_hash, min_fn, thresh_fn) ;
13851386
1386- min_fn (
1387- Satisfaction {
1388- stack : Witness :: combine ( b_sat. stack , a_sat. stack ) ,
1389- has_sig : a_sat. has_sig || b_sat. has_sig ,
1390- relative_timelock : cmp:: max (
1391- a_sat. relative_timelock ,
1392- b_sat. relative_timelock ,
1393- ) ,
1394- absolute_timelock : cmp:: max (
1395- a_sat. absolute_timelock ,
1396- b_sat. absolute_timelock ,
1397- ) ,
1398- } ,
1399- Satisfaction {
1400- stack : Witness :: combine ( c_sat. stack , a_nsat. stack ) ,
1401- has_sig : a_nsat. has_sig || c_sat. has_sig ,
1402- // timelocks can't be dissatisfied, so here we ignore a_nsat and only consider c_sat
1403- relative_timelock : c_sat. relative_timelock ,
1404- absolute_timelock : c_sat. absolute_timelock ,
1405- } ,
1406- )
1387+ min_fn ( a_sat. concatenate_rev ( b_sat) , a_nsat. concatenate_rev ( c_sat) )
14071388 }
14081389 Terminal :: OrB ( ref l, ref r) => {
14091390 let l_sat =
@@ -1431,18 +1412,8 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
14311412 assert ! ( !r_nsat. has_sig) ;
14321413
14331414 min_fn (
1434- Satisfaction {
1435- stack : Witness :: combine ( r_sat. stack , l_nsat. stack ) ,
1436- has_sig : r_sat. has_sig ,
1437- relative_timelock : r_sat. relative_timelock ,
1438- absolute_timelock : r_sat. absolute_timelock ,
1439- } ,
1440- Satisfaction {
1441- stack : Witness :: combine ( r_nsat. stack , l_sat. stack ) ,
1442- has_sig : l_sat. has_sig ,
1443- relative_timelock : l_sat. relative_timelock ,
1444- absolute_timelock : l_sat. absolute_timelock ,
1445- } ,
1415+ Satisfaction :: concatenate_rev ( l_nsat, r_sat) ,
1416+ Satisfaction :: concatenate_rev ( l_sat, r_nsat) ,
14461417 )
14471418 }
14481419 Terminal :: OrD ( ref l, ref r) | Terminal :: OrC ( ref l, ref r) => {
@@ -1461,15 +1432,7 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
14611432
14621433 assert ! ( !l_nsat. has_sig) ;
14631434
1464- min_fn (
1465- l_sat,
1466- Satisfaction {
1467- stack : Witness :: combine ( r_sat. stack , l_nsat. stack ) ,
1468- has_sig : r_sat. has_sig ,
1469- relative_timelock : r_sat. relative_timelock ,
1470- absolute_timelock : r_sat. absolute_timelock ,
1471- } ,
1472- )
1435+ min_fn ( l_sat, Satisfaction :: concatenate_rev ( l_nsat, r_sat) )
14731436 }
14741437 Terminal :: OrI ( ref l, ref r) => {
14751438 let l_sat =
@@ -1492,7 +1455,24 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
14921455 )
14931456 }
14941457 Terminal :: Thresh ( ref thresh) => {
1495- thresh_fn ( thresh, stfr, root_has_sig, leaf_hash, min_fn)
1458+ if thresh. k ( ) == thresh. n ( ) {
1459+ // this is just an and
1460+ thresh
1461+ . iter ( )
1462+ . map ( |s| {
1463+ Self :: satisfy_helper (
1464+ & s. node ,
1465+ stfr,
1466+ root_has_sig,
1467+ leaf_hash,
1468+ min_fn,
1469+ thresh_fn,
1470+ )
1471+ } )
1472+ . fold ( Satisfaction :: empty ( ) , Satisfaction :: concatenate_rev)
1473+ } else {
1474+ thresh_fn ( thresh, stfr, root_has_sig, leaf_hash, min_fn)
1475+ }
14961476 }
14971477 Terminal :: Multi ( ref thresh) => {
14981478 // Collect all available signatures
@@ -1682,12 +1662,7 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
16821662 min_fn,
16831663 thresh_fn,
16841664 ) ;
1685- Satisfaction {
1686- stack : Witness :: combine ( odissat. stack , vsat. stack ) ,
1687- has_sig : vsat. has_sig || odissat. has_sig ,
1688- relative_timelock : None ,
1689- absolute_timelock : None ,
1690- }
1665+ vsat. concatenate_rev ( odissat)
16911666 }
16921667 Terminal :: AndB ( ref l, ref r)
16931668 | Terminal :: OrB ( ref l, ref r)
@@ -1709,12 +1684,7 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
17091684 min_fn,
17101685 thresh_fn,
17111686 ) ;
1712- Satisfaction {
1713- stack : Witness :: combine ( rnsat. stack , lnsat. stack ) ,
1714- has_sig : rnsat. has_sig || lnsat. has_sig ,
1715- relative_timelock : None ,
1716- absolute_timelock : None ,
1717- }
1687+ lnsat. concatenate_rev ( rnsat)
17181688 }
17191689 Terminal :: OrI ( ref l, ref r) => {
17201690 let lnsat = Self :: dissatisfy_helper (
@@ -1750,23 +1720,19 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfaction<Placeholder<Pk>> {
17501720 // Dissatisfactions don't need to non-malleable. Use minimum_mall always
17511721 Satisfaction :: minimum_mall ( dissat_1, dissat_2)
17521722 }
1753- Terminal :: Thresh ( ref thresh) => Satisfaction {
1754- stack : thresh. iter ( ) . fold ( Witness :: empty ( ) , |acc, sub| {
1755- let nsat = Self :: dissatisfy_helper (
1756- & sub. node ,
1723+ Terminal :: Thresh ( ref thresh) => thresh
1724+ . iter ( )
1725+ . map ( |s| {
1726+ Self :: dissatisfy_helper (
1727+ & s. node ,
17571728 stfr,
17581729 root_has_sig,
17591730 leaf_hash,
17601731 min_fn,
17611732 thresh_fn,
1762- ) ;
1763- assert ! ( !nsat. has_sig) ;
1764- Witness :: combine ( nsat. stack , acc)
1765- } ) ,
1766- has_sig : false ,
1767- relative_timelock : None ,
1768- absolute_timelock : None ,
1769- } ,
1733+ )
1734+ } )
1735+ . fold ( Satisfaction :: empty ( ) , Satisfaction :: concatenate_rev) ,
17701736 Terminal :: Multi ( ref thresh) => Satisfaction {
17711737 stack : Witness :: Stack ( vec ! [ Placeholder :: PushZero ; thresh. k( ) + 1 ] ) ,
17721738 has_sig : false ,
0 commit comments