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

handshake-org / hsd / 12515507044

27 Dec 2024 11:26AM UTC coverage: 71.242% (-0.02%) from 71.265%
12515507044

push

github

nodech
Merge PR #914 from 'nodech/add-mid-checkpoint'

8053 of 13154 branches covered (61.22%)

Branch coverage included in aggregate %.

25712 of 34241 relevant lines covered (75.09%)

34514.12 hits per line

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

63.63
/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
/** @typedef {import('@handshake-org/bfilter').BloomFilter} BloomFilter */
31
/** @typedef {import('../types').BufioWriter} BufioWriter */
32
/** @typedef {import('../types').SighashType} SighashType */
33
/** @typedef {import('../types').VerifyFlags} VerifyFlags */
34
/** @typedef {import('../types').Amount} AmountValue */
35
/** @typedef {import('../types').Hash} Hash */
36
/** @typedef {import('./witness')} Witness */
37
/** @typedef {import('../primitives/address')} Address */
38
/** @typedef {import('../primitives/tx')} TX */
39

40
/*
41
 * Constants
42
 */
43

44
const EMPTY_BUFFER = Buffer.alloc(0);
68✔
45

46
/**
47
 * Script
48
 * Represents a input or output script.
49
 * @alias module:script.Script
50
 * @property {Array} code - Parsed script code.
51
 * @property {Buffer?} raw - Serialized script.
52
 * @property {Number} length - Number of parsed opcodes.
53
 */
54

55
class Script extends bio.Struct {
56
  /**
57
   * Create a script.
58
   * @constructor
59
   * @param {Object?} [options]
60
   */
61

62
  constructor(options) {
63
    super();
141,462✔
64

65
    this.raw = EMPTY_BUFFER;
141,462✔
66
    /** @type {Opcode[]} */
67
    this.code = [];
141,462✔
68

69
    if (options)
141,462✔
70
      this.fromOptions(options);
39✔
71
  }
72

73
  /**
74
   * Get length.
75
   * @returns {Number}
76
   */
77

78
  get length() {
79
    return this.code.length;
×
80
  }
81

82
  /**
83
   * Set length.
84
   * @param {Number} value
85
   */
86

87
  set length(value) {
88
    this.code.length = value;
×
89
  }
90

91
  /**
92
   * Inject properties from options object.
93
   * @param {Object} options
94
   * @returns {this}
95
   */
96

97
  fromOptions(options) {
98
    assert(options, 'Script data is required.');
39✔
99

100
    if (Buffer.isBuffer(options))
39!
101
      return this.decode(options);
×
102

103
    if (Array.isArray(options))
39!
104
      return this.fromArray(options);
39✔
105

106
    if (options.raw) {
×
107
      if (!options.code)
×
108
        return this.decode(options.raw);
×
109
      assert(Buffer.isBuffer(options.raw), 'Raw must be a Buffer.');
×
110
      this.raw = options.raw;
×
111
    }
112

113
    if (options.code) {
×
114
      if (!options.raw)
×
115
        return this.fromArray(options.code);
×
116
      assert(Array.isArray(options.code), 'Code must be an array.');
×
117
      this.code = options.code;
×
118
    }
119

120
    return this;
×
121
  }
122

123
  /**
124
   * Instantiate a value-only iterator.
125
   */
126

127
  values() {
128
    return this.code.values();
×
129
  }
130

131
  /**
132
   * Instantiate a key and value iterator.
133
   */
134

135
  entries() {
136
    return this.code.entries();
×
137
  }
138

139
  /**
140
   * Instantiate a value-only iterator.
141
   */
142

143
  [Symbol.iterator]() {
144
    return this.code[Symbol.iterator]();
×
145
  }
146

147
  /**
148
   * Convert the script to an array of
149
   * Buffers (pushdatas) and Numbers
150
   * (opcodes).
151
   * @returns {Array}
152
   */
153

154
  toArray() {
155
    return this.code.slice();
×
156
  }
157

158
  /**
159
   * Inject properties from an array of
160
   * of buffers and numbers.
161
   * @param {Opcode[]} code
162
   * @returns {this}
163
   */
164

165
  fromArray(code) {
166
    assert(Array.isArray(code));
39✔
167

168
    this.clear();
39✔
169

170
    for (const op of code)
39✔
171
      this.push(op);
133✔
172

173
    return this.compile();
39✔
174
  }
175

176
  /**
177
   * Instantiate script from an array
178
   * of buffers and numbers.
179
   * @param {Opcode[]} code
180
   * @returns {Script}
181
   */
182

183
  static fromArray(code) {
184
    return new this().fromArray(code);
×
185
  }
186

187
  /**
188
   * Convert script to stack items.
189
   * @returns {Buffer[]}
190
   */
191

192
  toItems() {
193
    const items = [];
×
194

195
    for (const op of this.code) {
×
196
      const data = op.toPush();
×
197

198
      if (!data)
×
199
        throw new Error('Non-push opcode in script.');
×
200

201
      items.push(data);
×
202
    }
203

204
    return items;
×
205
  }
206

207
  /**
208
   * Inject data from stack items.
209
   * @param {Buffer[]} items
210
   * @returns {this}
211
   */
212

213
  fromItems(items) {
214
    assert(Array.isArray(items));
×
215

216
    this.clear();
×
217

218
    for (const item of items)
×
219
      this.pushData(item);
×
220

221
    return this.compile();
×
222
  }
223

224
  /**
225
   * Instantiate script from stack items.
226
   * @param {Buffer[]} items
227
   * @returns {Script}
228
   */
229

230
  static fromItems(items) {
231
    return new this().fromItems(items);
×
232
  }
233

234
  /**
235
   * Convert script to stack.
236
   * @returns {Stack}
237
   */
238

239
  toStack() {
240
    return new Stack(this.toItems());
×
241
  }
242

243
  /**
244
   * Inject data from stack.
245
   * @param {Stack} stack
246
   * @returns {this}
247
   */
248

249
  fromStack(stack) {
250
    return this.fromItems(stack.items);
×
251
  }
252

253
  /**
254
   * Instantiate script from stack.
255
   * @param {Stack} stack
256
   * @returns {Script}
257
   */
258

259
  static fromStack(stack) {
260
    return new this().fromStack(stack);
×
261
  }
262

263
  /**
264
   * Inject properties from script.
265
   * Used for cloning.
266
   * @param {this} script
267
   * @returns {this}
268
   */
269

270
  inject(script) {
271
    this.raw = script.raw;
23,901✔
272
    this.code = script.code.slice();
23,901✔
273
    return this;
23,901✔
274
  }
275

276
  /**
277
   * Test equality against script.
278
   * @param {Script} script
279
   * @returns {Boolean}
280
   */
281

282
  equals(script) {
283
    assert(Script.isScript(script));
×
284
    return this.raw.equals(script.raw);
×
285
  }
286

287
  /**
288
   * Compare against another script.
289
   * @param {Script} script
290
   * @returns {Number}
291
   */
292

293
  compare(script) {
294
    assert(Script.isScript(script));
×
295
    return this.raw.compare(script.raw);
×
296
  }
297

298
  /**
299
   * Clear the script.
300
   * @returns {this}
301
   */
302

303
  clear() {
304
    this.raw = EMPTY_BUFFER;
3,361✔
305
    this.code.length = 0;
3,361✔
306
    return this;
3,361✔
307
  }
308

309
  /**
310
   * Inspect the script.
311
   * @returns {String} Human-readable script code.
312
   */
313

314
  format() {
315
    return `<Script: ${this.toString()}>`;
×
316
  }
317

318
  /**
319
   * Convert the script to a bitcoind test string.
320
   * @returns {String} Human-readable script code.
321
   */
322

323
  toString() {
324
    const out = [];
×
325

326
    for (const op of this.code)
×
327
      out.push(op.toFormat());
×
328

329
    return out.join(' ');
×
330
  }
331

332
  /**
333
   * Format the script as bitcoind asm.
334
   * @param {Boolean?} decode - Attempt to decode hash types.
335
   * @returns {String} Human-readable script.
336
   */
337

338
  toASM(decode) {
339
    const out = [];
×
340

341
    for (const op of this.code)
×
342
      out.push(op.toASM(decode));
×
343

344
    return out.join(' ');
×
345
  }
346

347
  /**
348
   * Re-encode the script internally. Useful if you
349
   * changed something manually in the `code` array.
350
   */
351

352
  compile() {
353
    if (this.code.length === 0)
3,362!
354
      return this.clear();
×
355

356
    let size = 0;
3,362✔
357

358
    for (const op of this.code)
3,362✔
359
      size += op.getSize();
18,084✔
360

361
    const bw = bio.write(size);
3,362✔
362

363
    for (const op of this.code)
3,362✔
364
      op.write(bw);
18,084✔
365

366
    this.raw = bw.render();
3,362✔
367

368
    return this;
3,362✔
369
  }
370

371
  /**
372
   * Write the script to a buffer writer.
373
   * @param {BufioWriter} bw
374
   * @returns {BufioWriter}
375
   */
376

377
  write(bw) {
378
    bw.writeVarBytes(this.raw);
×
379
    return bw;
×
380
  }
381

382
  /**
383
   * Encode the script to a Buffer. See {@link Script#encode}.
384
   * @returns {Buffer} Serialized script.
385
   */
386

387
  encode() {
388
    return this.raw;
61,215✔
389
  }
390

391
  /**
392
   * Convert script to a hex string.
393
   * @returns {String}
394
   */
395

396
  getJSON() {
397
    return this.toHex();
×
398
  }
399

400
  /**
401
   * Inject properties from json object.
402
   * @param {String} json
403
   */
404

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

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

416
  getSubscript(index) {
417
    if (index === 0)
23,901!
418
      return this.clone();
23,901✔
419

420
    /** @type {this} */
421
    const script = new Script();
×
422

423
    for (let i = index; i < this.code.length; i++) {
×
424
      const op = this.code[i];
×
425

426
      if (op.value === -1)
×
427
        break;
×
428

429
      script.code.push(op);
×
430
    }
431

432
    return script.compile();
×
433
  }
434

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

443
  removeSeparators() {
444
    let found = false;
×
445

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

452
      if (op.value === opcodes.OP_CODESEPARATOR) {
×
453
        found = true;
×
454
        break;
×
455
      }
456
    }
457

458
    if (!found)
×
459
      return this;
×
460

461
    // Uncommon case: someone actually
462
    // has a code separator. Go through
463
    // and remove them all.
464
    /** @type {this} */
465
    const script = new Script();
×
466

467
    for (const op of this.code) {
×
468
      if (op.value === -1)
×
469
        break;
×
470

471
      if (op.value !== opcodes.OP_CODESEPARATOR)
×
472
        script.code.push(op);
×
473
    }
474

475
    return script.compile();
×
476
  }
