| 1840 | template class GenericTransactionSignatureChecker<CMutableTransaction>; |
| 1841 | |
| 1842 | static bool ExecuteWitnessScript(const std::span<const valtype>& stack_span, const CScript& exec_script, script_verify_flags flags, SigVersion sigversion, const BaseSignatureChecker& checker, ScriptExecutionData& execdata, ScriptError* serror) |
| 1843 | { |
| 1844 | std::vector<valtype> stack{stack_span.begin(), stack_span.end()}; |
| 1845 | |
| 1846 | if (sigversion == SigVersion::TAPSCRIPT) { |
| 1847 | // OP_SUCCESSx processing overrides everything, including stack element size limits |
| 1848 | CScript::const_iterator pc = exec_script.begin(); |
| 1849 | while (pc < exec_script.end()) { |
| 1850 | opcodetype opcode; |
| 1851 | if (!exec_script.GetOp(pc, opcode)) { |
| 1852 | // Note how this condition would not be reached if an unknown OP_SUCCESSx was found |
| 1853 | return set_error(serror, SCRIPT_ERR_BAD_OPCODE); |
| 1854 | } |
| 1855 | // New opcodes will be listed here. May use a different sigversion to modify existing opcodes. |
| 1856 | if (IsOpSuccess(opcode)) { |
| 1857 | if (flags & SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS) { |
| 1858 | return set_error(serror, SCRIPT_ERR_DISCOURAGE_OP_SUCCESS); |
| 1859 | } |
| 1860 | return set_success(serror); |
| 1861 | } |
| 1862 | } |
| 1863 | |
| 1864 | // Tapscript enforces initial stack size limits (altstack is empty here) |
| 1865 | if (stack.size() > MAX_STACK_SIZE) return set_error(serror, SCRIPT_ERR_STACK_SIZE); |
| 1866 | } |
| 1867 | |
| 1868 | // Disallow stack item size > MAX_SCRIPT_ELEMENT_SIZE in witness stack |
| 1869 | for (const valtype& elem : stack) { |
| 1870 | if (elem.size() > MAX_SCRIPT_ELEMENT_SIZE) return set_error(serror, SCRIPT_ERR_PUSH_SIZE); |
| 1871 | } |
| 1872 | |
| 1873 | // Run the script interpreter. |
| 1874 | if (!EvalScript(stack, exec_script, flags, checker, sigversion, execdata, serror)) return false; |
| 1875 | |
| 1876 | // Scripts inside witness implicitly require cleanstack behaviour |
| 1877 | if (stack.size() != 1) return set_error(serror, SCRIPT_ERR_CLEANSTACK); |
| 1878 | if (!CastToBool(stack.back())) return set_error(serror, SCRIPT_ERR_EVAL_FALSE); |
| 1879 | return true; |
| 1880 | } |
| 1881 | |
| 1882 | uint256 ComputeTapleafHash(uint8_t leaf_version, std::span<const unsigned char> script) |
| 1883 | { |
no test coverage detected