| 522 | } |
| 523 | |
| 524 | std::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. |
no test coverage detected