477

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

488
  execute(stack, flags, tx, index, value) {
489
    if (flags == null)
26,589✔
490
      flags = Script.flags.STANDARD_VERIFY_FLAGS;
173✔
491

492
    if (this.raw.length > consensus.MAX_SCRIPT_SIZE)
26,589!
493
      throw new ScriptError('SCRIPT_SIZE');
×
494

495
    const state = [];
26,589✔
496
    const alt = [];
26,589✔
497

498
    let lastSep = 0;
26,589✔
499
    let opCount = 0;
26,589✔
500
    let negate = 0;
26,589✔
501
    let minimal = false;
26,589✔
502

503
    if (flags & Script.flags.VERIFY_MINIMALDATA)
26,589✔
504
      minimal = true;
25,808✔
505

506
    for (let ip = 0; ip < this.code.length; ip++) {
26,589✔
507
      const op = this.code[ip];
208,292✔
508

509
      if (op.value === -1)
208,292!
510
        throw new ScriptError('BAD_OPCODE', op, ip);
×
511

512
      if (op.data && op.data.length > consensus.MAX_SCRIPT_PUSH)
208,292✔
513
        throw new ScriptError('PUSH_SIZE', op, ip);
1✔
514

515
      if (op.value > opcodes.OP_16 && ++opCount > consensus.MAX_SCRIPT_OPS)
208,291✔
516
        throw new ScriptError('OP_COUNT', op, ip);
2✔
517

518
      if (op.isDisabled())
208,289✔
519
        throw new ScriptError('DISABLED_OPCODE', op, ip);
7✔
520

521
      if (negate && !op.isBranch()) {
208,282✔
522
        if (stack.length + alt.length > consensus.MAX_SCRIPT_STACK)
80,545!
523
          throw new ScriptError('STACK_SIZE', op, ip);
×
524
        continue;
80,545✔
525
      }
526

527
      if (op.data) {
127,737✔
528
        if (minimal && !op.isMinimal())
25,100!
529
          throw new ScriptError('MINIMALDATA', op, ip);
×
530

531
        stack.push(op.data);
25,100✔
532

533
        if (stack.length + alt.length > consensus.MAX_SCRIPT_STACK)
25,100!
534
          throw new ScriptError('STACK_SIZE', op, ip);
×
535

536
        continue;
25,100✔
537
      }
538

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

574
          if (index >= tx.outputs.length) {
27!
575
            stack.pushInt(0);
×
576
            break;
×
577
          }
578

579
          const {covenant} = tx.outputs[index];
27✔
580

581
          stack.pushInt(covenant.type);
27✔
582

583
          break;
27✔
584
        }
585
        case opcodes.OP_CHECKLOCKTIMEVERIFY: {
586
          if (!tx)
4!
587
            throw new ScriptError('UNKNOWN_ERROR', 'No TX passed in.');
×
588

589
          if (stack.length === 0)
4!
590
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
591

592
          const num = stack.getNum(-1, minimal, 5);
4✔
593

594
          if (num.isNeg())
4✔
595
            throw new ScriptError('NEGATIVE_LOCKTIME', op, ip);
1✔
596

597
          const locktime = num.toDouble();
3✔
598

599
          if (!tx.verifyLocktime(index, locktime))
3!
600
            throw new ScriptError('UNSATISFIED_LOCKTIME', op, ip);
3✔
601

602
          break;
×
603
        }
604
        case opcodes.OP_CHECKSEQUENCEVERIFY: {
605
          if (!tx)
11!
606
            throw new ScriptError('UNKNOWN_ERROR', 'No TX passed in.');
×
607

608
          if (stack.length === 0)
11✔
609
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
610

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

613
          if (num.isNeg())
9✔
614
            throw new ScriptError('NEGATIVE_LOCKTIME', op, ip);
1✔
615

616
          const locktime = num.toDouble();
8✔
617

618
          if (!tx.verifySequence(index, locktime))
8✔
619
            throw new ScriptError('UNSATISFIED_LOCKTIME', op, ip);
5✔
620

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

639
          if (!negate) {
1,051✔
640
            if (stack.length < 1)
1,037!
641
              throw new ScriptError('UNBALANCED_CONDITIONAL', op, ip);
×
642

643
            if (flags & Script.flags.VERIFY_MINIMALIF) {
1,037✔
644
              const item = stack.get(-1);
815✔
645

646
              if (item.length > 1)
815✔
647
                throw new ScriptError('MINIMALIF');
2✔
648

649
              if (item.length === 1 && item[0] !== 1)
813✔
650
                throw new ScriptError('MINIMALIF');
4✔
651
            }
652

653
            val = stack.getBool(-1);
1,031✔
654

655
            if (op.value === opcodes.OP_NOTIF)
1,031✔
656
              val = !val;
20✔
657

658
            stack.pop();
1,031✔
659
          }
660

661
          state.push(val);
1,045✔
662

663
          if (!val)
1,045✔
664
            negate += 1;
128✔
665

666
          break;
1,045✔
667
        }
668
        case opcodes.OP_ELSE: {
669
          if (state.length === 0)
1,030✔
670
            throw new ScriptError('UNBALANCED_CONDITIONAL', op, ip);
3✔
671

672
          state[state.length - 1] = !state[state.length - 1];
1,027✔
673

674
          if (!state[state.length - 1])
1,027✔
675
            negate += 1;
873✔
676
          else
677
            negate -= 1;
154✔
678

679
          break;
1,027✔
680
        }
681
        case opcodes.OP_ENDIF: {
682
          if (state.length === 0)
965✔
683
            throw new ScriptError('UNBALANCED_CONDITIONAL', op, ip);
6✔
684

685
          if (!state.pop())
959✔
686
            negate -= 1;
837✔
687

688
          break;
959✔
689
        }
690
        case opcodes.OP_VERIFY: {
691
          if (stack.length === 0)
29!
692
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
693

694
          if (!stack.getBool(-1))
29✔
695
            throw new ScriptError('VERIFY', op, ip);
1✔
696

697
          stack.pop();
28✔
698

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

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

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

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

730
          const v1 = stack.get(-2);
2✔
731
          const v2 = stack.get(-1);
2✔
732

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

741
          const v1 = stack.get(-3);
2✔
742
          const v2 = stack.get(-2);
2✔
743
          const v3 = stack.get(-1);
2✔
744

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

754
          const v1 = stack.get(-4);
2✔
755
          const v2 = stack.get(-3);
2✔
756

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

765
          const v1 = stack.get(-6);
12✔
766
          const v2 = stack.get(-5);
12✔
767

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

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

785
          if (stack.getBool(-1)) {
1!
786
            const val = stack.get(-1);
1✔
787
            stack.push(val);
1✔
788
          }
789

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

800
          stack.pop();
66✔
801
          break;
66✔
802
        }
803
        case opcodes.OP_DUP: {
804
          if (stack.length === 0)
23,512!
805
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
806

807
          stack.push(stack.get(-1));
23,512✔
808
          break;
23,512✔
809
        }
810
        case opcodes.OP_NIP: {
811
          if (stack.length < 2)
3✔
812
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
813

814
          stack.remove(-2);
2✔
815
          break;
2✔
816
        }
817
        case opcodes.OP_OVER: {
818
          if (stack.length < 2)
5✔
819
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
2✔
820

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

829
          const num = stack.getInt(-1, minimal, 4);
26✔
830
          stack.pop();
24✔
831

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

835
          const val = stack.get(-num - 1);
19✔
836

837
          if (op.value === opcodes.OP_ROLL)
19✔
838
            stack.remove(-num - 1);
10✔
839

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

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

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

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

869
          stack.pushInt(stack.get(-1).length);
29✔
870
          break;
29✔
871
        }
872
        case opcodes.OP_EQUAL:
873
        case opcodes.OP_EQUALVERIFY: {
874
          if (stack.length < 2)
23,927✔
875
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
4✔
876

877
          const v1 = stack.get(-2);
23,923✔
878
          const v2 = stack.get(-1);
23,923✔
879

880
          const res = v1.equals(v2);
23,923✔
881

882
          stack.pop();
23,923✔
883
          stack.pop();
23,923✔
884

885
          stack.pushBool(res);
23,923✔
886

887
          if (op.value === opcodes.OP_EQUALVERIFY) {
23,923✔
888
            if (!res)
23,535✔
889
              throw new ScriptError('EQUALVERIFY', op, ip);
8✔
890
            stack.pop();
23,527✔
891
          }
892

893
          break;
23,915✔
894
        }
895
        case opcodes.OP_1ADD:
896
        case opcodes.OP_1SUB:
897
        case opcodes.OP_NEGATE:
898
        case opcodes.OP_ABS:
899
        case opcodes.OP_NOT:
900
        case opcodes.OP_0NOTEQUAL: {
901
          if (stack.length < 1)
93!
902
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
903

904
          let num = stack.getNum(-1, minimal, 4);
93✔
905
          let cmp;
906

907
          switch (op.value) {
70!
908
            case opcodes.OP_1ADD:
909
              num.iaddn(1);
11✔
910
              break;
11✔
911
            case opcodes.OP_1SUB:
912
              num.isubn(1);
7✔
913
              break;
7✔
914
            case opcodes.OP_NEGATE:
915
              num.ineg();
8✔
916
              break;
8✔
917
            case opcodes.OP_ABS:
918
              num.iabs();
7✔
919
              break;
7✔
920
            case opcodes.OP_NOT:
921
              cmp = num.isZero();
30✔
922
              num = ScriptNum.fromBool(cmp);
30✔
923
              break;
30✔
924
            case opcodes.OP_0NOTEQUAL:
925
              cmp = !num.isZero();
7✔
926
              num = ScriptNum.fromBool(cmp);
7✔
927
              break;
7✔
928
            default:
929
              assert(false, 'Fatal script error.');
×
930
              break;
×
931
          }
932

933
          stack.pop();
70✔
934
          stack.pushNum(num);
70✔
935

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

954
          const n1 = stack.getNum(-2, minimal, 4);
238✔
955
          const n2 = stack.getNum(-1, minimal, 4);
223✔
956

957
          let num, cmp;
958

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

1013
          stack.pop();
210✔
1014
          stack.pop();
210✔
1015
          stack.pushNum(num);
210✔
1016

1017
          if (op.value === opcodes.OP_NUMEQUALVERIFY) {
210✔
1018
            if (!stack.getBool(-1))
3!
1019
              throw new ScriptError('NUMEQUALVERIFY', op, ip);
×
1020
            stack.pop();
3✔
1021
          }
1022

1023
          break;
210✔
1024
        }
1025
        case opcodes.OP_WITHIN: {
1026
          if (stack.length < 3)
26✔
1027
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
1028

1029
          const n1 = stack.getNum(-3, minimal, 4);
25✔
1030
          const n2 = stack.getNum(-2, minimal, 4);
24✔
1031
          const n3 = stack.getNum(-1, minimal, 4);
23✔
1032

1033
          const val = n2.lte(n1) && n1.lt(n3);
22✔
1034

1035
          stack.pop();
22✔
1036
          stack.pop();
22✔
1037
          stack.pop();
22✔
1038

1039
          stack.pushBool(val);
22✔
1040
          break;
22✔
1041
        }
1042
        case opcodes.OP_RIPEMD160: {
1043
          if (stack.length === 0)
5!
1044
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
1045

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

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

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

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

1074
          stack.push(hash256.digest(stack.pop()));
5✔
1075
          break;
5✔
1076
        }
1077
        case opcodes.OP_BLAKE160: {
1078
          if (stack.length === 0)
23,500✔
1079
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
1080

1081
          stack.push(blake2b.digest(stack.pop(), 20));
23,499✔
1082
          break;
23,499✔
1083
        }
1084
        case opcodes.OP_BLAKE256: {
1085
          if (stack.length === 0)
1!
1086
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
1087

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

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

1102
          stack.push(keccak.digest(stack.pop()));
×
1103
          break;
×
1104
        }
1105
        case opcodes.OP_CODESEPARATOR: {
1106
          lastSep = ip + 1;
×
1107
          break;
×
1108
        }
1109
        case opcodes.OP_CHECKSIG:
1110
        case opcodes.OP_CHECKSIGVERIFY: {
1111
          if (!tx)
23,564!
1112
            throw new ScriptError('UNKNOWN_ERROR', 'No TX passed in.');
×
1113

1114
          if (stack.length < 2)
23,564✔
1115
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
2✔
1116

1117
          const sig = stack.get(-2);
23,562✔
1118
          const key = stack.get(-1);
23,562✔
1119

1120
          const subscript = this.getSubscript(lastSep);
23,562✔
1121

1122
          validateSignature(sig, flags);
23,562✔
1123
          validateKey(key, flags);
23,501✔
1124

1125
          let res = false;
23,501✔
1126

1127
          if (sig.length > 0) {
23,501✔
1128
            const type = sig[sig.length - 1];
23,494✔
1129
            const hash = tx.signatureHash(
23,494✔
1130
              index,
1131
              subscript,
1132
              value,
1133
              type
1134
            );
1135
            res = checksig(hash, sig, key);
23,494✔
1136
          }
1137

1138
          if (!res && (flags & Script.flags.VERIFY_NULLFAIL)) {
23,501✔
1139
            if (sig.length !== 0)
3✔
1140
              throw new ScriptError('NULLFAIL', op, ip);
1✔
1141
          }
1142

1143
          stack.pop();
23,500✔
1144
          stack.pop();
23,500✔
1145

1146
          stack.pushBool(res);
23,500✔
1147

1148
          if (op.value === opcodes.OP_CHECKSIGVERIFY) {
23,500!
1149
            if (!res)
×
1150
              throw new ScriptError('CHECKSIGVERIFY', op, ip);
×
1151
            stack.pop();
×
1152
          }
1153

1154
          break;
23,500✔
1155
        }
1156
        case opcodes.OP_CHECKMULTISIG:
1157
        case opcodes.OP_CHECKMULTISIGVERIFY: {
1158
          if (!tx)
353!
1159
            throw new ScriptError('UNKNOWN_ERROR', 'No TX passed in.');
×
1160

1161
          let i = 1;
353✔
1162
          if (stack.length < i)
353✔
1163
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
1164

1165
          let n = stack.getInt(-i, minimal, 4);
352✔
1166
          let okey = n + 2;
350✔
1167
          let ikey, isig;
1168

1169
          if (n < 0 || n > consensus.MAX_MULTISIG_PUBKEYS)
350✔
1170
            throw new ScriptError('PUBKEY_COUNT', op, ip);
2✔
1171

1172
          opCount += n;
348✔
1173

1174
          if (opCount > consensus.MAX_SCRIPT_OPS)
348✔
1175
            throw new ScriptError('OP_COUNT', op, ip);
2✔
1176

1177
          i += 1;
346✔
1178
          ikey = i;
346✔
1179
          i += n;
346✔
1180

1181
          if (stack.length < i)
346✔
1182
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
1183

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

1186
          if (m < 0 || m > n)
342✔
1187
            throw new ScriptError('SIG_COUNT', op, ip);
2✔
1188

1189
          i += 1;
340✔
1190
          isig = i;
340✔
1191
          i += m;
340✔
1192

1193
          if (stack.length < i)
340✔
1194
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
1✔
1195

1196
          const subscript = this.getSubscript(lastSep);
339✔
1197

1198
          let res = true;
339✔
1199
          while (res && m > 0) {
339✔
1200
            const sig = stack.get(-isig);
55✔
1201
            const key = stack.get(-ikey);
55✔
1202

1203
            validateSignature(sig, flags);
55✔
1204
            validateKey(key, flags);
29✔
1205

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

1215
              if (checksig(hash, sig, key)) {
15✔
1216
                isig += 1;
14✔
1217
                m -= 1;
14✔
1218
              }
1219
            }
1220

1221
            ikey += 1;
23✔
1222
            n -= 1;
23✔
1223

1224
            if (m > n)
23✔
1225
              res = false;
7✔
1226
          }
1227

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

1234
            if (okey > 0)
1,776✔
1235
              okey -= 1;
1,748✔
1236

1237
            stack.pop();
1,776✔
1238

1239
            i -= 1;
1,776✔
1240
          }
