Skip to content

Commit bfcb649

Browse files
author
ChallengeDev210
committed
Update TaprootBuilder::finalize
This commit does two things: 1) BUG FIX: We should have checked that the length of the branch is 1 before computing the spend_info on it. This was introduced in #936, but slipped past my review :( 2) Update the return type to return the consumed `self` value. This function can only error when there the tree building is not complete. Returning TaprootBuilderError causes issues in downstream projects that need to deal with error cases which cannot happen in this function
1 parent 0ccc031 commit bfcb649

File tree

1 file changed

+14
-15
lines changed

1 file changed

+14
-15
lines changed

src/util/taproot.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,8 @@ impl TaprootSpendInfo {
199199
I: IntoIterator<Item=(u32, Script)>,
200200
C: secp256k1::Verification,
201201
{
202-
TaprootBuilder::with_huffman_tree(script_weights)?.finalize(secp, internal_key)
202+
let builder = TaprootBuilder::with_huffman_tree(script_weights)?;
203+
Ok(builder.finalize(secp, internal_key).expect("Huffman Tree is always complete"))
203204
}
204205

205206
/// Creates a new key spend with `internal_key` and `merkle_root`. Provide [`None`] for
@@ -451,19 +452,23 @@ impl TaprootBuilder {
451452

452453
/// Creates a [`TaprootSpendInfo`] with the given internal key.
453454
///
454-
// TODO: in a future breaking API change, this no longer needs to return result
455+
/// Returns the unmodified builder as Err if the builder is not finalized.
456+
/// See also [`TaprootBuilder::is_finalized`]
455457
pub fn finalize<C: secp256k1::Verification>(
456458
mut self,
457459
secp: &Secp256k1<C>,
458460
internal_key: UntweakedPublicKey,
459-
) -> Result<TaprootSpendInfo, TaprootBuilderError> {
460-
match self.branch.pop() {
461-
None => Ok(TaprootSpendInfo::new_key_spend(secp, internal_key, None)),
462-
Some(Some(node)) => {
463-
Ok(TaprootSpendInfo::from_node_info(secp, internal_key, node))
461+
) -> Result<TaprootSpendInfo, TaprootBuilder> {
462+
match self.branch.len() {
463+
0 => Ok(TaprootSpendInfo::new_key_spend(secp, internal_key, None)),
464+
1 => {
465+
if let Some(Some(node)) = self.branch.pop() {
466+
Ok(TaprootSpendInfo::from_node_info(secp, internal_key, node))
467+
} else {
468+
unreachable!("Size checked above. Builder guarantees the last element is Some")
469+
}
464470
}
465-
_ => Err(TaprootBuilderError::IncompleteTree),
466-
471+
_ => Err(self),
467472
}
468473
}
469474

@@ -1013,8 +1018,6 @@ pub enum TaprootBuilderError {
10131018
OverCompleteTree,
10141019
/// Invalid taproot internal key.
10151020
InvalidInternalKey(secp256k1::Error),
1016-
/// Called finalize on an incomplete tree.
1017-
IncompleteTree,
10181021
/// Called finalize on a empty tree.
10191022
EmptyTree,
10201023
}
@@ -1036,9 +1039,6 @@ impl fmt::Display for TaprootBuilderError {
10361039
TaprootBuilderError::InvalidInternalKey(ref e) => {
10371040
write_err!(f, "invalid internal x-only key"; e)
10381041
}
1039-
TaprootBuilderError::IncompleteTree => {
1040-
write!(f, "Called finalize on an incomplete tree")
1041-
}
10421042
TaprootBuilderError::EmptyTree => {
10431043
write!(f, "Called finalize on an empty tree")
10441044
}
@@ -1057,7 +1057,6 @@ impl std::error::Error for TaprootBuilderError {
10571057
InvalidMerkleTreeDepth(_)
10581058
| NodeNotInDfsOrder
10591059
| OverCompleteTree
1060-
| IncompleteTree
10611060
| EmptyTree => None
10621061
}
10631062
}

0 commit comments

Comments
 (0)