Skip to content
Bitcoin Roots

v30.3-roots.1 · Commit 3: [PATCH 03/68] feat(policy): preserve Roots relay and network controls on Core 30.3

src/script/script.cpp

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

File metadata
index 829e351be697a11ad7828f9512d13974df19d9ed..7fa814d50cc9ebc553a37b8f433d5ce6c5b2a467 100644

Download original patch · Release notes

Diff rows 1–125 of 125. 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/script/script.cpp CHANGED
@@ -8,6 +8,7 @@
8
  #include <crypto/common.h>
9
  #include <crypto/hex_base.h>
10
  #include <hash.h>
 
11
  #include <uint256.h>
12
  #include <util/hash_type.h>
13
 
@@ -310,6 +311,118 @@ bool CScript::HasValidOps() const
310
  return true;
311
  }
312
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
  bool GetScriptOp(CScriptBase::const_iterator& pc, CScriptBase::const_iterator end, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet)
314
  {
315
  opcodeRet = OP_INVALIDOPCODE;
 
8
  #include <crypto/common.h>
9
  #include <crypto/hex_base.h>
10
  #include <hash.h>
11
+ #include <script/interpreter.h>
12
  #include <uint256.h>
13
  #include <util/hash_type.h>
14
 
 
311
  return true;
312
  }
313
 
314
+ size_t CScript::IsOLGA(const size_t remaining_outputs) const
315
+ {
316
+ if (!IsPayToWitnessScriptHash()) {
317
+ return 0;
318
+ }
319
+
320
+ const size_t olga_payload_size{(size_t{(*this)[2]} << 8) | (*this)[3]};
321
+ const size_t olga_outputs{(olga_payload_size + 1) / WITNESS_V0_SCRIPTHASH_SIZE + 1};
322
+ if (remaining_outputs < olga_outputs) {
323
+ return 0;
324
+ }
325
+
326
+ if (((*this)[4] | 0x20) != 's') return 0;
327
+ if (((*this)[5] | 0x20) != 't') return 0;
328
+ if (((*this)[6] | 0x20) != 'a') return 0;
329
+ if (((*this)[7] | 0x20) != 'm') return 0;
330
+ if (((*this)[8] | 0x20) != 'p') return 0;
331
+ if ((*this)[9] != ':') return 0;
332
+
333
+ return olga_outputs * (WITNESS_V0_SCRIPTHASH_SIZE + /* script length */ 1 + /* amount */ 8);
334
+ }
335
+
336
+ size_t CScript::OPNetWitnessSize(const CScriptWitness& witness) const
337
+ {
338
+ const auto& stack = witness.stack;
339
+
340
+ if (stack.size() != 5) return 0;
341
+ if (stack[4].size() != 65) return 0;
342
+
343
+ const CScript tapscript{stack[3].begin(), stack[3].end()};
344
+ bool found_opnet{false};
345
+ size_t deduct{0};
346
+
347
+ CScript::const_iterator pc = tapscript.begin();
348
+ opcodetype opcode{OP_INVALIDOPCODE}, last_opcode{OP_INVALIDOPCODE};
349
+ std::vector<unsigned char> data;
350
+ while (pc < tapscript.end()) {
351
+ last_opcode = opcode;
352
+ if (!tapscript.GetOp(pc, opcode, data)) break;
353
+
354
+ if (data.size() == 2 && data[0] == 0x6f && data[1] == 0x70) {
355
+ found_opnet = true;
356
+ }
357
+ if (opcode == OP_CHECKSIGVERIFY && last_opcode == 0x20) {
358
+ deduct += 34;
359
+ }
360
+ }
361
+
362
+ if (!found_opnet) return 0;
363
+ return stack[0].size() + stack[3].size() - deduct;
364
+ }
365
+
366
+ std::pair<size_t, size_t> CScript::DatacarrierBytes(const size_t remaining_outputs, const CScriptWitness* witness) const
367
+ {
368
+ if (size_t olga_bytes = IsOLGA(remaining_outputs); olga_bytes) {
369
+ return {0, olga_bytes};
370
+ }
371
+
372
+ if (witness) {
373
+ if (uint32_t opnet_bytes = OPNetWitnessSize(*witness); opnet_bytes) {
374
+ return {0, opnet_bytes};
375
+ }
376
+ }
377
+
378
+ size_t counted{0};
379
+ opcodetype opcode, last_opcode{OP_INVALIDOPCODE};
380
+ std::vector<unsigned char> push_data;
381
+ unsigned int inside_noop{0}, inside_conditional{0};
382
+ CScript::const_iterator opcode_it = begin(), data_began = begin();
383
+ for (CScript::const_iterator it = begin(); it < end(); last_opcode = opcode) {
384
+ opcode_it = it;
385
+ if (!GetOp(it, opcode, push_data)) {
386
+ // Invalid scripts are necessarily all data
387
+ return {0, size()};
388
+ }
389
+
390
+ if (opcode == OP_IF || opcode == OP_NOTIF) {
391
+ ++inside_conditional;
392
+ } else if (opcode == OP_ENDIF) {
393
+ if (!inside_conditional) return {0, size()}; // invalid
394
+ --inside_conditional;
395
+ } else if (opcode == OP_RETURN && !inside_conditional) {
396
+ // unconditional OP_RETURN is unspendable
397
+ return {size(), 0};
398
+ }
399
+
400
+ // Match OP_FALSE OP_IF
401
+ if (inside_noop) {
402
+ switch (opcode) {
403
+ case OP_IF: case OP_NOTIF:
404
+ ++inside_noop;
405
+ break;
406
+ case OP_ENDIF:
407
+ if (0 == --inside_noop) {
408
+ counted += it - data_began + 1;
409
+ }
410
+ break;
411
+ default: /* do nothing */;
412
+ }
413
+ } else if (opcode == OP_IF && last_opcode == OP_FALSE) {
414
+ inside_noop = 1;
415
+ data_began = opcode_it;
416
+ // Match <data> OP_DROP
417
+ } else if (opcode <= OP_PUSHDATA4) {
418
+ data_began = opcode_it;
419
+ } else if (opcode == OP_DROP && last_opcode <= OP_PUSHDATA4) {
420
+ counted += it - data_began;
421
+ }
422
+ }
423
+ return {0, counted};
424
+ }
425
+
426
  bool GetScriptOp(CScriptBase::const_iterator& pc, CScriptBase::const_iterator end, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet)
427
  {
428
  opcodeRet = OP_INVALIDOPCODE;