@smartledger/bsv 7.12.0 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +178 -0
- package/README.md +38 -38
- package/bsv-didweb.min.js +6 -6
- package/bsv-gdaf.min.js +66 -66
- package/bsv-ltp.min.js +46 -46
- package/bsv-mnemonic.min.js +8 -8
- package/bsv-smartcontract.min.js +1 -1
- package/bsv.bundle.js +66 -66
- package/bsv.min.js +66 -66
- package/docs/AUDIT_SCOPE.md +29 -21
- 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/index.js +10 -2
- package/lib/crypto/bn.js +22 -2
- package/lib/crypto/hash.browser.js +13 -5
- package/lib/crypto/hash.js +58 -2
- package/lib/crypto/random.js +72 -15
- package/lib/didweb/index.js +88 -9
- package/lib/encoding/base58.js +67 -3
- package/lib/mnemonic/mnemonic.js +19 -5
- package/lib/mnemonic/pbkdf2.js +35 -2
- package/lib/script/interpreter.js +420 -58
- package/lib/transaction/input/multisig.js +1 -1
- package/lib/transaction/input/multisigscripthash.js +1 -1
- package/lib/transaction/input/publickey.js +1 -1
- package/lib/transaction/input/publickeyhash.js +1 -1
- package/lib/transaction/sighash.js +18 -6
- package/lib/transaction/signature.js +1 -1
- package/lib/util/inherits.js +37 -0
- package/package.json +7 -8
- 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/crypto/backend_selection.js +126 -0
- package/test/crypto/random.js +73 -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/didweb/relationships.js +144 -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/test/transaction/unspentoutput.js +6 -1
- package/version.js +1 -1
|
@@ -8,7 +8,26 @@ var BN = require('../crypto/bn')
|
|
|
8
8
|
var Hash = require('../crypto/hash')
|
|
9
9
|
var Signature = require('../crypto/signature')
|
|
10
10
|
var PublicKey = require('../publickey')
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Copy a script stack for the step listener, so a listener that mutates what it is
|
|
13
|
+
* handed cannot corrupt the running evaluation.
|
|
14
|
+
*
|
|
15
|
+
* Replaces the `clone-deep` dependency. The stack is an array of Buffers — every one of
|
|
16
|
+
* the 32 push sites in this file pushes a Buffer — so a shallow map with `Buffer.from`
|
|
17
|
+
* reproduces `cloneDeep(stack, true)` exactly for this input: same bytes, new backing
|
|
18
|
+
* memory, `Buffer.isBuffer` still true, empty buffers preserved.
|
|
19
|
+
*
|
|
20
|
+
* `structuredClone` is NOT a substitute: it returns Uint8Array for a Buffer input, which
|
|
21
|
+
* would silently change the type handed to every existing stepListener.
|
|
22
|
+
*
|
|
23
|
+
* Anything non-Buffer is passed through by reference. Nothing puts such a value on the
|
|
24
|
+
* stack today; if something ever does it will be a primitive, where sharing is harmless.
|
|
25
|
+
*/
|
|
26
|
+
function cloneStack (stack) {
|
|
27
|
+
return stack.map(function (item) {
|
|
28
|
+
return Buffer.isBuffer(item) ? Buffer.from(item) : item
|
|
29
|
+
})
|
|
30
|
+
}
|
|
12
31
|
|
|
13
32
|
/**
|
|
14
33
|
* Bitcoin transactions contain scripts. Each input has a script called the
|
|
@@ -56,7 +75,8 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
|
|
|
56
75
|
nin = 0
|
|
57
76
|
}
|
|
58
77
|
if (_.isUndefined(flags)) {
|
|
59
|
-
flags =
|
|
78
|
+
flags = Interpreter.currentConsensusFlags()
|
|
79
|
+
if (!satoshisBN) flags &= ~Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID
|
|
60
80
|
}
|
|
61
81
|
|
|
62
82
|
// If FORKID is enabled, we also ensure strict encoding.
|
|
@@ -88,7 +108,12 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
|
|
|
88
108
|
return false
|
|
89
109
|
}
|
|
90
110
|
|
|
91
|
-
|
|
111
|
+
// Genesis removed P2SH: an output created after it that happens to match the
|
|
112
|
+
// pattern is evaluated literally, with no redeem-script pass.
|
|
113
|
+
var p2sh = (flags & Interpreter.SCRIPT_VERIFY_P2SH) !== 0 &&
|
|
114
|
+
(flags & Interpreter.SCRIPT_UTXO_AFTER_GENESIS) === 0
|
|
115
|
+
|
|
116
|
+
if (p2sh) {
|
|
92
117
|
stackCopy = this.stack.slice()
|
|
93
118
|
}
|
|
94
119
|
|
|
@@ -120,7 +145,7 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
|
|
|
120
145
|
}
|
|
121
146
|
|
|
122
147
|
// Additional validation for spend-to-script-hash transactions:
|
|
123
|
-
if (
|
|
148
|
+
if (p2sh && scriptPubkey.isScriptHashOut()) {
|
|
124
149
|
// scriptSig must be literals-only or validation fails
|
|
125
150
|
if (!scriptSig.isPushOnly()) {
|
|
126
151
|
this.errstr = 'SCRIPT_ERR_SIG_PUSHONLY'
|
|
@@ -172,11 +197,18 @@ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags
|
|
|
172
197
|
// Disallow CLEANSTACK without P2SH, as otherwise a switch
|
|
173
198
|
// CLEANSTACK->P2SH+CLEANSTACK would be possible, which is not a
|
|
174
199
|
// softfork (and P2SH should be one).
|
|
175
|
-
|
|
200
|
+
// Genesis removed P2SH, so post-Genesis the pairing no longer applies and
|
|
201
|
+
// CLEANSTACK stands on its own.
|
|
202
|
+
if ((flags & Interpreter.SCRIPT_VERIFY_P2SH) === 0 &&
|
|
203
|
+
(flags & Interpreter.SCRIPT_UTXO_AFTER_GENESIS) === 0) {
|
|
176
204
|
throw new Error('internal error - CLEANSTACK without P2SH')
|
|
177
205
|
}
|
|
178
206
|
|
|
179
|
-
|
|
207
|
+
// The final stack. After a P2SH evaluation that is stackCopy itself, since
|
|
208
|
+
// the redeem script was evaluated over it, but reading stackCopy directly
|
|
209
|
+
// is wrong once P2SH no longer applies: it is then either the stack as it
|
|
210
|
+
// stood after the scriptSig, or never assigned at all.
|
|
211
|
+
if (this.stack.length !== 1) {
|
|
180
212
|
this.errstr = 'SCRIPT_ERR_CLEANSTACK'
|
|
181
213
|
return false
|
|
182
214
|
}
|
|
@@ -193,7 +225,15 @@ Interpreter.prototype.initialize = function (obj) {
|
|
|
193
225
|
this.pc = 0
|
|
194
226
|
this.pbegincodehash = 0
|
|
195
227
|
this.nOpCount = 0
|
|
228
|
+
this.returned = false
|
|
229
|
+
// Set when an OP_RETURN is reached inside a conditional after Genesis: the
|
|
230
|
+
// rest of the script stops executing while the conditional grammar is still
|
|
231
|
+
// checked to the end.
|
|
232
|
+
this.nonTopLevelReturnAfterGenesis = false
|
|
196
233
|
this.vfExec = []
|
|
234
|
+
// Whether the conditional at each depth has already seen an OP_ELSE.
|
|
235
|
+
// Genesis allows only one per OP_IF, which needs remembering per level.
|
|
236
|
+
this.vfElse = []
|
|
197
237
|
this.errstr = ''
|
|
198
238
|
this.flags = 0
|
|
199
239
|
}
|
|
@@ -208,7 +248,13 @@ Interpreter.prototype.set = function (obj) {
|
|
|
208
248
|
this.pc = typeof obj.pc !== 'undefined' ? obj.pc : this.pc
|
|
209
249
|
this.pbegincodehash = typeof obj.pbegincodehash !== 'undefined' ? obj.pbegincodehash : this.pbegincodehash
|
|
210
250
|
this.nOpCount = typeof obj.nOpCount !== 'undefined' ? obj.nOpCount : this.nOpCount
|
|
251
|
+
this.returned = typeof obj.returned !== 'undefined' ? obj.returned : this.returned
|
|
252
|
+
this.nonTopLevelReturnAfterGenesis =
|
|
253
|
+
typeof obj.nonTopLevelReturnAfterGenesis !== 'undefined'
|
|
254
|
+
? obj.nonTopLevelReturnAfterGenesis
|
|
255
|
+
: this.nonTopLevelReturnAfterGenesis
|
|
211
256
|
this.vfExec = obj.vfExec || this.vfExec
|
|
257
|
+
this.vfElse = obj.vfElse || this.vfElse
|
|
212
258
|
this.errstr = obj.errstr || this.errstr
|
|
213
259
|
this.flags = typeof obj.flags !== 'undefined' ? obj.flags : this.flags
|
|
214
260
|
}
|
|
@@ -217,12 +263,24 @@ Interpreter.true = Buffer.from([1])
|
|
|
217
263
|
Interpreter.false = Buffer.from([])
|
|
218
264
|
|
|
219
265
|
Interpreter.MAX_SCRIPT_ELEMENT_SIZE = 520
|
|
266
|
+
// CScriptNum's `max_length`: the widest a script NUMBER may be, in bytes. Distinct from
|
|
267
|
+
// MAX_SCRIPT_ELEMENT_SIZE, which caps a pushed data element. Arithmetic opcodes read
|
|
268
|
+
// operands through it, and Chronicle's shift bounds its result against it.
|
|
220
269
|
Interpreter.MAXIMUM_ELEMENT_SIZE = 4
|
|
270
|
+
|
|
271
|
+
// The script-number bound `useMainnetConsensus()` applies. Held separately from the
|
|
272
|
+
// pre-Genesis default above so the two can diverge once the post-Genesis value is pinned
|
|
273
|
+
// against the node source; see the note in useMainnetConsensus for why it is not simply
|
|
274
|
+
// raised with the other caps.
|
|
275
|
+
Interpreter.DEFAULT_SCRIPT_NUM_LENGTH = 4
|
|
221
276
|
// Maximum number of non-push opcodes per script. Pre-Genesis consensus is 201;
|
|
222
277
|
// post-Genesis BSV removed this limit. Exposed as a constant (instead of a magic
|
|
223
278
|
// number) so applications can opt into post-Genesis rules — e.g. OP_PUSH_TX
|
|
224
279
|
// covenants, which need a few hundred opcodes — without forking the interpreter.
|
|
225
|
-
|
|
280
|
+
// BSV's pre-Genesis figure is 500, not Bitcoin Core's 201: the limit was
|
|
281
|
+
// raised before Genesis removed it altogether. Carrying Core's number rejected
|
|
282
|
+
// scripts the network accepted.
|
|
283
|
+
Interpreter.MAX_OPS_PER_SCRIPT = 500
|
|
226
284
|
// Maximum total serialized script size. Pre-Genesis consensus is 10,000 bytes;
|
|
227
285
|
// post-Genesis BSV removed this limit too. It was previously a literal inside
|
|
228
286
|
// evaluate(), so `useGenesisLimits()` could not lift it and any script over 10 KB —
|
|
@@ -230,6 +288,16 @@ Interpreter.MAX_OPS_PER_SCRIPT = 201
|
|
|
230
288
|
// no matter what the caller asked for.
|
|
231
289
|
Interpreter.MAX_SCRIPT_SIZE = 10000
|
|
232
290
|
|
|
291
|
+
// Genesis and Chronicle limits, from the node's src/consensus/consensus.h.
|
|
292
|
+
// These are the values the WIP note above asked to be pinned against the node
|
|
293
|
+
// source: Genesis raised the script-number bound to 750,000 bytes and
|
|
294
|
+
// Chronicle to 32,000,000, and removed the element, script size and operation
|
|
295
|
+
// caps outright.
|
|
296
|
+
Interpreter.UNLIMITED = Number.MAX_SAFE_INTEGER
|
|
297
|
+
Interpreter.MAX_SCRIPT_NUM_LENGTH_AFTER_GENESIS = 750000
|
|
298
|
+
Interpreter.MAX_SCRIPT_NUM_LENGTH_AFTER_CHRONICLE = 32000000
|
|
299
|
+
Interpreter.MAX_PUBKEYS_PER_MULTISIG_AFTER_GENESIS = 4294967295
|
|
300
|
+
|
|
233
301
|
Interpreter.LOCKTIME_THRESHOLD = 500000000
|
|
234
302
|
Interpreter.LOCKTIME_THRESHOLD_BN = new BN(Interpreter.LOCKTIME_THRESHOLD)
|
|
235
303
|
|
|
@@ -379,17 +447,41 @@ Interpreter.SCRIPT_ENABLE_REPLAY_PROTECTION = (1 << 17)
|
|
|
379
447
|
|
|
380
448
|
// Enable new opcodes.
|
|
381
449
|
//
|
|
382
|
-
|
|
450
|
+
// Moved off 1<<18 and 1<<19, which the reference node assigns to
|
|
451
|
+
// SCRIPT_GENESIS and SCRIPT_UTXO_AFTER_GENESIS. Sharing those bits meant that
|
|
452
|
+
// node-derived flags passed into this library were silently read as something
|
|
453
|
+
// else. These two are BCH-era flags the node does not define at all, so their
|
|
454
|
+
// positions carry no consensus meaning and are free to move.
|
|
455
|
+
Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES = (1 << 11)
|
|
383
456
|
|
|
384
457
|
// Are the Magnetic upgrade opcodes enabled?
|
|
385
458
|
//
|
|
386
|
-
Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES = (1 <<
|
|
459
|
+
Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES = (1 << 12)
|
|
460
|
+
|
|
461
|
+
// The era flags, at the bit positions src/script/script_flags.h assigns them.
|
|
462
|
+
// Keep them in sync: they are consensus-relevant and are passed across the
|
|
463
|
+
// boundary with node-derived test vectors.
|
|
464
|
+
//
|
|
465
|
+
// The distinction between the pairs matters. SCRIPT_UTXO_AFTER_* describes the
|
|
466
|
+
// output being spent and governs almost every rule, because an output made
|
|
467
|
+
// before an upgrade is spent under the old rules forever. SCRIPT_GENESIS and
|
|
468
|
+
// SCRIPT_CHRONICLE describe the block the spending transaction is in.
|
|
469
|
+
Interpreter.SCRIPT_GENESIS = (1 << 18)
|
|
470
|
+
Interpreter.SCRIPT_UTXO_AFTER_GENESIS = (1 << 19)
|
|
387
471
|
|
|
388
472
|
// Chronicle restores OP_2MUL/OP_2DIV and gives OP_VER/OP_VERIF/OP_VERNOTIF meaning.
|
|
389
473
|
// Off by default: enabling it changes script evaluation, so it is an explicit opt-in
|
|
390
474
|
// exactly like the Monolith and Magnetic flags above.
|
|
391
475
|
Interpreter.SCRIPT_ENABLE_CHRONICLE = (1 << 20)
|
|
392
476
|
|
|
477
|
+
// The node's name for the same bit: Chronicle rules apply to the block the
|
|
478
|
+
// spending transaction is in.
|
|
479
|
+
Interpreter.SCRIPT_CHRONICLE = Interpreter.SCRIPT_ENABLE_CHRONICLE
|
|
480
|
+
|
|
481
|
+
// Was the output being spent created after Chronicle activated? This is what
|
|
482
|
+
// the node gates the restored opcodes on.
|
|
483
|
+
Interpreter.SCRIPT_UTXO_AFTER_CHRONICLE = (1 << 21)
|
|
484
|
+
|
|
393
485
|
/**
|
|
394
486
|
* Block height at which Chronicle activated on BSV mainnet (2026-04-07).
|
|
395
487
|
*
|
|
@@ -413,9 +505,21 @@ Interpreter.CHRONICLE_ACTIVATION_HEIGHT = 943816
|
|
|
413
505
|
* every output created since is subject to it. Pass `false` to validate the spend of a
|
|
414
506
|
* pre-activation UTXO, which is exactly the distinction the node makes.
|
|
415
507
|
*
|
|
508
|
+
* CLTV and CSV are deliberately ABSENT. Genesis reverted both opcodes to OP_NOP2/OP_NOP3,
|
|
509
|
+
* and the node ignores their flags entirely once the UTXO is post-Genesis:
|
|
510
|
+
*
|
|
511
|
+
* if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) || utxo_after_genesis) {
|
|
512
|
+
* // not enabled; treat as a NOP2
|
|
513
|
+
*
|
|
514
|
+
* Including them made this function reject `<n> OP_CHECKLOCKTIMEVERIFY OP_DROP OP_1`,
|
|
515
|
+
* which mainnet accepts — a validator STRICTER than consensus, which is as wrong as one
|
|
516
|
+
* that is looser and harder to notice, because nothing that tests this library against
|
|
517
|
+
* itself can see it. The flags still exist for callers deliberately emulating
|
|
518
|
+
* pre-Genesis rules; they are simply not mainnet.
|
|
519
|
+
*
|
|
416
520
|
* NOTE: script-number and element-size limits are NOT flags — they are process-wide
|
|
417
|
-
* statics
|
|
418
|
-
*
|
|
521
|
+
* statics. This function cannot set them, which is why `useMainnetConsensus()` exists;
|
|
522
|
+
* prefer it unless you are managing the limits yourself.
|
|
419
523
|
*
|
|
420
524
|
* @param {object} [opts]
|
|
421
525
|
* @param {boolean} [opts.afterChronicle=true] is the UTXO being spent post-activation
|
|
@@ -429,8 +533,6 @@ Interpreter.mainnetFlags = function (opts) {
|
|
|
429
533
|
Interpreter.SCRIPT_VERIFY_LOW_S |
|
|
430
534
|
Interpreter.SCRIPT_VERIFY_NULLFAIL |
|
|
431
535
|
Interpreter.SCRIPT_VERIFY_MINIMALDATA |
|
|
432
|
-
Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY |
|
|
433
|
-
Interpreter.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY |
|
|
434
536
|
Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID |
|
|
435
537
|
Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES |
|
|
436
538
|
Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES
|
|
@@ -440,6 +542,88 @@ Interpreter.mainnetFlags = function (opts) {
|
|
|
440
542
|
return flags
|
|
441
543
|
}
|
|
442
544
|
|
|
545
|
+
/**
|
|
546
|
+
* Configure this process for BSV mainnet consensus and return the matching flags.
|
|
547
|
+
*
|
|
548
|
+
* Flags and limits are separate mechanisms here — flags are an argument to `verify()`,
|
|
549
|
+
* limits are process-wide statics — and that split is what made `mainnetFlags()` alone
|
|
550
|
+
* insufficient: it returns mainnet flags while the interpreter still holds the
|
|
551
|
+
* PRE-Genesis 520 / 201 / 10,000 caps, so a 12,801-byte script valid on mainnet was
|
|
552
|
+
* rejected with SCRIPT_ERR_SCRIPT_SIZE.
|
|
553
|
+
*
|
|
554
|
+
* This is the single call that makes both agree. It MUTATES process-wide state, which is
|
|
555
|
+
* why it is named `use*` like `useGenesisLimits()` rather than reading like a getter.
|
|
556
|
+
*
|
|
557
|
+
* @param {object} [opts]
|
|
558
|
+
* @param {boolean} [opts.afterChronicle=true] is the UTXO being spent post-activation
|
|
559
|
+
* @param {number} [opts.max] element-size ceiling to pass through to useGenesisLimits()
|
|
560
|
+
* @returns {number} the flags to hand to verify()
|
|
561
|
+
*/
|
|
562
|
+
/**
|
|
563
|
+
* The flags describing BSV mainnet as it is today, and the default for `verify()`.
|
|
564
|
+
*
|
|
565
|
+
* Until 8.0.0 `verify()` defaulted to `0` — no rules at all. A BSV library whose
|
|
566
|
+
* out-of-the-box answer described Bitcoin in 2015 is wrong in the direction that is
|
|
567
|
+
* hardest to notice: it accepts scripts the network rejects, and nothing that tests this
|
|
568
|
+
* library against itself can see it. The era now has to be stated to get anything else.
|
|
569
|
+
*
|
|
570
|
+
* The set is derived from what the node applies, not assembled by judgement:
|
|
571
|
+
*
|
|
572
|
+
* MONOLITH / MAGNETIC BSV restored these opcodes in 2018 and the node does not gate
|
|
573
|
+
* them. This library still does, so omitting them here would be
|
|
574
|
+
* STRICTER than consensus. tools/sv-vector-harness.js sets the
|
|
575
|
+
* same pair as its baseline for every vector, for this reason.
|
|
576
|
+
* GENESIS rules keyed to the era of the spending transaction
|
|
577
|
+
* UTXO_AFTER_GENESIS rules keyed to the era of the output being spent (2020)
|
|
578
|
+
* CHRONICLE the spending transaction's era (2026)
|
|
579
|
+
* UTXO_AFTER_CHRONICLE the spent output's era
|
|
580
|
+
*
|
|
581
|
+
* Spending a pre-activation output is the explicit case, because that is the input the
|
|
582
|
+
* caller knows and the library cannot: `mainnetFlags({ afterChronicle: false })`, or a
|
|
583
|
+
* hand-assembled set for older eras.
|
|
584
|
+
*
|
|
585
|
+
* FORKID is deliberately absent here and added by `verify()` only when the input amount
|
|
586
|
+
* is available, since the digest cannot be computed without it.
|
|
587
|
+
*
|
|
588
|
+
* @returns {number}
|
|
589
|
+
*/
|
|
590
|
+
Interpreter.currentConsensusFlags = function () {
|
|
591
|
+
return Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES |
|
|
592
|
+
Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES |
|
|
593
|
+
Interpreter.SCRIPT_GENESIS |
|
|
594
|
+
Interpreter.SCRIPT_UTXO_AFTER_GENESIS |
|
|
595
|
+
Interpreter.SCRIPT_ENABLE_CHRONICLE |
|
|
596
|
+
Interpreter.SCRIPT_UTXO_AFTER_CHRONICLE |
|
|
597
|
+
Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
Interpreter.useMainnetConsensus = function (opts) {
|
|
601
|
+
opts = opts || {}
|
|
602
|
+
Interpreter.useGenesisLimits(opts.max)
|
|
603
|
+
|
|
604
|
+
// Restore a FINITE script-number bound. `useGenesisLimits()` raises all four caps to
|
|
605
|
+
// the same ceiling, and for MAXIMUM_ELEMENT_SIZE — which is CScriptNum's `max_length`,
|
|
606
|
+
// not a push-size cap — a ceiling of 0x7fffffff makes Chronicle's shift overflow check
|
|
607
|
+
// unreachable, because it tests `current_size + shift_bytes > max_length`. Measured:
|
|
608
|
+
//
|
|
609
|
+
// default limits: SCRIPT_ERR_SCRIPTNUM_OVERFLOW (correct)
|
|
610
|
+
// after useGenesisLimits(): valid, grows without bound (WRONG)
|
|
611
|
+
//
|
|
612
|
+
// A validator looser than consensus accepts what the network rejects, so the ceiling
|
|
613
|
+
// cannot be right whatever the true post-Genesis value turns out to be.
|
|
614
|
+
//
|
|
615
|
+
// The true value is NOT settled here. Genesis raised this bound above the pre-Genesis
|
|
616
|
+
// 4 bytes, so the conservative default below is stricter than mainnet for wide
|
|
617
|
+
// arithmetic — the same class of error #112 fixed, in the opposite direction. It is
|
|
618
|
+
// chosen deliberately: given a choice between rejecting a valid script and accepting
|
|
619
|
+
// an invalid one, this library fails closed. Callers who know the bound their workload
|
|
620
|
+
// needs should pass `maxScriptNumLength` explicitly, and the value should be pinned
|
|
621
|
+
// against the SV Node source before this default changes.
|
|
622
|
+
Interpreter.MAXIMUM_ELEMENT_SIZE = opts.maxScriptNumLength || Interpreter.DEFAULT_SCRIPT_NUM_LENGTH
|
|
623
|
+
|
|
624
|
+
return Interpreter.mainnetFlags(opts)
|
|
625
|
+
}
|
|
626
|
+
|
|
443
627
|
/* Below flags apply in the context of BIP 68 */
|
|
444
628
|
/**
|
|
445
629
|
* If this flag set, CTxIn::nSequence is NOT interpreted as a relative
|
|
@@ -507,6 +691,20 @@ Interpreter.prototype.checkSignatureEncoding = function (buf) {
|
|
|
507
691
|
return false
|
|
508
692
|
}
|
|
509
693
|
|
|
694
|
+
// A signature may only ask for the original digest where Chronicle
|
|
695
|
+
// applies. This is where the node stops a pre-Chronicle signature whose
|
|
696
|
+
// type byte happens to set 0x20 from being read as one asking for OTDA:
|
|
697
|
+
//
|
|
698
|
+
// if(!chronicleEnabled && usesChronicle) return SCRIPT_ERR_ILLEGAL_CHRONICLE;
|
|
699
|
+
//
|
|
700
|
+
// It rejects such a signature outright rather than reinterpreting it,
|
|
701
|
+
// which is why SignatureHash() itself can route on the bit alone.
|
|
702
|
+
if (!(this.flags & Interpreter.SCRIPT_CHRONICLE) &&
|
|
703
|
+
(sig.nhashtype & Signature.SIGHASH_CHRONICLE)) {
|
|
704
|
+
this.errstr = 'SCRIPT_ERR_ILLEGAL_CHRONICLE'
|
|
705
|
+
return false
|
|
706
|
+
}
|
|
707
|
+
|
|
510
708
|
if ((this.flags & Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID) &&
|
|
511
709
|
!(sig.nhashtype & Signature.SIGHASH_FORKID)) {
|
|
512
710
|
this.errstr = 'SCRIPT_ERR_MUST_USE_FORKID'
|
|
@@ -535,6 +733,67 @@ Interpreter.prototype.checkPubkeyEncoding = function (buf) {
|
|
|
535
733
|
*
|
|
536
734
|
*/
|
|
537
735
|
|
|
736
|
+
/**
|
|
737
|
+
* Which era's rules apply.
|
|
738
|
+
*
|
|
739
|
+
* The node decides almost everything by the era of the output being spent, so
|
|
740
|
+
* these read the SCRIPT_UTXO_AFTER_* flags rather than a process-wide setting.
|
|
741
|
+
* A caller that sets no era flag gets the previous behaviour exactly: the
|
|
742
|
+
* limit methods below fall back to the mutable statics, so useGenesisLimits()
|
|
743
|
+
* and setLimits() keep working as they did.
|
|
744
|
+
*/
|
|
745
|
+
Interpreter.prototype.isAfterGenesis = function () {
|
|
746
|
+
return (this.flags & Interpreter.SCRIPT_UTXO_AFTER_GENESIS) !== 0
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* SCRIPT_ENABLE_CHRONICLE is accepted alongside SCRIPT_UTXO_AFTER_CHRONICLE.
|
|
751
|
+
* The former is this library's existing opt-in and sits on the node's
|
|
752
|
+
* SCRIPT_CHRONICLE bit; the latter is what the node actually gates the
|
|
753
|
+
* restored opcodes on. Either enables them, so existing callers are unaffected.
|
|
754
|
+
*/
|
|
755
|
+
Interpreter.prototype.isAfterChronicle = function () {
|
|
756
|
+
return (this.flags &
|
|
757
|
+
(Interpreter.SCRIPT_UTXO_AFTER_CHRONICLE | Interpreter.SCRIPT_ENABLE_CHRONICLE)) !== 0
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
/** Genesis removed this limit; before it, whatever the statics say. */
|
|
761
|
+
Interpreter.prototype.maxScriptElementSize = function () {
|
|
762
|
+
return this.isAfterGenesis() ? Interpreter.UNLIMITED : Interpreter.MAX_SCRIPT_ELEMENT_SIZE
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
/** Genesis removed this limit too. */
|
|
766
|
+
Interpreter.prototype.maxScriptSize = function () {
|
|
767
|
+
return this.isAfterGenesis() ? Interpreter.UNLIMITED : Interpreter.MAX_SCRIPT_SIZE
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
/** And this one. Note the pre-Genesis figure on BSV is 500, not Core's 201. */
|
|
771
|
+
Interpreter.prototype.maxOpsPerScript = function () {
|
|
772
|
+
return this.isAfterGenesis() ? Interpreter.UNLIMITED : Interpreter.MAX_OPS_PER_SCRIPT
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
/**
|
|
776
|
+
* The widest a script number may be. Four bytes before Genesis, which is why
|
|
777
|
+
* pre-Genesis contracts cannot do arithmetic on satoshi amounts; Genesis
|
|
778
|
+
* raised it to 750KB and Chronicle to 32MB.
|
|
779
|
+
*/
|
|
780
|
+
Interpreter.prototype.maxScriptNumLength = function () {
|
|
781
|
+
if (this.isAfterChronicle()) {
|
|
782
|
+
return Interpreter.MAX_SCRIPT_NUM_LENGTH_AFTER_CHRONICLE
|
|
783
|
+
}
|
|
784
|
+
if (this.isAfterGenesis()) {
|
|
785
|
+
return Interpreter.MAX_SCRIPT_NUM_LENGTH_AFTER_GENESIS
|
|
786
|
+
}
|
|
787
|
+
return Interpreter.MAXIMUM_ELEMENT_SIZE
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
/** Genesis raised this rather than removing it: the node caps at UINT32_MAX. */
|
|
791
|
+
Interpreter.prototype.maxPubKeysPerMultisig = function () {
|
|
792
|
+
return this.isAfterGenesis()
|
|
793
|
+
? Interpreter.MAX_PUBKEYS_PER_MULTISIG_AFTER_GENESIS
|
|
794
|
+
: 20
|
|
795
|
+
}
|
|
796
|
+
|
|
538
797
|
Interpreter._isMinimallyEncoded = function (buf, nMaxNumSize) {
|
|
539
798
|
nMaxNumSize = nMaxNumSize || Interpreter.MAXIMUM_ELEMENT_SIZE
|
|
540
799
|
if (buf.length > nMaxNumSize) {
|
|
@@ -617,7 +876,7 @@ Interpreter._minimallyEncode = function (buf) {
|
|
|
617
876
|
* bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
|
|
618
877
|
*/
|
|
619
878
|
Interpreter.prototype.evaluate = function () {
|
|
620
|
-
if (this.script.toBuffer().length >
|
|
879
|
+
if (this.script.toBuffer().length > this.maxScriptSize()) {
|
|
621
880
|
this.errstr = 'SCRIPT_ERR_SCRIPT_SIZE'
|
|
622
881
|
return false
|
|
623
882
|
}
|
|
@@ -630,6 +889,12 @@ Interpreter.prototype.evaluate = function () {
|
|
|
630
889
|
return false
|
|
631
890
|
}
|
|
632
891
|
this._callbackStep(thisStep)
|
|
892
|
+
if (this.returned) {
|
|
893
|
+
// A top-level OP_RETURN after Genesis: the script is over and the top
|
|
894
|
+
// stack item decides. Nothing after it is read, so an unbalanced
|
|
895
|
+
// conditional or an invalid opcode beyond this point is not an error.
|
|
896
|
+
return true
|
|
897
|
+
}
|
|
633
898
|
}
|
|
634
899
|
|
|
635
900
|
// Size limits
|
|
@@ -638,7 +903,12 @@ Interpreter.prototype.evaluate = function () {
|
|
|
638
903
|
return false
|
|
639
904
|
}
|
|
640
905
|
} catch (e) {
|
|
641
|
-
|
|
906
|
+
// An error that knows the node's result code reports it. Script number
|
|
907
|
+
// decoding is the case that matters: 78 of the corpus's rejected vectors
|
|
908
|
+
// expect SCRIPTNUM_MINENCODE or SCRIPTNUM_OVERFLOW, and every one of them
|
|
909
|
+
// used to arrive here and be flattened into UNKNOWN_ERROR. The script
|
|
910
|
+
// failed either way, so the accept/reject vectors could not see it.
|
|
911
|
+
this.errstr = e.scriptErr || ('SCRIPT_ERR_UNKNOWN_ERROR: ' + e)
|
|
642
912
|
return false
|
|
643
913
|
}
|
|
644
914
|
|
|
@@ -653,7 +923,7 @@ Interpreter.prototype.evaluate = function () {
|
|
|
653
923
|
Interpreter.prototype._callbackStep = function (thisStep) {
|
|
654
924
|
if (typeof this.stepListener === 'function') {
|
|
655
925
|
try {
|
|
656
|
-
this.stepListener(thisStep,
|
|
926
|
+
this.stepListener(thisStep, cloneStack(this.stack), cloneStack(this.altstack))
|
|
657
927
|
} catch (err) {
|
|
658
928
|
console.log(`Error in Step callback:${err}`)
|
|
659
929
|
}
|
|
@@ -699,7 +969,11 @@ Interpreter.prototype.checkLockTime = function (nLockTime) {
|
|
|
699
969
|
// prevent this condition. Alternatively we could test all
|
|
700
970
|
// inputs, but testing just this input minimizes the data
|
|
701
971
|
// required to prove correct CHECKLOCKTIMEVERIFY execution.
|
|
702
|
-
|
|
972
|
+
// Same guard as checkSequence: no input at `nin` means the locktime cannot be
|
|
973
|
+
// satisfied. Reached only when the comparisons above pass, which is why this one
|
|
974
|
+
// never surfaced as a TypeError — the ordering hid it, not a check.
|
|
975
|
+
var input = this.tx.inputs[this.nin]
|
|
976
|
+
if (!input || input.isFinal()) {
|
|
703
977
|
return false
|
|
704
978
|
}
|
|
705
979
|
|
|
@@ -713,9 +987,19 @@ Interpreter.prototype.checkLockTime = function (nLockTime) {
|
|
|
713
987
|
* the transaction's sequence
|
|
714
988
|
*/
|
|
715
989
|
Interpreter.prototype.checkSequence = function (nSequence) {
|
|
990
|
+
// No input at `nin` means the relative locktime cannot be satisfied, so fail the
|
|
991
|
+
// script rather than dereferencing undefined. This used to throw a TypeError that the
|
|
992
|
+
// evaluator's try/catch converted into SCRIPT_ERR_UNKNOWN_ERROR — a misleading error
|
|
993
|
+
// that pointed at the script instead of at the caller's index. The same shape as the
|
|
994
|
+
// `new BN(...)` note below, and as the CHECKLOCKTIMEVERIFY guard.
|
|
995
|
+
var input = this.tx.inputs[this.nin]
|
|
996
|
+
if (!input) {
|
|
997
|
+
return false
|
|
998
|
+
}
|
|
999
|
+
|
|
716
1000
|
// Relative lock times are supported by comparing the passed in operand to
|
|
717
1001
|
// the sequence number of the input.
|
|
718
|
-
var txToSequence =
|
|
1002
|
+
var txToSequence = input.sequenceNumber
|
|
719
1003
|
|
|
720
1004
|
// Fail if the transaction's version number is not set high enough to
|
|
721
1005
|
// trigger BIP 68 rules.
|
|
@@ -800,7 +1084,7 @@ Interpreter.prototype.step = function () {
|
|
|
800
1084
|
// "disabled" is stronger than "unimplemented": a disabled opcode fails the
|
|
801
1085
|
// script even in an UNEXECUTED branch, which is why this lives in
|
|
802
1086
|
// isOpcodeDisabled rather than in the evaluation switch.
|
|
803
|
-
if (
|
|
1087
|
+
if (!self.isAfterChronicle()) {
|
|
804
1088
|
return true
|
|
805
1089
|
}
|
|
806
1090
|
break
|
|
@@ -838,8 +1122,6 @@ Interpreter.prototype.step = function () {
|
|
|
838
1122
|
|
|
839
1123
|
var fRequireMinimal = (this.flags & Interpreter.SCRIPT_VERIFY_MINIMALDATA) !== 0
|
|
840
1124
|
|
|
841
|
-
// bool fExec = !count(vfExec.begin(), vfExec.end(), false);
|
|
842
|
-
var fExec = (this.vfExec.indexOf(false) === -1)
|
|
843
1125
|
var buf, buf1, buf2, spliced, n, x1, x2, bn, bn1, bn2, bufSig, bufPubkey, subscript
|
|
844
1126
|
var sig, pubkey
|
|
845
1127
|
var fValue, fSuccess
|
|
@@ -848,22 +1130,35 @@ Interpreter.prototype.step = function () {
|
|
|
848
1130
|
var chunk = this.script.chunks[this.pc]
|
|
849
1131
|
this.pc++
|
|
850
1132
|
var opcodenum = chunk.opcodenum
|
|
1133
|
+
|
|
1134
|
+
// bool fExec = !count(vfExec.begin(), vfExec.end(), false);
|
|
1135
|
+
//
|
|
1136
|
+
// Computed after the opcode is read, because it depends on it: once an
|
|
1137
|
+
// OP_RETURN has been seen inside a conditional after Genesis, nothing but a
|
|
1138
|
+
// further OP_RETURN executes, while the conditional grammar is still checked
|
|
1139
|
+
// through to the end of the script.
|
|
1140
|
+
var fExec = (this.vfExec.indexOf(false) === -1) &&
|
|
1141
|
+
(!this.nonTopLevelReturnAfterGenesis || opcodenum === Opcode.OP_RETURN)
|
|
851
1142
|
if (_.isUndefined(opcodenum)) {
|
|
852
1143
|
this.errstr = 'SCRIPT_ERR_UNDEFINED_OPCODE'
|
|
853
1144
|
return false
|
|
854
1145
|
}
|
|
855
|
-
if (chunk.buf && chunk.buf.length >
|
|
1146
|
+
if (chunk.buf && chunk.buf.length > this.maxScriptElementSize()) {
|
|
856
1147
|
this.errstr = 'SCRIPT_ERR_PUSH_SIZE'
|
|
857
1148
|
return false
|
|
858
1149
|
}
|
|
859
1150
|
|
|
860
1151
|
// Note how Opcode.OP_RESERVED does not count towards the opcode limit.
|
|
861
|
-
if (opcodenum > Opcode.OP_16 && ++(this.nOpCount) >
|
|
1152
|
+
if (opcodenum > Opcode.OP_16 && ++(this.nOpCount) > this.maxOpsPerScript()) {
|
|
862
1153
|
this.errstr = 'SCRIPT_ERR_OP_COUNT'
|
|
863
1154
|
return false
|
|
864
1155
|
}
|
|
865
1156
|
|
|
866
|
-
|
|
1157
|
+
// Before Genesis the mere presence of a disabled opcode invalidates the
|
|
1158
|
+
// script, even in a branch that never runs. After it, only executing one
|
|
1159
|
+
// fails — the node states it as `IsOpcodeDisabled(...) && (!utxo_after_genesis
|
|
1160
|
+
// || fExec)`.
|
|
1161
|
+
if (isOpcodeDisabled(opcodenum) && (!this.isAfterGenesis() || fExec)) {
|
|
867
1162
|
this.errstr = 'SCRIPT_ERR_DISABLED_OPCODE'
|
|
868
1163
|
return false
|
|
869
1164
|
}
|
|
@@ -876,7 +1171,13 @@ Interpreter.prototype.step = function () {
|
|
|
876
1171
|
if (!chunk.buf) {
|
|
877
1172
|
this.stack.push(Interpreter.false)
|
|
878
1173
|
} else if (chunk.len !== chunk.buf.length) {
|
|
879
|
-
|
|
1174
|
+
// A push that declares more bytes than the script carries — "PUSHDATA1
|
|
1175
|
+
// with not enough bytes" and its PUSHDATA2/4 counterparts. The node
|
|
1176
|
+
// fails these as SCRIPT_ERR_BAD_OPCODE. Throwing reached the evaluator's
|
|
1177
|
+
// catch and became UNKNOWN_ERROR; this is inside step(), which can
|
|
1178
|
+
// simply fail.
|
|
1179
|
+
this.errstr = 'SCRIPT_ERR_BAD_OPCODE'
|
|
1180
|
+
return false
|
|
880
1181
|
} else {
|
|
881
1182
|
this.stack.push(chunk.buf)
|
|
882
1183
|
}
|
|
@@ -918,7 +1219,14 @@ Interpreter.prototype.step = function () {
|
|
|
918
1219
|
case Opcode.OP_NOP2:
|
|
919
1220
|
case Opcode.OP_CHECKLOCKTIMEVERIFY:
|
|
920
1221
|
|
|
921
|
-
|
|
1222
|
+
// Genesis reverted this to an upgradable NOP for outputs created
|
|
1223
|
+
// after it, so a post-Genesis script containing it enforces no
|
|
1224
|
+
// locktime at all. The node reads
|
|
1225
|
+
// !(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) || utxo_after_genesis
|
|
1226
|
+
// and without the second half a transaction the network accepts is
|
|
1227
|
+
// rejected here.
|
|
1228
|
+
if (!(this.flags & Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) ||
|
|
1229
|
+
this.isAfterGenesis()) {
|
|
922
1230
|
// not enabled; treat as a NOP2
|
|
923
1231
|
if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
|
|
924
1232
|
this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
|
|
@@ -966,7 +1274,14 @@ Interpreter.prototype.step = function () {
|
|
|
966
1274
|
case Opcode.OP_NOP3:
|
|
967
1275
|
case Opcode.OP_CHECKSEQUENCEVERIFY:
|
|
968
1276
|
|
|
969
|
-
|
|
1277
|
+
// Genesis reverted this to an upgradable NOP for outputs created
|
|
1278
|
+
// after it, so a post-Genesis script containing it enforces no
|
|
1279
|
+
// locktime at all. The node reads
|
|
1280
|
+
// !(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY) || utxo_after_genesis
|
|
1281
|
+
// and without the second half a transaction the network accepts is
|
|
1282
|
+
// rejected here.
|
|
1283
|
+
if (!(this.flags & Interpreter.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY) ||
|
|
1284
|
+
this.isAfterGenesis()) {
|
|
970
1285
|
// not enabled; treat as a NOP3
|
|
971
1286
|
if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
|
|
972
1287
|
this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
|
|
@@ -1037,7 +1352,7 @@ Interpreter.prototype.step = function () {
|
|
|
1037
1352
|
//
|
|
1038
1353
|
// Rejecting them outright would make this library refuse scripts the network
|
|
1039
1354
|
// accepts, which is the mirror of the bug that made them silently succeed.
|
|
1040
|
-
if (
|
|
1355
|
+
if (!this.isAfterChronicle()) {
|
|
1041
1356
|
if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
|
|
1042
1357
|
this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
|
|
1043
1358
|
return false
|
|
@@ -1050,7 +1365,7 @@ Interpreter.prototype.step = function () {
|
|
|
1050
1365
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
|
|
1051
1366
|
return false
|
|
1052
1367
|
}
|
|
1053
|
-
var maxNumSize =
|
|
1368
|
+
var maxNumSize = this.maxScriptNumLength()
|
|
1054
1369
|
var shiftBn = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, maxNumSize)
|
|
1055
1370
|
if (shiftBn.isNeg()) {
|
|
1056
1371
|
this.errstr = 'SCRIPT_ERR_INVALID_NUMBER_RANGE'
|
|
@@ -1114,7 +1429,7 @@ Interpreter.prototype.step = function () {
|
|
|
1114
1429
|
//
|
|
1115
1430
|
// Unlike the string opcodes, BAD_OPCODE pre-Chronicle IS correct here —
|
|
1116
1431
|
// the node returns it unconditionally.
|
|
1117
|
-
if (
|
|
1432
|
+
if (!this.isAfterChronicle()) {
|
|
1118
1433
|
this.errstr = 'SCRIPT_ERR_BAD_OPCODE'
|
|
1119
1434
|
return false
|
|
1120
1435
|
}
|
|
@@ -1138,8 +1453,13 @@ Interpreter.prototype.step = function () {
|
|
|
1138
1453
|
// So pre-Chronicle they are an error only in an EXECUTED branch. BSV is
|
|
1139
1454
|
// post-Genesis, which is the whole condition. Returning BAD_OPCODE
|
|
1140
1455
|
// unconditionally rejected scripts the network accepts.
|
|
1141
|
-
if (
|
|
1142
|
-
|
|
1456
|
+
if (!this.isAfterChronicle()) {
|
|
1457
|
+
// Genesis is part of the condition, not an assumption: before it
|
|
1458
|
+
// these are illegal everywhere, including in a branch that never
|
|
1459
|
+
// runs, and only from Genesis does an unexecuted one become
|
|
1460
|
+
// harmless. The era is carried in the flags now, so a pre-Genesis
|
|
1461
|
+
// output is validated as one.
|
|
1462
|
+
if (this.isAfterGenesis() && !fExec) {
|
|
1143
1463
|
break
|
|
1144
1464
|
}
|
|
1145
1465
|
this.errstr = 'SCRIPT_ERR_BAD_OPCODE'
|
|
@@ -1171,6 +1491,7 @@ Interpreter.prototype.step = function () {
|
|
|
1171
1491
|
this.stack.pop()
|
|
1172
1492
|
}
|
|
1173
1493
|
this.vfExec.push(fValue)
|
|
1494
|
+
this.vfElse.push(false)
|
|
1174
1495
|
break
|
|
1175
1496
|
|
|
1176
1497
|
case Opcode.OP_IF:
|
|
@@ -1202,14 +1523,21 @@ Interpreter.prototype.step = function () {
|
|
|
1202
1523
|
this.stack.pop()
|
|
1203
1524
|
}
|
|
1204
1525
|
this.vfExec.push(fValue)
|
|
1526
|
+
this.vfElse.push(false)
|
|
1205
1527
|
break
|
|
1206
1528
|
|
|
1207
1529
|
case Opcode.OP_ELSE:
|
|
1208
|
-
|
|
1530
|
+
// Genesis allows only one OP_ELSE per OP_IF. A second one is
|
|
1531
|
+
// unbalanced, and accepting it means accepting scripts the network
|
|
1532
|
+
// rejects — the node states it as
|
|
1533
|
+
// if (vfExec.empty() || (vfElse.back() && utxo_after_genesis))
|
|
1534
|
+
if (this.vfExec.length === 0 ||
|
|
1535
|
+
(this.vfElse[this.vfElse.length - 1] && this.isAfterGenesis())) {
|
|
1209
1536
|
this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL'
|
|
1210
1537
|
return false
|
|
1211
1538
|
}
|
|
1212
1539
|
this.vfExec[this.vfExec.length - 1] = !this.vfExec[this.vfExec.length - 1]
|
|
1540
|
+
this.vfElse[this.vfElse.length - 1] = true
|
|
1213
1541
|
break
|
|
1214
1542
|
|
|
1215
1543
|
case Opcode.OP_ENDIF:
|
|
@@ -1218,6 +1546,7 @@ Interpreter.prototype.step = function () {
|
|
|
1218
1546
|
return false
|
|
1219
1547
|
}
|
|
1220
1548
|
this.vfExec.pop()
|
|
1549
|
+
this.vfElse.pop()
|
|
1221
1550
|
break
|
|
1222
1551
|
|
|
1223
1552
|
case Opcode.OP_VERIFY:
|
|
@@ -1238,6 +1567,21 @@ Interpreter.prototype.step = function () {
|
|
|
1238
1567
|
break
|
|
1239
1568
|
|
|
1240
1569
|
case Opcode.OP_RETURN:
|
|
1570
|
+
if (this.isAfterGenesis()) {
|
|
1571
|
+
if (this.vfExec.length === 0) {
|
|
1572
|
+
// Genesis restored OP_RETURN's original meaning: it terminates the
|
|
1573
|
+
// script and the top stack item decides validity. The remainder
|
|
1574
|
+
// cannot affect the outcome, even if it holds unbalanced
|
|
1575
|
+
// conditionals or invalid opcodes, which is what makes
|
|
1576
|
+
// OP_FALSE OP_RETURN <data> outputs safe to carry anything.
|
|
1577
|
+
this.returned = true
|
|
1578
|
+
break
|
|
1579
|
+
}
|
|
1580
|
+
// Inside a conditional, suppress the rest but keep checking grammar.
|
|
1581
|
+
this.nonTopLevelReturnAfterGenesis = true
|
|
1582
|
+
break
|
|
1583
|
+
}
|
|
1584
|
+
// Before Genesis, an OP_RETURN alone invalidates the script.
|
|
1241
1585
|
this.errstr = 'SCRIPT_ERR_OP_RETURN'
|
|
1242
1586
|
return false
|
|
1243
1587
|
// break // unreachable
|
|
@@ -1395,7 +1739,7 @@ Interpreter.prototype.step = function () {
|
|
|
1395
1739
|
return false
|
|
1396
1740
|
}
|
|
1397
1741
|
buf = stacktop(-1)
|
|
1398
|
-
bn = BN.fromScriptNumBuffer(buf, fRequireMinimal)
|
|
1742
|
+
bn = BN.fromScriptNumBuffer(buf, fRequireMinimal, this.maxScriptNumLength())
|
|
1399
1743
|
n = bn.toNumber()
|
|
1400
1744
|
this.stack.pop()
|
|
1401
1745
|
if (n < 0 || n >= this.stack.length) {
|
|
@@ -1505,6 +1849,10 @@ Interpreter.prototype.step = function () {
|
|
|
1505
1849
|
// (x -- out)
|
|
1506
1850
|
if (this.stack.length < 1) {
|
|
1507
1851
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
|
|
1852
|
+
// The missing return here let evaluation continue and crash on the
|
|
1853
|
+
// absent operand, reporting an internal TypeError rather than the
|
|
1854
|
+
// stack error it had already decided on.
|
|
1855
|
+
return false
|
|
1508
1856
|
}
|
|
1509
1857
|
buf = stacktop(-1)
|
|
1510
1858
|
for (let i = 0; i < buf.length; i++) {
|
|
@@ -1524,7 +1872,7 @@ Interpreter.prototype.step = function () {
|
|
|
1524
1872
|
this.stack.pop()
|
|
1525
1873
|
} else {
|
|
1526
1874
|
bn1 = new BN(buf1)
|
|
1527
|
-
bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal)
|
|
1875
|
+
bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength())
|
|
1528
1876
|
n = bn2.toNumber()
|
|
1529
1877
|
if (n < 0) {
|
|
1530
1878
|
this.errstr = 'SCRIPT_ERR_INVALID_NUMBER_RANGE'
|
|
@@ -1589,7 +1937,7 @@ Interpreter.prototype.step = function () {
|
|
|
1589
1937
|
return false
|
|
1590
1938
|
}
|
|
1591
1939
|
buf = stacktop(-1)
|
|
1592
|
-
bn = BN.fromScriptNumBuffer(buf, fRequireMinimal)
|
|
1940
|
+
bn = BN.fromScriptNumBuffer(buf, fRequireMinimal, this.maxScriptNumLength())
|
|
1593
1941
|
switch (opcodenum) {
|
|
1594
1942
|
case Opcode.OP_2MUL:
|
|
1595
1943
|
bn = bn.mul(new BN(2))
|
|
@@ -1648,8 +1996,8 @@ Interpreter.prototype.step = function () {
|
|
|
1648
1996
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
|
|
1649
1997
|
return false
|
|
1650
1998
|
}
|
|
1651
|
-
bn1 = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal,
|
|
1652
|
-
bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal,
|
|
1999
|
+
bn1 = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal, this.maxScriptNumLength())
|
|
2000
|
+
bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength())
|
|
1653
2001
|
bn = new BN(0)
|
|
1654
2002
|
|
|
1655
2003
|
switch (opcodenum) {
|
|
@@ -1666,8 +2014,12 @@ Interpreter.prototype.step = function () {
|
|
|
1666
2014
|
break
|
|
1667
2015
|
|
|
1668
2016
|
case Opcode.OP_DIV:
|
|
1669
|
-
// denominator must not be 0
|
|
1670
|
-
|
|
2017
|
+
// denominator must not be 0. bn2 is a BN, so `bn2 === 0` was never
|
|
2018
|
+
// true and this guard never fired — bn.js asserted instead, and
|
|
2019
|
+
// the evaluator's catch reported SCRIPT_ERR_UNKNOWN_ERROR. The
|
|
2020
|
+
// script still failed, which is why the accept/reject vectors
|
|
2021
|
+
// stayed green while the reason was wrong.
|
|
2022
|
+
if (bn2.cmp(BN.Zero) === 0) {
|
|
1671
2023
|
this.errstr = 'SCRIPT_ERR_DIV_BY_ZERO'
|
|
1672
2024
|
return false
|
|
1673
2025
|
}
|
|
@@ -1675,9 +2027,9 @@ Interpreter.prototype.step = function () {
|
|
|
1675
2027
|
break
|
|
1676
2028
|
|
|
1677
2029
|
case Opcode.OP_MOD:
|
|
1678
|
-
// divisor must not be 0
|
|
1679
|
-
if (bn2 === 0) {
|
|
1680
|
-
this.errstr = '
|
|
2030
|
+
// divisor must not be 0. The node reports this one separately.
|
|
2031
|
+
if (bn2.cmp(BN.Zero) === 0) {
|
|
2032
|
+
this.errstr = 'SCRIPT_ERR_MOD_BY_ZERO'
|
|
1681
2033
|
return false
|
|
1682
2034
|
}
|
|
1683
2035
|
bn = bn1.mod(bn2)
|
|
@@ -1747,9 +2099,9 @@ Interpreter.prototype.step = function () {
|
|
|
1747
2099
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
|
|
1748
2100
|
return false
|
|
1749
2101
|
}
|
|
1750
|
-
bn1 = BN.fromScriptNumBuffer(stacktop(-3), fRequireMinimal,
|
|
1751
|
-
bn2 = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal,
|
|
1752
|
-
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())
|
|
1753
2105
|
// bool fValue = (bn2 <= bn1 && bn1 < bn3);
|
|
1754
2106
|
fValue = (bn2.cmp(bn1) <= 0) && (bn1.cmp(bn3) < 0)
|
|
1755
2107
|
this.stack.pop()
|
|
@@ -1861,9 +2213,10 @@ Interpreter.prototype.step = function () {
|
|
|
1861
2213
|
return false
|
|
1862
2214
|
}
|
|
1863
2215
|
|
|
1864
|
-
var nKeysCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal).toNumber()
|
|
2216
|
+
var nKeysCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal, this.maxScriptNumLength()).toNumber()
|
|
1865
2217
|
// TODO: Keys and opcount are parameterized in client. No magic numbers!
|
|
1866
|
-
|
|
2218
|
+
// Genesis raised this to UINT32_MAX rather than removing it.
|
|
2219
|
+
if (nKeysCount < 0 || nKeysCount > this.maxPubKeysPerMultisig()) {
|
|
1867
2220
|
this.errstr = 'SCRIPT_ERR_PUBKEY_COUNT'
|
|
1868
2221
|
return false
|
|
1869
2222
|
}
|
|
@@ -1887,7 +2240,7 @@ Interpreter.prototype.step = function () {
|
|
|
1887
2240
|
return false
|
|
1888
2241
|
}
|
|
1889
2242
|
|
|
1890
|
-
var nSigsCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal).toNumber()
|
|
2243
|
+
var nSigsCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal, this.maxScriptNumLength()).toNumber()
|
|
1891
2244
|
if (nSigsCount < 0 || nSigsCount > nKeysCount) {
|
|
1892
2245
|
this.errstr = 'SCRIPT_ERR_SIG_COUNT'
|
|
1893
2246
|
return false
|
|
@@ -2000,7 +2353,12 @@ Interpreter.prototype.step = function () {
|
|
|
2000
2353
|
|
|
2001
2354
|
buf1 = stacktop(-2)
|
|
2002
2355
|
buf2 = stacktop(-1)
|
|
2003
|
-
|
|
2356
|
+
// Era-derived, like every other element size check. Genesis lifted the
|
|
2357
|
+
// 520-byte cap, and reading the static here meant OP_CAT kept
|
|
2358
|
+
// enforcing it after Genesis — rejecting a concatenation the network
|
|
2359
|
+
// accepts. No vector in the corpus covers this, so it is held by
|
|
2360
|
+
// test/script/genesis_limits.js instead.
|
|
2361
|
+
if (buf1.length + buf2.length > this.maxScriptElementSize()) {
|
|
2004
2362
|
this.errstr = 'SCRIPT_ERR_PUSH_SIZE'
|
|
2005
2363
|
return false
|
|
2006
2364
|
}
|
|
@@ -2016,7 +2374,7 @@ Interpreter.prototype.step = function () {
|
|
|
2016
2374
|
buf1 = stacktop(-2)
|
|
2017
2375
|
|
|
2018
2376
|
// Make sure the split point is apropriate.
|
|
2019
|
-
var position = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal).toNumber()
|
|
2377
|
+
var position = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength()).toNumber()
|
|
2020
2378
|
if (position < 0 || position > buf1.length) {
|
|
2021
2379
|
this.errstr = 'SCRIPT_ERR_INVALID_SPLIT_RANGE'
|
|
2022
2380
|
return false
|
|
@@ -2046,7 +2404,7 @@ Interpreter.prototype.step = function () {
|
|
|
2046
2404
|
//
|
|
2047
2405
|
// Running them unconditionally consumed stack where the network does
|
|
2048
2406
|
// nothing, which is a wrong answer rather than an error.
|
|
2049
|
-
if (
|
|
2407
|
+
if (!this.isAfterChronicle()) {
|
|
2050
2408
|
if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
|
|
2051
2409
|
this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
|
|
2052
2410
|
return false
|
|
@@ -2059,7 +2417,7 @@ Interpreter.prototype.step = function () {
|
|
|
2059
2417
|
return false
|
|
2060
2418
|
}
|
|
2061
2419
|
buf1 = stacktop(-2)
|
|
2062
|
-
n = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal,
|
|
2420
|
+
n = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength()).toNumber()
|
|
2063
2421
|
// ERRORS on out of range; it does not clamp. The node is
|
|
2064
2422
|
// `if(len < 0 || len > size) return SCRIPT_ERR_INVALID_NUMBER_RANGE`.
|
|
2065
2423
|
// Clamping made scripts the node rejects succeed here.
|
|
@@ -2088,7 +2446,7 @@ Interpreter.prototype.step = function () {
|
|
|
2088
2446
|
//
|
|
2089
2447
|
// Running them unconditionally consumed stack where the network does
|
|
2090
2448
|
// nothing, which is a wrong answer rather than an error.
|
|
2091
|
-
if (
|
|
2449
|
+
if (!this.isAfterChronicle()) {
|
|
2092
2450
|
if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
|
|
2093
2451
|
this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
|
|
2094
2452
|
return false
|
|
@@ -2101,8 +2459,8 @@ Interpreter.prototype.step = function () {
|
|
|
2101
2459
|
return false
|
|
2102
2460
|
}
|
|
2103
2461
|
buf1 = stacktop(-3)
|
|
2104
|
-
var subSize = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal,
|
|
2105
|
-
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()
|
|
2106
2464
|
// ERRORS on out of range, matching
|
|
2107
2465
|
// offset < 0 || offset >= size || len < 0 || len > size - offset
|
|
2108
2466
|
// Note `offset >= size` is strict: a begin index AT the end is an
|
|
@@ -2126,8 +2484,12 @@ Interpreter.prototype.step = function () {
|
|
|
2126
2484
|
return false
|
|
2127
2485
|
}
|
|
2128
2486
|
|
|
2129
|
-
var size = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal).toNumber()
|
|
2130
|
-
|
|
2487
|
+
var size = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, this.maxScriptNumLength()).toNumber()
|
|
2488
|
+
// A negative size is a push size failure, not an encoding one. Without
|
|
2489
|
+
// the lower bound it fell through to the rawnum.length > size test,
|
|
2490
|
+
// which any number passes when size is negative, and reported
|
|
2491
|
+
// IMPOSSIBLE_ENCODING instead.
|
|
2492
|
+
if (size < 0 || size > this.maxScriptElementSize()) {
|
|
2131
2493
|
this.errstr = 'SCRIPT_ERR_PUSH_SIZE'
|
|
2132
2494
|
return false
|
|
2133
2495
|
}
|