From ef8a3a839e5f0faccf9f6299b295309f2eab3727 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Fri, 7 Jan 2022 16:03:15 +0100 Subject: [PATCH] Introduce FutureLeafVersion --- src/util/taproot.rs | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/src/util/taproot.rs b/src/util/taproot.rs index 5c6c4e89..9a1043e7 100644 --- a/src/util/taproot.rs +++ b/src/util/taproot.rs @@ -760,6 +760,37 @@ impl ControlBlock { } } +/// Inner type representing future (non-tapscript) leaf versions. See [`LeafVersion::Future`]. +/// +/// NB: NO PUBLIC CONSTRUCTOR! +/// The only way to construct this is by converting u8 to LeafVersion and then extracting it. +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub struct FutureLeafVersion(u8); + +impl FutureLeafVersion { + pub(self) fn from_consensus(version: u8) -> Result { + match version { + TAPROOT_LEAF_TAPSCRIPT => unreachable!("FutureLeafVersion::from_consensus should be never called for 0xC0 value"), + TAPROOT_ANNEX_PREFIX => Err(TaprootError::InvalidTaprootLeafVersion(TAPROOT_ANNEX_PREFIX)), + odd if odd & 0xFE != odd => Err(TaprootError::InvalidTaprootLeafVersion(odd)), + even => Ok(FutureLeafVersion(even)) + } + } + + /// Get consensus representation of the future leaf version. + #[inline] + pub fn into_consensus(self) -> u8 { + self.0 + } +} + +impl fmt::Display for FutureLeafVersion { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } +} + /// The leaf version for tapleafs #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum LeafVersion { @@ -767,7 +798,7 @@ pub enum LeafVersion { TapScript, /// Future leaf version - Future(u8) + Future(FutureLeafVersion) } impl LeafVersion { @@ -790,8 +821,7 @@ impl LeafVersion { match version { TAPROOT_LEAF_TAPSCRIPT => Ok(LeafVersion::TapScript), TAPROOT_ANNEX_PREFIX => Err(TaprootError::InvalidTaprootLeafVersion(TAPROOT_ANNEX_PREFIX)), - odd if odd & TAPROOT_LEAF_MASK != odd => Err(TaprootError::InvalidTaprootLeafVersion(odd)), - future => Ok(LeafVersion::Future(future)), + future => FutureLeafVersion::from_consensus(future).map(LeafVersion::Future), } } @@ -799,7 +829,7 @@ impl LeafVersion { pub fn into_consensus(self) -> u8 { match self { LeafVersion::TapScript => TAPROOT_LEAF_TAPSCRIPT, - LeafVersion::Future(version) => version, + LeafVersion::Future(version) => version.into_consensus(), } } } @@ -809,7 +839,7 @@ impl fmt::Display for LeafVersion { match (self, f.alternate()) { (LeafVersion::TapScript, false) => f.write_str("tapscript"), (LeafVersion::TapScript, true) => fmt::Display::fmt(&TAPROOT_LEAF_TAPSCRIPT, f), - (LeafVersion::Future(version), false) => write!(f, "future_script_{:#02x}", version), + (LeafVersion::Future(version), false) => write!(f, "future_script_{:#02x}", version.0), (LeafVersion::Future(version), true) => fmt::Display::fmt(version, f), } }