smartledger-bsv 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/LICENSE +36 -0
  2. package/README.md +305 -0
  3. package/SECURITY.md +75 -0
  4. package/bsv-ecies.min.js +12 -0
  5. package/bsv-message.min.js +10 -0
  6. package/bsv-mnemonic.min.js +12 -0
  7. package/bsv.d.ts +440 -0
  8. package/bsv.min.js +37 -0
  9. package/ecies/index.js +1 -0
  10. package/index.js +101 -0
  11. package/lib/address.js +526 -0
  12. package/lib/block/block.js +277 -0
  13. package/lib/block/blockheader.js +294 -0
  14. package/lib/block/index.js +4 -0
  15. package/lib/block/merkleblock.js +316 -0
  16. package/lib/crypto/bn.js +278 -0
  17. package/lib/crypto/ecdsa.js +330 -0
  18. package/lib/crypto/elliptic-fixed.js +74 -0
  19. package/lib/crypto/hash.browser.js +171 -0
  20. package/lib/crypto/hash.js +2 -0
  21. package/lib/crypto/hash.node.js +171 -0
  22. package/lib/crypto/point.js +217 -0
  23. package/lib/crypto/random.js +37 -0
  24. package/lib/crypto/signature.js +410 -0
  25. package/lib/crypto/smartledger_verify.js +109 -0
  26. package/lib/ecies/bitcore-ecies.js +163 -0
  27. package/lib/ecies/electrum-ecies.js +175 -0
  28. package/lib/ecies/errors.js +16 -0
  29. package/lib/ecies/index.js +1 -0
  30. package/lib/encoding/base58.js +108 -0
  31. package/lib/encoding/base58check.js +112 -0
  32. package/lib/encoding/bufferreader.js +200 -0
  33. package/lib/encoding/bufferwriter.js +150 -0
  34. package/lib/encoding/varint.js +71 -0
  35. package/lib/errors/index.js +57 -0
  36. package/lib/errors/spec.js +184 -0
  37. package/lib/hdprivatekey.js +655 -0
  38. package/lib/hdpublickey.js +509 -0
  39. package/lib/message/index.js +4 -0
  40. package/lib/message/message.js +181 -0
  41. package/lib/mnemonic/errors.js +18 -0
  42. package/lib/mnemonic/index.js +4 -0
  43. package/lib/mnemonic/mnemonic.js +304 -0
  44. package/lib/mnemonic/pbkdf2.js +68 -0
  45. package/lib/mnemonic/words/chinese.js +5 -0
  46. package/lib/mnemonic/words/english.js +5 -0
  47. package/lib/mnemonic/words/french.js +5 -0
  48. package/lib/mnemonic/words/index.js +8 -0
  49. package/lib/mnemonic/words/italian.js +5 -0
  50. package/lib/mnemonic/words/japanese.js +5 -0
  51. package/lib/mnemonic/words/spanish.js +5 -0
  52. package/lib/networks.js +392 -0
  53. package/lib/opcode.js +248 -0
  54. package/lib/privatekey.js +373 -0
  55. package/lib/publickey.js +387 -0
  56. package/lib/script/index.js +3 -0
  57. package/lib/script/interpreter.js +1807 -0
  58. package/lib/script/script.js +1153 -0
  59. package/lib/transaction/index.js +7 -0
  60. package/lib/transaction/input/index.js +6 -0
  61. package/lib/transaction/input/input.js +202 -0
  62. package/lib/transaction/input/multisig.js +220 -0
  63. package/lib/transaction/input/multisigscripthash.js +189 -0
  64. package/lib/transaction/input/publickey.js +96 -0
  65. package/lib/transaction/input/publickeyhash.js +103 -0
  66. package/lib/transaction/output.js +192 -0
  67. package/lib/transaction/sighash.js +288 -0
  68. package/lib/transaction/signature.js +88 -0
  69. package/lib/transaction/transaction.js +1208 -0
  70. package/lib/transaction/unspentoutput.js +97 -0
  71. package/lib/util/_.js +44 -0
  72. package/lib/util/js.js +91 -0
  73. package/lib/util/preconditions.js +34 -0
  74. package/message/index.js +1 -0
  75. package/mnemonic/index.js +1 -0
  76. package/package.json +86 -0
