• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

handshake-org / hsd / 3857666049

pending completion
3857666049

push

github

Nodari Chkuaselidze
Merge PR #739 from 'nodech/update-release-process'

7368 of 12653 branches covered (58.23%)

Branch coverage included in aggregate %.

23467 of 32546 relevant lines covered (72.1%)

31556.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.5
/lib/script/script.js
1
/*!
2
 * script.js - script interpreter for hsd
3
 * Copyright (c) 2017-2018, Christopher Jeffrey (MIT License).
4
 * https://github.com/handshake-org/hsd
5
 */
6

7
'use strict';
8

9
const assert = require('bsert');
68✔
10
const bio = require('bufio');
68✔
11
const ripemd160 = require('bcrypto/lib/ripemd160');
68✔
12
const sha1 = require('bcrypto/lib/sha1');
68✔
13
const sha256 = require('bcrypto/lib/sha256');
68✔
14
const hash160 = require('bcrypto/lib/hash160');
68✔
15
const hash256 = require('bcrypto/lib/hash256');
68✔
16
const blake2b = require('bcrypto/lib/blake2b');
68✔
17
const sha3 = require('bcrypto/lib/sha3');
68✔
18
const keccak = require('bcrypto/lib/keccak');
68✔
19
const secp256k1 = require('bcrypto/lib/secp256k1');
68✔
20
const consensus = require('../protocol/consensus');
68✔
21
const Opcode = require('./opcode');
68✔
22
const Stack = require('./stack');
68✔
23
const ScriptError = require('./scripterror');
68✔
24
const ScriptNum = require('./scriptnum');
68✔
25
const common = require('./common');
68✔
26
const opcodes = common.opcodes;
68✔
27
const scriptTypes = common.types;
68✔
28
const {encoding} = bio;
68✔
29

30
/*
31
 * Constants
32
 */
33

34
const EMPTY_BUFFER = Buffer.alloc(0);
68✔
35

36
/**
37
 * Script
38
 * Represents a input or output script.
39
 * @alias module:script.Script
40
 * @property {Array} code - Parsed script code.
41
 * @property {Buffer?} raw - Serialized script.
42
 * @property {Number} length - Number of parsed opcodes.
43
 */
44

