diff --git a/src/util/psbt/map/mod.rs b/src/util/psbt/map/mod.rs index e0ec96eb..3b25bd21 100644 --- a/src/util/psbt/map/mod.rs +++ b/src/util/psbt/map/mod.rs @@ -24,7 +24,7 @@ mod input; mod output; pub use self::input::{Input, PsbtSighashType}; -pub use self::output::{Output, TapTree}; +pub use self::output::{Output, TapTree, IncompleteTapTree}; /// A trait that describes a PSBT key-value map. pub(super) trait Map { diff --git a/src/util/psbt/map/output.rs b/src/util/psbt/map/output.rs index 53edd2d5..643fc59a 100644 --- a/src/util/psbt/map/output.rs +++ b/src/util/psbt/map/output.rs @@ -79,6 +79,39 @@ pub struct Output { pub unknown: BTreeMap>, } +/// Error happening when [`TapTree`] is constructed from a [`TaprootBuilder`] +/// having hidden branches or not being finalized. +#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] +pub enum IncompleteTapTree { + /// Indicates an attempt to construct a tap tree from a builder containing incomplete branches. + NotFinalized(TaprootBuilder), + /// Indicates an attempt to construct a tap tree from a builder containing hidden parts. + HiddenParts(TaprootBuilder), +} + +impl IncompleteTapTree { + /// Converts error into the original incomplete [`TaprootBuilder`] instance. + pub fn into_builder(self) -> TaprootBuilder { + match self { + IncompleteTapTree::NotFinalized(builder) | + IncompleteTapTree::HiddenParts(builder) => builder + } + } +} + +impl core::fmt::Display for IncompleteTapTree { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.write_str(match self { + IncompleteTapTree::NotFinalized(_) => "an attempt to construct a tap tree from a builder containing incomplete branches.", + IncompleteTapTree::HiddenParts(_) => "an attempt to construct a tap tree from a builder containing hidden parts.", + }) + } +} + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl ::std::error::Error for IncompleteTapTree {} + /// Taproot Tree representing a finalized [`TaprootBuilder`] (a complete binary tree). #[derive(Clone, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -104,13 +137,14 @@ impl TapTree { /// Converts a [`TaprootBuilder`] into a tree if it is complete binary tree. /// - /// # Return - /// A `TapTree` iff the `inner` builder is complete, otherwise return the inner as `Err`. - pub fn from_inner(inner: TaprootBuilder) -> Result { - if inner.is_complete() { - Ok(TapTree(inner)) + /// # Returns + /// A [`TapTree`] iff the `inner` builder is complete, otherwise return [`IncompleteTapTree`] + /// error with the content of incomplete builder `inner` instance. + pub fn from_inner(inner: TaprootBuilder) -> Result { + if !inner.is_complete() { + Err(IncompleteTapTree::NotFinalized(inner)) } else { - Err(inner) + Ok(TapTree(inner)) } } diff --git a/src/util/psbt/mod.rs b/src/util/psbt/mod.rs index 989542c2..4cf84ff6 100644 --- a/src/util/psbt/mod.rs +++ b/src/util/psbt/mod.rs @@ -41,7 +41,7 @@ mod macros; pub mod serialize; mod map; -pub use self::map::{Input, Output, TapTree, PsbtSighashType}; +pub use self::map::{Input, Output, TapTree, PsbtSighashType, IncompleteTapTree}; use self::map::Map; use util::bip32::{ExtendedPubKey, KeySource};