Skip to content
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

skip policy compilation when parsing descriptor #1553

Conversation

jp1ac4
Copy link
Collaborator

@jp1ac4 jp1ac4 commented Jan 22, 2025

This allows to create a new LianaPolicy without checking that it compiles into miniscript. This compilation check is used as a sanity check on the policy in addition to other Liana-specific checks, but this compiled policy is not otherwise used.

When parsing an existing descriptor, we will assume that the policy can be compiled. Otherwise, the method LianaPolicy::from_multipath_descriptor ends up calling LianaPolicy::into_multipath_descriptor_fallible.

A LianaPolicy is created from a descriptor each time we call LianaDescriptor::from_str, which is done often, e.g. when updating derivation indices in the DB. Removing the compilation check won't affect the LianaDescriptor that we end up with when parsing a string as we already use the Descriptor obtained from parsing the string rather than that obtained by compilation of the policy.

This change is particularly important with the upcoming upgrade to miniscript 12.0, which has been found to increase Liana policy compilation times significantly.

An additional option would be to reduce the number of times we call LianaDescriptor::from_str, e.g. by passing the descriptor as a parameter rather than reading from DB, but this current change should address the main performance issues.

@jp1ac4 jp1ac4 self-assigned this Jan 22, 2025
Copy link
Member

@darosior darosior left a comment

Choose a reason for hiding this comment

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

Concept ACK. Also it actually does not have the downside i mentioned to you privately: we still only ever store desc strings we generate, not the one we were given.

Comment on lines +650 to +658
// We don't compile the policy as we assume it compiles given we started with a descriptor.
// This will still perform all other checks to make sure the descriptor conforms to
// a Liana policy.
LianaPolicy::_new(
prim_path,
recovery_paths,
is_taproot,
/* compile = */ false,
)
Copy link
Member

Choose a reason for hiding this comment

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

The policy compilation would perform Miniscript sanity checks. Is it necessary to manually call sanity_check on the descriptor instead? Or maybe it's already called at parsing time (although technically this function is not aware of that).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for pointing this out 🙏

Yes I think then it makes sense to call this sanity_check method on the descriptor within the LianaDescriptor::from_str method.

I've checked that doing so does not noticeably harm performance when running the tests.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It looks like they're only called for Taproot: rust-bitcoin/rust-miniscript#734.

To be on the safe side, I've added a call to this method in all cases.

@jp1ac4 jp1ac4 marked this pull request as draft January 22, 2025 16:03
@jp1ac4 jp1ac4 force-pushed the liana-policy-skip-compile-when-parsing branch from 1f1a014 to 700ff94 Compare January 22, 2025 16:23
This allows to create a new `LianaPolicy` without checking that
it compiles into miniscript. This compilation check is used as
a sanity check on the policy in addition to other Liana-specific
checks, but this compiled policy is not otherwise used.

When parsing an existing descriptor, we will assume that the
policy can be compiled. Otherwise, the method `LianaPolicy::from_multipath_descriptor`
ends up calling `LianaPolicy::into_multipath_descriptor_fallible`.

A `LianaPolicy` is created from a descriptor each time we
call `LianaDescriptor::from_str`, which is done often, e.g.
when updating derivation indices in the DB. The sanity check
of the descriptor previously performed during compilation of
the policy will now be done explicitly as part of the
`LianaDescriptor::from_str` method.

Removing the compilation check won't affect the `LianaDescriptor`
that we end up with when parsing a string as we already use the
`Descriptor` obtained from parsing the string rather than that
obtained by compilation of the policy.

This change is particularly important with the upcoming upgrade
to miniscript 12.0, which has been found to increase Liana policy
compilation times significantly.

An additional option would be to reduce the number of times we
call `LianaDescriptor::from_str`, e.g. by passing the descriptor
as a parameter rather than reading from DB, but this current
change should address the main performance issues.
@jp1ac4 jp1ac4 force-pushed the liana-policy-skip-compile-when-parsing branch from 700ff94 to a95cfad Compare January 22, 2025 16:50
@jp1ac4 jp1ac4 marked this pull request as ready for review January 22, 2025 18:04
@pythcoiner
Copy link
Collaborator

utACK a95cfad

Copy link
Member

@edouardparis edouardparis left a comment

Choose a reason for hiding this comment

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

ACK a95cfad
Reviewed and quickly run with liana-gui

@edouardparis edouardparis merged commit 99db113 into wizardsardine:master Jan 23, 2025
24 checks passed
@jp1ac4 jp1ac4 deleted the liana-policy-skip-compile-when-parsing branch January 23, 2025 10:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

5 participants