Rename from_slice methods to decode

The `TaprootMerkleBranch` and `ControlBlock` both have methods on them
called `from_slice` but these methods do more that just basic copy from
a slice. `decode` is a more descriptive name.

Deprecate the `from_slice` methods and implement `decode`, on other
changes to the logic.
This commit is contained in:
Tobin C. Harding 2023-02-04 15:19:20 +11:00
parent 732dd038ff
commit 32d2d62e0f
No known key found for this signature in database
GPG Key ID: 40BF9E4C269D6607
3 changed files with 32 additions and 10 deletions

View File

@ -335,7 +335,7 @@ impl Serialize for ControlBlock {
impl Deserialize for ControlBlock { impl Deserialize for ControlBlock {
fn deserialize(bytes: &[u8]) -> Result<Self, Error> { fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
Self::from_slice(bytes) Self::decode(bytes)
.map_err(|_| Error::InvalidControlBlock) .map_err(|_| Error::InvalidControlBlock)
} }
} }

View File

@ -644,8 +644,22 @@ impl TaprootMerkleBranch {
/// Returns a reference to the inner vector of hashes. /// Returns a reference to the inner vector of hashes.
pub fn as_inner(&self) -> &[TapNodeHash] { &self.0 } pub fn as_inner(&self) -> &[TapNodeHash] { &self.0 }
/// Creates a merkle proof from raw data representing a list of hashes. /// Decodes bytes from control block.
#[deprecated(since = "0.30.0", note = "Use decode instead")]
pub fn from_slice(sl: &[u8]) -> Result<Self, TaprootError> { pub fn from_slice(sl: &[u8]) -> Result<Self, TaprootError> {
Self::decode(sl)
}
/// Decodes bytes from control block.
///
/// This reads the branch as encoded in the control block: the concatenated 32B byte chunks -
/// one for each hash.
///
/// # Errors
///
/// The function returns an error if the the number of bytes is not an integer multiple of 32 or
/// if the number of hashes exceeds 128.
pub fn decode(sl: &[u8]) -> Result<Self, TaprootError> {
if sl.len() % TAPROOT_CONTROL_NODE_SIZE != 0 { if sl.len() % TAPROOT_CONTROL_NODE_SIZE != 0 {
Err(TaprootError::InvalidMerkleBranchSize(sl.len())) Err(TaprootError::InvalidMerkleBranchSize(sl.len()))
} else if sl.len() > TAPROOT_CONTROL_NODE_SIZE * TAPROOT_CONTROL_MAX_NODE_COUNT { } else if sl.len() > TAPROOT_CONTROL_NODE_SIZE * TAPROOT_CONTROL_MAX_NODE_COUNT {
@ -743,9 +757,17 @@ pub struct ControlBlock {
} }
impl ControlBlock { impl ControlBlock {
/// Constructs a `ControlBlock` from slice. This is an extra witness element that provides the /// Constructs a `ControlBlock` from slice.
/// proof that taproot script pubkey is correctly computed with some specified leaf hash. This #[deprecated(since = "0.30.0", note = "Use decode instead")]
/// is the last element in taproot witness when spending a output via script path. pub fn from_slice(sl: &[u8]) -> Result<ControlBlock, TaprootError> {
Self::decode(sl)
}
/// 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
/// witness when spending a output via script path.
/// ///
/// # Errors /// # Errors
/// ///
@ -754,7 +776,7 @@ impl ControlBlock {
/// - [`TaprootError::InvalidTaprootLeafVersion`] if first byte of `sl` is not a valid leaf version. /// - [`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::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 from_slice(sl: &[u8]) -> Result<ControlBlock, TaprootError> { pub fn decode(sl: &[u8]) -> Result<ControlBlock, TaprootError> {
if sl.len() < TAPROOT_CONTROL_BASE_SIZE if sl.len() < TAPROOT_CONTROL_BASE_SIZE
|| (sl.len() - TAPROOT_CONTROL_BASE_SIZE) % TAPROOT_CONTROL_NODE_SIZE != 0 || (sl.len() - TAPROOT_CONTROL_BASE_SIZE) % TAPROOT_CONTROL_NODE_SIZE != 0
{ {
@ -765,7 +787,7 @@ impl ControlBlock {
let leaf_version = LeafVersion::from_consensus(sl[0] & TAPROOT_LEAF_MASK)?; let leaf_version = LeafVersion::from_consensus(sl[0] & TAPROOT_LEAF_MASK)?;
let internal_key = UntweakedPublicKey::from_slice(&sl[1..TAPROOT_CONTROL_BASE_SIZE]) let internal_key = UntweakedPublicKey::from_slice(&sl[1..TAPROOT_CONTROL_BASE_SIZE])
.map_err(TaprootError::InvalidInternalKey)?; .map_err(TaprootError::InvalidInternalKey)?;
let merkle_branch = TaprootMerkleBranch::from_slice(&sl[TAPROOT_CONTROL_BASE_SIZE..])?; let merkle_branch = TaprootMerkleBranch::decode(&sl[TAPROOT_CONTROL_BASE_SIZE..])?;
Ok(ControlBlock { leaf_version, output_key_parity, internal_key, merkle_branch }) Ok(ControlBlock { leaf_version, output_key_parity, internal_key, merkle_branch })
} }
@ -1207,7 +1229,7 @@ mod test {
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_slice(&Vec::<u8>::from_hex(control_block_hex).unwrap()).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));
} }
@ -1431,7 +1453,7 @@ 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::from_slice( let expected_ctrl_blk = ControlBlock::decode(
&Vec::<u8>::from_hex(ctrl_blks[i].as_str().unwrap()).unwrap(), &Vec::<u8>::from_hex(ctrl_blks[i].as_str().unwrap()).unwrap(),
) )
.unwrap(); .unwrap();

View File

@ -187,7 +187,7 @@ fn serde_regression_ecdsa_sig() {
#[test] #[test]
fn serde_regression_control_block() { fn serde_regression_control_block() {
let s = include_str!("data/serde/control_block_hex"); let s = include_str!("data/serde/control_block_hex");
let block = ControlBlock::from_slice(&Vec::<u8>::from_hex(s.trim()).unwrap()).unwrap(); let block = ControlBlock::decode(&Vec::<u8>::from_hex(s.trim()).unwrap()).unwrap();
let got = serialize(&block).unwrap(); let got = serialize(&block).unwrap();
let want = include_bytes!("data/serde/control_block_bincode") as &[_]; let want = include_bytes!("data/serde/control_block_bincode") as &[_];