Skip to content
Bitcoin Roots

v30.3-roots.1 · Commit 7: [PATCH 07/68] build: adapt Roots maintenance and assurance to Core 30.3

src/policy/policy.cpp

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

File metadata
index 79f46f540f7fbdfb71284714eeec68374a292dd9..3f2353c0604cf04365dfcc539d081309847d9c6c 100644

Download original patch · Release notes

Diff rows 1–178 of 178. 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
@@ -11,7 +11,6 @@
11
  #include <consensus/amount.h>
12
  #include <consensus/consensus.h>
13
  #include <consensus/validation.h>
14
- #include <kernel/mempool_options.h>
15
  #include <policy/feerate.h>
16
  #include <policy/settings.h>
17
  #include <primitives/transaction.h>
@@ -27,8 +26,6 @@
27
  #include <utility>
28
  #include <vector>
29
 
30
- unsigned int g_script_size_policy_limit{MAX_SCRIPT_SIZE};
31
-
32
  CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
33
  {
34
  // "Dust" is defined in terms of dustRelayFee,
@@ -121,7 +118,91 @@ static inline bool MaybeReject_(std::string& out_reason, const std::string& reas
121
  } \
122
  } while(0)
123
 
124
- bool IsStandardTx(const CTransaction& tx, const kernel::MemPoolOptions& opts, std::string& out_reason, const ignore_rejects_type& ignore_rejects)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  {
126
  const std::string reason_prefix;
127
 
@@ -216,7 +297,7 @@ bool IsStandardTx(const CTransaction& tx, const kernel::MemPoolOptions& opts, st
216
  else if ((whichType == TxoutType::MULTISIG) && (!opts.permit_bare_multisig)) {
217
  MaybeReject("bare-multisig");
218
  }
219
- else if (whichType == TxoutType::WITNESS_V0_SCRIPTHASH && opts.reject_tokens && txout.scriptPubKey.IsOLGA(tx.vout.size() - i)) {
220
  MaybeReject("tokens-olga");
221
  }
222
  }
@@ -245,7 +326,7 @@ bool IsStandardTx(const CTransaction& tx, const kernel::MemPoolOptions& opts, st
245
 
246
  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)
247
  {
248
- kernel::MemPoolOptions opts;
249
  opts.max_datacarrier_bytes = max_datacarrier_bytes;
250
  opts.permit_bare_multisig = permit_bare_multisig;
251
  opts.dust_relay_feerate = dust_relay_feerate;
@@ -255,7 +336,7 @@ bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_dat
255
  /**
256
  * Check the total number of non-witness sigops across the whole transaction, as per BIP54.
257
  */
258
- static bool CheckSigopsBIP54(const CTransaction& tx, const CCoinsViewCache& inputs, const kernel::MemPoolOptions& opts)
259
  {
260
  Assert(!tx.IsCoinBase());
261
 
@@ -299,7 +380,7 @@ static bool CheckSigopsBIP54(const CTransaction& tx, const CCoinsViewCache& inpu
299
  *
300
  * We also check the total number of non-witness sigops across the whole transaction, as per BIP54.
301
  */
302
- bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs, const kernel::MemPoolOptions& opts, const std::string& reason_prefix, std::string& out_reason, const ignore_rejects_type& ignore_rejects)
303
  {
304
  if (tx.IsCoinBase()) {
305
  return true; // Coinbases don't use vin normally
@@ -362,7 +443,7 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs,
362
 
363
  bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& map_inputs)
364
  {
365
- kernel::MemPoolOptions opts;
366
  std::string reason;
367
  return AreInputsStandard(tx, map_inputs, opts, "", reason);
368
  }
@@ -586,13 +667,13 @@ std::pair<size_t, size_t> DatacarrierBytes(const CTransaction& tx, const CCoinsV
586
  for (const CTxIn& txin : tx.vin) {
587
  const CTxOut &utxo = view.AccessCoin(txin.prevout).out;
588
  auto[script, consensus_weight_per_byte] = GetScriptForTransactionInput(utxo.scriptPubKey, txin);
589
- const auto dcb = script.DatacarrierBytes(0, &txin.scriptWitness);
590
  ret.first += dcb.first;
591
  ret.second += dcb.second;
592
  }
593
  for (size_t i{tx.vout.size()}; i; ) {
594
  const CTxOut& txout = tx.vout[--i];
595
- const auto dcb = txout.scriptPubKey.DatacarrierBytes(tx.vout.size() - i);
596
  ret.first += dcb.first;
597
  ret.second += dcb.second;
598
  }
@@ -610,14 +691,14 @@ int32_t CalculateExtraTxWeight(const CTransaction& tx, const CCoinsViewCache& vi
610
  const CTxOut &utxo = view.AccessCoin(txin.prevout).out;
611
  auto[script, consensus_weight_per_byte] = GetScriptForTransactionInput(utxo.scriptPubKey, txin);
612
  if (weight_per_data_byte > consensus_weight_per_byte) {
613
- const auto dcb = script.DatacarrierBytes(0, &txin.scriptWitness);
614
  mod_weight += int64_t(dcb.first + dcb.second) * (weight_per_data_byte - consensus_weight_per_byte);
615
  }
616
  }
617
  if (weight_per_data_byte > WITNESS_SCALE_FACTOR) {
618
  for (size_t i{tx.vout.size()}; i; ) {
619
  const CTxOut& txout = tx.vout[--i];
620
- const auto dcb = txout.scriptPubKey.DatacarrierBytes(tx.vout.size() - i);
621
  mod_weight += int64_t(dcb.first + dcb.second) * (weight_per_data_byte - WITNESS_SCALE_FACTOR);
622
  }
623
  }
 
11
  #include <consensus/amount.h>
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>
 
26
  #include <utility>
27
  #include <vector>
28
 
 
 
29
  CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
30
  {
31
  // "Dust" is defined in terms of dustRelayFee,
 
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
 
 
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
  }
 
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;
 
336
  /**
337
  * Check the total number of non-witness sigops across the whole transaction, as per BIP54.
338
  */
339
+ static bool CheckSigopsBIP54(const CTransaction& tx, const CCoinsViewCache& inputs, const StandardnessOptions& opts)
340
  {
341
  Assert(!tx.IsCoinBase());
342
 
 
380
  *
381
  * We also check the total number of non-witness sigops across the whole transaction, as per BIP54.
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
 
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
  }
 
667
  for (const CTxIn& txin : tx.vin) {
668
  const CTxOut &utxo = view.AccessCoin(txin.prevout).out;
669
  auto[script, consensus_weight_per_byte] = GetScriptForTransactionInput(utxo.scriptPubKey, txin);
670
+ const auto dcb = ScriptDatacarrierBytes(script, 0, &txin.scriptWitness);
671
  ret.first += dcb.first;
672
  ret.second += dcb.second;
673
  }
674
  for (size_t i{tx.vout.size()}; i; ) {
675
  const CTxOut& txout = tx.vout[--i];
676
+ const auto dcb = ScriptDatacarrierBytes(txout.scriptPubKey, tx.vout.size() - i);
677
  ret.first += dcb.first;
678
  ret.second += dcb.second;
679
  }
 
691
  const CTxOut &utxo = view.AccessCoin(txin.prevout).out;
692
  auto[script, consensus_weight_per_byte] = GetScriptForTransactionInput(utxo.scriptPubKey, txin);
693
  if (weight_per_data_byte > consensus_weight_per_byte) {
694
+ const auto dcb = ScriptDatacarrierBytes(script, 0, &txin.scriptWitness);
695
  mod_weight += int64_t(dcb.first + dcb.second) * (weight_per_data_byte - consensus_weight_per_byte);
696
  }
697
  }
698
  if (weight_per_data_byte > WITNESS_SCALE_FACTOR) {
699
  for (size_t i{tx.vout.size()}; i; ) {
700
  const CTxOut& txout = tx.vout[--i];
701
+ const auto dcb = ScriptDatacarrierBytes(txout.scriptPubKey, tx.vout.size() - i);
702
  mod_weight += int64_t(dcb.first + dcb.second) * (weight_per_data_byte - WITNESS_SCALE_FACTOR);
703
  }
704
  }