@@ -279,6 +279,76 @@ size_t ComputeScriptLen(Fragment fragment, Type sub0typ, size_t subsize, uint32_
279279 assert (false );
280280}
281281
282+ InputStack& InputStack::SetAvailable (Availability avail) {
283+ available = avail;
284+ if (avail == Availability::NO) {
285+ stack.clear ();
286+ size = std::numeric_limits<size_t >::max ();
287+ has_sig = false ;
288+ malleable = false ;
289+ non_canon = false ;
290+ }
291+ return *this ;
292+ }
293+
294+ InputStack& InputStack::SetWithSig () {
295+ has_sig = true ;
296+ return *this ;
297+ }
298+
299+ InputStack& InputStack::SetNonCanon () {
300+ non_canon = true ;
301+ return *this ;
302+ }
303+
304+ InputStack& InputStack::SetMalleable (bool x) {
305+ malleable = x;
306+ return *this ;
307+ }
308+
309+ InputStack operator +(InputStack a, InputStack b) {
310+ a.stack = Cat (std::move (a.stack ), std::move (b.stack ));
311+ if (a.available != Availability::NO && b.available != Availability::NO) a.size += b.size ;
312+ a.has_sig |= b.has_sig ;
313+ a.malleable |= b.malleable ;
314+ a.non_canon |= b.non_canon ;
315+ if (a.available == Availability::NO || b.available == Availability::NO) {
316+ a.SetAvailable (Availability::NO);
317+ } else if (a.available == Availability::MAYBE || b.available == Availability::MAYBE) {
318+ a.SetAvailable (Availability::MAYBE);
319+ }
320+ return a;
321+ }
322+
323+ InputStack operator |(InputStack a, InputStack b) {
324+ // If only one is invalid, pick the other one. If both are invalid, pick an arbitrary one.
325+ if (a.available == Availability::NO) return b;
326+ if (b.available == Availability::NO) return a;
327+ // If only one of the solutions has a signature, we must pick the other one.
328+ if (!a.has_sig && b.has_sig ) return a;
329+ if (!b.has_sig && a.has_sig ) return b;
330+ if (!a.has_sig && !b.has_sig ) {
331+ // If neither solution requires a signature, the result is inevitably malleable.
332+ a.malleable = true ;
333+ b.malleable = true ;
334+ } else {
335+ // If both options require a signature, prefer the non-malleable one.
336+ if (b.malleable && !a.malleable ) return a;
337+ if (a.malleable && !b.malleable ) return b;
338+ }
339+ // Between two malleable or two non-malleable solutions, pick the smaller one between
340+ // YESes, and the bigger ones between MAYBEs. Prefer YES over MAYBE.
341+ if (a.available == Availability::YES && b.available == Availability::YES) {
342+ return std::move (a.size <= b.size ? a : b);
343+ } else if (a.available == Availability::MAYBE && b.available == Availability::MAYBE) {
344+ return std::move (a.size >= b.size ? a : b);
345+ } else if (a.available == Availability::YES) {
346+ return a;
347+ } else {
348+ return b;
349+ }
350+ }
351+
282352std::optional<std::vector<Opcode>> DecomposeScript (const CScript& script)
283353{
284354 std::vector<Opcode> out;
0 commit comments