-
Couldn't load subscription status.
- Fork 168
Taproot descriptor #267
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 descriptor #267
Conversation
98c970d to
6135e57
Compare
|
@sanket1729 Kindly review this PR while I add the required docs for tr.rs. |
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 looks good. I just did a partial review and left some specific comments in the first commit.
Here are some general remarks:
In general, commits should be atomic (and they should just do one thing and the one thing completely in that commit) and they should do pass all tests/build.
A good way to test this is via -x option in git rebase.
git rebase -i HEAD~4 -x "cargo test --features=compiler". This will stop the code at the commit where the build/test fails, you can fix the changes there and git rebase --continue.
It might take a while to get familiar with advanced git techniques, but it is an important skill in the long run. Every project uses this method so that it is easier for tools like git bisect(essentially a binary search on commits) to figure out errors when something goes wrong and figure out which commit things went bad.
I think for starters, you can separate this into two commits. Adding the code and later another commit for adding the test.
| mod segwitv0; | ||
| mod sh; | ||
| mod sortedmulti; | ||
| mod tr; |
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.
In 73dd23e,
You should be exposing public utilities from private module tr to the external user. In particular, I think you need to expose TapTree/Tr.
A good exercise might be to write an example (see /examples folder) to see how an external user might use the library.
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 still not addressed
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 still need a statement with pub use self::tr::{TapTree} and all other utilities that need to be exposed.
src/descriptor/tr.rs
Outdated
| @@ -0,0 +1,201 @@ | |||
| // Tapscript | |||
|
|
|||
| // use super::{ | |||
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.
Unnecessary commented code here in 73dd23e
src/descriptor/tr.rs
Outdated
| use {miniscript::Miniscript, Error, MiniscriptKey}; | ||
|
|
||
| // TODO: Update this to infer version from descriptor. | ||
| const VER: u8 = 0xc0; |
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.
In 73dd23e,
The above two line should be removed.
src/descriptor/tr.rs
Outdated
| #[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] | ||
| pub enum TapTree<Pk: MiniscriptKey> { | ||
| Tree(Arc<TapTree<Pk>>, Arc<TapTree<Pk>>), | ||
| Miniscript_(u8, Arc<Miniscript<Pk, Segwitv0>>), |
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.
In 73dd23e,
The leaf version should be removed from Miniscript, and I think we can name the enum variants as Miniscript_ as Leaf
src/descriptor/tr.rs
Outdated
|
|
||
| #[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] | ||
| pub struct Tr<Pk: MiniscriptKey> { | ||
| key_path: 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.
rename as internal_key and tree? key_path and script_path represent the ways in which we spend scripts, not the structures.
src/descriptor/tr.rs
Outdated
| Pk::Hash: FromStr, | ||
| <Pk as FromStr>::Err: ToString, | ||
| <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString, | ||
| { |
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.
Same comment about the bounds here.
| Pk::Hash: FromStr, | ||
| <Pk as FromStr>::Err: ToString, | ||
| <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString, | ||
| { |
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.
Same comment about the bounds here. Try to separate out the functions that really need the bound into its own impl. For example, the new function Tr::new() should not need this bound.
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.
Also make accessor function for fields in Tr as those are private
src/descriptor/tr.rs
Outdated
| <Pk as FromStr>::Err: ToString, | ||
| <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString, | ||
| { | ||
| pub fn new(key_path: Pk, script_path: Option<TapTree<Pk>>) -> Result<Self, 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.
Add this check and return an error when this does not hold.
https://github.com/bitcoin/bitcoin/blob/81f4a3e84d6f30e7b12a9605dabc3359f614da93/src/script/interpreter.h#L229.
Introduce this constant in limits.rs
Right now, you can implement a simple depth/height function on Taptree.
We can cache the height/depth in the future.
| impl<'a> Tree<'a> { | ||
| fn from_slice(sl: &'a str) -> Result<(Tree<'a>, &'a str), Error> { | ||
| Self::from_slice_helper(sl, 0u32) | ||
| pub fn from_slice(sl: &'a str) -> Result<(Tree<'a>, &'a str), 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.
In 73dd23e, the function signature should be changed in this commit itself.
| #![deny(missing_docs)] | ||
| // #![deny(dead_code)] | ||
| // #![deny(unused_imports)] | ||
| // #![deny(missing_docs)] |
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.
in 73dd23e, this is fine.
Adding this change to check this is re-enabled again.
c0930e6 to
73ad38d
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.
Left some more remarks, we are getting closer :)
src/descriptor/tr.rs
Outdated
| match tree { | ||
| TapTree::Tree(ref left_tree, ref right_tree) => { | ||
| 1 + max( | ||
| Self::taptree_height(&**left_tree), |
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.
more idiomatic to call left_tree.taptree_height()
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.
and same for right tree below
| }; | ||
|
|
||
| if nodes > TAPROOT_MAX_NODE_COUNT { | ||
| Ok(Self { internal_key, tree }) |
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.
If condition is reversed. It should be error if nodes > TAPROOT_MAX_NODE_COUNT
src/descriptor/tr.rs
Outdated
| } | ||
| } | ||
|
|
||
| pub fn get_internal_key(&self) -> Result<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.
There is no need for this function to return a result, it should return &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.
In rust, typically the name get is not added for function names. See https://rust-lang.github.io/api-guidelines/naming.html#getter-names-follow-rust-convention-c-getter if you are interested for more guidelines.
src/descriptor/tr.rs
Outdated
| Ok(self.internal_key.clone()) | ||
| } | ||
|
|
||
| pub fn get_taptree(&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.
This should option and reference to TapTree. In general, try to avoid cloning(extra allocation) as possible
src/descriptor/tr.rs
Outdated
| Tree { name, args } if name.len() > 0 && args.len() == 0 => { | ||
| let script = name; | ||
| let script = Self::parse_miniscript(script)?; | ||
| let script = Arc::new(script); |
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: slight code preference for inlining some operations. You don't really need the function parse_miniscript. You can call
Miniscript::<Pk, Ctx>::from_str()
to get the miniscript directly. The function already does all the checks that you implement here. Also, the method parse_method does make sense itself inside an impl for TapTree
src/descriptor/tr.rs
Outdated
| let left_tree = Self::tr_script_path(&left_branch)?; | ||
| let right_tree = Self::tr_script_path(&right_branch)?; | ||
| let left_ref = Arc::new(left_tree); | ||
| let right_ref = Arc::new(right_tree); |
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 inlining some code instead of 6 lines.
let left = Self::tr_script_path(&args[0])?;
..
Ok(TapTree::Tree(Arc::new(left_ref), Arc::new(right_ref)))
src/descriptor/tr.rs
Outdated
| } | ||
| } | ||
|
|
||
| return if s.len() > 3 && &s[..3] == "tr(" && s.as_bytes()[s.len() - 1] == b')' { |
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.
assign let ret = expr; and do a return statement in the end
| if found == inp.len() - 1 { | ||
| Some((&inp[..], &"")) | ||
| } else { | ||
| Some((&inp[..found], &inp[found + 1..])) |
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.
Add a comment that this deals with the case when the , is the last character.
c75ffcc to
ff365fd
Compare
|
@sanket1729 I have made the suggested changes. Apart from that,
|
ff365fd to
fd12b77
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.
I think this is good overall. I can take it over from here and update the PR once #255 is merged.
| mod segwitv0; | ||
| mod sh; | ||
| mod sortedmulti; | ||
| mod tr; |
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 still need a statement with pub use self::tr::{TapTree} and all other utilities that need to be exposed.
| #[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] | ||
| pub enum TapTree<Pk: MiniscriptKey> { | ||
| Tree(Arc<TapTree<Pk>>, Arc<TapTree<Pk>>), | ||
| Leaf(Arc<Miniscript<Pk, Segwitv0>>), |
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.
@sanket1729: I assume we can't use Segwitv0 here. Neither Tap, since tapscript is only valid for leafs with hash version 0xC0. No idea how to solve this problem without refactoring the whole context system
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.
@dr-orlovsky. This is being done in #278 now
|
This commit was merged as a part of #278. |
This defines tree structure for TapTree and implements parsing of Taproot Descriptors as a part of #255 . The purpose is to get basic functionalities for the same and integrate it with the Miniscript compiler.
Feedback about changes to tr.rs and expression.rs would be really appreciated.
Trare required to parse taproot descriptor intoTree(as defined in expression.rs).TODO
tr.rsFuture Work
Descriptor(in mod.rs)