Skip to content

Various cleanups, mostly around the compiler #828

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

apoelstra
Copy link
Member

This PR is a grab back of prepatory commits for larger changes. It includes a couple of followups to #815 in the first commits. Then it cleans up some error types and paths.

I don't believe anything in here will be tricky or controversial, though there are API breaks because of the cleaned up error types.

@apoelstra apoelstra changed the base branch from 2025-05-compiler to master June 20, 2025 17:03
@apoelstra
Copy link
Member Author

Need to investigate why jj is not signing these commits.

@apoelstra
Copy link
Member Author

I had authored them with the wrong email address set.

Generally we try not to add special-case logic for weird tools, but this
is a a really simple change and I think that jujutsu is going to become
pretty popular among rust-bitcoin developers.

This is some repeated code which looks like it should be factored out
into a utility function, but we can't really do that because we need to
figure out the workspace root before we can even locate utility functions.
Copy link
Member

@tcharding tcharding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK bae6bf5

@tcharding
Copy link
Member

Code review only, my ack has no weight in regards to semantic correctness of the changes.

We can cause panics in the compiler comparing OrdF64s which are NaN,
which we can produce by parsing ors where every child has weight 0.

Simply make it a parse error to have any zero-probability branches.
In theory somebody might want an or where some fragments have positive
probability and others are 0, indicating "maximally pessimize these".
But it has never occurred to me to do this, and it's easy to simulate
this by using 100s and 1s, say.
In the compiler we have a function which inserts the "cast closure" of
an expression. It accepts the expression as a candidate as well as a
large list of cast-wrapped variants of the expression. For each
candidate it rejects it if it is consensus-invalid or has malleable
satisfactions.

In the original compiler (PR rust-bitcoin#29) it would decide whether an expression
was malleable by checking ty.mall.non_malleable on the miniscript. It
had the confusing comment "return malleable types directly" which I
believe was supposed to mean "return early if the node is malleable".
The comment also observes that "If a elem is malleable, all the casts to
it are also going to be malleable" but the code doesn't actually use
this fact anywhere. It always tries all the casts. But ok, whatever.

Later in rust-bitcoin#97 (add context to Miniscript) we weakened the malleability
check in a bizarre way -- now it checks that the node is malleable
according to the type system AND that it is non-malleable according to
the context system. That is, we whitelist or_i and d: as "acceptable
malleability" in a legacy/bare context.

This change, which was not commented on in the original PR, seems like
it's just totally wrong. I suspect it was supposed to be an or: if the
node is malleable according to the type system OR according to the
contextual checks, then skip it. But I'm unsure. (The check is also
wrong because the contextual check is wrong; see the last commit.)

Anyway, after some fairly heavy fuzzing I was unable to find any
instance where this check affects compiler output. I suspect that it's
merely an optimization. So change it back to the stronger, simpler check
and update the comment.
These can't be constfs but they're still useful.
This eliminates some expect()s and is plausibly faster.
…lerError

The limitation that we have only binary and()s and or()s is really just
a compiler limit; it's neither needed nor enforced when parsing
policies, printing them, lifting them, etc etc.

Maybe we _want_ to enforce this at the type level, but we don't now, and
given that, these error variants are in the wrong place (and will get in
the way of the refactors in the next commit).
Copy link
Member Author

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On c317cd7 successfully ran local tests

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants