Skip to content
Bitcoin Roots

v31.1-roots.1 · Commit 2: [PATCH 02/17] feat(policy): preserve Roots parsing and local transaction checks

src/policy/policy.cpp

Before: src/policy/policy.cpp · After: src/policy/policy.cpp

File metadata
index 46ec238c3b18fd1c0a5ce35f25d1b619317dafda..d0455dd98cedea3adbc884b10ed5a1e58c570eb1 100644

Download original patch · Release notes

Diff rows 1–400 of 550. Line numbers refer to the original before/after files.

+ Added− RemovedUnmarked lines are context.

Scroll the code area horizontally to read long lines. Before is on the left; after is on the right. Unified view fits narrow screens more easily.

src/policy/policy.cpp CHANGED
@@ -12,6 +12,7 @@
12
  #include <consensus/consensus.h>
13
  #include <consensus/validation.h>
14
  #include <policy/feerate.h>
 
15
  #include <primitives/transaction.h>
16
  #include <script/interpreter.h>
17
  #include <script/script.h>
@@ -21,6 +22,8 @@
21
 
22
  #include <algorithm>
23
  #include <cstddef>
 
 
24
  #include <vector>
25
 
26
  CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
@@ -42,7 +45,7 @@ CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
42
  if (txout.scriptPubKey.IsUnspendable())
43
  return 0;
44
 
45
- uint64_t nSize{GetSerializeSize(txout)};
46
  int witnessversion = 0;
47
  std::vector<unsigned char> witnessprogram;
48
 
@@ -76,6 +79,10 @@ std::vector<uint32_t> GetDust(const CTransaction& tx, CFeeRate dust_relay_rate)
76
  return dust_outputs;
77
  }
78
 
 
 
 
 
79
  bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType)
80
  {
81
  std::vector<std::vector<unsigned char> > vSolutions;
@@ -96,11 +103,111 @@ bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType)
96
  return true;
97
  }
98
 
99
- bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  if (tx.version > TX_MAX_STANDARD_VERSION || tx.version < TX_MIN_STANDARD_VERSION) {
102
- reason = "version";
103
- return false;
104
  }
105
 
106
  // Extremely large transactions with lots of inputs can cost the network
@@ -109,8 +216,11 @@ bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_dat
109
  // to MAX_STANDARD_TX_WEIGHT mitigates CPU exhaustion attacks.
110
  unsigned int sz = GetTransactionWeight(tx);
111
  if (sz > MAX_STANDARD_TX_WEIGHT) {
112
- reason = "tx-size";
113
- return false;
 
 
 
114
  }
115
 
116
  for (const CTxIn& txin : tx.vin)
@@ -123,50 +233,110 @@ bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_dat
123
  // some minor future-proofing. That's also enough to spend a
124
  // 20-of-20 CHECKMULTISIG scriptPubKey, though such a scriptPubKey
125
  // is not considered standard.
126
- if (txin.scriptSig.size() > MAX_STANDARD_SCRIPTSIG_SIZE) {
127
- reason = "scriptsig-size";
128
- return false;
129
  }
130
  if (!txin.scriptSig.IsPushOnly()) {
131
- reason = "scriptsig-not-pushonly";
132
- return false;
133
  }
134
  }
135
 
136
- unsigned int datacarrier_bytes_left = max_datacarrier_bytes.value_or(0);
 
 
 
137
  TxoutType whichType;
138
- for (const CTxOut& txout : tx.vout) {
 
 
 
 
 
 
139
  if (!::IsStandard(txout.scriptPubKey, whichType)) {
140
- reason = "scriptpubkey";
141
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  }
143
 
144
  if (whichType == TxoutType::NULL_DATA) {
145
- unsigned int size = txout.scriptPubKey.size();
146
  if (size > datacarrier_bytes_left) {
147
- reason = "datacarrier";
148
- return false;
 
 
149
  }
150
- datacarrier_bytes_left -= size;
151
- } else if ((whichType == TxoutType::MULTISIG) && (!permit_bare_multisig)) {
152
- reason = "bare-multisig";
153
- return false;
 
 
 
 
 
 
 
 
 
 
154
  }
155
  }
156
 
157
  // Only MAX_DUST_OUTPUTS_PER_TX dust is permitted(on otherwise valid ephemeral dust)
158
- if (GetDust(tx, dust_relay_fee).size() > MAX_DUST_OUTPUTS_PER_TX) {
159
- reason = "dust";
160
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  }
162
 
163
  return true;
164
  }
165
 
 
 
 
 
 
 
 
 
 
166
  /**
167
- * Check the total number of non-witness sigops across the whole transaction, as per BIP54.
168
  */
169
- static bool CheckSigopsBIP54(const CTransaction& tx, const CCoinsViewCache& inputs)
170
  {
171
  Assert(!tx.IsCoinBase());
172
 
@@ -184,7 +354,7 @@ static bool CheckSigopsBIP54(const CTransaction& tx, const CCoinsViewCache& inpu
184
  sigops += txin.scriptSig.GetSigOpCount(/*fAccurate=*/true);
185
  sigops += prev_txo.scriptPubKey.GetSigOpCount(txin.scriptSig);
186
 
187
- if (sigops > MAX_TX_LEGACY_SIGOPS) {
188
  return false;
189
  }
190
  }
@@ -208,39 +378,62 @@ static bool CheckSigopsBIP54(const CTransaction& tx, const CCoinsViewCache& inpu
208
  *
209
  * Note that only the non-witness portion of the transaction is checked here.
210
  *
211
- * We also check the total number of non-witness sigops across the whole transaction, as per BIP54.
212
  */
213
- bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
214
  {
215
  if (tx.IsCoinBase()) {
216
  return true; // Coinbases don't use vin normally
217
  }
218
 
219
- if (!CheckSigopsBIP54(tx, mapInputs)) {
220
- return false;
221
  }
222
 
223
  for (unsigned int i = 0; i < tx.vin.size(); i++) {
224
  const CTxOut& prev = mapInputs.AccessCoin(tx.vin[i].prevout).out;
225
 
 
 
 
 
226
  std::vector<std::vector<unsigned char> > vSolutions;
227
  TxoutType whichType = Solver(prev.scriptPubKey, vSolutions);
228
- if (whichType == TxoutType::NONSTANDARD || whichType == TxoutType::WITNESS_UNKNOWN) {
 
 
229
  // WITNESS_UNKNOWN failures are typically also caught with a policy
230
  // flag in the script interpreter, but it can be helpful to catch
231
  // this type of NONSTANDARD transaction earlier in transaction
232
  // validation.
233
- return false;
234
  } else if (whichType == TxoutType::SCRIPTHASH) {
 
 
 
 
 
 
235
  std::vector<std::vector<unsigned char> > stack;
236
  // convert the scriptSig into a stack, so we can inspect the redeemScript
237
  if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SigVersion::BASE))
 
 
 
238
  return false;
 
239
  if (stack.empty())
 
 
 
240
  return false;
 
241
  CScript subscript(stack.back().begin(), stack.back().end());
 
 
 
242
  if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) {
243
- return false;
244
  }
245
  }
246
  }
@@ -248,7 +441,14 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
248
  return true;
249
  }
250
 
251
- bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
 
 
 
 
 
 
 
252
  {
253
  if (tx.IsCoinBase())
254
  return true; // Coinbases are skipped
@@ -267,7 +467,7 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
267
 
268
  // witness stuffing detected
269
  if (prevScript.IsPayToAnchor()) {
270
- return false;
271
  }
272
 
273
  bool p2sh = false;
@@ -277,9 +477,15 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
277
  // into a stack. We do not check IsPushOnly nor compare the hash as these will be done later anyway.
278
  // If the check fails at this stage, we know that this txid must be a bad one.
279
  if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SigVersion::BASE))
 
 
280
  return false;
 
281
  if (stack.empty())
 
 
12
  #include <consensus/consensus.h>
13
  #include <consensus/validation.h>
14
  #include <policy/feerate.h>
15
+ #include <policy/settings.h>
16
  #include <primitives/transaction.h>
17
  #include <script/interpreter.h>
18
  #include <script/script.h>
 
22
 
23
  #include <algorithm>
24
  #include <cstddef>
25
+ #include <limits>
26
+ #include <utility>
27
  #include <vector>
28
 
29
  CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
 
45
  if (txout.scriptPubKey.IsUnspendable())
46
  return 0;
47
 
48
+ size_t nSize = GetSerializeSize(txout);
49
  int witnessversion = 0;
50
  std::vector<unsigned char> witnessprogram;
51
 
 
79
  return dust_outputs;
80
  }
81
 
82
+ /**
83
+ * Note this must assign whichType even if returning false, in case
84
+ * IsStandardTx ignores the "scriptpubkey" rejection.
85
+ */
86
  bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType)
87
  {
88
  std::vector<std::vector<unsigned char> > vSolutions;
 
103
  return true;
104
  }
105
 
106
+ static inline bool MaybeReject_(std::string& out_reason, const std::string& reason, const std::string& reason_prefix, const ignore_rejects_type& ignore_rejects) {
107
+ if (ignore_rejects.count(reason_prefix + reason)) {
108
+ return false;
109
+ }
110
+
111
+ out_reason = reason_prefix + reason;
112
+ return true;
113
+ }
114
+
115
+ #define MaybeReject(reason) do { \
116
+ if (MaybeReject_(out_reason, reason, reason_prefix, ignore_rejects)) { \
117
+ return false; \
118
+ } \
119
+ } while(0)
120
+
121
+ namespace {
122
+ size_t OlgaBytes(const CScript& script, size_t remaining_outputs)
123
+ {
124
+ if (!script.IsPayToWitnessScriptHash()) return 0;
125
+
126
+ const size_t payload_size{(size_t{script[2]} << 8) | script[3]};
127
+ const size_t outputs{(payload_size + 1) / WITNESS_V0_SCRIPTHASH_SIZE + 1};
128
+ if (remaining_outputs < outputs) return 0;
129
+ if ((script[4] | 0x20) != 's' || (script[5] | 0x20) != 't' ||
130
+ (script[6] | 0x20) != 'a' || (script[7] | 0x20) != 'm' ||
131
+ (script[8] | 0x20) != 'p' || script[9] != ':') {
132
+ return 0;
133
+ }
134
+ return outputs * (WITNESS_V0_SCRIPTHASH_SIZE + 1 + 8);
135
+ }
136
+
137
+ size_t OpNetWitnessBytes(const CScriptWitness& witness)
138
+ {
139
+ const auto& stack{witness.stack};
140
+ if (stack.size() != 5 || stack[4].size() != 65) return 0;
141
+
142
+ const CScript tapscript{stack[3].begin(), stack[3].end()};
143
+ bool found_opnet{false};
144
+ size_t deduct{0};
145
+ CScript::const_iterator pc{tapscript.begin()};
146
+ opcodetype opcode{OP_INVALIDOPCODE};
147
+ opcodetype last_opcode{OP_INVALIDOPCODE};
148
+ std::vector<unsigned char> data;
149
+ while (pc < tapscript.end()) {
150
+ last_opcode = opcode;
151
+ if (!tapscript.GetOp(pc, opcode, data)) break;
152
+ if (data.size() == 2 && data[0] == 0x6f && data[1] == 0x70) found_opnet = true;
153
+ if (opcode == OP_CHECKSIGVERIFY && last_opcode == 0x20) deduct += 34;
154
+ }
155
+ return found_opnet ? stack[0].size() + stack[3].size() - deduct : 0;
156
+ }
157
+
158
+ std::pair<size_t, size_t> ScriptDatacarrierBytes(const CScript& script, size_t remaining_outputs, const CScriptWitness* witness = nullptr)
159
  {
160
+ if (const size_t olga_bytes{OlgaBytes(script, remaining_outputs)}; olga_bytes) return {0, olga_bytes};
161
+ if (witness) {
162
+ if (const size_t opnet_bytes{OpNetWitnessBytes(*witness)}; opnet_bytes) return {0, opnet_bytes};
163
+ }
164
+
165
+ size_t counted{0};
166
+ opcodetype opcode{OP_INVALIDOPCODE};
167
+ opcodetype last_opcode{OP_INVALIDOPCODE};
168
+ std::vector<unsigned char> push_data;
169
+ unsigned int inside_noop{0};
170
+ unsigned int inside_conditional{0};
171
+ CScript::const_iterator opcode_it{script.begin()};
172
+ CScript::const_iterator data_began{script.begin()};
173
+ for (CScript::const_iterator it{script.begin()}; it < script.end(); last_opcode = opcode) {
174
+ opcode_it = it;
175
+ if (!script.GetOp(it, opcode, push_data)) return {0, script.size()};
176
+
177
+ if (opcode == OP_IF || opcode == OP_NOTIF) {
178
+ ++inside_conditional;
179
+ } else if (opcode == OP_ENDIF) {
180
+ if (!inside_conditional) return {0, script.size()};
181
+ --inside_conditional;
182
+ } else if (opcode == OP_RETURN && !inside_conditional) {
183
+ return {script.size(), 0};
184
+ }
185
+
186
+ if (inside_noop) {
187
+ if (opcode == OP_IF || opcode == OP_NOTIF) {
188
+ ++inside_noop;
189
+ } else if (opcode == OP_ENDIF && --inside_noop == 0) {
190
+ counted += it - data_began + 1;
191
+ }
192
+ } else if (opcode == OP_IF && last_opcode == OP_FALSE) {
193
+ inside_noop = 1;
194
+ data_began = opcode_it;
195
+ } else if (opcode <= OP_PUSHDATA4) {
196
+ data_began = opcode_it;
197
+ } else if (opcode == OP_DROP && last_opcode <= OP_PUSHDATA4) {
198
+ counted += it - data_began;
199
+ }
200
+ }
201
+ return {0, counted};
202
+ }
203
+ } // namespace
204
+
205
+ bool IsStandardTx(const CTransaction& tx, const StandardnessOptions& opts, std::string& out_reason, const ignore_rejects_type& ignore_rejects)
206
+ {
207
+ const std::string reason_prefix;
208
+
209
  if (tx.version > TX_MAX_STANDARD_VERSION || tx.version < TX_MIN_STANDARD_VERSION) {
210
+ MaybeReject("version");
 
211
  }
212
 
213
  // Extremely large transactions with lots of inputs can cost the network
 
216
  // to MAX_STANDARD_TX_WEIGHT mitigates CPU exhaustion attacks.
217
  unsigned int sz = GetTransactionWeight(tx);
218
  if (sz > MAX_STANDARD_TX_WEIGHT) {
219
+ MaybeReject("tx-size");
220
+ }
221
+
222
+ if (tx.nLockTime == PARASITE_CAT21_LOCKTIME && opts.reject_parasites) {
223
+ MaybeReject("parasite-cat21");
224
  }
225
 
226
  for (const CTxIn& txin : tx.vin)
 
233
  // some minor future-proofing. That's also enough to spend a
234
  // 20-of-20 CHECKMULTISIG scriptPubKey, though such a scriptPubKey
235
  // is not considered standard.
236
+ if (txin.scriptSig.size() > std::min(MAX_STANDARD_SCRIPTSIG_SIZE, g_script_size_policy_limit)) {
237
+ MaybeReject("scriptsig-size");
 
238
  }
239
  if (!txin.scriptSig.IsPushOnly()) {
240
+ MaybeReject("scriptsig-not-pushonly");
 
241
  }
242
  }
243
 
244
+ unsigned int datacarrier_bytes_left = opts.max_datacarrier_bytes.value_or(0);
245
+ unsigned int nDataOut = 0;
246
+ unsigned int n_dust{0};
247
+ unsigned int n_monetary{0};
248
  TxoutType whichType;
249
+ for (size_t i{tx.vout.size()}; i; ) {
250
+ const CTxOut& txout = tx.vout[--i];
251
+
252
+ if (txout.scriptPubKey.size() > g_script_size_policy_limit) {
253
+ MaybeReject("scriptpubkey-size");
254
+ }
255
+
256
  if (!::IsStandard(txout.scriptPubKey, whichType)) {
257
+ MaybeReject("scriptpubkey");
258
+ }
259
+
260
+ if (whichType == TxoutType::WITNESS_UNKNOWN && !opts.acceptunknownwitness) {
261
+ MaybeReject("scriptpubkey-unknown-witnessversion");
262
+ }
263
+
264
+ if (whichType == TxoutType::ANCHOR && !opts.permitephemeral_anchor) {
265
+ MaybeReject("anchor");
266
+ }
267
+
268
+ if (IsDust(txout, opts.dust_relay_feerate)) {
269
+ if (whichType != TxoutType::ANCHOR && !opts.permitephemeral_send) {
270
+ MaybeReject("dust-nonanchor");
271
+ }
272
+ if (txout.nValue && !opts.permitephemeral_dust) {
273
+ MaybeReject("dust-nonzero");
274
+ }
275
+ ++n_dust;
276
+ } else if (whichType != TxoutType::NULL_DATA) {
277
+ ++n_monetary;
278
  }
279
 
280
  if (whichType == TxoutType::NULL_DATA) {
281
+ const auto size = txout.scriptPubKey.size();
282
  if (size > datacarrier_bytes_left) {
283
+ MaybeReject("datacarrier");
284
+ datacarrier_bytes_left = 0;
285
+ } else {
286
+ datacarrier_bytes_left -= size;
287
  }
288
+ if (txout.scriptPubKey.size() > 2 && txout.scriptPubKey[1] == OP_13 && opts.reject_tokens) {
289
+ MaybeReject("tokens-runes");
290
+ }
291
+ nDataOut++;
292
+ continue;
293
+ }
294
+ else if ((whichType == TxoutType::PUBKEY) && (!opts.permit_bare_pubkey)) {
295
+ MaybeReject("bare-pubkey");
296
+ }
297
+ else if ((whichType == TxoutType::MULTISIG) && (!opts.permit_bare_multisig)) {
298
+ MaybeReject("bare-multisig");
299
+ }
300
+ else if (whichType == TxoutType::WITNESS_V0_SCRIPTHASH && opts.reject_tokens && OlgaBytes(txout.scriptPubKey, tx.vout.size() - i)) {
301
+ MaybeReject("tokens-olga");
302
  }
303
  }
304
 
305
  // Only MAX_DUST_OUTPUTS_PER_TX dust is permitted(on otherwise valid ephemeral dust)
306
+ if (n_dust > MAX_DUST_OUTPUTS_PER_TX) {
307
+ MaybeReject("dust");
308
+ }
309
+
310
+ // only one OP_RETURN txout is permitted
311
+ if (nDataOut > 1) {
312
+ MaybeReject("multi-op-return");
313
+ }
314
+
315
+ if (!n_monetary) {
316
+ if (nDataOut && !opts.permitbaredatacarrier) {
317
+ MaybeReject("bare-datacarrier");
318
+ }
319
+ if ((!nDataOut) && !opts.permitbareanchor) {
320
+ MaybeReject("bare-anchor");
321
+ }
322
  }
323
 
324
  return true;
325
  }
326
 
327
+ bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate& dust_relay_feerate, std::string& out_reason)
328
+ {
329
+ StandardnessOptions opts;
330
+ opts.max_datacarrier_bytes = max_datacarrier_bytes;
331
+ opts.permit_bare_multisig = permit_bare_multisig;
332
+ opts.dust_relay_feerate = dust_relay_feerate;
333
+ return IsStandardTx(tx, opts, out_reason);
334
+ }
335
+
336
  /**
337
+ * Check the local transaction limit for potentially executed legacy sigops.
338
  */
339
+ static bool CheckLegacyPolicySigops(const CTransaction& tx, const CCoinsViewCache& inputs, const StandardnessOptions& opts)
340
  {
341
  Assert(!tx.IsCoinBase());
342
 
 
354
  sigops += txin.scriptSig.GetSigOpCount(/*fAccurate=*/true);
355
  sigops += prev_txo.scriptPubKey.GetSigOpCount(txin.scriptSig);
356
 
357
+ if (sigops > opts.maxtxlegacysigops) {
358
  return false;
359
  }
360
  }
 
378
  *
379
  * Note that only the non-witness portion of the transaction is checked here.
380
  *
381
+ * We also check the local transaction limit for potentially executed legacy sigops.
382
  */
383
+ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs, const StandardnessOptions& opts, const std::string& reason_prefix, std::string& out_reason, const ignore_rejects_type& ignore_rejects)
384
  {
385
  if (tx.IsCoinBase()) {
386
  return true; // Coinbases don't use vin normally
387
  }
388
 
389
+ if (!CheckLegacyPolicySigops(tx, mapInputs, opts)) {
390
+ MaybeReject("sigops-toomany-overall");
391
  }
392
 
393
  for (unsigned int i = 0; i < tx.vin.size(); i++) {
394
  const CTxOut& prev = mapInputs.AccessCoin(tx.vin[i].prevout).out;
395
 
396
+ if (prev.scriptPubKey.size() > g_script_size_policy_limit) {
397
+ MaybeReject("script-size");
398
+ }
399
+
400
  std::vector<std::vector<unsigned char> > vSolutions;
401
  TxoutType whichType = Solver(prev.scriptPubKey, vSolutions);
402
+ if (whichType == TxoutType::NONSTANDARD) {
403
+ MaybeReject("script-unknown");
404
+ } else if (whichType == TxoutType::WITNESS_UNKNOWN) {
405
  // WITNESS_UNKNOWN failures are typically also caught with a policy
406
  // flag in the script interpreter, but it can be helpful to catch
407
  // this type of NONSTANDARD transaction earlier in transaction
408
  // validation.
409
+ MaybeReject("witness-unknown");
410
  } else if (whichType == TxoutType::SCRIPTHASH) {
411
+ if (!tx.vin[i].scriptSig.IsPushOnly()) {
412
+ // The only way we got this far, is if the user ignored scriptsig-not-pushonly.
413
+ // However, this case is invalid, and will be caught later on.
414
+ // But for now, we don't want to run the [possibly expensive] script here.
415
+ continue;
416
+ }
417
  std::vector<std::vector<unsigned char> > stack;
418
  // convert the scriptSig into a stack, so we can inspect the redeemScript
419
  if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SigVersion::BASE))
420
+ {
421
+ // This case is also invalid or a bug
422
+ out_reason = reason_prefix + "scriptsig-failure";
423
  return false;
424
+ }
425
  if (stack.empty())
426
+ {
427
+ // Also invalid
428
+ out_reason = reason_prefix + "scriptcheck-missing";
429
  return false;
430
+ }
431
  CScript subscript(stack.back().begin(), stack.back().end());
432
+ if (subscript.size() > g_script_size_policy_limit) {
433
+ MaybeReject("scriptcheck-size");
434
+ }
435
  if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) {
436
+ MaybeReject("scriptcheck-sigops");
437
  }
438
  }
439
  }
 
441
  return true;
442
  }
443
 
444
+ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& map_inputs)
445
+ {
446
+ StandardnessOptions opts;
447
+ std::string reason;
448
+ return AreInputsStandard(tx, map_inputs, opts, "", reason);
449
+ }
450
+
451
+ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs, const std::string& reason_prefix, std::string& out_reason, const ignore_rejects_type& ignore_rejects)
452
  {
453
  if (tx.IsCoinBase())
454
  return true; // Coinbases are skipped
 
467
 
468
  // witness stuffing detected
469
  if (prevScript.IsPayToAnchor()) {
470
+ MaybeReject("anchor-not-empty");
471
  }
472
 
473
  bool p2sh = false;
 
477
  // into a stack. We do not check IsPushOnly nor compare the hash as these will be done later anyway.
478
  // If the check fails at this stage, we know that this txid must be a bad one.
479
  if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SigVersion::BASE))
480
+ {
481
+ out_reason = reason_prefix + "scriptsig-failure";
482
  return false;
483
+ }
484
  if (stack.empty())
485
+ {