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