Bitcoin ABC 0.30.7
P2P Digital Currency
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
iguana_interpreter.cpp
Go to the documentation of this file.
1// Copyright (c) 2024 The Bitcoin developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
8#include <streams.h>
9
10#include <tinyformat.h>
11
13 const CTxIn &txin = tx.vin[inputIndex];
14
15 const bool isSigPushOnly = flags & SCRIPT_VERIFY_SIGPUSHONLY;
16
17 std::vector<std::vector<uint8_t>> stack;
18
19 IguanaResult result;
20 {
21 ScriptInterpreter interpreter(stack, txin.scriptSig, flags, sigChecker,
22 result.metrics);
23 result.traceScriptSig = RunScript(interpreter, isSigPushOnly);
25 return result;
26 }
27 }
28
29 std::vector<std::vector<uint8_t>> stackCopy = stack;
30
31 {
33 result.metrics);
34 result.traceScriptPubKey = RunScript(interpreter, false);
36 return result;
37 }
38 }
39
40 if (stack.empty() || CastToBool(stack.back()) == false) {
42 return result;
43 }
44
45 IguanaTrace *lastTrace = &result.traceScriptPubKey;
46
48 result.traceRedeemScript.emplace();
49 if (!txin.scriptSig.IsPushOnly()) {
50 result.traceRedeemScript->scriptError = ScriptError::SIG_PUSHONLY;
51 return result;
52 }
53
54 swap(stack, stackCopy);
55 const std::vector<uint8_t> &redeemScriptRaw = stack.back();
56 CScript redeemScript(redeemScriptRaw.begin(), redeemScriptRaw.end());
57 stack.pop_back();
58
59 if ((flags & SCRIPT_DISALLOW_SEGWIT_RECOVERY) == 0 && stack.empty() &&
60 redeemScript.IsWitnessProgram()) {
61 // Allow SegWit recovery; doesn't run redeemScript
62 result.traceRedeemScript = std::nullopt;
63 return result;
64 }
65
66 ScriptInterpreter interpreter(stack, redeemScript, flags, sigChecker,
67 result.metrics);
68 result.traceRedeemScript = RunScript(interpreter, false);
69
70 if (result.traceRedeemScript->scriptError != ScriptError::OK) {
71 return result;
72 }
73
74 if (stack.empty() || CastToBool(stack.back()) == false) {
75 result.traceRedeemScript->scriptError = ScriptError::EVAL_FALSE;
76 return result;
77 }
78 lastTrace = &*result.traceRedeemScript;
79 }
80
81 if ((flags & SCRIPT_VERIFY_CLEANSTACK) != 0) {
82 if (stack.size() != 1) {
84 return result;
85 }
86 }
87
89 if (int(txin.scriptSig.size()) < result.metrics.nSigChecks * 43 - 60) {
91 return result;
92 }
93 }
94
95 return result;
96}
97
99 bool isPushOnly) const {
100 IguanaTrace trace;
102 trace.initialStacks.stack = interpreter.GetStack();
103 trace.initialStacks.altstack = interpreter.GetAltStack();
104 try {
105 while (!interpreter.IsAtEnd()) {
106 IguanaTraceEntry nextEntry;
107 if (!interpreter.GetNextOp(nextEntry.opcode, nextEntry.pushdata)) {
108 // Override message for invalid encoding, since an unknown
109 // opcode also results in BAD_OPCODE
110 trace.errorMsg = "Invalidly encoded opcode";
112 return trace;
113 }
114
115 IguanaTraceEntry &entry = trace.entries.emplace_back(nextEntry);
116
117 if (isPushOnly && entry.opcode > OP_16) {
119 return trace;
120 }
121 if (!interpreter.RunNextOp()) {
122 trace.scriptError = interpreter.GetScriptError();
123 return trace;
124 }
125
126 entry.stacks.stack = interpreter.GetStack();
127 entry.stacks.altstack = interpreter.GetAltStack();
128 }
129 } catch (std::exception &ex) {
130 trace.errorMsg = strprintf("Exception: %s", ex.what());
131 return trace;
132 }
134 return trace;
135}
std::vector< CTxIn > vin
Definition: transaction.h:276
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:424
bool IsPushOnly(const_iterator pc) const
Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical).
Definition: script.cpp:404
bool IsPayToScriptHash() const
Definition: script.cpp:373
bool IsWitnessProgram(int &version, std::vector< uint8_t > &program) const
Definition: script.cpp:381
An input of a transaction.
Definition: transaction.h:59
CScript scriptSig
Definition: transaction.h:62
IguanaTrace RunScript(ScriptInterpreter &interpreter, bool isPushOnly) const
IguanaResult Run() const
Run the interpreter, stepping through the scripts and return the trace.
CMutableTransaction tx
MutableTransactionSignatureChecker sigChecker
const std::vector< std::vector< uint8_t > > & GetStack() const
Definition: interpreter.h:158
const std::vector< std::vector< uint8_t > > & GetAltStack() const
Definition: interpreter.h:161
ScriptError GetScriptError()
Definition: interpreter.h:155
bool GetNextOp(opcodetype &opcodeRet, std::vector< uint8_t > &vchRet) const
size_type size() const
Definition: prevector.h:394
bool CastToBool(const valtype &vch)
Definition: interpreter.cpp:19
@ OP_16
Definition: script.h:72
@ SCRIPT_VERIFY_P2SH
Definition: script_flags.h:16
@ SCRIPT_VERIFY_SIGPUSHONLY
Definition: script_flags.h:35
@ SCRIPT_VERIFY_CLEANSTACK
Definition: script_flags.h:63
@ SCRIPT_DISALLOW_SEGWIT_RECOVERY
Definition: script_flags.h:93
@ SCRIPT_VERIFY_INPUT_SIGCHECKS
Definition: script_flags.h:103
IguanaTrace traceScriptSig
IguanaTrace traceScriptPubKey
ScriptExecutionMetrics metrics
std::optional< IguanaTrace > traceRedeemScript
std::vector< std::vector< uint8_t > > stack
std::vector< std::vector< uint8_t > > altstack
IguanaStacks stacks
opcodetype opcode
std::vector< uint8_t > pushdata
std::vector< IguanaTraceEntry > entries
std::string errorMsg
IguanaStacks initialStacks
ScriptError scriptError
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1202