@@ -279,6 +279,76 @@ size_t ComputeScriptLen(Fragment fragment, Type sub0typ, size_t subsize, uint32_
279
279
assert (false );
280
280
}
281
281
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
+
282
352
std::optional<std::vector<Opcode>> DecomposeScript (const CScript& script)
283
353
{
284
354
std::vector<Opcode> out;
0 commit comments