@@ -0,0 +1,1807 @@
1
+ 'use strict'
2
+
3
+ var _ = require('../util/_')
4
+
5
+ var Script = require('./script')
6
+ var Opcode = require('../opcode')
7
+ var BN = require('../crypto/bn')
8
+ var Hash = require('../crypto/hash')
9
+ var Signature = require('../crypto/signature')
10
+ var PublicKey = require('../publickey')
11
+ var cloneDeep = require('clone-deep')
12
+
13
+ /**
14
+ * Bitcoin transactions contain scripts. Each input has a script called the
15
+ * scriptSig, and each output has a script called the scriptPubkey. To validate
16
+ * an input, the input's script is concatenated with the referenced output script,
17
+ * and the result is executed. If at the end of execution the stack contains a
18
+ * "true" value, then the transaction is valid.
19
+ *
20
+ * The primary way to use this class is via the verify function.
21
+ * e.g., Interpreter().verify( ... );
22
+ */
23
+ var Interpreter = function Interpreter (obj) {
24
+ if (!(this instanceof Interpreter)) {
25
+ return new Interpreter(obj)
26
+ }
27
+ if (obj) {
28
+ this.initialize()
29
+ this.set(obj)
30
+ } else {
31
+ this.initialize()
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Verifies a Script by executing it and returns true if it is valid.
37
+ * This function needs to be provided with the scriptSig and the scriptPubkey
38
+ * separately.
39
+ * @param {Script} scriptSig - the script's first part (corresponding to the tx input)
40
+ * @param {Script} scriptPubkey - the script's last part (corresponding to the tx output)
41
+ * @param {Transaction=} tx - the Transaction containing the scriptSig in one input (used
42
+ * to check signature validity for some opcodes like OP_CHECKSIG)
43
+ * @param {number} nin - index of the transaction input containing the scriptSig verified.
44
+ * @param {number} flags - evaluation flags. See Interpreter.SCRIPT_* constants
45
+ * @param {number} satoshisBN - amount in satoshis of the input to be verified (when FORKID signhash is used)
46
+ *
47
+ * Translated from bitcoind's VerifyScript
48
+ */
49
+ Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags, satoshisBN) {
50
+ var Transaction = require('../transaction')
51
+
52
+ if (_.isUndefined(tx)) {
53
+ tx = new Transaction()
54
+ }
55
+ if (_.isUndefined(nin)) {
56
+ nin = 0
57
+ }
58
+ if (_.isUndefined(flags)) {
59
+ flags = 0
60
+ }
61
+
62
+ // If FORKID is enabled, we also ensure strict encoding.
63
+ if (flags & Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID) {
64
+ flags |= Interpreter.SCRIPT_VERIFY_STRICTENC
65
+
66
+ // If FORKID is enabled, we need the input amount.
67
+ if (!satoshisBN) {
68
+ throw new Error('internal error - need satoshisBN to verify FORKID transactions')
69
+ }
70
+ }
71
+
72
+ this.set({
73
+ script: scriptSig,
74
+ tx: tx,
75
+ nin: nin,
76
+ flags: flags,
77
+ satoshisBN: satoshisBN
78
+ })
79
+ var stackCopy
80
+
81
+ if ((flags & Interpreter.SCRIPT_VERIFY_SIGPUSHONLY) !== 0 && !scriptSig.isPushOnly()) {
82
+ this.errstr = 'SCRIPT_ERR_SIG_PUSHONLY'
83
+ return false
84
+ }
85
+
86
+ // evaluate scriptSig
87
+ if (!this.evaluate()) {
88
+ return false
89
+ }
90
+
91
+ if (flags & Interpreter.SCRIPT_VERIFY_P2SH) {
92
+ stackCopy = this.stack.slice()
93
+ }
94
+
95
+ var stack = this.stack
96
+ this.initialize()
97
+ this.set({
98
+ script: scriptPubkey,
99
+ stack: stack,
100
+ tx: tx,
101
+ nin: nin,
102
+ flags: flags,
103
+ satoshisBN: satoshisBN
104
+ })
105
+
106
+ // evaluate scriptPubkey
107
+ if (!this.evaluate()) {
108
+ return false
109
+ }
110
+
111
+ if (this.stack.length === 0) {
112
+ this.errstr = 'SCRIPT_ERR_EVAL_FALSE_NO_RESULT'
113
+ return false
114
+ }
115
+
116
+ var buf = this.stack[this.stack.length - 1]
117
+ if (!Interpreter.castToBool(buf)) {
118
+ this.errstr = 'SCRIPT_ERR_EVAL_FALSE_IN_STACK'
119
+ return false
120
+ }
121
+
122
+ // Additional validation for spend-to-script-hash transactions:
123
+ if ((flags & Interpreter.SCRIPT_VERIFY_P2SH) && scriptPubkey.isScriptHashOut()) {
124
+ // scriptSig must be literals-only or validation fails
125
+ if (!scriptSig.isPushOnly()) {
126
+ this.errstr = 'SCRIPT_ERR_SIG_PUSHONLY'
127
+ return false
128
+ }
129
+
130
+ // stackCopy cannot be empty here, because if it was the
131
+ // P2SH HASH <> EQUAL scriptPubKey would be evaluated with
132
+ // an empty stack and the EvalScript above would return false.
133
+ if (stackCopy.length === 0) {
134
+ throw new Error('internal error - stack copy empty')
135
+ }
136
+
137
+ var redeemScriptSerialized = stackCopy[stackCopy.length - 1]
138
+ var redeemScript = Script.fromBuffer(redeemScriptSerialized)
139
+ stackCopy.pop()
140
+
141
+ this.initialize()
142
+ this.set({
143
+ script: redeemScript,
144
+ stack: stackCopy,
145
+ tx: tx,
146
+ nin: nin,
147
+ flags: flags,
148
+ satoshisBN: satoshisBN
149
+ })
150
+
151
+ // evaluate redeemScript
152
+ if (!this.evaluate()) {
153
+ return false
154
+ }
155
+
156
+ if (stackCopy.length === 0) {
157
+ this.errstr = 'SCRIPT_ERR_EVAL_FALSE_NO_P2SH_STACK'
158
+ return false
159
+ }
160
+
161
+ if (!Interpreter.castToBool(stackCopy[stackCopy.length - 1])) {
162
+ this.errstr = 'SCRIPT_ERR_EVAL_FALSE_IN_P2SH_STACK'
163
+ return false
164
+ }
165
+ }
166
+
167
+ // The CLEANSTACK check is only performed after potential P2SH evaluation,
168
+ // as the non-P2SH evaluation of a P2SH script will obviously not result in
169
+ // a clean stack (the P2SH inputs remain). The same holds for witness
170
+ // evaluation.
171
+ if ((flags & Interpreter.SCRIPT_VERIFY_CLEANSTACK) !== 0) {
172
+ // Disallow CLEANSTACK without P2SH, as otherwise a switch
173
+ // CLEANSTACK->P2SH+CLEANSTACK would be possible, which is not a
174
+ // softfork (and P2SH should be one).
175
+ if ((flags & Interpreter.SCRIPT_VERIFY_P2SH) === 0) {
176
+ throw new Error('internal error - CLEANSTACK without P2SH')
177
+ }
178
+
179
+ if (stackCopy.length !== 1) {
180
+ this.errstr = 'SCRIPT_ERR_CLEANSTACK'
181
+ return false
182
+ }
183
+ }
184
+
185
+ return true
186
+ }
187
+
188
+ module.exports = Interpreter
189
+
190
+ Interpreter.prototype.initialize = function (obj) {
191
+ this.stack = []
192
+ this.altstack = []
193
+ this.pc = 0
194
+ this.pbegincodehash = 0
195
+ this.nOpCount = 0
196
+ this.vfExec = []
197
+ this.errstr = ''
198
+ this.flags = 0
199
+ }
200
+
201
+ Interpreter.prototype.set = function (obj) {
202
+ this.script = obj.script || this.script
203
+ this.tx = obj.tx || this.tx
204
+ this.nin = typeof obj.nin !== 'undefined' ? obj.nin : this.nin
205
+ this.satoshisBN = obj.satoshisBN || this.satoshisBN
206
+ this.stack = obj.stack || this.stack
207
+ this.altstack = obj.altstack || this.altstack
208
+ this.pc = typeof obj.pc !== 'undefined' ? obj.pc : this.pc
209
+ this.pbegincodehash = typeof obj.pbegincodehash !== 'undefined' ? obj.pbegincodehash : this.pbegincodehash
210
+ this.nOpCount = typeof obj.nOpCount !== 'undefined' ? obj.nOpCount : this.nOpCount
211
+ this.vfExec = obj.vfExec || this.vfExec
212
+ this.errstr = obj.errstr || this.errstr
213
+ this.flags = typeof obj.flags !== 'undefined' ? obj.flags : this.flags
214
+ }
215
+
216
+ Interpreter.true = Buffer.from([1])
217
+ Interpreter.false = Buffer.from([])
218
+
219
+ Interpreter.MAX_SCRIPT_ELEMENT_SIZE = 520
220
+ Interpreter.MAXIMUM_ELEMENT_SIZE = 4
221
+
222
+ Interpreter.LOCKTIME_THRESHOLD = 500000000
223
+ Interpreter.LOCKTIME_THRESHOLD_BN = new BN(Interpreter.LOCKTIME_THRESHOLD)
224
+
225
+ // flags taken from bitcoind
226
+ // bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
227
+ Interpreter.SCRIPT_VERIFY_NONE = 0
228
+
229
+ // Evaluate P2SH subscripts (softfork safe, BIP16).
230
+ Interpreter.SCRIPT_VERIFY_P2SH = (1 << 0)
231
+
232
+ // Passing a non-strict-DER signature or one with undefined hashtype to a checksig operation causes script failure.
233
+ // Passing a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) to checksig causes that pubkey to be
234
+ // skipped (not softfork safe: this flag can widen the validity of OP_CHECKSIG OP_NOT).
235
+ Interpreter.SCRIPT_VERIFY_STRICTENC = (1 << 1)
236
+
237
+ // Passing a non-strict-DER signature to a checksig operation causes script failure (softfork safe, BIP62 rule 1)
238
+ Interpreter.SCRIPT_VERIFY_DERSIG = (1 << 2)
239
+
240
+ // Passing a non-strict-DER signature or one with S > order/2 to a checksig operation causes script failure
241
+ // (softfork safe, BIP62 rule 5).
242
+ Interpreter.SCRIPT_VERIFY_LOW_S = (1 << 3)
243
+
244
+ // verify dummy stack item consumed by CHECKMULTISIG is of zero-length (softfork safe, BIP62 rule 7).
245
+ Interpreter.SCRIPT_VERIFY_NULLDUMMY = (1 << 4)
246
+
247
+ // Using a non-push operator in the scriptSig causes script failure (softfork safe, BIP62 rule 2).
248
+ Interpreter.SCRIPT_VERIFY_SIGPUSHONLY = (1 << 5)
249
+
250
+ // Require minimal encodings for all push operations (OP_0... OP_16, OP_1NEGATE where possible, direct
251
+ // pushes up to 75 bytes, OP_PUSHDATA up to 255 bytes, OP_PUSHDATA2 for anything larger). Evaluating
252
+ // any other push causes the script to fail (BIP62 rule 3).
253
+ // In addition, whenever a stack element is interpreted as a number, it must be of minimal length (BIP62 rule 4).
254
+ // (softfork safe)
255
+ Interpreter.SCRIPT_VERIFY_MINIMALDATA = (1 << 6)
256
+
257
+ // Discourage use of NOPs reserved for upgrades (NOP1-10)
258
+ //
259
+ // Provided so that nodes can avoid accepting or mining transactions
260
+ // containing executed NOP's whose meaning may change after a soft-fork,
261
+ // thus rendering the script invalid; with this flag set executing
262
+ // discouraged NOPs fails the script. This verification flag will never be
263
+ // a mandatory flag applied to scripts in a block. NOPs that are not
264
+ // executed, e.g. within an unexecuted IF ENDIF block, are *not* rejected.
265
+ Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = (1 << 7)
266
+
267
+ // Require that only a single stack element remains after evaluation. This
268
+ // changes the success criterion from "At least one stack element must
269
+ // remain, and when interpreted as a boolean, it must be true" to "Exactly
270
+ // one stack element must remain, and when interpreted as a boolean, it must
271
+ // be true".
272
+ // (softfork safe, BIP62 rule 6)
273
+ // Note: CLEANSTACK should never be used without P2SH or WITNESS.
274
+ Interpreter.SCRIPT_VERIFY_CLEANSTACK = (1 << 8)
275
+
276
+ // CLTV See BIP65 for details.
277
+ Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1 << 9)
278
+
279
+ // support CHECKSEQUENCEVERIFY opcode
280
+ //
281
+ // See BIP112 for details
282
+ Interpreter.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = (1 << 10)
283
+
284
+ // Segwit script only: Require the argument of OP_IF/NOTIF to be exactly
285
+ // 0x01 or empty vector
286
+ //
287
+ Interpreter.SCRIPT_VERIFY_MINIMALIF = (1 << 13)
288
+
289
+ // Signature(s) must be empty vector if an CHECK(MULTI)SIG operation failed
290
+ //
291
+ Interpreter.SCRIPT_VERIFY_NULLFAIL = (1 << 14)
292
+
293
+ // Public keys in scripts must be compressed
294
+ Interpreter.SCRIPT_VERIFY_COMPRESSED_PUBKEYTYPE = (1 << 15)
295
+
296
+ // Do we accept signature using SIGHASH_FORKID
297
+ //
298
+ Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID = (1 << 16)
299
+
300
+ // Do we accept activate replay protection using a different fork id.
301
+ //
302
+ Interpreter.SCRIPT_ENABLE_REPLAY_PROTECTION = (1 << 17)
303
+
304
+ // Enable new opcodes.
305
+ //
306
+ Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES = (1 << 18)
307
+
308
+ // Are the Magnetic upgrade opcodes enabled?
309
+ //
310
+ Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES = (1 << 19)
311
+
312
+ /* Below flags apply in the context of BIP 68 */
313
+ /**
314
+ * If this flag set, CTxIn::nSequence is NOT interpreted as a relative
315
+ * lock-time.
316
+ */
317
+ Interpreter.SEQUENCE_LOCKTIME_DISABLE_FLAG = (1 << 31)
318
+
319
+ /**
320
+ * If CTxIn::nSequence encodes a relative lock-time and this flag is set,
321
+ * the relative lock-time has units of 512 seconds, otherwise it specifies
322
+ * blocks with a granularity of 1.
323
+ */
324
+ Interpreter.SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22)
325
+
326
+ /**
327
+ * If CTxIn::nSequence encodes a relative lock-time, this mask is applied to
328
+ * extract that lock-time from the sequence field.
329
+ */
330
+ Interpreter.SEQUENCE_LOCKTIME_MASK = 0x0000ffff
331
+
332
+ Interpreter.castToBool = function (buf) {
333
+ for (var i = 0; i < buf.length; i++) {
334
+ if (buf[i] !== 0) {
335
+ // can be negative zero
336
+ if (i === buf.length - 1 && buf[i] === 0x80) {
337
+ return false
338
+ }
339
+ return true
340
+ }
341
+ }
342
+ return false
343
+ }
344
+
345
+ /**
346
+ * Translated from bitcoind's CheckSignatureEncoding
347
+ */
348
+ Interpreter.prototype.checkSignatureEncoding = function (buf) {
349
+ var sig
350
+
351
+ // Empty signature. Not strictly DER encoded, but allowed to provide a
352
+ // compact way to provide an invalid signature for use with CHECK(MULTI)SIG
353
+ if (buf.length === 0) {
354
+ return true
355
+ }
356
+
357
+ if ((this.flags & (Interpreter.SCRIPT_VERIFY_DERSIG | Interpreter.SCRIPT_VERIFY_LOW_S | Interpreter.SCRIPT_VERIFY_STRICTENC)) !== 0 && !Signature.isTxDER(buf)) {
358
+ this.errstr = 'SCRIPT_ERR_SIG_DER_INVALID_FORMAT'
359
+ return false
360
+ } else if ((this.flags & Interpreter.SCRIPT_VERIFY_LOW_S) !== 0) {
361
+ sig = Signature.fromTxFormat(buf)
362
+ if (!sig.hasLowS()) {
363
+ this.errstr = 'SCRIPT_ERR_SIG_DER_HIGH_S'
364
+ return false
365
+ }
366
+ } else if ((this.flags & Interpreter.SCRIPT_VERIFY_STRICTENC) !== 0) {
367
+ sig = Signature.fromTxFormat(buf)
368
+ if (!sig.hasDefinedHashtype()) {
369
+ this.errstr = 'SCRIPT_ERR_SIG_HASHTYPE'
370
+ return false
371
+ }
372
+
373
+ if (!(this.flags & Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID) &&
374
+ (sig.nhashtype & Signature.SIGHASH_FORKID)) {
375
+ this.errstr = 'SCRIPT_ERR_ILLEGAL_FORKID'
376
+ return false
377
+ }
378
+
379
+ if ((this.flags & Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID) &&
380
+ !(sig.nhashtype & Signature.SIGHASH_FORKID)) {
381
+ this.errstr = 'SCRIPT_ERR_MUST_USE_FORKID'
382
+ return false
383
+ }
384
+ }
385
+
386
+ return true
387
+ }
388
+
389
+ /**
390
+ * Translated from bitcoind's CheckPubKeyEncoding
391
+ */
392
+ Interpreter.prototype.checkPubkeyEncoding = function (buf) {
393
+ if ((this.flags & Interpreter.SCRIPT_VERIFY_STRICTENC) !== 0 && !PublicKey.isValid(buf)) {
394
+ this.errstr = 'SCRIPT_ERR_PUBKEYTYPE'
395
+ return false
396
+ }
397
+ return true
398
+ }
399
+
400
+ /**
401
+ *
402
+ * Check the buffer is minimally encoded (see https://github.com/bitcoincashorg/spec/blob/master/may-2018-reenabled-opcodes.md#op_bin2num)
403
+ *
404
+ *
405
+ */
406
+
407
+ Interpreter._isMinimallyEncoded = function (buf, nMaxNumSize) {
408
+ nMaxNumSize = nMaxNumSize || Interpreter.MAXIMUM_ELEMENT_SIZE
409
+ if (buf.length > nMaxNumSize) {
410
+ return false
411
+ }
412
+
413
+ if (buf.length > 0) {
414
+ // Check that the number is encoded with the minimum possible number
415
+ // of bytes.
416
+ //
417
+ // If the most-significant-byte - excluding the sign bit - is zero
418
+ // then we're not minimal. Note how this test also rejects the
419
+ // negative-zero encoding, 0x80.
420
+ if ((buf[buf.length - 1] & 0x7f) === 0) {
421
+ // One exception: if there's more than one byte and the most
422
+ // significant bit of the second-most-significant-byte is set it
423
+ // would conflict with the sign bit. An example of this case is
424
+ // +-255, which encode to 0xff00 and 0xff80 respectively.
425
+ // (big-endian).
426
+ if (buf.length <= 1 || (buf[buf.length - 2] & 0x80) === 0) {
427
+ return false
428
+ }
429
+ }
430
+ }
431
+ return true
432
+ }
433
+
434
+ /**
435
+ *
436
+ * minimally encode the buffer content
437
+ *
438
+ * @param {number} nMaxNumSize (max allowed size)
439
+ */
440
+ Interpreter._minimallyEncode = function (buf) {
441
+ if (buf.length === 0) {
442
+ return buf
443
+ }
444
+
445
+ // If the last byte is not 0x00 or 0x80, we are minimally encoded.
446
+ var last = buf[buf.length - 1]
447
+ if (last & 0x7f) {
448
+ return buf
449
+ }
450
+
451
+ // If the script is one byte long, then we have a zero, which encodes as an
452
+ // empty array.
453
+ if (buf.length === 1) {
454
+ return Buffer.from('')
455
+ }
456
+
457
+ // If the next byte has it sign bit set, then we are minimaly encoded.
458
+ if (buf[buf.length - 2] & 0x80) {
459
+ return buf
460
+ }
461
+
462
+ // We are not minimally encoded, we need to figure out how much to trim.
463
+ for (var i = buf.length - 1; i > 0; i--) {
464
+ // We found a non zero byte, time to encode.
465
+ if (buf[i - 1] !== 0) {
466
+ if (buf[i - 1] & 0x80) {
467
+ // We found a byte with it sign bit set so we need one more
468
+ // byte.
469
+ buf[i++] = last
470
+ } else {
471
+ // the sign bit is clear, we can use it.
472
+ buf[i - 1] |= last
473
+ }
474
+
475
+ return buf.slice(0, i)
476
+ }
477
+ }
478
+
479
+ // If we found the whole thing is zeros, then we have a zero.
480
+ return Buffer.from('')
481
+ }
482
+
483
+ /**
484
+ * Based on bitcoind's EvalScript function, with the inner loop moved to
485
+ * Interpreter.prototype.step()
486
+ * bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
487
+ */
488
+ Interpreter.prototype.evaluate = function () {
489
+ // TODO: script size should be configurable. no magic numbers
490
+ if (this.script.toBuffer().length > 10000) {
491
+ this.errstr = 'SCRIPT_ERR_SCRIPT_SIZE'
492
+ return false
493
+ }
494
+
495
+ try {
496
+ while (this.pc < this.script.chunks.length) {
497
+ let thisStep = { pc: this.pc, opcode: Opcode.fromNumber(this.script.chunks[this.pc].opcodenum) }
498
+ var fSuccess = this.step()
499
+ if (!fSuccess) {
500
+ return false
501
+ }
502
+ this._callbackStep(thisStep)
503
+ }
504
+
505
+ // Size limits
506
+ if (this.stack.length + this.altstack.length > 1000) {
507
+ this.errstr = 'SCRIPT_ERR_STACK_SIZE'
508
+ return false
509
+ }
510
+ } catch (e) {
511
+ this.errstr = 'SCRIPT_ERR_UNKNOWN_ERROR: ' + e
512
+ return false
513
+ }
514
+
515
+ if (this.vfExec.length > 0) {
516
+ this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL'
517
+ return false
518
+ }
519
+
520
+ return true
521
+ }
522
+
523
+ Interpreter.prototype._callbackStep = function (thisStep) {
524
+ if (typeof this.stepListener === 'function') {
525
+ try {
526
+ this.stepListener(thisStep, cloneDeep(this.stack, true), cloneDeep(this.altstack, true))
527
+ } catch (err) {
528
+ console.log(`Error in Step callback:${err}`)
529
+ }
530
+ }
531
+ }
532
+
533
+ /**
534
+ * Checks a locktime parameter with the transaction's locktime.
535
+ * There are two times of nLockTime: lock-by-blockheight and lock-by-blocktime,
536
+ * distinguished by whether nLockTime < LOCKTIME_THRESHOLD = 500000000
537
+ *
538
+ * See the corresponding code on bitcoin core:
539
+ * https://github.com/bitcoin/bitcoin/blob/ffd75adce01a78b3461b3ff05bcc2b530a9ce994/src/script/interpreter.cpp#L1129
540
+ *
541
+ * @param {BN} nLockTime the locktime read from the script
542
+ * @return {boolean} true if the transaction's locktime is less than or equal to
543
+ * the transaction's locktime
544
+ */
545
+ Interpreter.prototype.checkLockTime = function (nLockTime) {
546
+ // We want to compare apples to apples, so fail the script
547
+ // unless the type of nLockTime being tested is the same as
548
+ // the nLockTime in the transaction.
549
+ if (!(
550
+ (this.tx.nLockTime < Interpreter.LOCKTIME_THRESHOLD && nLockTime.lt(Interpreter.LOCKTIME_THRESHOLD_BN)) ||
551
+ (this.tx.nLockTime >= Interpreter.LOCKTIME_THRESHOLD && nLockTime.gte(Interpreter.LOCKTIME_THRESHOLD_BN))
552
+ )) {
553
+ return false
554
+ }
555
+
556
+ // Now that we know we're comparing apples-to-apples, the
557
+ // comparison is a simple numeric one.
558
+ if (nLockTime.gt(new BN(this.tx.nLockTime))) {
559
+ return false
560
+ }
561
+
562
+ // Finally the nLockTime feature can be disabled and thus
563
+ // CHECKLOCKTIMEVERIFY bypassed if every txin has been
564
+ // finalized by setting nSequence to maxint. The
565
+ // transaction would be allowed into the blockchain, making
566
+ // the opcode ineffective.
567
+ //
568
+ // Testing if this vin is not final is sufficient to
569
+ // prevent this condition. Alternatively we could test all
570
+ // inputs, but testing just this input minimizes the data
571
+ // required to prove correct CHECKLOCKTIMEVERIFY execution.
572
+ if (this.tx.inputs[this.nin].isFinal()) {
573
+ return false
574
+ }
575
+
576
+ return true
577
+ }
578
+
579
+ /**
580
+ * Checks a sequence parameter with the transaction's sequence.
581
+ * @param {BN} nSequence the sequence read from the script
582
+ * @return {boolean} true if the transaction's sequence is less than or equal to
583
+ * the transaction's sequence
584
+ */
585
+ Interpreter.prototype.checkSequence = function (nSequence) {
586
+ // Relative lock times are supported by comparing the passed in operand to
587
+ // the sequence number of the input.
588
+ var txToSequence = this.tx.inputs[this.nin].sequenceNumber
589
+
590
+ // Fail if the transaction's version number is not set high enough to
591
+ // trigger BIP 68 rules.
592
+ if (this.tx.version < 2) {
593
+ return false
594
+ }
595
+
596
+ // Sequence numbers with their most significant bit set are not consensus
597
+ // constrained. Testing that the transaction's sequence number do not have
598
+ // this bit set prevents using this property to get around a
599
+ // CHECKSEQUENCEVERIFY check.
600
+ if (txToSequence & Interpreter.SEQUENCE_LOCKTIME_DISABLE_FLAG) {
601
+ return false
602
+ }
603
+
604
+ // Mask off any bits that do not have consensus-enforced meaning before
605
+ // doing the integer comparisons
606
+ var nLockTimeMask =
607
+ Interpreter.SEQUENCE_LOCKTIME_TYPE_FLAG | Interpreter.SEQUENCE_LOCKTIME_MASK
608
+ var txToSequenceMasked = new BN(txToSequence & nLockTimeMask)
609
+ var nSequenceMasked = nSequence.and(nLockTimeMask)
610
+
611
+ // There are two kinds of nSequence: lock-by-blockheight and
612
+ // lock-by-blocktime, distinguished by whether nSequenceMasked <
613
+ // CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG.
614
+ //
615
+ // We want to compare apples to apples, so fail the script unless the type
616
+ // of nSequenceMasked being tested is the same as the nSequenceMasked in the
617
+ // transaction.
618
+ var SEQUENCE_LOCKTIME_TYPE_FLAG_BN = new BN(Interpreter.SEQUENCE_LOCKTIME_TYPE_FLAG)
619
+
620
+ if (!((txToSequenceMasked.lt(SEQUENCE_LOCKTIME_TYPE_FLAG_BN) &&
621
+ nSequenceMasked.lt(SEQUENCE_LOCKTIME_TYPE_FLAG_BN)) ||
622
+ (txToSequenceMasked.gte(SEQUENCE_LOCKTIME_TYPE_FLAG_BN) &&
623
+ nSequenceMasked.gte(SEQUENCE_LOCKTIME_TYPE_FLAG_BN)))) {
624
+ return false
625
+ }
626
+
627
+ // Now that we know we're comparing apples-to-apples, the comparison is a
628
+ // simple numeric one.
629
+ if (nSequenceMasked.gt(txToSequenceMasked)) {
630
+ return false
631
+ }
632
+ return true
633
+ }
634
+
635
+ function padBufferToSize (buf, len) {
636
+ let b = buf
637
+ while (b.length < len) {
638
+ b = Buffer.concat([Buffer.from([0x00]), b])
639
+ }
640
+ return b
641
+ }
642
+
643
+ /**
644
+ * Based on the inner loop of bitcoind's EvalScript function
645
+ * bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
646
+ */
647
+ Interpreter.prototype.step = function () {
648
+ var self = this
649
+
650
+ function stacktop (i) {
651
+ return self.stack[self.stack.length + i]
652
+ }
653
+
654
+ function isOpcodeDisabled (opcode) {
655
+ switch (opcode) {
656
+ case Opcode.OP_2MUL:
657
+ case Opcode.OP_2DIV:
658
+
659
+ // Disabled opcodes.
660
+ return true
661
+
662
+ case Opcode.OP_INVERT:
663
+ case Opcode.OP_MUL:
664
+ case Opcode.OP_LSHIFT:
665
+ case Opcode.OP_RSHIFT:
666
+ // Opcodes that have been reenabled.
667
+ if ((self.flags & Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES) === 0) {
668
+ return true
669
+ }
670
+ break
671
+ case Opcode.OP_DIV:
672
+ case Opcode.OP_MOD:
673
+ case Opcode.OP_SPLIT:
674
+ case Opcode.OP_CAT:
675
+ case Opcode.OP_AND:
676
+ case Opcode.OP_OR:
677
+ case Opcode.OP_XOR:
678
+ case Opcode.OP_BIN2NUM:
679
+ case Opcode.OP_NUM2BIN:
680
+ // Opcodes that have been reenabled.
681
+ if ((self.flags & Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES) === 0) {
682
+ return true
683
+ }
684
+ break
685
+ default:
686
+ break
687
+ }
688
+
689
+ return false
690
+ }
691
+
692
+ var fRequireMinimal = (this.flags & Interpreter.SCRIPT_VERIFY_MINIMALDATA) !== 0
693
+
694
+ // bool fExec = !count(vfExec.begin(), vfExec.end(), false);
695
+ var fExec = (this.vfExec.indexOf(false) === -1)
696
+ var buf, buf1, buf2, spliced, n, x1, x2, bn, bn1, bn2, bufSig, bufPubkey, subscript
697
+ var sig, pubkey
698
+ var fValue, fSuccess
699
+
700
+ // Read instruction
701
+ var chunk = this.script.chunks[this.pc]
702
+ this.pc++
703
+ var opcodenum = chunk.opcodenum
704
+ if (_.isUndefined(opcodenum)) {
705
+ this.errstr = 'SCRIPT_ERR_UNDEFINED_OPCODE'
706
+ return false
707
+ }
708
+ if (chunk.buf && chunk.buf.length > Interpreter.MAX_SCRIPT_ELEMENT_SIZE) {
709
+ this.errstr = 'SCRIPT_ERR_PUSH_SIZE'
710
+ return false
711
+ }
712
+
713
+ // Note how Opcode.OP_RESERVED does not count towards the opcode limit.
714
+ if (opcodenum > Opcode.OP_16 && ++(this.nOpCount) > 201) {
715
+ this.errstr = 'SCRIPT_ERR_OP_COUNT'
716
+ return false
717
+ }
718
+
719
+ if (isOpcodeDisabled(opcodenum)) {
720
+ this.errstr = 'SCRIPT_ERR_DISABLED_OPCODE'
721
+ return false
722
+ }
723
+
724
+ if (fExec && opcodenum >= 0 && opcodenum <= Opcode.OP_PUSHDATA4) {
725
+ if (fRequireMinimal && !this.script.checkMinimalPush(this.pc - 1)) {
726
+ this.errstr = 'SCRIPT_ERR_MINIMALDATA'
727
+ return false
728
+ }
729
+ if (!chunk.buf) {
730
+ this.stack.push(Interpreter.false)
731
+ } else if (chunk.len !== chunk.buf.length) {
732
+ throw new Error(`Length of push value not equal to length of data (${chunk.len},${chunk.buf.length})`)
733
+ } else {
734
+ this.stack.push(chunk.buf)
735
+ }
736
+ } else if (fExec || (Opcode.OP_IF <= opcodenum && opcodenum <= Opcode.OP_ENDIF)) {
737
+ switch (opcodenum) {
738
+ // Push value
739
+ case Opcode.OP_1NEGATE:
740
+ case Opcode.OP_1:
741
+ case Opcode.OP_2:
742
+ case Opcode.OP_3:
743
+ case Opcode.OP_4:
744
+ case Opcode.OP_5:
745
+ case Opcode.OP_6:
746
+ case Opcode.OP_7:
747
+ case Opcode.OP_8:
748
+ case Opcode.OP_9:
749
+ case Opcode.OP_10:
750
+ case Opcode.OP_11:
751
+ case Opcode.OP_12:
752
+ case Opcode.OP_13:
753
+ case Opcode.OP_14:
754
+ case Opcode.OP_15:
755
+ case Opcode.OP_16:
756
+ // ( -- value)
757
+ // ScriptNum bn((int)opcode - (int)(Opcode.OP_1 - 1));
758
+ n = opcodenum - (Opcode.OP_1 - 1)
759
+ buf = new BN(n).toScriptNumBuffer()
760
+ this.stack.push(buf)
761
+ // The result of these opcodes should always be the minimal way to push the data
762
+ // they push, so no need for a CheckMinimalPush here.
763
+ break
764
+
765
+ //
766
+ // Control
767
+ //
768
+ case Opcode.OP_NOP:
769
+ break
770
+
771
+ case Opcode.OP_NOP2:
772
+ case Opcode.OP_CHECKLOCKTIMEVERIFY:
773
+
774
+ if (!(this.flags & Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) {
775
+ // not enabled; treat as a NOP2
776
+ if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
777
+ this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
778
+ return false
779
+ }
780
+ break
781
+ }
782
+
783
+ if (this.stack.length < 1) {
784
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
785
+ return false
786
+ }
787
+
788
+ // Note that elsewhere numeric opcodes are limited to
789
+ // operands in the range -2**31+1 to 2**31-1, however it is
790
+ // legal for opcodes to produce results exceeding that
791
+ // range. This limitation is implemented by CScriptNum's
792
+ // default 4-byte limit.
793
+ //
794
+ // If we kept to that limit we'd have a year 2038 problem,
795
+ // even though the nLockTime field in transactions
796
+ // themselves is uint32 which only becomes meaningless
797
+ // after the year 2106.
798
+ //
799
+ // Thus as a special case we tell CScriptNum to accept up
800
+ // to 5-byte bignums, which are good until 2**39-1, well
801
+ // beyond the 2**32-1 limit of the nLockTime field itself.
802
+ var nLockTime = BN.fromScriptNumBuffer(this.stack[this.stack.length - 1], fRequireMinimal, 5)
803
+
804
+ // In the rare event that the argument may be < 0 due to
805
+ // some arithmetic being done first, you can always use
806
+ // 0 MAX CHECKLOCKTIMEVERIFY.
807
+ if (nLockTime.lt(new BN(0))) {
808
+ this.errstr = 'SCRIPT_ERR_NEGATIVE_LOCKTIME'
809
+ return false
810
+ }
811
+
812
+ // Actually compare the specified lock time with the transaction.
813
+ if (!this.checkLockTime(nLockTime)) {
814
+ this.errstr = 'SCRIPT_ERR_UNSATISFIED_LOCKTIME'
815
+ return false
816
+ }
817
+ break
818
+
819
+ case Opcode.OP_NOP3:
820
+ case Opcode.OP_CHECKSEQUENCEVERIFY:
821
+
822
+ if (!(this.flags & Interpreter.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) {
823
+ // not enabled; treat as a NOP3
824
+ if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
825
+ this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
826
+ return false
827
+ }
828
+ break
829
+ }
830
+
831
+ if (this.stack.length < 1) {
832
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
833
+ return false
834
+ }
835
+
836
+ // nSequence, like nLockTime, is a 32-bit unsigned
837
+ // integer field. See the comment in CHECKLOCKTIMEVERIFY
838
+ // regarding 5-byte numeric operands.
839
+
840
+ var nSequence = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal, 5)
841
+
842
+ // In the rare event that the argument may be < 0 due to
843
+ // some arithmetic being done first, you can always use
844
+ // 0 MAX CHECKSEQUENCEVERIFY.
845
+ if (nSequence.lt(new BN(0))) {
846
+ this.errstr = 'SCRIPT_ERR_NEGATIVE_LOCKTIME'
847
+ return false
848
+ }
849
+
850
+ // To provide for future soft-fork extensibility, if the
851
+ // operand has the disabled lock-time flag set,
852
+ // CHECKSEQUENCEVERIFY behaves as a NOP.
853
+ if ((nSequence &
854
+ Interpreter.SEQUENCE_LOCKTIME_DISABLE_FLAG) !== 0) {
855
+ break
856
+ }
857
+
858
+ // Actually compare the specified lock time with the transaction.
859
+ if (!this.checkSequence(nSequence)) {
860
+ this.errstr = 'SCRIPT_ERR_UNSATISFIED_LOCKTIME'
861
+ return false
862
+ }
863
+ break
864
+
865
+ case Opcode.OP_NOP1:
866
+ case Opcode.OP_NOP4:
867
+ case Opcode.OP_NOP5:
868
+ case Opcode.OP_NOP6:
869
+ case Opcode.OP_NOP7:
870
+ case Opcode.OP_NOP8:
871
+ case Opcode.OP_NOP9:
872
+ case Opcode.OP_NOP10:
873
+ if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
874
+ this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'
875
+ return false
876
+ }
877
+ break
878
+
879
+ case Opcode.OP_IF:
880
+ case Opcode.OP_NOTIF:
881
+ // <expression> if [statements] [else [statements]] endif
882
+ // bool fValue = false;
883
+ fValue = false
884
+ if (fExec) {
885
+ if (this.stack.length < 1) {
886
+ this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL'
887
+ return false
888
+ }
889
+ buf = stacktop(-1)
890
+
891
+ if (this.flags & Interpreter.SCRIPT_VERIFY_MINIMALIF) {
892
+ if (buf.length > 1) {
893
+ this.errstr = 'SCRIPT_ERR_MINIMALIF'
894
+ return false
895
+ }
896
+ if (buf.length === 1 && buf[0] !== 1) {
897
+ this.errstr = 'SCRIPT_ERR_MINIMALIF'
898
+ return false
899
+ }
900
+ }
901
+ fValue = Interpreter.castToBool(buf)
902
+ if (opcodenum === Opcode.OP_NOTIF) {
903
+ fValue = !fValue
904
+ }
905
+ this.stack.pop()
906
+ }
907
+ this.vfExec.push(fValue)
908
+ break
909
+
910
+ case Opcode.OP_ELSE:
911
+ if (this.vfExec.length === 0) {
912
+ this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL'
913
+ return false
914
+ }
915
+ this.vfExec[this.vfExec.length - 1] = !this.vfExec[this.vfExec.length - 1]
916
+ break
917
+
918
+ case Opcode.OP_ENDIF:
919
+ if (this.vfExec.length === 0) {
920
+ this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL'
921
+ return false
922
+ }
923
+ this.vfExec.pop()
924
+ break
925
+
926
+ case Opcode.OP_VERIFY:
927
+ // (true -- ) or
928
+ // (false -- false) and return
929
+ if (this.stack.length < 1) {
930
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
931
+ return false
932
+ }
933
+ buf = stacktop(-1)
934
+ fValue = Interpreter.castToBool(buf)
935
+ if (fValue) {
936
+ this.stack.pop()
937
+ } else {
938
+ this.errstr = 'SCRIPT_ERR_VERIFY'
939
+ return false
940
+ }
941
+ break
942
+
943
+ case Opcode.OP_RETURN:
944
+ this.errstr = 'SCRIPT_ERR_OP_RETURN'
945
+ return false
946
+ // break // unreachable
947
+
948
+ //
949
+ // Stack ops
950
+ //
951
+ case Opcode.OP_TOALTSTACK:
952
+ if (this.stack.length < 1) {
953
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
954
+ return false
955
+ }
956
+ this.altstack.push(this.stack.pop())
957
+ break
958
+
959
+ case Opcode.OP_FROMALTSTACK:
960
+ if (this.altstack.length < 1) {
961
+ this.errstr = 'SCRIPT_ERR_INVALID_ALTSTACK_OPERATION'
962
+ return false
963
+ }
964
+ this.stack.push(this.altstack.pop())
965
+ break
966
+
967
+ case Opcode.OP_2DROP:
968
+ // (x1 x2 -- )
969
+ if (this.stack.length < 2) {
970
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
971
+ return false
972
+ }
973
+ this.stack.pop()
974
+ this.stack.pop()
975
+ break
976
+
977
+ case Opcode.OP_2DUP:
978
+ // (x1 x2 -- x1 x2 x1 x2)
979
+ if (this.stack.length < 2) {
980
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
981
+ return false
982
+ }
983
+ buf1 = stacktop(-2)
984
+ buf2 = stacktop(-1)
985
+ this.stack.push(Buffer.from(buf1))
986
+ this.stack.push(Buffer.from(buf2))
987
+ break
988
+
989
+ case Opcode.OP_3DUP:
990
+ // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3)
991
+ if (this.stack.length < 3) {
992
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
993
+ return false
994
+ }
995
+ buf1 = stacktop(-3)
996
+ buf2 = stacktop(-2)
997
+ var buf3 = stacktop(-1)
998
+ this.stack.push(Buffer.from(buf1))
999
+ this.stack.push(Buffer.from(buf2))
1000
+ this.stack.push(Buffer.from(buf3))
1001
+ break
1002
+
1003
+ case Opcode.OP_2OVER:
1004
+ // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2)
1005
+ if (this.stack.length < 4) {
1006
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1007
+ return false
1008
+ }
1009
+ buf1 = stacktop(-4)
1010
+ buf2 = stacktop(-3)
1011
+ this.stack.push(Buffer.from(buf1))
1012
+ this.stack.push(Buffer.from(buf2))
1013
+ break
1014
+
1015
+ case Opcode.OP_2ROT:
1016
+ // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
1017
+ if (this.stack.length < 6) {
1018
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1019
+ return false
1020
+ }
1021
+ spliced = this.stack.splice(this.stack.length - 6, 2)
1022
+ this.stack.push(spliced[0])
1023
+ this.stack.push(spliced[1])
1024
+ break
1025
+
1026
+ case Opcode.OP_2SWAP:
1027
+ // (x1 x2 x3 x4 -- x3 x4 x1 x2)
1028
+ if (this.stack.length < 4) {
1029
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1030
+ return false
1031
+ }
1032
+ spliced = this.stack.splice(this.stack.length - 4, 2)
1033
+ this.stack.push(spliced[0])
1034
+ this.stack.push(spliced[1])
1035
+ break
1036
+
1037
+ case Opcode.OP_IFDUP:
1038
+ // (x - 0 | x x)
1039
+ if (this.stack.length < 1) {
1040
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1041
+ return false
1042
+ }
1043
+ buf = stacktop(-1)
1044
+ fValue = Interpreter.castToBool(buf)
1045
+ if (fValue) {
1046
+ this.stack.push(Buffer.from(buf))
1047
+ }
1048
+ break
1049
+
1050
+ case Opcode.OP_DEPTH:
1051
+ // -- stacksize
1052
+ buf = new BN(this.stack.length).toScriptNumBuffer()
1053
+ this.stack.push(buf)
1054
+ break
1055
+
1056
+ case Opcode.OP_DROP:
1057
+ // (x -- )
1058
+ if (this.stack.length < 1) {
1059
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1060
+ return false
1061
+ }
1062
+ this.stack.pop()
1063
+ break
1064
+
1065
+ case Opcode.OP_DUP:
1066
+ // (x -- x x)
1067
+ if (this.stack.length < 1) {
1068
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1069
+ return false
1070
+ }
1071
+ this.stack.push(Buffer.from(stacktop(-1)))
1072
+ break
1073
+
1074
+ case Opcode.OP_NIP:
1075
+ // (x1 x2 -- x2)
1076
+ if (this.stack.length < 2) {
1077
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1078
+ return false
1079
+ }
1080
+ this.stack.splice(this.stack.length - 2, 1)
1081
+ break
1082
+
1083
+ case Opcode.OP_OVER:
1084
+ // (x1 x2 -- x1 x2 x1)
1085
+ if (this.stack.length < 2) {
1086
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1087
+ return false
1088
+ }
1089
+ this.stack.push(Buffer.from(stacktop(-2)))
1090
+ break
1091
+
1092
+ case Opcode.OP_PICK:
1093
+ case Opcode.OP_ROLL:
1094
+ // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn)
1095
+ // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
1096
+ if (this.stack.length < 2) {
1097
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1098
+ return false
1099
+ }
1100
+ buf = stacktop(-1)
1101
+ bn = BN.fromScriptNumBuffer(buf, fRequireMinimal)
1102
+ n = bn.toNumber()
1103
+ this.stack.pop()
1104
+ if (n < 0 || n >= this.stack.length) {
1105
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1106
+ return false
1107
+ }
1108
+ buf = stacktop(-n - 1)
1109
+ if (opcodenum === Opcode.OP_ROLL) {
1110
+ this.stack.splice(this.stack.length - n - 1, 1)
1111
+ }
1112
+ this.stack.push(Buffer.from(buf))
1113
+ break
1114
+
1115
+ case Opcode.OP_ROT:
1116
+ // (x1 x2 x3 -- x2 x3 x1)
1117
+ // x2 x1 x3 after first swap
1118
+ // x2 x3 x1 after second swap
1119
+ if (this.stack.length < 3) {
1120
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1121
+ return false
1122
+ }
1123
+ x1 = stacktop(-3)
1124
+ x2 = stacktop(-2)
1125
+ var x3 = stacktop(-1)
1126
+ this.stack[this.stack.length - 3] = x2
1127
+ this.stack[this.stack.length - 2] = x3
1128
+ this.stack[this.stack.length - 1] = x1
1129
+ break
1130
+
1131
+ case Opcode.OP_SWAP:
1132
+ // (x1 x2 -- x2 x1)
1133
+ if (this.stack.length < 2) {
1134
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1135
+ return false
1136
+ }
1137
+ x1 = stacktop(-2)
1138
+ x2 = stacktop(-1)
1139
+ this.stack[this.stack.length - 2] = x2
1140
+ this.stack[this.stack.length - 1] = x1
1141
+ break
1142
+
1143
+ case Opcode.OP_TUCK:
1144
+ // (x1 x2 -- x2 x1 x2)
1145
+ if (this.stack.length < 2) {
1146
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1147
+ return false
1148
+ }
1149
+ this.stack.splice(this.stack.length - 2, 0, Buffer.from(stacktop(-1)))
1150
+ break
1151
+
1152
+ case Opcode.OP_SIZE:
1153
+ // (in -- in size)
1154
+ if (this.stack.length < 1) {
1155
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1156
+ return false
1157
+ }
1158
+ bn = new BN(stacktop(-1).length)
1159
+ this.stack.push(bn.toScriptNumBuffer())
1160
+ break
1161
+
1162
+ //
1163
+ // Bitwise logic
1164
+ //
1165
+ case Opcode.OP_AND:
1166
+ case Opcode.OP_OR:
1167
+ case Opcode.OP_XOR:
1168
+ // (x1 x2 - out)
1169
+ if (this.stack.length < 2) {
1170
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1171
+ return false
1172
+ }
1173
+ buf1 = stacktop(-2)
1174
+ buf2 = stacktop(-1)
1175
+
1176
+ // Inputs must be the same size
1177
+ if (buf1.length !== buf2.length) {
1178
+ this.errstr = 'SCRIPT_ERR_INVALID_OPERAND_SIZE'
1179
+ return false
1180
+ }
1181
+
1182
+ // To avoid allocating, we modify vch1 in place.
1183
+ switch (opcodenum) {
1184
+ case Opcode.OP_AND:
1185
+ for (let i = 0; i < buf1.length; i++) {
1186
+ buf1[i] &= buf2[i]
1187
+ }
1188
+ break
1189
+ case Opcode.OP_OR:
1190
+ for (let i = 0; i < buf1.length; i++) {
1191
+ buf1[i] |= buf2[i]
1192
+ }
1193
+ break
1194
+ case Opcode.OP_XOR:
1195
+ for (let i = 0; i < buf1.length; i++) {
1196
+ buf1[i] ^= buf2[i]
1197
+ }
1198
+ break
1199
+ default:
1200
+ break
1201
+ }
1202
+
1203
+ // And pop vch2.
1204
+ this.stack.pop()
1205
+ break
1206
+
1207
+ case Opcode.OP_INVERT:
1208
+ // (x -- out)
1209
+ if (this.stack.length < 1) {
1210
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1211
+ }
1212
+ buf = stacktop(-1)
1213
+ for (let i = 0; i < buf.length; i++) {
1214
+ buf[i] = ~buf[i]
1215
+ }
1216
+ break
1217
+
1218
+ case Opcode.OP_LSHIFT:
1219
+ case Opcode.OP_RSHIFT:
1220
+ // (x n -- out)
1221
+ if (this.stack.length < 2) {
1222
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1223
+ return false
1224
+ }
1225
+ buf1 = stacktop(-2)
1226
+ if (buf1.length === 0) {
1227
+ this.stack.pop()
1228
+ } else {
1229
+ bn1 = new BN(buf1)
1230
+ bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal)
1231
+ n = bn2.toNumber()
1232
+ if (n < 0) {
1233
+ this.errstr = 'SCRIPT_ERR_INVALID_NUMBER_RANGE'
1234
+ return false
1235
+ }
1236
+ this.stack.pop()
1237
+ this.stack.pop()
1238
+ let shifted
1239
+ if (opcodenum === Opcode.OP_LSHIFT) {
1240
+ shifted = bn1.ushln(n)
1241
+ }
1242
+ if (opcodenum === Opcode.OP_RSHIFT) {
1243
+ shifted = bn1.ushrn(n)
1244
+ }
1245
+ // bitcoin client implementation of l/rshift is unconventional, therefore this implementation is a bit unconventional
1246
+ // bn library has shift functions however it expands the carried bits into a new byte
1247
+ // in contrast to the bitcoin client implementation which drops off the carried bits
1248
+ // in other words, if operand was 1 byte then we put 1 byte back on the stack instead of expanding to more shifted bytes
1249
+ let bufShifted = padBufferToSize(Buffer.from(shifted.toArray().slice(buf1.length * -1)), buf1.length)
1250
+ this.stack.push(bufShifted)
1251
+ }
1252
+ break
1253
+
1254
+ case Opcode.OP_EQUAL:
1255
+ case Opcode.OP_EQUALVERIFY:
1256
+ // case Opcode.OP_NOTEQUAL: // use Opcode.OP_NUMNOTEQUAL
1257
+ // (x1 x2 - bool)
1258
+ if (this.stack.length < 2) {
1259
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1260
+ return false
1261
+ }
1262
+ buf1 = stacktop(-2)
1263
+ buf2 = stacktop(-1)
1264
+ var fEqual = buf1.toString('hex') === buf2.toString('hex')
1265
+ this.stack.pop()
1266
+ this.stack.pop()
1267
+ this.stack.push(fEqual ? Interpreter.true : Interpreter.false)
1268
+ if (opcodenum === Opcode.OP_EQUALVERIFY) {
1269
+ if (fEqual) {
1270
+ this.stack.pop()
1271
+ } else {
1272
+ this.errstr = 'SCRIPT_ERR_EQUALVERIFY'
1273
+ return false
1274
+ }
1275
+ }
1276
+ break
1277
+
1278
+ //
1279
+ // Numeric
1280
+ //
1281
+ case Opcode.OP_1ADD:
1282
+ case Opcode.OP_1SUB:
1283
+ case Opcode.OP_NEGATE:
1284
+ case Opcode.OP_ABS:
1285
+ case Opcode.OP_NOT:
1286
+ case Opcode.OP_0NOTEQUAL:
1287
+ // (in -- out)
1288
+ if (this.stack.length < 1) {
1289
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1290
+ return false
1291
+ }
1292
+ buf = stacktop(-1)
1293
+ bn = BN.fromScriptNumBuffer(buf, fRequireMinimal)
1294
+ switch (opcodenum) {
1295
+ case Opcode.OP_1ADD:
1296
+ bn = bn.add(BN.One)
1297
+ break
1298
+ case Opcode.OP_1SUB:
1299
+ bn = bn.sub(BN.One)
1300
+ break
1301
+ case Opcode.OP_NEGATE:
1302
+ bn = bn.neg()
1303
+ break
1304
+ case Opcode.OP_ABS:
1305
+ if (bn.cmp(BN.Zero) < 0) {
1306
+ bn = bn.neg()
1307
+ }
1308
+ break
1309
+ case Opcode.OP_NOT:
1310
+ bn = new BN((bn.cmp(BN.Zero) === 0) + 0)
1311
+ break
1312
+ case Opcode.OP_0NOTEQUAL:
1313
+ bn = new BN((bn.cmp(BN.Zero) !== 0) + 0)
1314
+ break
1315
+ // default: assert(!'invalid opcode'); break; // TODO: does this ever occur?
1316
+ }
1317
+ this.stack.pop()
1318
+ this.stack.push(bn.toScriptNumBuffer())
1319
+ break
1320
+
1321
+ case Opcode.OP_ADD:
1322
+ case Opcode.OP_SUB:
1323
+ case Opcode.OP_MUL:
1324
+ case Opcode.OP_MOD:
1325
+ case Opcode.OP_DIV:
1326
+ case Opcode.OP_BOOLAND:
1327
+ case Opcode.OP_BOOLOR:
1328
+ case Opcode.OP_NUMEQUAL:
1329
+ case Opcode.OP_NUMEQUALVERIFY:
1330
+ case Opcode.OP_NUMNOTEQUAL:
1331
+ case Opcode.OP_LESSTHAN:
1332
+ case Opcode.OP_GREATERTHAN:
1333
+ case Opcode.OP_LESSTHANOREQUAL:
1334
+ case Opcode.OP_GREATERTHANOREQUAL:
1335
+ case Opcode.OP_MIN:
1336
+ case Opcode.OP_MAX:
1337
+ // (x1 x2 -- out)
1338
+ if (this.stack.length < 2) {
1339
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1340
+ return false
1341
+ }
1342
+ bn1 = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal)
1343
+ bn2 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal)
1344
+ bn = new BN(0)
1345
+
1346
+ switch (opcodenum) {
1347
+ case Opcode.OP_ADD:
1348
+ bn = bn1.add(bn2)
1349
+ break
1350
+
1351
+ case Opcode.OP_SUB:
1352
+ bn = bn1.sub(bn2)
1353
+ break
1354
+
1355
+ case Opcode.OP_MUL:
1356
+ bn = bn1.mul(bn2)
1357
+ break
1358
+
1359
+ case Opcode.OP_DIV:
1360
+ // denominator must not be 0
1361
+ if (bn2 === 0) {
1362
+ this.errstr = 'SCRIPT_ERR_DIV_BY_ZERO'
1363
+ return false
1364
+ }
1365
+ bn = bn1.div(bn2)
1366
+ break
1367
+
1368
+ case Opcode.OP_MOD:
1369
+ // divisor must not be 0
1370
+ if (bn2 === 0) {
1371
+ this.errstr = 'SCRIPT_ERR_DIV_BY_ZERO'
1372
+ return false
1373
+ }
1374
+ bn = bn1.mod(bn2)
1375
+ break
1376
+
1377
+ case Opcode.OP_BOOLAND:
1378
+ bn = new BN(((bn1.cmp(BN.Zero) !== 0) && (bn2.cmp(BN.Zero) !== 0)) + 0)
1379
+ break
1380
+ // case Opcode.OP_BOOLOR: bn = (bn1 !== bnZero || bn2 !== bnZero); break;
1381
+ case Opcode.OP_BOOLOR:
1382
+ bn = new BN(((bn1.cmp(BN.Zero) !== 0) || (bn2.cmp(BN.Zero) !== 0)) + 0)
1383
+ break
1384
+ // case Opcode.OP_NUMEQUAL: bn = (bn1 === bn2); break;
1385
+ case Opcode.OP_NUMEQUAL:
1386
+ bn = new BN((bn1.cmp(bn2) === 0) + 0)
1387
+ break
1388
+ // case Opcode.OP_NUMEQUALVERIFY: bn = (bn1 === bn2); break;
1389
+ case Opcode.OP_NUMEQUALVERIFY:
1390
+ bn = new BN((bn1.cmp(bn2) === 0) + 0)
1391
+ break
1392
+ // case Opcode.OP_NUMNOTEQUAL: bn = (bn1 !== bn2); break;
1393
+ case Opcode.OP_NUMNOTEQUAL:
1394
+ bn = new BN((bn1.cmp(bn2) !== 0) + 0)
1395
+ break
1396
+ // case Opcode.OP_LESSTHAN: bn = (bn1 < bn2); break;
1397
+ case Opcode.OP_LESSTHAN:
1398
+ bn = new BN((bn1.cmp(bn2) < 0) + 0)
1399
+ break
1400
+ // case Opcode.OP_GREATERTHAN: bn = (bn1 > bn2); break;
1401
+ case Opcode.OP_GREATERTHAN:
1402
+ bn = new BN((bn1.cmp(bn2) > 0) + 0)
1403
+ break
1404
+ // case Opcode.OP_LESSTHANOREQUAL: bn = (bn1 <= bn2); break;
1405
+ case Opcode.OP_LESSTHANOREQUAL:
1406
+ bn = new BN((bn1.cmp(bn2) <= 0) + 0)
1407
+ break
1408
+ // case Opcode.OP_GREATERTHANOREQUAL: bn = (bn1 >= bn2); break;
1409
+ case Opcode.OP_GREATERTHANOREQUAL:
1410
+ bn = new BN((bn1.cmp(bn2) >= 0) + 0)
1411
+ break
1412
+ case Opcode.OP_MIN:
1413
+ bn = (bn1.cmp(bn2) < 0 ? bn1 : bn2)
1414
+ break
1415
+ case Opcode.OP_MAX:
1416
+ bn = (bn1.cmp(bn2) > 0 ? bn1 : bn2)
1417
+ break
1418
+ // default: assert(!'invalid opcode'); break; //TODO: does this ever occur?
1419
+ }
1420
+ this.stack.pop()
1421
+ this.stack.pop()
1422
+ this.stack.push(bn.toScriptNumBuffer())
1423
+
1424
+ if (opcodenum === Opcode.OP_NUMEQUALVERIFY) {
1425
+ // if (CastToBool(stacktop(-1)))
1426
+ if (Interpreter.castToBool(stacktop(-1))) {
1427
+ this.stack.pop()
1428
+ } else {
1429
+ this.errstr = 'SCRIPT_ERR_NUMEQUALVERIFY'
1430
+ return false
1431
+ }
1432
+ }
1433
+ break
1434
+
1435
+ case Opcode.OP_WITHIN:
1436
+ // (x min max -- out)
1437
+ if (this.stack.length < 3) {
1438
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1439
+ return false
1440
+ }
1441
+ bn1 = BN.fromScriptNumBuffer(stacktop(-3), fRequireMinimal)
1442
+ bn2 = BN.fromScriptNumBuffer(stacktop(-2), fRequireMinimal)
1443
+ var bn3 = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal)
1444
+ // bool fValue = (bn2 <= bn1 && bn1 < bn3);
1445
+ fValue = (bn2.cmp(bn1) <= 0) && (bn1.cmp(bn3) < 0)
1446
+ this.stack.pop()
1447
+ this.stack.pop()
1448
+ this.stack.pop()
1449
+ this.stack.push(fValue ? Interpreter.true : Interpreter.false)
1450
+ break
1451
+
1452
+ //
1453
+ // Crypto
1454
+ //
1455
+ case Opcode.OP_RIPEMD160:
1456
+ case Opcode.OP_SHA1:
1457
+ case Opcode.OP_SHA256:
1458
+ case Opcode.OP_HASH160:
1459
+ case Opcode.OP_HASH256:
1460
+ // (in -- hash)
1461
+ if (this.stack.length < 1) {
1462
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1463
+ return false
1464
+ }
1465
+ buf = stacktop(-1)
1466
+ // valtype vchHash((opcode === Opcode.OP_RIPEMD160 ||
1467
+ // opcode === Opcode.OP_SHA1 || opcode === Opcode.OP_HASH160) ? 20 : 32);
1468
+ var bufHash
1469
+ if (opcodenum === Opcode.OP_RIPEMD160) {
1470
+ bufHash = Hash.ripemd160(buf)
1471
+ } else if (opcodenum === Opcode.OP_SHA1) {
1472
+ bufHash = Hash.sha1(buf)
1473
+ } else if (opcodenum === Opcode.OP_SHA256) {
1474
+ bufHash = Hash.sha256(buf)
1475
+ } else if (opcodenum === Opcode.OP_HASH160) {
1476
+ bufHash = Hash.sha256ripemd160(buf)
1477
+ } else if (opcodenum === Opcode.OP_HASH256) {
1478
+ bufHash = Hash.sha256sha256(buf)
1479
+ }
1480
+ this.stack.pop()
1481
+ this.stack.push(bufHash)
1482
+ break
1483
+
1484
+ case Opcode.OP_CODESEPARATOR:
1485
+ // Hash starts after the code separator
1486
+ this.pbegincodehash = this.pc
1487
+ break
1488
+
1489
+ case Opcode.OP_CHECKSIG:
1490
+ case Opcode.OP_CHECKSIGVERIFY:
1491
+ // (sig pubkey -- bool)
1492
+ if (this.stack.length < 2) {
1493
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1494
+ return false
1495
+ }
1496
+
1497
+ bufSig = stacktop(-2)
1498
+ bufPubkey = stacktop(-1)
1499
+
1500
+ if (!this.checkSignatureEncoding(bufSig) || !this.checkPubkeyEncoding(bufPubkey)) {
1501
+ return false
1502
+ }
1503
+
1504
+ // Subset of script starting at the most recent codeseparator
1505
+ // CScript scriptCode(pbegincodehash, pend);
1506
+ subscript = new Script().set({
1507
+ chunks: this.script.chunks.slice(this.pbegincodehash)
1508
+ })
1509
+
1510
+ // Drop the signature, since there's no way for a signature to sign itself
1511
+ var tmpScript = new Script().add(bufSig)
1512
+ subscript.findAndDelete(tmpScript)
1513
+
1514
+ try {
1515
+ sig = Signature.fromTxFormat(bufSig)
1516
+ pubkey = PublicKey.fromBuffer(bufPubkey, false)
1517
+
1518
+ fSuccess = this.tx.verifySignature(sig, pubkey, this.nin, subscript, this.satoshisBN, this.flags)
1519
+ } catch (e) {
1520
+ // invalid sig or pubkey
1521
+ fSuccess = false
1522
+ }
1523
+
1524
+ if (!fSuccess && (this.flags & Interpreter.SCRIPT_VERIFY_NULLFAIL) &&
1525
+ bufSig.length) {
1526
+ this.errstr = 'SCRIPT_ERR_NULLFAIL'
1527
+ return false
1528
+ }
1529
+
1530
+ this.stack.pop()
1531
+ this.stack.pop()
1532
+
1533
+ // stack.push_back(fSuccess ? vchTrue : vchFalse);
1534
+ this.stack.push(fSuccess ? Interpreter.true : Interpreter.false)
1535
+ if (opcodenum === Opcode.OP_CHECKSIGVERIFY) {
1536
+ if (fSuccess) {
1537
+ this.stack.pop()
1538
+ } else {
1539
+ this.errstr = 'SCRIPT_ERR_CHECKSIGVERIFY'
1540
+ return false
1541
+ }
1542
+ }
1543
+ break
1544
+
1545
+ case Opcode.OP_CHECKMULTISIG:
1546
+ case Opcode.OP_CHECKMULTISIGVERIFY:
1547
+ // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool)
1548
+
1549
+ var i = 1
1550
+ if (this.stack.length < i) {
1551
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1552
+ return false
1553
+ }
1554
+
1555
+ var nKeysCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal).toNumber()
1556
+ // TODO: Keys and opcount are parameterized in client. No magic numbers!
1557
+ if (nKeysCount < 0 || nKeysCount > 20) {
1558
+ this.errstr = 'SCRIPT_ERR_PUBKEY_COUNT'
1559
+ return false
1560
+ }
1561
+ this.nOpCount += nKeysCount
1562
+ if (this.nOpCount > 201) {
1563
+ this.errstr = 'SCRIPT_ERR_OP_COUNT'
1564
+ return false
1565
+ }
1566
+ // int ikey = ++i;
1567
+ var ikey = ++i
1568
+ i += nKeysCount
1569
+
1570
+ // ikey2 is the position of last non-signature item in
1571
+ // the stack. Top stack item = 1. With
1572
+ // SCRIPT_VERIFY_NULLFAIL, this is used for cleanup if
1573
+ // operation fails.
1574
+ var ikey2 = nKeysCount + 2
1575
+
1576
+ if (this.stack.length < i) {
1577
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1578
+ return false
1579
+ }
1580
+
1581
+ var nSigsCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal).toNumber()
1582
+ if (nSigsCount < 0 || nSigsCount > nKeysCount) {
1583
+ this.errstr = 'SCRIPT_ERR_SIG_COUNT'
1584
+ return false
1585
+ }
1586
+ // int isig = ++i;
1587
+ var isig = ++i
1588
+ i += nSigsCount
1589
+ if (this.stack.length < i) {
1590
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1591
+ return false
1592
+ }
1593
+
1594
+ // Subset of script starting at the most recent codeseparator
1595
+ subscript = new Script().set({
1596
+ chunks: this.script.chunks.slice(this.pbegincodehash)
1597
+ })
1598
+
1599
+ // Drop the signatures, since there's no way for a signature to sign itself
1600
+ for (var k = 0; k < nSigsCount; k++) {
1601
+ bufSig = stacktop(-isig - k)
1602
+ subscript.findAndDelete(new Script().add(bufSig))
1603
+ }
1604
+
1605
+ fSuccess = true
1606
+ while (fSuccess && nSigsCount > 0) {
1607
+ // valtype& vchSig = stacktop(-isig);
1608
+ bufSig = stacktop(-isig)
1609
+ // valtype& vchPubKey = stacktop(-ikey);
1610
+ bufPubkey = stacktop(-ikey)
1611
+
1612
+ if (!this.checkSignatureEncoding(bufSig) || !this.checkPubkeyEncoding(bufPubkey)) {
1613
+ return false
1614
+ }
1615
+
1616
+ var fOk
1617
+ try {
1618
+ sig = Signature.fromTxFormat(bufSig)
1619
+ pubkey = PublicKey.fromBuffer(bufPubkey, false)
1620
+ fOk = this.tx.verifySignature(sig, pubkey, this.nin, subscript, this.satoshisBN, this.flags)
1621
+ } catch (e) {
1622
+ // invalid sig or pubkey
1623
+ fOk = false
1624
+ }
1625
+
1626
+ if (fOk) {
1627
+ isig++
1628
+ nSigsCount--
1629
+ }
1630
+ ikey++
1631
+ nKeysCount--
1632
+
1633
+ // If there are more signatures left than keys left,
1634
+ // then too many signatures have failed
1635
+ if (nSigsCount > nKeysCount) {
1636
+ fSuccess = false
1637
+ }
1638
+ }
1639
+
1640
+ // Clean up stack of actual arguments
1641
+ while (i-- > 1) {
1642
+ if (!fSuccess && (this.flags & Interpreter.SCRIPT_VERIFY_NULLFAIL) &&
1643
+ !ikey2 && stacktop(-1).length) {
1644
+ this.errstr = 'SCRIPT_ERR_NULLFAIL'
1645
+ return false
1646
+ }
1647
+
1648
+ if (ikey2 > 0) {
1649
+ ikey2--
1650
+ }
1651
+
1652
+ this.stack.pop()
1653
+ }
1654
+
1655
+ // A bug causes CHECKMULTISIG to consume one extra argument
1656
+ // whose contents were not checked in any way.
1657
+ //
1658
+ // Unfortunately this is a potential source of mutability,
1659
+ // so optionally verify it is exactly equal to zero prior
1660
+ // to removing it from the stack.
1661
+ if (this.stack.length < 1) {
1662
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1663
+ return false
1664
+ }
1665
+ if ((this.flags & Interpreter.SCRIPT_VERIFY_NULLDUMMY) && stacktop(-1).length) {
1666
+ this.errstr = 'SCRIPT_ERR_SIG_NULLDUMMY'
1667
+ return false
1668
+ }
1669
+ this.stack.pop()
1670
+
1671
+ this.stack.push(fSuccess ? Interpreter.true : Interpreter.false)
1672
+
1673
+ if (opcodenum === Opcode.OP_CHECKMULTISIGVERIFY) {
1674
+ if (fSuccess) {
1675
+ this.stack.pop()
1676
+ } else {
1677
+ this.errstr = 'SCRIPT_ERR_CHECKMULTISIGVERIFY'
1678
+ return false
1679
+ }
1680
+ }
1681
+ break
1682
+
1683
+ //
1684
+ // Byte string operations
1685
+ //
1686
+ case Opcode.OP_CAT:
1687
+ if (this.stack.length < 2) {
1688
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1689
+ return false
1690
+ }
1691
+
1692
+ buf1 = stacktop(-2)
1693
+ buf2 = stacktop(-1)
1694
+ if (buf1.length + buf2.length > Interpreter.MAX_SCRIPT_ELEMENT_SIZE) {
1695
+ this.errstr = 'SCRIPT_ERR_PUSH_SIZE'
1696
+ return false
1697
+ }
1698
+ this.stack[this.stack.length - 2] = Buffer.concat([buf1, buf2])
1699
+ this.stack.pop()
1700
+ break
1701
+
1702
+ case Opcode.OP_SPLIT:
1703
+ if (this.stack.length < 2) {
1704
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1705
+ return false
1706
+ }
1707
+ buf1 = stacktop(-2)
1708
+
1709
+ // Make sure the split point is apropriate.
1710
+ var position = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal).toNumber()
1711
+ if (position < 0 || position > buf1.length) {
1712
+ this.errstr = 'SCRIPT_ERR_INVALID_SPLIT_RANGE'
1713
+ return false
1714
+ }
1715
+
1716
+ // Prepare the results in their own buffer as `data`
1717
+ // will be invalidated.
1718
+ // Copy buffer data, to slice it before
1719
+ var n1 = Buffer.from(buf1)
1720
+
1721
+ // Replace existing stack values by the new values.
1722
+ this.stack[this.stack.length - 2] = n1.slice(0, position)
1723
+ this.stack[this.stack.length - 1] = n1.slice(position)
1724
+ break
1725
+
1726
+ //
1727
+ // Conversion operations
1728
+ //
1729
+ case Opcode.OP_NUM2BIN:
1730
+ // (in -- out)
1731
+ if (this.stack.length < 2) {
1732
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1733
+ return false
1734
+ }
1735
+
1736
+ var size = BN.fromScriptNumBuffer(stacktop(-1), fRequireMinimal).toNumber()
1737
+ if (size > Interpreter.MAX_SCRIPT_ELEMENT_SIZE) {
1738
+ this.errstr = 'SCRIPT_ERR_PUSH_SIZE'
1739
+ return false
1740
+ }
1741
+
1742
+ this.stack.pop()
1743
+ var rawnum = stacktop(-1)
1744
+
1745
+ // Try to see if we can fit that number in the number of
1746
+ // byte requested.
1747
+ rawnum = Interpreter._minimallyEncode(rawnum)
1748
+
1749
+ if (rawnum.length > size) {
1750
+ // We definitively cannot.
1751
+ this.errstr = 'SCRIPT_ERR_IMPOSSIBLE_ENCODING'
1752
+ return false
1753
+ }
1754
+
1755
+ // We already have an element of the right size, we
1756
+ // don't need to do anything.
1757
+ if (rawnum.length === size) {
1758
+ this.stack[this.stack.length - 1] = rawnum
1759
+ break
1760
+ }
1761
+
1762
+ var signbit = 0x00
1763
+ if (rawnum.length > 0) {
1764
+ signbit = rawnum[rawnum.length - 1] & 0x80
1765
+ rawnum[rawnum.length - 1] &= 0x7f
1766
+ }
1767
+
1768
+ var num = Buffer.alloc(size)
1769
+ rawnum.copy(num, 0)
1770
+
1771
+ var l = rawnum.length - 1
1772
+ while (l++ < size - 2) {
1773
+ num[l] = 0x00
1774
+ }
1775
+
1776
+ num[l] = signbit
1777
+
1778
+ this.stack[this.stack.length - 1] = num
1779
+ break
1780
+
1781
+ case Opcode.OP_BIN2NUM:
1782
+ // (in -- out)
1783
+ if (this.stack.length < 1) {
1784
+ this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
1785
+ return false
1786
+ }
1787
+
1788
+ buf1 = stacktop(-1)
1789
+ buf2 = Interpreter._minimallyEncode(buf1)
1790
+
1791
+ this.stack[this.stack.length - 1] = buf2
1792
+
1793
+ // The resulting number must be a valid number.
1794
+ if (!Interpreter._isMinimallyEncoded(buf2)) {
1795
+ this.errstr = 'SCRIPT_ERR_INVALID_NUMBER_RANGE'
1796
+ return false
1797
+ }
1798
+ break
1799
+
1800
+ default:
1801
+ this.errstr = 'SCRIPT_ERR_BAD_OPCODE'
1802
+ return false
1803
+ }
1804
+ }
1805
+
1806
+ return true
1807
+ }