Skip to content

Commit a314848

Browse files
committed
Merge rust-bitcoin/rust-bitcoin#924: Improvements to taproot script iterator
3c59897 Removed IntoIterator for TapTree implementation (Dr Maxim Orlovsky) 7a5482d Rename LeafInfo into ScriptLeaf (Dr Maxim Orlovsky) 2b8d965 Rename TapTree::iter into TapTree::script_leaves (Dr Maxim Orlovsky) 6f871ba Add convenience LeafInfo::depth method (Dr Maxim Orlovsky) 3c502ff Making all LeafInfo fields private (Dr Maxim Orlovsky) d655ff3 Make TapTreeIterator use LeafInfo (Dr Maxim Orlovsky) 79345fc LeafInfo field accessor methods (Dr Maxim Orlovsky) 5958466 Make LeafInfo::leaf_hash public and change its name and return type (Dr Maxim Orlovsky) c83893d Make taproot LeafInfo public (Dr Maxim Orlovsky) Pull request description: This PR makes existing taproot script iterator to iterate `LeafScript` values instead of constructed `(u8, &Script)`. First, this is more idiomatic (iterator should not construct value but iterate through real internal representation); second information about merkle path of the scripts is required for me downstream to implement OP_RETURN taproot commitments. The PR also removes unnecessary iterator type, replacing it with a slice iterator type from the core rust library. I am asking to include this PR into RC fix scope, since it is required downstream. ACKs for top commit: sanket1729: ACK 3c59897. Reviewed the range-diff with the post that I previously ACKed Tree-SHA512: 99e341443987204a8aba20869c750bd80a725f3d49d1b5731d554dff7377181b02a4517f8b390101afb2957135dbb255c6e360f90cadd6ee07b17eb14fd30af5
2 parents 8efc9a1 + 22fadf4 commit a314848

File tree

3 files changed

+60
-43
lines changed

3 files changed

+60
-43
lines changed

src/util/psbt/map/output.rs

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use util::psbt::map::Map;
2626
use util::psbt::raw;
2727
use util::psbt::Error;
2828

29-
use util::taproot::{LeafInfo, TapLeafHash};
29+
use util::taproot::{ScriptLeaf, TapLeafHash};
3030

3131
use util::taproot::{NodeInfo, TaprootBuilder};
3232

@@ -155,43 +155,33 @@ impl TapTree {
155155
self.0
156156
}
157157

158-
/// Returns iterator for a taproot script tree, operating in DFS order over leaf depth and
159-
/// leaf script pairs.
160-
pub fn iter(&self) -> TapTreeIter {
161-
self.into_iter()
158+
/// Returns [`TapTreeIter`] iterator for a taproot script tree, operating in DFS order over
159+
/// tree [`ScriptLeaf`]s.
160+
pub fn script_leaves(&self) -> TapTreeIter {
161+
match (self.0.branch().len(), self.0.branch().last()) {
162+
(1, Some(Some(root))) => {
163+
TapTreeIter {
164+
leaf_iter: root.leaves.iter()
165+
}
166+
}
167+
// This should be unreachable as we Taptree is already finalized
168+
_ => unreachable!("non-finalized tree builder inside TapTree"),
169+
}
162170
}
163171
}
164172

165173
/// Iterator for a taproot script tree, operating in DFS order over leaf depth and
166174
/// leaf script pairs.
167175
pub struct TapTreeIter<'tree> {
168-
leaf_iter: core::slice::Iter<'tree, LeafInfo>,
176+
leaf_iter: core::slice::Iter<'tree, ScriptLeaf>,
169177
}
170178

