Skip to content

Commit 8ab549a

Browse files
committed
Merge #895: miniscript: rewrite satisfier to be non-recursive
a662453 satisfy: add regression test for timelock tracking in or_i satisfaction (Andrew Poelstra) c491ae5 miniscript/satisfy: rewrite satifier to be non-recursive (Andrew Poelstra) ffbf415 miniscript/satisfy: move multi/multi_a into submodule (Andrew Poelstra) 3214b70 miniscript/satisfy: move the rest of the terminals into their own module (Andrew Poelstra) fe0d153 miniscript/satisfy: move pk_k logic into helper function (Andrew Poelstra) e372b12 miniscript/satisfy: use Miniscript instead of Terminal in API (Andrew Poelstra) 171bd33 rename miniscript/satisfy.rs to miniscript/satisfy/mod.rs (Andrew Poelstra) Pull request description: Currently the `Miniscript::satisfy` function is implemented by the function `Satisfaction::satisfy_helper` which is mutually recursive with the function `Satisfaction::dissatisfy_helper`. There are a few issues with this: 1. Rust does not handle recursion well, and this may stack overflow. 2. We need to fish several parameters (closures for computing min/thresh based on whether we allow malleability; the Taproot leaf hash which might be garbage for non-Taproot outputs; a boolean indicating whether we are hassig) through every single recursive call, which results in a *lot* of noise and makes the code very hard to maintain. (In particular, I want to fix the Taproot leaf hash thing, but without rewriting the satisfier, this requires changing several dozen call sites.) 3. The logic is very hard to follow and mixes somewhat-complicated recursion logic with actual satisfaction logic, which might be wrong (there is one logic change I made related to timelocks; I have a FIXME to find a test case for this because I am pretty sure the old logic was wrong.) So I rewrote the whole function. I haven't benchmarked but I suspect the new one is a little slower, though it is asymptotically the same. The slowness comes from using heap-based rather than stack-based recursion, and also because the old algorithm could sometimes skip computing dissatisfactions while this one never does. I think the increase in code clarity justifies the loss of performance (if there is one). See the last commit message for more details. ACKs for top commit: trevarj: ACK a662453 apoelstra: On a662453 successfully ran local tests tcharding: ACK a662453 Tree-SHA512: b017fa5774b9bb4fc1a2d985e40c0fb41bf9cb055a53dded12cb2392effab046dc727f7d0558b74a6034db1cd1dce45e995d6d00f1382def677a6c5b01c9e5f9
2 parents 7243b45 + a662453 commit 8ab549a

3 files changed

Lines changed: 615 additions & 661 deletions

File tree

src/miniscript/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
464464
{
465465
// Only satisfactions for default versions (0xc0) are allowed.
466466
let satisfaction = satisfy::Satisfaction::satisfy(
467-
&self.node,
467+
self,
468468
&satisfier,
469469
self.ty.mall.safe,
470470
&self.leaf_hash_internal(),
@@ -482,7 +482,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
482482
Pk: ToPublicKey,
483483
{
484484
let satisfaction = satisfy::Satisfaction::satisfy_mall(
485-
&self.node,
485+
self,
486486
&satisfier,
487487
self.ty.mall.safe,
488488
&self.leaf_hash_internal(),
@@ -511,7 +511,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
511511
Pk: ToPublicKey,
512512
{
513513
satisfy::Satisfaction::build_template(
514-
&self.node,
514+
self,
515515
provider,
516516
self.ty.mall.safe,
517517
&self.leaf_hash_internal(),
@@ -527,7 +527,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
527527
Pk: ToPublicKey,
528528
{
529529
satisfy::Satisfaction::build_template_mall(
530-
&self.node,
530+
self,
531531
provider,
532532
self.ty.mall.safe,
533533
&self.leaf_hash_internal(),

0 commit comments

Comments
 (0)