1241

1242
          if (stack.length < 1)
307!
1243
            throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
×
1244

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

1248
          stack.pop();
303✔
1249

1250
          stack.pushBool(res);
303✔
1251

1252
          if (op.value === opcodes.OP_CHECKMULTISIGVERIFY) {
303✔
1253
            if (!res)
245!
1254
              throw new ScriptError('CHECKMULTISIGVERIFY', op, ip);
×
1255
            stack.pop();
245✔
1256
          }
1257

1258
          break;
303✔
1259
        }
1260
        default: {
1261
          throw new ScriptError('BAD_OPCODE', op, ip);
78✔
1262
        }
1263
      }
1264

1265
      if (stack.length + alt.length > consensus.MAX_SCRIPT_STACK)
102,291!
1266
        throw new ScriptError('STACK_SIZE', op, ip);
×
1267
    }
1268

1269
    if (state.length !== 0)
26,233✔
1270
      throw new ScriptError('UNBALANCED_CONDITIONAL');
1✔
1271
  }
1272

1273
  /**
1274
   * Find a data element in a script.
1275
   * @param {Buffer} data - Data element to match against.
1276
   * @returns {Number} Index (`-1` if not present).
1277
   */
1278

1279
  indexOf(data) {
1280
    for (let i = 0; i < this.code.length; i++) {
5✔
1281
      const op = this.code[i];
13✔
1282

1283
      if (op.value === -1)
13!
1284
        break;
×
1285

1286
      if (!op.data)
13✔
1287
        continue;
5✔
1288

1289
      if (op.data.equals(data))
8✔
1290
        return i;
5✔
1291
    }
1292

1293
    return -1;
×
1294
  }
