taproot: add TapNodeHash getter method on TapTree and NodeInfo #2467
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Submitting this to fix what I think is an API hole. Please correct me if I'm mistaken here and there is an easier way to do what I'm after.
Problem
From what I can tell of the existing 0.31.1 API, there doesn't seem to be any way for a consumer to build a taproot tree using
TaprootBuilder
and then simply output the resulting tap tree merkle rootTapNodeHash
.Instead, the API forces me to do
TaprootBuilder::finalize(secp_ctx, internal_key)
first to get aTaprootSpendInfo
, and then callTaprootSpendInfo::merkle_root()
to get the rootTapNodehash
. This requires ECC point addition/multiplication for the tweak operation (insideTaprootBuilder::finalize
), so it is a lot less performant than the simple hashing operations needed to build a taproot tree.Obviously if I want to spend the taproot tree, I'll need to tweak an internal key. But if all I want is to examine the merkle root hashes of taproot trees (e.g. for quick validation), there should be a faster and more direct option for me.
Suggested Solution
My suggestion, demonstrated in this PR, would be to add a couple of simple getter methods:
TapTree::node_hash() -> TapNodeHash
NodeInfo::node_hash() -> TapNodeHash
These rhyme with the existing
LeafNode::node_hash()
method. These provide a roundabout way for downstream consumers to extract a taptree merkle rootTapNodeHash
while still using the safe API provided byTaprootBuilder
. I would simply useTaprootBuilder
to build aTapTree
orNodeInfo
, and then invoke thenode_hash
method on that object. No point addition required.Footguns
This does open up more opportunities for consumers to footgun themselves by, for example, committing a P2TR script pubkey to a leaf node by accident, instead of the root node. I'd argue this possibility already exists in the form of
LeafNode::node_hash()
. We're not making that problem much worse here.If the caller is using
TaprootBuilder
to construct their tree, the only way they'll be able to get aNodeInfo
orTapTree
in the first place would be to finalize the builder into it, which seems like an acceptable and intuitive-enough usage path to me.