-
Notifications
You must be signed in to change notification settings - Fork 142
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
Add tr descriptor #278
Add tr descriptor #278
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.
Concept ACK. Left two API improvement suggestions
// A new leaf version would require a new Context, therefore there is no point | ||
// in adding a LeafVersion with Leaf type here. All Miniscripts right now | ||
// are of Leafversion::default | ||
Leaf(Arc<Miniscript<Pk, 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.
I think the problem may be solved by having a dedicated enum variant for each Leaf version. So this will become LeafTapScript
, the enum will become #[non_exhaustive]
and there will be no problem to add more contexts with more enum variants with post-0xC0
leafs
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.
Yeah, marking everything non-exhaustive is a big step. I suppose we will have a big breaking as soon as the MSRV lands
@@ -63,6 +63,26 @@ impl<Pk: MiniscriptKey> Bare<Pk> { | |||
} | |||
} | |||
|
|||
impl<Pk: MiniscriptKey + ToPublicKey> Bare<Pk> { |
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 think all this non-failing methods can be re-organized into an additional trait, let's say PreTaprootDescriptor: Descriptor
, such that all pre-taproot descriptor types may be used as a generalized function arguments
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.
We could do for the release. But I think that the effort is not worth it considering everything will go back to non-fallible once we have a new major breaking release of rust-secp that has static contexts
cbe744e
to
9581f2e
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.
Spotted one bug
// This belongs in rust-bitcoin, make this upstream later | ||
pub(crate) fn script_is_v1_tr(s: &Script) -> bool { | ||
let mut iter = s.instructions_minimal(); | ||
if s.len() != 32 |
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 is bug: the key is 32 bytes indeed, but the script s 34.
if s.len() != 32 | |
if s.len() != 34 |
let mut iter = s.instructions_minimal(); | ||
if s.len() != 32 | ||
|| iter.next() != Some(Ok(Instruction::Op(opcodes::all::OP_PUSHNUM_1))) | ||
|| iter.next() != Some(Ok(Instruction::Op(opcodes::all::OP_PUSHBYTES_32))) |
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 does not work neither, I do not know why. But using spk.is_v1_p2tr()
makes things working
1a63641
to
90fabf6
Compare
90fabf6
to
f11baaa
Compare
f11baaa
to
6d920ed
Compare
src/descriptor/tr.rs
Outdated
let spend_info = self | ||
.spend_info | ||
.as_ref() | ||
.ok_or(Error::TaprootSpendInfoUnavialable)?; |
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 error case is the thing that forces us to make script_pubkey()
return a Result
right? Wouldn't it be preferable to make caching spend_info
optional. So make a public API for caching it but if it hasn't been cached just compute it on the fly. For me, the risk of possibly doing some extra (usually minor) computation seems better than giving me a Result
that I may arrogantly .unwrap()
.
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 is not possible because we require a secp
parameter to do the tweaking. Creating a new context inside a method is expensive and causes severe performance issues. This would go away once we get static verification tables in rust-secp, but still a while to go.
I am also unhappy with the current PR :( . Some rough thoughts,
- I am considering more changes in the type system to distinguish between
Derived
andUnDerived
descriptors. We would then implementDescriptorTriat
only forDerived
descriptors. Or perhaps having two traits. - I also don't like that
address()
fails for raw descriptors which are not that common. MaybeDescriptorTrait
methods are not that useful.
I will make another candidate PR by tomorrow with the goal of avoiding unwraps() for common case like script_pubkey
and address
etc
@apoelstra, the last commit is a suggested way to avoid calling It would be great if we can get rust-secp release with static contexts, then we don't have to worry about caching at all. In the interest of moving things forward, I will be separating the PR into two parts. Adding a 1) native |
hey @sanket1729 -- I've been testing out this branch. FWIW I found the One thing that I found to be inconvenient was that the |
Hey @LLFourn, good news is that we now would not even have to do the
I stopped working on this, because the cheap context creation means that we should be back to the old API :) |
I did some benchmarking on the rust-bitcoin/rust-secp256k1#384 for the tweaking. Currently
After the update:
Ideally (with full static context support), meaning no calls to context_create.
A 100 times increase from 5ms to 50mirco s. I think (for now), it is acceptable to create a new context with a double overhead. This is a massive improvement over the previous 100 times overhead. This can be improved later when we have an API without secp context like I will be working on a follow-up PR where we use interior mutability to cache the spend_data so that only the first invocation would be costly. Subsequent invocations can use the cached value of |
f83f62b
to
abe64dd
Compare
The 50us delay should also go away in the near(ish) future -- I believe it is caused by our current logic re-randomizing even static contexts on creation, which (a) ought to be done at compile-time, it doesn't use fresh randomness, and (b) doesn't need to be done at all for verification-only contexts. See rust-bitcoin/rust-secp256k1#388 for further discussion |
e210332
to
c81d9ab
Compare
I really like the removal of |
97bab62
to
f3f37b0
Compare
fixups to Tr descriptor code from SarcasticNastik
Co-authored-by: SarcasticNastik <aman.rojjha@research.iiit.ac.in>
Fix TapTree iter depth Fix tr spend_info lock * Attempt to read cache prior to matching on spend_info Option * This bug would cause function to hang * Also added test tr_script_pubkey Co-authored-by: nickfarrow <nicholas.w.farrow@gmail.com>
f3f37b0
to
f5c8d7f
Compare
Thanks @nickfarrow, merged, credited, and squashed your commit into 7eac908. |
Done reviewing f5c8d7f Overall looks great. A few comments, which I think should be addressed in future PRs:
Finally, I have some fixups at https://github.com/apoelstra/rust-miniscript/tree/2022-02--278-fixups -- mostly minor stuff, but I also cleaned up the locking code. |
I don't follow this. Every
Agreed.
The naming was mostly done to mimic the psbt naming. This is slightly more complicated because there are two different uses of Schnorr sigs. Overall, we have three main types of sigs:
So, really need different types here :( because the function signatures vastly differ for key_spend and script_spend.
I am also not happy with the current state of parsing. I will dedup it in a follow-up PR.
Any special reason why you prefer .clone() on |
I may be confused. What happens if you create a
Can you elaborate on the difference between the latter two cases?
No special reason. The docs on |
The internal key would return the internal key correctly. The script_pubkey()/spk() API calculation would calculate the output key as per BIP341.
One needs to know the leaf_hash under which the signature is applicable, the key spend one does not
I can do it in the follow-up PR. I like calling Arc::clone() because it clearly highlights that it is a cheap clone. |
@sanket1729 ah! Ok, I missed the BIP341 logic. Alright, I'm happy. If you cherry-pick my commits I'll ACK this. (Or I can change the |
@sanket1729 there are four extra commits on my branch |
@apoelstra, oops. Missed those |
There are multiple `Tree`s in this file and the expression Tree is a somewhat obscure one. It is confusing to have it referenced without any qualification.
1. `RwLock` is typically much slower than `Mutex`, so the Rust developers discourage its use unless you really need lots of simultaneous readers. We do not, we only need to unlock this mutex for tiny amounts of time locking logic 2. The `clone` implementation missed an opportunity to clone an internal `Arc`, instead using `Mutex::new(None)` and forcing the clone to recompute the spend info. 3. Minor idiomatic cleanups.
170bc3e
to
7195bd7
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 7195bd7
Good to merge, I think.
Awesome. Working on fixups based on this |
2b13694 Add non-trivial multi-node example (Aman Rojjha) 1c2a80e Add validity and malleability checks. (Aman Rojjha) 0866807 Add P2Tr compiler (Aman Rojjha) 285207e Internal-key extraction done (Aman Rojjha) 26fc574 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 2b13694 sanket1729: 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. Tree-SHA512: 4ceca51a383f5d52b572a16937bbcc3a9c53f0247e4b6df57a6547fd0b1c7cc33ff04dd9a476914bcf6d0a09e255918b8f7ebfe176c839d6ae31c84613dce67f
No description provided.