Implement TryFrom<TaprootBuilder> for TapTree

TryFrom` became available in Rust 1.34 so we can use it now we have
bumped our MSRV.

Implement `TryFrom<TaprootBuilder>` for `TapTree` and deprecate the
`from_builder` method.
This commit is contained in:
Tobin C. Harding 2022-05-25 16:44:18 +10:00
parent 632a5db8d9
commit 5c49fe775f
2 changed files with 27 additions and 9 deletions

View File

@ -14,6 +14,7 @@
use crate::prelude::*; use crate::prelude::*;
use core; use core;
use core::convert::TryFrom;
use crate::io; use crate::io;
@ -158,16 +159,12 @@ impl TapTree {
/// # Returns /// # Returns
/// A [`TapTree`] iff the `builder` is complete, otherwise return [`IncompleteTapTree`] /// A [`TapTree`] iff the `builder` is complete, otherwise return [`IncompleteTapTree`]
/// error with the content of incomplete `builder` instance. /// error with the content of incomplete `builder` instance.
#[deprecated(since = "0.29.0", note = "use try_from instead")]
pub fn from_builder(builder: TaprootBuilder) -> Result<Self, IncompleteTapTree> { pub fn from_builder(builder: TaprootBuilder) -> Result<Self, IncompleteTapTree> {
if !builder.is_finalized() { Self::try_from(builder)
Err(IncompleteTapTree::NotFinalized(builder))
} else if builder.has_hidden_nodes() {
Err(IncompleteTapTree::HiddenParts(builder))
} else {
Ok(TapTree(builder))
}
} }
/// Converts self into builder [`TaprootBuilder`]. The builder is guaranteed to be finalized. /// Converts self into builder [`TaprootBuilder`]. The builder is guaranteed to be finalized.
pub fn into_builder(self) -> TaprootBuilder { pub fn into_builder(self) -> TaprootBuilder {
self.0 self.0
@ -194,6 +191,25 @@ impl TapTree {
} }
} }
impl TryFrom<TaprootBuilder> for TapTree {
type Error = IncompleteTapTree;
/// Constructs [`TapTree`] from a [`TaprootBuilder`] if it is complete binary tree.
///
/// # Returns
/// A [`TapTree`] iff the `builder` is complete, otherwise return [`IncompleteTapTree`]
/// error with the content of incomplete `builder` instance.
fn try_from(builder: TaprootBuilder) -> Result<Self, Self::Error> {
if !builder.is_finalized() {
Err(IncompleteTapTree::NotFinalized(builder))
} else if builder.has_hidden_nodes() {
Err(IncompleteTapTree::HiddenParts(builder))
} else {
Ok(TapTree(builder))
}
}
}
/// Iterator for a taproot script tree, operating in DFS order over leaf depth and /// Iterator for a taproot script tree, operating in DFS order over leaf depth and
/// leaf script pairs. /// leaf script pairs.
pub struct TapTreeIter<'tree> { pub struct TapTreeIter<'tree> {

View File

@ -370,6 +370,8 @@ fn key_source_len(key_source: &KeySource) -> usize {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use core::convert::TryFrom;
use crate::hashes::hex::FromHex; use crate::hashes::hex::FromHex;
use super::*; use super::*;
@ -393,14 +395,14 @@ mod tests {
let mut builder = compose_taproot_builder(0x51, &[2, 2, 2]); let mut builder = compose_taproot_builder(0x51, &[2, 2, 2]);
builder = builder.add_leaf_with_ver(3, Script::from_hex("b9").unwrap(), LeafVersion::from_consensus(0xC2).unwrap()).unwrap(); builder = builder.add_leaf_with_ver(3, Script::from_hex("b9").unwrap(), LeafVersion::from_consensus(0xC2).unwrap()).unwrap();
builder = builder.add_hidden_node(3, sha256::Hash::default()).unwrap(); builder = builder.add_hidden_node(3, sha256::Hash::default()).unwrap();
assert!(TapTree::from_builder(builder).is_err()); assert!(TapTree::try_from(builder).is_err());
} }
#[test] #[test]
fn taptree_roundtrip() { fn taptree_roundtrip() {
let mut builder = compose_taproot_builder(0x51, &[2, 2, 2, 3]); let mut builder = compose_taproot_builder(0x51, &[2, 2, 2, 3]);
builder = builder.add_leaf_with_ver(3, Script::from_hex("b9").unwrap(), LeafVersion::from_consensus(0xC2).unwrap()).unwrap(); builder = builder.add_leaf_with_ver(3, Script::from_hex("b9").unwrap(), LeafVersion::from_consensus(0xC2).unwrap()).unwrap();
let tree = TapTree::from_builder(builder).unwrap(); let tree = TapTree::try_from(builder).unwrap();
let tree_prime = TapTree::deserialize(&tree.serialize()).unwrap(); let tree_prime = TapTree::deserialize(&tree.serialize()).unwrap();
assert_eq!(tree, tree_prime); assert_eq!(tree, tree_prime);
} }