@@ -1834,9 +1834,13 @@ static bool ExecuteWitnessScript(const Span<const valtype>& stack_span, const CS
18341834static bool VerifyTaprootCommitment (const std::vector<unsigned char >& control, const std::vector<unsigned char >& program, const CScript& script, uint256& tapleaf_hash)
18351835{
18361836 const int path_len = (control.size () - TAPROOT_CONTROL_BASE_SIZE) / TAPROOT_CONTROL_NODE_SIZE;
1837+ // ! The inner pubkey (x-only, so no Y coordinate parity).
18371838 const XOnlyPubKey p{uint256 (std::vector<unsigned char >(control.begin () + 1 , control.begin () + TAPROOT_CONTROL_BASE_SIZE))};
1839+ // ! The output pubkey (taken from the scriptPubKey).
18381840 const XOnlyPubKey q{uint256 (program)};
1841+ // Compute the tapleaf hash.
18391842 tapleaf_hash = (CHashWriter (HASHER_TAPLEAF) << uint8_t (control[0 ] & TAPROOT_LEAF_MASK) << script).GetSHA256 ();
1843+ // Compute the Merkle root from the leaf and the provided path.
18401844 uint256 k = tapleaf_hash;
18411845 for (int i = 0 ; i < path_len; ++i) {
18421846 CHashWriter ss_branch{HASHER_TAPBRANCH};
@@ -1848,7 +1852,9 @@ static bool VerifyTaprootCommitment(const std::vector<unsigned char>& control, c
18481852 }
18491853 k = ss_branch.GetSHA256 ();
18501854 }
1855+ // Compute the tweak from the Merkle root and the inner pubkey.
18511856 k = (CHashWriter (HASHER_TAPTWEAK) << MakeSpan (p) << k).GetSHA256 ();
1857+ // Verify that the output pubkey matches the tweaked inner pubkey, after correcting for parity.
18521858 return q.CheckPayToContract (p, k, control[0 ] & 1 );
18531859}
18541860
0 commit comments