1295

1296
  /**
1297
   * Test a script to see if it is likely
1298
   * to be script code (no weird opcodes).
1299
   * @returns {Boolean}
1300
   */
1301

1302
  isCode() {
1303
    for (const op of this.code) {
×
1304
      if (op.value === -1)
×
1305
        return false;
×
1306

1307
      if (op.isDisabled())
×
1308
        return false;
×
1309

1310
      switch (op.value) {
×
1311
        case opcodes.OP_RESERVED:
1312
        case opcodes.OP_NOP:
1313
        case opcodes.OP_VER:
1314
        case opcodes.OP_VERIF:
1315
        case opcodes.OP_VERNOTIF:
1316
        case opcodes.OP_RESERVED1:
1317
        case opcodes.OP_RESERVED2:
1318
          return false;
×
1319
      }
1320

1321
      if (op.value > opcodes.OP_CHECKSEQUENCEVERIFY)
×
1322
        return false;
×
1323
    }
1324

1325
    return true;
×
1326
  }
1327

1328
  /**
1329
   * Inject properties from a pay-to-pubkey script.
1330
   * @param {Buffer} key
1331
   * @returns {this}
1332
   */
1333

1334
  fromPubkey(key) {
1335
    assert(Buffer.isBuffer(key) && key.length === 33);
×
1336

1337
    this.raw = Buffer.allocUnsafe(35);
×
1338
    this.raw[0] = 33;
×
1339
    key.copy(this.raw, 1);
×
1340
    this.raw[34] = opcodes.OP_CHECKSIG;
×
1341

1342
    key = this.raw.slice(1, 34);
×
1343

1344
    this.code.length = 0;
×
1345
    this.code.push(Opcode.fromPush(key));
×
1346
    this.code.push(Opcode.fromOp(opcodes.OP_CHECKSIG));
×
1347

1348
    return this;
×
1349
  }
1350

1351
  /**
1352
   * Create a pay-to-pubkey script.
1353
   * @param {Buffer} key
1354
   * @returns {Script}
1355
   */
1356

1357
  static fromPubkey(key) {
1358
    return new this().fromPubkey(key);
×
1359
  }
1360

1361
  /**
1362
   * Inject properties from a pay-to-pubkeyhash script.
1363
   * @private
1364
   * @param {Buffer} hash
1365
   */
1366

1367
  fromPubkeyhash(hash) {
1368
    assert(Buffer.isBuffer(hash) && hash.length === 20);
105,816✔
1369

1370
    this.raw = Buffer.allocUnsafe(25);
105,816✔
1371
    this.raw[0] = opcodes.OP_DUP;
105,816✔
1372
    this.raw[1] = opcodes.OP_BLAKE160;
105,816✔
1373
    this.raw[2] = 0x14;
105,816✔
1374
    hash.copy(this.raw, 3);
105,816✔
1375
    this.raw[23] = opcodes.OP_EQUALVERIFY;
105,816✔
1376
    this.raw[24] = opcodes.OP_CHECKSIG;
105,816✔
1377

1378
    hash = this.raw.slice(3, 23);
105,816✔
1379

1380
    this.code.length = 0;
105,816✔
1381
    this.code.push(Opcode.fromOp(opcodes.OP_DUP));
105,816✔
1382
    this.code.push(Opcode.fromOp(opcodes.OP_BLAKE160));
105,816✔
1383
    this.code.push(Opcode.fromPush(hash));
105,816✔
1384
    this.code.push(Opcode.fromOp(opcodes.OP_EQUALVERIFY));
105,816✔
1385
    this.code.push(Opcode.fromOp(opcodes.OP_CHECKSIG));
105,816✔
1386

1387
    return this;
105,816✔
1388
  }
1389

1390
  /**
1391
   * Create a pay-to-pubkeyhash script.
1392
   * @param {Buffer} hash
1393
   * @returns {Script}
1394
   */
1395

1396
  static fromPubkeyhash(hash) {
1397
    return new this().fromPubkeyhash(hash);
105,816✔
1398
  }
1399

1400
  /**
1401
   * Inject properties from pay-to-multisig script.
1402
   * @private
1403
   * @param {Number} m
1404
   * @param {Number} n
1405
   * @param {Buffer[]} keys
1406
   */
1407

1408
  fromMultisig(m, n, keys) {
1409
    assert((m & 0xff) === m && (n & 0xff) === n);
3,322✔
1410
    assert(Array.isArray(keys));
3,322✔
1411
    assert(keys.length === n, '`n` keys are required for multisig.');
3,322✔
1412
    assert(m >= 1 && m <= n);
3,322✔
1413
    assert(n >= 1 && n <= 15);
3,322✔
1414

1415
    this.clear();
3,322✔
1416

1417
    this.pushSmall(m);
3,322✔
1418

1419
    for (const key of sortKeys(keys))
3,322✔
1420
      this.pushData(key);
7,880✔
1421

1422
    this.pushSmall(n);
3,322✔
1423
    this.pushOp(opcodes.OP_CHECKMULTISIG);
3,322✔
1424

1425
    return this.compile();
3,322✔
1426
  }
1427

1428
  /**
1429
   * Create a pay-to-multisig script.
1430
   * @param {Number} m
1431
   * @param {Number} n
1432
   * @param {Buffer[]} keys
1433
   * @returns {Script}
1434
   */
1435

1436
  static fromMultisig(m, n, keys) {
1437
    return new this().fromMultisig(m, n, keys);
3,322✔
1438
  }
1439

1440
  /**
1441
   * Get the standard script type.
1442
   * @returns {common.types}
1443
   */
1444

1445
  getType() {
1446
    if (this.isPubkey())
×
1447
      return scriptTypes.PUBKEY;
×
1448

1449
    if (this.isPubkeyhash())
×
1450
      return scriptTypes.PUBKEYHASH;
×
1451

1452
    if (this.isMultisig())
×
1453
      return scriptTypes.MULTISIG;
×
1454

1455
    return scriptTypes.NONSTANDARD;
×
1456
  }
1457

1458
  /**
1459
   * Test whether a script is of an unknown/non-standard type.
1460
   * @returns {Boolean}
1461
   */
1462

1463
  isUnknown() {
1464
    return this.getType() === scriptTypes.NONSTANDARD;
×
1465
  }
1466

1467
  /**
1468
   * Test whether the script is standard by policy standards.
1469
   * @returns {Boolean}
1470
   */
1471

1472
  isStandard() {
1473
    const [m, n] = this.getMultisig();
×
1474

1475
    if (m !== -1) {
×
1476
      if (n < 1 || n > 3)
×
1477
        return false;
×
1478

1479
      if (m < 1 || m > n)
×
1480
        return false;
×
1481

1482
      return true;
×
1483
    }
1484

1485
    return this.getType() !== scriptTypes.NONSTANDARD;
×
1486
  }
1487

1488
  /**
1489
   * Calculate the size of the script
1490
   * excluding the varint size bytes.
1491
   * @returns {Number}
1492
   */
1493

1494
  getSize() {
1495
    return this.raw.length;
×
1496
  }
1497

1498
  /**
1499
   * Calculate the size of the script
1500
   * including the varint size bytes.
1501
   * @returns {Number}
1502
   */
1503

1504
  getVarSize() {
1505
    return encoding.sizeVarBytes(this.raw);
53,282✔
1506
  }
1507

1508
  /**
1509
   * Get the sha3 of the raw script.
1510
   * @returns {Hash}
1511
   */
1512

1513
  sha3() {
1514
    return sha3.digest(this.encode());
3,322✔
1515
  }
1516

1517
  /**
1518
   * Test whether the output script is pay-to-pubkey.
1519
   * @param {Boolean} [minimal=false] - Minimaldata only.
1520
   * @returns {Boolean}
1521
   */
1522

1523
  isPubkey(minimal) {
1524
    if (minimal) {
82,320!
1525
      return this.raw.length === 35
×
1526
        && this.raw[0] === 33
1527
        && this.raw[0] + 2 === this.raw.length
1528
        && this.raw[this.raw.length - 1] === opcodes.OP_CHECKSIG;
1529
    }
1530

1531
    if (this.code.length !== 2)
82,320!
1532
      return false;
82,320✔
1533

1534
    return this.getLength(0) === 33
×
1535
      && this.getOp(1) === opcodes.OP_CHECKSIG;
1536
  }
1537

1538
  /**
1539
   * Get P2PK key if present.
1540
   * @param {Boolean} [minimal=false] - Minimaldata only.
1541
   * @returns {Buffer|null}
1542
   */
1543

1544
  getPubkey(minimal) {
1545
    if (!this.isPubkey(minimal))
59,049!
1546
      return null;
59,049✔
1547

1548
    if (minimal)
×
1549
      return this.raw.slice(1, 1 + this.raw[0]);
×
1550

1551
    return this.getData(0);
×
1552
  }
1553

1554
  /**
1555
   * Test whether the output script is pay-to-pubkeyhash.
1556
   * @param {Boolean} [minimal=false] - Minimaldata only.
1557
   * @returns {Boolean}
1558
   */
1559

1560
  isPubkeyhash(minimal) {
1561
    if (minimal || this.raw.length === 25) {
82,320✔
1562
      return this.raw.length === 25
82,307✔
1563
        && this.raw[0] === opcodes.OP_DUP
1564
        && this.raw[1] === opcodes.OP_BLAKE160
1565
        && this.raw[2] === 0x14
1566
        && this.raw[23] === opcodes.OP_EQUALVERIFY
1567
        && this.raw[24] === opcodes.OP_CHECKSIG;
1568
    }
1569

1570
    if (this.code.length !== 5)
13✔
1571
      return false;
3✔
1572

1573
    return this.getOp(0) === opcodes.OP_DUP
10!
1574
      && this.getOp(1) === opcodes.OP_BLAKE160
1575
      && this.getLength(2) === 20
1576
      && this.getOp(3) === opcodes.OP_EQUALVERIFY
1577
      && this.getOp(4) === opcodes.OP_CHECKSIG;
1578
  }
