-
Notifications
You must be signed in to change notification settings - Fork 147
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
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.
@@ -45,6 +45,7 @@ mod bare; | |||
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.
@@ -38,11 +38,29 @@ pub trait FromTree: Sized { | |||
} | |||
|
|||
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.
@@ -45,6 +45,7 @@ mod bare; | |||
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.
Tr
are required to parse taproot descriptor intoTree
(as defined in expression.rs).TODO
tr.rs
Future Work
Descriptor
(in mod.rs)