Skip to content
Bitcoin Roots

v29.4-roots.2 · Commit 7: [PATCH 07/21] release: establish Roots maintenance and assurance

src/policy/policy.cpp

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

File metadata
index cc9c5432d52230bcf2657d81d4bb316c83c233d9..b5d3a1436b225716992f271814b37c0d63e0b3db 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,
@@ -125,7 +122,91 @@ static inline bool MaybeReject_(std::string& out_reason, const std::string& reas
125
  } \
126
  } while(0)
127
 
128
- bool IsStandardTx(const CTransaction& tx, const kernel::MemPoolOptions& opts, std::string& out_reason, const ignore_rejects_type& ignore_rejects)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  {
130
  const std::string reason_prefix;
131
 
@@ -212,7 +293,7 @@ bool IsStandardTx(const CTransaction& tx, const kernel::MemPoolOptions& opts, st
212
  else if ((whichType == TxoutType::MULTISIG) && (!opts.permit_bare_multisig)) {
213
  MaybeReject("bare-multisig");
214
  }
215
- else if (whichType == TxoutType::WITNESS_V0_SCRIPTHASH && opts.reject_tokens && txout.scriptPubKey.IsOLGA(tx.vout.size() - i)) {
216
  MaybeReject("tokens-olga");
217
  }
218
  }
@@ -241,7 +322,7 @@ bool IsStandardTx(const CTransaction& tx, const kernel::MemPoolOptions& opts, st
241
 
242
  bool IsStandardTx(const CTransaction& tx, unsigned int max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate& dust_relay_feerate, std::string& out_reason)
243
  {
244
- kernel::MemPoolOptions opts;
245
  opts.max_datacarrier_bytes = max_datacarrier_bytes;
246
  opts.permit_bare_multisig = permit_bare_multisig;
247
  opts.dust_relay_feerate = dust_relay_feerate;
@@ -251,7 +332,7 @@ bool IsStandardTx(const CTransaction& tx, unsigned int max_datacarrier_bytes, bo
251
  /**
252
  * Check the total number of non-witness sigops across the whole transaction, as per BIP54.
253
  */
254
- static bool CheckSigopsBIP54(const CTransaction& tx, const CCoinsViewCache& inputs, const kernel::MemPoolOptions& opts)
255
  {
256
  Assert(!tx.IsCoinBase());
257
 
@@ -297,7 +378,7 @@ static bool CheckSigopsBIP54(const CTransaction& tx, const CCoinsViewCache& inpu
297
  *
298
  * We also check the total number of non-witness sigops across the whole transaction, as per BIP54.
299
  */
300
- 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)
301
  {
302
  if (tx.IsCoinBase()) {
303
  return true; // Coinbases don't use vin normally
@@ -360,7 +441,7 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs,
360
 
361
  bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& map_inputs)
362
  {
363
- kernel::MemPoolOptions opts;
364
  std::string reason;
365
  return AreInputsStandard(tx, map_inputs, opts, "", reason);
366
  }
@@ -584,13 +665,13 @@ std::pair<size_t, size_t> DatacarrierBytes(const CTransaction& tx, const CCoinsV
584
  for (const CTxIn& txin : tx.vin) {
585
  const CTxOut &utxo = view.AccessCoin(txin.prevout).out;
586
  auto[script, consensus_weight_per_byte] = GetScriptForTransactionInput(utxo.scriptPubKey, txin);
587
- const auto dcb = script.DatacarrierBytes(0, &txin.scriptWitness);
588
  ret.first += dcb.first;
589
  ret.second += dcb.second;
590
  }
591
  for (size_t i{tx.vout.size()}; i; ) {
592
  const CTxOut& txout = tx.vout[--i];
593
- const auto dcb = txout.scriptPubKey.DatacarrierBytes(tx.vout.size() - i);
594
  ret.first += dcb.first;
595
  ret.second += dcb.second;
596
  }
@@ -608,14 +689,14 @@ int32_t CalculateExtraTxWeight(const CTransaction& tx, const CCoinsViewCache& vi
608
  const CTxOut &utxo = view.AccessCoin(txin.prevout).out;
609
  auto[script, consensus_weight_per_byte] = GetScriptForTransactionInput(utxo.scriptPubKey, txin);
610
  if (weight_per_data_byte > consensus_weight_per_byte) {
611
- const auto dcb = script.DatacarrierBytes(0, &txin.scriptWitness);
612
  mod_weight += int64_t(dcb.first + dcb.second) * (weight_per_data_byte - consensus_weight_per_byte);
613
  }
614
  }
615
  if (weight_per_data_byte > WITNESS_SCALE_FACTOR) {
616
  for (size_t i{tx.vout.size()}; i; ) {
617
  const CTxOut& txout = tx.vout[--i];
618
- const auto dcb = txout.scriptPubKey.DatacarrierBytes(tx.vout.size() - i);
619
  mod_weight += int64_t(dcb.first + dcb.second) * (weight_per_data_byte - WITNESS_SCALE_FACTOR);
620
  }
621
  }
 
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,
 
122
  } \
123
  } while(0)
124
 
125
+ namespace {
126
+ size_t OlgaBytes(const CScript& script, size_t remaining_outputs)
127
+ {
128
+ if (!script.IsPayToWitnessScriptHash()) return 0;
129
+
130
+ const size_t payload_size{(size_t{script[2]} << 8) | script[3]};
131
+ const size_t outputs{(payload_size + 1) / WITNESS_V0_SCRIPTHASH_SIZE + 1};
132
+ if (remaining_outputs < outputs) return 0;
133
+ if ((script[4] | 0x20) != 's' || (script[5] | 0x20) != 't' ||
134
+ (script[6] | 0x20) != 'a' || (script[7] | 0x20) != 'm' ||
135
+ (script[8] | 0x20) != 'p' || script[9] != ':') {
136
+ return 0;
137
+ }
138
+ return outputs * (WITNESS_V0_SCRIPTHASH_SIZE + 1 + 8);
139
+ }
140
+
141
+ size_t OpNetWitnessBytes(const CScriptWitness& witness)
142
+ {
143
+ const auto& stack{witness.stack};
144
+ if (stack.size() != 5 || stack[4].size() != 65) return 0;
145
+
146
+ const CScript tapscript{stack[3].begin(), stack[3].end()};
147
+ bool found_opnet{false};
148
+ size_t deduct{0};
149
+ CScript::const_iterator pc{tapscript.begin()};
150
+ opcodetype opcode{OP_INVALIDOPCODE};
151
+ opcodetype last_opcode{OP_INVALIDOPCODE};
152
+ std::vector<unsigned char> data;
153
+ while (pc < tapscript.end()) {
154
+ last_opcode = opcode;
155
+ if (!tapscript.GetOp(pc, opcode, data)) break;
156
+ if (data.size() == 2 && data[0] == 0x6f && data[1] == 0x70) found_opnet = true;
157
+ if (opcode == OP_CHECKSIGVERIFY && last_opcode == 0x20) deduct += 34;
158
+ }
159
+ return found_opnet ? stack[0].size() + stack[3].size() - deduct : 0;
160
+ }
161
+
162
+ std::pair<size_t, size_t> ScriptDatacarrierBytes(const CScript& script, size_t remaining_outputs, const CScriptWitness* witness = nullptr)
163
+ {
164
+ if (const size_t olga_bytes{OlgaBytes(script, remaining_outputs)}; olga_bytes) return {0, olga_bytes};
165
+ if (witness) {
166
+ if (const size_t opnet_bytes{OpNetWitnessBytes(*witness)}; opnet_bytes) return {0, opnet_bytes};
167
+ }
168
+
169
+ size_t counted{0};
170
+ opcodetype opcode{OP_INVALIDOPCODE};
171
+ opcodetype last_opcode{OP_INVALIDOPCODE};
172
+ std::vector<unsigned char> push_data;
173
+ unsigned int inside_noop{0};
174
+ unsigned int inside_conditional{0};
175
+ CScript::const_iterator opcode_it{script.begin()};
176
+ CScript::const_iterator data_began{script.begin()};
177
+ for (CScript::const_iterator it{script.begin()}; it < script.end(); last_opcode = opcode) {
178
+ opcode_it = it;
179
+ if (!script.GetOp(it, opcode, push_data)) return {0, script.size()};
180
+
181
+ if (opcode == OP_IF || opcode == OP_NOTIF) {
182
+ ++inside_conditional;
183
+ } else if (opcode == OP_ENDIF) {
184
+ if (!inside_conditional) return {0, script.size()};
185
+ --inside_conditional;
186
+ } else if (opcode == OP_RETURN && !inside_conditional) {
187
+ return {script.size(), 0};
188
+ }
189
+
190
+ if (inside_noop) {
191
+ if (opcode == OP_IF || opcode == OP_NOTIF) {
192
+ ++inside_noop;
193
+ } else if (opcode == OP_ENDIF && --inside_noop == 0) {
194
+ counted += it - data_began + 1;
195
+ }
196
+ } else if (opcode == OP_IF && last_opcode == OP_FALSE) {
197
+ inside_noop = 1;
198
+ data_began = opcode_it;
199
+ } else if (opcode <= OP_PUSHDATA4) {
200
+ data_began = opcode_it;
201
+ } else if (opcode == OP_DROP && last_opcode <= OP_PUSHDATA4) {
202
+ counted += it - data_began;
203
+ }
204
+ }
205
+ return {0, counted};
206
+ }
207
+ } // namespace
208
+
209
+ bool IsStandardTx(const CTransaction& tx, const StandardnessOptions& opts, std::string& out_reason, const ignore_rejects_type& ignore_rejects)
210
  {
211
  const std::string reason_prefix;
212
 
 
293
  else if ((whichType == TxoutType::MULTISIG) && (!opts.permit_bare_multisig)) {
294
  MaybeReject("bare-multisig");
295
  }
296
+ else if (whichType == TxoutType::WITNESS_V0_SCRIPTHASH && opts.reject_tokens && OlgaBytes(txout.scriptPubKey, tx.vout.size() - i)) {
297
  MaybeReject("tokens-olga");
298
  }
299
  }
 
322
 
323
  bool IsStandardTx(const CTransaction& tx, unsigned int max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate& dust_relay_feerate, std::string& out_reason)
324
  {
325
+ StandardnessOptions opts;
326
  opts.max_datacarrier_bytes = max_datacarrier_bytes;
327
  opts.permit_bare_multisig = permit_bare_multisig;
328
  opts.dust_relay_feerate = dust_relay_feerate;
 
332
  /**
333
  * Check the total number of non-witness sigops across the whole transaction, as per BIP54.
334
  */
335
+ static bool CheckSigopsBIP54(const CTransaction& tx, const CCoinsViewCache& inputs, const StandardnessOptions& opts)
336
  {
337
  Assert(!tx.IsCoinBase());
338
 
 
378
  *
379
  * We also check the total number of non-witness sigops across the whole transaction, as per BIP54.
380
  */
381
+ 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)
382
  {
383
  if (tx.IsCoinBase()) {
384
  return true; // Coinbases don't use vin normally
 
441
 
442
  bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& map_inputs)
443
  {
444
+ StandardnessOptions opts;
445
  std::string reason;
446
  return AreInputsStandard(tx, map_inputs, opts, "", reason);
447
  }
 
665
  for (const CTxIn& txin : tx.vin) {
666
  const CTxOut &utxo = view.AccessCoin(txin.prevout).out;
667
  auto[script, consensus_weight_per_byte] = GetScriptForTransactionInput(utxo.scriptPubKey, txin);
668
+ const auto dcb = ScriptDatacarrierBytes(script, 0, &txin.scriptWitness);
669
  ret.first += dcb.first;
670
  ret.second += dcb.second;
671
  }
672
  for (size_t i{tx.vout.size()}; i; ) {
673
  const CTxOut& txout = tx.vout[--i];
674
+ const auto dcb = ScriptDatacarrierBytes(txout.scriptPubKey, tx.vout.size() - i);
675
  ret.first += dcb.first;
676
  ret.second += dcb.second;
677
  }
 
689
  const CTxOut &utxo = view.AccessCoin(txin.prevout).out;
690
  auto[script, consensus_weight_per_byte] = GetScriptForTransactionInput(utxo.scriptPubKey, txin);
691
  if (weight_per_data_byte > consensus_weight_per_byte) {
692
+ const auto dcb = ScriptDatacarrierBytes(script, 0, &txin.scriptWitness);
693
  mod_weight += int64_t(dcb.first + dcb.second) * (weight_per_data_byte - consensus_weight_per_byte);
694
  }
695
  }
696
  if (weight_per_data_byte > WITNESS_SCALE_FACTOR) {
697
  for (size_t i{tx.vout.size()}; i; ) {
698
  const CTxOut& txout = tx.vout[--i];
699
+ const auto dcb = ScriptDatacarrierBytes(txout.scriptPubKey, tx.vout.size() - i);
700
  mod_weight += int64_t(dcb.first + dcb.second) * (weight_per_data_byte - WITNESS_SCALE_FACTOR);
701
  }
702
  }