1579

1580
  /**
1581
   * Get P2PKH hash if present.
1582
   * @param {Boolean} [minimal=false] - Minimaldata only.
1583
   * @returns {Buffer|null}
1584
   */
1585

1586
  getPubkeyhash(minimal) {
1587
    if (!this.isPubkeyhash(minimal))
59,049✔
1588
      return null;
13✔
1589

1590
    if (minimal)
59,036!
1591
      return this.raw.slice(3, 23);
×
1592

1593
    return this.getData(2);
59,036✔
1594
  }
1595

1596
  /**
1597
   * Test whether the output script is pay-to-multisig.
1598
   * @param {Boolean} [minimal=false] - Minimaldata only.
1599
   * @returns {Boolean}
1600
   */
1601

1602
  isMultisig(minimal) {
1603
    if (this.code.length < 4 || this.code.length > 19)
13!
1604
      return false;
×
1605

1606
    if (this.getOp(-1) !== opcodes.OP_CHECKMULTISIG)
13!
1607
      return false;
×
1608

1609
    const m = this.getSmall(0);
13✔
1610

1611
    if (m < 1)
13!
1612
      return false;
×
1613

1614
    const n = this.getSmall(-2);
13✔
1615

1616
    if (n < 1 || m > n)
13!
1617
      return false;
×
1618

1619
    if (this.code.length !== n + 3)
13!
1620
      return false;
×
1621

1622
    for (let i = 1; i < n + 1; i++) {
13✔
1623
      const op = this.code[i];
29✔
1624

1625
      if (op.toLength() !== 33)
29!
1626
        return false;
×
1627

1628
      if (minimal && !op.isMinimal())
29!
1629
        return false;
×
1630
    }
1631

1632
    return true;
13✔
1633
  }
1634

1635
  /**
1636
   * Get multisig m and n values if present.
1637
   * @param {Boolean} [minimal=false] - Minimaldata only.
1638
   * @returns {Array} [m, n]
1639
   */
1640

1641
  getMultisig(minimal) {
1642
    if (!this.isMultisig(minimal))
13!
1643
      return [-1, -1];
×
1644

1645
    return [this.getSmall(0), this.getSmall(-2)];
13✔
1646
  }
1647

1648
  /**
1649
   * Test whether the output script is unspendable.
1650
   * @returns {Boolean}
1651
   */
1652

1653
  isUnspendable() {
1654
    if (this.raw.length > consensus.MAX_SCRIPT_SIZE)
×
1655
      return true;
×
1656

1657
    return this.raw.length > 0 && this.raw[0] === opcodes.OP_RETURN;
×
1658
  }
1659

1660
  /**
1661
   * Test the script against a bloom filter.
1662
   * @param {BloomFilter} filter
1663
   * @returns {Boolean}
1664
   */
1665

1666
  test(filter) {
1667
    for (const op of this.code) {
×
1668
      if (op.value === -1)
×
1669
        break;
×
1670

1671
      if (!op.data || op.data.length === 0)
×
1672
        continue;
×
1673

1674
      if (filter.test(op.data))
×
1675
        return true;
×
1676
    }
1677

1678
    return false;
×
1679
  }
1680

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

1687
  isPushOnly() {
1688
    for (const op of this.code) {
×
1689
      if (op.value === -1)
×
1690
        return false;
×
1691

1692
      if (op.value > opcodes.OP_16)
×
1693
        return false;
×
1694
    }
1695

1696
    return true;
×
1697
  }
1698

1699
  /**
1700
   * Count the sigops in the script.
1701
   * @returns {Number} sigop count
1702
   */
1703

1704
  getSigops() {
1705
    let total = 0;
4,421✔
1706
    let lastOp = -1;
4,421✔
1707

1708
    for (const op of this.code) {
4,421✔
1709
      if (op.value === -1)
336,061!
1710
        break;
×
1711

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

1726
      lastOp = op.value;
336,061✔
1727
    }
1728

1729
    return total;
4,421✔
1730
  }
1731

1732
  /*
1733
   * Mutation
1734
   */
1735

1736
  get(index) {
1737
    if (index < 0)
59,111✔
1738
      index += this.code.length;
39✔
1739

1740
    if (index < 0 || index >= this.code.length)
59,111!
1741
      return null;
×
1742

1743
    return this.code[index];
59,111✔
1744
  }
1745

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

1751
  shift() {
1752
    const op = this.code.shift();
×
1753
    return op || null;
×
1754
  }
1755

1756
  remove(index) {
1757
    if (index < 0)
×
1758
      index += this.code.length;
×
1759

1760
    if (index < 0 || index >= this.code.length)
×
1761
      return null;
×
1762

1763
    const items = this.code.splice(index, 1);
×
1764

1765
    if (items.length === 0)
×
1766
      return null;
×
1767

1768
    return items[0];
×
1769
  }
1770

1771
  set(index, op) {
1772
    if (index < 0)
×
1773
      index += this.code.length;
×
1774

1775
    assert(Opcode.isOpcode(op));
×
1776
    assert(index >= 0 && index <= this.code.length);
×
1777

1778
    this.code[index] = op;
×
1779

1780
    return this;
×
1781
  }
1782

1783
  push(op) {
1784
    assert(Opcode.isOpcode(op));
18,084✔
1785
    this.code.push(op);
18,084✔
1786
    return this;
18,084✔
1787
  }
1788

1789
  unshift(op) {
1790
    assert(Opcode.isOpcode(op));
×
1791
    this.code.unshift(op);
×
1792
    return this;
×
1793
  }
1794

1795
  insert(index, op) {
1796
    if (index < 0)
×
1797
      index += this.code.length;
×
1798

1799
    assert(Opcode.isOpcode(op));
×
1800
    assert(index >= 0 && index <= this.code.length);
×
1801

1802
    this.code.splice(index, 0, op);
×
1803

1804
    return this;
×
1805
  }
1806

1807
  /*
1808
   * Op
1809
   */
1810

1811
  getOp(index) {
1812
    const op = this.get(index);
23✔
1813
    return op ? op.value : -1;
23!
1814
  }
1815

1816
  popOp() {
1817
    const op = this.pop();
×
1818
    return op ? op.value : -1;
×
1819
  }
1820

1821
  shiftOp() {
1822
    const op = this.shift();
×
1823
    return op ? op.value : -1;
×
1824
  }
1825

1826
  removeOp(index) {
1827
    const op = this.remove(index);
×
1828
    return op ? op.value : -1;
×
1829
  }
1830

1831
  setOp(index, value) {
1832
    return this.set(index, Opcode.fromOp(value));
×
1833
  }
1834

1835
  pushOp(value) {
1836
    return this.push(Opcode.fromOp(value));
3,427✔
1837
  }
1838

1839
  unshiftOp(value) {
1840
    return this.unshift(Opcode.fromOp(value));
×
1841
  }
1842

1843
  insertOp(index, value) {
1844
    return this.insert(index, Opcode.fromOp(value));
×
1845
  }
1846

1847
  /*
1848
   * Data
1849
   */
1850

1851
  getData(index) {
1852
    const op = this.get(index);
59,036✔
1853
    return op ? op.data : null;
59,036!
1854
  }
1855

1856
  popData() {
1857
    const op = this.pop();
×
1858
    return op ? op.data : null;
×
1859
  }
1860

1861
  shiftData() {
1862
    const op = this.shift();
×
1863
    return op ? op.data : null;
×
1864
  }
1865

1866
  removeData(index) {
1867
    const op = this.remove(index);
×
1868
    return op ? op.data : null;
×
1869
  }
1870

1871
  setData(index, data) {
1872
    return this.set(index, Opcode.fromData(data));
×
1873
  }
1874

1875
  pushData(data) {
1876
    return this.push(Opcode.fromData(data));
7,880✔
1877
  }
