MCPcopy Create free account
hub / github.com/ElementsProject/elements / InferTaprootTree

Function InferTaprootTree

src/script/standard.cpp:524–657  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

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

Callers 1

InferScriptFunction · 0.85

Calls 11

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

Tested by

no test coverage detected