UNPKG

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