45
class Script extends bio.Struct {
46
  /**
47
   * Create a script.
48
   * @constructor
49
   * @param {Buffer|Array|Object} code
50
   */
51

52
  constructor(options) {
53
    super();
127,600✔
54

55
    this.raw = EMPTY_BUFFER;
127,600✔
56
    this.code = [];
127,600✔
57

58
    if (options)
127,600✔
59
      this.fromOptions(options);
39✔
60
  }
61

62
  /**
63
   * Get length.
64
   * @returns {Number}
65
   */
66

67
  get length() {
68
    return this.code.length;
×
69
  }
70

71
  /**
72
   * Set length.
73
   * @param {Number} value
74
   */
75

76
  set length(value) {
77
    this.code.length = value;
×
78
  }
79

80
  /**
81
   * Inject properties from options object.
82
   * @private
83
   * @param {Object} options
84
   */
85

86
  fromOptions(options) {
87
    assert(options, 'Script data is required.');
39✔
88

89
    if (Buffer.isBuffer(options))
39!
90
      return this.decode(options);
×
91

92
    if (Array.isArray(options))
39!
93
      return this.fromArray(options);
39✔
94

95
    if (options.raw) {
×
96
      if (!options.code)
×
97
        return this.decode(options.raw);
×
98
      assert(Buffer.isBuffer(options.raw), 'Raw must be a Buffer.');
×
99
      this.raw = options.raw;
×
100
    }
101

102
    if (options.code) {
×
103
      if (!options.raw)
×
104
        return this.fromArray(options.code);
×
105
      assert(Array.isArray(options.code), 'Code must be an array.');
×
106
      this.code = options.code;
×
107
    }
108

109
    return this;
×
110
  }
111

112
  /**
113
   * Instantiate a value-only iterator.
114
   * @returns {ScriptIterator}
115
   */
116

117
  values() {
118
    return this.code.values();
×
119
  }
120

121
  /**
122
   * Instantiate a key and value iterator.
123
   * @returns {ScriptIterator}
124
   */
125

126
  entries() {
127
    return this.code.entries();
×
128
  }
129

130
  /**
131
   * Instantiate a value-only iterator.
132
   * @returns {ScriptIterator}
133
   */
134

135
  [Symbol.iterator]() {
136
    return this.code[Symbol.iterator]();
×
137
  }
138

139
  /**
140
   * Convert the script to an array of
141
   * Buffers (pushdatas) and Numbers
142
   * (opcodes).
143
   * @returns {Array}
144
   */
145

146
  toArray() {
147
    return this.code.slice();
×
148
  }
149

150
  /**
151
   * Inject properties from an array of
152
   * of buffers and numbers.
153
   * @private
154
   * @param {Array} code
155
   * @returns {Script}
156
   */
157

158
  fromArray(code) {
159
    assert(Array.isArray(code));
39✔
160

161
    this.clear();
39✔
162

163
    for (const op of code)
39✔
164
      this.push(op);
133✔
165

166
    return this.compile();
39✔
167
  }
168

169
  /**
170
   * Instantiate script from an array
171
   * of buffers and numbers.
172
   * @param {Array} code
173
   * @returns {Script}
174
   */
175

176
  static fromArray(code) {
177
    return new this().fromArray(code);
×
178
  }
179

180
  /**
181
   * Convert script to stack items.
182
   * @returns {Buffer[]}
183
   */
184

185
  toItems() {
186
    const items = [];
×
187

188
    for (const op of this.code) {
×
189
      const data = op.toPush();
×
190

191
      if (!data)
×
192
        throw new Error('Non-push opcode in script.');
×
193

194
      items.push(data);
×
195
    }
196

197
    return items;
×
198
  }
199

200
  /**
201
   * Inject data from stack items.
202
   * @private
203
   * @param {Buffer[]} items
204
   * @returns {Script}
205
   */
206

207
  fromItems(items) {
208
    assert(Array.isArray(items));
×
209

210
    this.clear();
×
211

212
    for (const item of items)
×
213
      this.pushData(item);
×
214

215
    return this.compile();
×
216
  }
217

218
  /**
219
   * Instantiate script from stack items.
220
   * @param {Buffer[]} items
221
   * @returns {Script}
222
   */
223

224
  static fromItems(items) {
225
    return new this().fromItems(items);
×
226
  }
227

228
  /**
229
   * Convert script to stack.
230
   * @returns {Stack}
231
   */
232

233
  toStack() {
234
    return new Stack(this.toItems());
×
235
  }
236

237
  /**
238
   * Inject data from stack.
239
   * @private
240
   * @param {Stack} stack
241
   * @returns {Script}
242
   */
243

244
  fromStack(stack) {
245
    return this.fromItems(stack.items);
×
246
  }
247

248
  /**
249
   * Instantiate script from stack.
250
   * @param {Stack} stack
251
   * @returns {Script}
252
   */
253

254
  static fromStack(stack) {
255
    return new this().fromStack(stack);
×
256
  }
257

258
  /**
259
   * Inject properties from script.
260
   * Used for cloning.
261
   * @private
262
   * @param {Script} script
263
   * @returns {Script}
264
   */
265

266
  inject(script) {
267
    this.raw = script.raw;
19,995✔
268
    this.code = script.code.slice();
19,995✔
269
    return this;
19,995✔
270
  }
271

272
  /**
273
   * Test equality against script.
274
   * @param {Script} script
275
   * @returns {Boolean}
276
   */
277

278
  equals(script) {
279
    assert(Script.isScript(script));
×
280
    return this.raw.equals(script.raw);
×
281
  }
282

283
  /**
284
   * Compare against another script.
285
   * @param {Script} script
286
   * @returns {Number}
287
   */
288

289
  compare(script) {
290
    assert(Script.isScript(script));
×
291
    return this.raw.compare(script.raw);
×
292
  }
293

294
  /**
295
   * Clear the script.
296
   * @returns {Script}
297
   */
298

299
  clear() {
300
    this.raw = EMPTY_BUFFER;
3,340✔
301
    this.code.length = 0;
3,340✔
302
    return this;
3,340✔
303
  }
304

305
  /**
306
   * Inspect the script.
307
   * @returns {String} Human-readable script code.
308
   */
309

310
  format() {
311
    return `<Script: ${this.toString()}>`;
×
312
  }
313

314
  /**
315
   * Convert the script to a bitcoind test string.
316
   * @returns {String} Human-readable script code.
317
   */
318

319
  toString() {
320
    const out = [];
×
321

322
    for (const op of this.code)
×
323
      out.push(op.toFormat());
×
324

325
    return out.join(' ');
×
326
  }
327

328
  /**
329
   * Format the script as bitcoind asm.
330
   * @param {Boolean?} decode - Attempt to decode hash types.
331
   * @returns {String} Human-readable script.
332
   */
333

334
  toASM(decode) {
335
    const out = [];
×
336

337
    for (const op of this.code)
×
338
      out.push(op.toASM(decode));
×
339

340
    return out.join(' ');
×
341
  }
342

343
  /**
344
   * Re-encode the script internally. Useful if you
345
   * changed something manually in the `code` array.
346
   * @returns {Script}
347
   */
348

349
  compile() {
350
    if (this.code.length === 0)
3,341!
351
      return this.clear();
×
352

353
    let size = 0;
3,341✔
354

355
    for (const op of this.code)
3,341✔
356
      size += op.getSize();
17,979✔
357

358
    const bw = bio.write(size);
3,341✔
359

360
    for (const op of this.code)
3,341✔
361
      op.write(bw);
17,979✔
362

363
    this.raw = bw.render();
3,341✔
364

365
    return this;
3,341✔
366
  }
367

368
  /**
369
   * Write the script to a buffer writer.
370
   * @param {BufferWriter} bw
371
   */
372

373
  write(bw) {
374
    bw.writeVarBytes(this.raw);
×
375
    return bw;
×
376
  }
377

378
  /**
379
   * Encode the script to a Buffer. See {@link Script#encode}.
380
   * @param {String} enc - Encoding, either `'hex'` or `null`.
381
   * @returns {Buffer|String} Serialized script.
382
   */
383

384
  encode() {
385
    return this.raw;
55,322✔
386
  }
387

388
  /**
389
   * Convert script to a hex string.
390
   * @returns {String}
391
   */
392

393
  getJSON() {
394
    return this.toHex();
×
395
  }
396

397
  /**
398
   * Inject properties from json object.
399
   * @private
400
   * @param {String} json
401
   */
402

403
  fromJSON(json) {
404
    assert(typeof json === 'string', 'Code must be a string.');
×
405
    return this.decode(Buffer.from(json, 'hex'));
×
406
  }
407

408
  /**
409
   * Get the script's "subscript" starting at a separator.
410
   * @param {Number} index - The last separator to sign/verify beyond.
411
   * @returns {Script} Subscript.
412
   */
413

414
  getSubscript(index) {
415
    if (index === 0)
19,995!
416
      return this.clone();
19,995✔
417

418
    const script = new Script();
×
419

420
    for (let i = index; i < this.code.length; i++) {
×
421
      const op = this.code[i];
×
422

423
      if (op.value === -1)
×
424
        break;
×
425

426
      script.code.push(op);
×
427
    }
428

429
    return script.compile();
×
430
  }
431

432
  /**
433
   * Get the script's "subscript" starting at a separator.
434
   * Remove all OP_CODESEPARATORs if present. This bizarre
435
   * behavior is necessary for signing and verification when
436
   * code separators are present.
437
   * @returns {Script} Subscript.
438
   */
439

440
  removeSeparators() {
441
    let found = false;
×
442

443
    // Optimizing for the common case:
444
    // Check for any separators first.
445
    for (const op of this.code) {
×
446
      if (op.value === -1)
×
447
        break;
×
448

449
      if (op.value === opcodes.OP_CODESEPARATOR) {
×
450
        found = true;
×
451
        break;
×
452
      }
453
    }
454

455
    if (!found)
×
456
      return this;
×
457

458
    // Uncommon case: someone actually
459
    // has a code separator. Go through
460
    // and remove them all.
461
    const script = new Script();
×
462

463
    for (const op of this.code) {
×
464
      if (op.value === -1)
×
465
        break;
×
466

467
      if (op.value !== opcodes.OP_CODESEPARATOR)
×
468
        script.code.push(op);
×
469
    }
470

471
    return script.compile();
×
472
  }
473

474
  /**
475
   * Execute and interpret the script.
476
   * @param {Stack} stack - Script execution stack.
477
   * @param {Number?} flags - Script standard flags.
478
   * @param {TX?} tx - Transaction being verified.
479
   * @param {Number?} index - Index of input being verified.
480
   * @param {Amount?} value - Previous output value.
481
   * @throws {ScriptError} Will be thrown on VERIFY failures.
482
   */
483

484
  execute(stack, flags, tx, index, value) {
485
    if (flags == null)
22,525✔
486
      flags = Script.flags.STANDARD_VERIFY_FLAGS;
16✔
487

488
    if (this.raw.length > consensus.MAX_SCRIPT_SIZE)
22,525!
489
      throw new ScriptError('SCRIPT_SIZE');
×
490

491
    const state = [];
22,525✔
492
    const alt = [];
22,525✔
493

494
    let lastSep = 0;
22,525✔
495
    let opCount = 0;
22,525✔
496
    let negate = 0;
22,525✔
497
    let minimal = false;
22,525✔
498

499
    if (flags & Script.flags.VERIFY_MINIMALDATA)
22,525✔
500
      minimal = true;
21,745✔
501

502
    for (let ip = 0; ip < this.code.length; ip++) {
22,525✔
503
      const op = this.code[ip];
187,995✔
504

505
      if (op.value === -1)
187,995!
506
        throw new ScriptError('BAD_OPCODE', op, ip);
×
507

508
      if (op.data && op.data.length > consensus.MAX_SCRIPT_PUSH)
187,995✔
509
        throw new ScriptError('PUSH_SIZE', op, ip);
1✔
510

511
      if (op.value > opcodes.OP_16 && ++opCount > consensus.MAX_SCRIPT_OPS)
187,994✔
512
        throw new ScriptError('OP_COUNT', op, ip);
2✔
513

514
      if (op.isDisabled())
187,992✔
515
        throw new ScriptError('DISABLED_OPCODE', op, ip);
7✔
516

517
      if (negate && !op.isBranch()) {
187,985✔
518
        if (stack.length + alt.length > consensus.MAX_SCRIPT_STACK)
80,545!
519
          throw new ScriptError('STACK_SIZE', op, ip);
×
520
        continue;
80,545✔
521
      }
522

523
      if (op.data) {
107,440✔
524
        if (minimal && !op.isMinimal())
21,025!
525
          throw new ScriptError('MINIMALDATA', op, ip);
×
526

527
        stack.push(op.data);
21,025✔
528

529
        if (stack.length + alt.length > consensus.MAX_SCRIPT_STACK)
21,025!
530
          throw new ScriptError('STACK_SIZE', op, ip);
×
531

532
        continue;
21,025✔
533
      }
534

535
      switch (op.value) {
86,415!
536
        case opcodes.OP_0: {
537
          stack.pushInt(0);
889✔
538
          break;
889✔
539
        }
540
        case opcodes.OP_1NEGATE: {
541
          stack.pushInt(-1);
5✔
542
          break;
5✔
543
        }
544
        case opcodes.OP_1:
545
        case opcodes.OP_2:
546
        case opcodes.OP_3:
547
        case opcodes.OP_4:
548
        case opcodes.OP_5:
549
        case opcodes.OP_6:
550
        case opcodes.OP_7:
551
        case opcodes.OP_8:
552
        case opcodes.OP_9:
553
        case opcodes.OP_10:
554
        case opcodes.OP_11:
555
        case opcodes.OP_12:
556
        case opcodes.OP_13:
557
        case opcodes.OP_14:
558
        case opcodes.OP_15:
559
        case opcodes.OP_16: {
560
          stack.pushInt(op.value - 0x50);
2,224✔
561
          break;
2,224✔
562
        }
563
        case opcodes.OP_NOP: {
564
          break;
459✔
565
        }
566
        case opcodes.OP_TYPE: {
567
          if (!tx)
27!
568
            throw new ScriptError('UNKNOWN_ERROR', 'No TX passed in.');
×
569

570
          if (index >= tx.outputs.length) {
27!
571
            stack.pushInt(0);
×
572
            break;
×
573
          }
574

575
          const {covenant} = tx.outputs[index];
27✔
576

577
          stack.pushInt(covenant.type);
27✔
578

579
          break;
27✔
580
        }
581
        case opcodes.OP_CHECKLOCKTIMEVERIFY: {
582
          if (!tx)
3!
583
            throw new ScriptError('UNKNOWN_ERROR', 'No TX passed in.');
×
584

585
          if (stack.length === 0)
3!
586
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
587

588
          const num = stack.getNum(-1, minimal, 5);
3✔
589

590
          if (num.isNeg())
3!
591
            throw new ScriptError('NEGATIVE_LOCKTIME', op, ip);
×
592

593
          const locktime = num.toDouble();
3✔
594

595
          if (!tx.verifyLocktime(index, locktime))
3!
596
            throw new ScriptError('UNSATISFIED_LOCKTIME', op, ip);
3✔
597

598
          break;
×
599
        }
600
        case opcodes.OP_CHECKSEQUENCEVERIFY: {
601
          if (!tx)
11!
602
            throw new ScriptError('UNKNOWN_ERROR', 'No TX passed in.');
×
603

604
          if (stack.length === 0)
11✔
605
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
606

607
          const num = stack.getNum(-1, minimal, 5);
10✔
608

609
          if (num.isNeg())
9✔
610
            throw new ScriptError('NEGATIVE_LOCKTIME', op, ip);
1✔
611

612
          const locktime = num.toDouble();
8✔
613

614
          if (!tx.verifySequence(index, locktime))
8✔
615
            throw new ScriptError('UNSATISFIED_LOCKTIME', op, ip);
5✔
616

617
          break;
3✔
618
        }
619
        case opcodes.OP_NOP1:
620
        case opcodes.OP_NOP4:
621
        case opcodes.OP_NOP5:
622
        case opcodes.OP_NOP6:
623
        case opcodes.OP_NOP7:
624
        case opcodes.OP_NOP8:
625
        case opcodes.OP_NOP9:
626
        case opcodes.OP_NOP10: {
627
          if (flags & Script.flags.VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
10✔
628
            throw new ScriptError('DISCOURAGE_UPGRADABLE_NOPS', op, ip);
8✔
629
          break;
2✔
630
        }
631
        case opcodes.OP_IF:
632
        case opcodes.OP_NOTIF: {
633
          let val = false;
1,051✔
634

635
          if (!negate) {
1,051✔
636
            if (stack.length < 1)
1,037!
637
              throw new ScriptError('UNBALANCED_CONDITIONAL', op, ip);
×
638

639
            if (flags & Script.flags.VERIFY_MINIMALIF) {
1,037✔
640
              const item = stack.get(-1);
815✔
641

642
              if (item.length > 1)
815✔
643
                throw new ScriptError('MINIMALIF');
2✔
644

645
              if (item.length === 1 && item[0] !== 1)
813✔
646
                throw new ScriptError('MINIMALIF');
4✔
647
            }
648

649
            val = stack.getBool(-1);
1,031✔
650

651
            if (op.value === opcodes.OP_NOTIF)
1,031✔
652
              val = !val;
20✔
653

654
            stack.pop();
1,031✔
655
          }
656

657
          state.push(val);
1,045✔
658

659
          if (!val)
1,045✔
660
            negate += 1;
128✔
661

662
          break;
1,045✔
663
        }
664
        case opcodes.OP_ELSE: {
665
          if (state.length === 0)
1,030✔
666
            throw new ScriptError('UNBALANCED_CONDITIONAL', op, ip);
3✔
667

668
          state[state.length - 1] = !state[state.length - 1];
1,027✔
669

670
          if (!state[state.length - 1])
1,027✔
671
            negate += 1;
873✔
672
          else
673
            negate -= 1;
154✔
674

675
          break;
1,027✔
676
        }
677
        case opcodes.OP_ENDIF: {
678
          if (state.length === 0)
965✔
679
            throw new ScriptError('UNBALANCED_CONDITIONAL', op, ip);
6✔
680

681
          if (!state.pop())
959✔
682
            negate -= 1;
837✔
683

684
          break;
959✔
685
        }
686
        case opcodes.OP_VERIFY: {
687
          if (stack.length === 0)
29!
688
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
689

690
          if (!stack.getBool(-1))
29✔
691
            throw new ScriptError('VERIFY', op, ip);
1✔
692

693
          stack.pop();
28✔
694

695
          break;
28✔
696
        }
697
        case opcodes.OP_RETURN: {
698
          throw new ScriptError('OP_RETURN', op, ip);
5✔
699
        }
700
        case opcodes.OP_TOALTSTACK: {
701
          if (stack.length === 0)
2!
702
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
703

704
          alt.push(stack.pop());
2✔
705
          break;
2✔
706
        }
707
        case opcodes.OP_FROMALTSTACK: {
708
          if (alt.length === 0)
2✔
709
            throw new ScriptError('INVALID_ALTSTACK_OPERATION', op, ip);
1✔
710

711
          stack.push(alt.pop());
1✔
712
          break;
1✔
713
        }
714
        case opcodes.OP_2DROP: {
715
          if (stack.length < 2)
11✔
716
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
717

718
          stack.pop();
10✔
719
          stack.pop();
10✔
720
          break;
10✔
721
        }
722
        case opcodes.OP_2DUP: {
723
          if (stack.length < 2)
4✔
724
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
2✔
725

726
          const v1 = stack.get(-2);
2✔
727
          const v2 = stack.get(-1);
2✔
728

729
          stack.push(v1);
2✔
730
          stack.push(v2);
2✔
731
          break;
2✔
732
        }
733
        case opcodes.OP_3DUP: {
734
          if (stack.length < 3)
5✔
735
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
3✔
736

737
          const v1 = stack.get(-3);
2✔
738
          const v2 = stack.get(-2);
2✔
739
          const v3 = stack.get(-1);
2✔
740

741
          stack.push(v1);
2✔
742
          stack.push(v2);
2✔
743
          stack.push(v3);
2✔
744
          break;
2✔
745
        }
746
        case opcodes.OP_2OVER: {
747
          if (stack.length < 4)
4✔
748
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
2✔
749

750
          const v1 = stack.get(-4);
2✔
751
          const v2 = stack.get(-3);
2✔
752

753
          stack.push(v1);
2✔
754
          stack.push(v2);
2✔
755
          break;
2✔
756
        }
757
        case opcodes.OP_2ROT: {
758
          if (stack.length < 6)
13✔
759
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
760

761
          const v1 = stack.get(-6);
12✔
762
          const v2 = stack.get(-5);
12✔
763

764
          stack.erase(-6, -4);
12✔
765
          stack.push(v1);
12✔
766
          stack.push(v2);
12✔
767
          break;
12✔
768
        }
769
        case opcodes.OP_2SWAP: {
770
          if (stack.length < 4)
4✔
771
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
2✔
772

773
          stack.swap(-4, -2);
2✔
774
          stack.swap(-3, -1);
2✔
775
          break;
2✔
776
        }
777
        case opcodes.OP_IFDUP: {
778
          if (stack.length === 0)
1!
779
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
780

781
          if (stack.getBool(-1)) {
1!
782
            const val = stack.get(-1);
1✔
783
            stack.push(val);
1✔
784
          }
785

786
          break;
1✔
787
        }
788
        case opcodes.OP_DEPTH: {
789
          stack.pushInt(stack.length);
68✔
790
          break;
68✔
791
        }
792
        case opcodes.OP_DROP: {
793
          if (stack.length === 0)
66!
794
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
795

796
          stack.pop();
66✔
797
          break;
66✔
798
        }
799
        case opcodes.OP_DUP: {
800
          if (stack.length === 0)
19,606!
801
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
802

803
          stack.push(stack.get(-1));
19,606✔
804
          break;
19,606✔
805
        }
806
        case opcodes.OP_NIP: {
807
          if (stack.length < 2)
3✔
808
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
809

810
          stack.remove(-2);
2✔
811
          break;
2✔
812
        }
813
        case opcodes.OP_OVER: {
814
          if (stack.length < 2)
5✔
815
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
2✔
816

817
          stack.push(stack.get(-2));
3✔
818
          break;
3✔
819
        }
820
        case opcodes.OP_PICK:
821
        case opcodes.OP_ROLL: {
822
          if (stack.length < 2)
28✔
823
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
2✔
824

825
          const num = stack.getInt(-1, minimal, 4);
26✔
826
          stack.pop();
24✔
827

828
          if (num < 0 || num >= stack.length)
24✔
829
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
5✔
830

831
          const val = stack.get(-num - 1);
19✔
832

833
          if (op.value === opcodes.OP_ROLL)
19✔
834
            stack.remove(-num - 1);
10✔
835

836
          stack.push(val);
19✔
837
          break;
19✔
838
        }
839
        case opcodes.OP_ROT: {
840
          if (stack.length < 3)
11✔
841
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
842

843
          stack.swap(-3, -2);
10✔
844
          stack.swap(-2, -1);
10✔
845
          break;
10✔
846
        }
847
        case opcodes.OP_SWAP: {
848
          if (stack.length < 2)
9✔
849
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
2✔
850

851
          stack.swap(-2, -1);
7✔
852
          break;
7✔
853
        }
854
        case opcodes.OP_TUCK: {
855
          if (stack.length < 2)
5✔
856
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
2✔
857

858
          stack.insert(-2, stack.get(-1));
3✔
859
          break;
3✔
860
        }
861
        case opcodes.OP_SIZE: {
862
          if (stack.length < 1)
29!
863
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
864

865
          stack.pushInt(stack.get(-1).length);
29✔
866
          break;
29✔
867
        }
868
        case opcodes.OP_EQUAL:
869
        case opcodes.OP_EQUALVERIFY: {
870
          if (stack.length < 2)
19,864✔
871
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
4✔
872

873
          const v1 = stack.get(-2);
19,860✔
874
          const v2 = stack.get(-1);
19,860✔
875

876
          const res = v1.equals(v2);
19,860✔
877

878
          stack.pop();
19,860✔
879
          stack.pop();
19,860✔
880

881
          stack.pushBool(res);
19,860✔
882

883
          if (op.value === opcodes.OP_EQUALVERIFY) {
19,860✔
884
            if (!res)
19,629✔
885
              throw new ScriptError('EQUALVERIFY', op, ip);
8✔
886
            stack.pop();
19,621✔
887
          }
888

889
          break;
19,852✔
890
        }
891
        case opcodes.OP_1ADD:
892
        case opcodes.OP_1SUB:
893
        case opcodes.OP_NEGATE:
894
        case opcodes.OP_ABS:
895
        case opcodes.OP_NOT:
896
        case opcodes.OP_0NOTEQUAL: {
897
          if (stack.length < 1)
63!
898
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
899

900
          let num = stack.getNum(-1, minimal, 4);
63✔
901
          let cmp;
902

903
          switch (op.value) {
40!
904
            case opcodes.OP_1ADD:
905
              num.iaddn(1);
6✔
906
              break;
6✔
907
            case opcodes.OP_1SUB:
908
              num.isubn(1);
2✔
909
              break;
2✔
910
            case opcodes.OP_NEGATE:
911
              num.ineg();
3✔
912
              break;
3✔
913
            case opcodes.OP_ABS:
914
              num.iabs();
2✔
915
              break;
2✔
916
            case opcodes.OP_NOT:
917
              cmp = num.isZero();
25✔
918
              num = ScriptNum.fromBool(cmp);
25✔
919
              break;
25✔
920
            case opcodes.OP_0NOTEQUAL:
921
              cmp = !num.isZero();
2✔
922
              num = ScriptNum.fromBool(cmp);
2✔
923
              break;
2✔
924
            default:
925
              assert(false, 'Fatal script error.');
×
926
              break;
×
927
          }
928

929
          stack.pop();
40✔
930
          stack.pushNum(num);
40✔
931

932
          break;
40✔
933
        }
934
        case opcodes.OP_ADD:
935
        case opcodes.OP_SUB:
936
        case opcodes.OP_BOOLAND:
937
        case opcodes.OP_BOOLOR:
938
        case opcodes.OP_NUMEQUAL:
939
        case opcodes.OP_NUMEQUALVERIFY:
940
        case opcodes.OP_NUMNOTEQUAL:
941
        case opcodes.OP_LESSTHAN:
942
        case opcodes.OP_GREATERTHAN:
943
        case opcodes.OP_LESSTHANOREQUAL:
944
        case opcodes.OP_GREATERTHANOREQUAL:
945
        case opcodes.OP_MIN:
946
        case opcodes.OP_MAX: {
947
          if (stack.length < 2)
135✔
948
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
13✔
949

950
          const n1 = stack.getNum(-2, minimal, 4);
122✔
951
          const n2 = stack.getNum(-1, minimal, 4);
107✔
952

953
          let num, cmp;
954

955
          switch (op.value) {
94!
956
            case opcodes.OP_ADD:
957
              num = n1.iadd(n2);
21✔
958
              break;
21✔
959
            case opcodes.OP_SUB:
960
              num = n1.isub(n2);
3✔
961
              break;
3✔
962
            case opcodes.OP_BOOLAND:
963
              cmp = n1.toBool() && n2.toBool();
3✔
964
              num = ScriptNum.fromBool(cmp);
3✔
965
              break;
3✔
966
            case opcodes.OP_BOOLOR:
967
              cmp = n1.toBool() || n2.toBool();
3✔
968
              num = ScriptNum.fromBool(cmp);
3✔
969
              break;
3✔
970
            case opcodes.OP_NUMEQUAL:
971
              cmp = n1.eq(n2);
19✔
972
              num = ScriptNum.fromBool(cmp);
19✔
973
              break;
19✔
974
            case opcodes.OP_NUMEQUALVERIFY:
975
              cmp = n1.eq(n2);
3✔
976
              num = ScriptNum.fromBool(cmp);
3✔
977
              break;
3✔
978
            case opcodes.OP_NUMNOTEQUAL:
979
              cmp = !n1.eq(n2);
4✔
980
              num = ScriptNum.fromBool(cmp);
4✔
981
              break;
4✔
982
            case opcodes.OP_LESSTHAN:
983
              cmp = n1.lt(n2);
8✔
984
              num = ScriptNum.fromBool(cmp);
8✔
985
              break;
8✔
986
            case opcodes.OP_GREATERTHAN:
987
              cmp = n1.gt(n2);
8✔
988
              num = ScriptNum.fromBool(cmp);
8✔
989
              break;
8✔
990
            case opcodes.OP_LESSTHANOREQUAL:
991
              cmp = n1.lte(n2);
8✔
992
              num = ScriptNum.fromBool(cmp);
8✔
993
              break;
8✔
994
            case opcodes.OP_GREATERTHANOREQUAL:
995
              cmp = n1.gte(n2);
8✔
996
              num = ScriptNum.fromBool(cmp);
8✔
997
              break;
8✔
998
            case opcodes.OP_MIN:
999
              num = ScriptNum.min(n1, n2);
3✔
1000
              break;
3✔
1001
            case opcodes.OP_MAX:
1002
              num = ScriptNum.max(n1, n2);
3✔
1003
              break;
3✔
1004
            default:
1005
              assert(false, 'Fatal script error.');
×
1006
              break;
×
1007
          }
1008

1009
          stack.pop();
94✔
1010
          stack.pop();
94✔
1011
          stack.pushNum(num);
94✔
1012

1013
          if (op.value === opcodes.OP_NUMEQUALVERIFY) {
94✔
1014
            if (!stack.getBool(-1))
3!
1015
              throw new ScriptError('NUMEQUALVERIFY', op, ip);
×
1016
            stack.pop();
3✔
1017
          }
1018

1019
          break;
94✔
1020
        }
1021
        case opcodes.OP_WITHIN: {
1022
          if (stack.length < 3)
15✔
1023
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
1024

1025
          const n1 = stack.getNum(-3, minimal, 4);
14✔
1026
          const n2 = stack.getNum(-2, minimal, 4);
13✔
1027
          const n3 = stack.getNum(-1, minimal, 4);
12✔
1028

1029
          const val = n2.lte(n1) && n1.lt(n3);
11✔
1030

1031
          stack.pop();
11✔
1032
          stack.pop();
11✔
1033
          stack.pop();
11✔
1034

1035
          stack.pushBool(val);
11✔
1036
          break;
11✔
1037
        }
1038
        case opcodes.OP_RIPEMD160: {
1039
          if (stack.length === 0)
5!
1040
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
1041

1042
          stack.push(ripemd160.digest(stack.pop()));
5✔
1043
          break;
5✔
1044
        }
1045
        case opcodes.OP_SHA1: {
1046
          if (stack.length === 0)
44!
1047
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
1048

1049
          stack.push(sha1.digest(stack.pop()));
44✔
1050
          break;
44✔
1051
        }
1052
        case opcodes.OP_SHA256: {
1053
          if (stack.length === 0)
7!
1054
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
1055

1056
          stack.push(sha256.digest(stack.pop()));
7✔
1057
          break;
7✔
1058
        }
1059
        case opcodes.OP_HASH160: {
1060
          if (stack.length === 0)
7!
1061
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
1062

1063
          stack.push(hash160.digest(stack.pop()));
7✔
1064
          break;
7✔
1065
        }
1066
        case opcodes.OP_HASH256: {
1067
          if (stack.length === 0)
5!
1068
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
1069

1070
          stack.push(hash256.digest(stack.pop()));
5✔
1071
          break;
5✔
1072
        }
1073
        case opcodes.OP_BLAKE160: {
1074
          if (stack.length === 0)
19,594✔
1075
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
1076

1077
          stack.push(blake2b.digest(stack.pop(), 20));
19,593✔
1078
          break;
19,593✔
1079
        }
1080
        case opcodes.OP_BLAKE256: {
1081
          if (stack.length === 0)
1!
1082
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
1083

1084
          stack.push(blake2b.digest(stack.pop()));
×
1085
          break;
×
1086
        }
1087
        case opcodes.OP_SHA3: {
1088
          if (stack.length === 0)
1!
1089
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
1090

1091
          stack.push(sha3.digest(stack.pop()));
×
1092
          break;
×
1093
        }
1094
        case opcodes.OP_KECCAK: {
1095
          if (stack.length === 0)
1!
1096
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
1097

1098
          stack.push(keccak.digest(stack.pop()));
×
1099
          break;
×
1100
        }
1101
        case opcodes.OP_CODESEPARATOR: {
1102
          lastSep = ip + 1;
×
1103
          break;
×
1104
        }
1105
        case opcodes.OP_CHECKSIG:
1106
        case opcodes.OP_CHECKSIGVERIFY: {
1107
          if (!tx)
19,658!
1108
            throw new ScriptError('UNKNOWN_ERROR', 'No TX passed in.');
×
1109

1110
          if (stack.length < 2)
19,658✔
1111
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
2✔
1112

1113
          const sig = stack.get(-2);
19,656✔
1114
          const key = stack.get(-1);
19,656✔
1115

1116
          const subscript = this.getSubscript(lastSep);
19,656✔
1117

1118
          validateSignature(sig, flags);
19,656✔
1119
          validateKey(key, flags);
19,595✔
1120

1121
          let res = false;
19,595✔
1122

1123
          if (sig.length > 0) {
19,595✔
1124
            const type = sig[sig.length - 1];
19,588✔
1125
            const hash = tx.signatureHash(
19,588✔
1126
              index,
1127
              subscript,
1128
              value,
1129
              type
1130
            );
1131
            res = checksig(hash, sig, key);
19,588✔
1132
          }
1133

1134
          if (!res && (flags & Script.flags.VERIFY_NULLFAIL)) {
19,595✔
1135
            if (sig.length !== 0)
3✔
1136
              throw new ScriptError('NULLFAIL', op, ip);
1✔
1137
          }
1138

1139
          stack.pop();
19,594✔
1140
          stack.pop();
19,594✔
1141

1142
          stack.pushBool(res);
19,594✔
1143

1144
          if (op.value === opcodes.OP_CHECKSIGVERIFY) {
19,594!
1145
            if (!res)
×
1146
              throw new ScriptError('CHECKSIGVERIFY', op, ip);
×
1147
            stack.pop();
×
1148
          }
1149

1150
          break;
19,594✔
1151
        }
1152
        case opcodes.OP_CHECKMULTISIG:
1153
        case opcodes.OP_CHECKMULTISIGVERIFY: {
1154
          if (!tx)
353!
1155
            throw new ScriptError('UNKNOWN_ERROR', 'No TX passed in.');
×
1156

1157
          let i = 1;
353✔
1158
          if (stack.length < i)
353✔
1159
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
1160

1161
          let n = stack.getInt(-i, minimal, 4);
352✔
1162
          let okey = n + 2;
350✔
1163
          let ikey, isig;
1164

1165
          if (n < 0 || n > consensus.MAX_MULTISIG_PUBKEYS)
350✔
1166
            throw new ScriptError('PUBKEY_COUNT', op, ip);
2✔
1167

1168
          opCount += n;
348✔
1169

1170
          if (opCount > consensus.MAX_SCRIPT_OPS)
348✔
1171
            throw new ScriptError('OP_COUNT', op, ip);
2✔
1172

1173
          i += 1;
346✔
1174
          ikey = i;
346✔
1175
          i += n;
346✔
1176

1177
          if (stack.length < i)
346✔
1178
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
1179

1180
          let m = stack.getInt(-i, minimal, 4);
345✔
1181

1182
          if (m < 0 || m > n)
342✔
1183
            throw new ScriptError('SIG_COUNT', op, ip);
2✔
1184

1185
          i += 1;
340✔
1186
          isig = i;
340✔
1187
          i += m;
340✔
1188

1189
          if (stack.length < i)
340✔
1190
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
1191

1192
          const subscript = this.getSubscript(lastSep);
339✔
1193

1194
          let res = true;
339✔
1195
          while (res && m > 0) {
339✔
1196
            const sig = stack.get(-isig);
55✔
1197
            const key = stack.get(-ikey);
55✔
1198

1199
            validateSignature(sig, flags);
55✔
1200
            validateKey(key, flags);
29✔
1201

1202
            if (sig.length > 0) {
23✔
1203
              const type = sig[sig.length - 1];
15✔
1204
              const hash = tx.signatureHash(
15✔
1205
                index,
1206
                subscript,
1207
                value,
1208
                type
1209
              );
1210

1211
              if (checksig(hash, sig, key)) {
15✔
1212
                isig += 1;
14✔
1213
                m -= 1;
14✔
1214
              }
1215
            }
1216

1217
            ikey += 1;
23✔
1218
            n -= 1;
23✔
1219

1220
            if (m > n)
23✔
1221
              res = false;
7✔
1222
          }
1223

1224
          while (i > 1) {
307✔
1225
            if (!res && (flags & Script.flags.VERIFY_NULLFAIL)) {
1,776✔
1226
              if (okey === 0 && stack.get(-1).length !== 0)
7!
1227
                throw new ScriptError('NULLFAIL', op, ip);
×
1228
            }
1229

1230
            if (okey > 0)
1,776✔
1231
              okey -= 1;
1,748✔
1232

1233
            stack.pop();
1,776✔
1234

1235
            i -= 1;
1,776✔
1236
          }
1237

1238
          if (stack.length < 1)
307!
1239
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
1240

1241
          if (stack.get(-1).length !== 0)
307✔
1242
            throw new ScriptError('SIG_NULLDUMMY', op, ip);
4✔
1243

1244
          stack.pop();
303✔
1245

1246
          stack.pushBool(res);
303✔
1247

1248
          if (op.value === opcodes.OP_CHECKMULTISIGVERIFY) {
303✔
1249
            if (!res)
245!
1250
              throw new ScriptError('CHECKMULTISIGVERIFY', op, ip);
×
1251
            stack.pop();
245✔
1252
          }
1253

1254
          break;
303✔
1255
        }
1256
        default: {
1257
          throw new ScriptError('BAD_OPCODE', op, ip);
78✔
1258
        }
1259
      }
1260

1261
      if (stack.length + alt.length > consensus.MAX_SCRIPT_STACK)
86,070!
1262
        throw new ScriptError('STACK_SIZE', op, ip);
×
1263
    }
1264

1265
    if (state.length !== 0)
22,170✔
1266
      throw new ScriptError('UNBALANCED_CONDITIONAL');
1✔
1267
  }
1268

1269
  /**
1270
   * Find a data element in a script.
1271
   * @param {Buffer} data - Data element to match against.
1272
   * @returns {Number} Index (`-1` if not present).
1273
   */
1274

1275
  indexOf(data) {
1276
    for (let i = 0; i < this.code.length; i++) {
5✔
1277
      const op = this.code[i];
11✔
1278

1279
      if (op.value === -1)
11!
1280
        break;
×
1281

1282
      if (!op.data)
11✔
1283
        continue;
5✔
1284

1285
      if (op.data.equals(data))
6✔
1286
        return i;
5✔
1287
    }
1288

1289
    return -1;
×
1290
  }
1291

1292
  /**
1293
   * Test a script to see if it is likely
1294
   * to be script code (no weird opcodes).
1295
   * @returns {Boolean}
1296
   */
1297

1298
  isCode() {
1299
    for (const op of this.code) {
×
1300
      if (op.value === -1)
×
1301
        return false;
×
1302

1303
      if (op.isDisabled())
×
1304
        return false;
×
1305

1306
      switch (op.value) {
×
1307
        case opcodes.OP_RESERVED:
1308
        case opcodes.OP_NOP:
1309
        case opcodes.OP_VER:
1310
        case opcodes.OP_VERIF:
1311
        case opcodes.OP_VERNOTIF:
1312
        case opcodes.OP_RESERVED1:
1313
        case opcodes.OP_RESERVED2:
1314
          return false;
×
1315
      }
1316

1317
      if (op.value > opcodes.OP_CHECKSEQUENCEVERIFY)
×
1318
        return false;
×
1319
    }
1320

1321
    return true;
×
1322
  }
1323

1324
  /**
1325
   * Inject properties from a pay-to-pubkey script.
1326
   * @private
1327
   * @param {Buffer} key
1328
   */
1329

1330
  fromPubkey(key) {
1331
    assert(Buffer.isBuffer(key) && key.length === 33);
×
1332

1333
    this.raw = Buffer.allocUnsafe(35);
×
1334
    this.raw[0] = 33;
×
1335
    key.copy(this.raw, 1);
×
1336
    this.raw[34] = opcodes.OP_CHECKSIG;
×
1337

1338
    key = this.raw.slice(1, 34);
×
1339

1340
    this.code.length = 0;
×
1341
    this.code.push(Opcode.fromPush(key));
×
1342
    this.code.push(Opcode.fromOp(opcodes.OP_CHECKSIG));
×
1343

1344
    return this;
×
1345
  }
1346

1347
  /**
1348
   * Create a pay-to-pubkey script.
1349
   * @param {Buffer} key
1350
   * @returns {Script}
1351
   */
1352

1353
  static fromPubkey(key) {
1354
    return new this().fromPubkey(key);
×
1355
  }
1356

1357
  /**
1358
   * Inject properties from a pay-to-pubkeyhash script.
1359
   * @private
1360
   * @param {Buffer} hash
1361
   */
1362

1363
  fromPubkeyhash(hash) {
1364
    assert(Buffer.isBuffer(hash) && hash.length === 20);
96,040✔
1365

1366
    this.raw = Buffer.allocUnsafe(25);
96,040✔
1367
    this.raw[0] = opcodes.OP_DUP;
96,040✔
1368
    this.raw[1] = opcodes.OP_BLAKE160;
96,040✔
1369
    this.raw[2] = 0x14;
96,040✔
1370
    hash.copy(this.raw, 3);
96,040✔
1371
    this.raw[23] = opcodes.OP_EQUALVERIFY;
96,040✔
1372
    this.raw[24] = opcodes.OP_CHECKSIG;
96,040✔
1373

1374
    hash = this.raw.slice(3, 23);
96,040✔
1375

1376
    this.code.length = 0;
96,040✔
1377
    this.code.push(Opcode.fromOp(opcodes.OP_DUP));
96,040✔
1378
    this.code.push(Opcode.fromOp(opcodes.OP_BLAKE160));
96,040✔
1379
    this.code.push(Opcode.fromPush(hash));
96,040✔
1380
    this.code.push(Opcode.fromOp(opcodes.OP_EQUALVERIFY));
96,040✔
1381
    this.code.push(Opcode.fromOp(opcodes.OP_CHECKSIG));
96,040✔
1382

1383
    return this;
96,040✔
1384
  }
1385

1386
  /**
1387
   * Create a pay-to-pubkeyhash script.
1388
   * @param {Buffer} hash
1389
   * @returns {Script}
1390
   */
1391

1392
  static fromPubkeyhash(hash) {
1393
    return new this().fromPubkeyhash(hash);
96,040✔
1394
  }
1395

1396
  /**
1397
   * Inject properties from pay-to-multisig script.
1398
   * @private
1399
   * @param {Number} m
1400
   * @param {Number} n
1401
   * @param {Buffer[]} keys
1402
   */
1403

1404
  fromMultisig(m, n, keys) {
1405
    assert((m & 0xff) === m && (n & 0xff) === n);
3,301✔
1406
    assert(Array.isArray(keys));
3,301✔
1407
    assert(keys.length === n, '`n` keys are required for multisig.');
3,301✔
1408
    assert(m >= 1 && m <= n);
3,301✔
1409
    assert(n >= 1 && n <= 15);
3,301✔
1410

1411
    this.clear();
3,301✔
1412

1413
    this.pushSmall(m);
3,301✔
1414

1415
    for (const key of sortKeys(keys))
3,301✔
1416
      this.pushData(key);
7,838✔
1417

1418
    this.pushSmall(n);
3,301✔
1419
    this.pushOp(opcodes.OP_CHECKMULTISIG);
3,301✔
1420

1421
    return this.compile();
3,301✔
1422
  }
1423

1424
  /**
1425
   * Create a pay-to-multisig script.
1426
   * @param {Number} m
1427
   * @param {Number} n
1428
   * @param {Buffer[]} keys
1429
   * @returns {Script}
1430
   */
1431

1432
  static fromMultisig(m, n, keys) {
1433
    return new this().fromMultisig(m, n, keys);
3,301✔
1434
  }
1435

1436
  /**
1437
   * Get the standard script type.
1438
   * @returns {ScriptType}
1439
   */
1440

1441
  getType() {
1442
    if (this.isPubkey())
×
1443
      return scriptTypes.PUBKEY;
×
1444

1445
    if (this.isPubkeyhash())
×
1446
      return scriptTypes.PUBKEYHASH;
×
1447

1448
    if (this.isMultisig())
×
1449
      return scriptTypes.MULTISIG;
×
1450

1451
    return scriptTypes.NONSTANDARD;
×
1452
  }
1453

1454
  /**
1455
   * Test whether a script is of an unknown/non-standard type.
1456
   * @returns {Boolean}
1457
   */
1458

1459
  isUnknown() {
1460
    return this.getType() === scriptTypes.NONSTANDARD;
×
1461
  }
1462

1463
  /**
1464
   * Test whether the script is standard by policy standards.
1465
   * @returns {Boolean}
1466
   */
1467

1468
  isStandard() {
1469
    const [m, n] = this.getMultisig();
×
1470

1471
    if (m !== -1) {
×
1472
      if (n < 1 || n > 3)
×
1473
        return false;
×
1474

1475
      if (m < 1 || m > n)
×
1476
        return false;
×
1477

1478
      return true;
×
1479
    }
1480

1481
    return this.getType() !== scriptTypes.NONSTANDARD;
×
1482
  }
1483

1484
  /**
1485
   * Calculate the size of the script
1486
   * excluding the varint size bytes.
1487
   * @returns {Number}
1488
   */
1489

1490
  getSize() {
1491
    return this.raw.length;
×
1492
  }
1493

1494
  /**
1495
   * Calculate the size of the script
1496
   * including the varint size bytes.
1497
   * @returns {Number}
1498
   */
1499

1500
  getVarSize() {
1501
    return encoding.sizeVarBytes(this.raw);
47,412✔
1502
  }
1503

1504
  /**
1505
   * Get the sha3 of the raw script.
1506
   * @returns {Hash}
1507
   */
1508

1509
  sha3() {
1510
    return sha3.digest(this.encode());
3,301✔
1511
  }
1512

1513
  /**
1514
   * Test whether the output script is pay-to-pubkey.
1515
   * @param {Boolean} [minimal=false] - Minimaldata only.
1516
   * @returns {Boolean}
1517
   */
1518

1519
  isPubkey(minimal) {
1520
    if (minimal) {
76,450!
1521
      return this.raw.length === 35
×
1522
        && this.raw[0] === 33
1523
        && this.raw[0] + 2 === this.raw.length
1524
        && this.raw[this.raw.length - 1] === opcodes.OP_CHECKSIG;
1525
    }
1526

1527
    if (this.code.length !== 2)
76,450!
1528
      return false;
76,450✔
1529

1530
    return this.getLength(0) === 33
×
1531
      && this.getOp(1) === opcodes.OP_CHECKSIG;
1532
  }
1533

1534
  /**
1535
   * Get P2PK key if present.
1536
   * @param {Boolean} [minimal=false] - Minimaldata only.
1537
   * @returns {Buffer|null}
1538
   */
1539

1540
  getPubkey(minimal) {
1541
    if (!this.isPubkey(minimal))
55,013!
1542
      return null;
55,013✔
1543

1544
    if (minimal)
×
1545
      return this.raw.slice(1, 1 + this.raw[0]);
×
1546

1547
    return this.getData(0);
×
1548
  }
1549

1550
  /**
1551
   * Test whether the output script is pay-to-pubkeyhash.
1552
   * @param {Boolean} [minimal=false] - Minimaldata only.
1553
   * @returns {Boolean}
1554
   */
1555

1556
  isPubkeyhash(minimal) {
1557
    if (minimal || this.raw.length === 25) {
76,450✔
1558
      return this.raw.length === 25
76,437✔
1559
        && this.raw[0] === opcodes.OP_DUP
1560
        && this.raw[1] === opcodes.OP_BLAKE160
1561
        && this.raw[2] === 0x14
1562
        && this.raw[23] === opcodes.OP_EQUALVERIFY
1563
        && this.raw[24] === opcodes.OP_CHECKSIG;
1564
    }
1565

1566
    if (this.code.length !== 5)
13✔
1567
      return false;
3✔
1568

1569
    return this.getOp(0) === opcodes.OP_DUP
10!
1570
      && this.getOp(1) === opcodes.OP_BLAKE160
1571
      && this.getLength(2) === 20
1572
      && this.getOp(3) === opcodes.OP_EQUALVERIFY
1573
      && this.getOp(4) === opcodes.OP_CHECKSIG;
1574
  }
1575

1576
  /**
1577
   * Get P2PKH hash if present.
1578
   * @param {Boolean} [minimal=false] - Minimaldata only.
1579
   * @returns {Buffer|null}
1580
   */
1581

1582
  getPubkeyhash(minimal) {
1583
    if (!this.isPubkeyhash(minimal))
55,013✔
1584
      return null;
13✔
1585

1586
    if (minimal)
55,000!
1587
      return this.raw.slice(3, 23);
×
1588

1589
    return this.getData(2);
55,000✔
1590
  }
1591

1592
  /**
1593
   * Test whether the output script is pay-to-multisig.
1594
   * @param {Boolean} [minimal=false] - Minimaldata only.
1595
   * @returns {Boolean}
1596
   */
1597

1598
  isMultisig(minimal) {
1599
    if (this.code.length < 4 || this.code.length > 19)
13!
1600
      return false;
×
1601

1602
    if (this.getOp(-1) !== opcodes.OP_CHECKMULTISIG)
13!
1603
      return false;
×
1604

1605
    const m = this.getSmall(0);
13✔
1606

1607
    if (m < 1)
13!
1608
      return false;
×
1609

1610
    const n = this.getSmall(-2);
13✔
1611

1612
    if (n < 1 || m > n)
13!
1613
      return false;
×
1614

1615
    if (this.code.length !== n + 3)
13!
1616
      return false;
×
1617

1618
    for (let i = 1; i < n + 1; i++) {
13✔
1619
      const op = this.code[i];
29✔
1620

1621
      if (op.toLength() !== 33)
29!
1622
        return false;
×
1623

1624
      if (minimal && !op.isMinimal())
29!
1625
        return false;
×
1626
    }
1627

1628
    return true;
13✔
1629
  }
1630

1631
  /**
1632
   * Get multisig m and n values if present.
1633
   * @param {Boolean} [minimal=false] - Minimaldata only.
1634
   * @returns {Array} [m, n]
1635
   */
1636

1637
  getMultisig(minimal) {
1638
    if (!this.isMultisig(minimal))
13!
1639
      return [-1, -1];
×
1640

1641
    return [this.getSmall(0), this.getSmall(-2)];
13✔
1642
  }
1643

1644
  /**
1645
   * Test whether the output script is unspendable.
1646
   * @returns {Boolean}
1647
   */
1648

1649
  isUnspendable() {
1650
    if (this.raw.length > consensus.MAX_SCRIPT_SIZE)
×
1651
      return true;
×
1652

1653
    return this.raw.length > 0 && this.raw[0] === opcodes.OP_RETURN;
×
1654
  }
1655

1656
  /**
1657
   * Test the script against a bloom filter.
1658
   * @param {Bloom} filter
1659
   * @returns {Boolean}
1660
   */
1661

1662
  test(filter) {
1663
    for (const op of this.code) {
×
1664
      if (op.value === -1)
×
1665
        break;
×
1666

1667
      if (!op.data || op.data.length === 0)
×
1668
        continue;
×
1669

1670
      if (filter.test(op.data))
×
1671
        return true;
×
1672
    }
1673

1674
    return false;
×
1675
  }
1676

1677
  /**
1678
   * Test the script to see if it contains only push ops.
1679
   * Push ops are: OP_1NEGATE, OP_0-OP_16 and all PUSHDATAs.
1680
   * @returns {Boolean}
1681
   */
1682

1683
  isPushOnly() {
1684
    for (const op of this.code) {
×
1685
      if (op.value === -1)
×
1686
        return false;
×
1687

1688
      if (op.value > opcodes.OP_16)
×
1689
        return false;
×
1690
    }
1691

1692
    return true;
×
1693
  }
1694

1695
  /**
1696
   * Count the sigops in the script.
1697
   * @returns {Number} sigop count
1698
   */
1699

1700
  getSigops() {
1701
    let total = 0;
4,421✔
1702
    let lastOp = -1;
4,421✔
1703

1704
    for (const op of this.code) {
4,421✔
1705
      if (op.value === -1)
336,061!
1706
        break;
×
1707

1708
      switch (op.value) {
336,061✔
1709
        case opcodes.OP_CHECKSIG:
1710
        case opcodes.OP_CHECKSIGVERIFY:
1711
          total += 1;
320,000✔
1712
          break;
320,000✔
1713
        case opcodes.OP_CHECKMULTISIG:
1714
        case opcodes.OP_CHECKMULTISIGVERIFY:
1715
          if (lastOp >= opcodes.OP_1 && lastOp <= opcodes.OP_16)
7!
1716
            total += lastOp - 0x50;
7✔
1717
          else
1718
            total += consensus.MAX_MULTISIG_PUBKEYS;
×
1719
          break;
7✔
1720
      }
1721

1722
      lastOp = op.value;
336,061✔
1723
    }
1724

1725
    return total;
4,421✔
1726
  }
1727

1728
  /*
1729
   * Mutation
1730
   */
1731

1732
  get(index) {
1733
    if (index < 0)
55,075✔
1734
      index += this.code.length;
39✔
1735

1736
    if (index < 0 || index >= this.code.length)
55,075!
1737
      return null;
×
1738

1739
    return this.code[index];
55,075✔
1740
  }
1741

1742
  pop() {
1743
    const op = this.code.pop();
×
1744
    return op || null;
×
1745
  }
1746

1747
  shift() {
1748
    const op = this.code.shift();
×
1749
    return op || null;
×
1750
  }
1751

1752
  remove(index) {
1753
    if (index < 0)
×
1754
      index += this.code.length;
×
1755

1756
    if (index < 0 || index >= this.code.length)
×
1757
      return null;
×
1758

1759
    const items = this.code.splice(index, 1);
×
1760

1761
    if (items.length === 0)
×
1762
      return null;
×
1763

1764
    return items[0];
×
1765
  }
1766

1767
  set(index, op) {
1768
    if (index < 0)
×
1769
      index += this.code.length;
×
1770

1771
    assert(Opcode.isOpcode(op));
×
1772
    assert(index >= 0 && index <= this.code.length);
×
1773

1774
    this.code[index] = op;
×
1775

1776
    return this;
×
1777
  }
1778

1779
  push(op) {
1780
    assert(Opcode.isOpcode(op));
17,979✔
1781
    this.code.push(op);
17,979✔
1782
    return this;
17,979✔
1783
  }
1784

1785
  unshift(op) {
1786
    assert(Opcode.isOpcode(op));
×
1787
    this.code.unshift(op);
×
1788
    return this;
×
1789
  }
1790

1791
  insert(index, op) {
1792
    if (index < 0)
×
1793
      index += this.code.length;
×
1794

1795
    assert(Opcode.isOpcode(op));
×
1796
    assert(index >= 0 && index <= this.code.length);
×
1797

1798
    this.code.splice(index, 0, op);
×
1799

1800
    return this;
×
1801
  }
1802

1803
  /*
1804
   * Op
1805
   */
1806

1807
  getOp(index) {
1808
    const op = this.get(index);
23✔
1809
    return op ? op.value : -1;
23!
1810
  }
1811

1812
  popOp() {
1813
    const op = this.pop();
×
1814
    return op ? op.value : -1;
×
1815
  }
1816

1817
  shiftOp() {
1818
    const op = this.shift();
×
1819
    return op ? op.value : -1;
×
1820
  }
1821

1822
  removeOp(index) {
1823
    const op = this.remove(index);
×
1824
    return op ? op.value : -1;
×
1825
  }
1826

1827
  setOp(index, value) {
1828
    return this.set(index, Opcode.fromOp(value));
×
1829
  }
1830

1831
  pushOp(value) {
1832
    return this.push(Opcode.fromOp(value));
3,406✔
1833
  }
1834

1835
  unshiftOp(value) {
1836
    return this.unshift(Opcode.fromOp(value));
×
1837
  }
1838

1839
  insertOp(index, value) {
1840
    return this.insert(index, Opcode.fromOp(value));
×
1841
  }
1842

1843
  /*
1844
   * Data
1845
   */
1846

1847
  getData(index) {
1848
    const op = this.get(index);
55,000✔
1849
    return op ? op.data : null;
55,000!
1850
  }
1851

1852
  popData() {
1853
    const op = this.pop();
×
1854
    return op ? op.data : null;
×
1855
  }
1856

1857
  shiftData() {
1858
    const op = this.shift();
×
1859
    return op ? op.data : null;
×
1860
  }
1861

1862
  removeData(index) {
1863
    const op = this.remove(index);
×
1864
    return op ? op.data : null;
×
1865
  }
1866

1867
  setData(index, data) {
1868
    return this.set(index, Opcode.fromData(data));
×
1869
  }
1870

1871
  pushData(data) {
1872
    return this.push(Opcode.fromData(data));
7,838✔
1873
  }
1874

1875
  unshiftData(data) {
1876
    return this.unshift(Opcode.fromData(data));
×
1877
  }
1878

1879
  insertData(index, data) {
1880
    return this.insert(index, Opcode.fromData(data));
×
1881
  }
1882

1883
  /*
1884
   * Length
1885
   */
1886

1887
  getLength(index) {
1888
    const op = this.get(index);
×
1889
    return op ? op.toLength() : -1;
×
1890
  }
1891

1892
  /*
1893
   * Push
1894
   */
1895

1896
  getPush(index) {
1897
    const op = this.get(index);
×
1898
    return op ? op.toPush() : null;
×
1899
  }
1900

1901
  popPush() {
1902
    const op = this.pop();
×
1903
    return op ? op.toPush() : null;
×
1904
  }
1905

1906
  shiftPush() {
1907
    const op = this.shift();
×
1908
    return op ? op.toPush() : null;
×
1909
  }
1910

1911
  removePush(index) {
1912
    const op = this.remove(index);
×
1913
    return op ? op.toPush() : null;
×
1914
  }
1915

1916
  setPush(index, data) {
1917
    return this.set(index, Opcode.fromPush(data));
×
1918
  }
1919

1920
  pushPush(data) {
1921
    return this.push(Opcode.fromPush(data));
×
1922
  }
1923

1924
  unshiftPush(data) {
1925
    return this.unshift(Opcode.fromPush(data));
×
1926
  }
1927

1928
  insertPush(index, data) {
1929
    return this.insert(index, Opcode.fromPush(data));
×
1930
  }
1931

1932
  /*
1933
   * String
1934
   */
1935

1936
  getString(index, enc) {
1937
    const op = this.get(index);
×
1938
    return op ? op.toString(enc) : null;
×
1939
  }
1940

1941
  popString(enc) {
1942
    const op = this.pop();
×
1943
    return op ? op.toString(enc) : null;
×
1944
  }
1945

1946
  shiftString(enc) {
1947
    const op = this.shift();
×
1948
    return op ? op.toString(enc) : null;
×
1949
  }
1950

1951
  removeString(index, enc) {
1952
    const op = this.remove(index);
×
1953
    return op ? op.toString(enc) : null;
×
1954
  }
1955

1956
  setString(index, str, enc) {
1957
    return this.set(index, Opcode.fromString(str, enc));
×
1958
  }
1959

1960
  pushString(str, enc) {
1961
    return this.push(Opcode.fromString(str, enc));
×
1962
  }
1963

1964
  unshiftString(str, enc) {
1965
    return this.unshift(Opcode.fromString(str, enc));
×
1966
  }
1967

1968
  insertString(index, str, enc) {
1969
    return this.insert(index, Opcode.fromString(str, enc));
×
1970
  }
1971

1972
  /*
1973
   * Small
1974
   */
1975

1976
  getSmall(index) {
1977
    const op = this.get(index);
52✔
1978
    return op ? op.toSmall() : -1;
52!
1979
  }
1980

1981
  popSmall() {
1982
    const op = this.pop();
×
1983
    return op ? op.toSmall() : -1;
×
1984
  }
1985

1986
  shiftSmall() {
1987
    const op = this.shift();
×
1988
    return op ? op.toSmall() : -1;
×
1989
  }
1990

1991
  removeSmall(index) {
1992
    const op = this.remove(index);
×
1993
    return op ? op.toSmall() : -1;
×
1994
  }
1995

1996
  setSmall(index, num) {
1997
    return this.set(index, Opcode.fromSmall(num));
×
1998
  }
1999

2000
  pushSmall(num) {
2001
    return this.push(Opcode.fromSmall(num));
6,602✔
2002
  }
2003

2004
  unshiftSmall(num) {
2005
    return this.unshift(Opcode.fromSmall(num));
×
2006
  }
2007

2008
  insertSmall(index, num) {
2009
    return this.insert(index, Opcode.fromSmall(num));
×
2010
  }
2011

2012
  /*
2013
   * Num
2014
   */
2015

2016
  getNum(index, minimal, limit) {
2017
    const op = this.get(index);
×
2018
    return op ? op.toNum(minimal, limit) : null;
×
2019
  }
2020

2021
  popNum(minimal, limit) {
2022
    const op = this.pop();
×
2023
    return op ? op.toNum(minimal, limit) : null;
×
2024
  }
2025

2026
  shiftNum(minimal, limit) {
2027
    const op = this.shift();
×
2028
    return op ? op.toNum(minimal, limit) : null;
×
2029
  }
2030

2031
  removeNum(index, minimal, limit) {
2032
    const op = this.remove(index);
×
2033
    return op ? op.toNum(minimal, limit) : null;
×
2034
  }
2035

2036
  setNum(index, num) {
2037
    return this.set(index, Opcode.fromNum(num));
×
2038
  }
2039

2040
  pushNum(num) {
2041
    return this.push(Opcode.fromNum(num));
×
2042
  }
2043

2044
  unshiftNum(num) {
2045
    return this.unshift(Opcode.fromNum(num));
×
2046
  }
2047

2048
  insertNum(index, num) {
2049
    return this.insert(index, Opcode.fromNum(num));
×
2050
  }
2051

2052
  /*
2053
   * Int
2054
   */
2055

2056
  getInt(index, minimal, limit) {
2057
    const op = this.get(index);
×
2058
    return op ? op.toInt(minimal, limit) : -1;
×
2059
  }
2060

2061
  popInt(minimal, limit) {
2062
    const op = this.pop();
×
2063
    return op ? op.toInt(minimal, limit) : -1;
×
2064
  }
2065

2066
  shiftInt(minimal, limit) {
2067
    const op = this.shift();
×
2068
    return op ? op.toInt(minimal, limit) : -1;
×
2069
  }
2070

2071
  removeInt(index, minimal, limit) {
2072
    const op = this.remove(index);
×
2073
    return op ? op.toInt(minimal, limit) : -1;
×
2074
  }
2075

2076
  setInt(index, num) {
2077
    return this.set(index, Opcode.fromInt(num));
×
2078
  }
2079

2080
  pushInt(num) {
2081
    return this.push(Opcode.fromInt(num));
×
2082
  }
2083

2084
  unshiftInt(num) {
2085
    return this.unshift(Opcode.fromInt(num));
×
2086
  }
2087

2088
  insertInt(index, num) {
2089
    return this.insert(index, Opcode.fromInt(num));
×
2090
  }
2091

2092
  /*
2093
   * Bool
2094
   */
2095

2096
  getBool(index) {
2097
    const op = this.get(index);
×
2098
    return op ? op.toBool() : false;
×
2099
  }
2100

2101
  popBool() {
2102
    const op = this.pop();
×
2103
    return op ? op.toBool() : false;
×
2104
  }
2105

2106
  shiftBool() {
2107
    const op = this.shift();
×
2108
    return op ? op.toBool() : false;
×
2109
  }
2110

2111
  removeBool(index) {
2112
    const op = this.remove(index);
×
2113
    return op ? op.toBool() : false;
×
2114
  }
2115

2116
  setBool(index, value) {
2117
    return this.set(index, Opcode.fromBool(value));
×
2118
  }
2119

2120
  pushBool(value) {
2121
    return this.push(Opcode.fromBool(value));
×
2122
  }
2123

2124
  unshiftBool(value) {
2125
    return this.unshift(Opcode.fromBool(value));
×
2126
  }
2127

2128
  insertBool(index, value) {
2129
    return this.insert(index, Opcode.fromBool(value));
×
2130
  }
2131

2132
  /*
2133
   * Symbol
2134
   */
2135

2136
  getSym(index) {
2137
    const op = this.get(index);
×
2138
    return op ? op.toSymbol() : null;
×
2139
  }
2140

2141
  popSym() {
2142
    const op = this.pop();
×
2143
    return op ? op.toSymbol() : null;
×
2144
  }
2145

2146
  shiftSym() {
2147
    const op = this.shift();
×
2148
    return op ? op.toSymbol() : null;
×
2149
  }
2150

2151
  removeSym(index) {
2152
    const op = this.remove(index);
×
2153
    return op ? op.toSymbol() : null;
×
2154
  }
2155

2156
  setSym(index, symbol) {
2157
    return this.set(index, Opcode.fromSymbol(symbol));
×
2158
  }
2159

2160
  pushSym(symbol) {
2161
    return this.push(Opcode.fromSymbol(symbol));
×
2162
  }
2163

2164
  unshiftSym(symbol) {
2165
    return this.unshift(Opcode.fromSymbol(symbol));
×
2166
  }
2167

2168
  insertSym(index, symbol) {
2169
    return this.insert(index, Opcode.fromSymbol(symbol));
×
2170
  }
2171

2172
  /**
2173
   * Inject properties from bitcoind test string.
2174
   * @private
2175
   * @param {String} items - Script string.
2176
   * @throws Parse error.
2177
   */
2178

2179
  fromString(code) {
2180
    assert(typeof code === 'string');
875✔
2181

2182
    code = code.trim();
875✔
2183

2184
    if (code.length === 0)
875✔
2185
      return this;
4✔
2186

2187
    const items = code.split(/\s+/);
871✔
2188
    const bw = bio.write();
871✔
2189

2190
    for (const item of items) {
871✔
2191
      let symbol = item;
8,281✔
2192

2193
      if (symbol.charCodeAt(0) & 32)
8,281✔
2194
        symbol = symbol.toUpperCase();
1,690✔
2195

2196
      if (!/^OP_/.test(symbol))
8,281✔
2197
        symbol = `OP_${symbol}`;
1,690✔
2198

2199
      const value = opcodes[symbol];
8,281✔
2200

2201
      if (value == null) {
8,281✔
2202
        if (item[0] === '\'') {
1,690!
2203
          assert(item[item.length - 1] === '\'', 'Invalid string.');
×
2204
          const str = item.slice(1, -1);
×
2205
          const op = Opcode.fromString(str);
×
2206
          bw.writeBytes(op.encode());
×
2207
          continue;
×
2208
        }
2209

2210
        if (/^-?\d+$/.test(item)) {
1,690✔
2211
          const num = ScriptNum.fromString(item, 10);
1,253✔
2212
          const op = Opcode.fromNum(num);
1,253✔
2213
          bw.writeBytes(op.encode());
1,253✔
2214
          continue;
1,253✔
2215
        }
2216

2217
        assert(item.indexOf('0x') === 0, 'Unknown opcode.');
437✔
2218

2219
        const hex = item.substring(2);
437✔
2220
        const data = Buffer.from(hex, 'hex');
437✔
2221

2222
        assert(data.length === hex.length / 2, 'Invalid hex string.');
437✔
2223

2224
        bw.writeBytes(data);
437✔
2225

2226
        continue;
437✔
2227
      }
2228

2229
      bw.writeU8(value);
6,591✔
2230
    }
2231

2232
    return this.decode(bw.render());
871✔
2233
  }
2234

2235
  /**
2236
   * Verify an input and output script, and a witness if present.
2237
   * @param {Witness} witness
2238
   * @param {Address} addr
2239
   * @param {TX} tx
2240
   * @param {Number} index
2241
   * @param {Amount} value
2242
   * @param {VerifyFlags} flags
2243
   * @throws {ScriptError}
2244
   */
2245

2246
  static verify(witness, addr, tx, index, value, flags) {
2247
    if (flags == null)
22,513✔
2248
      flags = Script.flags.STANDARD_VERIFY_FLAGS;
89✔
2249

2250
    assert(addr.version <= 31);
22,513✔
2251

2252
    if (addr.version === 31)
22,513!
2253
      throw new ScriptError('OP_RETURN');
×
2254

2255
    if (witness.items.length > consensus.MAX_SCRIPT_STACK)
22,513!
2256
      throw new ScriptError('STACK_SIZE');
×
2257

2258
    const stack = witness.toStack();
22,513✔
2259

2260
    let redeem = null;
22,513✔
2261

2262
    if (addr.version === 0) {
22,513!
2263
      if (addr.hash.length === 32) {
22,513✔
2264
        if (stack.length === 0)
2,917!
2265
          throw new ScriptError('WITNESS_PROGRAM_WITNESS_EMPTY');
×
2266

2267
        const witnessScript = stack.pop();
2,917✔
2268

2269
        if (witnessScript.length > consensus.MAX_SCRIPT_SIZE)
2,917!
2270
          throw new ScriptError('SCRIPT_SIZE');
×
2271

2272
        if (!sha3.digest(witnessScript).equals(addr.hash))
2,917✔
2273
          throw new ScriptError('WITNESS_PROGRAM_MISMATCH');
1✔
2274

2275
        redeem = Script.decode(witnessScript);
2,916✔
2276
      } else if (addr.hash.length === 20) {
19,596!
2277
        if (stack.length !== 2)
19,596✔
2278
          throw new ScriptError('WITNESS_PROGRAM_MISMATCH');
3✔
2279

2280
        redeem = Script.fromPubkeyhash(addr.hash);
19,593✔
2281
      } else {
2282
        // Failure on version=0 (bad program data length).
2283
        throw new ScriptError('WITNESS_PROGRAM_WRONG_LENGTH');
×
2284
      }
2285
    } else {
2286
      if (flags & Script.flags.VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)
×
2287
        throw new ScriptError('DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM');
×
2288
      return;
×
2289
    }
2290

2291
    // Witnesses still have push limits.
2292
    for (let j = 0; j < stack.length; j++) {
22,509✔
2293
      if (stack.get(j).length > consensus.MAX_SCRIPT_PUSH)
41,794!
2294
        throw new ScriptError('PUSH_SIZE');
×
2295
    }
2296

2297
    // Verify the redeem script.
2298
    redeem.execute(stack, flags, tx, index, value);
22,509✔
2299

2300
    // Verify the stack values.
2301
    if (stack.length !== 1 || !stack.getBool(-1))
22,153✔
2302
      throw new ScriptError('EVAL_FALSE');
132✔
2303
  }
2304

2305
  /**
2306
   * Inject properties from buffer reader.
2307
   * @private
2308
   * @param {BufferReader} br
2309
   */
2310

2311
  read(br) {
2312
    return this.decode(br.readVarBytes());
×
2313
  }
2314

2315
  /**
2316
   * Inject properties from serialized data.
2317
   * @private
2318
   * @param {Buffer}
2319
   */
2320

2321
  decode(data) {
2322
    const br = bio.read(data);
8,218✔
2323

2324
    this.raw = data;
8,218✔
2325

2326
    while (br.left())
8,218✔
2327
      this.code.push(Opcode.read(br));
436,491✔
2328

2329
    return this;
8,218✔
2330
  }
2331

2332
  /**
2333
   * Test whether an object a Script.
2334
   * @param {Object} obj
2335
   * @returns {Boolean}
2336
   */
2337

2338
  static isScript(obj) {
2339
    return obj instanceof Script;
×
2340
  }
2341
}
2342

2343
/**
2344
 * Script opcodes.
2345
 * @enum {Number}
2346
 * @default
2347
 */
2348

2349
Script.opcodes = common.opcodes;
68✔
2350

2351
/**
2352
 * Opcodes by value.
2353
 * @const {RevMap}
2354
 */
2355

2356
Script.opcodesByVal = common.opcodesByVal;
68✔
2357

2358
/**
2359
 * Script and locktime flags. See {@link VerifyFlags}.
2360
 * @enum {Number}
2361
 */
2362

2363
Script.flags = common.flags;
68✔
2364

2365
/**
2366
 * Sighash Types.
2367
 * @enum {SighashType}
2368
 * @default
2369
 */
2370

2371
Script.hashType = common.hashType;
68✔
2372

2373
/**
2374
 * Sighash types by value.
2375
 * @const {RevMap}
2376
 */
2377

2378
Script.hashTypeByVal = common.hashTypeByVal;
68✔
2379

2380
/**
2381
 * Output script types.
2382
 * @enum {Number}
2383
 */
2384

2385
Script.types = common.types;
68✔
2386

2387
/**
2388
 * Output script types by value.
2389
 * @const {RevMap}
2390
 */
2391

2392
Script.typesByVal = common.typesByVal;
68✔
2393

2394
/*
2395
 * Helpers
2396
 */
2397

2398
function sortKeys(keys) {
2399
  return keys.slice().sort((a, b) => {
3,301✔
2400
    return a.compare(b);
5,983✔
2401
  });
2402
}
2403

2404
/**
2405
 * Test whether the data element is a valid key if VERIFY_STRICTENC is enabled.
2406
 * @param {Buffer} key
2407
 * @param {VerifyFlags?} flags
2408
 * @returns {Boolean}
2409
 * @throws {ScriptError}
2410
 */
2411

2412
function validateKey(key, flags) {
2413
  assert(Buffer.isBuffer(key));
19,624✔
2414
  assert(typeof flags === 'number');
19,624✔
2415

2416
  if (!common.isKeyEncoding(key))
19,624✔
2417
    throw new ScriptError('PUBKEY_ENCODING');
6✔
2418

2419
  return true;
19,618✔
2420
}
2421

2422
/**
2423
 * Test whether the data element is a valid signature based
2424
 * on the encoding, S value, and sighash type. Requires
2425
 * VERIFY_DERSIG|VERIFY_LOW_S|VERIFY_STRICTENC, VERIFY_LOW_S
2426
 * and VERIFY_STRING_ENC to be enabled respectively. Note that
2427
 * this will allow zero-length signatures.
2428
 * @param {Buffer} sig
2429
 * @param {VerifyFlags?} flags
2430
 * @returns {Boolean}
2431
 * @throws {ScriptError}
2432
 */
2433

2434
function validateSignature(sig, flags) {
2435
  assert(Buffer.isBuffer(sig));
19,711✔
2436
  assert(typeof flags === 'number');
19,711✔
2437

2438
  // Allow empty sigs
2439
  if (sig.length === 0)
19,711✔
2440
    return true;
21✔
2441

2442
  if (!common.isSignatureEncoding(sig))
19,690✔
2443
    throw new ScriptError('SIG_ENCODING');
87✔
2444

2445
  return true;
19,603✔
2446
}
2447

2448
/**
2449
 * Verify a signature, taking into account sighash type.
2450
 * @param {Buffer} msg - Signature hash.
2451
 * @param {Buffer} sig
2452
 * @param {Buffer} key
2453
 * @returns {Boolean}
2454
 */
2455

2456
function checksig(msg, sig, key) {
2457
  return secp256k1.verify(msg, sig.slice(0, -1), key);
19,603✔
2458
}
2459

2460
/*
2461
 * Expose
2462
 */
2463

2464
module.exports = Script;
68✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc