-
Notifications
You must be signed in to change notification settings - Fork 168
Taproot Compiler #291
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
Taproot Compiler #291
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did an initial review. I think we would need a few more iterations before we get this.
src/policy/compiler.rs
Outdated
| .collect(); | ||
|
|
||
| if key_vec.len() == subs.len() && subs.len() <= MAX_PUBKEYS_PER_MULTISIG { | ||
| if Ctx::sig_type() == SigType::Schnorr { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: prefer explicit matching over all script arms instead of if else
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactored in b36c116
src/policy/concrete.rs
Outdated
| #[cfg(feature = "compiler")] | ||
| use Miniscript; | ||
| #[cfg(feature = "compiler")] | ||
| use Tap; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: You can import all of these in one line.
#[cfg(feature = "compiler")]
use {}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactored in b36c116
src/policy/concrete.rs
Outdated
| impl<Pk: MiniscriptKey> Policy<Pk> { | ||
| /// Single-Node compilation | ||
| #[cfg(feature = "compiler")] | ||
| fn compile_huffman_taptree(policy: &Self) -> Result<TapTree<Pk>, Error> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a convention to use &self instead of &Self. &self stands for self: &Self
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is called compile_huffman. I expect in the next commit it would do something different
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. The naming convention for the function was kept keeping future in mind. I'll rename it to compile_leaf_taptree for proper naming convention for this commit.
src/policy/concrete.rs
Outdated
| } | ||
| /// Extract the Taproot internal_key from policy tree. | ||
| #[cfg(feature = "compiler")] | ||
| fn extract_key(policy: &Self, unspendable_key: Option<Pk>) -> Result<(Pk, &Policy<Pk>), Error> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comment about &Self. This function should consume self. Functionally this should change the policy and extra the internal key out of it. I think this maybe done in the next commit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would require us to make the compile_tr function consume self which doesn't align with the compile<Pk, Ctx>(&self) function. I will update this function as suggested and use a cloned copy for the same until we discuss further.
src/policy/semantic.rs
Outdated
| 1, | ||
| vec![Policy::KeyHash("".to_owned()), Policy::Older(1000),] | ||
| ) | ||
| Policy::Threshold(1, vec![Policy::KeyHash("".to_owned()), Policy::Older(1000)]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes in semantic.rs apart from pub(crate) one seem unnecessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see this is because you removed the "," at the end of all lines. This change is okay, but it is not a part of this commit. But I can live with this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i would recommend to bump 1.58.0 and then cargo fmt as one commit maybe?
src/policy/concrete.rs
Outdated
|
|
||
| for key in concrete_keys.iter() { | ||
| if semantic_policy | ||
| .clone() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This algorithm is poor in memory performance because it calls clone for every single iteration. We can do a new tree traversal for every key we see. I think we will eventually need a better algorithm that avoids all these allocations.
We can first focus on the correctness/code hygine of the PR, then address these efficiency issues.
b10cb7a to
e507066
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very close. Last few comments.
src/policy/concrete.rs
Outdated
| .pop() | ||
| .expect("huffman tree algorithm is broken") | ||
| .1; | ||
| Ok((*node).clone()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggested how to fix it above.
src/policy/semantic.rs
Outdated
| 1, | ||
| vec![Policy::KeyHash("".to_owned()), Policy::Older(1000),] | ||
| ) | ||
| Policy::Threshold(1, vec![Policy::KeyHash("".to_owned()), Policy::Older(1000)]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see this is because you removed the "," at the end of all lines. This change is okay, but it is not a part of this commit. But I can live with this
1a1d192 to
4358e88
Compare
4358e88 to
f47ba52
Compare
255fbed to
4b8c5fe
Compare
|
shouldn't this try to compile the common: And(Or(a,b), Or(c,d)) to: ac ad bc bd? how do we judge if the increased number of nodes vs script length cutoff makes sense? It seems like there is a script length beyond which it always makes sense, maybe like 32 byte script? the issue is that many scripts it'd be exp to actually do this unrolling, but it's what i'd expect. |
|
@JeremyRubin You're right in the intuitive analysis of the method taproot compiler should ideally adopt. I plan on introducing this type to reduction/ enumeration of policy nodes in a follow-up PR. The reason to keep that on hold was to understand if doing so would turn out to be intractable. For example:- Consider a generic |
|
@sanket1729 is there plans of getting this into the release? |
|
@dr-orlovsky, no this won't go into the release. There is still some work to be done here, and the compiler implemented here is feature complete. We still have a few things we want before we support this. Maybe we will have another release with support for partial descriptors, unspendable key support, musig descriptors etc... Possibly 1 month from now |
4b8c5fe to
96b4e66
Compare
| let mut prob = 0.; | ||
| let semantic_policy = self.lift()?; | ||
| let concrete_keys = self.keys(); | ||
| let key_prob_map: HashMap<_, _> = self |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic of internal-key extraction has been changed from selecting first-encountered key satisfying the policy to most-probable key satisfying the policy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the ertract key is updated in next commit. No need to fix it here.
96b4e66 to
6e5a600
Compare
|
Can you rebase on top of master.? And remove the last CI commit. |
src/policy/concrete.rs
Outdated
| f: T, | ||
| ) -> Result<TapTree<Pk>, Error> | ||
| where | ||
| T: Fn(OrdF64) -> OrdF64, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's not have this confusing argument for now. And hard-code whatever dummy metric we have
6e5a600 to
ad6c02b
Compare
|
Changes in the force update:
|
0ec0202 to
658a66b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks mostly good
|
@SarcasticNastik can you also add in the description how all the PRs relate and what they do. |
3e9214c to
08c6530
Compare
|
Sorry, @SarcasticNastik this would require a rebase again :( . @apoelstra requesting your review. This is a major contribution from a new contributor and I don't want to go ahead without your review. The commit messages and PR description are helpful in understanding how this is structured. |
08c6530 to
e08486d
Compare
|
@sanket1729 I've rebased the PR onto current master. @apoelstra A kind request for your review. EDIT
|
e08486d to
4831134
Compare
A new method `compile_tr` is introduced in policy for creating a Tr descriptor with TapTree containing single script child-node. An internal-key extraction method from the policy has also been implemented for the same.
The internal-key extraction method now selects the most-likely key (in the policy) as suggested by BIP341.
Introduce a `compiler_tr` API for compiling a policy to a Tr Descriptor.
Testing done.
4831134 to
2b13694
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 2b13694
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 2b13694 . Let's push forward on this. In the interest of ACKs and multiple rebases already done here, I am merging this. We recently shifted to rust 2018. And this code has a bunch of warnings because of it.
ef4249d Add taproot compiler example usage (Aman Rojjha) cef2a5b Add Tr-compiler write-up and doc-comment (Aman Rojjha) 5233c66 Add Taproot compiler API (Aman Rojjha) Pull request description: This PR builds on top of #291. This aims to introduce an efficient version of the tapscript compiler by using a few heuristics to optimize over the expected average total cost for the TapTree. ## Strategy implemented - While merging TapTrees `A` and `B`, check whether the compilation of `Policy::Or(policy(A), policy(B))` is more efficient than a TapTree with the respective children `A` and `B`. **Note**: This doesn't include the `thresh(k, ...n..)` enumeration strategy. Planning on working on it separately. ACKs for top commit: sanket1729: ACK ef4249d Tree-SHA512: ae5949b5170ff4cc8202434655af41b4938e96801209896d117bf4e4bd85c0becc6fd0c7affb100c31655f0085c1ff5e7c19184db3433b2831f73db22d94348d
169d849 Add policy to descriptor target compilation method (Aman Rojjha) Pull request description: This PR works on top of #291 and #342. It introduces a new function `compile_to_descriptor` which requires a `DescriptorCtx` (suggestions for a better enum name are welcome!) allowing directly compilation of a policy into the specified descriptor type. ACKs for top commit: apoelstra: ACK 169d849 sanket1729: ACK 169d849 Tree-SHA512: 0f895f4774ea4f56db76280ac756df616a70e5d7d60cc128f9a050ef86658f786b2d45885d748dba51751146a6e93b3731f4ae193b7d80284ffaea20be1e8f92
2b1369409adb49c838253572a59d05b00060df23 Add non-trivial multi-node example (Aman Rojjha)
1c2a80e33cbc183e4db5ce74a4c40a11b0a1217e Add validity and malleability checks. (Aman Rojjha)
0866807031ade6879ca4ef7d6cfac6ac5f14140d Add P2Tr compiler (Aman Rojjha)
285207e26f25939e9108c810f573ca6d74d3f230 Internal-key extraction done (Aman Rojjha)
26fc574434e90117280c9579d28bbcccb1d300d5 Policy to single-leaf TapTree compilation done (Aman Rojjha)
Pull request description:
This PR builds on top of #278.
This is one in a series of PRs aimed to implement a feature-complete *Pay-to-Taproot* **P2Tr** compiler.
Specifically, this introduces a basic compilation for a given policy by collecting the leaf nodes of the *tree* generated by considering root-level disjunctive `OR`and using this to generate a `TapTree`.
> Assuming that _duplicate keys_ are **NOT** possible even in different branches of the TapTree.
# Follow Up PRs
- #342 - Uses heuristic for tree-generation/ _merging_ algorithm while buillding `TapTree` to optimize over the *expected average total cost*.
- #352
- A future PR implementing enumerative strategies for optimizing `thresh` `k`-of-`n` and similar structures.
ACKs for top commit:
apoelstra:
ACK 2b1369409adb49c838253572a59d05b00060df23
sanket1729:
ACK 2b1369409adb49c838253572a59d05b00060df23 . Let's push forward on this. In the interest of ACKs and multiple rebases already done here, I am merging this. We recently shifted to rust 2018. And this code has a bunch of warnings because of it.
Tree-SHA512: 4ceca51a383f5d52b572a16937bbcc3a9c53f0247e4b6df57a6547fd0b1c7cc33ff04dd9a476914bcf6d0a09e255918b8f7ebfe176c839d6ae31c84613dce67f

This PR builds on top of #278.
This is one in a series of PRs aimed to implement a feature-complete Pay-to-Taproot P2Tr compiler.
Specifically, this introduces a basic compilation for a given policy by collecting the leaf nodes of the tree generated by considering root-level disjunctive
ORand using this to generate aTapTree.Follow Up PRs
TapTreeto optimize over the expected average total cost.threshk-of-nand similar structures.