1878

1879
  unshiftData(data) {
1880
    return this.unshift(Opcode.fromData(data));
×
1881
  }
1882

1883
  insertData(index, data) {
1884
    return this.insert(index, Opcode.fromData(data));
×
1885
  }
1886

1887
  /*
1888
   * Length
1889
   */
1890

1891
  getLength(index) {
1892
    const op = this.get(index);
×
1893
    return op ? op.toLength() : -1;
×
1894
  }
1895

1896
  /*
1897
   * Push
1898
   */
1899

1900
  getPush(index) {
1901
    const op = this.get(index);
×
1902
    return op ? op.toPush() : null;
×
1903
  }
1904

1905
  popPush() {
1906
    const op = this.pop();
×
1907
    return op ? op.toPush() : null;
×
1908
  }
1909

1910
  shiftPush() {
1911
    const op = this.shift();
×
1912
    return op ? op.toPush() : null;
×
1913
  }
1914

1915
  removePush(index) {
1916
    const op = this.remove(index);
×
1917
    return op ? op.toPush() : null;
×
1918
  }
1919

1920
  setPush(index, data) {
1921
    return this.set(index, Opcode.fromPush(data));
×
1922
  }
1923

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

1928
  unshiftPush(data) {
1929
    return this.unshift(Opcode.fromPush(data));
×
1930
  }
1931

1932
  insertPush(index, data) {
1933
    return this.insert(index, Opcode.fromPush(data));
×
1934
  }
1935

1936
  /*
1937
   * String
1938
   */
1939

1940
  getString(index, enc) {
1941
    const op = this.get(index);
×
1942
    return op ? op.toString(enc) : null;
×
1943
  }
1944

1945
  popString(enc) {
1946
    const op = this.pop();
×
1947
    return op ? op.toString(enc) : null;
×
1948
  }
1949

1950
  shiftString(enc) {
1951
    const op = this.shift();
×
1952
    return op ? op.toString(enc) : null;
×
1953
  }
1954

1955
  removeString(index, enc) {
1956
    const op = this.remove(index);
×
1957
    return op ? op.toString(enc) : null;
×
1958
  }
1959

1960
  setString(index, str, enc) {
1961
    return this.set(index, Opcode.fromString(str, enc));
×
1962
  }
1963

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

1968
  unshiftString(str, enc) {
1969
    return this.unshift(Opcode.fromString(str, enc));
×
1970
  }
1971

1972
  insertString(index, str, enc) {
1973
    return this.insert(index, Opcode.fromString(str, enc));
×
1974
  }
1975

1976
  /*
1977
   * Small
1978
   */
1979

1980
  getSmall(index) {
1981
    const op = this.get(index);
52✔
1982
    return op ? op.toSmall() : -1;
52!
1983
  }
1984

1985
  popSmall() {
1986
    const op = this.pop();
×
1987
    return op ? op.toSmall() : -1;
×
1988
  }
1989

1990
  shiftSmall() {
1991
    const op = this.shift();
×
1992
    return op ? op.toSmall() : -1;
×
1993
  }
1994

1995
  removeSmall(index) {
1996
    const op = this.remove(index);
×
1997
    return op ? op.toSmall() : -1;
×
1998
  }
1999

2000
  setSmall(index, num) {
2001
    return this.set(index, Opcode.fromSmall(num));
×
2002
  }
2003

2004
  pushSmall(num) {
2005
    return this.push(Opcode.fromSmall(num));
6,644✔
2006
  }
2007

2008
  unshiftSmall(num) {
2009
    return this.unshift(Opcode.fromSmall(num));
×
2010
  }
2011

2012
  insertSmall(index, num) {
2013
    return this.insert(index, Opcode.fromSmall(num));
×
2014
  }
2015

2016
  /*
2017
   * Num
2018
   */
2019

2020
  getNum(index, minimal, limit) {
2021
    const op = this.get(index);
×
2022
    return op ? op.toNum(minimal, limit) : null;
×
2023
  }
2024

2025
  popNum(minimal, limit) {
2026
    const op = this.pop();
×
2027
    return op ? op.toNum(minimal, limit) : null;
×
2028
  }
2029

2030
  shiftNum(minimal, limit) {
2031
    const op = this.shift();
×
2032
    return op ? op.toNum(minimal, limit) : null;
×
2033
  }
2034

2035
  removeNum(index, minimal, limit) {
2036
    const op = this.remove(index);
×
2037
    return op ? op.toNum(minimal, limit) : null;
×
2038
  }
2039

2040
  setNum(index, num) {
2041
    return this.set(index, Opcode.fromNum(num));
×
2042
  }
2043

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

2048
  unshiftNum(num) {
2049
    return this.unshift(Opcode.fromNum(num));
×
2050
  }
2051

2052
  insertNum(index, num) {
2053
    return this.insert(index, Opcode.fromNum(num));
×
2054
  }
2055

2056
  /*
2057
   * Int
2058
   */
2059

2060
  getInt(index, minimal, limit) {
2061
    const op = this.get(index);
×
2062
    return op ? op.toInt(minimal, limit) : -1;
×
2063
  }
2064

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

2070
  shiftInt(minimal, limit) {
2071
    const op = this.shift();
×
2072
    return op ? op.toInt(minimal, limit) : -1;
×
2073
  }
2074

2075
  removeInt(index, minimal, limit) {
2076
    const op = this.remove(index);
×
2077
    return op ? op.toInt(minimal, limit) : -1;
×
2078
  }
2079

2080
  setInt(index, num) {
2081
    return this.set(index, Opcode.fromInt(num));
×
2082
  }
2083

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

2088
  unshiftInt(num) {
2089
    return this.unshift(Opcode.fromInt(num));
×
2090
  }
2091

2092
  insertInt(index, num) {
2093
    return this.insert(index, Opcode.fromInt(num));
×
2094
  }
2095

2096
  /*
2097
   * Bool
2098
   */
2099

2100
  getBool(index) {
2101
    const op = this.get(index);
×
2102
    return op ? op.toBool() : false;
×
2103
  }
2104

2105
  popBool() {
2106
    const op = this.pop();
×
2107
    return op ? op.toBool() : false;
×
2108
  }
2109

2110
  shiftBool() {
2111
    const op = this.shift();
×
2112
    return op ? op.toBool() : false;
×
2113
  }
2114

2115
  removeBool(index) {
2116
    const op = this.remove(index);
×
2117
    return op ? op.toBool() : false;
×
2118
  }
2119

2120
  setBool(index, value) {
2121
    return this.set(index, Opcode.fromBool(value));
×
2122
  }
2123

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

2128
  unshiftBool(value) {
2129
    return this.unshift(Opcode.fromBool(value));
×
2130
  }
2131

2132
  insertBool(index, value) {
2133
    return this.insert(index, Opcode.fromBool(value));
×
2134
  }
2135

2136
  /*
2137
   * Symbol
2138
   */
2139

2140
  getSym(index) {
2141
    const op = this.get(index);
×
2142
    return op ? op.toSymbol() : null;
×
2143
  }
2144

2145
  popSym() {
2146
    const op = this.pop();
×
2147
    return op ? op.toSymbol() : null;
×
2148
  }
2149

2150
  shiftSym() {
2151
    const op = this.shift();
×
2152
    return op ? op.toSymbol() : null;
×
2153
  }
2154

2155
  removeSym(index) {
2156
    const op = this.remove(index);
×
2157
    return op ? op.toSymbol() : null;
×
2158
  }
2159

2160
  setSym(index, symbol) {
2161
    return this.set(index, Opcode.fromSymbol(symbol));
×
2162
  }
2163

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

2168
  unshiftSym(symbol) {
2169
    return this.unshift(Opcode.fromSymbol(symbol));
×
2170
  }
2171

2172
  insertSym(index, symbol) {
2173
    return this.insert(index, Opcode.fromSymbol(symbol));
×
2174
  }
2175

2176
  /**
2177
   * Inject properties from bitcoind test string.
2178
   * @param {String} code - Script string.
2179
   * @throws Parse error.
2180
   */
2181

2182
  fromString(code) {
2183
    assert(typeof code === 'string');
1,033✔
2184

2185
    code = code.trim();
1,033✔
2186

2187
    if (code.length === 0)
1,033✔
2188
      return this;
4✔
2189

2190
    const items = code.split(/\s+/);
1,029✔
2191
    const bw = bio.write();
1,029✔
2192

2193
    for (const item of items) {
1,029✔
2194
      let symbol = item;
9,048✔
2195

2196
      if (symbol.charCodeAt(0) & 32)
9,048✔
2197
        symbol = symbol.toUpperCase();
2,426✔
2198

2199
      if (!/^OP_/.test(symbol))
9,048✔
2200
        symbol = `OP_${symbol}`;
2,426✔
2201

2202
      const value = opcodes[symbol];
9,048✔
2203

2204
      if (value == null) {
9,048✔
2205
        if (item[0] === '\'') {
1,883!
2206
          assert(item[item.length - 1] === '\'', 'Invalid string.');
×
2207
          const str = item.slice(1, -1);
×
2208
          const op = Opcode.fromString(str);
×
2209
          bw.writeBytes(op.encode());
×
2210
          continue;
×
2211
        }
2212

2213
        if (/^-?\d+$/.test(item)) {
1,883✔
2214
          const num = ScriptNum.fromString(item, 10);
1,446✔
2215
          const op = Opcode.fromNum(num);
1,446✔
2216
          bw.writeBytes(op.encode());
1,446✔
2217
          continue;
1,446✔
2218
        }
2219

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

2222
        const hex = item.substring(2);
437✔
2223
        const data = Buffer.from(hex, 'hex');
437✔
2224

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

2227
        bw.writeBytes(data);
437✔
2228

2229
        continue;
437✔
2230
      }
2231

2232
      bw.writeU8(value);
7,165✔
2233
    }
2234

2235
    return this.decode(bw.render());
1,029✔
2236
  }
2237

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

2249
  static verify(witness, addr, tx, index, value, flags) {
2250
    if (flags == null)
26,420✔
2251
      flags = Script.flags.STANDARD_VERIFY_FLAGS;
89✔
2252

2253
    assert(addr.version <= 31);
26,420✔
2254

2255
    if (addr.version === 31)
26,420!
2256
      throw new ScriptError('OP_RETURN');
×
2257

2258
    if (witness.items.length > consensus.MAX_SCRIPT_STACK)
26,420!
2259
      throw new ScriptError('STACK_SIZE');
×
2260

2261
    const stack = witness.toStack();
26,420✔
2262

2263
    let redeem = null;
26,420✔
2264

2265
    if (addr.version === 0) {
26,420!
2266
      if (addr.hash.length === 32) {
26,420✔
2267
        if (stack.length === 0)
2,918!
2268
          throw new ScriptError('WITNESS_PROGRAM_WITNESS_EMPTY');
×
2269

2270
        const witnessScript = stack.pop();
2,918✔
2271

2272
        if (witnessScript.length > consensus.MAX_SCRIPT_SIZE)
2,918!
2273
          throw new ScriptError('SCRIPT_SIZE');
×
2274

2275
        if (!sha3.digest(witnessScript).equals(addr.hash))
2,918✔
2276
          throw new ScriptError('WITNESS_PROGRAM_MISMATCH');
1✔
2277

2278
        redeem = Script.decode(witnessScript);
2,917✔
2279
      } else if (addr.hash.length === 20) {
23,502!
2280
        if (stack.length !== 2)
23,502✔
2281
          throw new ScriptError('WITNESS_PROGRAM_MISMATCH');
3✔
2282

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

2294
    // Witnesses still have push limits.
2295
    for (let j = 0; j < stack.length; j++) {
26,416✔
2296
      if (stack.get(j).length > consensus.MAX_SCRIPT_PUSH)
49,607!
2297
        throw new ScriptError('PUSH_SIZE');
×
2298
    }
2299

2300
    // Verify the redeem script.
2301
    redeem.execute(stack, flags, tx, index, value);
26,416✔
2302

2303
    // Verify the stack values.
2304
    if (stack.length !== 1 || !stack.getBool(-1))
26,059✔
2305
      throw new ScriptError('EVAL_FALSE');
132✔
2306
  }
2307

2308
  /**
2309
   * Inject properties from buffer reader.
2310
   * @param {bio.BufferReader} br
2311
   */
2312

2313
  read(br) {
2314
    return this.decode(br.readVarBytes());
×
2315
  }
2316

2317
  /**
2318
   * Inject properties from serialized data.
2319
   * @param {Buffer} data
2320
   * @returns {this}
2321
   */
2322

2323
  decode(data) {
2324
    const br = bio.read(data);
8,377✔
2325

2326
    this.raw = data;
8,377✔
2327

2328
    while (br.left())
8,377✔
2329
      this.code.push(Opcode.read(br));
437,259✔
2330

2331
    return this;
8,377✔
2332
  }
2333

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

2340
  static isScript(obj) {
2341
    return obj instanceof Script;
×
2342
  }
2343
}
2344

2345
/**
2346
 * Script opcodes.
2347
 * @enum {Number}
2348
 * @default
2349
 */
2350

2351
Script.opcodes = common.opcodes;
68✔
2352

2353
/**
2354
 * Opcodes by value.
2355
 * @const {RevMap}
2356
 */
2357

2358
Script.opcodesByVal = common.opcodesByVal;
68✔
2359

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

2365
Script.flags = common.flags;
68✔
2366

2367
/**
2368
 * Sighash Types.
2369
 * @enum {SighashType}
2370
 * @default
2371
 */
2372

2373
Script.hashType = common.hashType;
68✔
2374

2375
/**
2376
 * Sighash types by value.
2377
 * @const {RevMap}
2378
 */
2379

2380
Script.hashTypeByVal = common.hashTypeByVal;
68✔
2381

2382
/**
2383
 * Output script types.
2384
 * @enum {Number}
2385
 */
2386

2387
Script.types = common.types;
68✔
2388

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

2394
Script.typesByVal = common.typesByVal;
68✔
2395

2396
/*
2397
 * Helpers
2398
 */
2399

2400
function sortKeys(keys) {
2401
  return keys.slice().sort((a, b) => {
3,322✔
2402
    return a.compare(b);
6,008✔
2403
  });
2404
}
2405

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

2414
function validateKey(key, flags) {
2415
  assert(Buffer.isBuffer(key));
23,530✔
2416
  assert(typeof flags === 'number');
23,530✔
2417

2418
  if (!common.isKeyEncoding(key))
23,530✔
2419
    throw new ScriptError('PUBKEY_ENCODING');
6✔
2420

2421
  return true;
23,524✔
2422
}
2423

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

2436
function validateSignature(sig, flags) {
2437
  assert(Buffer.isBuffer(sig));
23,617✔
2438
  assert(typeof flags === 'number');
23,617✔
2439

2440
  // Allow empty sigs
2441
  if (sig.length === 0)
23,617✔
2442
    return true;
21✔
2443

2444
  if (!common.isSignatureEncoding(sig))
23,596✔
2445
    throw new ScriptError('SIG_ENCODING');
87✔
2446

2447
  return true;
23,509✔
2448
}
2449

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

2458
function checksig(msg, sig, key) {
2459
  return secp256k1.verify(msg, sig.slice(0, -1), key);
23,509✔
2460
}
2461

2462
/*
2463
 * Expose
2464
 */
2465

2466
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