-
Notifications
You must be signed in to change notification settings - Fork 142
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Taproot Compiler #291
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
@@ -994,7 +995,9 @@ where | |||
}) | |||
.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
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
@@ -128,6 +137,33 @@ impl fmt::Display for PolicyError { | |||
} | |||
|
|||
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:
|
ad6c02b
to
0ec0202
Compare
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
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 aTapTree
.Follow Up PRs
TapTree
to optimize over the expected average total cost.thresh
k
-of-n
and similar structures.