Skip to content

Commit 29e5dd1

Browse files
committed
consensus refactor: extract ComputeTapleafHash, ComputeTaprootMerkleRoot
1 parent 0f47e01 commit 29e5dd1

File tree

2 files changed

+28
-10
lines changed

2 files changed

+28
-10
lines changed

src/script/interpreter.cpp

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1847,16 +1847,14 @@ static bool ExecuteWitnessScript(const Span<const valtype>& stack_span, const CS
18471847
return true;
18481848
}
18491849

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)
18511856
{
18521857
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.
18601858
uint256 k = tapleaf_hash;
18611859
for (int i = 0; i < path_len; ++i) {
18621860
CHashWriter ss_branch{HASHER_TAPBRANCH};
@@ -1868,8 +1866,21 @@ static bool VerifyTaprootCommitment(const std::vector<unsigned char>& control, c
18681866
}
18691867
k = ss_branch.GetSHA256();
18701868
}
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);
18711882
// 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);
18731884
}
18741885

18751886
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,
19291940
if (control.size() < TAPROOT_CONTROL_BASE_SIZE || control.size() > TAPROOT_CONTROL_MAX_SIZE || ((control.size() - TAPROOT_CONTROL_BASE_SIZE) % TAPROOT_CONTROL_NODE_SIZE) != 0) {
19301941
return set_error(serror, SCRIPT_ERR_TAPROOT_WRONG_CONTROL_SIZE);
19311942
}
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)) {
19331945
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
19341946
}
19351947
execdata.m_tapleaf_hash_init = true;

src/script/interpreter.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,12 @@ class DeferringSignatureChecker : public BaseSignatureChecker
317317
}
318318
};
319319

320+
/** Compute the BIP341 tapleaf hash from leaf version & script. */
321+
uint256 ComputeTapleafHash(uint8_t leaf_version, const CScript& script);
322+
/** Compute the BIP341 taproot script tree Merkle root from control block and leaf hash.
323+
* Requires control block to have valid length (33 + k*32, with k in {0,1,..,128}). */
324+
uint256 ComputeTaprootMerkleRoot(Span<const unsigned char> control, const uint256& tapleaf_hash);
325+
320326
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* error = nullptr);
321327
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* error = nullptr);
322328
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror = nullptr);

0 commit comments

Comments
 (0)