// Rust Bitcoin Library
// Written in 2019 by
// The rust-bitcoin developers.
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see .
//
//! Bitcoin Taproot.
//!
//! This module provides support for taproot tagged hashes.
//!
use prelude::*;
use io;
use secp256k1::{self, Secp256k1};
use core::fmt;
use core::cmp::Reverse;
#[cfg(feature = "std")]
use std::error;
use hashes::{sha256, sha256t, Hash, HashEngine};
use schnorr::{TweakedPublicKey, UntweakedPublicKey, TapTweak};
use Script;
use consensus::Encodable;
/// The SHA-256 midstate value for the TapLeaf hash.
const MIDSTATE_TAPLEAF: [u8; 32] = [
156, 224, 228, 230, 124, 17, 108, 57, 56, 179, 202, 242, 195, 15, 80, 137, 211, 243, 147, 108,
71, 99, 110, 96, 125, 179, 62, 234, 221, 198, 240, 201,
];
// 9ce0e4e67c116c3938b3caf2c30f5089d3f3936c47636e607db33eeaddc6f0c9
/// The SHA-256 midstate value for the TapBranch hash.
const MIDSTATE_TAPBRANCH: [u8; 32] = [
35, 168, 101, 169, 184, 164, 13, 167, 151, 124, 30, 4, 196, 158, 36, 111, 181, 190, 19, 118,
157, 36, 201, 183, 181, 131, 181, 212, 168, 210, 38, 210,
];
// 23a865a9b8a40da7977c1e04c49e246fb5be13769d24c9b7b583b5d4a8d226d2
/// The SHA-256 midstate value for the TapTweak hash.
const MIDSTATE_TAPTWEAK: [u8; 32] = [
209, 41, 162, 243, 112, 28, 101, 93, 101, 131, 182, 195, 185, 65, 151, 39, 149, 244, 226, 50,
148, 253, 84, 244, 162, 174, 141, 133, 71, 202, 89, 11,
];
// d129a2f3701c655d6583b6c3b941972795f4e23294fd54f4a2ae8d8547ca590b
/// The SHA-256 midstate value for the TapSigHash hash.
const MIDSTATE_TAPSIGHASH: [u8; 32] = [
245, 4, 164, 37, 215, 248, 120, 59, 19, 99, 134, 138, 227, 229, 86, 88, 110, 238, 148, 93, 188,
120, 136, 221, 2, 166, 226, 195, 24, 115, 254, 159,
];
// f504a425d7f8783b1363868ae3e556586eee945dbc7888dd02a6e2c31873fe9f
/// Internal macro to speficy the different taproot tagged hashes.
macro_rules! sha256t_hash_newtype {
($newtype:ident, $tag:ident, $midstate:ident, $midstate_len:expr, $docs:meta, $reverse: expr) => {
sha256t_hash_newtype!($newtype, $tag, $midstate, $midstate_len, $docs, $reverse, stringify!($newtype));
};
($newtype:ident, $tag:ident, $midstate:ident, $midstate_len:expr, $docs:meta, $reverse: expr, $sname:expr) => {
#[doc = "The tag used for ["]
#[doc = $sname]
#[doc = "]"]
#[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
pub struct $tag;
impl sha256t::Tag for $tag {
fn engine() -> sha256::HashEngine {
let midstate = sha256::Midstate::from_inner($midstate);
sha256::HashEngine::from_midstate(midstate, $midstate_len)
}
}
hash_newtype!($newtype, sha256t::Hash<$tag>, 32, $docs, $reverse);
};
}
// Taproot test vectors from BIP-341 state the hashes without any reversing
sha256t_hash_newtype!(TapLeafHash, TapLeafTag, MIDSTATE_TAPLEAF, 64,
doc="Taproot-tagged hash for tapscript Merkle tree leafs", false
);
sha256t_hash_newtype!(TapBranchHash, TapBranchTag, MIDSTATE_TAPBRANCH, 64,
doc="Taproot-tagged hash for tapscript Merkle tree branches", false
);
sha256t_hash_newtype!(TapTweakHash, TapTweakTag, MIDSTATE_TAPTWEAK, 64,
doc="Taproot-tagged hash for public key tweaks", false
);
sha256t_hash_newtype!(TapSighashHash, TapSighashTag, MIDSTATE_TAPSIGHASH, 64,
doc="Taproot-tagged hash for the taproot signature hash", false
);
impl TapTweakHash {
/// Create a new BIP341 [`TapTweakHash`] from key and tweak
/// Produces H_taptweak(P||R) where P is internal key and R is the merkle root
pub fn from_key_and_tweak(
internal_key: UntweakedPublicKey,
merkle_root: Option,
) -> TapTweakHash {
let mut eng = TapTweakHash::engine();
// always hash the key
eng.input(&internal_key.serialize());
if let Some(h) = merkle_root {
eng.input(&h);
} else {
// nothing to hash
}
TapTweakHash::from_engine(eng)
}
}
impl TapLeafHash {
/// function to compute leaf hash from components
pub fn from_script(script: &Script, ver: LeafVersion) -> TapLeafHash {
let mut eng = TapLeafHash::engine();
ver.as_u8()
.consensus_encode(&mut eng)
.expect("engines don't error");
script
.consensus_encode(&mut eng)
.expect("engines don't error");
TapLeafHash::from_engine(eng)
}
}
/// Maximum depth of a Taproot Tree Script spend path
// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L229
pub const TAPROOT_CONTROL_MAX_NODE_COUNT: usize = 128;
/// Size of a taproot control node
// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L228
pub const TAPROOT_CONTROL_NODE_SIZE: usize = 32;
/// Tapleaf mask for getting the leaf version from first byte of control block
// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L225
pub const TAPROOT_LEAF_MASK: u8 = 0xfe;
/// Tapscript leaf version
// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L226
pub const TAPROOT_LEAF_TAPSCRIPT: u8 = 0xc0;
/// Tapscript control base size
// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L227
pub const TAPROOT_CONTROL_BASE_SIZE: usize = 33;
/// Tapscript control max size
// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L230
pub const TAPROOT_CONTROL_MAX_SIZE: usize =
TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * TAPROOT_CONTROL_MAX_NODE_COUNT;
// type alias for versioned tap script corresponding merkle proof
type ScriptMerkleProofMap = BTreeMap<(Script, LeafVersion), BTreeSet>;
/// Data structure for representing Taproot spending information.
/// Taproot output corresponds to a combination of a
/// single public key condition (known the internal key), and zero or more
/// general conditions encoded in scripts organized in the form of a binary tree.
///
/// Taproot can be spent be either:
/// - Spending using the key path i.e., with secret key corresponding to the output_key
/// - By satisfying any of the scripts in the script spent path. Each script can be satisfied by providing
/// a witness stack consisting of the script's inputs, plus the script itself and the control block.
///
/// If one or more of the spending conditions consist of just a single key (after aggregation),
/// the most likely one should be made the internal key.
/// See [BIP341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki) for more details
/// on choosing internal keys for a taproot application
///
/// Note: This library currently does not support [annex](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#cite_note-5)
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TaprootSpendInfo {
/// The BIP341 internal key.
internal_key: UntweakedPublicKey,
/// The Merkle root of the script tree (None if there are no scripts)
merkle_root: Option,
/// The sign final output pubkey as per BIP 341
output_key_parity: bool,
/// The tweaked output key
output_key: TweakedPublicKey,
/// Map from (script, leaf_version) to (sets of) [`TaprootMerkleBranch`].
/// More than one control block for a given script is only possible if it
/// appears in multiple branches of the tree. In all cases, keeping one should
/// be enough for spending funds, but we keep all of the paths so that
/// a full tree can be constructed again from spending data if required.
script_map: ScriptMerkleProofMap,
}
impl TaprootSpendInfo {
/// Create a new [`TaprootSpendInfo`] from a list of script(with default script version) and
/// weights of satisfaction for that script. The weights represent the probability of
/// each branch being taken. If probabilities/weights for each condition are known,
/// constructing the tree as a Huffman tree is the optimal way to minimize average
/// case satisfaction cost. This function takes input an iterator of tuple(u64, &Script)
/// where usize represents the satisfaction weights of the branch.
/// For example, [(3, S1), (2, S2), (5, S3)] would construct a TapTree that has optimal
/// satisfaction weight when probability for S1 is 30%, S2 is 20% and S3 is 50%.
///
/// # Errors:
///
/// - When the optimal huffman tree has a depth more than 128
/// - If the provided list of script weights is empty
///
/// # Edge Cases:
/// - If the script weight calculations overflow, a sub-optimal tree may be generated. This
/// should not happen unless you are dealing with billions of branches with weights close to
/// 2^32.
pub fn with_huffman_tree(
secp: &Secp256k1,
internal_key: UntweakedPublicKey,
script_weights: I,
) -> Result
where
I: IntoIterator,
C: secp256k1::Verification,
{
let mut node_weights = BinaryHeap::<(Reverse, NodeInfo)>::new();
for (p, leaf) in script_weights {
node_weights.push((Reverse(p as u64), NodeInfo::new_leaf_with_ver(leaf, LeafVersion::default())));
}
if node_weights.is_empty() {
return Err(TaprootBuilderError::IncompleteTree);
}
while node_weights.len() > 1 {
// Combine the last two elements and insert a new node
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");
// Insert the sum of first two in the tree as a new node
// N.B.: p1 + p2 can not practically saturate as you would need to have 2**32 max u32s
// from the input to overflow. However, saturating is a reasonable behavior here as
// huffman tree construction would treat all such elements as "very likely".
let p = Reverse(p1.0.saturating_add(p2.0));
node_weights.push((p, NodeInfo::combine(s1, s2)?));
}
// Every iteration of the loop reduces the node_weights.len() by exactly 1
// Therefore, the loop will eventually terminate with exactly 1 element
debug_assert!(node_weights.len() == 1);
let node = node_weights.pop().expect("huffman tree algorithm is broken").1;
return Ok(Self::from_node_info(secp, internal_key, node));
}
/// Create a new key spend with internal key and proided merkle root.
/// Provide [`None`] for merkle_root if there is no script path.
///
/// *Note*: As per BIP341
///
/// When the merkle root is [`None`], the output key commits to an unspendable
/// script path instead of having no script path. This is achieved by computing
/// the output key point as Q = P + int(hashTapTweak(bytes(P)))G.
/// See also [`TaprootSpendInfo::tap_tweak`].
/// Refer to BIP 341 footnote (Why should the output key always have
/// a taproot commitment, even if there is no script path?) for more details
///
pub fn new_key_spend(
secp: &Secp256k1,
internal_key: UntweakedPublicKey,
merkle_root: Option,
) -> Self {
let (output_key, parity) = internal_key.tap_tweak(secp, merkle_root);
Self {
internal_key: internal_key,
merkle_root: merkle_root,
output_key_parity: parity,
output_key: output_key,
script_map: BTreeMap::new(),
}
}
/// Obtain the tweak and parity used to compute the output_key
pub fn tap_tweak(&self) -> TapTweakHash {
TapTweakHash::from_key_and_tweak(self.internal_key, self.merkle_root)
}
/// Obtain the internal key
pub fn internal_key(&self) -> UntweakedPublicKey {
self.internal_key
}
/// Obtain the merkle root
pub fn merkle_root(&self) -> Option {
self.merkle_root
}
/// Output key(the key used in script pubkey) from Spend data. See also
/// [`TaprootSpendInfo::output_key_parity`]
pub fn output_key(&self) -> TweakedPublicKey {
self.output_key
}
/// Parity of the output key. See also [`TaprootSpendInfo::output_key`]
pub fn output_key_parity(&self) -> bool {
self.output_key_parity
}
// Internal function to compute [`TaprootSpendInfo`] from NodeInfo
fn from_node_info(
secp: &Secp256k1,
internal_key: UntweakedPublicKey,
node: NodeInfo,
) -> TaprootSpendInfo {
// Create as if it is a key spend path with the given merkle root
let root_hash = Some(TapBranchHash::from_inner(node.hash.into_inner()));
let mut info = TaprootSpendInfo::new_key_spend(secp, internal_key, root_hash);
for leaves in node.leaves {
let key = (leaves.script, leaves.ver);
let value = leaves.merkle_branch;
match info.script_map.get_mut(&key) {
Some(set) => {
set.insert(value);
continue; // NLL fix
}
None => {}
}
let mut set = BTreeSet::new();
set.insert(value);
info.script_map.insert(key, set);
}
info
}
/// Access the internal script map
pub fn as_script_map(&self) -> &ScriptMerkleProofMap {
&self.script_map
}
/// Obtain a [`ControlBlock`] for particular script with the given version.
/// Returns [`None`] if the script is not contained in the [`TaprootSpendInfo`]
/// If there are multiple ControlBlocks possible, this returns the shortest one.
pub fn control_block(&self, script_ver: &(Script, LeafVersion)) -> Option {
let merkle_branch_set = self.script_map.get(script_ver)?;
// Choose the smallest one amongst the multiple script maps
let smallest = merkle_branch_set
.iter()
.min_by(|x, y| x.0.len().cmp(&y.0.len()))
.expect("Invariant: Script 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(),
})
}
}
/// Builder for building taproot iteratively. Users can specify tap leaf or omitted/hidden
/// branches in a DFS(Depth first search) walk to construct this tree.
// Similar to Taproot Builder in bitcoin core
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct TaprootBuilder {
// The following doc-comment is from bitcoin core, but modified for rust
// The comment below describes the current state of the builder for a given tree.
//
// For each level in the tree, one NodeInfo object may be present. branch at index 0
// is information about the root; further values are for deeper subtrees being
// explored.
//
// During the construction of Taptree, for every right branch taken to
// reach the position we're currently working in, there will be a (Some(_))
// entry in branch corresponding to the left branch at that level.
//
// For example, imagine this tree: - N0 -
// / \
// N1 N2
// / \ / \
// A B C N3
// / \
// D E
//
// Initially, branch is empty. After processing leaf A, it would become
// {None, None, A}. When processing leaf B, an entry at level 2 already
// exists, and it would thus be combined with it to produce a level 1 one,
// resulting in {None, N1}. Adding C and D takes us to {None, N1, C}
// and {None, N1, C, D} respectively. When E is processed, it is combined
// with D, and then C, and then N1, to produce the root, resulting in {N0}.
//
// This structure allows processing with just O(log n) overhead if the leaves
// are computed on the fly.
//
// As an invariant, there can never be None entries at the end. There can
// also not be more than 128 entries (as that would mean more than 128 levels
// in the tree). The depth of newly added entries will always be at least
// equal to the current size of branch (otherwise it does not correspond
// to a depth-first traversal of a tree). branch is only empty if no entries
// have ever be processed. branch having length 1 corresponds to being done.
//
branch: Vec