171179
impl<'tree> Iterator for TapTreeIter<'tree> {
172-
type Item = (u8, &'tree Script);
180+
type Item = &'tree ScriptLeaf;
173181

182+
#[inline]
174183
fn next(&mut self) -> Option<Self::Item> {
175-
self.leaf_iter.next().map(|leaf_info| {
176-
(leaf_info.merkle_branch.as_inner().len() as u8, &leaf_info.script)
177-
})
178-
}
179-
}
180-
181-
impl<'tree> IntoIterator for &'tree TapTree {
182-
type Item = (u8, &'tree Script);
183-
type IntoIter = TapTreeIter<'tree>;
184-
185-
fn into_iter(self) -> Self::IntoIter {
186-
match (self.0.branch().len(), self.0.branch().last()) {
187-
(1, Some(Some(root))) => {
188-
TapTreeIter {
189-
leaf_iter: root.leaves.iter()
190-
}
191-
}
192-
// This should be unreachable as we Taptree is already finalized
193-
_ => unreachable!("non-finalized tree builder inside TapTree"),
194-
}
184+
self.leaf_iter.next()
195185
}
196186
}
197187

src/util/psbt/serialize.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -327,9 +327,9 @@ impl Serialize for TapTree {
327327
//
328328
// TaprootMerkleBranch can only have len atmost 128(TAPROOT_CONTROL_MAX_NODE_COUNT).
329329
// safe to cast from usize to u8
330-
buf.push(leaf_info.merkle_branch.as_inner().len() as u8);
331-
buf.push(leaf_info.ver.to_consensus());
332-
leaf_info.script.consensus_encode(&mut buf).expect("Vecs dont err");
330+
buf.push(leaf_info.merkle_branch().as_inner().len() as u8);
331+
buf.push(leaf_info.leaf_version().to_consensus());
332+
leaf_info.script().consensus_encode(&mut buf).expect("Vecs dont err");
333333
}
334334
buf
335335
}

src/util/taproot.rs

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ pub struct NodeInfo {
560560
/// Merkle hash for this node.
561561
pub(crate) hash: sha256::Hash,
562562
/// Information about leaves inside this node.
563-
pub(crate) leaves: Vec<LeafInfo>,
563+
pub(crate) leaves: Vec<ScriptLeaf>,
564564
/// Tracks information on hidden nodes below this node.
565565
pub(crate) has_hidden_nodes: bool,
566566
}
@@ -577,9 +577,9 @@ impl NodeInfo {
577577

578578
/// Creates a new leaf [`NodeInfo`] with given [`Script`] and [`LeafVersion`].
579579
pub fn new_leaf_with_ver(script: Script, ver: LeafVersion) -> Self {
580-
let leaf = LeafInfo::new(script, ver);
580+
let leaf = ScriptLeaf::new(script, ver);
581581
Self {
582-
hash: leaf.hash(),
582+
hash: sha256::Hash::from_inner(leaf.leaf_hash().into_inner()),
583583
leaves: vec![leaf],
584584
has_hidden_nodes: false,
585585
}
@@ -608,17 +608,17 @@ impl NodeInfo {
608608
/// Store information about taproot leaf node.
609609
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
610610
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
611-
pub(crate) struct LeafInfo {
611+
pub struct ScriptLeaf {
612612
/// The underlying script.
613-
pub(crate) script: Script,
613+
script: Script,
614614
/// The leaf version.
615-
pub(crate) ver: LeafVersion,
615+
ver: LeafVersion,
616616
/// The merkle proof (hashing partners) to get this node.
617-
pub(crate) merkle_branch: TaprootMerkleBranch,
617+
merkle_branch: TaprootMerkleBranch,
618618
}
619619

620-
impl LeafInfo {
621-
/// Creates an new [`LeafInfo`] from `script` and `ver` and no merkle branch.
620+
impl ScriptLeaf {
621+
/// Creates an new [`ScriptLeaf`] from `script` and `ver` and no merkle branch.
622622
fn new(script: Script, ver: LeafVersion) -> Self {
623623
Self {
624624
script: script,
@@ -627,10 +627,37 @@ impl LeafInfo {
627627
}
628628
}
629629

630-
/// Computes a leaf hash for this [`LeafInfo`].
631-
fn hash(&self) -> sha256::Hash {
632-
let leaf_hash = TapLeafHash::from_script(&self.script, self.ver);
633-
sha256::Hash::from_inner(leaf_hash.into_inner())
630+
/// Returns the depth of this script leaf in the tap tree.
631+
#[inline]
632+
pub fn depth(&self) -> u8 {
633+
// The depth is guaranteed to be < 127 by the TaprootBuilder type.
634+
// TODO: Following MSRV bump implement via `try_into().expect("")`.
635+
self.merkle_branch.0.len() as u8
636+
}
637+
638+
/// Computes a leaf hash for this [`ScriptLeaf`].
639+
#[inline]
640+
pub fn leaf_hash(&self) -> TapLeafHash {
641+
TapLeafHash::from_script(&self.script, self.ver)
642+
}
643+
644+
/// Returns reference to the leaf script.
645+
#[inline]
646+
pub fn script(&self) -> &Script {
647+
&self.script
648+
}
649+
650+
/// Returns leaf version of the script.
651+
#[inline]
652+
pub fn leaf_version(&self) -> LeafVersion {
653+
self.ver
654+
}
655+
656+
/// Returns reference to the merkle proof (hashing partners) to get this
657+
/// node in form of [`TaprootMerkleBranch`].
658+
#[inline]
659+
pub fn merkle_branch(&self) -> &TaprootMerkleBranch {
660+
&self.merkle_branch
634661
}
635662
}
636663

0 commit comments

Comments
 (0)