Improve docs in taproot module
As has been done in other places in the codebase; improve the docs in the `taproot` module by doing: - Use full sentences (capital letters + full stops) - Use back ticks and links for types where appropriate - Fix grammar - Fix stale docs - Use third person for describing functions - Use 100 character line width - Use markdown sections (`# Examples`, `# Returns`) where appropriate - Separate brief heading from extended description when appropriate - Use `///` for all functions/types (both private and public) I also did: - Build the docs and check all the links - Read all the built docs, check for sanity and pretty-ness
This commit is contained in:
parent
730d35516c
commit
8631474f08
|
@ -53,7 +53,7 @@ const MIDSTATE_TAPTWEAK: [u8; 32] = [
|
||||||
];
|
];
|
||||||
// d129a2f3701c655d6583b6c3b941972795f4e23294fd54f4a2ae8d8547ca590b
|
// d129a2f3701c655d6583b6c3b941972795f4e23294fd54f4a2ae8d8547ca590b
|
||||||
|
|
||||||
/// The SHA-256 midstate value for the TapSigHash hash.
|
/// The SHA-256 midstate value for the [`TapSighashHash`].
|
||||||
const MIDSTATE_TAPSIGHASH: [u8; 32] = [
|
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,
|
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,
|
120, 136, 221, 2, 166, 226, 195, 24, 115, 254, 159,
|
||||||
|
@ -99,8 +99,8 @@ sha256t_hash_newtype!(TapSighashHash, TapSighashTag, MIDSTATE_TAPSIGHASH, 64,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl TapTweakHash {
|
impl TapTweakHash {
|
||||||
/// Create a new BIP341 [`TapTweakHash`] from key and tweak
|
/// Creates a new BIP341 [`TapTweakHash`] from key and tweak. Produces `H_taptweak(P||R)` where
|
||||||
/// Produces H_taptweak(P||R) where P is internal key and R is the merkle root
|
/// `P` is the internal key and `R` is the merkle root.
|
||||||
pub fn from_key_and_tweak(
|
pub fn from_key_and_tweak(
|
||||||
internal_key: UntweakedPublicKey,
|
internal_key: UntweakedPublicKey,
|
||||||
merkle_root: Option<TapBranchHash>,
|
merkle_root: Option<TapBranchHash>,
|
||||||
|
@ -118,7 +118,7 @@ impl TapTweakHash {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TapLeafHash {
|
impl TapLeafHash {
|
||||||
/// function to compute leaf hash from components
|
/// Computes the leaf hash from components.
|
||||||
pub fn from_script(script: &Script, ver: LeafVersion) -> TapLeafHash {
|
pub fn from_script(script: &Script, ver: LeafVersion) -> TapLeafHash {
|
||||||
let mut eng = TapLeafHash::engine();
|
let mut eng = TapLeafHash::engine();
|
||||||
ver.to_consensus()
|
ver.to_consensus()
|
||||||
|
@ -131,24 +131,24 @@ impl TapLeafHash {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maximum depth of a Taproot Tree Script spend path
|
/// Maximum depth of a taproot tree script spend path.
|
||||||
// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L229
|
// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L229
|
||||||
pub const TAPROOT_CONTROL_MAX_NODE_COUNT: usize = 128;
|
pub const TAPROOT_CONTROL_MAX_NODE_COUNT: usize = 128;
|
||||||
/// Size of a taproot control node
|
/// Size of a taproot control node.
|
||||||
// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L228
|
// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L228
|
||||||
pub const TAPROOT_CONTROL_NODE_SIZE: usize = 32;
|
pub const TAPROOT_CONTROL_NODE_SIZE: usize = 32;
|
||||||
/// Tapleaf mask for getting the leaf version from first byte of control block
|
/// 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
|
// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L225
|
||||||
pub const TAPROOT_LEAF_MASK: u8 = 0xfe;
|
pub const TAPROOT_LEAF_MASK: u8 = 0xfe;
|
||||||
/// Tapscript leaf version
|
/// Tapscript leaf version.
|
||||||
// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L226
|
// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L226
|
||||||
pub const TAPROOT_LEAF_TAPSCRIPT: u8 = 0xc0;
|
pub const TAPROOT_LEAF_TAPSCRIPT: u8 = 0xc0;
|
||||||
/// Taproot annex prefix
|
/// Taproot annex prefix.
|
||||||
pub const TAPROOT_ANNEX_PREFIX: u8 = 0x50;
|
pub const TAPROOT_ANNEX_PREFIX: u8 = 0x50;
|
||||||
/// Tapscript control base size
|
/// Tapscript control base size.
|
||||||
// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L227
|
// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L227
|
||||||
pub const TAPROOT_CONTROL_BASE_SIZE: usize = 33;
|
pub const TAPROOT_CONTROL_BASE_SIZE: usize = 33;
|
||||||
/// Tapscript control max size
|
/// Tapscript control max size.
|
||||||
// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L230
|
// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L230
|
||||||
pub const TAPROOT_CONTROL_MAX_SIZE: usize =
|
pub const TAPROOT_CONTROL_MAX_SIZE: usize =
|
||||||
TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * TAPROOT_CONTROL_MAX_NODE_COUNT;
|
TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * TAPROOT_CONTROL_MAX_NODE_COUNT;
|
||||||
|
@ -156,45 +156,48 @@ pub const TAPROOT_CONTROL_MAX_SIZE: usize =
|
||||||
// type alias for versioned tap script corresponding merkle proof
|
// type alias for versioned tap script corresponding merkle proof
|
||||||
type ScriptMerkleProofMap = BTreeMap<(Script, LeafVersion), BTreeSet<TaprootMerkleBranch>>;
|
type ScriptMerkleProofMap = BTreeMap<(Script, LeafVersion), BTreeSet<TaprootMerkleBranch>>;
|
||||||
|
|
||||||
/// Data structure for representing Taproot spending information.
|
/// Represents 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:
|
/// Taproot output corresponds to a combination of a single public key condition (known as the
|
||||||
/// - Spending using the key path i.e., with secret key corresponding to the output_key
|
/// internal key), and zero or more general conditions encoded in scripts organized in the form of a
|
||||||
/// - By satisfying any of the scripts in the script spent path. Each script can be satisfied by providing
|
/// binary tree.
|
||||||
/// 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),
|
/// Taproot can be spent by either:
|
||||||
/// the most likely one should be made the internal key.
|
/// - Spending using the key path i.e., with secret key corresponding to the tweaked `output_key`.
|
||||||
/// See [BIP341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki) for more details
|
/// - By satisfying any of the scripts in the script spend path. Each script can be satisfied by
|
||||||
/// on choosing internal keys for a taproot application
|
/// providing a witness stack consisting of the script's inputs, plus the script itself and the
|
||||||
|
/// control block.
|
||||||
///
|
///
|
||||||
/// Note: This library currently does not support [annex](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#cite_note-5)
|
/// If one or more of the spending conditions consist of just a single key (after aggregation), the
|
||||||
|
/// most likely key 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)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct TaprootSpendInfo {
|
pub struct TaprootSpendInfo {
|
||||||
/// The BIP341 internal key.
|
/// The BIP341 internal key.
|
||||||
internal_key: UntweakedPublicKey,
|
internal_key: UntweakedPublicKey,
|
||||||
/// The Merkle root of the script tree (None if there are no scripts)
|
/// The merkle root of the script tree (None if there are no scripts).
|
||||||
merkle_root: Option<TapBranchHash>,
|
merkle_root: Option<TapBranchHash>,
|
||||||
/// The sign final output pubkey as per BIP 341
|
/// The sign final output pubkey as per BIP 341.
|
||||||
output_key_parity: secp256k1::Parity,
|
output_key_parity: secp256k1::Parity,
|
||||||
/// The tweaked output key
|
/// The tweaked output key.
|
||||||
output_key: TweakedPublicKey,
|
output_key: TweakedPublicKey,
|
||||||
/// Map from (script, leaf_version) to (sets of) [`TaprootMerkleBranch`].
|
/// Map from (script, leaf_version) to (sets of) [`TaprootMerkleBranch`]. More than one control
|
||||||
/// More than one control block for a given script is only possible if it
|
/// block for a given script is only possible if it appears in multiple branches of the tree. In
|
||||||
/// appears in multiple branches of the tree. In all cases, keeping one should
|
/// all cases, keeping one should be enough for spending funds, but we keep all of the paths so
|
||||||
/// be enough for spending funds, but we keep all of the paths so that
|
/// that a full tree can be constructed again from spending data if required.
|
||||||
/// a full tree can be constructed again from spending data if required.
|
|
||||||
script_map: ScriptMerkleProofMap,
|
script_map: ScriptMerkleProofMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TaprootSpendInfo {
|
impl TaprootSpendInfo {
|
||||||
/// Create a new [`TaprootSpendInfo`] from a list of script(with default script version).
|
/// Creates a new [`TaprootSpendInfo`] from a list of scripts (with default script version) and
|
||||||
|
/// weights of satisfaction for that script.
|
||||||
///
|
///
|
||||||
/// See [`TaprootBuilder::with_huffman_tree`] for more detailed documentation
|
/// See [`TaprootBuilder::with_huffman_tree`] for more detailed documentation.
|
||||||
pub fn with_huffman_tree<C, I>(
|
pub fn with_huffman_tree<C, I>(
|
||||||
secp: &Secp256k1<C>,
|
secp: &Secp256k1<C>,
|
||||||
internal_key: UntweakedPublicKey,
|
internal_key: UntweakedPublicKey,
|
||||||
|
@ -207,18 +210,17 @@ impl TaprootSpendInfo {
|
||||||
TaprootBuilder::with_huffman_tree(script_weights)?.finalize(secp, internal_key)
|
TaprootBuilder::with_huffman_tree(script_weights)?.finalize(secp, internal_key)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new key spend with internal key and proided merkle root.
|
/// Creates a new key spend with `internal_key` and `merkle_root`. Provide [`None`] for
|
||||||
/// Provide [`None`] for merkle_root if there is no script path.
|
/// `merkle_root` if there is no script path.
|
||||||
///
|
///
|
||||||
/// *Note*: As per BIP341
|
/// *Note*: As per BIP341
|
||||||
///
|
///
|
||||||
/// When the merkle root is [`None`], the output key commits to an unspendable
|
/// When the merkle root is [`None`], the output key commits to an unspendable script path
|
||||||
/// script path instead of having no script path. This is achieved by computing
|
/// instead of having no script path. This is achieved by computing the output key point as
|
||||||
/// the output key point as Q = P + int(hashTapTweak(bytes(P)))G.
|
/// `Q = P + int(hashTapTweak(bytes(P)))G`. See also [`TaprootSpendInfo::tap_tweak`].
|
||||||
/// 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
|
|
||||||
///
|
///
|
||||||
|
/// 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<C: secp256k1::Verification>(
|
pub fn new_key_spend<C: secp256k1::Verification>(
|
||||||
secp: &Secp256k1<C>,
|
secp: &Secp256k1<C>,
|
||||||
internal_key: UntweakedPublicKey,
|
internal_key: UntweakedPublicKey,
|
||||||
|
@ -234,35 +236,36 @@ impl TaprootSpendInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtain the tweak and parity used to compute the output_key
|
/// Returns the `TapTweakHash` for this [`TaprootSpendInfo`] i.e., the tweak using `internal_key`
|
||||||
|
/// and `merkle_root`.
|
||||||
pub fn tap_tweak(&self) -> TapTweakHash {
|
pub fn tap_tweak(&self) -> TapTweakHash {
|
||||||
TapTweakHash::from_key_and_tweak(self.internal_key, self.merkle_root)
|
TapTweakHash::from_key_and_tweak(self.internal_key, self.merkle_root)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtain the internal key
|
/// Returns the internal key for this [`TaprootSpendInfo`].
|
||||||
pub fn internal_key(&self) -> UntweakedPublicKey {
|
pub fn internal_key(&self) -> UntweakedPublicKey {
|
||||||
self.internal_key
|
self.internal_key
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtain the merkle root
|
/// Returns the merkle root for this [`TaprootSpendInfo`].
|
||||||
pub fn merkle_root(&self) -> Option<TapBranchHash> {
|
pub fn merkle_root(&self) -> Option<TapBranchHash> {
|
||||||
self.merkle_root
|
self.merkle_root
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Output key(the key used in script pubkey) from Spend data. See also
|
/// Returns the output key (the key used in script pubkey) for this [`TaprootSpendInfo`].
|
||||||
/// [`TaprootSpendInfo::output_key_parity`]
|
|
||||||
pub fn output_key(&self) -> TweakedPublicKey {
|
pub fn output_key(&self) -> TweakedPublicKey {
|
||||||
self.output_key
|
self.output_key
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parity of the output key. See also [`TaprootSpendInfo::output_key`]
|
/// Returns the parity of the output key. See also [`TaprootSpendInfo::output_key`].
|
||||||
pub fn output_key_parity(&self) -> secp256k1::Parity {
|
pub fn output_key_parity(&self) -> secp256k1::Parity {
|
||||||
self.output_key_parity
|
self.output_key_parity
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compute [`TaprootSpendInfo`] from [`NodeInfo`], and internal key.
|
/// Computes the [`TaprootSpendInfo`] from `internal_key` and `node`.
|
||||||
/// This is useful when you want to manually build a taproot tree wihtout
|
///
|
||||||
/// using [`TaprootBuilder`].
|
/// This is useful when you want to manually build a taproot tree without using
|
||||||
|
/// [`TaprootBuilder`].
|
||||||
pub fn from_node_info<C: secp256k1::Verification>(
|
pub fn from_node_info<C: secp256k1::Verification>(
|
||||||
secp: &Secp256k1<C>,
|
secp: &Secp256k1<C>,
|
||||||
internal_key: UntweakedPublicKey,
|
internal_key: UntweakedPublicKey,
|
||||||
|
@ -288,14 +291,17 @@ impl TaprootSpendInfo {
|
||||||
info
|
info
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the internal script map
|
/// Returns the internal script map.
|
||||||
pub fn as_script_map(&self) -> &ScriptMerkleProofMap {
|
pub fn as_script_map(&self) -> &ScriptMerkleProofMap {
|
||||||
&self.script_map
|
&self.script_map
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtain a [`ControlBlock`] for particular script with the given version.
|
/// Constructs 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.
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// - If there are multiple control blocks possible, returns the shortest one.
|
||||||
|
/// - If the script is not contained in the [`TaprootSpendInfo`], returns `None`.
|
||||||
pub fn control_block(&self, script_ver: &(Script, LeafVersion)) -> Option<ControlBlock> {
|
pub fn control_block(&self, script_ver: &(Script, LeafVersion)) -> Option<ControlBlock> {
|
||||||
let merkle_branch_set = self.script_map.get(script_ver)?;
|
let merkle_branch_set = self.script_map.get(script_ver)?;
|
||||||
// Choose the smallest one amongst the multiple script maps
|
// Choose the smallest one amongst the multiple script maps
|
||||||
|
@ -312,22 +318,23 @@ impl TaprootSpendInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builder for building taproot iteratively. Users can specify tap leaf or omitted/hidden
|
/// Builder for building taproot iteratively. Users can specify tap leaf or omitted/hidden branches
|
||||||
/// branches in a DFS(Depth first search) walk to construct this tree.
|
/// in a depth-first search (DFS) walk order to construct this tree.
|
||||||
// Similar to Taproot Builder in bitcoin core
|
///
|
||||||
|
/// See Wikipedia for more details on [DFS](https://en.wikipedia.org/wiki/Depth-first_search).
|
||||||
|
// Similar to Taproot Builder in bitcoin core.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct TaprootBuilder {
|
pub struct TaprootBuilder {
|
||||||
// The following doc-comment is from bitcoin core, but modified for rust
|
// The following doc-comment is from bitcoin core, but modified for Rust. It describes the
|
||||||
// The comment below describes the current state of the builder for a given tree.
|
// 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
|
// For each level in the tree, one NodeInfo object may be present. Branch at index 0 is
|
||||||
// is information about the root; further values are for deeper subtrees being
|
// information about the root; further values are for deeper subtrees being explored.
|
||||||
// explored.
|
|
||||||
//
|
//
|
||||||
// During the construction of Taptree, for every right branch taken to
|
// During the construction of Taptree, for every right branch taken to reach the position we're
|
||||||
// reach the position we're currently working in, there will be a (Some(_))
|
// currently working on, there will be a `(Some(_))` entry in branch corresponding to the left
|
||||||
// entry in branch corresponding to the left branch at that level.
|
// branch at that level.
|
||||||
//
|
//
|
||||||
// For example, imagine this tree: - N0 -
|
// For example, imagine this tree: - N0 -
|
||||||
// / \
|
// / \
|
||||||
|
@ -337,50 +344,50 @@ pub struct TaprootBuilder {
|
||||||
// / \
|
// / \
|
||||||
// D E
|
// D E
|
||||||
//
|
//
|
||||||
// Initially, branch is empty. After processing leaf A, it would become
|
// Initially, branch is empty. After processing leaf A, it would become {None, None, A}. When
|
||||||
// {None, None, A}. When processing leaf B, an entry at level 2 already
|
// processing leaf B, an entry at level 2 already exists, and it would thus be combined with it
|
||||||
// exists, and it would thus be combined with it to produce a level 1 one,
|
// to produce a level 1 entry, resulting in {None, N1}. Adding C and D takes us to {None, N1, C}
|
||||||
// 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 {None, N1, C, D} respectively. When E is processed, it is combined
|
// and then N1, to produce the root, resulting in {N0}.
|
||||||
// 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
|
// This structure allows processing with just O(log n) overhead if the leaves are computed on
|
||||||
// are computed on the fly.
|
// 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.
|
|
||||||
//
|
//
|
||||||
|
// 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). A branch is only empty if no entries have
|
||||||
|
// ever be processed. A branch having length 1 corresponds to being done.
|
||||||
branch: Vec<Option<NodeInfo>>,
|
branch: Vec<Option<NodeInfo>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TaprootBuilder {
|
impl TaprootBuilder {
|
||||||
/// Create a new instance of [`TaprootBuilder`]
|
/// Creates a new instance of [`TaprootBuilder`].
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
TaprootBuilder { branch: vec![] }
|
TaprootBuilder { branch: vec![] }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new [`TaprootBuilder`] from a list of script(with default script version) and
|
/// Creates a new [`TaprootSpendInfo`] from a list of scripts (with default script version) and
|
||||||
/// weights of satisfaction for that script. The weights represent the probability of
|
/// weights of satisfaction for that script.
|
||||||
/// 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
|
/// The weights represent the probability of each branch being taken. If probabilities/weights
|
||||||
/// case satisfaction cost. This function takes an iterator of (`u32`, &[`Script`]) tuples
|
/// for each condition are known, constructing the tree as a Huffman Tree is the optimal way to
|
||||||
/// as an input, where `u32` represents the satisfaction weights of the script branch.
|
/// minimize average case satisfaction cost. This function takes as input an iterator of
|
||||||
/// For example, [(3, S1), (2, S2), (5, S3)] would construct a TapTree that has optimal
|
/// `tuple(u32, &Script)` where `u32` 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%.
|
/// satisfaction weight when probability for S1 is 30%, S2 is 20% and S3 is 50%.
|
||||||
///
|
///
|
||||||
/// # Errors:
|
/// # Errors:
|
||||||
///
|
///
|
||||||
/// - When the optimal huffman tree has a depth more than 128
|
/// - When the optimal Huffman Tree has a depth more than 128.
|
||||||
/// - If the provided list of script weights is empty
|
/// - If the provided list of script weights is empty.
|
||||||
///
|
///
|
||||||
/// # Edge Cases:
|
/// # 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
|
/// If the script weight calculations overflow, a sub-optimal tree may be generated. This should
|
||||||
/// 2^32.
|
/// not happen unless you are dealing with billions of branches with weights close to 2^32.
|
||||||
|
///
|
||||||
|
/// [`TapTree`]: ::util::psbt::TapTree
|
||||||
pub fn with_huffman_tree<I>(
|
pub fn with_huffman_tree<I>(
|
||||||
script_weights: I,
|
script_weights: I,
|
||||||
) -> Result<Self, TaprootBuilderError>
|
) -> Result<Self, TaprootBuilderError>
|
||||||
|
@ -412,7 +419,8 @@ impl TaprootBuilder {
|
||||||
Ok(TaprootBuilder{branch: vec![Some(node)]})
|
Ok(TaprootBuilder{branch: vec![Some(node)]})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Just like [`TaprootBuilder::add_leaf`] but allows to specify script version
|
/// Adds a leaf script at `depth` to the builder with script version `ver`. Errors if the leaves
|
||||||
|
/// are not provided in DFS walk order. The depth of the root node is 0.
|
||||||
pub fn add_leaf_with_ver(
|
pub fn add_leaf_with_ver(
|
||||||
self,
|
self,
|
||||||
depth: usize,
|
depth: usize,
|
||||||
|
@ -423,29 +431,27 @@ impl TaprootBuilder {
|
||||||
self.insert(leaf, depth)
|
self.insert(leaf, depth)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a leaf script at a depth `depth` to the builder with default script version.
|
/// Adds a leaf script at `depth` to the builder with default script version. Errors if the
|
||||||
/// This will error if the leave are not provided in a DFS walk order. The depth of the
|
/// leaves are not provided in DFS walk order. The depth of the root node is 0.
|
||||||
/// root node is 0 and it's immediate child would be at depth 1.
|
///
|
||||||
/// See [`TaprootBuilder::add_leaf_with_ver`] for adding a leaf with specific version
|
/// See [`TaprootBuilder::add_leaf_with_ver`] for adding a leaf with specific version.
|
||||||
/// See [Wikipedia](https://en.wikipedia.org/wiki/Depth-first_search) for more details
|
|
||||||
pub fn add_leaf(self, depth: usize, script: Script) -> Result<Self, TaprootBuilderError> {
|
pub fn add_leaf(self, depth: usize, script: Script) -> Result<Self, TaprootBuilderError> {
|
||||||
self.add_leaf_with_ver(depth, script, LeafVersion::TapScript)
|
self.add_leaf_with_ver(depth, script, LeafVersion::TapScript)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a hidden/omitted node at a depth `depth` to the builder.
|
/// Adds a hidden/omitted node at `depth` to the builder. Errors if the leaves are not provided
|
||||||
/// This will error if the node are not provided in a DFS walk order. The depth of the
|
/// in DFS walk order. The depth of the root node is 0.
|
||||||
/// root node is 0 and it's immediate child would be at depth 1.
|
|
||||||
pub fn add_hidden(self, depth: usize, hash: sha256::Hash) -> Result<Self, TaprootBuilderError> {
|
pub fn add_hidden(self, depth: usize, hash: sha256::Hash) -> Result<Self, TaprootBuilderError> {
|
||||||
let node = NodeInfo::new_hidden(hash);
|
let node = NodeInfo::new_hidden(hash);
|
||||||
self.insert(node, depth)
|
self.insert(node, depth)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the builder is a complete tree
|
/// Checks if the builder is a complete tree.
|
||||||
pub fn is_complete(&self) -> bool {
|
pub fn is_complete(&self) -> bool {
|
||||||
self.branch.len() == 1 && self.branch[0].is_some()
|
self.branch.len() == 1 && self.branch[0].is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create [`TaprootSpendInfo`] with the given internal key
|
/// Creates a [`TaprootSpendInfo`] with the given internal key.
|
||||||
pub fn finalize<C: secp256k1::Verification>(
|
pub fn finalize<C: secp256k1::Verification>(
|
||||||
mut self,
|
mut self,
|
||||||
secp: &Secp256k1<C>,
|
secp: &Secp256k1<C>,
|
||||||
|
@ -466,7 +472,7 @@ impl TaprootBuilder {
|
||||||
&self.branch
|
&self.branch
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to insert a leaf at a depth
|
/// Inserts a leaf at `depth`.
|
||||||
fn insert(mut self, mut node: NodeInfo, mut depth: usize) -> Result<Self, TaprootBuilderError> {
|
fn insert(mut self, mut node: NodeInfo, mut depth: usize) -> Result<Self, TaprootBuilderError> {
|
||||||
// early error on invalid depth. Though this will be checked later
|
// early error on invalid depth. Though this will be checked later
|
||||||
// while constructing TaprootMerkelBranch
|
// while constructing TaprootMerkelBranch
|
||||||
|
@ -513,15 +519,16 @@ impl TaprootBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data structure used to represent node information in taproot tree.
|
/// Represents the node information in taproot tree.
|
||||||
|
///
|
||||||
/// You can use [`TaprootSpendInfo::from_node_info`] to a get [`TaprootSpendInfo`]
|
/// You can use [`TaprootSpendInfo::from_node_info`] to a get [`TaprootSpendInfo`]
|
||||||
/// from the merkle root [`NodeInfo`].
|
/// from the merkle root [`NodeInfo`].
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct NodeInfo {
|
pub struct NodeInfo {
|
||||||
/// Merkle Hash for this node
|
/// Merkle hash for this node.
|
||||||
pub(crate) hash: sha256::Hash,
|
pub(crate) hash: sha256::Hash,
|
||||||
/// information about leaves inside this node
|
/// Information about leaves inside this node.
|
||||||
pub(crate) leaves: Vec<LeafInfo>,
|
pub(crate) leaves: Vec<LeafInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,20 +576,20 @@ impl NodeInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internally used structure to store information about taproot leaf node
|
/// Store information about taproot leaf node.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub(crate) struct LeafInfo {
|
pub(crate) struct LeafInfo {
|
||||||
// The underlying script
|
/// The underlying script.
|
||||||
pub(crate) script: Script,
|
pub(crate) script: Script,
|
||||||
// The leaf version
|
/// The leaf version.
|
||||||
pub(crate) ver: LeafVersion,
|
pub(crate) ver: LeafVersion,
|
||||||
// The merkle proof(hashing partners) to get this node
|
/// The merkle proof (hashing partners) to get this node.
|
||||||
pub(crate) merkle_branch: TaprootMerkleBranch,
|
pub(crate) merkle_branch: TaprootMerkleBranch,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LeafInfo {
|
impl LeafInfo {
|
||||||
// Create an instance of Self from Script with default version and no merkle branch
|
/// Creates an new [`LeafInfo`] from `script` and `ver` and no merkle branch.
|
||||||
fn new(script: Script, ver: LeafVersion) -> Self {
|
fn new(script: Script, ver: LeafVersion) -> Self {
|
||||||
Self {
|
Self {
|
||||||
script: script,
|
script: script,
|
||||||
|
@ -591,27 +598,27 @@ impl LeafInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute a leaf hash for the given leaf
|
/// Computes a leaf hash for this [`LeafInfo`].
|
||||||
fn hash(&self) -> sha256::Hash {
|
fn hash(&self) -> sha256::Hash {
|
||||||
let leaf_hash = TapLeafHash::from_script(&self.script, self.ver);
|
let leaf_hash = TapLeafHash::from_script(&self.script, self.ver);
|
||||||
sha256::Hash::from_inner(leaf_hash.into_inner())
|
sha256::Hash::from_inner(leaf_hash.into_inner())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The Merkle proof for inclusion of a tree in a taptree hash
|
/// The merkle proof for inclusion of a tree in a taptree hash.
|
||||||
// The type of hash is sha256::Hash because the vector might contain
|
// The type of hash is `sha256::Hash` because the vector might contain both `TapBranchHash` and
|
||||||
// both TapBranchHash and TapLeafHash
|
// `TapLeafHash`.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct TaprootMerkleBranch(Vec<sha256::Hash>);
|
pub struct TaprootMerkleBranch(Vec<sha256::Hash>);
|
||||||
|
|
||||||
impl TaprootMerkleBranch {
|
impl TaprootMerkleBranch {
|
||||||
/// Obtain a reference to inner
|
/// Returns a reference to the inner vector of hashes.
|
||||||
pub fn as_inner(&self) -> &[sha256::Hash] {
|
pub fn as_inner(&self) -> &[sha256::Hash] {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a merkle proof from slice
|
/// Creates a merkle proof from raw data representing a list of hashes.
|
||||||
pub fn from_slice(sl: &[u8]) -> Result<Self, TaprootError> {
|
pub fn from_slice(sl: &[u8]) -> Result<Self, TaprootError> {
|
||||||
if sl.len() % TAPROOT_CONTROL_NODE_SIZE != 0 {
|
if sl.len() % TAPROOT_CONTROL_NODE_SIZE != 0 {
|
||||||
Err(TaprootError::InvalidMerkleBranchSize(sl.len()))
|
Err(TaprootError::InvalidMerkleBranchSize(sl.len()))
|
||||||
|
@ -630,7 +637,11 @@ impl TaprootMerkleBranch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serialize to a writer. Returns the number of bytes written
|
/// Serializes to a writer.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// The number of bytes written to the writer.
|
||||||
pub fn encode<Write: io::Write>(&self, mut writer: Write) -> io::Result<usize> {
|
pub fn encode<Write: io::Write>(&self, mut writer: Write) -> io::Result<usize> {
|
||||||
for hash in self.0.iter() {
|
for hash in self.0.iter() {
|
||||||
writer.write_all(hash)?;
|
writer.write_all(hash)?;
|
||||||
|
@ -638,12 +649,12 @@ impl TaprootMerkleBranch {
|
||||||
Ok(self.0.len() * sha256::Hash::LEN)
|
Ok(self.0.len() * sha256::Hash::LEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serialize self as bytes
|
/// Serializes `self` as bytes.
|
||||||
pub fn serialize(&self) -> Vec<u8> {
|
pub fn serialize(&self) -> Vec<u8> {
|
||||||
self.0.iter().map(|e| e.as_inner()).flatten().map(|x| *x).collect::<Vec<u8>>()
|
self.0.iter().map(|e| e.as_inner()).flatten().map(|x| *x).collect::<Vec<u8>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal function to append elements to proof
|
/// Appends elements to proof.
|
||||||
fn push(&mut self, h: sha256::Hash) -> Result<(), TaprootBuilderError> {
|
fn push(&mut self, h: sha256::Hash) -> Result<(), TaprootBuilderError> {
|
||||||
if self.0.len() >= TAPROOT_CONTROL_MAX_NODE_COUNT {
|
if self.0.len() >= TAPROOT_CONTROL_MAX_NODE_COUNT {
|
||||||
Err(TaprootBuilderError::InvalidMerkleTreeDepth(self.0.len()))
|
Err(TaprootBuilderError::InvalidMerkleTreeDepth(self.0.len()))
|
||||||
|
@ -653,8 +664,11 @@ impl TaprootMerkleBranch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a MerkleProof from Vec<[`sha256::Hash`]>. Returns an error when
|
/// Creates a merkle proof from list of hashes.
|
||||||
/// inner proof len is more than TAPROOT_CONTROL_MAX_NODE_COUNT (128)
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// If inner proof length is more than [`TAPROOT_CONTROL_MAX_NODE_COUNT`] (128).
|
||||||
pub fn from_inner(inner: Vec<sha256::Hash>) -> Result<Self, TaprootError> {
|
pub fn from_inner(inner: Vec<sha256::Hash>) -> Result<Self, TaprootError> {
|
||||||
if inner.len() > TAPROOT_CONTROL_MAX_NODE_COUNT {
|
if inner.len() > TAPROOT_CONTROL_MAX_NODE_COUNT {
|
||||||
Err(TaprootError::InvalidMerkleTreeDepth(inner.len()))
|
Err(TaprootError::InvalidMerkleTreeDepth(inner.len()))
|
||||||
|
@ -663,35 +677,38 @@ impl TaprootMerkleBranch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consume Self to get Vec<[`sha256::Hash`]>
|
/// Returns the inner list of hashes.
|
||||||
pub fn into_inner(self) -> Vec<sha256::Hash> {
|
pub fn into_inner(self) -> Vec<sha256::Hash> {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Control Block data structure used in Tapscript satisfaction
|
/// Control block data structure used in Tapscript satisfaction.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct ControlBlock {
|
pub struct ControlBlock {
|
||||||
/// The tapleaf version,
|
/// The tapleaf version.
|
||||||
pub leaf_version: LeafVersion,
|
pub leaf_version: LeafVersion,
|
||||||
/// The parity of the output key (NOT THE INTERNAL KEY WHICH IS ALWAYS XONLY)
|
/// The parity of the output key (NOT THE INTERNAL KEY WHICH IS ALWAYS XONLY).
|
||||||
pub output_key_parity: secp256k1::Parity,
|
pub output_key_parity: secp256k1::Parity,
|
||||||
/// The internal key
|
/// The internal key.
|
||||||
pub internal_key: UntweakedPublicKey,
|
pub internal_key: UntweakedPublicKey,
|
||||||
/// The merkle proof of a script associated with this leaf
|
/// The merkle proof of a script associated with this leaf.
|
||||||
pub merkle_branch: TaprootMerkleBranch,
|
pub merkle_branch: TaprootMerkleBranch,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ControlBlock {
|
impl ControlBlock {
|
||||||
/// Obtain a ControlBlock from slice. This is an extra witness element
|
/// Constructs a `ControlBlock` from slice. This is an extra witness element that provides the
|
||||||
/// that provides the proof that taproot script pubkey is correctly computed
|
/// proof that taproot script pubkey is correctly computed with some specified leaf hash. This
|
||||||
/// with some specified leaf hash. This is the last element in
|
/// is the last element in taproot witness when spending a output via script path.
|
||||||
/// taproot witness when spending a output via script path.
|
|
||||||
///
|
///
|
||||||
/// # Errors:
|
/// # Errors
|
||||||
/// - If the control block size is not of the form 33 + 32m where
|
///
|
||||||
/// 0 <= m <= 128, InvalidControlBlock is returned
|
/// - `TaprootError::InvalidControlBlockSize` if `sl` is not of size 1 + 32 + 32N for any N >= 0.
|
||||||
|
/// - `TaprootError::InvalidParity` if first byte of `sl` is not a valid output key parity.
|
||||||
|
/// - `TaprootError::InvalidTaprootLeafVersion` if first byte of `sl` is not a valid leaf version.
|
||||||
|
/// - `TaprootError::InvalidInternalKey` if internal key is invalid (first 32 bytes after the parity byte).
|
||||||
|
/// - `TaprootError::InvalidMerkleTreeDepth` if merkle tree is too deep (more than 128 levels).
|
||||||
pub fn from_slice(sl: &[u8]) -> Result<ControlBlock, TaprootError> {
|
pub fn from_slice(sl: &[u8]) -> Result<ControlBlock, TaprootError> {
|
||||||
if sl.len() < TAPROOT_CONTROL_BASE_SIZE
|
if sl.len() < TAPROOT_CONTROL_BASE_SIZE
|
||||||
|| (sl.len() - TAPROOT_CONTROL_BASE_SIZE) % TAPROOT_CONTROL_NODE_SIZE != 0
|
|| (sl.len() - TAPROOT_CONTROL_BASE_SIZE) % TAPROOT_CONTROL_NODE_SIZE != 0
|
||||||
|
@ -712,13 +729,17 @@ impl ControlBlock {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtain the size of control block. Faster and more efficient than calling
|
/// Returns the size of control block. Faster and more efficient than calling
|
||||||
/// serialize() followed by len(). Can be handy for fee estimation
|
/// `Self::serialize().len()`. Can be handy for fee estimation.
|
||||||
pub fn size(&self) -> usize {
|
pub fn size(&self) -> usize {
|
||||||
TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * self.merkle_branch.as_inner().len()
|
TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * self.merkle_branch.as_inner().len()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serialize to a writer. Returns the number of bytes written
|
/// Serializes to a writer.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// The number of bytes written to the writer.
|
||||||
pub fn encode<Write: io::Write>(&self, mut writer: Write) -> io::Result<usize> {
|
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();
|
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(&[first_byte])?;
|
||||||
|
@ -727,19 +748,21 @@ impl ControlBlock {
|
||||||
Ok(self.size())
|
Ok(self.size())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serialize the control block. This would be required when
|
/// Serializes the control block.
|
||||||
/// using ControlBlock as a witness element while spending an output via
|
///
|
||||||
/// script path. This serialization does not include the VarInt prefix that would be
|
/// This would be required when using [`ControlBlock`] as a witness element while spending an
|
||||||
/// applied when encoding this element as a witness.
|
/// output via script path. This serialization does not include the [`::VarInt`] prefix that would
|
||||||
|
/// be applied when encoding this element as a witness.
|
||||||
pub fn serialize(&self) -> Vec<u8> {
|
pub fn serialize(&self) -> Vec<u8> {
|
||||||
let mut buf = Vec::with_capacity(self.size());
|
let mut buf = Vec::with_capacity(self.size());
|
||||||
self.encode(&mut buf).expect("writers don't error");
|
self.encode(&mut buf).expect("writers don't error");
|
||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Verify that a control block is correct proof for a given output key and script
|
/// Verifies that a control block is correct proof for a given output key and script.
|
||||||
/// This only checks that script is contained inside the taptree described by
|
///
|
||||||
/// output key, full verification must also execute the script with witness data
|
/// Only checks that script is contained inside the taptree described by output key. Full
|
||||||
|
/// verification must also execute the script with witness data.
|
||||||
pub fn verify_taproot_commitment<C: secp256k1::Verification>(
|
pub fn verify_taproot_commitment<C: secp256k1::Verification>(
|
||||||
&self,
|
&self,
|
||||||
secp: &Secp256k1<C>,
|
secp: &Secp256k1<C>,
|
||||||
|
@ -791,7 +814,7 @@ impl FutureLeafVersion {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get consensus representation of the future leaf version.
|
/// Returns the consensus representation of this [`FutureLeafVersion`].
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_consensus(self) -> u8 {
|
pub fn to_consensus(self) -> u8 {
|
||||||
self.0
|
self.0
|
||||||
|
@ -819,20 +842,21 @@ impl fmt::UpperHex for FutureLeafVersion {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The leaf version for tapleafs
|
/// The leaf version for tapleafs.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub enum LeafVersion {
|
pub enum LeafVersion {
|
||||||
/// BIP-342 tapscript
|
/// BIP-342 tapscript.
|
||||||
TapScript,
|
TapScript,
|
||||||
|
|
||||||
/// Future leaf version
|
/// Future leaf version.
|
||||||
Future(FutureLeafVersion)
|
Future(FutureLeafVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LeafVersion {
|
impl LeafVersion {
|
||||||
/// Obtain LeafVersion from consensus byte representation.
|
/// Creates a [`LeafVersion`] from consensus byte representation.
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
|
///
|
||||||
/// - If the last bit of the `version` is odd.
|
/// - If the last bit of the `version` is odd.
|
||||||
/// - If the `version` is 0x50 ([`TAPROOT_ANNEX_PREFIX`]).
|
/// - If the `version` is 0x50 ([`TAPROOT_ANNEX_PREFIX`]).
|
||||||
// Text from BIP341:
|
// Text from BIP341:
|
||||||
|
@ -852,7 +876,7 @@ impl LeafVersion {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get consensus representation of the [`LeafVersion`].
|
/// Returns the consensus representation of this [`LeafVersion`].
|
||||||
pub fn to_consensus(self) -> u8 {
|
pub fn to_consensus(self) -> u8 {
|
||||||
match self {
|
match self {
|
||||||
LeafVersion::TapScript => TAPROOT_LEAF_TAPSCRIPT,
|
LeafVersion::TapScript => TAPROOT_LEAF_TAPSCRIPT,
|
||||||
|
@ -884,7 +908,7 @@ impl fmt::UpperHex for LeafVersion {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serializes LeafVersion as u8 using consensus encoding
|
/// Serializes [`LeafVersion`] as a `u8` using consensus encoding.
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
||||||
impl ::serde::Serialize for LeafVersion {
|
impl ::serde::Serialize for LeafVersion {
|
||||||
|
@ -896,7 +920,7 @@ impl ::serde::Serialize for LeafVersion {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deserializes LeafVersion as u8 using consensus encoding
|
/// Deserializes [`LeafVersion`] as a `u8` using consensus encoding.
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
||||||
impl<'de> ::serde::Deserialize<'de> for LeafVersion {
|
impl<'de> ::serde::Deserialize<'de> for LeafVersion {
|
||||||
|
@ -926,20 +950,20 @@ impl<'de> ::serde::Deserialize<'de> for LeafVersion {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Detailed error type for taproot builder
|
/// Detailed error type for taproot builder.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub enum TaprootBuilderError {
|
pub enum TaprootBuilderError {
|
||||||
/// Merkle Tree depth must not be more than 128
|
/// Merkle tree depth must not be more than 128.
|
||||||
InvalidMerkleTreeDepth(usize),
|
InvalidMerkleTreeDepth(usize),
|
||||||
/// Nodes must be added specified in DFS order
|
/// Nodes must be added specified in DFS walk order.
|
||||||
NodeNotInDfsOrder,
|
NodeNotInDfsOrder,
|
||||||
/// Two nodes at depth 0 are not allowed
|
/// Two nodes at depth 0 are not allowed.
|
||||||
OverCompleteTree,
|
OverCompleteTree,
|
||||||
/// Invalid taproot internal key
|
/// Invalid taproot internal key.
|
||||||
InvalidInternalKey(secp256k1::Error),
|
InvalidInternalKey(secp256k1::Error),
|
||||||
/// Called finalize on an incomplete tree
|
/// Called finalize on an incomplete tree.
|
||||||
IncompleteTree,
|
IncompleteTree,
|
||||||
/// Called finalize on a empty tree
|
/// Called finalize on a empty tree.
|
||||||
EmptyTree,
|
EmptyTree,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -974,22 +998,22 @@ impl fmt::Display for TaprootBuilderError {
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
impl error::Error for TaprootBuilderError {}
|
impl error::Error for TaprootBuilderError {}
|
||||||
|
|
||||||
/// Detailed error type for taproot utilities
|
/// Detailed error type for taproot utilities.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub enum TaprootError {
|
pub enum TaprootError {
|
||||||
/// Proof size must be a multiple of 32
|
/// Proof size must be a multiple of 32.
|
||||||
InvalidMerkleBranchSize(usize),
|
InvalidMerkleBranchSize(usize),
|
||||||
/// Merkle Tree depth must not be more than 128
|
/// Merkle tree depth must not be more than 128.
|
||||||
InvalidMerkleTreeDepth(usize),
|
InvalidMerkleTreeDepth(usize),
|
||||||
/// The last bit of tapleaf version must be zero
|
/// The last bit of tapleaf version must be zero.
|
||||||
InvalidTaprootLeafVersion(u8),
|
InvalidTaprootLeafVersion(u8),
|
||||||
/// Invalid Control Block Size
|
/// Invalid control block size.
|
||||||
InvalidControlBlockSize(usize),
|
InvalidControlBlockSize(usize),
|
||||||
/// Invalid taproot internal key
|
/// Invalid taproot internal key.
|
||||||
InvalidInternalKey(secp256k1::Error),
|
InvalidInternalKey(secp256k1::Error),
|
||||||
/// Invalid parity for internal key
|
/// Invalid parity for internal key.
|
||||||
InvalidParity(secp256k1::InvalidParityValue),
|
InvalidParity(secp256k1::InvalidParityValue),
|
||||||
/// Empty TapTree
|
/// Empty tap tree.
|
||||||
EmptyTree,
|
EmptyTree,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue