@smartledger/bsv 7.12.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 (56) hide show
  1. package/CHANGELOG.md +178 -0
  2. package/README.md +38 -38
  3. package/bsv-didweb.min.js +6 -6
  4. package/bsv-gdaf.min.js +66 -66
  5. package/bsv-ltp.min.js +46 -46
  6. package/bsv-mnemonic.min.js +8 -8
  7. package/bsv-smartcontract.min.js +1 -1
  8. package/bsv.bundle.js +66 -66
  9. package/bsv.min.js +66 -66
  10. package/docs/AUDIT_SCOPE.md +29 -21
  11. package/docs/MODULE_REFERENCE_COMPLETE.md +27 -27
  12. package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
  13. package/docs/getting-started/INSTALLATION.md +23 -23
  14. package/docs/getting-started/QUICK_START.md +7 -7
  15. package/docs/migration/FROM_BSV_1_5_6.md +5 -5
  16. package/index.js +10 -2
  17. package/lib/crypto/bn.js +22 -2
  18. package/lib/crypto/hash.browser.js +13 -5
  19. package/lib/crypto/hash.js +58 -2
  20. package/lib/crypto/random.js +72 -15
  21. package/lib/didweb/index.js +88 -9
  22. package/lib/encoding/base58.js +67 -3
  23. package/lib/mnemonic/mnemonic.js +19 -5
  24. package/lib/mnemonic/pbkdf2.js +35 -2
  25. package/lib/script/interpreter.js +420 -58
  26. package/lib/transaction/input/multisig.js +1 -1
  27. package/lib/transaction/input/multisigscripthash.js +1 -1
  28. package/lib/transaction/input/publickey.js +1 -1
  29. package/lib/transaction/input/publickeyhash.js +1 -1
  30. package/lib/transaction/sighash.js +18 -6
  31. package/lib/transaction/signature.js +1 -1
  32. package/lib/util/inherits.js +37 -0
  33. package/package.json +7 -8
  34. package/test/consensus/base58-vectors.js +120 -0
  35. package/test/consensus/sv-script-vectors.js +81 -0
  36. package/test/consensus/sv-sighash-vectors.js +51 -0
  37. package/test/consensus/sv-tx-vectors.js +48 -0
  38. package/test/crypto/backend_selection.js +126 -0
  39. package/test/crypto/random.js +73 -0
  40. package/test/data/bitcoin-sv/README.md +170 -0
  41. package/test/data/bitcoin-sv/base58_encode_decode.json +14 -0
  42. package/test/data/bitcoin-sv/base58_keys_invalid.json +152 -0
  43. package/test/data/bitcoin-sv/base58_keys_valid.json +452 -0
  44. package/test/data/bitcoin-sv/script_tests.json +2591 -0
  45. package/test/data/bitcoin-sv/sighash.json +1003 -0
  46. package/test/data/bitcoin-sv/tx_invalid.json +285 -0
  47. package/test/data/bitcoin-sv/tx_valid.json +367 -0
  48. package/test/didweb/relationships.js +144 -0
  49. package/test/regressions.js +35 -0
  50. package/test/script/chronicle.js +170 -25
  51. package/test/script/defaults.js +93 -0
  52. package/test/script/genesis_limits.js +62 -6
  53. package/test/script/interpreter.js +24 -8
  54. package/test/transaction/sighash.js +21 -1
  55. package/test/transaction/unspentoutput.js +6 -1
  56. package/version.js +1 -1
@@ -8,7 +8,26 @@ var BN = require('../crypto/bn')
8
8
  var Hash = require('../crypto/hash')
9
9
  var Signature = require('../crypto/signature')
10
10
  var PublicKey = require('../publickey')
11
- var cloneDeep = require('clone-deep')
11
+ /**
12
+ * Copy a script stack for the step listener, so a listener that mutates what it is
13
+ * handed cannot corrupt the running evaluation.
14
+ *
15
+ * Replaces the `clone-deep` dependency. The stack is an array of Buffers — every one of
16
+ * the 32 push sites in this file pushes a Buffer — so a shallow map with `Buffer.from`
17
+ * reproduces `cloneDeep(stack, true)` exactly for this input: same bytes, new backing
18
+ * memory, `Buffer.isBuffer` still true, empty buffers preserved.
19
+ *
20
+ * `structuredClone` is NOT a substitute: it returns Uint8Array for a Buffer input, which
21
+ * would silently change the type handed to every existing stepListener.
22
+ *
23
+ * Anything non-Buffer is passed through by reference. Nothing puts such a value on the
24
+ * stack today; if something ever does it will be a primitive, where sharing is harmless.
25
+ */
26
+ function cloneStack (stack) {
27
+ return stack.map(function (item) {
28
+ return Buffer.isBuffer(item) ? Buffer.from(item) : item
29
+ })
30
+ }
12
31
 
13
32
  /**
14
33
  * Bitcoin transactions contain scripts. Each input has a script called the
@@ -56,7 +75,8 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
56
75
  nin = 0
57
76
  }
58
77
  if (_.isUndefined(flags)) {
59
- flags = 0
78
+ flags = Interpreter.currentConsensusFlags()
79
+ if (!satoshisBN) flags &= ~Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID
60
80
  }
61
81
 
62
82
  // If FORKID is enabled, we also ensure strict encoding.
@@ -88,7 +108,12 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
88
108
  return false
89
109
  }
90
110
 
91
- 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) {
92
117
  stackCopy = this.stack.slice()
93
118
  }
94
119
 
@@ -120,7 +145,7 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
120
145
  }
121
146
 
122
147
  // Additional validation for spend-to-script-hash transactions:
123
- if ((flags & Interpreter.SCRIPT_VERIFY_P2SH) && scriptPubkey.isScriptHashOut()) {
148
+ if (p2sh && scriptPubkey.isScriptHashOut()) {
124
149
  // scriptSig must be literals-only or validation fails
125
150
  if (!scriptSig.isPushOnly()) {
126
151
  this.errstr = 'SCRIPT_ERR_SIG_PUSHONLY'
@@ -172,11 +197,18 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
172
197
  // Disallow CLEANSTACK without P2SH, as otherwise a switch
173
198
  // CLEANSTACK->P2SH+CLEANSTACK would be possible, which is not a
174
199
  // softfork (and P2SH should be one).
175
- 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) {
176
204
  throw new Error('internal error - CLEANSTACK without P2SH')
177
205
  }
178
206
 
179
- 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) {
180
212
  this.errstr = 'SCRIPT_ERR_CLEANSTACK'
181
213
  return false
182
214
  }
@@ -193,7 +225,15 @@ Interpreter.prototype.initialize = function (obj) {
193
225
  this.pc = 0
194
226
  this.pbegincodehash = 0
195
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
196
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 = []
197
237
  this.errstr = ''
198
238
  this.flags = 0
199
239
  }
@@ -208,7 +248,13 @@ Interpreter.prototype.set = function (obj) {
208
248
  this.pc = typeof obj.pc !== 'undefined' ? obj.pc : this.pc
209
249
  this.pbegincodehash = typeof obj.pbegincodehash !== 'undefined' ? obj.pbegincodehash : this.pbegincodehash
210
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
211
256
  this.vfExec = obj.vfExec || this.vfExec
257
+ this.vfElse = obj.vfElse || this.vfElse
212
258
  this.errstr = obj.errstr || this.errstr
213
259
  this.flags = typeof obj.flags !== 'undefined' ? obj.flags : this.flags
214
260
  }
@@ -217,12 +263,24 @@ Interpreter.true = Buffer.from([1])
217
263
  Interpreter.false = Buffer.from([])
218
264
 
219
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.
220
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
221
276
  // Maximum number of non-push opcodes per script. Pre-Genesis consensus is 201;
222
277
  // post-Genesis BSV removed this limit. Exposed as a constant (instead of a magic
223
278
  // number) so applications can opt into post-Genesis rules — e.g. OP_PUSH_TX
224
279
  // covenants, which need a few hundred opcodes — without forking the interpreter.
225
- 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
226
284
  // Maximum total serialized script size. Pre-Genesis consensus is 10,000 bytes;
227
285
  // post-Genesis BSV removed this limit too. It was previously a literal inside
228
286
  // evaluate(), so `useGenesisLimits()` could not lift it and any script over 10 KB —
@@ -230,6 +288,16 @@ Interpreter.MAX_OPS_PER_SCRIPT = 201
230
288
  // no matter what the caller asked for.
231
289
  Interpreter.MAX_SCRIPT_SIZE = 10000
232
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
+
233
301
  Interpreter.LOCKTIME_THRESHOLD = 500000000
234
302
  Interpreter.LOCKTIME_THRESHOLD_BN = new BN(Interpreter.LOCKTIME_THRESHOLD)
235
303
 
@@ -379,17 +447,41 @@ Interpreter.SCRIPT_ENABLE_REPLAY_PROTECTION = (1 << 17)
379
447
 
380
448
  // Enable new opcodes.
381
449
  //
382
- 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)
383
456
 
384
457
  // Are the Magnetic upgrade opcodes enabled?
385
458
  //
386
- 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)
387
471
 
388
472
  // Chronicle restores OP_2MUL/OP_2DIV and gives OP_VER/OP_VERIF/OP_VERNOTIF meaning.
389
473
  // Off by default: enabling it changes script evaluation, so it is an explicit opt-in
390
474
  // exactly like the Monolith and Magnetic flags above.
391
475
  Interpreter.SCRIPT_ENABLE_CHRONICLE = (1 << 20)
392
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
+
393
485
  /**
394
486
  * Block height at which Chronicle activated on BSV mainnet (2026-04-07).
395
487
  *
@@ -413,9 +505,21 @@ Interpreter.CHRONICLE_ACTIVATION_HEIGHT = 943816
413
505
  * every output created since is subject to it. Pass `false` to validate the spend of a
414
506
  * pre-activation UTXO, which is exactly the distinction the node makes.
415
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
+ *
416
520
  * NOTE: script-number and element-size limits are NOT flags — they are process-wide
417
- * statics raised by `useGenesisLimits()`. A post-Genesis validator needs both this flag
418
- * 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.
419
523
  *
420
524
  * @param {object} [opts]
421
525
  * @param {boolean} [opts.afterChronicle=true] is the UTXO being spent post-activation
@@ -429,8 +533,6 @@ Interpreter.mainnetFlags = function (opts) {
429
533
  Interpreter.SCRIPT_VERIFY_LOW_S |
430
534
  Interpreter.SCRIPT_VERIFY_NULLFAIL |
431
535
  Interpreter.SCRIPT_VERIFY_MINIMALDATA |
432
- Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY |
433
- Interpreter.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY |
434
536
  Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID |
435
537
  Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES |
436
538
  Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES
@@ -440,6 +542,88 @@ Interpreter.mainnetFlags = function (opts) {
440
542
  return flags
441
543
  }
442
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
+
443
627
  /* Below flags apply in the context of BIP 68 */
444
628
  /**
445
629
  * If this flag set, CTxIn::nSequence is NOT interpreted as a relative
@@ -507,6 +691,20 @@ Interpreter.prototype.checkSignatureEncoding = function (buf) {
507
691
  return false
508
692
  }
509
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
+
510
708
  if ((this.flags & Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID) &&
511
709
  !(sig.nhashtype & Signature.SIGHASH_FORKID)) {
512
710
  this.errstr = 'SCRIPT_ERR_MUST_USE_FORKID'
@@ -535,6 +733,67 @@ Interpreter.prototype.checkPubkeyEncoding = function (buf) {
535
733
  *
536
734
  */
537
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
+
538
797
  Interpreter._isMinimallyEncoded = function (buf, nMaxNumSize) {
539
798
  nMaxNumSize = nMaxNumSize || Interpreter.MAXIMUM_ELEMENT_SIZE
540
799
  if (buf.length > nMaxNumSize) {
@@ -617,7 +876,7 @@ Interpreter._minimallyEncode = function (buf) {
617
876
  * bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
618
877
  */
619
878
  Interpreter.prototype.evaluate = function () {
620
- if (this.script.toBuffer().length > Interpreter.MAX_SCRIPT_SIZE) {
879
+ if (this.script.toBuffer().length > this.maxScriptSize()) {
621
880
  this.errstr = 'SCRIPT_ERR_SCRIPT_SIZE'
622
881
  return false
623
882
  }
@@ -630,6 +889,12 @@ Interpreter.prototype.evaluate = function () {
630
889
  return false
631
890
  }
632
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
+ }
633
898
  }
634
899
 
635
900
  // Size limits
@@ -638,7 +903,12 @@ Interpreter.prototype.evaluate = function () {
638
903
  return false
639
904
  }
640
905
  } catch (e) {
641
- 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)
642
912
  return false
643
913
  }
644
914
 
@@ -653,7 +923,7 @@ Interpreter.prototype.evaluate = function () {
653
923
  Interpreter.prototype._callbackStep = function (thisStep) {
654
924
  if (typeof this.stepListener === 'function') {
655
925
  try {
656
- this.stepListener(thisStep, cloneDeep(this.stack, true), cloneDeep(this.altstack, true))
926
+ this.stepListener(thisStep, cloneStack(this.stack), cloneStack(this.altstack))
657
927
  } catch (err) {
658
928
  console.log(`Error in Step callback:${err}`)
659
929
  }
@@ -699,7 +969,11 @@ Interpreter.prototype.checkLockTime = function (nLockTime) {
699
969
  // prevent this condition. Alternatively we could test all
700
970
  // inputs, but testing just this input minimizes the data
701
971
  // required to prove correct CHECKLOCKTIMEVERIFY execution.
702
- 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()) {
703
977
  return false
704
978
  }
705
979
 
@@ -713,9 +987,19 @@ Interpreter.prototype.checkLockTime = function (nLockTime) {
713
987
  * the transaction's sequence
714
988
  */
715
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
+
716
1000
  // Relative lock times are supported by comparing the passed in operand to
717
1001
  // the sequence number of the input.
718
- var txToSequence = this.tx.inputs[this.nin].sequenceNumber
1002
+ var txToSequence = input.sequenceNumber
719
1003
 
720
1004
  // Fail if the transaction's version number is not set high enough to
721
1005
  // trigger BIP 68 rules.
@@ -800,7 +1084,7 @@ Interpreter.prototype.step = function () {
800
1084
  // "disabled" is stronger than "unimplemented": a disabled opcode fails the
801
1085
  // script even in an UNEXECUTED branch, which is why this lives in
802
1086
  // isOpcodeDisabled rather than in the evaluation switch.
803
- if ((self.flags & Interpreter.SCRIPT_ENABLE_CHRONICLE) === 0) {
1087
+ if (!self.isAfterChronicle()) {
804
1088
  return true
805
1089
  }
806
1090
  break
@@ -838,8 +1122,6 @@ Interpreter.prototype.step = function () {
838
1122
 
839
1123
  var fRequireMinimal = (this.flags & Interpreter.SCRIPT_VERIFY_MINIMALDATA) !== 0
840
1124
 
841
- // bool fExec = !count(vfExec.begin(), vfExec.end(), false);
842
- var fExec = (this.vfExec.indexOf(false) === -1)
843
1125
  var buf, buf1, buf2, spliced, n, x1, x2, bn, bn1, bn2, bufSig, bufPubkey, subscript
844
1126
  var sig, pubkey
845
1127
  var fValue, fSuccess
@@ -848,22 +1130,35 @@ Interpreter.prototype.step = function () {
848
1130
  var chunk = this.script.chunks[this.pc]
849
1131
  this.pc++
850
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)
851
1142
  if (_.isUndefined(opcodenum)) {
852
1143
  this.errstr = 'SCRIPT_ERR_UNDEFINED_OPCODE'
853
1144
  return false
854
1145
  }
855
- if (chunk.buf && chunk.buf.length > Interpreter.MAX_SCRIPT_ELEMENT_SIZE) {
1146
+ if (chunk.buf && chunk.buf.length > this.maxScriptElementSize()) {
856
1147
  this.errstr = 'SCRIPT_ERR_PUSH_SIZE'
857
1148
  return false
858
1149
  }
859
1150
 
860
1151
  // Note how Opcode.OP_RESERVED does not count towards the opcode limit.
861
- if (opcodenum > Opcode.OP_16 && ++(this.nOpCount) > Interpreter.MAX_OPS_PER_SCRIPT) {
1152
+ if (opcodenum > Opcode.OP_16 && ++(this.nOpCount) > this.maxOpsPerScript()) {
862
1153
  this.errstr = 'SCRIPT_ERR_OP_COUNT'
863
1154
  return false
864
1155
  }
865
1156
 
866
- 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)) {
867
1162
  this.errstr = 'SCRIPT_ERR_DISABLED_OPCODE'
868
1163
  return false
869
1164
  }
@@ -876,7 +1171,13 @@ Interpreter.prototype.step = function () {
876
1171
  if (!chunk.buf) {
877
1172
  this.stack.push(Interpreter.false)
878
1173
  } else if (chunk.len !== chunk.buf.length) {
879
- 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
880
1181
  } else {
881
1182
  this.stack.push(chunk.buf)
882
1183
  }
@@ -918,7 +1219,14 @@ Interpreter.prototype.step = function () {
918
1219
  case Opcode.OP_NOP2:
919
1220
  case Opcode.OP_CHECKLOCKTIMEVERIFY:
920
1221
 
921
- 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()) {
922
1230
  // not enabled; treat as a NOP2
923
1231
  if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
924
1232
  this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
@@ -966,7 +1274,14 @@ Interpreter.prototype.step = function () {
966
1274
  case Opcode.OP_NOP3:
967
1275
  case Opcode.OP_CHECKSEQUENCEVERIFY:
968
1276
 
969
- 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()) {
970
1285
  // not enabled; treat as a NOP3
971
1286
  if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
972
1287
  this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
@@ -1037,7 +1352,7 @@ Interpreter.prototype.step = function () {
1037
1352
  //
1038
1353
  // Rejecting them outright would make this library refuse scripts the network
1039
1354
  // accepts, which is the mirror of the bug that made them silently succeed.
1040
- if ((this.flags & Interpreter.SCRIPT_ENABLE_CHRONICLE) === 0) {
1355
+ if (!this.isAfterChronicle()) {
1041
1356
  if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
1042
1357
  this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
1043
1358
  return false
@@ -1050,7 +1365,7 @@ Interpreter.prototype.step = function () {
1050
1365
  this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1051
1366
  return false
1052
1367
  }
1053
- var maxNumSize = Interpreter.MAXIMUM_ELEMENT_SIZE
1368
+ var maxNumSize = this.maxScriptNumLength()
1054
1369
  var shiftBn = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, maxNumSize)
1055
1370
  if (shiftBn.isNeg()) {
1056
1371
  this.errstr = 'SCRIPT_ERR_INVALID_NUMBER_RANGE'
@@ -1114,7 +1429,7 @@ Interpreter.prototype.step = function () {
1114
1429
  //
1115
1430
  // Unlike the string opcodes, BAD_OPCODE pre-Chronicle IS correct here —
1116
1431
  // the node returns it unconditionally.
1117
- if ((this.flags & Interpreter.SCRIPT_ENABLE_CHRONICLE) === 0) {
1432
+ if (!this.isAfterChronicle()) {
1118
1433
  this.errstr = 'SCRIPT_ERR_BAD_OPCODE'
1119
1434
  return false
1120
1435
  }
@@ -1138,8 +1453,13 @@ Interpreter.prototype.step = function () {
1138
1453
  // So pre-Chronicle they are an error only in an EXECUTED branch. BSV is
1139
1454
  // post-Genesis, which is the whole condition. Returning BAD_OPCODE
1140
1455
  // unconditionally rejected scripts the network accepts.
1141
- if ((this.flags & Interpreter.SCRIPT_ENABLE_CHRONICLE) === 0) {
1142
- 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) {
1143
1463
  break
1144
1464
  }
1145
1465
  this.errstr = 'SCRIPT_ERR_BAD_OPCODE'
@@ -1171,6 +1491,7 @@ Interpreter.prototype.step = function () {
1171
1491
  this.stack.pop()
1172
1492
  }
1173
1493
  this.vfExec.push(fValue)
1494
+ this.vfElse.push(false)
1174
1495
  break
1175
1496
 
1176
1497
  case Opcode.OP_IF:
@@ -1202,14 +1523,21 @@ Interpreter.prototype.step = function () {
1202
1523
  this.stack.pop()
1203
1524
  }
1204
1525
  this.vfExec.push(fValue)
1526
+ this.vfElse.push(false)
1205
1527
  break
1206
1528
 
1207
1529
  case Opcode.OP_ELSE:
1208
- 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())) {
1209
1536
  this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL'
1210
1537
  return false
1211
1538
  }
1212
1539
  this.vfExec[this.vfExec.length - 1] = !this.vfExec[this.vfExec.length - 1]
1540
+ this.vfElse[this.vfElse.length - 1] = true
1213
1541
  break
1214
1542
 
1215
1543
  case Opcode.OP_ENDIF:
@@ -1218,6 +1546,7 @@ Interpreter.prototype.step = function () {
1218
1546
  return false
1219
1547
  }
1220
1548
  this.vfExec.pop()
1549
+ this.vfElse.pop()
1221
1550
  break
1222
1551
 
1223
1552
  case Opcode.OP_VERIFY:
@@ -1238,6 +1567,21 @@ Interpreter.prototype.step = function () {
1238
1567
  break
1239
1568
 
1240
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.
1241
1585
  this.errstr = 'SCRIPT_ERR_OP_RETURN'
1242
1586
  return false
1243
1587
  // break // unreachable
@@ -1395,7 +1739,7 @@ Interpreter.prototype.step = function () {
1395
1739
  return false
1396
1740
  }
1397
1741
  buf = stacktop(-1)
1398
- bn = BN.fromScriptNumBuffer(buf, fRequireMinimal)
1742
+ bn = BN.fromScriptNumBuffer(buf, fRequireMinimal, this.maxScriptNumLength())
1399
1743
  n = bn.toNumber()
1400
1744
  this.stack.pop()
1401
1745
  if (n < 0 || n >= this.stack.length) {
@@ -1505,6 +1849,10 @@ Interpreter.prototype.step = function () {
1505
1849
  // (x -- out)
1506
1850
  if (this.stack.length < 1) {
1507
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
1508
1856
  }
1509
1857
  buf = stacktop(-1)
1510
1858
  for (let i = 0; i < buf.length; i++) {
@@ -1524,7 +1872,7 @@ Interpreter.prototype.step = function () {
1524
1872
  this.stack.pop()
1525
1873
  } else {
1526
1874
  bn1 = new BN(buf1)
1527
- bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal)
1875
+ bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength())
1528
1876
  n = bn2.toNumber()
1529
1877
  if (n < 0) {
1530
1878
  this.errstr = 'SCRIPT_ERR_INVALID_NUMBER_RANGE'
@@ -1589,7 +1937,7 @@ Interpreter.prototype.step = function () {
1589
1937
  return false
1590
1938
  }
1591
1939
  buf = stacktop(-1)
1592
- bn = BN.fromScriptNumBuffer(buf, fRequireMinimal)
1940
+ bn = BN.fromScriptNumBuffer(buf, fRequireMinimal, this.maxScriptNumLength())
1593
1941
  switch (opcodenum) {
1594
1942
  case Opcode.OP_2MUL:
1595
1943
  bn = bn.mul(new BN(2))
@@ -1648,8 +1996,8 @@ Interpreter.prototype.step = function () {
1648
1996
  this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1649
1997
  return false
1650
1998
  }
1651
- bn1 = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal, Interpreter.MAXIMUM_ELEMENT_SIZE)
1652
- 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())
1653
2001
  bn = new BN(0)
1654
2002
 
1655
2003
  switch (opcodenum) {
@@ -1666,8 +2014,12 @@ Interpreter.prototype.step = function () {
1666
2014
  break
1667
2015
 
1668
2016
  case Opcode.OP_DIV:
1669
- // denominator must not be 0
1670
- 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) {
1671
2023
  this.errstr = 'SCRIPT_ERR_DIV_BY_ZERO'
1672
2024
  return false
1673
2025
  }
@@ -1675,9 +2027,9 @@ Interpreter.prototype.step = function () {
1675
2027
  break
1676
2028
 
1677
2029
  case Opcode.OP_MOD:
1678
- // divisor must not be 0
1679
- if (bn2 === 0) {
1680
- 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'
1681
2033
  return false
1682
2034
  }
1683
2035
  bn = bn1.mod(bn2)
@@ -1747,9 +2099,9 @@ Interpreter.prototype.step = function () {
1747
2099
  this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1748
2100
  return false
1749
2101
  }
1750
- bn1 = BN.fromScriptNumBuffer(stacktop(-3), fRequireMinimal, Interpreter.MAXIMUM_ELEMENT_SIZE)
1751
- bn2 = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal, Interpreter.MAXIMUM_ELEMENT_SIZE)
1752
- 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())
1753
2105
  // bool fValue = (bn2 <= bn1 && bn1 < bn3);
1754
2106
  fValue = (bn2.cmp(bn1) <= 0) && (bn1.cmp(bn3) < 0)
1755
2107
  this.stack.pop()
@@ -1861,9 +2213,10 @@ Interpreter.prototype.step = function () {
1861
2213
  return false
1862
2214
  }
1863
2215
 
1864
- var nKeysCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal).toNumber()
2216
+ var nKeysCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal, this.maxScriptNumLength()).toNumber()
1865
2217
  // TODO: Keys and opcount are parameterized in client. No magic numbers!
1866
- if (nKeysCount < 0 || nKeysCount > 20) {
2218
+ // Genesis raised this to UINT32_MAX rather than removing it.
2219
+ if (nKeysCount < 0 || nKeysCount > this.maxPubKeysPerMultisig()) {
1867
2220
  this.errstr = 'SCRIPT_ERR_PUBKEY_COUNT'
1868
2221
  return false
1869
2222
  }
@@ -1887,7 +2240,7 @@ Interpreter.prototype.step = function () {
1887
2240
  return false
1888
2241
  }
1889
2242
 
1890
- var nSigsCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal).toNumber()
2243
+ var nSigsCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal, this.maxScriptNumLength()).toNumber()
1891
2244
  if (nSigsCount < 0 || nSigsCount > nKeysCount) {
1892
2245
  this.errstr = 'SCRIPT_ERR_SIG_COUNT'
1893
2246
  return false
@@ -2000,7 +2353,12 @@ Interpreter.prototype.step = function () {
2000
2353
 
2001
2354
  buf1 = stacktop(-2)
2002
2355
  buf2 = stacktop(-1)
2003
- 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()) {
2004
2362
  this.errstr = 'SCRIPT_ERR_PUSH_SIZE'
2005
2363
  return false
2006
2364
  }
@@ -2016,7 +2374,7 @@ Interpreter.prototype.step = function () {
2016
2374
  buf1 = stacktop(-2)
2017
2375
 
2018
2376
  // Make sure the split point is apropriate.
2019
- var position = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal).toNumber()
2377
+ var position = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength()).toNumber()
2020
2378
  if (position < 0 || position > buf1.length) {
2021
2379
  this.errstr = 'SCRIPT_ERR_INVALID_SPLIT_RANGE'
2022
2380
  return false
@@ -2046,7 +2404,7 @@ Interpreter.prototype.step = function () {
2046
2404
  //
2047
2405
  // Running them unconditionally consumed stack where the network does
2048
2406
  // nothing, which is a wrong answer rather than an error.
2049
- if ((this.flags & Interpreter.SCRIPT_ENABLE_CHRONICLE) === 0) {
2407
+ if (!this.isAfterChronicle()) {
2050
2408
  if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
2051
2409
  this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
2052
2410
  return false
@@ -2059,7 +2417,7 @@ Interpreter.prototype.step = function () {
2059
2417
  return false
2060
2418
  }
2061
2419
  buf1 = stacktop(-2)
2062
- n = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, Interpreter.MAXIMUM_ELEMENT_SIZE).toNumber()
2420
+ n = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength()).toNumber()
2063
2421
  // ERRORS on out of range; it does not clamp. The node is
2064
2422
  // `if(len < 0 || len > size) return SCRIPT_ERR_INVALID_NUMBER_RANGE`.
2065
2423
  // Clamping made scripts the node rejects succeed here.
@@ -2088,7 +2446,7 @@ Interpreter.prototype.step = function () {
2088
2446
  //
2089
2447
  // Running them unconditionally consumed stack where the network does
2090
2448
  // nothing, which is a wrong answer rather than an error.
2091
- if ((this.flags & Interpreter.SCRIPT_ENABLE_CHRONICLE) === 0) {
2449
+ if (!this.isAfterChronicle()) {
2092
2450
  if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
2093
2451
  this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
2094
2452
  return false
@@ -2101,8 +2459,8 @@ Interpreter.prototype.step = function () {
2101
2459
  return false
2102
2460
  }
2103
2461
  buf1 = stacktop(-3)
2104
- var subSize = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, Interpreter.MAXIMUM_ELEMENT_SIZE).toNumber()
2105
- 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()
2106
2464
  // ERRORS on out of range, matching
2107
2465
  // offset < 0 || offset >= size || len < 0 || len > size - offset
2108
2466
  // Note `offset >= size` is strict: a begin index AT the end is an
@@ -2126,8 +2484,12 @@ Interpreter.prototype.step = function () {
2126
2484
  return false
2127
2485
  }
2128
2486
 
2129
- var size = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal).toNumber()
2130
- 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()) {
2131
2493
  this.errstr = 'SCRIPT_ERR_PUSH_SIZE'
2132
2494
  return false
2133
2495
  }