Conversation
98c970d to
6135e57
Compare
|
@sanket1729 Kindly review this PR while I add the required docs for tr.rs. |
sanket1729
left a comment
There was a problem hiding this comment.
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.
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.
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::{ | |||
src/descriptor/tr.rs
Outdated
| use {miniscript::Miniscript, Error, MiniscriptKey}; | ||
|
|
||
| // TODO: Update this to infer version from descriptor. | ||
| const VER: u8 = 0xc0; |
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.
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.
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.
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.
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.
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.
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.
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.
in 73dd23e, this is fine.
Adding this change to check this is re-enabled again.
c0930e6 to
73ad38d
Compare
sanket1729
left a comment
There was a problem hiding this comment.
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.
more idiomatic to call left_tree.taptree_height()
There was a problem hiding this comment.
and same for right tree below
| }; | ||
|
|
||
| if nodes > TAPROOT_MAX_NODE_COUNT { | ||
| Ok(Self { internal_key, tree }) |
There was a problem hiding this comment.
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.
There is no need for this function to return a result, it should return &Pk.
There was a problem hiding this comment.
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.
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.
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.
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.
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.
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
sanket1729
left a comment
There was a problem hiding this comment.
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.
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.
@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
|
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)