MCPcopy Create free account
hub / github.com/bitcoin/bitcoin / InferTaprootTree

Function InferTaprootTree

src/script/signingprovider.cpp:501–634  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

499}
500
501std::optional<std::vector<std::tuple<int, std::vector<unsigned char>, int>>> InferTaprootTree(const TaprootSpendData& spenddata, const XOnlyPubKey& output)
502{
503 // Verify that the output matches the assumed Merkle root and internal key.
504 auto tweak = spenddata.internal_key.CreateTapTweak(spenddata.merkle_root.IsNull() ? nullptr : &spenddata.merkle_root);
505 if (!tweak || tweak->first != output) return std::nullopt;
506 // If the Merkle root is 0, the tree is empty, and we're done.
507 std::vector<std::tuple<int, std::vector<unsigned char>, int>> ret;
508 if (spenddata.merkle_root.IsNull()) return ret;
509
510 /** Data structure to represent the nodes of the tree we're going to build. */
511 struct TreeNode {
512 /** Hash of this node, if known; 0 otherwise. */
513 uint256 hash;
514 /** The left and right subtrees (note that their order is irrelevant). */
515 std::unique_ptr<TreeNode> sub[2];
516 /** If this is known to be a leaf node, a pointer to the (script, leaf_ver) pair.
517 * nullptr otherwise. */
518 const std::pair<std::vector<unsigned char>, int>* leaf = nullptr;
519 /** Whether or not this node has been explored (is known to be a leaf, or known to have children). */
520 bool explored = false;
521 /** Whether or not this node is an inner node (unknown until explored = true). */
522 bool inner;
523 /** Whether or not we have produced output for this subtree. */
524 bool done = false;
525 };
526
527 // Build tree from the provided branches.
528 TreeNode root;
529 root.hash = spenddata.merkle_root;
530 for (const auto& [key, control_blocks] : spenddata.scripts) {
531 const auto& [script, leaf_ver] = key;
532 for (const auto& control : control_blocks) {
533 // Skip script records with nonsensical leaf version.
534 if (leaf_ver < 0 || leaf_ver >= 0x100 || leaf_ver & 1) continue;
535 // Skip script records with invalid control block sizes.
536 if (control.size() < TAPROOT_CONTROL_BASE_SIZE || control.size() > TAPROOT_CONTROL_MAX_SIZE ||
537 ((control.size() - TAPROOT_CONTROL_BASE_SIZE) % TAPROOT_CONTROL_NODE_SIZE) != 0) continue;
538 // Skip script records that don't match the control block.
539 if ((control[0] & TAPROOT_LEAF_MASK) != leaf_ver) continue;
540 // Skip script records that don't match the provided Merkle root.
541 const uint256 leaf_hash = ComputeTapleafHash(leaf_ver, script);
542 const uint256 merkle_root = ComputeTaprootMerkleRoot(control, leaf_hash);
543 if (merkle_root != spenddata.merkle_root) continue;
544
545 TreeNode* node = &root;
546 size_t levels = (control.size() - TAPROOT_CONTROL_BASE_SIZE) / TAPROOT_CONTROL_NODE_SIZE;
547 for (size_t depth = 0; depth < levels; ++depth) {
548 // Can't descend into a node which we already know is a leaf.
549 if (node->explored && !node->inner) return std::nullopt;
550
551 // Extract partner hash from Merkle branch in control block.
552 uint256 hash;
553 std::copy(control.begin() + TAPROOT_CONTROL_BASE_SIZE + (levels - 1 - depth) * TAPROOT_CONTROL_NODE_SIZE,
554 control.begin() + TAPROOT_CONTROL_BASE_SIZE + (levels - depth) * TAPROOT_CONTROL_NODE_SIZE,
555 hash.begin());
556
557 if (node->sub[0]) {
558 // Descend into the existing left or right branch.

Callers 1

InferScriptFunction · 0.85

Calls 12

ComputeTapleafHashFunction · 0.85
ComputeTaprootMerkleRootFunction · 0.85
ComputeTapbranchHashFunction · 0.85
CreateTapTweakMethod · 0.80
IsNullMethod · 0.45
sizeMethod · 0.45
beginMethod · 0.45
emptyMethod · 0.45
backMethod · 0.45
emplace_backMethod · 0.45
pop_backMethod · 0.45
push_backMethod · 0.45

Tested by

no test coverage detected