Merge rust-bitcoin/rust-bitcoin#4375: Add ControlBlock constructor that takes a hex string
3319e6ef6d
Add ControlBlock constructor that takes a hex string (Shing Him Ng) Pull request description: Closes #4362 ACKs for top commit: Kixunil: ACK3319e6ef6d
apoelstra: ACK 3319e6ef6dd964f40e6e880843648c112a6b74ed; successfully ran local tests Tree-SHA512: 230e4607402b3df6a8c5fe1e03209573baffbd08ca9d28e1208bff1464668a083ddb5ae72781eceb2546bc99b150dd2f832d122570d55aa323c603481c5eff93
This commit is contained in:
commit
2d8ebb79c3
|
@ -13,6 +13,7 @@ use core::fmt;
|
||||||
use core::iter::FusedIterator;
|
use core::iter::FusedIterator;
|
||||||
|
|
||||||
use hashes::{hash_newtype, sha256t, sha256t_tag, HashEngine};
|
use hashes::{hash_newtype, sha256t, sha256t_tag, HashEngine};
|
||||||
|
use hex::{FromHex, HexToBytesError};
|
||||||
use internals::array::ArrayExt;
|
use internals::array::ArrayExt;
|
||||||
#[allow(unused)] // MSRV polyfill
|
#[allow(unused)] // MSRV polyfill
|
||||||
use internals::slice::SliceExt;
|
use internals::slice::SliceExt;
|
||||||
|
@ -1198,6 +1199,12 @@ impl ControlBlock {
|
||||||
|
|
||||||
Ok(ControlBlock { leaf_version, output_key_parity, internal_key, merkle_branch })
|
Ok(ControlBlock { leaf_version, output_key_parity, internal_key, merkle_branch })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructs a new [`ControlBlock`] from a hex string.
|
||||||
|
pub fn from_hex(hex: &str) -> Result<Self, TaprootError> {
|
||||||
|
let vec = Vec::from_hex(hex).map_err(TaprootError::InvalidControlBlockHex)?;
|
||||||
|
ControlBlock::decode(vec.as_slice())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, K> ControlBlock<B, K> {
|
impl<B, K> ControlBlock<B, K> {
|
||||||
|
@ -1514,6 +1521,8 @@ pub enum TaprootError {
|
||||||
InvalidControlBlockSize(InvalidControlBlockSizeError),
|
InvalidControlBlockSize(InvalidControlBlockSizeError),
|
||||||
/// Invalid Taproot internal key.
|
/// Invalid Taproot internal key.
|
||||||
InvalidInternalKey(secp256k1::Error),
|
InvalidInternalKey(secp256k1::Error),
|
||||||
|
/// Invalid control block hex
|
||||||
|
InvalidControlBlockHex(HexToBytesError),
|
||||||
/// Empty Taproot tree.
|
/// Empty Taproot tree.
|
||||||
EmptyTree,
|
EmptyTree,
|
||||||
}
|
}
|
||||||
|
@ -1531,6 +1540,7 @@ impl fmt::Display for TaprootError {
|
||||||
InvalidMerkleTreeDepth(ref e) => write_err!(f, "invalid Merkle tree depth"; e),
|
InvalidMerkleTreeDepth(ref e) => write_err!(f, "invalid Merkle tree depth"; e),
|
||||||
InvalidTaprootLeafVersion(ref e) => write_err!(f, "invalid Taproot leaf version"; e),
|
InvalidTaprootLeafVersion(ref e) => write_err!(f, "invalid Taproot leaf version"; e),
|
||||||
InvalidControlBlockSize(ref e) => write_err!(f, "invalid control block size"; e),
|
InvalidControlBlockSize(ref e) => write_err!(f, "invalid control block size"; e),
|
||||||
|
InvalidControlBlockHex(ref e) => write_err!(f, "invalid control block hex"; e),
|
||||||
InvalidInternalKey(ref e) => write_err!(f, "invalid internal x-only key"; 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"),
|
||||||
}
|
}
|
||||||
|
@ -1546,6 +1556,7 @@ impl std::error::Error for TaprootError {
|
||||||
InvalidInternalKey(e) => Some(e),
|
InvalidInternalKey(e) => Some(e),
|
||||||
InvalidTaprootLeafVersion(ref e) => Some(e),
|
InvalidTaprootLeafVersion(ref e) => Some(e),
|
||||||
InvalidMerkleTreeDepth(ref e) => Some(e),
|
InvalidMerkleTreeDepth(ref e) => Some(e),
|
||||||
|
InvalidControlBlockHex(ref e) => Some(e),
|
||||||
InvalidMerkleBranchSize(_) | InvalidControlBlockSize(_) | EmptyTree => None,
|
InvalidMerkleBranchSize(_) | InvalidControlBlockSize(_) | EmptyTree => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1670,7 +1681,7 @@ impl std::error::Error for InvalidControlBlockSizeError {}
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use hashes::sha256;
|
use hashes::sha256;
|
||||||
use hex::{DisplayHex, FromHex};
|
use hex::DisplayHex;
|
||||||
use secp256k1::VerifyOnly;
|
use secp256k1::VerifyOnly;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -1771,8 +1782,7 @@ mod test {
|
||||||
let out_pk = out_spk_hex[4..].parse::<XOnlyPublicKey>().unwrap();
|
let out_pk = out_spk_hex[4..].parse::<XOnlyPublicKey>().unwrap();
|
||||||
let out_pk = TweakedPublicKey::dangerous_assume_tweaked(out_pk);
|
let out_pk = TweakedPublicKey::dangerous_assume_tweaked(out_pk);
|
||||||
let script = ScriptBuf::from_hex(script_hex).unwrap();
|
let script = ScriptBuf::from_hex(script_hex).unwrap();
|
||||||
let control_block =
|
let control_block = ControlBlock::from_hex(control_block_hex).unwrap();
|
||||||
ControlBlock::decode(&Vec::<u8>::from_hex(control_block_hex).unwrap()).unwrap();
|
|
||||||
assert_eq!(control_block_hex, control_block.serialize().to_lower_hex_string());
|
assert_eq!(control_block_hex, control_block.serialize().to_lower_hex_string());
|
||||||
assert!(control_block.verify_taproot_commitment(secp, out_pk.to_inner(), &script));
|
assert!(control_block.verify_taproot_commitment(secp, out_pk.to_inner(), &script));
|
||||||
}
|
}
|
||||||
|
@ -2053,10 +2063,8 @@ mod test {
|
||||||
let spend_info = builder.finalize(secp, internal_key).unwrap();
|
let spend_info = builder.finalize(secp, internal_key).unwrap();
|
||||||
for (i, script_ver) in leaves.iter().enumerate() {
|
for (i, script_ver) in leaves.iter().enumerate() {
|
||||||
let expected_leaf_hash = leaf_hashes[i].as_str().unwrap();
|
let expected_leaf_hash = leaf_hashes[i].as_str().unwrap();
|
||||||
let expected_ctrl_blk = ControlBlock::decode(
|
let expected_ctrl_blk =
|
||||||
&Vec::<u8>::from_hex(ctrl_blks[i].as_str().unwrap()).unwrap(),
|
ControlBlock::from_hex(ctrl_blks[i].as_str().unwrap()).unwrap();
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let leaf_hash = TapLeafHash::from_script(&script_ver.0, script_ver.1);
|
let leaf_hash = TapLeafHash::from_script(&script_ver.0, script_ver.1);
|
||||||
let ctrl_blk = spend_info.control_block(script_ver).unwrap();
|
let ctrl_blk = spend_info.control_block(script_ver).unwrap();
|
||||||
|
|
Loading…
Reference in New Issue