@@ -865,36 +865,61 @@ struct Node {
865
865
return {ZERO + InputStack (key), (InputStack (std::move (sig)).SetWithSig () + InputStack (key)).SetAvailable (avail)};
866
866
}
867
867
case Fragment::MULTI: {
868
+ // sats[j] represents the best stack containing j valid signatures (out of the first i keys).
869
+ // In the loop below, these stacks are built up using a dynamic programming approach.
870
+ // sats[0] starts off being {0}, due to the CHECKMULTISIG bug that pops off one element too many.
868
871
std::vector<InputStack> sats = Vector (ZERO);
869
872
for (size_t i = 0 ; i < node.keys .size (); ++i) {
870
873
std::vector<unsigned char > sig;
871
874
Availability avail = ctx.Sign (node.keys [i], sig);
875
+ // Compute signature stack for just the i'th key.
872
876
auto sat = InputStack (std::move (sig)).SetWithSig ().SetAvailable (avail);
877
+ // Compute the next sats vector: next_sats[0] is a copy of sats[0] (no signatures). All further
878
+ // next_sats[j] are equal to either the existing sats[j], or sats[j-1] plus a signature for the
879
+ // current (i'th) key. The very last element needs all signatures filled.
873
880
std::vector<InputStack> next_sats;
874
881
next_sats.push_back (sats[0 ]);
875
882
for (size_t j = 1 ; j < sats.size (); ++j) next_sats.push_back (sats[j] | (std::move (sats[j - 1 ]) + sat));
876
883
next_sats.push_back (std::move (sats[sats.size () - 1 ]) + std::move (sat));
884
+ // Switch over.
877
885
sats = std::move (next_sats);
878
886
}
887
+ // The dissatisfaction consists of k+1 stack elements all equal to 0.
879
888
InputStack nsat = ZERO;
880
889
for (size_t i = 0 ; i < node.k ; ++i) nsat = std::move (nsat) + ZERO;
881
890
assert (node.k <= sats.size ());
882
891
return {std::move (nsat), std::move (sats[node.k ])};
883
892
}
884
893
case Fragment::THRESH: {
894
+ // sats[k] represents the best stack that satisfies k out of the *last* i subexpressions.
895
+ // In the loop below, these stacks are built up using a dynamic programming approach.
896
+ // sats[0] starts off empty.
885
897
std::vector<InputStack> sats = Vector (EMPTY);
886
898
for (size_t i = 0 ; i < subres.size (); ++i) {
899
+ // Introduce an alias for the i'th last satisfaction/dissatisfaction.
887
900
auto & res = subres[subres.size () - i - 1 ];
901
+ // Compute the next sats vector: next_sats[0] is sats[0] plus res.nsat (thus containing all dissatisfactions
902
+ // so far. next_sats[j] is either sats[j] + res.nsat (reusing j earlier satisfactions) or sats[j-1] + res.sat
903
+ // (reusing j-1 earlier satisfactions plus a new one). The very last next_sats[j] is all satisfactions.
888
904
std::vector<InputStack> next_sats;
889
905
next_sats.push_back (sats[0 ] + res.nsat );
890
906
for (size_t j = 1 ; j < sats.size (); ++j) next_sats.push_back ((sats[j] + res.nsat ) | (std::move (sats[j - 1 ]) + res.sat ));
891
907
next_sats.push_back (std::move (sats[sats.size () - 1 ]) + std::move (res.sat ));
908
+ // Switch over.
892
909
sats = std::move (next_sats);
893
910
}
911
+ // At this point, sats[k].sat is the best satisfaction for the overall thresh() node. The best dissatisfaction
912
+ // is computed by gathering all sats[i].nsat for i != k.
894
913
InputStack nsat = INVALID;
895
914
for (size_t i = 0 ; i < sats.size (); ++i) {
896
- // i==k is the satisfaction; i==0 is the canonical dissatisfaction; the rest are non-canonical.
897
- if (i != 0 && i != node.k ) sats[i].SetNonCanon ();
915
+ // i==k is the satisfaction; i==0 is the canonical dissatisfaction;
916
+ // the rest are non-canonical (a no-signature dissatisfaction - the i=0
917
+ // form - is always available) and malleable (due to overcompleteness).
918
+ // Marking the solutions malleable here is not strictly necessary, as they
919
+ // should already never be picked in non-malleable solutions due to the
920
+ // availability of the i=0 form.
921
+ if (i != 0 && i != node.k ) sats[i].SetMalleable ().SetNonCanon ();
922
+ // Include all dissatisfactions (even these non-canonical ones) in nsat.
898
923
if (i != node.k ) nsat = std::move (nsat) | std::move (sats[i]);
899
924
}
900
925
assert (node.k <= sats.size ());
@@ -928,10 +953,21 @@ struct Node {
928
953
}
929
954
case Fragment::AND_V: {
930
955
auto & x = subres[0 ], &y = subres[1 ];
956
+ // As the dissatisfaction here only consist of a single option, it doesn't
957
+ // actually need to be listed (it's not required for reasoning about malleability of
958
+ // other options), and is never required (no valid miniscript relies on the ability
959
+ // to satisfy the type V left subexpression). It's still listed here for
960
+ // completeness, as a hypothetical (not currently implemented) satisfier that doesn't
961
+ // care about malleability might in some cases prefer it still.
931
962
return {(y.nsat + x.sat ).SetNonCanon (), y.sat + x.sat };
932
963
}
933
964
case Fragment::AND_B: {
934
965
auto & x = subres[0 ], &y = subres[1 ];
966
+ // Note that it is not strictly necessary to mark the 2nd and 3rd dissatisfaction here
967
+ // as malleable. While they are definitely malleable, they are also non-canonical due
968
+ // to the guaranteed existence of a no-signature other dissatisfaction (the 1st)
969
+ // option. Because of that, the 2nd and 3rd option will never be chosen, even if they
970
+ // weren't marked as malleable.
935
971
return {(y.nsat + x.nsat ) | (y.sat + x.nsat ).SetMalleable ().SetNonCanon () | (y.nsat + x.sat ).SetMalleable ().SetNonCanon (), y.sat + x.sat };
936
972
}
937
973
case Fragment::OR_B: {
0 commit comments