Capitalize Merkle

Merkle is a proper noun and should be capitalized in docs and strings.

Capitalize all occurances of Merkle in docs and strings.
This commit is contained in:
Jamil Lambert, PhD 2024-06-25 14:19:43 +01:00
parent be5b93ea4f
commit 175f69abeb
9 changed files with 65 additions and 65 deletions

View File

@ -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,7 +58,7 @@ 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)

View File

@ -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 {

View File

@ -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,

View File

@ -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

View File

@ -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\

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: CC0-1.0
//! Bitcoin merkle tree functions.
//! Bitcoin Merkle tree functions.
//!
//! # Examples
//!

View File

@ -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>();

View File

@ -10,7 +10,7 @@ use super::{
};
use crate::prelude::{Borrow, BorrowMut, Box, Vec};
/// The merkle proof for inclusion of a tree in a Taproot tree 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)]

View File

@ -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>,
@ -158,7 +158,7 @@ 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.
@ -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,
@ -220,7 +220,7 @@ 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`].
///
@ -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`].
@ -271,7 +271,7 @@ impl TaprootSpendInfo {
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);
@ -686,7 +686,7 @@ impl std::error::Error for HiddenNodesError {
/// 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.
@ -801,11 +801,11 @@ impl<'tree> DoubleEndedIterator for LeafNodes<'tree> {
/// 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 {
@ -985,17 +985,17 @@ impl TapLeaf {
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() }
}
@ -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,7 +1089,7 @@ 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,
}
@ -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