use core::cmp::Reverse;
use core::convert::TryFrom;
use core::fmt;
use core::iter::FusedIterator;
use hashes::{sha256t_hash_newtype, Hash, HashEngine};
use internals::write_err;
use secp256k1::{self, Scalar, Secp256k1};
use crate::consensus::Encodable;
use crate::crypto::key::{TapTweak, TweakedPublicKey, UntweakedPublicKey, XOnlyPublicKey};
pub use crate::crypto::taproot::{SigFromSliceError, Signature};
use crate::prelude::*;
use crate::{io, Script, ScriptBuf};
sha256t_hash_newtype! {
pub struct TapLeafTag = hash_str("TapLeaf");
#[hash_newtype(forward)]
pub struct TapLeafHash(_);
pub struct TapBranchTag = hash_str("TapBranch");
#[hash_newtype(forward)]
pub struct TapNodeHash(_);
pub struct TapTweakTag = hash_str("TapTweak");
#[hash_newtype(forward)]
pub struct TapTweakHash(_);
}
impl TapTweakHash {
pub fn from_key_and_tweak(
internal_key: UntweakedPublicKey,
merkle_root: Option<TapNodeHash>,
) -> TapTweakHash {
let mut eng = TapTweakHash::engine();
eng.input(&internal_key.serialize());
if let Some(h) = merkle_root {
eng.input(h.as_ref());
} else {
}
TapTweakHash::from_engine(eng)
}
pub fn to_scalar(self) -> Scalar {
Scalar::from_be_bytes(self.to_byte_array()).expect("hash value greater than curve order")
}
}
impl TapLeafHash {
pub fn from_script(script: &Script, ver: LeafVersion) -> TapLeafHash {
let mut eng = TapLeafHash::engine();
ver.to_consensus().consensus_encode(&mut eng).expect("engines don't error");
script.consensus_encode(&mut eng).expect("engines don't error");
TapLeafHash::from_engine(eng)
}
}
impl From<LeafNode> for TapNodeHash {
fn from(leaf: LeafNode) -> TapNodeHash {
leaf.node_hash()
}
}
impl From<&LeafNode> for TapNodeHash {
fn from(leaf: &LeafNode) -> TapNodeHash {
leaf.node_hash()
}
}
impl TapNodeHash {
pub fn from_node_hashes(a: TapNodeHash, b: TapNodeHash) -> TapNodeHash {
Self::combine_node_hashes(a, b).0
}
fn combine_node_hashes(a: TapNodeHash, b: TapNodeHash) -> (TapNodeHash, bool) {
let mut eng = TapNodeHash::engine();
if a < b {
eng.input(a.as_ref());
eng.input(b.as_ref());
} else {
eng.input(b.as_ref());
eng.input(a.as_ref());
};
(TapNodeHash::from_engine(eng), a < b)
}
pub fn assume_hidden(hash: [u8; 32]) -> TapNodeHash {
TapNodeHash::from_byte_array(hash)
}
pub fn from_script(script: &Script, ver: LeafVersion) -> TapNodeHash {
TapNodeHash::from(TapLeafHash::from_script(script, ver))
}
}
impl From<TapLeafHash> for TapNodeHash {
fn from(leaf: TapLeafHash) -> TapNodeHash {
TapNodeHash::from_byte_array(leaf.to_byte_array())
}
}
pub const TAPROOT_CONTROL_MAX_NODE_COUNT: usize = 128;
pub const TAPROOT_CONTROL_NODE_SIZE: usize = 32;
pub const TAPROOT_LEAF_MASK: u8 = 0xfe;
pub const TAPROOT_LEAF_TAPSCRIPT: u8 = 0xc0;
pub const TAPROOT_ANNEX_PREFIX: u8 = 0x50;
pub const TAPROOT_CONTROL_BASE_SIZE: usize = 33;
pub const TAPROOT_CONTROL_MAX_SIZE: usize =
TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * TAPROOT_CONTROL_MAX_NODE_COUNT;
type ScriptMerkleProofMap = BTreeMap<(ScriptBuf, LeafVersion), BTreeSet<TaprootMerkleBranch>>;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TaprootSpendInfo {
internal_key: UntweakedPublicKey,
merkle_root: Option<TapNodeHash>,
output_key_parity: secp256k1::Parity,
output_key: TweakedPublicKey,
script_map: ScriptMerkleProofMap,
}
impl TaprootSpendInfo {
pub fn with_huffman_tree<C, I>(
secp: &Secp256k1<C>,
internal_key: UntweakedPublicKey,
script_weights: I,
) -> Result<Self, TaprootBuilderError>
where
I: IntoIterator<Item = (u32, ScriptBuf)>,
C: secp256k1::Verification,
{
let builder = TaprootBuilder::with_huffman_tree(script_weights)?;
Ok(builder.finalize(secp, internal_key).expect("Huffman Tree is always complete"))
}
pub fn new_key_spend<C: secp256k1::Verification>(
secp: &Secp256k1<C>,
internal_key: UntweakedPublicKey,
merkle_root: Option<TapNodeHash>,
) -> Self {
let (output_key, parity) = internal_key.tap_tweak(secp, merkle_root);
Self {
internal_key,
merkle_root,
output_key_parity: parity,
output_key,
script_map: BTreeMap::new(),
}
}
pub fn tap_tweak(&self) -> TapTweakHash {
TapTweakHash::from_key_and_tweak(self.internal_key, self.merkle_root)
}
pub fn internal_key(&self) -> UntweakedPublicKey {
self.internal_key
}
pub fn merkle_root(&self) -> Option<TapNodeHash> {
self.merkle_root
}
pub fn output_key(&self) -> TweakedPublicKey {
self.output_key
}
pub fn output_key_parity(&self) -> secp256k1::Parity {
self.output_key_parity
}
pub fn script_map(&self) -> &ScriptMerkleProofMap {
&self.script_map
}
pub fn from_node_info<C: secp256k1::Verification>(
secp: &Secp256k1<C>,
internal_key: UntweakedPublicKey,
node: NodeInfo,
) -> TaprootSpendInfo {
let root_hash = Some(node.hash);
let mut info = TaprootSpendInfo::new_key_spend(secp, internal_key, root_hash);
for leaves in node.leaves {
match leaves.leaf {
TapLeaf::Hidden(_) => {
}
TapLeaf::Script(script, ver) => {
let key = (script, ver);
let value = leaves.merkle_branch;
match info.script_map.get_mut(&key) {
None => {
let mut set = BTreeSet::new();
set.insert(value);
info.script_map.insert(key, set);
}
Some(set) => {
set.insert(value);
}
}
}
}
}
info
}
#[deprecated(since = "0.31.0", note = "use Self::script_map instead")]
pub fn as_script_map(&self) -> &ScriptMerkleProofMap {
self.script_map()
}
pub fn control_block(&self, script_ver: &(ScriptBuf, LeafVersion)) -> Option<ControlBlock> {
let merkle_branch_set = self.script_map.get(script_ver)?;
let smallest = merkle_branch_set
.iter()
.min_by(|x, y| x.0.len().cmp(&y.0.len()))
.expect("Invariant: ScriptBuf map key must contain non-empty set value");
Some(ControlBlock {
internal_key: self.internal_key,
output_key_parity: self.output_key_parity,
leaf_version: script_ver.1,
merkle_branch: smallest.clone(),
})
}
}
impl From<TaprootSpendInfo> for TapTweakHash {
fn from(spend_info: TaprootSpendInfo) -> TapTweakHash {
spend_info.tap_tweak()
}
}
impl From<&TaprootSpendInfo> for TapTweakHash {
fn from(spend_info: &TaprootSpendInfo) -> TapTweakHash {
spend_info.tap_tweak()
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TaprootBuilder {
branch: Vec<Option<NodeInfo>>,
}
impl TaprootBuilder {
pub fn new() -> Self {
TaprootBuilder { branch: vec![] }
}
pub fn with_capacity(size: usize) -> Self {
TaprootBuilder { branch: Vec::with_capacity(size) }
}
pub fn with_huffman_tree<I>(script_weights: I) -> Result<Self, TaprootBuilderError>
where
I: IntoIterator<Item = (u32, ScriptBuf)>,
{
let mut node_weights = BinaryHeap::<(Reverse<u32>, NodeInfo)>::new();
for (p, leaf) in script_weights {
node_weights
.push((Reverse(p), NodeInfo::new_leaf_with_ver(leaf, LeafVersion::TapScript)));
}
if node_weights.is_empty() {
return Err(TaprootBuilderError::EmptyTree);
}
while node_weights.len() > 1 {
let (p1, s1) = node_weights.pop().expect("len must be at least two");
let (p2, s2) = node_weights.pop().expect("len must be at least two");
let p = Reverse(p1.0.saturating_add(p2.0));
node_weights.push((p, NodeInfo::combine(s1, s2)?));
}
debug_assert_eq!(node_weights.len(), 1);
let node = node_weights.pop().expect("huffman tree algorithm is broken").1;
Ok(TaprootBuilder { branch: vec![Some(node)] })
}
pub fn add_leaf_with_ver(
self,
depth: u8,
script: ScriptBuf,
ver: LeafVersion,
) -> Result<Self, TaprootBuilderError> {
let leaf = NodeInfo::new_leaf_with_ver(script, ver);
self.insert(leaf, depth)
}
pub fn add_leaf(self, depth: u8, script: ScriptBuf) -> Result<Self, TaprootBuilderError> {
self.add_leaf_with_ver(depth, script, LeafVersion::TapScript)
}
pub fn add_hidden_node(
self,
depth: u8,
hash: TapNodeHash,
) -> Result<Self, TaprootBuilderError> {
let node = NodeInfo::new_hidden_node(hash);
self.insert(node, depth)
}
pub fn is_finalizable(&self) -> bool {
self.branch.len() == 1 && self.branch[0].is_some()
}
pub fn try_into_node_info(mut self) -> Result<NodeInfo, IncompleteBuilderError> {
if self.branch().len() != 1 {
return Err(IncompleteBuilderError::NotFinalized(self));
}
Ok(self
.branch
.pop()
.expect("length checked above")
.expect("invariant guarantees node info exists"))
}
pub fn try_into_taptree(self) -> Result<TapTree, IncompleteBuilderError> {
let node = self.try_into_node_info()?;
if node.has_hidden_nodes {
return Err(IncompleteBuilderError::HiddenParts(TaprootBuilder {
branch: vec![Some(node)],
}));
}
Ok(TapTree(node))
}
pub fn has_hidden_nodes(&self) -> bool {
self.branch.iter().flatten().any(|node| node.has_hidden_nodes)
}
pub fn finalize<C: secp256k1::Verification>(
mut self,
secp: &Secp256k1<C>,
internal_key: UntweakedPublicKey,
) -> Result<TaprootSpendInfo, TaprootBuilder> {
match self.branch.len() {
0 => Ok(TaprootSpendInfo::new_key_spend(secp, internal_key, None)),
1 => {
if let Some(Some(node)) = self.branch.pop() {
Ok(TaprootSpendInfo::from_node_info(secp, internal_key, node))
} else {
unreachable!("Size checked above. Builder guarantees the last element is Some")
}
}
_ => Err(self),
}
}
pub(crate) fn branch(&self) -> &[Option<NodeInfo>] {
&self.branch
}
fn insert(mut self, mut node: NodeInfo, mut depth: u8) -> Result<Self, TaprootBuilderError> {
if depth as usize > TAPROOT_CONTROL_MAX_NODE_COUNT {
return Err(TaprootBuilderError::InvalidMerkleTreeDepth(depth as usize));
}
if (depth as usize + 1) < self.branch.len() {
return Err(TaprootBuilderError::NodeNotInDfsOrder);
}
while self.branch.len() == depth as usize + 1 {
let child = match self.branch.pop() {
None => unreachable!("Len of branch checked to be >= 1"),
Some(Some(child)) => child,
Some(None) => {
self.branch.push(None);
break;
} };
if depth == 0 {
return Err(TaprootBuilderError::OverCompleteTree);
}
node = NodeInfo::combine(node, child)?;
depth -= 1;
}
if self.branch.len() < depth as usize + 1 {
let num_extra_nodes = depth as usize + 1 - self.branch.len();
self.branch.extend((0..num_extra_nodes).map(|_| None));
}
self.branch[depth as usize] = Some(node);
Ok(self)
}
}
impl Default for TaprootBuilder {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum IncompleteBuilderError {
NotFinalized(TaprootBuilder),
HiddenParts(TaprootBuilder),
}
impl IncompleteBuilderError {
pub fn into_builder(self) -> TaprootBuilder {
use IncompleteBuilderError::*;
match self {
NotFinalized(builder) | HiddenParts(builder) => builder,
}
}
}
impl core::fmt::Display for IncompleteBuilderError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
use IncompleteBuilderError::*;
f.write_str(match self {
NotFinalized(_) => {
"an attempt to construct a tap tree from a builder containing incomplete branches."
}
HiddenParts(_) => {
"an attempt to construct a tap tree from a builder containing hidden parts."
}
})
}
}
#[cfg(feature = "std")]
impl std::error::Error for IncompleteBuilderError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use IncompleteBuilderError::*;
match *self {
NotFinalized(_) | HiddenParts(_) => None,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum HiddenNodesError {
HiddenParts(NodeInfo),
}
impl HiddenNodesError {
pub fn into_node_info(self) -> NodeInfo {
use HiddenNodesError::*;
match self {
HiddenParts(node_info) => node_info,
}
}
}
impl core::fmt::Display for HiddenNodesError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
use HiddenNodesError::*;
f.write_str(match self {
HiddenParts(_) => {
"an attempt to construct a tap tree from a node_info containing hidden parts."
}
})
}
}
#[cfg(feature = "std")]
impl std::error::Error for HiddenNodesError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use HiddenNodesError::*;
match self {
HiddenParts(_) => None,
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
#[cfg_attr(feature = "serde", serde(into = "NodeInfo"))]
#[cfg_attr(feature = "serde", serde(try_from = "NodeInfo"))]
pub struct TapTree(NodeInfo);
impl From<TapTree> for NodeInfo {
#[inline]
fn from(tree: TapTree) -> Self {
tree.into_node_info()
}
}
impl TapTree {
pub fn node_info(&self) -> &NodeInfo {
&self.0
}
pub fn into_node_info(self) -> NodeInfo {
self.0
}
pub fn script_leaves(&self) -> ScriptLeaves {
ScriptLeaves { leaf_iter: self.0.leaf_nodes() }
}
}
impl TryFrom<TaprootBuilder> for TapTree {
type Error = IncompleteBuilderError;
fn try_from(builder: TaprootBuilder) -> Result<Self, Self::Error> {
builder.try_into_taptree()
}
}
impl TryFrom<NodeInfo> for TapTree {
type Error = HiddenNodesError;
fn try_from(node_info: NodeInfo) -> Result<Self, Self::Error> {
if node_info.has_hidden_nodes {
Err(HiddenNodesError::HiddenParts(node_info))
} else {
Ok(TapTree(node_info))
}
}
}
pub struct ScriptLeaves<'tree> {
leaf_iter: LeafNodes<'tree>,
}
impl<'tree> Iterator for ScriptLeaves<'tree> {
type Item = ScriptLeaf<'tree>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
ScriptLeaf::from_leaf_node(self.leaf_iter.next()?)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.leaf_iter.size_hint()
}
}
impl<'tree> ExactSizeIterator for ScriptLeaves<'tree> {}
impl<'tree> FusedIterator for ScriptLeaves<'tree> {}
impl<'tree> DoubleEndedIterator for ScriptLeaves<'tree> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
ScriptLeaf::from_leaf_node(self.leaf_iter.next_back()?)
}
}
pub struct LeafNodes<'a> {
leaf_iter: core::slice::Iter<'a, LeafNode>,
}
impl<'a> Iterator for LeafNodes<'a> {
type Item = &'a LeafNode;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.leaf_iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.leaf_iter.size_hint()
}
}
impl<'tree> ExactSizeIterator for LeafNodes<'tree> {}
impl<'tree> FusedIterator for LeafNodes<'tree> {}
impl<'tree> DoubleEndedIterator for LeafNodes<'tree> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.leaf_iter.next_back()
}
}
#[derive(Debug, Clone, PartialOrd, Ord)]
pub struct NodeInfo {
pub(crate) hash: TapNodeHash,
pub(crate) leaves: Vec<LeafNode>,
pub(crate) has_hidden_nodes: bool,
}
impl PartialEq for NodeInfo {
fn eq(&self, other: &Self) -> bool {
self.hash.eq(&other.hash)
}
}
impl core::hash::Hash for NodeInfo {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.hash.hash(state)
}
}
impl Eq for NodeInfo {}
impl NodeInfo {
pub fn new_hidden_node(hash: TapNodeHash) -> Self {
Self { hash, leaves: vec![], has_hidden_nodes: true }
}
pub fn new_leaf_with_ver(script: ScriptBuf, ver: LeafVersion) -> Self {
Self {
hash: TapNodeHash::from_script(&script, ver),
leaves: vec![LeafNode::new_script(script, ver)],
has_hidden_nodes: false,
}
}
pub fn combine(a: Self, b: Self) -> Result<Self, TaprootBuilderError> {
let mut all_leaves = Vec::with_capacity(a.leaves.len() + b.leaves.len());
let (hash, left_first) = TapNodeHash::combine_node_hashes(a.hash, b.hash);
let (a, b) = if left_first { (a, b) } else { (b, a) };
for mut a_leaf in a.leaves {
a_leaf.merkle_branch.push(b.hash)?; all_leaves.push(a_leaf);
}
for mut b_leaf in b.leaves {
b_leaf.merkle_branch.push(a.hash)?; all_leaves.push(b_leaf);
}
Ok(Self {
hash,
leaves: all_leaves,
has_hidden_nodes: a.has_hidden_nodes || b.has_hidden_nodes,
})
}
pub fn leaf_nodes(&self) -> LeafNodes {
LeafNodes { leaf_iter: self.leaves.iter() }
}
}
impl TryFrom<TaprootBuilder> for NodeInfo {
type Error = IncompleteBuilderError;
fn try_from(builder: TaprootBuilder) -> Result<Self, Self::Error> {
builder.try_into_node_info()
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for NodeInfo {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeSeq;
let mut seq = serializer.serialize_seq(Some(self.leaves.len() * 2))?;
for tap_leaf in self.leaves.iter() {
seq.serialize_element(&tap_leaf.merkle_branch().len())?;
seq.serialize_element(&tap_leaf.leaf)?;
}
seq.end()
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for NodeInfo {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct SeqVisitor;
impl<'de> serde::de::Visitor<'de> for SeqVisitor {
type Value = NodeInfo;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("Taproot tree in DFS walk order")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
let size = seq
.size_hint()
.map(|x| core::mem::size_of::<usize>() * 8 - x.leading_zeros() as usize)
.map(|x| x / 2) .unwrap_or(0)
.min(TAPROOT_CONTROL_MAX_NODE_COUNT); let mut builder = TaprootBuilder::with_capacity(size);
while let Some(depth) = seq.next_element()? {
let tap_leaf: TapLeaf = seq
.next_element()?
.ok_or_else(|| serde::de::Error::custom("Missing tap_leaf"))?;
match tap_leaf {
TapLeaf::Script(script, ver) => {
builder =
builder.add_leaf_with_ver(depth, script, ver).map_err(|e| {
serde::de::Error::custom(format!("Leaf insertion error: {}", e))
})?;
}
TapLeaf::Hidden(h) => {
builder = builder.add_hidden_node(depth, h).map_err(|e| {
serde::de::Error::custom(format!(
"Hidden node insertion error: {}",
e
))
})?;
}
}
}
NodeInfo::try_from(builder).map_err(|e| {
serde::de::Error::custom(format!("Incomplete taproot tree: {}", e))
})
}
}
deserializer.deserialize_seq(SeqVisitor)
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
pub enum TapLeaf {
Script(ScriptBuf, LeafVersion),
Hidden(TapNodeHash),
}
impl TapLeaf {
pub fn as_hidden(&self) -> Option<&TapNodeHash> {
if let Self::Hidden(v) = self {
Some(v)
} else {
None
}
}
pub fn as_script(&self) -> Option<(&Script, LeafVersion)> {
if let Self::Script(script, ver) = self {
Some((script, *ver))
} else {
None
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct LeafNode {
leaf: TapLeaf,
merkle_branch: TaprootMerkleBranch,
}
impl LeafNode {
pub fn new_script(script: ScriptBuf, ver: LeafVersion) -> Self {
Self { leaf: TapLeaf::Script(script, ver), merkle_branch: TaprootMerkleBranch(vec![]) }
}
pub fn new_hidden(hash: TapNodeHash) -> Self {
Self { leaf: TapLeaf::Hidden(hash), merkle_branch: TaprootMerkleBranch(vec![]) }
}
#[inline]
pub fn depth(&self) -> u8 {
u8::try_from(self.merkle_branch().0.len()).expect("depth is guaranteed to fit in a u8")
}
#[inline]
pub fn leaf_hash(&self) -> Option<TapLeafHash> {
let (script, ver) = self.leaf.as_script()?;
Some(TapLeafHash::from_script(script, ver))
}
#[inline]
pub fn node_hash(&self) -> TapNodeHash {
match self.leaf {
TapLeaf::Script(ref script, ver) => TapLeafHash::from_script(script, ver).into(),
TapLeaf::Hidden(ref hash) => *hash,
}
}
#[inline]
pub fn script(&self) -> Option<&Script> {
self.leaf.as_script().map(|x| x.0)
}
#[inline]
pub fn leaf_version(&self) -> Option<LeafVersion> {
self.leaf.as_script().map(|x| x.1)
}
#[inline]
pub fn merkle_branch(&self) -> &TaprootMerkleBranch {
&self.merkle_branch
}
#[inline]
pub fn leaf(&self) -> &TapLeaf {
&self.leaf
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ScriptLeaf<'leaf> {
version: LeafVersion,
script: &'leaf Script,
merkle_branch: &'leaf TaprootMerkleBranch,
}
impl<'leaf> ScriptLeaf<'leaf> {
pub fn version(&self) -> LeafVersion {
self.version
}
pub fn script(&self) -> &Script {
self.script
}
pub fn merkle_branch(&self) -> &TaprootMerkleBranch {
self.merkle_branch
}
pub fn from_leaf_node(leaf_node: &'leaf LeafNode) -> Option<Self> {
let (script, ver) = leaf_node.leaf.as_script()?;
Some(Self { version: ver, script, merkle_branch: &leaf_node.merkle_branch })
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
#[cfg_attr(feature = "serde", serde(into = "Vec<TapNodeHash>"))]
#[cfg_attr(feature = "serde", serde(try_from = "Vec<TapNodeHash>"))]
pub struct TaprootMerkleBranch(Vec<TapNodeHash>);
impl TaprootMerkleBranch {
pub fn as_inner(&self) -> &[TapNodeHash] {
&self.0
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn decode(sl: &[u8]) -> Result<Self, TaprootError> {
if sl.len() % TAPROOT_CONTROL_NODE_SIZE != 0 {
Err(TaprootError::InvalidMerkleBranchSize(sl.len()))
} else if sl.len() > TAPROOT_CONTROL_NODE_SIZE * TAPROOT_CONTROL_MAX_NODE_COUNT {
Err(TaprootError::InvalidMerkleTreeDepth(sl.len() / TAPROOT_CONTROL_NODE_SIZE))
} else {
let inner = sl
.chunks_exact(TAPROOT_CONTROL_NODE_SIZE)
.map(|chunk| {
TapNodeHash::from_slice(chunk)
.expect("chunks_exact always returns the correct size")
})
.collect();
Ok(TaprootMerkleBranch(inner))
}
}
fn from_collection<T: AsRef<[TapNodeHash]> + Into<Vec<TapNodeHash>>>(
collection: T,
) -> Result<Self, TaprootError> {
if collection.as_ref().len() > TAPROOT_CONTROL_MAX_NODE_COUNT {
Err(TaprootError::InvalidMerkleTreeDepth(collection.as_ref().len()))
} else {
Ok(TaprootMerkleBranch(collection.into()))
}
}
pub fn encode<Write: io::Write>(&self, mut writer: Write) -> io::Result<usize> {
for hash in self.0.iter() {
writer.write_all(hash.as_ref())?;
}
Ok(self.0.len() * TapNodeHash::LEN)
}
pub fn serialize(&self) -> Vec<u8> {
self.0.iter().flat_map(|e| e.as_byte_array()).copied().collect::<Vec<u8>>()
}
fn push(&mut self, h: TapNodeHash) -> Result<(), TaprootBuilderError> {
if self.0.len() >= TAPROOT_CONTROL_MAX_NODE_COUNT {
Err(TaprootBuilderError::InvalidMerkleTreeDepth(self.0.len()))
} else {
self.0.push(h);
Ok(())
}
}
pub fn into_inner(self) -> Vec<TapNodeHash> {
self.0
}
}
macro_rules! impl_try_from {
($from:ty) => {
impl TryFrom<$from> for TaprootMerkleBranch {
type Error = TaprootError;
fn try_from(v: $from) -> Result<Self, Self::Error> {
TaprootMerkleBranch::from_collection(v)
}
}
};
}
impl_try_from!(&[TapNodeHash]);
impl_try_from!(Vec<TapNodeHash>);
impl_try_from!(Box<[TapNodeHash]>);
macro_rules! impl_try_from_array {
($($len:expr),* $(,)?) => {
$(
impl From<[TapNodeHash; $len]> for TaprootMerkleBranch {
fn from(a: [TapNodeHash; $len]) -> Self {
Self(a.to_vec())
}
}
)*
}
}
impl_try_from_array!(
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128
);
impl From<TaprootMerkleBranch> for Vec<TapNodeHash> {
fn from(branch: TaprootMerkleBranch) -> Self {
branch.0
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
pub struct ControlBlock {
pub leaf_version: LeafVersion,
pub output_key_parity: secp256k1::Parity,
pub internal_key: UntweakedPublicKey,
pub merkle_branch: TaprootMerkleBranch,
}
impl ControlBlock {
pub fn decode(sl: &[u8]) -> Result<ControlBlock, TaprootError> {
if sl.len() < TAPROOT_CONTROL_BASE_SIZE
|| (sl.len() - TAPROOT_CONTROL_BASE_SIZE) % TAPROOT_CONTROL_NODE_SIZE != 0
{
return Err(TaprootError::InvalidControlBlockSize(sl.len()));
}
let output_key_parity =
secp256k1::Parity::from_i32((sl[0] & 1) as i32).map_err(TaprootError::InvalidParity)?;
let leaf_version = LeafVersion::from_consensus(sl[0] & TAPROOT_LEAF_MASK)?;
let internal_key = UntweakedPublicKey::from_slice(&sl[1..TAPROOT_CONTROL_BASE_SIZE])
.map_err(TaprootError::InvalidInternalKey)?;
let merkle_branch = TaprootMerkleBranch::decode(&sl[TAPROOT_CONTROL_BASE_SIZE..])?;
Ok(ControlBlock { leaf_version, output_key_parity, internal_key, merkle_branch })
}
pub fn size(&self) -> usize {
TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * self.merkle_branch.as_inner().len()
}
pub fn encode<Write: io::Write>(&self, mut writer: Write) -> io::Result<usize> {
let first_byte: u8 =
i32::from(self.output_key_parity) as u8 | self.leaf_version.to_consensus();
writer.write_all(&[first_byte])?;
writer.write_all(&self.internal_key.serialize())?;
self.merkle_branch.encode(&mut writer)?;
Ok(self.size())
}
pub fn serialize(&self) -> Vec<u8> {
let mut buf = Vec::with_capacity(self.size());
self.encode(&mut buf).expect("writers don't error");
buf
}
pub fn verify_taproot_commitment<C: secp256k1::Verification>(
&self,
secp: &Secp256k1<C>,
output_key: XOnlyPublicKey,
script: &Script,
) -> bool {
let mut curr_hash = TapNodeHash::from_script(script, self.leaf_version);
for elem in self.merkle_branch.as_inner() {
curr_hash = TapNodeHash::from_node_hashes(curr_hash, *elem);
}
let tweak =
TapTweakHash::from_key_and_tweak(self.internal_key, Some(curr_hash)).to_scalar();
self.internal_key.tweak_add_check(secp, &output_key, self.output_key_parity, tweak)
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct FutureLeafVersion(u8);
impl FutureLeafVersion {
pub(self) fn from_consensus(version: u8) -> Result<FutureLeafVersion, TaprootError> {
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)),
}
}
#[inline]
pub fn to_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)
}
}
impl fmt::LowerHex for FutureLeafVersion {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::LowerHex::fmt(&self.0, f)
}
}
impl fmt::UpperHex for FutureLeafVersion {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::UpperHex::fmt(&self.0, f)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum LeafVersion {
TapScript,
Future(FutureLeafVersion),
}
impl LeafVersion {
pub fn from_consensus(version: u8) -> Result<Self, TaprootError> {
match version {
TAPROOT_LEAF_TAPSCRIPT => Ok(LeafVersion::TapScript),
TAPROOT_ANNEX_PREFIX => {
Err(TaprootError::InvalidTaprootLeafVersion(TAPROOT_ANNEX_PREFIX))
}
future => FutureLeafVersion::from_consensus(future).map(LeafVersion::Future),
}
}
pub fn to_consensus(self) -> u8 {
match self {
LeafVersion::TapScript => TAPROOT_LEAF_TAPSCRIPT,
LeafVersion::Future(version) => version.to_consensus(),
}
}
}
impl fmt::Display for LeafVersion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match (self, f.alternate()) {
(LeafVersion::TapScript, true) => f.write_str("tapscript"),
(LeafVersion::TapScript, false) => fmt::Display::fmt(&TAPROOT_LEAF_TAPSCRIPT, f),
(LeafVersion::Future(version), true) => write!(f, "future_script_{:#02x}", version.0),
(LeafVersion::Future(version), false) => fmt::Display::fmt(version, f),
}
}
}
impl fmt::LowerHex for LeafVersion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::LowerHex::fmt(&self.to_consensus(), f)
}
}
impl fmt::UpperHex for LeafVersion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::UpperHex::fmt(&self.to_consensus(), f)
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for LeafVersion {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_u8(self.to_consensus())
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for LeafVersion {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct U8Visitor;
impl<'de> serde::de::Visitor<'de> for U8Visitor {
type Value = LeafVersion;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a valid consensus-encoded taproot leaf version")
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
let value = u8::try_from(value).map_err(|_| {
E::invalid_value(
serde::de::Unexpected::Unsigned(value),
&"consensus-encoded leaf version as u8",
)
})?;
LeafVersion::from_consensus(value).map_err(|_| {
E::invalid_value(
::serde::de::Unexpected::Unsigned(value as u64),
&"consensus-encoded leaf version as u8",
)
})
}
}
deserializer.deserialize_u8(U8Visitor)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum TaprootBuilderError {
InvalidMerkleTreeDepth(usize),
NodeNotInDfsOrder,
OverCompleteTree,
InvalidInternalKey(secp256k1::Error),
EmptyTree,
}
impl fmt::Display for TaprootBuilderError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use TaprootBuilderError::*;
match *self {
InvalidMerkleTreeDepth(d) => {
write!(
f,
"Merkle Tree depth({}) must be less than {}",
d, TAPROOT_CONTROL_MAX_NODE_COUNT
)
}
NodeNotInDfsOrder => {
write!(f, "add_leaf/add_hidden must be called in DFS walk order",)
}
OverCompleteTree => write!(
f,
"Attempted to create a tree with two nodes at depth 0. There must\
only be a exactly one node at depth 0",
),
InvalidInternalKey(ref e) => {
write_err!(f, "invalid internal x-only key"; e)
}
EmptyTree => {
write!(f, "Called finalize on an empty tree")
}
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for TaprootBuilderError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use TaprootBuilderError::*;
match self {
InvalidInternalKey(e) => Some(e),
InvalidMerkleTreeDepth(_) | NodeNotInDfsOrder | OverCompleteTree | EmptyTree => None,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum TaprootError {
InvalidMerkleBranchSize(usize),
InvalidMerkleTreeDepth(usize),
InvalidTaprootLeafVersion(u8),
InvalidControlBlockSize(usize),
InvalidInternalKey(secp256k1::Error),
InvalidParity(secp256k1::InvalidParityValue),
EmptyTree,
}
impl fmt::Display for TaprootError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use TaprootError::*;
match *self {
InvalidMerkleBranchSize(sz) => write!(
f,
"Merkle branch size({}) must be a multiple of {}",
sz, TAPROOT_CONTROL_NODE_SIZE
),
InvalidMerkleTreeDepth(d) => write!(
f,
"Merkle Tree depth({}) must be less than {}",
d, TAPROOT_CONTROL_MAX_NODE_COUNT
),
InvalidTaprootLeafVersion(v) => {
write!(f, "Leaf version({}) must have the least significant bit 0", v)
}
InvalidControlBlockSize(sz) => write!(
f,
"Control Block size({}) must be of the form 33 + 32*m where 0 <= m <= {} ",
sz, TAPROOT_CONTROL_MAX_NODE_COUNT
),
InvalidInternalKey(ref e) => {
write_err!(f, "invalid internal x-only key"; e)
}
InvalidParity(_) => write!(f, "invalid parity value for internal key"),
EmptyTree => write!(f, "Taproot Tree must contain at least one script"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for TaprootError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use TaprootError::*;
match self {
InvalidInternalKey(e) => Some(e),
InvalidMerkleBranchSize(_)
| InvalidMerkleTreeDepth(_)
| InvalidTaprootLeafVersion(_)
| InvalidControlBlockSize(_)
| InvalidParity(_)
| EmptyTree => None,
}
}
}