Skip to content

taproot: add TapNodeHash getter method on TapTree and NodeInfo#2467

Merged
apoelstra merged 1 commit into
rust-bitcoin:masterfrom
conduition:tap-node-hash
Feb 13, 2024
Merged

taproot: add TapNodeHash getter method on TapTree and NodeInfo#2467
apoelstra merged 1 commit into
rust-bitcoin:masterfrom
conduition:tap-node-hash

Conversation

@conduition

@conduition conduition commented Feb 11, 2024

Copy link
Copy Markdown
Contributor

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 root TapNodeHash.

Instead, the API forces me to do TaprootBuilder::finalize(secp_ctx, internal_key) first to get a TaprootSpendInfo, and then call TaprootSpendInfo::merkle_root() to get the root TapNodehash. This requires ECC point addition/multiplication for the tweak operation (inside TaprootBuilder::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 root TapNodeHash while still using the safe API provided by TaprootBuilder. I would simply use TaprootBuilder to build a TapTree or NodeInfo, and then invoke the node_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 a NodeInfo or TapTree in the first place would be to finalize the builder into it, which seems like an acceptable and intuitive-enough usage path to me.

@github-actions github-actions Bot added the C-bitcoin PRs modifying the bitcoin crate label Feb 11, 2024
@coveralls

coveralls commented Feb 11, 2024

Copy link
Copy Markdown

Pull Request Test Coverage Report for Build 7879485491

Details

  • -2 of 2 (0.0%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-0.007%) to 84.038%

Changes Missing Coverage Covered Lines Changed/Added Lines %
bitcoin/src/taproot/mod.rs 0 2 0.0%
Totals Coverage Status
Change from base Build 7879164707: -0.007%
Covered Lines: 19433
Relevant Lines: 23124

💛 - Coveralls

@apoelstra

Copy link
Copy Markdown
Member

I think the method on TapTree should be called root_hash, since the hash has to be the hash of the root of the tree. (You can't compose or modify TapTrees once they're created.)

But I think you're correct that this is an API gap. I agree there's a mild footgun in the NodeInfo::node_hash method but realistically people can stick all sorts of wrong hashes into wrong places, and since this doesn't affect the normal API I think it's fine.

@Kixunil

Kixunil commented Feb 12, 2024

Copy link
Copy Markdown
Collaborator

Concept ACK.

Maybe root_node would be better? Anyway, I agree with having root in the name.

Fixes a gap in the API of the taproot module. Callers can now use
TapTree::root_hash or NodeInfo::node_hash to extract the taproot
tree merkle root hash for fast validation without any ECC overhead.
@conduition

Copy link
Copy Markdown
Contributor Author

I renamed node_hash to root_hash on TapTree. I left the method on NodeInfo alone.

Then squashed, rebased, and added a more detailed commit message.

@apoelstra apoelstra left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 1384330

@tcharding tcharding left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 1384330

@apoelstra apoelstra merged commit 668df1d into rust-bitcoin:master Feb 13, 2024
@conduition conduition deleted the tap-node-hash branch February 13, 2024 21:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-bitcoin PRs modifying the bitcoin crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants