@smartledger/bsv 7.13.0 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/README.md +38 -38
  3. package/bsv-gdaf.min.js +55 -55
  4. package/bsv-ltp.min.js +39 -39
  5. package/bsv-smartcontract.min.js +1 -1
  6. package/bsv.bundle.js +55 -55
  7. package/bsv.min.js +55 -55
  8. package/docs/AUDIT_SCOPE.md +21 -12
  9. package/docs/MODULE_REFERENCE_COMPLETE.md +27 -27
  10. package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
  11. package/docs/getting-started/INSTALLATION.md +23 -23
  12. package/docs/getting-started/QUICK_START.md +7 -7
  13. package/docs/migration/FROM_BSV_1_5_6.md +5 -5
  14. package/lib/crypto/bn.js +22 -2
  15. package/lib/script/interpreter.js +399 -56
  16. package/lib/transaction/sighash.js +18 -6
  17. package/package.json +4 -1
  18. package/test/consensus/base58-vectors.js +120 -0
  19. package/test/consensus/sv-script-vectors.js +81 -0
  20. package/test/consensus/sv-sighash-vectors.js +51 -0
  21. package/test/consensus/sv-tx-vectors.js +48 -0
  22. package/test/data/bitcoin-sv/README.md +170 -0
  23. package/test/data/bitcoin-sv/base58_encode_decode.json +14 -0
  24. package/test/data/bitcoin-sv/base58_keys_invalid.json +152 -0
  25. package/test/data/bitcoin-sv/base58_keys_valid.json +452 -0
  26. package/test/data/bitcoin-sv/script_tests.json +2591 -0
  27. package/test/data/bitcoin-sv/sighash.json +1003 -0
  28. package/test/data/bitcoin-sv/tx_invalid.json +285 -0
  29. package/test/data/bitcoin-sv/tx_valid.json +367 -0
  30. package/test/regressions.js +35 -0
  31. package/test/script/chronicle.js +170 -25
  32. package/test/script/defaults.js +93 -0
  33. package/test/script/genesis_limits.js +62 -6
  34. package/test/script/interpreter.js +24 -8
  35. package/test/transaction/sighash.js +21 -1
  36. package/version.js +1 -1
@@ -75,7 +75,8 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
75
75
  nin = 0
76
76
  }
77
77
  if (_.isUndefined(flags)) {
78
- flags = 0
78
+ flags = Interpreter.currentConsensusFlags()
79
+ if (!satoshisBN) flags &= ~Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID
79
80
  }
80
81
 
81
82
  // If FORKID is enabled, we also ensure strict encoding.
@@ -107,7 +108,12 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
107
108
  return false
108
109
  }
109
110
 
110
- if (flags & Interpreter.SCRIPT_VERIFY_P2SH) {
111
+ // Genesis removed P2SH: an output created after it that happens to match the
112
+ // pattern is evaluated literally, with no redeem-script pass.
113
+ var p2sh = (flags & Interpreter.SCRIPT_VERIFY_P2SH) !== 0 &&
114
+ (flags & Interpreter.SCRIPT_UTXO_AFTER_GENESIS) === 0
115
+
116
+ if (p2sh) {
111
117
  stackCopy = this.stack.slice()
112
118
  }
113
119
 
@@ -139,7 +145,7 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
139
145
  }
140
146
 
141
147
  // Additional validation for spend-to-script-hash transactions:
142
- if ((flags & Interpreter.SCRIPT_VERIFY_P2SH) && scriptPubkey.isScriptHashOut()) {
148
+ if (p2sh && scriptPubkey.isScriptHashOut()) {
143
149
  // scriptSig must be literals-only or validation fails
144
150
  if (!scriptSig.isPushOnly()) {
145
151
  this.errstr = 'SCRIPT_ERR_SIG_PUSHONLY'
@@ -191,11 +197,18 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
191
197
  // Disallow CLEANSTACK without P2SH, as otherwise a switch
192
198
  // CLEANSTACK->P2SH+CLEANSTACK would be possible, which is not a
193
199
  // softfork (and P2SH should be one).
194
- if ((flags & Interpreter.SCRIPT_VERIFY_P2SH) === 0) {
200
+ // Genesis removed P2SH, so post-Genesis the pairing no longer applies and
201
+ // CLEANSTACK stands on its own.
202
+ if ((flags & Interpreter.SCRIPT_VERIFY_P2SH) === 0 &&
203
+ (flags & Interpreter.SCRIPT_UTXO_AFTER_GENESIS) === 0) {
195
204
  throw new Error('internal error - CLEANSTACK without P2SH')
196
205
  }
197
206
 
198
- if (stackCopy.length !== 1) {
207
+ // The final stack. After a P2SH evaluation that is stackCopy itself, since
208
+ // the redeem script was evaluated over it, but reading stackCopy directly
209
+ // is wrong once P2SH no longer applies: it is then either the stack as it
210
+ // stood after the scriptSig, or never assigned at all.
211
+ if (this.stack.length !== 1) {
199
212
  this.errstr = 'SCRIPT_ERR_CLEANSTACK'
200
213
  return false
201
214
  }
@@ -212,7 +225,15 @@ Interpreter.prototype.initialize = function (obj) {
212
225
  this.pc = 0
213
226
  this.pbegincodehash = 0
214
227
  this.nOpCount = 0
228
+ this.returned = false
229
+ // Set when an OP_RETURN is reached inside a conditional after Genesis: the
230
+ // rest of the script stops executing while the conditional grammar is still
231
+ // checked to the end.
232
+ this.nonTopLevelReturnAfterGenesis = false
215
233
  this.vfExec = []
234
+ // Whether the conditional at each depth has already seen an OP_ELSE.
235
+ // Genesis allows only one per OP_IF, which needs remembering per level.
236
+ this.vfElse = []
216
237
  this.errstr = ''
217
238
  this.flags = 0
218
239
  }
@@ -227,7 +248,13 @@ Interpreter.prototype.set = function (obj) {
227
248
  this.pc = typeof obj.pc !== 'undefined' ? obj.pc : this.pc
228
249
  this.pbegincodehash = typeof obj.pbegincodehash !== 'undefined' ? obj.pbegincodehash : this.pbegincodehash
229
250
  this.nOpCount = typeof obj.nOpCount !== 'undefined' ? obj.nOpCount : this.nOpCount
251
+ this.returned = typeof obj.returned !== 'undefined' ? obj.returned : this.returned
252
+ this.nonTopLevelReturnAfterGenesis =
253
+ typeof obj.nonTopLevelReturnAfterGenesis !== 'undefined'
254
+ ? obj.nonTopLevelReturnAfterGenesis
255
+ : this.nonTopLevelReturnAfterGenesis
230
256
  this.vfExec = obj.vfExec || this.vfExec
257
+ this.vfElse = obj.vfElse || this.vfElse
231
258
  this.errstr = obj.errstr || this.errstr
232
259
  this.flags = typeof obj.flags !== 'undefined' ? obj.flags : this.flags
233
260
  }
@@ -236,12 +263,24 @@ Interpreter.true = Buffer.from([1])
236
263
  Interpreter.false = Buffer.from([])
237
264
 
238
265
  Interpreter.MAX_SCRIPT_ELEMENT_SIZE = 520
266
+ // CScriptNum's `max_length`: the widest a script NUMBER may be, in bytes. Distinct from
267
+ // MAX_SCRIPT_ELEMENT_SIZE, which caps a pushed data element. Arithmetic opcodes read
268
+ // operands through it, and Chronicle's shift bounds its result against it.
239
269
  Interpreter.MAXIMUM_ELEMENT_SIZE = 4
270
+
271
+ // The script-number bound `useMainnetConsensus()` applies. Held separately from the
272
+ // pre-Genesis default above so the two can diverge once the post-Genesis value is pinned
273
+ // against the node source; see the note in useMainnetConsensus for why it is not simply
274
+ // raised with the other caps.
275
+ Interpreter.DEFAULT_SCRIPT_NUM_LENGTH = 4
240
276
  // Maximum number of non-push opcodes per script. Pre-Genesis consensus is 201;
241
277
  // post-Genesis BSV removed this limit. Exposed as a constant (instead of a magic
242
278
  // number) so applications can opt into post-Genesis rules — e.g. OP_PUSH_TX
243
279
  // covenants, which need a few hundred opcodes — without forking the interpreter.
244
- Interpreter.MAX_OPS_PER_SCRIPT = 201
280
+ // BSV's pre-Genesis figure is 500, not Bitcoin Core's 201: the limit was
281
+ // raised before Genesis removed it altogether. Carrying Core's number rejected
282
+ // scripts the network accepted.
283
+ Interpreter.MAX_OPS_PER_SCRIPT = 500
245
284
  // Maximum total serialized script size. Pre-Genesis consensus is 10,000 bytes;
246
285
  // post-Genesis BSV removed this limit too. It was previously a literal inside
247
286
  // evaluate(), so `useGenesisLimits()` could not lift it and any script over 10 KB —
@@ -249,6 +288,16 @@ Interpreter.MAX_OPS_PER_SCRIPT = 201
249
288
  // no matter what the caller asked for.
250
289
  Interpreter.MAX_SCRIPT_SIZE = 10000
251
290
 
291
+ // Genesis and Chronicle limits, from the node's src/consensus/consensus.h.
292
+ // These are the values the WIP note above asked to be pinned against the node
293
+ // source: Genesis raised the script-number bound to 750,000 bytes and
294
+ // Chronicle to 32,000,000, and removed the element, script size and operation
295
+ // caps outright.
296
+ Interpreter.UNLIMITED = Number.MAX_SAFE_INTEGER
297
+ Interpreter.MAX_SCRIPT_NUM_LENGTH_AFTER_GENESIS = 750000
298
+ Interpreter.MAX_SCRIPT_NUM_LENGTH_AFTER_CHRONICLE = 32000000
299
+ Interpreter.MAX_PUBKEYS_PER_MULTISIG_AFTER_GENESIS = 4294967295
300
+
252
301
  Interpreter.LOCKTIME_THRESHOLD = 500000000
253
302
  Interpreter.LOCKTIME_THRESHOLD_BN = new BN(Interpreter.LOCKTIME_THRESHOLD)
254
303
 
@@ -398,17 +447,41 @@ Interpreter.SCRIPT_ENABLE_REPLAY_PROTECTION = (1 << 17)
398
447
 
399
448
  // Enable new opcodes.
400
449
  //
401
- Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES = (1 << 18)
450
+ // Moved off 1<<18 and 1<<19, which the reference node assigns to
451
+ // SCRIPT_GENESIS and SCRIPT_UTXO_AFTER_GENESIS. Sharing those bits meant that
452
+ // node-derived flags passed into this library were silently read as something
453
+ // else. These two are BCH-era flags the node does not define at all, so their
454
+ // positions carry no consensus meaning and are free to move.
455
+ Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES = (1 << 11)
402
456
 
403
457
  // Are the Magnetic upgrade opcodes enabled?
404
458
  //
405
- Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES = (1 << 19)
459
+ Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES = (1 << 12)
460
+
461
+ // The era flags, at the bit positions src/script/script_flags.h assigns them.
462
+ // Keep them in sync: they are consensus-relevant and are passed across the
463
+ // boundary with node-derived test vectors.
464
+ //
465
+ // The distinction between the pairs matters. SCRIPT_UTXO_AFTER_* describes the
466
+ // output being spent and governs almost every rule, because an output made
467
+ // before an upgrade is spent under the old rules forever. SCRIPT_GENESIS and
468
+ // SCRIPT_CHRONICLE describe the block the spending transaction is in.
469
+ Interpreter.SCRIPT_GENESIS = (1 << 18)
470
+ Interpreter.SCRIPT_UTXO_AFTER_GENESIS = (1 << 19)
406
471
 
407
472
  // Chronicle restores OP_2MUL/OP_2DIV and gives OP_VER/OP_VERIF/OP_VERNOTIF meaning.
408
473
  // Off by default: enabling it changes script evaluation, so it is an explicit opt-in
409
474
  // exactly like the Monolith and Magnetic flags above.
410
475
  Interpreter.SCRIPT_ENABLE_CHRONICLE = (1 << 20)
411
476
 
477
+ // The node's name for the same bit: Chronicle rules apply to the block the
478
+ // spending transaction is in.
479
+ Interpreter.SCRIPT_CHRONICLE = Interpreter.SCRIPT_ENABLE_CHRONICLE
480
+
481
+ // Was the output being spent created after Chronicle activated? This is what
482
+ // the node gates the restored opcodes on.
483
+ Interpreter.SCRIPT_UTXO_AFTER_CHRONICLE = (1 << 21)
484
+
412
485
  /**
413
486
  * Block height at which Chronicle activated on BSV mainnet (2026-04-07).
414
487
  *
@@ -432,9 +505,21 @@ Interpreter.CHRONICLE_ACTIVATION_HEIGHT = 943816
432
505
  * every output created since is subject to it. Pass `false` to validate the spend of a
433
506
  * pre-activation UTXO, which is exactly the distinction the node makes.
434
507
  *
508
+ * CLTV and CSV are deliberately ABSENT. Genesis reverted both opcodes to OP_NOP2/OP_NOP3,
509
+ * and the node ignores their flags entirely once the UTXO is post-Genesis:
510
+ *
511
+ * if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) || utxo_after_genesis) {
512
+ * // not enabled; treat as a NOP2
513
+ *
514
+ * Including them made this function reject `<n> OP_CHECKLOCKTIMEVERIFY OP_DROP OP_1`,
515
+ * which mainnet accepts — a validator STRICTER than consensus, which is as wrong as one
516
+ * that is looser and harder to notice, because nothing that tests this library against
517
+ * itself can see it. The flags still exist for callers deliberately emulating
518
+ * pre-Genesis rules; they are simply not mainnet.
519
+ *
435
520
  * NOTE: script-number and element-size limits are NOT flags — they are process-wide
436
- * statics raised by `useGenesisLimits()`. A post-Genesis validator needs both this flag
437
- * set and that call.
521
+ * statics. This function cannot set them, which is why `useMainnetConsensus()` exists;
522
+ * prefer it unless you are managing the limits yourself.
438
523
  *
439
524
  * @param {object} [opts]
440
525
  * @param {boolean} [opts.afterChronicle=true] is the UTXO being spent post-activation
@@ -448,8 +533,6 @@ Interpreter.mainnetFlags = function (opts) {
448
533
  Interpreter.SCRIPT_VERIFY_LOW_S |
449
534
  Interpreter.SCRIPT_VERIFY_NULLFAIL |
450
535
  Interpreter.SCRIPT_VERIFY_MINIMALDATA |
451
- Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY |
452
- Interpreter.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY |
453
536
  Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID |
454
537
  Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES |
455
538
  Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES
@@ -459,6 +542,88 @@ Interpreter.mainnetFlags = function (opts) {
459
542
  return flags
460
543
  }
461
544
 
545
+ /**
546
+ * Configure this process for BSV mainnet consensus and return the matching flags.
547
+ *
548
+ * Flags and limits are separate mechanisms here — flags are an argument to `verify()`,
549
+ * limits are process-wide statics — and that split is what made `mainnetFlags()` alone
550
+ * insufficient: it returns mainnet flags while the interpreter still holds the
551
+ * PRE-Genesis 520 / 201 / 10,000 caps, so a 12,801-byte script valid on mainnet was
552
+ * rejected with SCRIPT_ERR_SCRIPT_SIZE.
553
+ *
554
+ * This is the single call that makes both agree. It MUTATES process-wide state, which is
555
+ * why it is named `use*` like `useGenesisLimits()` rather than reading like a getter.
556
+ *
557
+ * @param {object} [opts]
558
+ * @param {boolean} [opts.afterChronicle=true] is the UTXO being spent post-activation
559
+ * @param {number} [opts.max] element-size ceiling to pass through to useGenesisLimits()
560
+ * @returns {number} the flags to hand to verify()
561
+ */
562
+ /**
563
+ * The flags describing BSV mainnet as it is today, and the default for `verify()`.
564
+ *
565
+ * Until 8.0.0 `verify()` defaulted to `0` — no rules at all. A BSV library whose
566
+ * out-of-the-box answer described Bitcoin in 2015 is wrong in the direction that is
567
+ * hardest to notice: it accepts scripts the network rejects, and nothing that tests this
568
+ * library against itself can see it. The era now has to be stated to get anything else.
569
+ *
570
+ * The set is derived from what the node applies, not assembled by judgement:
571
+ *
572
+ * MONOLITH / MAGNETIC BSV restored these opcodes in 2018 and the node does not gate
573
+ * them. This library still does, so omitting them here would be
574
+ * STRICTER than consensus. tools/sv-vector-harness.js sets the
575
+ * same pair as its baseline for every vector, for this reason.
576
+ * GENESIS rules keyed to the era of the spending transaction
577
+ * UTXO_AFTER_GENESIS rules keyed to the era of the output being spent (2020)
578
+ * CHRONICLE the spending transaction's era (2026)
579
+ * UTXO_AFTER_CHRONICLE the spent output's era
580
+ *
581
+ * Spending a pre-activation output is the explicit case, because that is the input the
582
+ * caller knows and the library cannot: `mainnetFlags({ afterChronicle: false })`, or a
583
+ * hand-assembled set for older eras.
584
+ *
585
+ * FORKID is deliberately absent here and added by `verify()` only when the input amount
586
+ * is available, since the digest cannot be computed without it.
587
+ *
588
+ * @returns {number}
589
+ */
590
+ Interpreter.currentConsensusFlags = function () {
591
+ return Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES |
592
+ Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES |
593
+ Interpreter.SCRIPT_GENESIS |
594
+ Interpreter.SCRIPT_UTXO_AFTER_GENESIS |
595
+ Interpreter.SCRIPT_ENABLE_CHRONICLE |
596
+ Interpreter.SCRIPT_UTXO_AFTER_CHRONICLE |
597
+ Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID
598
+ }
599
+
600
+ Interpreter.useMainnetConsensus = function (opts) {
601
+ opts = opts || {}
602
+ Interpreter.useGenesisLimits(opts.max)
603
+
604
+ // Restore a FINITE script-number bound. `useGenesisLimits()` raises all four caps to
605
+ // the same ceiling, and for MAXIMUM_ELEMENT_SIZE — which is CScriptNum's `max_length`,
606
+ // not a push-size cap — a ceiling of 0x7fffffff makes Chronicle's shift overflow check
607
+ // unreachable, because it tests `current_size + shift_bytes > max_length`. Measured:
608
+ //
609
+ // default limits: SCRIPT_ERR_SCRIPTNUM_OVERFLOW (correct)
610
+ // after useGenesisLimits(): valid, grows without bound (WRONG)
611
+ //
612
+ // A validator looser than consensus accepts what the network rejects, so the ceiling
613
+ // cannot be right whatever the true post-Genesis value turns out to be.
614
+ //
615
+ // The true value is NOT settled here. Genesis raised this bound above the pre-Genesis
616
+ // 4 bytes, so the conservative default below is stricter than mainnet for wide
617
+ // arithmetic — the same class of error #112 fixed, in the opposite direction. It is
618
+ // chosen deliberately: given a choice between rejecting a valid script and accepting
619
+ // an invalid one, this library fails closed. Callers who know the bound their workload
620
+ // needs should pass `maxScriptNumLength` explicitly, and the value should be pinned
621
+ // against the SV Node source before this default changes.
622
+ Interpreter.MAXIMUM_ELEMENT_SIZE = opts.maxScriptNumLength || Interpreter.DEFAULT_SCRIPT_NUM_LENGTH
623
+
624
+ return Interpreter.mainnetFlags(opts)
625
+ }
626
+
462
627
  /* Below flags apply in the context of BIP 68 */
463
628
  /**
464
629
  * If this flag set, CTxIn::nSequence is NOT interpreted as a relative
@@ -526,6 +691,20 @@ Interpreter.prototype.checkSignatureEncoding = function (buf) {
526
691
  return false
527
692
  }
528
693
 
694
+ // A signature may only ask for the original digest where Chronicle
695
+ // applies. This is where the node stops a pre-Chronicle signature whose
696
+ // type byte happens to set 0x20 from being read as one asking for OTDA:
697
+ //
698
+ // if(!chronicleEnabled && usesChronicle) return SCRIPT_ERR_ILLEGAL_CHRONICLE;
699
+ //
700
+ // It rejects such a signature outright rather than reinterpreting it,
701
+ // which is why SignatureHash() itself can route on the bit alone.
702
+ if (!(this.flags & Interpreter.SCRIPT_CHRONICLE) &&
703
+ (sig.nhashtype & Signature.SIGHASH_CHRONICLE)) {
704
+ this.errstr = 'SCRIPT_ERR_ILLEGAL_CHRONICLE'
705
+ return false
706
+ }
707
+
529
708
  if ((this.flags & Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID) &&
530
709
  !(sig.nhashtype & Signature.SIGHASH_FORKID)) {
531
710
  this.errstr = 'SCRIPT_ERR_MUST_USE_FORKID'
@@ -554,6 +733,67 @@ Interpreter.prototype.checkPubkeyEncoding = function (buf) {
554
733
  *
555
734
  */
556
735
 
736
+ /**
737
+ * Which era's rules apply.
738
+ *
739
+ * The node decides almost everything by the era of the output being spent, so
740
+ * these read the SCRIPT_UTXO_AFTER_* flags rather than a process-wide setting.
741
+ * A caller that sets no era flag gets the previous behaviour exactly: the
742
+ * limit methods below fall back to the mutable statics, so useGenesisLimits()
743
+ * and setLimits() keep working as they did.
744
+ */
745
+ Interpreter.prototype.isAfterGenesis = function () {
746
+ return (this.flags & Interpreter.SCRIPT_UTXO_AFTER_GENESIS) !== 0
747
+ }
748
+
749
+ /**
750
+ * SCRIPT_ENABLE_CHRONICLE is accepted alongside SCRIPT_UTXO_AFTER_CHRONICLE.
751
+ * The former is this library's existing opt-in and sits on the node's
752
+ * SCRIPT_CHRONICLE bit; the latter is what the node actually gates the
753
+ * restored opcodes on. Either enables them, so existing callers are unaffected.
754
+ */
755
+ Interpreter.prototype.isAfterChronicle = function () {
756
+ return (this.flags &
757
+ (Interpreter.SCRIPT_UTXO_AFTER_CHRONICLE | Interpreter.SCRIPT_ENABLE_CHRONICLE)) !== 0
758
+ }
759
+
760
+ /** Genesis removed this limit; before it, whatever the statics say. */
761
+ Interpreter.prototype.maxScriptElementSize = function () {
762
+ return this.isAfterGenesis() ? Interpreter.UNLIMITED : Interpreter.MAX_SCRIPT_ELEMENT_SIZE
763
+ }
764
+
765
+ /** Genesis removed this limit too. */
766
+ Interpreter.prototype.maxScriptSize = function () {
767
+ return this.isAfterGenesis() ? Interpreter.UNLIMITED : Interpreter.MAX_SCRIPT_SIZE
768
+ }
769
+
770
+ /** And this one. Note the pre-Genesis figure on BSV is 500, not Core's 201. */
771
+ Interpreter.prototype.maxOpsPerScript = function () {
772
+ return this.isAfterGenesis() ? Interpreter.UNLIMITED : Interpreter.MAX_OPS_PER_SCRIPT
773
+ }
774
+
775
+ /**
776
+ * The widest a script number may be. Four bytes before Genesis, which is why
777
+ * pre-Genesis contracts cannot do arithmetic on satoshi amounts; Genesis
778
+ * raised it to 750KB and Chronicle to 32MB.
779
+ */
780
+ Interpreter.prototype.maxScriptNumLength = function () {
781
+ if (this.isAfterChronicle()) {
782
+ return Interpreter.MAX_SCRIPT_NUM_LENGTH_AFTER_CHRONICLE
783
+ }
784
+ if (this.isAfterGenesis()) {
785
+ return Interpreter.MAX_SCRIPT_NUM_LENGTH_AFTER_GENESIS
786
+ }
787
+ return Interpreter.MAXIMUM_ELEMENT_SIZE
788
+ }
789
+
790
+ /** Genesis raised this rather than removing it: the node caps at UINT32_MAX. */
791
+ Interpreter.prototype.maxPubKeysPerMultisig = function () {
792
+ return this.isAfterGenesis()
793
+ ? Interpreter.MAX_PUBKEYS_PER_MULTISIG_AFTER_GENESIS
794
+ : 20
795
+ }
796
+
557
797
  Interpreter._isMinimallyEncoded = function (buf, nMaxNumSize) {
558
798
  nMaxNumSize = nMaxNumSize || Interpreter.MAXIMUM_ELEMENT_SIZE
559
799
  if (buf.length > nMaxNumSize) {
@@ -636,7 +876,7 @@ Interpreter._minimallyEncode = function (buf) {
636
876
  * bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
637
877
  */
638
878
  Interpreter.prototype.evaluate = function () {
639
- if (this.script.toBuffer().length > Interpreter.MAX_SCRIPT_SIZE) {
879
+ if (this.script.toBuffer().length > this.maxScriptSize()) {
640
880
  this.errstr = 'SCRIPT_ERR_SCRIPT_SIZE'
641
881
  return false
642
882
  }
@@ -649,6 +889,12 @@ Interpreter.prototype.evaluate = function () {
649
889
  return false
650
890
  }
651
891
  this._callbackStep(thisStep)
892
+ if (this.returned) {
893
+ // A top-level OP_RETURN after Genesis: the script is over and the top
894
+ // stack item decides. Nothing after it is read, so an unbalanced
895
+ // conditional or an invalid opcode beyond this point is not an error.
896
+ return true
897
+ }
652
898
  }
653
899
 
654
900
  // Size limits
@@ -657,7 +903,12 @@ Interpreter.prototype.evaluate = function () {
657
903
  return false
658
904
  }
659
905
  } catch (e) {
660
- this.errstr = 'SCRIPT_ERR_UNKNOWN_ERROR: ' + e
906
+ // An error that knows the node's result code reports it. Script number
907
+ // decoding is the case that matters: 78 of the corpus's rejected vectors
908
+ // expect SCRIPTNUM_MINENCODE or SCRIPTNUM_OVERFLOW, and every one of them
909
+ // used to arrive here and be flattened into UNKNOWN_ERROR. The script
910
+ // failed either way, so the accept/reject vectors could not see it.
911
+ this.errstr = e.scriptErr || ('SCRIPT_ERR_UNKNOWN_ERROR: ' + e)
661
912
  return false
662
913
  }
663
914
 
@@ -718,7 +969,11 @@ Interpreter.prototype.checkLockTime = function (nLockTime) {
718
969
  // prevent this condition. Alternatively we could test all
719
970
  // inputs, but testing just this input minimizes the data
720
971
  // required to prove correct CHECKLOCKTIMEVERIFY execution.
721
- if (this.tx.inputs[this.nin].isFinal()) {
972
+ // Same guard as checkSequence: no input at `nin` means the locktime cannot be
973
+ // satisfied. Reached only when the comparisons above pass, which is why this one
974
+ // never surfaced as a TypeError — the ordering hid it, not a check.
975
+ var input = this.tx.inputs[this.nin]
976
+ if (!input || input.isFinal()) {
722
977
  return false
723
978
  }
724
979
 
@@ -732,9 +987,19 @@ Interpreter.prototype.checkLockTime = function (nLockTime) {
732
987
  * the transaction's sequence
733
988
  */
734
989
  Interpreter.prototype.checkSequence = function (nSequence) {
990
+ // No input at `nin` means the relative locktime cannot be satisfied, so fail the
991
+ // script rather than dereferencing undefined. This used to throw a TypeError that the
992
+ // evaluator's try/catch converted into SCRIPT_ERR_UNKNOWN_ERROR — a misleading error
993
+ // that pointed at the script instead of at the caller's index. The same shape as the
994
+ // `new BN(...)` note below, and as the CHECKLOCKTIMEVERIFY guard.
995
+ var input = this.tx.inputs[this.nin]
996
+ if (!input) {
997
+ return false
998
+ }
999
+
735
1000
  // Relative lock times are supported by comparing the passed in operand to
736
1001
  // the sequence number of the input.
737
- var txToSequence = this.tx.inputs[this.nin].sequenceNumber
1002
+ var txToSequence = input.sequenceNumber
738
1003
 
739
1004
  // Fail if the transaction's version number is not set high enough to
740
1005
  // trigger BIP 68 rules.
@@ -819,7 +1084,7 @@ Interpreter.prototype.step = function () {
819
1084
  // "disabled" is stronger than "unimplemented": a disabled opcode fails the
820
1085
  // script even in an UNEXECUTED branch, which is why this lives in
821
1086
  // isOpcodeDisabled rather than in the evaluation switch.
822
- if ((self.flags & Interpreter.SCRIPT_ENABLE_CHRONICLE) === 0) {
1087
+ if (!self.isAfterChronicle()) {
823
1088
  return true
824
1089
  }
825
1090
  break
@@ -857,8 +1122,6 @@ Interpreter.prototype.step = function () {
857
1122
 
858
1123
  var fRequireMinimal = (this.flags & Interpreter.SCRIPT_VERIFY_MINIMALDATA) !== 0
859
1124
 
860
- // bool fExec = !count(vfExec.begin(), vfExec.end(), false);
861
- var fExec = (this.vfExec.indexOf(false) === -1)
862
1125
  var buf, buf1, buf2, spliced, n, x1, x2, bn, bn1, bn2, bufSig, bufPubkey, subscript
863
1126
  var sig, pubkey
864
1127
  var fValue, fSuccess
@@ -867,22 +1130,35 @@ Interpreter.prototype.step = function () {
867
1130
  var chunk = this.script.chunks[this.pc]
868
1131
  this.pc++
869
1132
  var opcodenum = chunk.opcodenum
1133
+
1134
+ // bool fExec = !count(vfExec.begin(), vfExec.end(), false);
1135
+ //
1136
+ // Computed after the opcode is read, because it depends on it: once an
1137
+ // OP_RETURN has been seen inside a conditional after Genesis, nothing but a
1138
+ // further OP_RETURN executes, while the conditional grammar is still checked
1139
+ // through to the end of the script.
1140
+ var fExec = (this.vfExec.indexOf(false) === -1) &&
1141
+ (!this.nonTopLevelReturnAfterGenesis || opcodenum === Opcode.OP_RETURN)
870
1142
  if (_.isUndefined(opcodenum)) {
871
1143
  this.errstr = 'SCRIPT_ERR_UNDEFINED_OPCODE'
872
1144
  return false
873
1145
  }
874
- if (chunk.buf && chunk.buf.length > Interpreter.MAX_SCRIPT_ELEMENT_SIZE) {
1146
+ if (chunk.buf && chunk.buf.length > this.maxScriptElementSize()) {
875
1147
  this.errstr = 'SCRIPT_ERR_PUSH_SIZE'
876
1148
  return false
877
1149
  }
878
1150
 
879
1151
  // Note how Opcode.OP_RESERVED does not count towards the opcode limit.
880
- if (opcodenum > Opcode.OP_16 && ++(this.nOpCount) > Interpreter.MAX_OPS_PER_SCRIPT) {
1152
+ if (opcodenum > Opcode.OP_16 && ++(this.nOpCount) > this.maxOpsPerScript()) {
881
1153
  this.errstr = 'SCRIPT_ERR_OP_COUNT'
882
1154
  return false
883
1155
  }
884
1156
 
885
- if (isOpcodeDisabled(opcodenum)) {
1157
+ // Before Genesis the mere presence of a disabled opcode invalidates the
1158
+ // script, even in a branch that never runs. After it, only executing one
1159
+ // fails — the node states it as `IsOpcodeDisabled(...) && (!utxo_after_genesis
1160
+ // || fExec)`.
1161
+ if (isOpcodeDisabled(opcodenum) && (!this.isAfterGenesis() || fExec)) {
886
1162
  this.errstr = 'SCRIPT_ERR_DISABLED_OPCODE'
887
1163
  return false
888
1164
  }
@@ -895,7 +1171,13 @@ Interpreter.prototype.step = function () {
895
1171
  if (!chunk.buf) {
896
1172
  this.stack.push(Interpreter.false)
897
1173
  } else if (chunk.len !== chunk.buf.length) {
898
- throw new Error(`Length of push value not equal to length of data (${chunk.len},${chunk.buf.length})`)
1174
+ // A push that declares more bytes than the script carries — "PUSHDATA1
1175
+ // with not enough bytes" and its PUSHDATA2/4 counterparts. The node
1176
+ // fails these as SCRIPT_ERR_BAD_OPCODE. Throwing reached the evaluator's
1177
+ // catch and became UNKNOWN_ERROR; this is inside step(), which can
1178
+ // simply fail.
1179
+ this.errstr = 'SCRIPT_ERR_BAD_OPCODE'
1180
+ return false
899
1181
  } else {
900
1182
  this.stack.push(chunk.buf)
901
1183
  }
@@ -937,7 +1219,14 @@ Interpreter.prototype.step = function () {
937
1219
  case Opcode.OP_NOP2:
938
1220
  case Opcode.OP_CHECKLOCKTIMEVERIFY:
939
1221
 
940
- if (!(this.flags & Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) {
1222
+ // Genesis reverted this to an upgradable NOP for outputs created
1223
+ // after it, so a post-Genesis script containing it enforces no
1224
+ // locktime at all. The node reads
1225
+ // !(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) || utxo_after_genesis
1226
+ // and without the second half a transaction the network accepts is
1227
+ // rejected here.
1228
+ if (!(this.flags & Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) ||
1229
+ this.isAfterGenesis()) {
941
1230
  // not enabled; treat as a NOP2
942
1231
  if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
943
1232
  this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
@@ -985,7 +1274,14 @@ Interpreter.prototype.step = function () {
985
1274
  case Opcode.OP_NOP3:
986
1275
  case Opcode.OP_CHECKSEQUENCEVERIFY:
987
1276
 
988
- if (!(this.flags & Interpreter.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) {
1277
+ // Genesis reverted this to an upgradable NOP for outputs created
1278
+ // after it, so a post-Genesis script containing it enforces no
1279
+ // locktime at all. The node reads
1280
+ // !(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY) || utxo_after_genesis
1281
+ // and without the second half a transaction the network accepts is
1282
+ // rejected here.
1283
+ if (!(this.flags & Interpreter.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY) ||
1284
+ this.isAfterGenesis()) {
989
1285
  // not enabled; treat as a NOP3
990
1286
  if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
991
1287
  this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
@@ -1056,7 +1352,7 @@ Interpreter.prototype.step = function () {
1056
1352
  //
1057
1353
  // Rejecting them outright would make this library refuse scripts the network
1058
1354
  // accepts, which is the mirror of the bug that made them silently succeed.
1059
- if ((this.flags & Interpreter.SCRIPT_ENABLE_CHRONICLE) === 0) {
1355
+ if (!this.isAfterChronicle()) {
1060
1356
  if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
1061
1357
  this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
1062
1358
  return false
@@ -1069,7 +1365,7 @@ Interpreter.prototype.step = function () {
1069
1365
  this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1070
1366
  return false
1071
1367
  }
1072
- var maxNumSize = Interpreter.MAXIMUM_ELEMENT_SIZE
1368
+ var maxNumSize = this.maxScriptNumLength()
1073
1369
  var shiftBn = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, maxNumSize)
1074
1370
  if (shiftBn.isNeg()) {
1075
1371
  this.errstr = 'SCRIPT_ERR_INVALID_NUMBER_RANGE'
@@ -1133,7 +1429,7 @@ Interpreter.prototype.step = function () {
1133
1429
  //
1134
1430
  // Unlike the string opcodes, BAD_OPCODE pre-Chronicle IS correct here —
1135
1431
  // the node returns it unconditionally.
1136
- if ((this.flags & Interpreter.SCRIPT_ENABLE_CHRONICLE) === 0) {
1432
+ if (!this.isAfterChronicle()) {
1137
1433
  this.errstr = 'SCRIPT_ERR_BAD_OPCODE'
1138
1434
  return false
1139
1435
  }
@@ -1157,8 +1453,13 @@ Interpreter.prototype.step = function () {
1157
1453
  // So pre-Chronicle they are an error only in an EXECUTED branch. BSV is
1158
1454
  // post-Genesis, which is the whole condition. Returning BAD_OPCODE
1159
1455
  // unconditionally rejected scripts the network accepts.
1160
- if ((this.flags & Interpreter.SCRIPT_ENABLE_CHRONICLE) === 0) {
1161
- if (!fExec) {
1456
+ if (!this.isAfterChronicle()) {
1457
+ // Genesis is part of the condition, not an assumption: before it
1458
+ // these are illegal everywhere, including in a branch that never
1459
+ // runs, and only from Genesis does an unexecuted one become
1460
+ // harmless. The era is carried in the flags now, so a pre-Genesis
1461
+ // output is validated as one.
1462
+ if (this.isAfterGenesis() && !fExec) {
1162
1463
  break
1163
1464
  }
1164
1465
  this.errstr = 'SCRIPT_ERR_BAD_OPCODE'
@@ -1190,6 +1491,7 @@ Interpreter.prototype.step = function () {
1190
1491
  this.stack.pop()
1191
1492
  }
1192
1493
  this.vfExec.push(fValue)
1494
+ this.vfElse.push(false)
1193
1495
  break
1194
1496
 
1195
1497
  case Opcode.OP_IF:
@@ -1221,14 +1523,21 @@ Interpreter.prototype.step = function () {
1221
1523
  this.stack.pop()
1222
1524
  }
1223
1525
  this.vfExec.push(fValue)
1526
+ this.vfElse.push(false)
1224
1527
  break
1225
1528
 
1226
1529
  case Opcode.OP_ELSE:
1227
- if (this.vfExec.length === 0) {
1530
+ // Genesis allows only one OP_ELSE per OP_IF. A second one is
1531
+ // unbalanced, and accepting it means accepting scripts the network
1532
+ // rejects — the node states it as
1533
+ // if (vfExec.empty() || (vfElse.back() && utxo_after_genesis))
1534
+ if (this.vfExec.length === 0 ||
1535
+ (this.vfElse[this.vfElse.length - 1] && this.isAfterGenesis())) {
1228
1536
  this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL'
1229
1537
  return false
1230
1538
  }
1231
1539
  this.vfExec[this.vfExec.length - 1] = !this.vfExec[this.vfExec.length - 1]
1540
+ this.vfElse[this.vfElse.length - 1] = true
1232
1541
  break
1233
1542
 
1234
1543
  case Opcode.OP_ENDIF:
@@ -1237,6 +1546,7 @@ Interpreter.prototype.step = function () {
1237
1546
  return false
1238
1547
  }
1239
1548
  this.vfExec.pop()
1549
+ this.vfElse.pop()
1240
1550
  break
1241
1551
 
1242
1552
  case Opcode.OP_VERIFY:
@@ -1257,6 +1567,21 @@ Interpreter.prototype.step = function () {
1257
1567
  break
1258
1568
 
1259
1569
  case Opcode.OP_RETURN:
1570
+ if (this.isAfterGenesis()) {
1571
+ if (this.vfExec.length === 0) {
1572
+ // Genesis restored OP_RETURN's original meaning: it terminates the
1573
+ // script and the top stack item decides validity. The remainder
1574
+ // cannot affect the outcome, even if it holds unbalanced
1575
+ // conditionals or invalid opcodes, which is what makes
1576
+ // OP_FALSE OP_RETURN <data> outputs safe to carry anything.
1577
+ this.returned = true
1578
+ break
1579
+ }
1580
+ // Inside a conditional, suppress the rest but keep checking grammar.
1581
+ this.nonTopLevelReturnAfterGenesis = true
1582
+ break
1583
+ }
1584
+ // Before Genesis, an OP_RETURN alone invalidates the script.
1260
1585
  this.errstr = 'SCRIPT_ERR_OP_RETURN'
1261
1586
  return false
1262
1587
  // break // unreachable
@@ -1414,7 +1739,7 @@ Interpreter.prototype.step = function () {
1414
1739
  return false
1415
1740
  }
1416
1741
  buf = stacktop(-1)
1417
- bn = BN.fromScriptNumBuffer(buf, fRequireMinimal)
1742
+ bn = BN.fromScriptNumBuffer(buf, fRequireMinimal, this.maxScriptNumLength())
1418
1743
  n = bn.toNumber()
1419
1744
  this.stack.pop()
1420
1745
  if (n < 0 || n >= this.stack.length) {
@@ -1524,6 +1849,10 @@ Interpreter.prototype.step = function () {
1524
1849
  // (x -- out)
1525
1850
  if (this.stack.length < 1) {
1526
1851
  this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1852
+ // The missing return here let evaluation continue and crash on the
1853
+ // absent operand, reporting an internal TypeError rather than the
1854
+ // stack error it had already decided on.
1855
+ return false
1527
1856
  }
1528
1857
  buf = stacktop(-1)
1529
1858
  for (let i = 0; i < buf.length; i++) {
@@ -1543,7 +1872,7 @@ Interpreter.prototype.step = function () {
1543
1872
  this.stack.pop()
1544
1873
  } else {
1545
1874
  bn1 = new BN(buf1)
1546
- bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal)
1875
+ bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength())
1547
1876
  n = bn2.toNumber()
1548
1877
  if (n < 0) {
1549
1878
  this.errstr = 'SCRIPT_ERR_INVALID_NUMBER_RANGE'
@@ -1608,7 +1937,7 @@ Interpreter.prototype.step = function () {
1608
1937
  return false
1609
1938
  }
1610
1939
  buf = stacktop(-1)
1611
- bn = BN.fromScriptNumBuffer(buf, fRequireMinimal)
1940
+ bn = BN.fromScriptNumBuffer(buf, fRequireMinimal, this.maxScriptNumLength())
1612
1941
  switch (opcodenum) {
1613
1942
  case Opcode.OP_2MUL:
1614
1943
  bn = bn.mul(new BN(2))
@@ -1667,8 +1996,8 @@ Interpreter.prototype.step = function () {
1667
1996
  this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1668
1997
  return false
1669
1998
  }
1670
- bn1 = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal, Interpreter.MAXIMUM_ELEMENT_SIZE)
1671
- bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, Interpreter.MAXIMUM_ELEMENT_SIZE)
1999
+ bn1 = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal, this.maxScriptNumLength())
2000
+ bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength())
1672
2001
  bn = new BN(0)
1673
2002
 
1674
2003
  switch (opcodenum) {
@@ -1685,8 +2014,12 @@ Interpreter.prototype.step = function () {
1685
2014
  break
1686
2015
 
1687
2016
  case Opcode.OP_DIV:
1688
- // denominator must not be 0
1689
- if (bn2 === 0) {
2017
+ // denominator must not be 0. bn2 is a BN, so `bn2 === 0` was never
2018
+ // true and this guard never fired — bn.js asserted instead, and
2019
+ // the evaluator's catch reported SCRIPT_ERR_UNKNOWN_ERROR. The
2020
+ // script still failed, which is why the accept/reject vectors
2021
+ // stayed green while the reason was wrong.
2022
+ if (bn2.cmp(BN.Zero) === 0) {
1690
2023
  this.errstr = 'SCRIPT_ERR_DIV_BY_ZERO'
1691
2024
  return false
1692
2025
  }
@@ -1694,9 +2027,9 @@ Interpreter.prototype.step = function () {
1694
2027
  break
1695
2028
 
1696
2029
  case Opcode.OP_MOD:
1697
- // divisor must not be 0
1698
- if (bn2 === 0) {
1699
- this.errstr = 'SCRIPT_ERR_DIV_BY_ZERO'
2030
+ // divisor must not be 0. The node reports this one separately.
2031
+ if (bn2.cmp(BN.Zero) === 0) {
2032
+ this.errstr = 'SCRIPT_ERR_MOD_BY_ZERO'
1700
2033
  return false
1701
2034
  }
1702
2035
  bn = bn1.mod(bn2)
@@ -1766,9 +2099,9 @@ Interpreter.prototype.step = function () {
1766
2099
  this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1767
2100
  return false
1768
2101
  }
1769
- bn1 = BN.fromScriptNumBuffer(stacktop(-3), fRequireMinimal, Interpreter.MAXIMUM_ELEMENT_SIZE)
1770
- bn2 = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal, Interpreter.MAXIMUM_ELEMENT_SIZE)
1771
- var bn3 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, Interpreter.MAXIMUM_ELEMENT_SIZE)
2102
+ bn1 = BN.fromScriptNumBuffer(stacktop(-3), fRequireMinimal, this.maxScriptNumLength())
2103
+ bn2 = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal, this.maxScriptNumLength())
2104
+ var bn3 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength())
1772
2105
  // bool fValue = (bn2 <= bn1 && bn1 < bn3);
1773
2106
  fValue = (bn2.cmp(bn1) <= 0) && (bn1.cmp(bn3) < 0)
1774
2107
  this.stack.pop()
@@ -1880,9 +2213,10 @@ Interpreter.prototype.step = function () {
1880
2213
  return false
1881
2214
  }
1882
2215
 
1883
- var nKeysCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal).toNumber()
2216
+ var nKeysCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal, this.maxScriptNumLength()).toNumber()
1884
2217
  // TODO: Keys and opcount are parameterized in client. No magic numbers!
1885
- if (nKeysCount < 0 || nKeysCount > 20) {
2218
+ // Genesis raised this to UINT32_MAX rather than removing it.
2219
+ if (nKeysCount < 0 || nKeysCount > this.maxPubKeysPerMultisig()) {
1886
2220
  this.errstr = 'SCRIPT_ERR_PUBKEY_COUNT'
1887
2221
  return false
1888
2222
  }
@@ -1906,7 +2240,7 @@ Interpreter.prototype.step = function () {
1906
2240
  return false
1907
2241
  }
1908
2242
 
1909
- var nSigsCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal).toNumber()
2243
+ var nSigsCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal, this.maxScriptNumLength()).toNumber()
1910
2244
  if (nSigsCount < 0 || nSigsCount > nKeysCount) {
1911
2245
  this.errstr = 'SCRIPT_ERR_SIG_COUNT'
1912
2246
  return false
@@ -2019,7 +2353,12 @@ Interpreter.prototype.step = function () {
2019
2353
 
2020
2354
  buf1 = stacktop(-2)
2021
2355
  buf2 = stacktop(-1)
2022
- if (buf1.length + buf2.length > Interpreter.MAX_SCRIPT_ELEMENT_SIZE) {
2356
+ // Era-derived, like every other element size check. Genesis lifted the
2357
+ // 520-byte cap, and reading the static here meant OP_CAT kept
2358
+ // enforcing it after Genesis — rejecting a concatenation the network
2359
+ // accepts. No vector in the corpus covers this, so it is held by
2360
+ // test/script/genesis_limits.js instead.
2361
+ if (buf1.length + buf2.length > this.maxScriptElementSize()) {
2023
2362
  this.errstr = 'SCRIPT_ERR_PUSH_SIZE'
2024
2363
  return false
2025
2364
  }
@@ -2035,7 +2374,7 @@ Interpreter.prototype.step = function () {
2035
2374
  buf1 = stacktop(-2)
2036
2375
 
2037
2376
  // Make sure the split point is apropriate.
2038
- var position = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal).toNumber()
2377
+ var position = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength()).toNumber()
2039
2378
  if (position < 0 || position > buf1.length) {
2040
2379
  this.errstr = 'SCRIPT_ERR_INVALID_SPLIT_RANGE'
2041
2380
  return false
@@ -2065,7 +2404,7 @@ Interpreter.prototype.step = function () {
2065
2404
  //
2066
2405
  // Running them unconditionally consumed stack where the network does
2067
2406
  // nothing, which is a wrong answer rather than an error.
2068
- if ((this.flags & Interpreter.SCRIPT_ENABLE_CHRONICLE) === 0) {
2407
+ if (!this.isAfterChronicle()) {
2069
2408
  if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
2070
2409
  this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
2071
2410
  return false
@@ -2078,7 +2417,7 @@ Interpreter.prototype.step = function () {
2078
2417
  return false
2079
2418
  }
2080
2419
  buf1 = stacktop(-2)
2081
- n = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, Interpreter.MAXIMUM_ELEMENT_SIZE).toNumber()
2420
+ n = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength()).toNumber()
2082
2421
  // ERRORS on out of range; it does not clamp. The node is
2083
2422
  // `if(len < 0 || len > size) return SCRIPT_ERR_INVALID_NUMBER_RANGE`.
2084
2423
  // Clamping made scripts the node rejects succeed here.
@@ -2107,7 +2446,7 @@ Interpreter.prototype.step = function () {
2107
2446
  //
2108
2447
  // Running them unconditionally consumed stack where the network does
2109
2448
  // nothing, which is a wrong answer rather than an error.
2110
- if ((this.flags & Interpreter.SCRIPT_ENABLE_CHRONICLE) === 0) {
2449
+ if (!this.isAfterChronicle()) {
2111
2450
  if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
2112
2451
  this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
2113
2452
  return false
@@ -2120,8 +2459,8 @@ Interpreter.prototype.step = function () {
2120
2459
  return false
2121
2460
  }
2122
2461
  buf1 = stacktop(-3)
2123
- var subSize = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, Interpreter.MAXIMUM_ELEMENT_SIZE).toNumber()
2124
- var subBegin = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal, Interpreter.MAXIMUM_ELEMENT_SIZE).toNumber()
2462
+ var subSize = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength()).toNumber()
2463
+ var subBegin = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal, this.maxScriptNumLength()).toNumber()
2125
2464
  // ERRORS on out of range, matching
2126
2465
  // offset < 0 || offset >= size || len < 0 || len > size - offset
2127
2466
  // Note `offset >= size` is strict: a begin index AT the end is an
@@ -2145,8 +2484,12 @@ Interpreter.prototype.step = function () {
2145
2484
  return false
2146
2485
  }
2147
2486
 
2148
- var size = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal).toNumber()
2149
- if (size > Interpreter.MAX_SCRIPT_ELEMENT_SIZE) {
2487
+ var size = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength()).toNumber()
2488
+ // A negative size is a push size failure, not an encoding one. Without
2489
+ // the lower bound it fell through to the rawnum.length > size test,
2490
+ // which any number passes when size is negative, and reported
2491
+ // IMPOSSIBLE_ENCODING instead.
2492
+ if (size < 0 || size > this.maxScriptElementSize()) {
2150
2493
  this.errstr = 'SCRIPT_ERR_PUSH_SIZE'
2151
2494
  return false
2152
2495
  }