Merge rust-bitcoin/rust-bitcoin#2916: Capitalize proper nouns
e8a30bfca7
taproot: Lowercase error messages (Jamil Lambert, PhD)717da4bf69
Capitalize Huffman (Jamil Lambert, PhD)175f69abeb
Capitalize Merkle (Jamil Lambert, PhD)be5b93ea4f
Do not capitalize tree (Jamil Lambert, PhD)b48ca050f9
Remove tap tree (Jamil Lambert, PhD)c8e6c13608
Capitalize Taproot (Jamil Lambert, PhD) Pull request description: Taproot, Merkle and Huffman are proper nouns and should be capitalized in strings and docs. These have been capitalized everywhere. All cases of `taproot`/`taptree`/`tap tree` in docs and strings have been changed to be `Taproot tree` or ```[`TapTree`]``` as appropriate. All cases of `tree` have been changed to lower cases, except where it is in title case. Error messages in `Taproot` have been changed to start with a lowercase character, except when it is a proper noun, and not end with a period. Close: #2913 ACKs for top commit: tcharding: ACKe8a30bfca7
apoelstra: ACKe8a30bfca7
Tree-SHA512: 7d06b717072f7894093df8501752374637fc6673bd7b6f1b95297ab076725eb0d7f48caa45c321fd13a45d0e4387ab9eeb398261f7988d3c9f90cfa75aee17ca
This commit is contained in:
commit
a302656767
|
@ -27,7 +27,7 @@ smaller crates AKA crate smashing.
|
|||
- Use network when calculating difficulty [#2168](https://github.com/rust-bitcoin/rust-bitcoin/pull/2168)
|
||||
- Fix `InputWeightPrediction::P2WPKH_MAX` constant DER sig length [#2213](https://github.com/rust-bitcoin/rust-bitcoin/pull/2213)
|
||||
- Fix CJDNS marker byte check [#2546](https://github.com/rust-bitcoin/rust-bitcoin/pull/2546)
|
||||
- Add resource limit check during deserialization of merkle block [#2607](https://github.com/rust-bitcoin/rust-bitcoin/pull/2607)
|
||||
- Add resource limit check during deserialization of Merkle block [#2607](https://github.com/rust-bitcoin/rust-bitcoin/pull/2607)
|
||||
|
||||
## Changes to and involving the `Network` type
|
||||
|
||||
|
@ -58,14 +58,14 @@ In particular consider having some type that implements `AsRef<Params>`, we have
|
|||
- Add `Weight::from_vb_weight function` function (added in [#2206](https://github.com/rust-bitcoin/rust-bitcoin/pull/2206),
|
||||
renamed in [#2228](https://github.com/rust-bitcoin/rust-bitcoin/pull/2228)
|
||||
- Implement `LowerHex` and `UpperHex` for `CompactTarget` [#2221](https://github.com/rust-bitcoin/rust-bitcoin/pull/2221)
|
||||
- Add conversions from TXIDs to merkle nodes [#2227](https://github.com/rust-bitcoin/rust-bitcoin/pull/2227)
|
||||
- Add conversions from TXIDs to Merkle nodes [#2227](https://github.com/rust-bitcoin/rust-bitcoin/pull/2227)
|
||||
- Add `transaction::effective_value()` function [#2230](https://github.com/rust-bitcoin/rust-bitcoin/pull/2230)
|
||||
- Improve `LockTime`s and related types:
|
||||
- Improve relative locktime API [#2549](https://github.com/rust-bitcoin/rust-bitcoin/pull/2549)
|
||||
- Implement `ordered::ArbitraryOrd` for absolute and relative locktimes, introducing the "ordered" feature:
|
||||
- [#2581](https://github.com/rust-bitcoin/rust-bitcoin/pull/2581)
|
||||
- [#2248](https://github.com/rust-bitcoin/rust-bitcoin/pull/2248)
|
||||
- Add and use custom `ArrayVec`
|
||||
- Add and use custom `ArrayVec`
|
||||
- [#2287](https://github.com/rust-bitcoin/rust-bitcoin/pull/2287)
|
||||
- [#2286](https://github.com/rust-bitcoin/rust-bitcoin/pull/2286)
|
||||
- [#2310](https://github.com/rust-bitcoin/rust-bitcoin/pull/2310)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! Example of taproot PSBT workflow
|
||||
//! Example of Taproot PSBT workflow
|
||||
|
||||
// We use the alias `alias bt='bitcoin-cli -regtest'` for brevity.
|
||||
|
||||
|
@ -192,7 +192,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
|
||||
// At some point we may want to extend the locktime further into the future for the beneficiary.
|
||||
// We can do this by "refreshing" the inheritance transaction as the benefactor. This effectively
|
||||
// spends the inheritance transaction via the key path of the taproot output, and is not encumbered
|
||||
// spends the inheritance transaction via the key path of the Taproot output, and is not encumbered
|
||||
// by the timelock so we can spend it immediately. We set up a new output similar to the first with
|
||||
// a locktime that is 'locktime_delta' blocks greater.
|
||||
let (tx, _) = benefactor.refresh_tx(1000)?;
|
||||
|
@ -294,7 +294,7 @@ fn generate_bip86_key_spend_tx(
|
|||
let (_, (_, derivation_path)) = input
|
||||
.tap_key_origins
|
||||
.get(&input.tap_internal_key.ok_or("Internal key missing in PSBT")?)
|
||||
.ok_or("Missing taproot key origin")?;
|
||||
.ok_or("Missing Taproot key origin")?;
|
||||
|
||||
let secret_key = master_xpriv.derive_priv(secp, &derivation_path).to_priv().inner;
|
||||
sign_psbt_taproot(
|
||||
|
@ -395,7 +395,7 @@ impl BenefactorWallet {
|
|||
let beneficiary_key =
|
||||
self.beneficiary_xpub.derive_pub(&self.secp, &derivation_path)?.to_x_only_pub();
|
||||
|
||||
// Build up the leaf script and combine with internal key into a taproot commitment
|
||||
// Build up the leaf script and combine with internal key into a Taproot commitment
|
||||
let script = Self::time_lock_script(lock_time, beneficiary_key);
|
||||
let leaf_hash = script.tapscript_leaf_hash();
|
||||
|
||||
|
@ -486,7 +486,7 @@ impl BenefactorWallet {
|
|||
let beneficiary_key =
|
||||
self.beneficiary_xpub.derive_pub(&self.secp, &new_derivation_path)?.to_x_only_pub();
|
||||
|
||||
// Build up the leaf script and combine with internal key into a taproot commitment
|
||||
// Build up the leaf script and combine with internal key into a Taproot commitment
|
||||
let lock_time = absolute::LockTime::from_height(
|
||||
psbt.unsigned_tx.lock_time.to_consensus_u32() + lock_time_delta,
|
||||
)
|
||||
|
@ -528,7 +528,7 @@ impl BenefactorWallet {
|
|||
let (_, (_, derivation_path)) = input
|
||||
.tap_key_origins
|
||||
.get(&input.tap_internal_key.ok_or("Internal key missing in PSBT")?)
|
||||
.ok_or("Missing taproot key origin")?;
|
||||
.ok_or("Missing Taproot key origin")?;
|
||||
let secret_key =
|
||||
self.master_xpriv.derive_priv(&self.secp, &derivation_path).to_priv().inner;
|
||||
sign_psbt_taproot(
|
||||
|
|
|
@ -465,7 +465,7 @@ impl Address {
|
|||
Ok(Address::p2sh_from_hash(script_hash, network))
|
||||
}
|
||||
|
||||
/// Creates a pay to taproot address from an untweaked key.
|
||||
/// Creates a pay to Taproot address from an untweaked key.
|
||||
pub fn p2tr<C: Verification>(
|
||||
secp: &Secp256k1<C>,
|
||||
internal_key: UntweakedPublicKey,
|
||||
|
@ -476,7 +476,7 @@ impl Address {
|
|||
Address::from_witness_program(program, hrp)
|
||||
}
|
||||
|
||||
/// Creates a pay to taproot address from a pre-tweaked output key.
|
||||
/// Creates a pay to Taproot address from a pre-tweaked output key.
|
||||
pub fn p2tr_tweaked(output_key: TweakedPublicKey, hrp: impl Into<KnownHrp>) -> Address {
|
||||
let program = WitnessProgram::p2tr_tweaked(output_key);
|
||||
Address::from_witness_program(program, hrp)
|
||||
|
@ -642,7 +642,7 @@ impl Address {
|
|||
///
|
||||
/// This is determined by directly comparing the address payload with either the
|
||||
/// hash of the given public key or the segwit redeem hash generated from the
|
||||
/// given key. For taproot addresses, the supplied key is assumed to be tweaked
|
||||
/// given key. For Taproot addresses, the supplied key is assumed to be tweaked
|
||||
pub fn is_related_to_pubkey(&self, pubkey: PublicKey) -> bool {
|
||||
let pubkey_hash = pubkey.pubkey_hash();
|
||||
let payload = self.payload_as_bytes();
|
||||
|
|
|
@ -39,9 +39,9 @@ impl BlockHash {
|
|||
/// Bitcoin block header.
|
||||
///
|
||||
/// Contains all the block's information except the actual transactions, but
|
||||
/// including a root of a [merkle tree] committing to all transactions in the block.
|
||||
/// including a root of a [Merkle tree] committing to all transactions in the block.
|
||||
///
|
||||
/// [merkle tree]: https://en.wikipedia.org/wiki/Merkle_tree
|
||||
/// [Merkle tree]: https://en.wikipedia.org/wiki/Merkle_tree
|
||||
///
|
||||
/// ### Bitcoin Core References
|
||||
///
|
||||
|
@ -54,7 +54,7 @@ pub struct Header {
|
|||
pub version: Version,
|
||||
/// Reference to the previous block in the chain.
|
||||
pub prev_blockhash: BlockHash,
|
||||
/// The root hash of the merkle tree of transactions in the block.
|
||||
/// The root hash of the Merkle tree of transactions in the block.
|
||||
pub merkle_root: TxMerkleNode,
|
||||
/// The timestamp of the block, as claimed by the miner.
|
||||
pub time: u32,
|
||||
|
@ -236,7 +236,7 @@ impl Block {
|
|||
/// Returns the block hash.
|
||||
pub fn block_hash(&self) -> BlockHash { self.header.block_hash() }
|
||||
|
||||
/// Checks if merkle root of header matches merkle root of the transaction list.
|
||||
/// Checks if Merkle root of header matches Merkle root of the transaction list.
|
||||
pub fn check_merkle_root(&self) -> bool {
|
||||
match self.compute_merkle_root() {
|
||||
Some(merkle_root) => self.header.merkle_root == merkle_root,
|
||||
|
@ -284,7 +284,7 @@ impl Block {
|
|||
false
|
||||
}
|
||||
|
||||
/// Computes the transaction merkle root.
|
||||
/// Computes the transaction Merkle root.
|
||||
pub fn compute_merkle_root(&self) -> Option<TxMerkleNode> {
|
||||
let hashes = self.txdata.iter().map(|obj| obj.compute_txid());
|
||||
TxMerkleNode::calculate_root(hashes)
|
||||
|
@ -301,7 +301,7 @@ impl Block {
|
|||
WitnessCommitment(sha256d::Hash::from_engine(encoder))
|
||||
}
|
||||
|
||||
/// Computes the merkle root of transactions hashed for witness.
|
||||
/// Computes the Merkle root of transactions hashed for witness.
|
||||
pub fn witness_root(&self) -> Option<WitnessMerkleNode> {
|
||||
let hashes = self.txdata.iter().enumerate().map(|(i, t)| {
|
||||
if i == 0 {
|
||||
|
|
|
@ -468,9 +468,9 @@ impl Script {
|
|||
/// Bitcoin Core uses accurate counting for sigops contained within redeemScripts (P2SH)
|
||||
/// and witnessScripts (P2WSH) only. It uses legacy for sigops in scriptSigs and scriptPubkeys.
|
||||
///
|
||||
/// (Note: taproot scripts don't count toward the sigop count of the block,
|
||||
/// (Note: Taproot scripts don't count toward the sigop count of the block,
|
||||
/// nor do they have CHECKMULTISIG operations. This function does not count OP_CHECKSIGADD,
|
||||
/// so do not use this to try and estimate if a taproot script goes over the sigop budget.)
|
||||
/// so do not use this to try and estimate if a Taproot script goes over the sigop budget.)
|
||||
pub fn count_sigops(&self) -> usize { self.count_sigops_internal(true) }
|
||||
|
||||
/// Counts the sigops for this Script using legacy counting.
|
||||
|
@ -482,9 +482,9 @@ impl Script {
|
|||
/// Bitcoin Core uses legacy counting for sigops contained within scriptSigs and
|
||||
/// scriptPubkeys. It uses accurate for redeemScripts (P2SH) and witnessScripts (P2WSH).
|
||||
///
|
||||
/// (Note: taproot scripts don't count toward the sigop count of the block,
|
||||
/// (Note: Taproot scripts don't count toward the sigop count of the block,
|
||||
/// nor do they have CHECKMULTISIG operations. This function does not count OP_CHECKSIGADD,
|
||||
/// so do not use this to try and estimate if a taproot script goes over the sigop budget.)
|
||||
/// so do not use this to try and estimate if a Taproot script goes over the sigop budget.)
|
||||
pub fn count_sigops_legacy(&self) -> usize { self.count_sigops_internal(false) }
|
||||
|
||||
fn count_sigops_internal(&self, accurate: bool) -> usize {
|
||||
|
|
|
@ -113,7 +113,7 @@ impl ScriptBuf {
|
|||
}
|
||||
|
||||
/// Generates P2TR for script spending path using an internal public key and some optional
|
||||
/// script tree merkle root.
|
||||
/// script tree Merkle root.
|
||||
pub fn new_p2tr<C: Verification>(
|
||||
secp: &Secp256k1<C>,
|
||||
internal_key: UntweakedPublicKey,
|
||||
|
|
|
@ -65,7 +65,7 @@ impl WitnessProgram {
|
|||
WitnessProgram { version: WitnessVersion::V0, program: ArrayVec::from_slice(&program) }
|
||||
}
|
||||
|
||||
/// Creates a [`WitnessProgram`] from a 32 byte serialize taproot xonly pubkey.
|
||||
/// Creates a [`WitnessProgram`] from a 32 byte serialize Taproot xonly pubkey.
|
||||
fn new_p2tr(program: [u8; 32]) -> Self {
|
||||
WitnessProgram { version: WitnessVersion::V1, program: ArrayVec::from_slice(&program) }
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ impl WitnessProgram {
|
|||
WitnessProgram::new_p2wsh(hash.to_byte_array())
|
||||
}
|
||||
|
||||
/// Creates a pay to taproot address from an untweaked key.
|
||||
/// Creates a pay to Taproot address from an untweaked key.
|
||||
pub fn p2tr<C: Verification>(
|
||||
secp: &Secp256k1<C>,
|
||||
internal_key: UntweakedPublicKey,
|
||||
|
@ -97,7 +97,7 @@ impl WitnessProgram {
|
|||
WitnessProgram::new_p2tr(pubkey)
|
||||
}
|
||||
|
||||
/// Creates a pay to taproot address from a pre-tweaked output key.
|
||||
/// Creates a pay to Taproot address from a pre-tweaked output key.
|
||||
pub fn p2tr_tweaked(output_key: TweakedPublicKey) -> Self {
|
||||
let pubkey = output_key.to_inner().serialize();
|
||||
WitnessProgram::new_p2tr(pubkey)
|
||||
|
|
|
@ -920,9 +920,9 @@ impl Transaction {
|
|||
|
||||
/// Counts the total number of sigops.
|
||||
///
|
||||
/// This value is for pre-taproot transactions only.
|
||||
/// This value is for pre-Taproot transactions only.
|
||||
///
|
||||
/// > In taproot, a different mechanism is used. Instead of having a global per-block limit,
|
||||
/// > In Taproot, a different mechanism is used. Instead of having a global per-block limit,
|
||||
/// > there is a per-transaction-input limit, proportional to the size of that input.
|
||||
/// > ref: <https://bitcoin.stackexchange.com/questions/117356/what-is-sigop-signature-operation#117359>
|
||||
///
|
||||
|
@ -983,7 +983,7 @@ impl Transaction {
|
|||
count
|
||||
}
|
||||
|
||||
/// Includes wrapped segwit (returns 0 for taproot spends).
|
||||
/// Includes wrapped segwit (returns 0 for Taproot spends).
|
||||
fn count_witness_sigops<S>(&self, spent: &mut S) -> usize
|
||||
where
|
||||
S: FnMut(&OutPoint) -> Option<TxOut>,
|
||||
|
@ -1523,14 +1523,14 @@ impl InputWeightPrediction {
|
|||
/// [`InputWeightPrediction::new`].
|
||||
pub const P2PKH_UNCOMPRESSED_MAX: Self = InputWeightPrediction::from_slice(139, &[]);
|
||||
|
||||
/// Input weight prediction corresponding to spending of taproot output using the key and
|
||||
/// Input weight prediction corresponding to spending of Taproot output using the key and
|
||||
/// default sighash.
|
||||
///
|
||||
/// If the input in your transaction uses Taproot key spend you can use this instead of
|
||||
/// [`InputWeightPrediction::new`].
|
||||
pub const P2TR_KEY_DEFAULT_SIGHASH: Self = InputWeightPrediction::from_slice(0, &[64]);
|
||||
|
||||
/// Input weight prediction corresponding to spending of taproot output using the key and
|
||||
/// Input weight prediction corresponding to spending of Taproot output using the key and
|
||||
/// **non**-default sighash.
|
||||
///
|
||||
/// If the input in your transaction uses Taproot key spend you can use this instead of
|
||||
|
|
|
@ -738,7 +738,7 @@ pub trait TapTweak {
|
|||
/// Tweaked key type.
|
||||
type TweakedKey;
|
||||
|
||||
/// Tweaks an untweaked key with corresponding public key value and optional script tree merkle
|
||||
/// Tweaks an untweaked key with corresponding public key value and optional script tree Merkle
|
||||
/// root. For the [`Keypair`] type this also tweaks the private key in the pair.
|
||||
///
|
||||
/// This is done by using the equation Q = P + H(P|c)G, where
|
||||
|
@ -769,7 +769,7 @@ impl TapTweak for UntweakedPublicKey {
|
|||
type TweakedKey = TweakedPublicKey;
|
||||
|
||||
/// Tweaks an untweaked public key with corresponding public key value and optional script tree
|
||||
/// merkle root.
|
||||
/// Merkle root.
|
||||
///
|
||||
/// This is done by using the equation Q = P + H(P|c)G, where
|
||||
/// * Q is the tweaked public key
|
||||
|
|
|
@ -72,13 +72,13 @@ sha256t_hash_newtype! {
|
|||
|
||||
/// Taproot-tagged hash with tag \"TapSighash\".
|
||||
///
|
||||
/// This hash type is used for computing taproot signature hash."
|
||||
/// This hash type is used for computing Taproot signature hash."
|
||||
pub struct TapSighash(_);
|
||||
}
|
||||
|
||||
impl_message_from_hash!(TapSighash);
|
||||
|
||||
/// Efficiently calculates signature hash message for legacy, segwit and taproot inputs.
|
||||
/// Efficiently calculates signature hash message for legacy, segwit and Taproot inputs.
|
||||
#[derive(Debug)]
|
||||
pub struct SighashCache<T: Borrow<Transaction>> {
|
||||
/// Access to transaction required for transaction introspection. Moreover, type
|
||||
|
@ -86,17 +86,17 @@ pub struct SighashCache<T: Borrow<Transaction>> {
|
|||
/// the latter in particular is necessary for [`SighashCache::witness_mut`].
|
||||
tx: T,
|
||||
|
||||
/// Common cache for taproot and segwit inputs, `None` for legacy inputs.
|
||||
/// Common cache for Taproot and segwit inputs, `None` for legacy inputs.
|
||||
common_cache: Option<CommonCache>,
|
||||
|
||||
/// Cache for segwit v0 inputs (the result of another round of sha256 on `common_cache`).
|
||||
segwit_cache: Option<SegwitCache>,
|
||||
|
||||
/// Cache for taproot v1 inputs.
|
||||
/// Cache for Taproot v1 inputs.
|
||||
taproot_cache: Option<TaprootCache>,
|
||||
}
|
||||
|
||||
/// Common values cached between segwit and taproot inputs.
|
||||
/// Common values cached between segwit and Taproot inputs.
|
||||
#[derive(Debug)]
|
||||
struct CommonCache {
|
||||
prevouts: sha256::Hash,
|
||||
|
@ -115,7 +115,7 @@ struct SegwitCache {
|
|||
outputs: sha256d::Hash,
|
||||
}
|
||||
|
||||
/// Values cached for taproot inputs.
|
||||
/// Values cached for Taproot inputs.
|
||||
#[derive(Debug)]
|
||||
struct TaprootCache {
|
||||
amounts: sha256::Hash,
|
||||
|
@ -1166,7 +1166,7 @@ impl<'a> Encodable for Annex<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Error computing a taproot sighash.
|
||||
/// Error computing a Taproot sighash.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
pub enum TaprootError {
|
||||
|
@ -1196,7 +1196,7 @@ impl fmt::Display for TaprootError {
|
|||
PrevoutsSize(ref e) => write_err!(f, "prevouts size"; e),
|
||||
PrevoutsIndex(ref e) => write_err!(f, "prevouts index"; e),
|
||||
PrevoutsKind(ref e) => write_err!(f, "prevouts kind"; e),
|
||||
InvalidSighashType(hash_ty) => write!(f, "invalid taproot sighash type : {} ", hash_ty),
|
||||
InvalidSighashType(hash_ty) => write!(f, "invalid Taproot sighash type : {} ", hash_ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
//! Bitcoin taproot keys.
|
||||
//! Bitcoin Taproot keys.
|
||||
//!
|
||||
//! This module provides taproot keys used in Bitcoin (including reexporting secp256k1 keys).
|
||||
//! This module provides Taproot keys used in Bitcoin (including reexporting secp256k1 keys).
|
||||
|
||||
use core::fmt;
|
||||
|
||||
|
@ -13,7 +13,7 @@ use crate::prelude::Vec;
|
|||
use crate::sighash::{InvalidSighashTypeError, TapSighashType};
|
||||
use crate::taproot::serialized_signature::{self, SerializedSignature};
|
||||
|
||||
/// A BIP340-341 serialized taproot signature with the corresponding hash type.
|
||||
/// A BIP340-341 serialized Taproot signature with the corresponding hash type.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
|
||||
|
@ -96,7 +96,7 @@ pub enum SigFromSliceError {
|
|||
SighashType(InvalidSighashTypeError),
|
||||
/// A secp256k1 error.
|
||||
Secp256k1(secp256k1::Error),
|
||||
/// Invalid taproot signature size
|
||||
/// Invalid Taproot signature size
|
||||
InvalidSignatureSize(usize),
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ impl fmt::Display for SigFromSliceError {
|
|||
match *self {
|
||||
SighashType(ref e) => write_err!(f, "sighash"; e),
|
||||
Secp256k1(ref e) => write_err!(f, "secp256k1"; e),
|
||||
InvalidSignatureSize(sz) => write!(f, "invalid taproot signature size: {}", sz),
|
||||
InvalidSignatureSize(sz) => write!(f, "invalid Taproot signature size: {}", sz),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ use crate::prelude::Vec;
|
|||
use crate::transaction::{Transaction, Txid};
|
||||
use crate::Weight;
|
||||
|
||||
/// Data structure that represents a block header paired to a partial merkle tree.
|
||||
/// Data structure that represents a block header paired to a partial Merkle tree.
|
||||
///
|
||||
/// NOTE: This assumes that the given Block has *at least* 1 transaction. If the Block has 0 txs,
|
||||
/// it will hit an assertion.
|
||||
|
@ -29,7 +29,7 @@ use crate::Weight;
|
|||
pub struct MerkleBlock {
|
||||
/// The block header
|
||||
pub header: block::Header,
|
||||
/// Transactions making up a partial merkle tree
|
||||
/// Transactions making up a partial Merkle tree
|
||||
pub txn: PartialMerkleTree,
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ impl MerkleBlock {
|
|||
/// Create a MerkleBlock from a block, that contains proofs for specific txids.
|
||||
///
|
||||
/// The `block` is a full block containing the header and transactions and `match_txids` is a
|
||||
/// function that returns true for the ids that should be included in the partial merkle tree.
|
||||
/// function that returns true for the ids that should be included in the partial Merkle tree.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -59,7 +59,7 @@ impl MerkleBlock {
|
|||
/// 5d35549d88ac00000000").unwrap();
|
||||
/// let block: Block = bitcoin::consensus::deserialize(&block_bytes).unwrap();
|
||||
///
|
||||
/// // Create a merkle block containing a single transaction
|
||||
/// // Create a Merkle block containing a single transaction
|
||||
/// let txid = "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2".parse::<Txid>().unwrap();
|
||||
/// let match_txids: Vec<Txid> = vec![txid].into_iter().collect();
|
||||
/// let mb = MerkleBlock::from_block_with_predicate(&block, |t| match_txids.contains(t));
|
||||
|
@ -81,7 +81,7 @@ impl MerkleBlock {
|
|||
/// Create a MerkleBlock from the block's header and txids, that contain proofs for specific txids.
|
||||
///
|
||||
/// The `header` is the block header, `block_txids` is the full list of txids included in the block and
|
||||
/// `match_txids` is a function that returns true for the ids that should be included in the partial merkle tree.
|
||||
/// `match_txids` is a function that returns true for the ids that should be included in the partial Merkle tree.
|
||||
pub fn from_header_txids_with_predicate<F>(
|
||||
header: &block::Header,
|
||||
block_txids: &[Txid],
|
||||
|
@ -96,7 +96,7 @@ impl MerkleBlock {
|
|||
MerkleBlock { header: *header, txn: pmt }
|
||||
}
|
||||
|
||||
/// Extract the matching txid's represented by this partial merkle tree
|
||||
/// Extract the matching txid's represented by this partial Merkle tree
|
||||
/// and their respective indices within the partial tree.
|
||||
/// returns Ok(()) on success, or error in case of failure
|
||||
pub fn extract_matches(
|
||||
|
@ -130,16 +130,16 @@ impl Decodable for MerkleBlock {
|
|||
}
|
||||
}
|
||||
|
||||
/// Data structure that represents a partial merkle tree.
|
||||
/// Data structure that represents a partial Merkle tree.
|
||||
///
|
||||
/// It represents a subset of the txid's of a known block, in a way that
|
||||
/// allows recovery of the list of txid's and the merkle root, in an
|
||||
/// allows recovery of the list of txid's and the Merkle root, in an
|
||||
/// authenticated way.
|
||||
///
|
||||
/// The encoding works as follows: we traverse the tree in depth-first order,
|
||||
/// storing a bit for each traversed node, signifying whether the node is the
|
||||
/// parent of at least one matched leaf txid (or a matched txid itself). In
|
||||
/// case we are at the leaf level, or this bit is 0, its merkle node hash is
|
||||
/// case we are at the leaf level, or this bit is 0, its Merkle node hash is
|
||||
/// stored, and its children are not explored further. Otherwise, no hash is
|
||||
/// stored, but we recurse into both (or the only) child branch. During
|
||||
/// decoding, the same depth-first traversal is performed, consuming bits and
|
||||
|
@ -178,13 +178,13 @@ impl PartialMerkleTree {
|
|||
/// Returns the total number of transactions in the block.
|
||||
pub fn num_transactions(&self) -> u32 { self.num_transactions }
|
||||
|
||||
/// Returns the node-is-parent-of-matched-txid bits of the partial merkle tree.
|
||||
/// Returns the node-is-parent-of-matched-txid bits of the partial Merkle tree.
|
||||
pub fn bits(&self) -> &Vec<bool> { &self.bits }
|
||||
|
||||
/// Returns the transaction ids and internal hashes of the partial merkle tree.
|
||||
/// Returns the transaction ids and internal hashes of the partial Merkle tree.
|
||||
pub fn hashes(&self) -> &Vec<TxMerkleNode> { &self.hashes }
|
||||
|
||||
/// Construct a partial merkle tree
|
||||
/// Construct a partial Merkle tree
|
||||
/// The `txids` are the transaction hashes of the block and the `matches` is the contains flags
|
||||
/// wherever a tx hash should be included in the proof.
|
||||
///
|
||||
|
@ -214,7 +214,7 @@ impl PartialMerkleTree {
|
|||
/// assert!(tree.extract_matches(&mut vec![], &mut vec![]).is_ok());
|
||||
/// ```
|
||||
pub fn from_txids(txids: &[Txid], matches: &[bool]) -> Self {
|
||||
// We can never have zero txs in a merkle block, we always need the coinbase tx
|
||||
// We can never have zero txs in a Merkle block, we always need the coinbase tx
|
||||
assert_ne!(txids.len(), 0);
|
||||
assert_eq!(txids.len(), matches.len());
|
||||
|
||||
|
@ -230,9 +230,9 @@ impl PartialMerkleTree {
|
|||
pmt
|
||||
}
|
||||
|
||||
/// Extract the matching txid's represented by this partial merkle tree
|
||||
/// Extract the matching txid's represented by this partial Merkle tree
|
||||
/// and their respective indices within the partial tree.
|
||||
/// returns the merkle root, or error in case of failure
|
||||
/// returns the Merkle root, or error in case of failure
|
||||
pub fn extract_matches(
|
||||
&self,
|
||||
matches: &mut Vec<Txid>,
|
||||
|
@ -286,13 +286,13 @@ impl PartialMerkleTree {
|
|||
}
|
||||
|
||||
/// Helper function to efficiently calculate the number of nodes at given height
|
||||
/// in the merkle tree
|
||||
/// in the Merkle tree
|
||||
#[inline]
|
||||
fn calc_tree_width(&self, height: u32) -> u32 {
|
||||
(self.num_transactions + (1 << height) - 1) >> height
|
||||
}
|
||||
|
||||
/// Calculate the hash of a node in the merkle tree (at leaf level: the txid's themselves)
|
||||
/// Calculate the hash of a node in the Merkle tree (at leaf level: the txid's themselves)
|
||||
fn calc_hash(&self, height: u32, pos: u32, txids: &[Txid]) -> TxMerkleNode {
|
||||
if height == 0 {
|
||||
// Hash at height 0 is the txid itself
|
||||
|
@ -443,13 +443,13 @@ impl Decodable for PartialMerkleTree {
|
|||
}
|
||||
}
|
||||
|
||||
/// An error when verifying the merkle block.
|
||||
/// An error when verifying the Merkle block.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
pub enum MerkleBlockError {
|
||||
/// Merkle root in the header doesn't match to the root calculated from partial merkle tree.
|
||||
/// Merkle root in the header doesn't match to the root calculated from partial Merkle tree.
|
||||
MerkleRootMismatch,
|
||||
/// Partial merkle tree contains no transactions.
|
||||
/// Partial Merkle tree contains no transactions.
|
||||
NoTransactions,
|
||||
/// There are too many transactions.
|
||||
TooManyTransactions,
|
||||
|
@ -477,8 +477,8 @@ impl fmt::Display for MerkleBlockError {
|
|||
use MerkleBlockError::*;
|
||||
|
||||
match *self {
|
||||
MerkleRootMismatch => write!(f, "merkle header root doesn't match to the root calculated from the partial merkle tree"),
|
||||
NoTransactions => write!(f, "partial merkle tree contains no transactions"),
|
||||
MerkleRootMismatch => write!(f, "Merkle header root doesn't match to the root calculated from the partial Merkle tree"),
|
||||
NoTransactions => write!(f, "partial Merkle tree contains no transactions"),
|
||||
TooManyTransactions => write!(f, "too many transactions"),
|
||||
TooManyHashes => write!(f, "proof contains more hashes than transactions"),
|
||||
NotEnoughBits => write!(f, "proof contains less bits than hashes"),
|
||||
|
@ -554,7 +554,7 @@ mod tests {
|
|||
.map(|i| format!("{:064x}", i).parse::<Txid>().unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Calculate the merkle root and height
|
||||
// Calculate the Merkle root and height
|
||||
let hashes = tx_ids.iter().copied();
|
||||
let merkle_root_1 = TxMerkleNode::calculate_root(hashes).expect("hashes is not empty");
|
||||
let mut height = 1;
|
||||
|
@ -582,7 +582,7 @@ mod tests {
|
|||
};
|
||||
}
|
||||
|
||||
// Build the partial merkle tree
|
||||
// Build the partial Merkle tree
|
||||
let pmt1 = PartialMerkleTree::from_txids(&tx_ids, &matches);
|
||||
let serialized = encode::serialize(&pmt1);
|
||||
|
||||
|
@ -594,14 +594,14 @@ mod tests {
|
|||
let pmt2: PartialMerkleTree =
|
||||
encode::deserialize(&serialized).expect("Could not deserialize own data");
|
||||
|
||||
// Extract merkle root and matched txids from copy
|
||||
// Extract Merkle root and matched txids from copy
|
||||
let mut match_txid2: Vec<Txid> = vec![];
|
||||
let mut indexes = vec![];
|
||||
let merkle_root_2 = pmt2
|
||||
.extract_matches(&mut match_txid2, &mut indexes)
|
||||
.expect("Could not extract matches");
|
||||
|
||||
// Check that it has the same merkle root as the original, and a valid one
|
||||
// Check that it has the same Merkle root as the original, and a valid one
|
||||
assert_eq!(merkle_root_1, merkle_root_2);
|
||||
assert_ne!(merkle_root_2, TxMerkleNode::from_byte_array([0; 32]));
|
||||
|
||||
|
@ -787,7 +787,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn regression_2606() {
|
||||
// Attempt to deserialize a partial merkle tree with a number of hashes that would
|
||||
// Attempt to deserialize a partial Merkle tree with a number of hashes that would
|
||||
// overflow the maximum allowed size.
|
||||
let bytes = hex!(
|
||||
"000006000000000000000004ee00000004c7f1ccb1000000ffff000000010000\
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
//! Bitcoin merkle tree functions.
|
||||
//! Bitcoin Merkle tree functions.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
|
|
|
@ -83,13 +83,13 @@ pub enum Error {
|
|||
InvalidXOnlyPublicKey,
|
||||
/// Parsing error indicating invalid ECDSA signatures
|
||||
InvalidEcdsaSignature(crate::crypto::ecdsa::Error),
|
||||
/// Parsing error indicating invalid taproot signatures
|
||||
/// Parsing error indicating invalid Taproot signatures
|
||||
InvalidTaprootSignature(crate::crypto::taproot::SigFromSliceError),
|
||||
/// Parsing error indicating invalid control block
|
||||
InvalidControlBlock,
|
||||
/// Parsing error indicating invalid leaf version
|
||||
InvalidLeafVersion,
|
||||
/// Parsing error indicating a taproot error
|
||||
/// Parsing error indicating a Taproot error
|
||||
Taproot(&'static str),
|
||||
/// Taproot tree deserilaization error
|
||||
TapTree(crate::taproot::IncompleteBuilderError),
|
||||
|
@ -147,11 +147,11 @@ impl fmt::Display for Error {
|
|||
InvalidSecp256k1PublicKey(ref e) => write_err!(f, "invalid secp256k1 public key"; e),
|
||||
InvalidXOnlyPublicKey => f.write_str("invalid xonly public key"),
|
||||
InvalidEcdsaSignature(ref e) => write_err!(f, "invalid ECDSA signature"; e),
|
||||
InvalidTaprootSignature(ref e) => write_err!(f, "invalid taproot signature"; e),
|
||||
InvalidTaprootSignature(ref e) => write_err!(f, "invalid Taproot signature"; e),
|
||||
InvalidControlBlock => f.write_str("invalid control block"),
|
||||
InvalidLeafVersion => f.write_str("invalid leaf version"),
|
||||
Taproot(s) => write!(f, "taproot error - {}", s),
|
||||
TapTree(ref e) => write_err!(f, "taproot tree error"; e),
|
||||
Taproot(s) => write!(f, "Taproot error - {}", s),
|
||||
TapTree(ref e) => write_err!(f, "Taproot tree error"; e),
|
||||
XPubKey(s) => write!(f, "xpub key error - {}", s),
|
||||
Version(s) => write!(f, "version error {}", s),
|
||||
PartialDataConsumption =>
|
||||
|
|
|
@ -78,7 +78,7 @@ pub struct Input {
|
|||
/// including P2SH embedded ones.
|
||||
pub witness_utxo: Option<TxOut>,
|
||||
/// A map from public keys to their corresponding signature as would be
|
||||
/// pushed to the stack from a scriptSig or witness for a non-taproot inputs.
|
||||
/// pushed to the stack from a scriptSig or witness for a non-Taproot inputs.
|
||||
pub partial_sigs: BTreeMap<PublicKey, ecdsa::Signature>,
|
||||
/// The sighash type to be used for this input. Signatures for this input
|
||||
/// must use the sighash type.
|
||||
|
@ -109,7 +109,7 @@ pub struct Input {
|
|||
/// HAS256 hash to preimage map.
|
||||
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))]
|
||||
pub hash256_preimages: BTreeMap<sha256d::Hash, Vec<u8>>,
|
||||
/// Serialized taproot signature with sighash type for key spend.
|
||||
/// Serialized Taproot signature with sighash type for key spend.
|
||||
pub tap_key_sig: Option<taproot::Signature>,
|
||||
/// Map of `<xonlypubkey>|<leafhash>` with signature.
|
||||
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))]
|
||||
|
@ -132,7 +132,7 @@ pub struct Input {
|
|||
pub unknown: BTreeMap<raw::Key, Vec<u8>>,
|
||||
}
|
||||
|
||||
/// A Signature hash type for the corresponding input. As of taproot upgrade, the signature hash
|
||||
/// A Signature hash type for the corresponding input. As of Taproot upgrade, the signature hash
|
||||
/// type can be either [`EcdsaSighashType`] or [`TapSighashType`] but it is not possible to know
|
||||
/// directly which signature hash type the user is dealing with. Therefore, the user is responsible
|
||||
/// for converting to/from [`PsbtSighashType`] from/to the desired signature hash type they need.
|
||||
|
@ -169,7 +169,7 @@ impl FromStr for PsbtSighashType {
|
|||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
// We accept strings of form: "SIGHASH_ALL" etc.
|
||||
//
|
||||
// NB: some of Taproot sighash types are non-standard for pre-taproot
|
||||
// NB: some of Taproot sighash types are non-standard for pre-Taproot
|
||||
// inputs. We also do not support SIGHASH_RESERVED in verbatim form
|
||||
// ("0xFF" string should be used instead).
|
||||
if let Ok(ty) = TapSighashType::from_str(s) {
|
||||
|
|
|
@ -545,7 +545,7 @@ impl Psbt {
|
|||
Ok((Message::from(sighash), hash_ty))
|
||||
}
|
||||
Tr => {
|
||||
// This PSBT signing API is WIP, taproot to come shortly.
|
||||
// This PSBT signing API is WIP, Taproot to come shortly.
|
||||
Err(SignError::Unsupported)
|
||||
}
|
||||
}
|
||||
|
@ -899,7 +899,7 @@ pub enum OutputType {
|
|||
ShWsh,
|
||||
/// A pay-to-script-hash output excluding wrapped segwit (P2SH).
|
||||
Sh,
|
||||
/// A taproot output (P2TR).
|
||||
/// A Taproot output (P2TR).
|
||||
Tr,
|
||||
}
|
||||
|
||||
|
@ -954,7 +954,7 @@ pub enum SignError {
|
|||
SegwitV0Sighash(transaction::InputsIndexError),
|
||||
/// Sighash computation error (p2wpkh input).
|
||||
P2wpkhSighash(sighash::P2wpkhError),
|
||||
/// Sighash computation error (taproot input).
|
||||
/// Sighash computation error (Taproot input).
|
||||
TaprootError(sighash::TaprootError),
|
||||
/// Unable to determine the output type.
|
||||
UnknownOutputType,
|
||||
|
@ -984,7 +984,7 @@ impl fmt::Display for SignError {
|
|||
NotWpkh => write!(f, "the scriptPubkey is not a P2WPKH script"),
|
||||
SegwitV0Sighash(ref e) => write_err!(f, "segwit v0 sighash"; e),
|
||||
P2wpkhSighash(ref e) => write_err!(f, "p2wpkh sighash"; e),
|
||||
TaprootError(ref e) => write_err!(f, "taproot sighash"; e),
|
||||
TaprootError(ref e) => write_err!(f, "Taproot sighash"; e),
|
||||
UnknownOutputType => write!(f, "unable to determine the output type"),
|
||||
KeyNotFound => write!(f, "unable to find key"),
|
||||
WrongSigningAlgorithm =>
|
||||
|
@ -1867,11 +1867,11 @@ mod tests {
|
|||
assert_eq!(err.to_string(), "invalid xonly public key");
|
||||
let err = hex_psbt("70736274ff010071020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02787c01000000000016001483a7e34bd99ff03a4962ef8a1a101bb295461ece606b042a010000001600147ac369df1b20e033d6116623957b0ac49f3c52e8000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757011342173bb3d36c074afb716fec6307a069a2e450b995f3c82785945ab8df0e24260dcd703b0cbf34de399184a9481ac2b3586db6601f026a77f7e4938481bc34751701aa000000").unwrap_err();
|
||||
#[cfg(feature = "std")]
|
||||
assert_eq!(err.to_string(), "invalid taproot signature");
|
||||
assert_eq!(err.to_string(), "invalid Taproot signature");
|
||||
#[cfg(not(feature = "std"))]
|
||||
assert_eq!(
|
||||
err.to_string(),
|
||||
"invalid taproot signature: invalid taproot signature size: 66"
|
||||
"invalid Taproot signature: invalid Taproot signature size: 66"
|
||||
);
|
||||
let err = hex_psbt("70736274ff010071020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02787c01000000000016001483a7e34bd99ff03a4962ef8a1a101bb295461ece606b042a010000001600147ac369df1b20e033d6116623957b0ac49f3c52e8000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757221602fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da75600008001000080000000800100000000000000000000").unwrap_err();
|
||||
assert_eq!(err.to_string(), "invalid xonly public key");
|
||||
|
@ -1889,19 +1889,19 @@ mod tests {
|
|||
);
|
||||
let err = hex_psbt("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b094289756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb01010000").unwrap_err();
|
||||
#[cfg(feature = "std")]
|
||||
assert_eq!(err.to_string(), "invalid taproot signature");
|
||||
assert_eq!(err.to_string(), "invalid Taproot signature");
|
||||
#[cfg(not(feature = "std"))]
|
||||
assert_eq!(
|
||||
err.to_string(),
|
||||
"invalid taproot signature: invalid taproot signature size: 66"
|
||||
"invalid Taproot signature: invalid Taproot signature size: 66"
|
||||
);
|
||||
let err = hex_psbt("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b093989756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb0000").unwrap_err();
|
||||
#[cfg(feature = "std")]
|
||||
assert_eq!(err.to_string(), "invalid taproot signature");
|
||||
assert_eq!(err.to_string(), "invalid Taproot signature");
|
||||
#[cfg(not(feature = "std"))]
|
||||
assert_eq!(
|
||||
err.to_string(),
|
||||
"invalid taproot signature: invalid taproot signature size: 57"
|
||||
"invalid Taproot signature: invalid Taproot signature size: 57"
|
||||
);
|
||||
let err = hex_psbt("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6926315c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac06f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f80023202cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2acc00000").unwrap_err();
|
||||
assert_eq!(err.to_string(), "invalid control block");
|
||||
|
|
|
@ -117,7 +117,7 @@ impl_psbt_hash_de_serialize!(TapNodeHash);
|
|||
impl_psbt_hash_de_serialize!(hash160::Hash);
|
||||
impl_psbt_hash_de_serialize!(sha256d::Hash);
|
||||
|
||||
// taproot
|
||||
// Taproot
|
||||
impl_psbt_de_serialize!(Vec<TapLeafHash>);
|
||||
|
||||
impl Serialize for ScriptBuf {
|
||||
|
@ -339,7 +339,7 @@ impl Serialize for TapTree {
|
|||
.script_leaves()
|
||||
.map(|l| {
|
||||
l.script().len() + VarInt::from(l.script().len()).size() // script version
|
||||
+ 1 // merkle branch
|
||||
+ 1 // Merkle branch
|
||||
+ 1 // leaf version
|
||||
})
|
||||
.sum::<usize>();
|
||||
|
|
|
@ -10,7 +10,7 @@ use super::{
|
|||
};
|
||||
use crate::prelude::{Borrow, BorrowMut, Box, Vec};
|
||||
|
||||
/// The merkle proof for inclusion of a tree in a taptree hash.
|
||||
/// The Merkle proof for inclusion of a tree in a Taproot tree hash.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
|
||||
|
@ -28,11 +28,11 @@ impl TaprootMerkleBranch {
|
|||
#[inline]
|
||||
pub fn as_slice(&self) -> &[TapNodeHash] { &self.0 }
|
||||
|
||||
/// Returns the number of nodes in this merkle proof.
|
||||
/// Returns the number of nodes in this Merkle proof.
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize { self.0.len() }
|
||||
|
||||
/// Checks if this merkle proof is empty.
|
||||
/// Checks if this Merkle proof is empty.
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool { self.0.is_empty() }
|
||||
|
||||
|
@ -63,7 +63,7 @@ impl TaprootMerkleBranch {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a merkle proof from list of hashes.
|
||||
/// Creates a Merkle proof from list of hashes.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
|
@ -121,7 +121,7 @@ macro_rules! impl_try_from {
|
|||
impl TryFrom<$from> for TaprootMerkleBranch {
|
||||
type Error = InvalidMerkleTreeDepthError;
|
||||
|
||||
/// Creates a merkle proof from list of hashes.
|
||||
/// Creates a Merkle proof from list of hashes.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
|
@ -223,7 +223,7 @@ impl BorrowMut<[TapNodeHash]> for TaprootMerkleBranch {
|
|||
fn borrow_mut(&mut self) -> &mut [TapNodeHash] { &mut self.0 }
|
||||
}
|
||||
|
||||
/// Iterator over node hashes within Taproot merkle branch.
|
||||
/// Iterator over node hashes within Taproot Merkle branch.
|
||||
///
|
||||
/// This is created by `into_iter` method on `TaprootMerkleBranch` (via `IntoIterator` trait).
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
//! Bitcoin Taproot.
|
||||
//!
|
||||
//! This module provides support for taproot tagged hashes.
|
||||
//! This module provides support for Taproot tagged hashes.
|
||||
|
||||
pub mod merkle_branch;
|
||||
pub mod serialized_signature;
|
||||
|
@ -41,7 +41,7 @@ sha256t_hash_newtype! {
|
|||
sha256t_hash_newtype! {
|
||||
pub struct TapBranchTag = hash_str("TapBranch");
|
||||
|
||||
/// Tagged hash used in taproot trees.
|
||||
/// Tagged hash used in Taproot trees.
|
||||
///
|
||||
/// See BIP-340 for tagging rules.
|
||||
pub struct TapNodeHash(_);
|
||||
|
@ -58,7 +58,7 @@ sha256t_hash_newtype! {
|
|||
|
||||
impl TapTweakHash {
|
||||
/// Creates a new BIP341 [`TapTweakHash`] from key and tweak. Produces `H_taptweak(P||R)` where
|
||||
/// `P` is the 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(
|
||||
internal_key: UntweakedPublicKey,
|
||||
merkle_root: Option<TapNodeHash>,
|
||||
|
@ -136,10 +136,10 @@ impl From<TapLeafHash> for TapNodeHash {
|
|||
fn from(leaf: TapLeafHash) -> TapNodeHash { TapNodeHash::from_byte_array(leaf.to_byte_array()) }
|
||||
}
|
||||
|
||||
/// 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
|
||||
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
|
||||
pub const TAPROOT_CONTROL_NODE_SIZE: usize = 32;
|
||||
/// Tapleaf mask for getting the leaf version from first byte of control block.
|
||||
|
@ -158,10 +158,10 @@ 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 alias for versioned tap script corresponding merkle proof
|
||||
// type alias for versioned tap script corresponding Merkle proof
|
||||
type ScriptMerkleProofMap = BTreeMap<(ScriptBuf, LeafVersion), BTreeSet<TaprootMerkleBranch>>;
|
||||
|
||||
/// Represents taproot spending information.
|
||||
/// Represents Taproot spending information.
|
||||
///
|
||||
/// Taproot output corresponds to a combination of a single public key condition (known as the
|
||||
/// internal key), and zero or more general conditions encoded in scripts organized in the form of a
|
||||
|
@ -176,7 +176,7 @@ type ScriptMerkleProofMap = BTreeMap<(ScriptBuf, LeafVersion), BTreeSet<TaprootM
|
|||
/// 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.
|
||||
/// 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).
|
||||
|
@ -184,7 +184,7 @@ type ScriptMerkleProofMap = BTreeMap<(ScriptBuf, LeafVersion), BTreeSet<TaprootM
|
|||
pub struct TaprootSpendInfo {
|
||||
/// The BIP341 internal key.
|
||||
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<TapNodeHash>,
|
||||
/// The sign final output pubkey as per BIP 341.
|
||||
output_key_parity: secp256k1::Parity,
|
||||
|
@ -212,7 +212,7 @@ impl TaprootSpendInfo {
|
|||
C: secp256k1::Verification,
|
||||
{
|
||||
let builder = TaprootBuilder::with_huffman_tree(script_weights)?;
|
||||
Ok(builder.finalize(secp, internal_key).expect("Huffman Tree is always complete"))
|
||||
Ok(builder.finalize(secp, internal_key).expect("Huffman tree is always complete"))
|
||||
}
|
||||
|
||||
/// Creates a new key spend with `internal_key` and `merkle_root`. Provide [`None`] for
|
||||
|
@ -220,11 +220,11 @@ impl TaprootSpendInfo {
|
|||
///
|
||||
/// *Note*: As per BIP341
|
||||
///
|
||||
/// When the merkle root is [`None`], the output key commits to an unspendable script path
|
||||
/// 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
|
||||
/// 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>(
|
||||
secp: &Secp256k1<C>,
|
||||
|
@ -250,7 +250,7 @@ impl TaprootSpendInfo {
|
|||
/// Returns the internal key for this [`TaprootSpendInfo`].
|
||||
pub fn internal_key(&self) -> UntweakedPublicKey { self.internal_key }
|
||||
|
||||
/// Returns the merkle root for this [`TaprootSpendInfo`].
|
||||
/// Returns the Merkle root for this [`TaprootSpendInfo`].
|
||||
pub fn merkle_root(&self) -> Option<TapNodeHash> { self.merkle_root }
|
||||
|
||||
/// Returns the output key (the key used in script pubkey) for this [`TaprootSpendInfo`].
|
||||
|
@ -264,14 +264,14 @@ impl TaprootSpendInfo {
|
|||
|
||||
/// Computes the [`TaprootSpendInfo`] from `internal_key` and `node`.
|
||||
///
|
||||
/// This is useful when you want to manually build a taproot tree without using
|
||||
/// This is useful when you want to manually build a Taproot tree without using
|
||||
/// [`TaprootBuilder`].
|
||||
pub fn from_node_info<C: secp256k1::Verification>(
|
||||
secp: &Secp256k1<C>,
|
||||
internal_key: UntweakedPublicKey,
|
||||
node: NodeInfo,
|
||||
) -> TaprootSpendInfo {
|
||||
// Create as if it is a key spend path with the given merkle root
|
||||
// Create as if it is a key spend path with the given Merkle root
|
||||
let root_hash = Some(node.hash);
|
||||
let mut info = TaprootSpendInfo::new_key_spend(secp, internal_key, root_hash);
|
||||
|
||||
|
@ -329,7 +329,7 @@ impl From<&TaprootSpendInfo> for TapTweakHash {
|
|||
fn from(spend_info: &TaprootSpendInfo) -> TapTweakHash { spend_info.tap_tweak() }
|
||||
}
|
||||
|
||||
/// Builder for building taproot iteratively. Users can specify tap leaf or omitted/hidden branches
|
||||
/// Builder for building Taproot iteratively. Users can specify tap leaf or omitted/hidden branches
|
||||
/// in a depth-first search (DFS) walk order to construct this tree.
|
||||
///
|
||||
/// See Wikipedia for more details on [DFS](https://en.wikipedia.org/wiki/Depth-first_search).
|
||||
|
@ -342,7 +342,7 @@ pub struct TaprootBuilder {
|
|||
// 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
|
||||
// During the construction of [`TapTree`], for every right branch taken to reach the position we're
|
||||
// currently working on, there will be a `(Some(_))` entry in branch corresponding to the left
|
||||
// branch at that level.
|
||||
//
|
||||
|
@ -386,7 +386,7 @@ impl TaprootBuilder {
|
|||
/// 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
|
||||
/// 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 as input an iterator of
|
||||
/// `tuple(u32, ScriptBuf)` where `u32` represents the satisfaction weights of the branch. For
|
||||
/// example, [(3, S1), (2, S2), (5, S3)] would construct a [`TapTree`] that has optimal
|
||||
|
@ -394,7 +394,7 @@ impl TaprootBuilder {
|
|||
///
|
||||
/// # 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.
|
||||
///
|
||||
/// # Edge Cases
|
||||
|
@ -422,14 +422,14 @@ impl TaprootBuilder {
|
|||
// 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".
|
||||
// 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_eq!(node_weights.len(), 1);
|
||||
let node = node_weights.pop().expect("huffman tree algorithm is broken").1;
|
||||
let node = node_weights.pop().expect("Huffman tree algorithm is broken").1;
|
||||
Ok(TaprootBuilder { branch: vec![Some(node)] })
|
||||
}
|
||||
|
||||
|
@ -533,7 +533,7 @@ impl TaprootBuilder {
|
|||
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")
|
||||
unreachable!("size checked above. Builder guarantees the last element is Some")
|
||||
},
|
||||
_ => Err(self),
|
||||
}
|
||||
|
@ -557,7 +557,7 @@ impl TaprootBuilder {
|
|||
|
||||
while self.branch.len() == depth as usize + 1 {
|
||||
let child = match self.branch.pop() {
|
||||
None => unreachable!("Len of branch checked to be >= 1"),
|
||||
None => unreachable!("length of branch checked to be >= 1"),
|
||||
Some(Some(child)) => child,
|
||||
// Needs an explicit push to add the None that we just popped.
|
||||
// Cannot use .last() because of borrow checker issues.
|
||||
|
@ -596,9 +596,9 @@ impl Default for TaprootBuilder {
|
|||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
pub enum IncompleteBuilderError {
|
||||
/// Indicates an attempt to construct a tap tree from a builder containing incomplete branches.
|
||||
/// Indicates an attempt to construct a Taproot tree from a builder containing incomplete branches.
|
||||
NotFinalized(TaprootBuilder),
|
||||
/// Indicates an attempt to construct a tap tree from a builder containing hidden parts.
|
||||
/// Indicates an attempt to construct a Taproot tree from a builder containing hidden parts.
|
||||
HiddenParts(TaprootBuilder),
|
||||
}
|
||||
|
||||
|
@ -621,9 +621,9 @@ impl core::fmt::Display for IncompleteBuilderError {
|
|||
|
||||
f.write_str(match self {
|
||||
NotFinalized(_) =>
|
||||
"an attempt to construct a tap tree from a builder containing incomplete branches.",
|
||||
"an attempt to construct a Taproot tree from a builder containing incomplete branches",
|
||||
HiddenParts(_) =>
|
||||
"an attempt to construct a tap tree from a builder containing hidden parts.",
|
||||
"an attempt to construct a Taproot tree from a builder containing hidden parts",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -644,7 +644,7 @@ impl std::error::Error for IncompleteBuilderError {
|
|||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
pub enum HiddenNodesError {
|
||||
/// Indicates an attempt to construct a tap tree from a builder containing hidden parts.
|
||||
/// Indicates an attempt to construct a Taproot tree from a builder containing hidden parts.
|
||||
HiddenParts(NodeInfo),
|
||||
}
|
||||
|
||||
|
@ -667,7 +667,7 @@ impl core::fmt::Display for HiddenNodesError {
|
|||
|
||||
f.write_str(match self {
|
||||
HiddenParts(_) =>
|
||||
"an attempt to construct a tap tree from a node_info containing hidden parts.",
|
||||
"an attempt to construct a Taproot tree from a node_info containing hidden parts",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -683,10 +683,10 @@ impl std::error::Error for HiddenNodesError {
|
|||
}
|
||||
}
|
||||
|
||||
/// Taproot Tree representing a complete binary tree without any hidden nodes.
|
||||
/// Taproot tree representing a complete binary tree without any hidden nodes.
|
||||
///
|
||||
/// This is in contrast to [`NodeInfo`], which allows hidden nodes.
|
||||
/// The implementations for Eq, PartialEq and Hash compare the merkle root of the tree
|
||||
/// The implementations for Eq, PartialEq and Hash compare the Merkle root of the tree
|
||||
//
|
||||
// This is a bug in BIP370 that does not specify how to share trees with hidden nodes,
|
||||
// for which we need a separate type.
|
||||
|
@ -709,7 +709,7 @@ impl TapTree {
|
|||
/// Gets the inner [`NodeInfo`] of this tree root.
|
||||
pub fn into_node_info(self) -> NodeInfo { self.0 }
|
||||
|
||||
/// Returns [`TapTreeIter<'_>`] iterator for a taproot script tree, operating in DFS order over
|
||||
/// Returns [`TapTreeIter<'_>`] iterator for a Taproot script tree, operating in DFS order over
|
||||
/// tree [`ScriptLeaf`]s.
|
||||
pub fn script_leaves(&self) -> ScriptLeaves { ScriptLeaves { leaf_iter: self.0.leaf_nodes() } }
|
||||
|
||||
|
@ -747,7 +747,7 @@ impl TryFrom<NodeInfo> for TapTree {
|
|||
}
|
||||
}
|
||||
|
||||
/// Iterator for a taproot script tree, operating in DFS order yielding [`ScriptLeaf`].
|
||||
/// Iterator for a Taproot script tree, operating in DFS order yielding [`ScriptLeaf`].
|
||||
///
|
||||
/// Returned by [`TapTree::script_leaves`]. [`TapTree`] does not allow hidden nodes,
|
||||
/// so this iterator is guaranteed to yield all known leaves.
|
||||
|
@ -774,7 +774,7 @@ impl<'tree> DoubleEndedIterator for ScriptLeaves<'tree> {
|
|||
ScriptLeaf::from_leaf_node(self.leaf_iter.next_back()?)
|
||||
}
|
||||
}
|
||||
/// Iterator for a taproot script tree, operating in DFS order yielding [`LeafNode`].
|
||||
/// Iterator for a Taproot script tree, operating in DFS order yielding [`LeafNode`].
|
||||
///
|
||||
/// Returned by [`NodeInfo::leaf_nodes`]. This can potentially yield hidden nodes.
|
||||
pub struct LeafNodes<'a> {
|
||||
|
@ -798,14 +798,14 @@ impl<'tree> DoubleEndedIterator for LeafNodes<'tree> {
|
|||
#[inline]
|
||||
fn next_back(&mut self) -> Option<Self::Item> { self.leaf_iter.next_back() }
|
||||
}
|
||||
/// Represents the node information in taproot tree. In contrast to [`TapTree`], this
|
||||
/// Represents the node information in Taproot tree. In contrast to [`TapTree`], this
|
||||
/// is allowed to have hidden leaves as children.
|
||||
///
|
||||
/// Helper type used in merkle tree construction allowing one to build sparse merkle trees. The node
|
||||
/// Helper type used in Merkle tree construction allowing one to build sparse Merkle trees. The node
|
||||
/// represents part of the tree that has information about all of its descendants.
|
||||
/// See how [`TaprootBuilder`] works for more details.
|
||||
///
|
||||
/// You can use [`TaprootSpendInfo::from_node_info`] to a get a [`TaprootSpendInfo`] from the merkle
|
||||
/// You can use [`TaprootSpendInfo::from_node_info`] to a get a [`TaprootSpendInfo`] from the Merkle
|
||||
/// root [`NodeInfo`].
|
||||
#[derive(Debug, Clone, PartialOrd, Ord)]
|
||||
pub struct NodeInfo {
|
||||
|
@ -921,18 +921,18 @@ impl<'de> serde::Deserialize<'de> for NodeInfo {
|
|||
while let Some(depth) = seq.next_element()? {
|
||||
let tap_leaf: TapLeaf = seq
|
||||
.next_element()?
|
||||
.ok_or_else(|| serde::de::Error::custom("Missing tap_leaf"))?;
|
||||
.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))
|
||||
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: {}",
|
||||
"hidden node insertion error: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
|
@ -940,7 +940,7 @@ impl<'de> serde::Deserialize<'de> for NodeInfo {
|
|||
}
|
||||
}
|
||||
NodeInfo::try_from(builder).map_err(|e| {
|
||||
serde::de::Error::custom(format!("Incomplete taproot tree: {}", e))
|
||||
serde::de::Error::custom(format!("incomplete Taproot tree: {}", e))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -949,7 +949,7 @@ impl<'de> serde::Deserialize<'de> for NodeInfo {
|
|||
}
|
||||
}
|
||||
|
||||
/// Leaf node in a taproot tree. Can be either hidden or known.
|
||||
/// Leaf node in a Taproot tree. Can be either hidden or known.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
|
||||
|
@ -980,27 +980,27 @@ impl TapLeaf {
|
|||
}
|
||||
}
|
||||
|
||||
/// Store information about taproot leaf node.
|
||||
/// Store information about Taproot leaf node.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct LeafNode {
|
||||
/// The [`TapLeaf`]
|
||||
leaf: TapLeaf,
|
||||
/// The merkle proof (hashing partners) to get this node.
|
||||
/// The Merkle proof (hashing partners) to get this node.
|
||||
merkle_branch: TaprootMerkleBranch,
|
||||
}
|
||||
|
||||
impl LeafNode {
|
||||
/// Creates an new [`ScriptLeaf`] from `script` and `ver` and no merkle branch.
|
||||
/// Creates an new [`ScriptLeaf`] from `script` and `ver` and no Merkle branch.
|
||||
pub fn new_script(script: ScriptBuf, ver: LeafVersion) -> Self {
|
||||
Self { leaf: TapLeaf::Script(script, ver), merkle_branch: Default::default() }
|
||||
}
|
||||
|
||||
/// Creates an new [`ScriptLeaf`] from `hash` and no merkle branch.
|
||||
/// Creates an new [`ScriptLeaf`] from `hash` and no Merkle branch.
|
||||
pub fn new_hidden(hash: TapNodeHash) -> Self {
|
||||
Self { leaf: TapLeaf::Hidden(hash), merkle_branch: Default::default() }
|
||||
}
|
||||
|
||||
/// Returns the depth of this script leaf in the tap tree.
|
||||
/// Returns the depth of this script leaf in the Taproot tree.
|
||||
#[inline]
|
||||
pub fn depth(&self) -> u8 {
|
||||
// Depth is guarded by TAPROOT_CONTROL_MAX_NODE_COUNT.
|
||||
|
@ -1009,7 +1009,7 @@ impl LeafNode {
|
|||
|
||||
/// Computes a leaf hash for this [`ScriptLeaf`] if the leaf is known.
|
||||
///
|
||||
/// This [`TapLeafHash`] is useful while signing taproot script spends.
|
||||
/// This [`TapLeafHash`] is useful while signing Taproot script spends.
|
||||
///
|
||||
/// See [`LeafNode::node_hash`] for computing the [`TapNodeHash`] which returns the hidden node
|
||||
/// hash if the node is hidden.
|
||||
|
@ -1039,7 +1039,7 @@ impl LeafNode {
|
|||
#[inline]
|
||||
pub fn leaf_version(&self) -> Option<LeafVersion> { self.leaf.as_script().map(|x| x.1) }
|
||||
|
||||
/// Returns reference to the merkle proof (hashing partners) to get this
|
||||
/// Returns reference to the Merkle proof (hashing partners) to get this
|
||||
/// node in form of [`TaprootMerkleBranch`].
|
||||
#[inline]
|
||||
pub fn merkle_branch(&self) -> &TaprootMerkleBranch { &self.merkle_branch }
|
||||
|
@ -1049,7 +1049,7 @@ impl LeafNode {
|
|||
pub fn leaf(&self) -> &TapLeaf { &self.leaf }
|
||||
}
|
||||
|
||||
/// Script leaf node in a taproot tree along with the merkle proof to get this node.
|
||||
/// Script leaf node in a Taproot tree along with the Merkle proof to get this node.
|
||||
/// Returned by [`TapTree::script_leaves`]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct ScriptLeaf<'leaf> {
|
||||
|
@ -1057,7 +1057,7 @@ pub struct ScriptLeaf<'leaf> {
|
|||
version: LeafVersion,
|
||||
/// The script.
|
||||
script: &'leaf Script,
|
||||
/// The merkle proof (hashing partners) to get this node.
|
||||
/// The Merkle proof (hashing partners) to get this node.
|
||||
merkle_branch: &'leaf TaprootMerkleBranch,
|
||||
}
|
||||
|
||||
|
@ -1068,7 +1068,7 @@ impl<'leaf> ScriptLeaf<'leaf> {
|
|||
/// Obtains a reference to the script inside the leaf.
|
||||
pub fn script(&self) -> &Script { self.script }
|
||||
|
||||
/// Obtains a reference to the merkle proof of the leaf.
|
||||
/// Obtains a reference to the Merkle proof of the leaf.
|
||||
pub fn merkle_branch(&self) -> &TaprootMerkleBranch { self.merkle_branch }
|
||||
|
||||
/// Obtains a script leaf from the leaf node if the leaf is not hidden.
|
||||
|
@ -1089,15 +1089,15 @@ pub struct ControlBlock {
|
|||
pub output_key_parity: secp256k1::Parity,
|
||||
/// The internal key.
|
||||
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,
|
||||
}
|
||||
|
||||
impl ControlBlock {
|
||||
/// Decodes bytes representing a `ControlBlock`.
|
||||
///
|
||||
/// This is an extra witness element that provides the proof that taproot script pubkey is
|
||||
/// correctly computed with some specified leaf hash. This is the last element in taproot
|
||||
/// This is an extra witness element that provides the proof that Taproot script pubkey is
|
||||
/// correctly computed with some specified leaf hash. This is the last element in Taproot
|
||||
/// witness when spending a output via script path.
|
||||
///
|
||||
/// # Errors
|
||||
|
@ -1105,7 +1105,7 @@ impl ControlBlock {
|
|||
/// - [`TaprootError::InvalidControlBlockSize`] if `sl` is not of size 1 + 32 + 32N for any N >= 0.
|
||||
/// - [`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).
|
||||
/// - [`TaprootError::InvalidMerkleTreeDepth`] if Merkle tree is too deep (more than 128 levels).
|
||||
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
|
||||
|
@ -1157,7 +1157,7 @@ impl ControlBlock {
|
|||
|
||||
/// Verifies that a control block is correct proof for a given output key and script.
|
||||
///
|
||||
/// Only checks that script is contained inside the taptree described by output key. Full
|
||||
/// 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>(
|
||||
&self,
|
||||
|
@ -1301,7 +1301,7 @@ impl<'de> serde::Deserialize<'de> for LeafVersion {
|
|||
type Value = LeafVersion;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a valid consensus-encoded taproot leaf version")
|
||||
formatter.write_str("a valid consensus-encoded Taproot leaf version")
|
||||
}
|
||||
|
||||
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
|
||||
|
@ -1327,7 +1327,7 @@ impl<'de> serde::Deserialize<'de> for LeafVersion {
|
|||
}
|
||||
}
|
||||
|
||||
/// Detailed error type for taproot builder.
|
||||
/// Detailed error type for Taproot builder.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
pub enum TaprootBuilderError {
|
||||
|
@ -1354,11 +1354,11 @@ impl fmt::Display for TaprootBuilderError {
|
|||
}
|
||||
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",
|
||||
"attempted to create a tree with two nodes at depth 0. There must\
|
||||
only be exactly one node at depth 0",
|
||||
),
|
||||
EmptyTree => {
|
||||
write!(f, "Called finalize on an empty tree")
|
||||
write!(f, "called finalize on an empty tree")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1380,7 +1380,7 @@ impl From<InvalidMerkleTreeDepthError> for TaprootBuilderError {
|
|||
fn from(e: InvalidMerkleTreeDepthError) -> Self { Self::InvalidMerkleTreeDepth(e) }
|
||||
}
|
||||
|
||||
/// Detailed error type for taproot utilities.
|
||||
/// Detailed error type for Taproot utilities.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
pub enum TaprootError {
|
||||
|
@ -1392,9 +1392,9 @@ pub enum TaprootError {
|
|||
InvalidTaprootLeafVersion(InvalidTaprootLeafVersionError),
|
||||
/// Invalid control block size.
|
||||
InvalidControlBlockSize(InvalidControlBlockSizeError),
|
||||
/// Invalid taproot internal key.
|
||||
/// Invalid Taproot internal key.
|
||||
InvalidInternalKey(secp256k1::Error),
|
||||
/// Empty tap tree.
|
||||
/// Empty Taproot tree.
|
||||
EmptyTree,
|
||||
}
|
||||
|
||||
|
@ -1410,7 +1410,7 @@ impl fmt::Display for TaprootError {
|
|||
InvalidTaprootLeafVersion(ref e) => write_err!(f, "invalid Taproot leaf version"; e),
|
||||
InvalidControlBlockSize(ref e) => write_err!(f, "invalid control block size"; e),
|
||||
InvalidInternalKey(ref e) => write_err!(f, "invalid internal x-only key"; e),
|
||||
EmptyTree => write!(f, "Taproot Tree must contain at least one script"),
|
||||
EmptyTree => write!(f, "Taproot tree must contain at least one script"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue