| 3285 | } |
| 3286 | |
| 3287 | 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) |
| 3288 | { |
| 3289 | CScript exec_script; //!< Actually executed script (last stack item in P2WSH; implied P2PKH script in P2WPKH; leaf script in P2TR) |
| 3290 | Span stack{witness.stack}; |
| 3291 | ScriptExecutionData execdata; |
| 3292 | |
| 3293 | if (witversion == 0) { |
| 3294 | if (program.size() == WITNESS_V0_SCRIPTHASH_SIZE) { |
| 3295 | // BIP141 P2WSH: 32-byte witness v0 program (which encodes SHA256(script)) |
| 3296 | if (stack.size() == 0) { |
| 3297 | return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY); |
| 3298 | } |
| 3299 | const valtype& script_bytes = SpanPopBack(stack); |
| 3300 | exec_script = CScript(script_bytes.begin(), script_bytes.end()); |
| 3301 | uint256 hash_exec_script; |
| 3302 | CSHA256().Write(exec_script.data(), exec_script.size()).Finalize(hash_exec_script.begin()); |
| 3303 | if (memcmp(hash_exec_script.begin(), program.data(), 32)) { |
| 3304 | return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH); |
| 3305 | } |
| 3306 | return ExecuteWitnessScript(stack, exec_script, flags, SigVersion::WITNESS_V0, checker, execdata, serror); |
| 3307 | } else if (program.size() == WITNESS_V0_KEYHASH_SIZE) { |
| 3308 | // BIP141 P2WPKH: 20-byte witness v0 program (which encodes Hash160(pubkey)) |
| 3309 | if (stack.size() != 2) { |
| 3310 | return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH); // 2 items in witness |
| 3311 | } |
| 3312 | exec_script << OP_DUP << OP_HASH160 << program << OP_EQUALVERIFY << OP_CHECKSIG; |
| 3313 | return ExecuteWitnessScript(stack, exec_script, flags, SigVersion::WITNESS_V0, checker, execdata, serror); |
| 3314 | } else { |
| 3315 | return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH); |
| 3316 | } |
| 3317 | } else if (witversion == 1 && program.size() == WITNESS_V1_TAPROOT_SIZE && !is_p2sh) { |
| 3318 | // BIP341 Taproot: 32-byte non-P2SH witness v1 program (which encodes a P2C-tweaked pubkey) |
| 3319 | if (!(flags & SCRIPT_VERIFY_TAPROOT)) return set_success(serror); |
| 3320 | if (stack.size() == 0) return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY); |
| 3321 | if (stack.size() >= 2 && !stack.back().empty() && stack.back()[0] == ANNEX_TAG) { |
| 3322 | // Drop annex (this is non-standard; see IsWitnessStandard) |
| 3323 | const valtype& annex = SpanPopBack(stack); |
| 3324 | execdata.m_annex_hash = (CHashWriter(SER_GETHASH, 0) << annex).GetSHA256(); |
| 3325 | execdata.m_annex_present = true; |
| 3326 | } else { |
| 3327 | execdata.m_annex_present = false; |
| 3328 | } |
| 3329 | execdata.m_annex_init = true; |
| 3330 | if (stack.size() == 1) { |
| 3331 | // Key path spending (stack size is 1 after removing optional annex) |
| 3332 | if (!checker.CheckSchnorrSignature(stack.front(), program, SigVersion::TAPROOT, execdata, serror)) { |
| 3333 | return false; // serror is set |
| 3334 | } |
| 3335 | return set_success(serror); |
| 3336 | } else { |
| 3337 | // Script path spending (stack size is >1 after removing optional annex) |
| 3338 | const valtype& control = SpanPopBack(stack); |
| 3339 | const valtype& script_bytes = SpanPopBack(stack); |
| 3340 | exec_script = CScript(script_bytes.begin(), script_bytes.end()); |
| 3341 | if (control.size() < TAPROOT_CONTROL_BASE_SIZE || control.size() > TAPROOT_CONTROL_MAX_SIZE || ((control.size() - TAPROOT_CONTROL_BASE_SIZE) % TAPROOT_CONTROL_NODE_SIZE) != 0) { |
| 3342 | return set_error(serror, SCRIPT_ERR_TAPROOT_WRONG_CONTROL_SIZE); |
| 3343 | } |
| 3344 | execdata.m_tapleaf_hash = ComputeTapleafHash(control[0] & TAPROOT_LEAF_MASK, exec_script); |
no test coverage detected