@@ -1847,16 +1847,14 @@ static bool ExecuteWitnessScript(const Span<const valtype>& stack_span, const CS
1847
1847
return true ;
1848
1848
}
1849
1849
1850
- static bool VerifyTaprootCommitment (const std::vector<unsigned char >& control, const std::vector<unsigned char >& program, const CScript& script, uint256& tapleaf_hash)
1850
+ uint256 ComputeTapleafHash (uint8_t leaf_version, const CScript& script)
1851
+ {
1852
+ return (CHashWriter (HASHER_TAPLEAF) << leaf_version << script).GetSHA256 ();
1853
+ }
1854
+
1855
+ uint256 ComputeTaprootMerkleRoot (Span<const unsigned char > control, const uint256& tapleaf_hash)
1851
1856
{
1852
1857
const int path_len = (control.size () - TAPROOT_CONTROL_BASE_SIZE) / TAPROOT_CONTROL_NODE_SIZE;
1853
- // ! The internal pubkey (x-only, so no Y coordinate parity).
1854
- const XOnlyPubKey p{uint256 (std::vector<unsigned char >(control.begin () + 1 , control.begin () + TAPROOT_CONTROL_BASE_SIZE))};
1855
- // ! The output pubkey (taken from the scriptPubKey).
1856
- const XOnlyPubKey q{uint256 (program)};
1857
- // Compute the tapleaf hash.
1858
- tapleaf_hash = (CHashWriter (HASHER_TAPLEAF) << uint8_t (control[0 ] & TAPROOT_LEAF_MASK) << script).GetSHA256 ();
1859
- // Compute the Merkle root from the leaf and the provided path.
1860
1858
uint256 k = tapleaf_hash;
1861
1859
for (int i = 0 ; i < path_len; ++i) {
1862
1860
CHashWriter ss_branch{HASHER_TAPBRANCH};
@@ -1868,8 +1866,21 @@ static bool VerifyTaprootCommitment(const std::vector<unsigned char>& control, c
1868
1866
}
1869
1867
k = ss_branch.GetSHA256 ();
1870
1868
}
1869
+ return k;
1870
+ }
1871
+
1872
+ static bool VerifyTaprootCommitment (const std::vector<unsigned char >& control, const std::vector<unsigned char >& program, const uint256& tapleaf_hash)
1873
+ {
1874
+ assert (control.size () >= TAPROOT_CONTROL_BASE_SIZE);
1875
+ assert (program.size () >= uint256::size ());
1876
+ // ! The internal pubkey (x-only, so no Y coordinate parity).
1877
+ const XOnlyPubKey p{uint256 (std::vector<unsigned char >(control.begin () + 1 , control.begin () + TAPROOT_CONTROL_BASE_SIZE))};
1878
+ // ! The output pubkey (taken from the scriptPubKey).
1879
+ const XOnlyPubKey q{uint256 (program)};
1880
+ // Compute the Merkle root from the leaf and the provided path.
1881
+ const uint256 merkle_root = ComputeTaprootMerkleRoot (control, tapleaf_hash);
1871
1882
// Verify that the output pubkey matches the tweaked internal pubkey, after correcting for parity.
1872
- return q.CheckTapTweak (p, k , control[0 ] & 1 );
1883
+ return q.CheckTapTweak (p, merkle_root , control[0 ] & 1 );
1873
1884
}
1874
1885
1875
1886
static bool VerifyWitnessProgram (const CScriptWitness& witness, int witversion, const std::vector<unsigned char >& program, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror, bool is_p2sh)
@@ -1929,7 +1940,8 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion,
1929
1940
if (control.size () < TAPROOT_CONTROL_BASE_SIZE || control.size () > TAPROOT_CONTROL_MAX_SIZE || ((control.size () - TAPROOT_CONTROL_BASE_SIZE) % TAPROOT_CONTROL_NODE_SIZE) != 0 ) {
1930
1941
return set_error (serror, SCRIPT_ERR_TAPROOT_WRONG_CONTROL_SIZE);
1931
1942
}
1932
- if (!VerifyTaprootCommitment (control, program, exec_script, execdata.m_tapleaf_hash )) {
1943
+ execdata.m_tapleaf_hash = ComputeTapleafHash (control[0 ] & TAPROOT_LEAF_MASK, exec_script);
1944
+ if (!VerifyTaprootCommitment (control, program, execdata.m_tapleaf_hash )) {
1933
1945
return set_error (serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
1934
1946
}
1935
1947
execdata.m_tapleaf_hash_init = true ;
0 commit comments