@smartledger/bsv 7.13.0 → 8.0.1
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.
- package/CHANGELOG.md +151 -0
- package/README.md +38 -38
- package/bsv-gdaf.min.js +55 -55
- package/bsv-ltp.min.js +39 -39
- package/bsv-smartcontract.min.js +1 -1
- package/bsv.bundle.js +55 -55
- package/bsv.min.js +55 -55
- package/docs/AUDIT_SCOPE.md +21 -12
- package/docs/MODULE_REFERENCE_COMPLETE.md +27 -27
- package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
- package/docs/getting-started/INSTALLATION.md +23 -23
- package/docs/getting-started/QUICK_START.md +7 -7
- package/docs/migration/FROM_BSV_1_5_6.md +5 -5
- package/lib/crypto/bn.js +22 -2
- package/lib/script/interpreter.js +396 -58
- package/lib/transaction/sighash.js +18 -6
- package/package.json +4 -1
- package/test/consensus/base58-vectors.js +120 -0
- package/test/consensus/sv-script-vectors.js +81 -0
- package/test/consensus/sv-sighash-vectors.js +51 -0
- package/test/consensus/sv-tx-vectors.js +48 -0
- package/test/data/bitcoin-sv/README.md +170 -0
- package/test/data/bitcoin-sv/base58_encode_decode.json +14 -0
- package/test/data/bitcoin-sv/base58_keys_invalid.json +152 -0
- package/test/data/bitcoin-sv/base58_keys_valid.json +452 -0
- package/test/data/bitcoin-sv/script_tests.json +2591 -0
- package/test/data/bitcoin-sv/sighash.json +1003 -0
- package/test/data/bitcoin-sv/tx_invalid.json +285 -0
- package/test/data/bitcoin-sv/tx_valid.json +367 -0
- package/test/regressions.js +35 -0
- package/test/script/chronicle.js +170 -25
- package/test/script/defaults.js +160 -0
- package/test/script/genesis_limits.js +62 -6
- package/test/script/interpreter.js +24 -8
- package/test/transaction/sighash.js +21 -1
- 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 =
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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,19 @@ 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
|
+
|
|
240
271
|
// Maximum number of non-push opcodes per script. Pre-Genesis consensus is 201;
|
|
241
272
|
// post-Genesis BSV removed this limit. Exposed as a constant (instead of a magic
|
|
242
273
|
// number) so applications can opt into post-Genesis rules — e.g. OP_PUSH_TX
|
|
243
274
|
// covenants, which need a few hundred opcodes — without forking the interpreter.
|
|
244
|
-
|
|
275
|
+
// BSV's pre-Genesis figure is 500, not Bitcoin Core's 201: the limit was
|
|
276
|
+
// raised before Genesis removed it altogether. Carrying Core's number rejected
|
|
277
|
+
// scripts the network accepted.
|
|
278
|
+
Interpreter.MAX_OPS_PER_SCRIPT = 500
|
|
245
279
|
// Maximum total serialized script size. Pre-Genesis consensus is 10,000 bytes;
|
|
246
280
|
// post-Genesis BSV removed this limit too. It was previously a literal inside
|
|
247
281
|
// evaluate(), so `useGenesisLimits()` could not lift it and any script over 10 KB —
|
|
@@ -249,6 +283,16 @@ Interpreter.MAX_OPS_PER_SCRIPT = 201
|
|
|
249
283
|
// no matter what the caller asked for.
|
|
250
284
|
Interpreter.MAX_SCRIPT_SIZE = 10000
|
|
251
285
|
|
|
286
|
+
// Genesis and Chronicle limits, from the node's src/consensus/consensus.h.
|
|
287
|
+
// These are the values the WIP note above asked to be pinned against the node
|
|
288
|
+
// source: Genesis raised the script-number bound to 750,000 bytes and
|
|
289
|
+
// Chronicle to 32,000,000, and removed the element, script size and operation
|
|
290
|
+
// caps outright.
|
|
291
|
+
Interpreter.UNLIMITED = Number.MAX_SAFE_INTEGER
|
|
292
|
+
Interpreter.MAX_SCRIPT_NUM_LENGTH_AFTER_GENESIS = 750000
|
|
293
|
+
Interpreter.MAX_SCRIPT_NUM_LENGTH_AFTER_CHRONICLE = 32000000
|
|
294
|
+
Interpreter.MAX_PUBKEYS_PER_MULTISIG_AFTER_GENESIS = 4294967295
|
|
295
|
+
|
|
252
296
|
Interpreter.LOCKTIME_THRESHOLD = 500000000
|
|
253
297
|
Interpreter.LOCKTIME_THRESHOLD_BN = new BN(Interpreter.LOCKTIME_THRESHOLD)
|
|
254
298
|
|
|
@@ -398,17 +442,41 @@ Interpreter.SCRIPT_ENABLE_REPLAY_PROTECTION = (1 << 17)
|
|
|
398
442
|
|
|
399
443
|
// Enable new opcodes.
|
|
400
444
|
//
|
|
401
|
-
|
|
445
|
+
// Moved off 1<<18 and 1<<19, which the reference node assigns to
|
|
446
|
+
// SCRIPT_GENESIS and SCRIPT_UTXO_AFTER_GENESIS. Sharing those bits meant that
|
|
447
|
+
// node-derived flags passed into this library were silently read as something
|
|
448
|
+
// else. These two are BCH-era flags the node does not define at all, so their
|
|
449
|
+
// positions carry no consensus meaning and are free to move.
|
|
450
|
+
Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES = (1 << 11)
|
|
402
451
|
|
|
403
452
|
// Are the Magnetic upgrade opcodes enabled?
|
|
404
453
|
//
|
|
405
|
-
Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES = (1 <<
|
|
454
|
+
Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES = (1 << 12)
|
|
455
|
+
|
|
456
|
+
// The era flags, at the bit positions src/script/script_flags.h assigns them.
|
|
457
|
+
// Keep them in sync: they are consensus-relevant and are passed across the
|
|
458
|
+
// boundary with node-derived test vectors.
|
|
459
|
+
//
|
|
460
|
+
// The distinction between the pairs matters. SCRIPT_UTXO_AFTER_* describes the
|
|
461
|
+
// output being spent and governs almost every rule, because an output made
|
|
462
|
+
// before an upgrade is spent under the old rules forever. SCRIPT_GENESIS and
|
|
463
|
+
// SCRIPT_CHRONICLE describe the block the spending transaction is in.
|
|
464
|
+
Interpreter.SCRIPT_GENESIS = (1 << 18)
|
|
465
|
+
Interpreter.SCRIPT_UTXO_AFTER_GENESIS = (1 << 19)
|
|
406
466
|
|
|
407
467
|
// Chronicle restores OP_2MUL/OP_2DIV and gives OP_VER/OP_VERIF/OP_VERNOTIF meaning.
|
|
408
468
|
// Off by default: enabling it changes script evaluation, so it is an explicit opt-in
|
|
409
469
|
// exactly like the Monolith and Magnetic flags above.
|
|
410
470
|
Interpreter.SCRIPT_ENABLE_CHRONICLE = (1 << 20)
|
|
411
471
|
|
|
472
|
+
// The node's name for the same bit: Chronicle rules apply to the block the
|
|
473
|
+
// spending transaction is in.
|
|
474
|
+
Interpreter.SCRIPT_CHRONICLE = Interpreter.SCRIPT_ENABLE_CHRONICLE
|
|
475
|
+
|
|
476
|
+
// Was the output being spent created after Chronicle activated? This is what
|
|
477
|
+
// the node gates the restored opcodes on.
|
|
478
|
+
Interpreter.SCRIPT_UTXO_AFTER_CHRONICLE = (1 << 21)
|
|
479
|
+
|
|
412
480
|
/**
|
|
413
481
|
* Block height at which Chronicle activated on BSV mainnet (2026-04-07).
|
|
414
482
|
*
|
|
@@ -432,9 +500,21 @@ Interpreter.CHRONICLE_ACTIVATION_HEIGHT = 943816
|
|
|
432
500
|
* every output created since is subject to it. Pass `false` to validate the spend of a
|
|
433
501
|
* pre-activation UTXO, which is exactly the distinction the node makes.
|
|
434
502
|
*
|
|
503
|
+
* CLTV and CSV are deliberately ABSENT. Genesis reverted both opcodes to OP_NOP2/OP_NOP3,
|
|
504
|
+
* and the node ignores their flags entirely once the UTXO is post-Genesis:
|
|
505
|
+
*
|
|
506
|
+
* if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) || utxo_after_genesis) {
|
|
507
|
+
* // not enabled; treat as a NOP2
|
|
508
|
+
*
|
|
509
|
+
* Including them made this function reject `<n> OP_CHECKLOCKTIMEVERIFY OP_DROP OP_1`,
|
|
510
|
+
* which mainnet accepts — a validator STRICTER than consensus, which is as wrong as one
|
|
511
|
+
* that is looser and harder to notice, because nothing that tests this library against
|
|
512
|
+
* itself can see it. The flags still exist for callers deliberately emulating
|
|
513
|
+
* pre-Genesis rules; they are simply not mainnet.
|
|
514
|
+
*
|
|
435
515
|
* NOTE: script-number and element-size limits are NOT flags — they are process-wide
|
|
436
|
-
* statics
|
|
437
|
-
*
|
|
516
|
+
* statics. This function cannot set them, which is why `useMainnetConsensus()` exists;
|
|
517
|
+
* prefer it unless you are managing the limits yourself.
|
|
438
518
|
*
|
|
439
519
|
* @param {object} [opts]
|
|
440
520
|
* @param {boolean} [opts.afterChronicle=true] is the UTXO being spent post-activation
|
|
@@ -448,17 +528,97 @@ Interpreter.mainnetFlags = function (opts) {
|
|
|
448
528
|
Interpreter.SCRIPT_VERIFY_LOW_S |
|
|
449
529
|
Interpreter.SCRIPT_VERIFY_NULLFAIL |
|
|
450
530
|
Interpreter.SCRIPT_VERIFY_MINIMALDATA |
|
|
451
|
-
Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY |
|
|
452
|
-
Interpreter.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY |
|
|
453
531
|
Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID |
|
|
454
532
|
Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES |
|
|
455
|
-
Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES
|
|
533
|
+
Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES |
|
|
534
|
+
// The era flags. Without these the interpreter falls back to the pre-Genesis
|
|
535
|
+
// statics, so a validator built from a helper named after mainnet was applying
|
|
536
|
+
// 2019 limits — most sharply the 4-byte script-number bound, where post-Genesis
|
|
537
|
+
// is 750,000 and post-Chronicle 32,000,000. Genesis is unconditional here: it
|
|
538
|
+
// activated in 2020 and cannot be opted out of by anything still being spent.
|
|
539
|
+
Interpreter.SCRIPT_GENESIS |
|
|
540
|
+
Interpreter.SCRIPT_UTXO_AFTER_GENESIS
|
|
456
541
|
if (opts.afterChronicle !== false) {
|
|
457
|
-
flags |= Interpreter.SCRIPT_ENABLE_CHRONICLE
|
|
542
|
+
flags |= Interpreter.SCRIPT_ENABLE_CHRONICLE | Interpreter.SCRIPT_UTXO_AFTER_CHRONICLE
|
|
458
543
|
}
|
|
459
544
|
return flags
|
|
460
545
|
}
|
|
461
546
|
|
|
547
|
+
/**
|
|
548
|
+
* Configure this process for BSV mainnet consensus and return the matching flags.
|
|
549
|
+
*
|
|
550
|
+
* Flags and limits are separate mechanisms here — flags are an argument to `verify()`,
|
|
551
|
+
* limits are process-wide statics — and that split is what made `mainnetFlags()` alone
|
|
552
|
+
* insufficient: it returns mainnet flags while the interpreter still holds the
|
|
553
|
+
* PRE-Genesis 520 / 201 / 10,000 caps, so a 12,801-byte script valid on mainnet was
|
|
554
|
+
* rejected with SCRIPT_ERR_SCRIPT_SIZE.
|
|
555
|
+
*
|
|
556
|
+
* This is the single call that makes both agree. It MUTATES process-wide state, which is
|
|
557
|
+
* why it is named `use*` like `useGenesisLimits()` rather than reading like a getter.
|
|
558
|
+
*
|
|
559
|
+
* @param {object} [opts]
|
|
560
|
+
* @param {boolean} [opts.afterChronicle=true] is the UTXO being spent post-activation
|
|
561
|
+
* @param {number} [opts.max] element-size ceiling to pass through to useGenesisLimits()
|
|
562
|
+
* @returns {number} the flags to hand to verify()
|
|
563
|
+
*/
|
|
564
|
+
/**
|
|
565
|
+
* The flags describing BSV mainnet as it is today, and the default for `verify()`.
|
|
566
|
+
*
|
|
567
|
+
* Until 8.0.0 `verify()` defaulted to `0` — no rules at all. A BSV library whose
|
|
568
|
+
* out-of-the-box answer described Bitcoin in 2015 is wrong in the direction that is
|
|
569
|
+
* hardest to notice: it accepts scripts the network rejects, and nothing that tests this
|
|
570
|
+
* library against itself can see it. The era now has to be stated to get anything else.
|
|
571
|
+
*
|
|
572
|
+
* The set is derived from what the node applies, not assembled by judgement:
|
|
573
|
+
*
|
|
574
|
+
* MONOLITH / MAGNETIC BSV restored these opcodes in 2018 and the node does not gate
|
|
575
|
+
* them. This library still does, so omitting them here would be
|
|
576
|
+
* STRICTER than consensus. tools/sv-vector-harness.js sets the
|
|
577
|
+
* same pair as its baseline for every vector, for this reason.
|
|
578
|
+
* GENESIS rules keyed to the era of the spending transaction
|
|
579
|
+
* UTXO_AFTER_GENESIS rules keyed to the era of the output being spent (2020)
|
|
580
|
+
* CHRONICLE the spending transaction's era (2026)
|
|
581
|
+
* UTXO_AFTER_CHRONICLE the spent output's era
|
|
582
|
+
*
|
|
583
|
+
* Spending a pre-activation output is the explicit case, because that is the input the
|
|
584
|
+
* caller knows and the library cannot: `mainnetFlags({ afterChronicle: false })`, or a
|
|
585
|
+
* hand-assembled set for older eras.
|
|
586
|
+
*
|
|
587
|
+
* FORKID is deliberately absent here and added by `verify()` only when the input amount
|
|
588
|
+
* is available, since the digest cannot be computed without it.
|
|
589
|
+
*
|
|
590
|
+
* @returns {number}
|
|
591
|
+
*/
|
|
592
|
+
Interpreter.currentConsensusFlags = function () {
|
|
593
|
+
return Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES |
|
|
594
|
+
Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES |
|
|
595
|
+
Interpreter.SCRIPT_GENESIS |
|
|
596
|
+
Interpreter.SCRIPT_UTXO_AFTER_GENESIS |
|
|
597
|
+
Interpreter.SCRIPT_ENABLE_CHRONICLE |
|
|
598
|
+
Interpreter.SCRIPT_UTXO_AFTER_CHRONICLE |
|
|
599
|
+
Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
Interpreter.useMainnetConsensus = function (opts) {
|
|
603
|
+
opts = opts || {}
|
|
604
|
+
Interpreter.useGenesisLimits(opts.max)
|
|
605
|
+
|
|
606
|
+
// The script-number bound is NOT set here. It is era-derived from the flags by
|
|
607
|
+
// Interpreter#maxScriptNumLength(): 4 bytes pre-Genesis, 750,000 after Genesis,
|
|
608
|
+
// 32,000,000 after Chronicle. An earlier version of this function pinned
|
|
609
|
+
// MAXIMUM_ELEMENT_SIZE to a static value to stop useGenesisLimits() raising it to
|
|
610
|
+
// 0x7fffffff, which made Chronicle's shift-overflow check unreachable. That was
|
|
611
|
+
// treating the symptom: the real defect was mainnetFlags() omitting the era flags,
|
|
612
|
+
// so the era-derived bound never applied. Fixed there instead.
|
|
613
|
+
//
|
|
614
|
+
// The node's vectors settle the pre-Genesis value at 4 and are silent on the rest —
|
|
615
|
+
// all 22 SCRIPTNUM_OVERFLOW rows carry P2SH,STRICTENC and no era flag. Raising the
|
|
616
|
+
// static bound to 8 turns 15 of them into false accepts, which is how that was
|
|
617
|
+
// measured.
|
|
618
|
+
|
|
619
|
+
return Interpreter.mainnetFlags(opts)
|
|
620
|
+
}
|
|
621
|
+
|
|
462
622
|
/* Below flags apply in the context of BIP 68 */
|
|
463
623
|
/**
|
|
464
624
|
* If this flag set, CTxIn::nSequence is NOT interpreted as a relative
|
|
@@ -526,6 +686,20 @@ Interpreter.prototype.checkSignatureEncoding = function (buf) {
|
|
|
526
686
|
return false
|
|
527
687
|
}
|
|
528
688
|
|
|
689
|
+
// A signature may only ask for the original digest where Chronicle
|
|
690
|
+
// applies. This is where the node stops a pre-Chronicle signature whose
|
|
691
|
+
// type byte happens to set 0x20 from being read as one asking for OTDA:
|
|
692
|
+
//
|
|
693
|
+
// if(!chronicleEnabled && usesChronicle) return SCRIPT_ERR_ILLEGAL_CHRONICLE;
|
|
694
|
+
//
|
|
695
|
+
// It rejects such a signature outright rather than reinterpreting it,
|
|
696
|
+
// which is why SignatureHash() itself can route on the bit alone.
|
|
697
|
+
if (!(this.flags & Interpreter.SCRIPT_CHRONICLE) &&
|
|
698
|
+
(sig.nhashtype & Signature.SIGHASH_CHRONICLE)) {
|
|
699
|
+
this.errstr = 'SCRIPT_ERR_ILLEGAL_CHRONICLE'
|
|
700
|
+
return false
|
|
701
|
+
}
|
|
702
|
+
|
|
529
703
|
if ((this.flags & Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID) &&
|
|
530
704
|
!(sig.nhashtype & Signature.SIGHASH_FORKID)) {
|
|
531
705
|
this.errstr = 'SCRIPT_ERR_MUST_USE_FORKID'
|
|
@@ -554,6 +728,67 @@ Interpreter.prototype.checkPubkeyEncoding = function (buf) {
|
|
|
554
728
|
*
|
|
555
729
|
*/
|
|
556
730
|
|
|
731
|
+
/**
|
|
732
|
+
* Which era's rules apply.
|
|
733
|
+
*
|
|
734
|
+
* The node decides almost everything by the era of the output being spent, so
|
|
735
|
+
* these read the SCRIPT_UTXO_AFTER_* flags rather than a process-wide setting.
|
|
736
|
+
* A caller that sets no era flag gets the previous behaviour exactly: the
|
|
737
|
+
* limit methods below fall back to the mutable statics, so useGenesisLimits()
|
|
738
|
+
* and setLimits() keep working as they did.
|
|
739
|
+
*/
|
|
740
|
+
Interpreter.prototype.isAfterGenesis = function () {
|
|
741
|
+
return (this.flags & Interpreter.SCRIPT_UTXO_AFTER_GENESIS) !== 0
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* SCRIPT_ENABLE_CHRONICLE is accepted alongside SCRIPT_UTXO_AFTER_CHRONICLE.
|
|
746
|
+
* The former is this library's existing opt-in and sits on the node's
|
|
747
|
+
* SCRIPT_CHRONICLE bit; the latter is what the node actually gates the
|
|
748
|
+
* restored opcodes on. Either enables them, so existing callers are unaffected.
|
|
749
|
+
*/
|
|
750
|
+
Interpreter.prototype.isAfterChronicle = function () {
|
|
751
|
+
return (this.flags &
|
|
752
|
+
(Interpreter.SCRIPT_UTXO_AFTER_CHRONICLE | Interpreter.SCRIPT_ENABLE_CHRONICLE)) !== 0
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
/** Genesis removed this limit; before it, whatever the statics say. */
|
|
756
|
+
Interpreter.prototype.maxScriptElementSize = function () {
|
|
757
|
+
return this.isAfterGenesis() ? Interpreter.UNLIMITED : Interpreter.MAX_SCRIPT_ELEMENT_SIZE
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
/** Genesis removed this limit too. */
|
|
761
|
+
Interpreter.prototype.maxScriptSize = function () {
|
|
762
|
+
return this.isAfterGenesis() ? Interpreter.UNLIMITED : Interpreter.MAX_SCRIPT_SIZE
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
/** And this one. Note the pre-Genesis figure on BSV is 500, not Core's 201. */
|
|
766
|
+
Interpreter.prototype.maxOpsPerScript = function () {
|
|
767
|
+
return this.isAfterGenesis() ? Interpreter.UNLIMITED : Interpreter.MAX_OPS_PER_SCRIPT
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
/**
|
|
771
|
+
* The widest a script number may be. Four bytes before Genesis, which is why
|
|
772
|
+
* pre-Genesis contracts cannot do arithmetic on satoshi amounts; Genesis
|
|
773
|
+
* raised it to 750KB and Chronicle to 32MB.
|
|
774
|
+
*/
|
|
775
|
+
Interpreter.prototype.maxScriptNumLength = function () {
|
|
776
|
+
if (this.isAfterChronicle()) {
|
|
777
|
+
return Interpreter.MAX_SCRIPT_NUM_LENGTH_AFTER_CHRONICLE
|
|
778
|
+
}
|
|
779
|
+
if (this.isAfterGenesis()) {
|
|
780
|
+
return Interpreter.MAX_SCRIPT_NUM_LENGTH_AFTER_GENESIS
|
|
781
|
+
}
|
|
782
|
+
return Interpreter.MAXIMUM_ELEMENT_SIZE
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
/** Genesis raised this rather than removing it: the node caps at UINT32_MAX. */
|
|
786
|
+
Interpreter.prototype.maxPubKeysPerMultisig = function () {
|
|
787
|
+
return this.isAfterGenesis()
|
|
788
|
+
? Interpreter.MAX_PUBKEYS_PER_MULTISIG_AFTER_GENESIS
|
|
789
|
+
: 20
|
|
790
|
+
}
|
|
791
|
+
|
|
557
792
|
Interpreter._isMinimallyEncoded = function (buf, nMaxNumSize) {
|
|
558
793
|
nMaxNumSize = nMaxNumSize || Interpreter.MAXIMUM_ELEMENT_SIZE
|
|
559
794
|
if (buf.length > nMaxNumSize) {
|
|
@@ -636,7 +871,7 @@ Interpreter._minimallyEncode = function (buf) {
|
|
|
636
871
|
* bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
|
|
637
872
|
*/
|
|
638
873
|
Interpreter.prototype.evaluate = function () {
|
|
639
|
-
if (this.script.toBuffer().length >
|
|
874
|
+
if (this.script.toBuffer().length > this.maxScriptSize()) {
|
|
640
875
|
this.errstr = 'SCRIPT_ERR_SCRIPT_SIZE'
|
|
641
876
|
return false
|
|
642
877
|
}
|
|
@@ -649,6 +884,12 @@ Interpreter.prototype.evaluate = function () {
|
|
|
649
884
|
return false
|
|
650
885
|
}
|
|
651
886
|
this._callbackStep(thisStep)
|
|
887
|
+
if (this.returned) {
|
|
888
|
+
// A top-level OP_RETURN after Genesis: the script is over and the top
|
|
889
|
+
// stack item decides. Nothing after it is read, so an unbalanced
|
|
890
|
+
// conditional or an invalid opcode beyond this point is not an error.
|
|
891
|
+
return true
|
|
892
|
+
}
|
|
652
893
|
}
|
|
653
894
|
|
|
654
895
|
// Size limits
|
|
@@ -657,7 +898,12 @@ Interpreter.prototype.evaluate = function () {
|
|
|
657
898
|
return false
|
|
658
899
|
}
|
|
659
900
|
} catch (e) {
|
|
660
|
-
|
|
901
|
+
// An error that knows the node's result code reports it. Script number
|
|
902
|
+
// decoding is the case that matters: 78 of the corpus's rejected vectors
|
|
903
|
+
// expect SCRIPTNUM_MINENCODE or SCRIPTNUM_OVERFLOW, and every one of them
|
|
904
|
+
// used to arrive here and be flattened into UNKNOWN_ERROR. The script
|
|
905
|
+
// failed either way, so the accept/reject vectors could not see it.
|
|
906
|
+
this.errstr = e.scriptErr || ('SCRIPT_ERR_UNKNOWN_ERROR: ' + e)
|
|
661
907
|
return false
|
|
662
908
|
}
|
|
663
909
|
|
|
@@ -718,7 +964,11 @@ Interpreter.prototype.checkLockTime = function (nLockTime) {
|
|
|
718
964
|
// prevent this condition. Alternatively we could test all
|
|
719
965
|
// inputs, but testing just this input minimizes the data
|
|
720
966
|
// required to prove correct CHECKLOCKTIMEVERIFY execution.
|
|
721
|
-
|
|
967
|
+
// Same guard as checkSequence: no input at `nin` means the locktime cannot be
|
|
968
|
+
// satisfied. Reached only when the comparisons above pass, which is why this one
|
|
969
|
+
// never surfaced as a TypeError — the ordering hid it, not a check.
|
|
970
|
+
var input = this.tx.inputs[this.nin]
|
|
971
|
+
if (!input || input.isFinal()) {
|
|
722
972
|
return false
|
|
723
973
|
}
|
|
724
974
|
|
|
@@ -732,9 +982,19 @@ Interpreter.prototype.checkLockTime = function (nLockTime) {
|
|
|
732
982
|
* the transaction's sequence
|
|
733
983
|
*/
|
|
734
984
|
Interpreter.prototype.checkSequence = function (nSequence) {
|
|
985
|
+
// No input at `nin` means the relative locktime cannot be satisfied, so fail the
|
|
986
|
+
// script rather than dereferencing undefined. This used to throw a TypeError that the
|
|
987
|
+
// evaluator's try/catch converted into SCRIPT_ERR_UNKNOWN_ERROR — a misleading error
|
|
988
|
+
// that pointed at the script instead of at the caller's index. The same shape as the
|
|
989
|
+
// `new BN(...)` note below, and as the CHECKLOCKTIMEVERIFY guard.
|
|
990
|
+
var input = this.tx.inputs[this.nin]
|
|
991
|
+
if (!input) {
|
|
992
|
+
return false
|
|
993
|
+
}
|
|
994
|
+
|
|
735
995
|
// Relative lock times are supported by comparing the passed in operand to
|
|
736
996
|
// the sequence number of the input.
|
|
737
|
-
var txToSequence =
|
|
997
|
+
var txToSequence = input.sequenceNumber
|
|
738
998
|
|
|
739
999
|
// Fail if the transaction's version number is not set high enough to
|
|
740
1000
|
// trigger BIP 68 rules.
|
|
@@ -819,7 +1079,7 @@ Interpreter.prototype.step = function () {
|
|
|
819
1079
|
// "disabled" is stronger than "unimplemented": a disabled opcode fails the
|
|
820
1080
|
// script even in an UNEXECUTED branch, which is why this lives in
|
|
821
1081
|
// isOpcodeDisabled rather than in the evaluation switch.
|
|
822
|
-
if (
|
|
1082
|
+
if (!self.isAfterChronicle()) {
|
|
823
1083
|
return true
|
|
824
1084
|
}
|
|
825
1085
|
break
|
|
@@ -857,8 +1117,6 @@ Interpreter.prototype.step = function () {
|
|
|
857
1117
|
|
|
858
1118
|
var fRequireMinimal = (this.flags & Interpreter.SCRIPT_VERIFY_MINIMALDATA) !== 0
|
|
859
1119
|
|
|
860
|
-
// bool fExec = !count(vfExec.begin(), vfExec.end(), false);
|
|
861
|
-
var fExec = (this.vfExec.indexOf(false) === -1)
|
|
862
1120
|
var buf, buf1, buf2, spliced, n, x1, x2, bn, bn1, bn2, bufSig, bufPubkey, subscript
|
|
863
1121
|
var sig, pubkey
|
|
864
1122
|
var fValue, fSuccess
|
|
@@ -867,22 +1125,35 @@ Interpreter.prototype.step = function () {
|
|
|
867
1125
|
var chunk = this.script.chunks[this.pc]
|
|
868
1126
|
this.pc++
|
|
869
1127
|
var opcodenum = chunk.opcodenum
|
|
1128
|
+
|
|
1129
|
+
// bool fExec = !count(vfExec.begin(), vfExec.end(), false);
|
|
1130
|
+
//
|
|
1131
|
+
// Computed after the opcode is read, because it depends on it: once an
|
|
1132
|
+
// OP_RETURN has been seen inside a conditional after Genesis, nothing but a
|
|
1133
|
+
// further OP_RETURN executes, while the conditional grammar is still checked
|
|
1134
|
+
// through to the end of the script.
|
|
1135
|
+
var fExec = (this.vfExec.indexOf(false) === -1) &&
|
|
1136
|
+
(!this.nonTopLevelReturnAfterGenesis || opcodenum === Opcode.OP_RETURN)
|
|
870
1137
|
if (_.isUndefined(opcodenum)) {
|
|
871
1138
|
this.errstr = 'SCRIPT_ERR_UNDEFINED_OPCODE'
|
|
872
1139
|
return false
|
|
873
1140
|
}
|
|
874
|
-
if (chunk.buf && chunk.buf.length >
|
|
1141
|
+
if (chunk.buf && chunk.buf.length > this.maxScriptElementSize()) {
|
|
875
1142
|
this.errstr = 'SCRIPT_ERR_PUSH_SIZE'
|
|
876
1143
|
return false
|
|
877
1144
|
}
|
|
878
1145
|
|
|
879
1146
|
// Note how Opcode.OP_RESERVED does not count towards the opcode limit.
|
|
880
|
-
if (opcodenum > Opcode.OP_16 && ++(this.nOpCount) >
|
|
1147
|
+
if (opcodenum > Opcode.OP_16 && ++(this.nOpCount) > this.maxOpsPerScript()) {
|
|
881
1148
|
this.errstr = 'SCRIPT_ERR_OP_COUNT'
|
|
882
1149
|
return false
|
|
883
1150
|
}
|
|
884
1151
|
|
|
885
|
-
|
|
1152
|
+
// Before Genesis the mere presence of a disabled opcode invalidates the
|
|
1153
|
+
// script, even in a branch that never runs. After it, only executing one
|
|
1154
|
+
// fails — the node states it as `IsOpcodeDisabled(...) && (!utxo_after_genesis
|
|
1155
|
+
// || fExec)`.
|
|
1156
|
+
if (isOpcodeDisabled(opcodenum) && (!this.isAfterGenesis() || fExec)) {
|
|
886
1157
|
this.errstr = 'SCRIPT_ERR_DISABLED_OPCODE'
|
|
887
1158
|
return false
|
|
888
1159
|
}
|
|
@@ -895,7 +1166,13 @@ Interpreter.prototype.step = function () {
|
|
|
895
1166
|
if (!chunk.buf) {
|
|
896
1167
|
this.stack.push(Interpreter.false)
|
|
897
1168
|
} else if (chunk.len !== chunk.buf.length) {
|
|
898
|
-
|
|
1169
|
+
// A push that declares more bytes than the script carries — "PUSHDATA1
|
|
1170
|
+
// with not enough bytes" and its PUSHDATA2/4 counterparts. The node
|
|
1171
|
+
// fails these as SCRIPT_ERR_BAD_OPCODE. Throwing reached the evaluator's
|
|
1172
|
+
// catch and became UNKNOWN_ERROR; this is inside step(), which can
|
|
1173
|
+
// simply fail.
|
|
1174
|
+
this.errstr = 'SCRIPT_ERR_BAD_OPCODE'
|
|
1175
|
+
return false
|
|
899
1176
|
} else {
|
|
900
1177
|
this.stack.push(chunk.buf)
|
|
901
1178
|
}
|
|
@@ -937,7 +1214,14 @@ Interpreter.prototype.step = function () {
|
|
|
937
1214
|
case Opcode.OP_NOP2:
|
|
938
1215
|
case Opcode.OP_CHECKLOCKTIMEVERIFY:
|
|
939
1216
|
|
|
940
|
-
|
|
1217
|
+
// Genesis reverted this to an upgradable NOP for outputs created
|
|
1218
|
+
// after it, so a post-Genesis script containing it enforces no
|
|
1219
|
+
// locktime at all. The node reads
|
|
1220
|
+
// !(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) || utxo_after_genesis
|
|
1221
|
+
// and without the second half a transaction the network accepts is
|
|
1222
|
+
// rejected here.
|
|
1223
|
+
if (!(this.flags & Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) ||
|
|
1224
|
+
this.isAfterGenesis()) {
|
|
941
1225
|
// not enabled; treat as a NOP2
|
|
942
1226
|
if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
|
|
943
1227
|
this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
|
|
@@ -985,7 +1269,14 @@ Interpreter.prototype.step = function () {
|
|
|
985
1269
|
case Opcode.OP_NOP3:
|
|
986
1270
|
case Opcode.OP_CHECKSEQUENCEVERIFY:
|
|
987
1271
|
|
|
988
|
-
|
|
1272
|
+
// Genesis reverted this to an upgradable NOP for outputs created
|
|
1273
|
+
// after it, so a post-Genesis script containing it enforces no
|
|
1274
|
+
// locktime at all. The node reads
|
|
1275
|
+
// !(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY) || utxo_after_genesis
|
|
1276
|
+
// and without the second half a transaction the network accepts is
|
|
1277
|
+
// rejected here.
|
|
1278
|
+
if (!(this.flags & Interpreter.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY) ||
|
|
1279
|
+
this.isAfterGenesis()) {
|
|
989
1280
|
// not enabled; treat as a NOP3
|
|
990
1281
|
if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
|
|
991
1282
|
this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
|
|
@@ -1056,7 +1347,7 @@ Interpreter.prototype.step = function () {
|
|
|
1056
1347
|
//
|
|
1057
1348
|
// Rejecting them outright would make this library refuse scripts the network
|
|
1058
1349
|
// accepts, which is the mirror of the bug that made them silently succeed.
|
|
1059
|
-
if (
|
|
1350
|
+
if (!this.isAfterChronicle()) {
|
|
1060
1351
|
if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
|
|
1061
1352
|
this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
|
|
1062
1353
|
return false
|
|
@@ -1069,7 +1360,7 @@ Interpreter.prototype.step = function () {
|
|
|
1069
1360
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
|
|
1070
1361
|
return false
|
|
1071
1362
|
}
|
|
1072
|
-
var maxNumSize =
|
|
1363
|
+
var maxNumSize = this.maxScriptNumLength()
|
|
1073
1364
|
var shiftBn = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, maxNumSize)
|
|
1074
1365
|
if (shiftBn.isNeg()) {
|
|
1075
1366
|
this.errstr = 'SCRIPT_ERR_INVALID_NUMBER_RANGE'
|
|
@@ -1133,7 +1424,7 @@ Interpreter.prototype.step = function () {
|
|
|
1133
1424
|
//
|
|
1134
1425
|
// Unlike the string opcodes, BAD_OPCODE pre-Chronicle IS correct here —
|
|
1135
1426
|
// the node returns it unconditionally.
|
|
1136
|
-
if (
|
|
1427
|
+
if (!this.isAfterChronicle()) {
|
|
1137
1428
|
this.errstr = 'SCRIPT_ERR_BAD_OPCODE'
|
|
1138
1429
|
return false
|
|
1139
1430
|
}
|
|
@@ -1157,8 +1448,13 @@ Interpreter.prototype.step = function () {
|
|
|
1157
1448
|
// So pre-Chronicle they are an error only in an EXECUTED branch. BSV is
|
|
1158
1449
|
// post-Genesis, which is the whole condition. Returning BAD_OPCODE
|
|
1159
1450
|
// unconditionally rejected scripts the network accepts.
|
|
1160
|
-
if (
|
|
1161
|
-
|
|
1451
|
+
if (!this.isAfterChronicle()) {
|
|
1452
|
+
// Genesis is part of the condition, not an assumption: before it
|
|
1453
|
+
// these are illegal everywhere, including in a branch that never
|
|
1454
|
+
// runs, and only from Genesis does an unexecuted one become
|
|
1455
|
+
// harmless. The era is carried in the flags now, so a pre-Genesis
|
|
1456
|
+
// output is validated as one.
|
|
1457
|
+
if (this.isAfterGenesis() && !fExec) {
|
|
1162
1458
|
break
|
|
1163
1459
|
}
|
|
1164
1460
|
this.errstr = 'SCRIPT_ERR_BAD_OPCODE'
|
|
@@ -1190,6 +1486,7 @@ Interpreter.prototype.step = function () {
|
|
|
1190
1486
|
this.stack.pop()
|
|
1191
1487
|
}
|
|
1192
1488
|
this.vfExec.push(fValue)
|
|
1489
|
+
this.vfElse.push(false)
|
|
1193
1490
|
break
|
|
1194
1491
|
|
|
1195
1492
|
case Opcode.OP_IF:
|
|
@@ -1221,14 +1518,21 @@ Interpreter.prototype.step = function () {
|
|
|
1221
1518
|
this.stack.pop()
|
|
1222
1519
|
}
|
|
1223
1520
|
this.vfExec.push(fValue)
|
|
1521
|
+
this.vfElse.push(false)
|
|
1224
1522
|
break
|
|
1225
1523
|
|
|
1226
1524
|
case Opcode.OP_ELSE:
|
|
1227
|
-
|
|
1525
|
+
// Genesis allows only one OP_ELSE per OP_IF. A second one is
|
|
1526
|
+
// unbalanced, and accepting it means accepting scripts the network
|
|
1527
|
+
// rejects — the node states it as
|
|
1528
|
+
// if (vfExec.empty() || (vfElse.back() && utxo_after_genesis))
|
|
1529
|
+
if (this.vfExec.length === 0 ||
|
|
1530
|
+
(this.vfElse[this.vfElse.length - 1] && this.isAfterGenesis())) {
|
|
1228
1531
|
this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL'
|
|
1229
1532
|
return false
|
|
1230
1533
|
}
|
|
1231
1534
|
this.vfExec[this.vfExec.length - 1] = !this.vfExec[this.vfExec.length - 1]
|
|
1535
|
+
this.vfElse[this.vfElse.length - 1] = true
|
|
1232
1536
|
break
|
|
1233
1537
|
|
|
1234
1538
|
case Opcode.OP_ENDIF:
|
|
@@ -1237,6 +1541,7 @@ Interpreter.prototype.step = function () {
|
|
|
1237
1541
|
return false
|
|
1238
1542
|
}
|
|
1239
1543
|
this.vfExec.pop()
|
|
1544
|
+
this.vfElse.pop()
|
|
1240
1545
|
break
|
|
1241
1546
|
|
|
1242
1547
|
case Opcode.OP_VERIFY:
|
|
@@ -1257,6 +1562,21 @@ Interpreter.prototype.step = function () {
|
|
|
1257
1562
|
break
|
|
1258
1563
|
|
|
1259
1564
|
case Opcode.OP_RETURN:
|
|
1565
|
+
if (this.isAfterGenesis()) {
|
|
1566
|
+
if (this.vfExec.length === 0) {
|
|
1567
|
+
// Genesis restored OP_RETURN's original meaning: it terminates the
|
|
1568
|
+
// script and the top stack item decides validity. The remainder
|
|
1569
|
+
// cannot affect the outcome, even if it holds unbalanced
|
|
1570
|
+
// conditionals or invalid opcodes, which is what makes
|
|
1571
|
+
// OP_FALSE OP_RETURN <data> outputs safe to carry anything.
|
|
1572
|
+
this.returned = true
|
|
1573
|
+
break
|
|
1574
|
+
}
|
|
1575
|
+
// Inside a conditional, suppress the rest but keep checking grammar.
|
|
1576
|
+
this.nonTopLevelReturnAfterGenesis = true
|
|
1577
|
+
break
|
|
1578
|
+
}
|
|
1579
|
+
// Before Genesis, an OP_RETURN alone invalidates the script.
|
|
1260
1580
|
this.errstr = 'SCRIPT_ERR_OP_RETURN'
|
|
1261
1581
|
return false
|
|
1262
1582
|
// break // unreachable
|
|
@@ -1414,7 +1734,7 @@ Interpreter.prototype.step = function () {
|
|
|
1414
1734
|
return false
|
|
1415
1735
|
}
|
|
1416
1736
|
buf = stacktop(-1)
|
|
1417
|
-
bn = BN.fromScriptNumBuffer(buf, fRequireMinimal)
|
|
1737
|
+
bn = BN.fromScriptNumBuffer(buf, fRequireMinimal, this.maxScriptNumLength())
|
|
1418
1738
|
n = bn.toNumber()
|
|
1419
1739
|
this.stack.pop()
|
|
1420
1740
|
if (n < 0 || n >= this.stack.length) {
|
|
@@ -1524,6 +1844,10 @@ Interpreter.prototype.step = function () {
|
|
|
1524
1844
|
// (x -- out)
|
|
1525
1845
|
if (this.stack.length < 1) {
|
|
1526
1846
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
|
|
1847
|
+
// The missing return here let evaluation continue and crash on the
|
|
1848
|
+
// absent operand, reporting an internal TypeError rather than the
|
|
1849
|
+
// stack error it had already decided on.
|
|
1850
|
+
return false
|
|
1527
1851
|
}
|
|
1528
1852
|
buf = stacktop(-1)
|
|
1529
1853
|
for (let i = 0; i < buf.length; i++) {
|
|
@@ -1543,7 +1867,7 @@ Interpreter.prototype.step = function () {
|
|
|
1543
1867
|
this.stack.pop()
|
|
1544
1868
|
} else {
|
|
1545
1869
|
bn1 = new BN(buf1)
|
|
1546
|
-
bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal)
|
|
1870
|
+
bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength())
|
|
1547
1871
|
n = bn2.toNumber()
|
|
1548
1872
|
if (n < 0) {
|
|
1549
1873
|
this.errstr = 'SCRIPT_ERR_INVALID_NUMBER_RANGE'
|
|
@@ -1608,7 +1932,7 @@ Interpreter.prototype.step = function () {
|
|
|
1608
1932
|
return false
|
|
1609
1933
|
}
|
|
1610
1934
|
buf = stacktop(-1)
|
|
1611
|
-
bn = BN.fromScriptNumBuffer(buf, fRequireMinimal)
|
|
1935
|
+
bn = BN.fromScriptNumBuffer(buf, fRequireMinimal, this.maxScriptNumLength())
|
|
1612
1936
|
switch (opcodenum) {
|
|
1613
1937
|
case Opcode.OP_2MUL:
|
|
1614
1938
|
bn = bn.mul(new BN(2))
|
|
@@ -1667,8 +1991,8 @@ Interpreter.prototype.step = function () {
|
|
|
1667
1991
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
|
|
1668
1992
|
return false
|
|
1669
1993
|
}
|
|
1670
|
-
bn1 = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal,
|
|
1671
|
-
bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal,
|
|
1994
|
+
bn1 = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal, this.maxScriptNumLength())
|
|
1995
|
+
bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength())
|
|
1672
1996
|
bn = new BN(0)
|
|
1673
1997
|
|
|
1674
1998
|
switch (opcodenum) {
|
|
@@ -1685,8 +2009,12 @@ Interpreter.prototype.step = function () {
|
|
|
1685
2009
|
break
|
|
1686
2010
|
|
|
1687
2011
|
case Opcode.OP_DIV:
|
|
1688
|
-
// denominator must not be 0
|
|
1689
|
-
|
|
2012
|
+
// denominator must not be 0. bn2 is a BN, so `bn2 === 0` was never
|
|
2013
|
+
// true and this guard never fired — bn.js asserted instead, and
|
|
2014
|
+
// the evaluator's catch reported SCRIPT_ERR_UNKNOWN_ERROR. The
|
|
2015
|
+
// script still failed, which is why the accept/reject vectors
|
|
2016
|
+
// stayed green while the reason was wrong.
|
|
2017
|
+
if (bn2.cmp(BN.Zero) === 0) {
|
|
1690
2018
|
this.errstr = 'SCRIPT_ERR_DIV_BY_ZERO'
|
|
1691
2019
|
return false
|
|
1692
2020
|
}
|
|
@@ -1694,9 +2022,9 @@ Interpreter.prototype.step = function () {
|
|
|
1694
2022
|
break
|
|
1695
2023
|
|
|
1696
2024
|
case Opcode.OP_MOD:
|
|
1697
|
-
// divisor must not be 0
|
|
1698
|
-
if (bn2 === 0) {
|
|
1699
|
-
this.errstr = '
|
|
2025
|
+
// divisor must not be 0. The node reports this one separately.
|
|
2026
|
+
if (bn2.cmp(BN.Zero) === 0) {
|
|
2027
|
+
this.errstr = 'SCRIPT_ERR_MOD_BY_ZERO'
|
|
1700
2028
|
return false
|
|
1701
2029
|
}
|
|
1702
2030
|
bn = bn1.mod(bn2)
|
|
@@ -1766,9 +2094,9 @@ Interpreter.prototype.step = function () {
|
|
|
1766
2094
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
|
|
1767
2095
|
return false
|
|
1768
2096
|
}
|
|
1769
|
-
bn1 = BN.fromScriptNumBuffer(stacktop(-3), fRequireMinimal,
|
|
1770
|
-
bn2 = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal,
|
|
1771
|
-
var bn3 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal,
|
|
2097
|
+
bn1 = BN.fromScriptNumBuffer(stacktop(-3), fRequireMinimal, this.maxScriptNumLength())
|
|
2098
|
+
bn2 = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal, this.maxScriptNumLength())
|
|
2099
|
+
var bn3 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength())
|
|
1772
2100
|
// bool fValue = (bn2 <= bn1 && bn1 < bn3);
|
|
1773
2101
|
fValue = (bn2.cmp(bn1) <= 0) && (bn1.cmp(bn3) < 0)
|
|
1774
2102
|
this.stack.pop()
|
|
@@ -1880,9 +2208,10 @@ Interpreter.prototype.step = function () {
|
|
|
1880
2208
|
return false
|
|
1881
2209
|
}
|
|
1882
2210
|
|
|
1883
|
-
var nKeysCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal).toNumber()
|
|
2211
|
+
var nKeysCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal, this.maxScriptNumLength()).toNumber()
|
|
1884
2212
|
// TODO: Keys and opcount are parameterized in client. No magic numbers!
|
|
1885
|
-
|
|
2213
|
+
// Genesis raised this to UINT32_MAX rather than removing it.
|
|
2214
|
+
if (nKeysCount < 0 || nKeysCount > this.maxPubKeysPerMultisig()) {
|
|
1886
2215
|
this.errstr = 'SCRIPT_ERR_PUBKEY_COUNT'
|
|
1887
2216
|
return false
|
|
1888
2217
|
}
|
|
@@ -1906,7 +2235,7 @@ Interpreter.prototype.step = function () {
|
|
|
1906
2235
|
return false
|
|
1907
2236
|
}
|
|
1908
2237
|
|
|
1909
|
-
var nSigsCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal).toNumber()
|
|
2238
|
+
var nSigsCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal, this.maxScriptNumLength()).toNumber()
|
|
1910
2239
|
if (nSigsCount < 0 || nSigsCount > nKeysCount) {
|
|
1911
2240
|
this.errstr = 'SCRIPT_ERR_SIG_COUNT'
|
|
1912
2241
|
return false
|
|
@@ -2019,7 +2348,12 @@ Interpreter.prototype.step = function () {
|
|
|
2019
2348
|
|
|
2020
2349
|
buf1 = stacktop(-2)
|
|
2021
2350
|
buf2 = stacktop(-1)
|
|
2022
|
-
|
|
2351
|
+
// Era-derived, like every other element size check. Genesis lifted the
|
|
2352
|
+
// 520-byte cap, and reading the static here meant OP_CAT kept
|
|
2353
|
+
// enforcing it after Genesis — rejecting a concatenation the network
|
|
2354
|
+
// accepts. No vector in the corpus covers this, so it is held by
|
|
2355
|
+
// test/script/genesis_limits.js instead.
|
|
2356
|
+
if (buf1.length + buf2.length > this.maxScriptElementSize()) {
|
|
2023
2357
|
this.errstr = 'SCRIPT_ERR_PUSH_SIZE'
|
|
2024
2358
|
return false
|
|
2025
2359
|
}
|
|
@@ -2035,7 +2369,7 @@ Interpreter.prototype.step = function () {
|
|
|
2035
2369
|
buf1 = stacktop(-2)
|
|
2036
2370
|
|
|
2037
2371
|
// Make sure the split point is apropriate.
|
|
2038
|
-
var position = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal).toNumber()
|
|
2372
|
+
var position = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength()).toNumber()
|
|
2039
2373
|
if (position < 0 || position > buf1.length) {
|
|
2040
2374
|
this.errstr = 'SCRIPT_ERR_INVALID_SPLIT_RANGE'
|
|
2041
2375
|
return false
|
|
@@ -2065,7 +2399,7 @@ Interpreter.prototype.step = function () {
|
|
|
2065
2399
|
//
|
|
2066
2400
|
// Running them unconditionally consumed stack where the network does
|
|
2067
2401
|
// nothing, which is a wrong answer rather than an error.
|
|
2068
|
-
if (
|
|
2402
|
+
if (!this.isAfterChronicle()) {
|
|
2069
2403
|
if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
|
|
2070
2404
|
this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
|
|
2071
2405
|
return false
|
|
@@ -2078,7 +2412,7 @@ Interpreter.prototype.step = function () {
|
|
|
2078
2412
|
return false
|
|
2079
2413
|
}
|
|
2080
2414
|
buf1 = stacktop(-2)
|
|
2081
|
-
n = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal,
|
|
2415
|
+
n = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength()).toNumber()
|
|
2082
2416
|
// ERRORS on out of range; it does not clamp. The node is
|
|
2083
2417
|
// `if(len < 0 || len > size) return SCRIPT_ERR_INVALID_NUMBER_RANGE`.
|
|
2084
2418
|
// Clamping made scripts the node rejects succeed here.
|
|
@@ -2107,7 +2441,7 @@ Interpreter.prototype.step = function () {
|
|
|
2107
2441
|
//
|
|
2108
2442
|
// Running them unconditionally consumed stack where the network does
|
|
2109
2443
|
// nothing, which is a wrong answer rather than an error.
|
|
2110
|
-
if (
|
|
2444
|
+
if (!this.isAfterChronicle()) {
|
|
2111
2445
|
if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
|
|
2112
2446
|
this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
|
|
2113
2447
|
return false
|
|
@@ -2120,8 +2454,8 @@ Interpreter.prototype.step = function () {
|
|
|
2120
2454
|
return false
|
|
2121
2455
|
}
|
|
2122
2456
|
buf1 = stacktop(-3)
|
|
2123
|
-
var subSize = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal,
|
|
2124
|
-
var subBegin = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal,
|
|
2457
|
+
var subSize = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength()).toNumber()
|
|
2458
|
+
var subBegin = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal, this.maxScriptNumLength()).toNumber()
|
|
2125
2459
|
// ERRORS on out of range, matching
|
|
2126
2460
|
// offset < 0 || offset >= size || len < 0 || len > size - offset
|
|
2127
2461
|
// Note `offset >= size` is strict: a begin index AT the end is an
|
|
@@ -2145,8 +2479,12 @@ Interpreter.prototype.step = function () {
|
|
|
2145
2479
|
return false
|
|
2146
2480
|
}
|
|
2147
2481
|
|
|
2148
|
-
var size = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal).toNumber()
|
|
2149
|
-
|
|
2482
|
+
var size = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength()).toNumber()
|
|
2483
|
+
// A negative size is a push size failure, not an encoding one. Without
|
|
2484
|
+
// the lower bound it fell through to the rawnum.length > size test,
|
|
2485
|
+
// which any number passes when size is negative, and reported
|
|
2486
|
+
// IMPOSSIBLE_ENCODING instead.
|
|
2487
|
+
if (size < 0 || size > this.maxScriptElementSize()) {
|
|
2150
2488
|
this.errstr = 'SCRIPT_ERR_PUSH_SIZE'
|
|
2151
2489
|
return false
|
|
2152
2490
|
}
|