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

handshake-org / hsd / 11895505322

18 Nov 2024 03:21PM UTC coverage: 71.265% (+1.2%) from 70.033%
11895505322

Pull #888

github

web-flow
Merge a914b01ee into 1b331eedb
Pull Request #888: Wallet TX Count and time indexing

8052 of 13150 branches covered (61.23%)

Branch coverage included in aggregate %.

826 of 885 new or added lines in 16 files covered. (93.33%)

2063 existing lines in 60 files now uncovered.

25720 of 34239 relevant lines covered (75.12%)

34512.26 hits per line

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

57.89
/lib/script/common.js
1
/*!
2
 * common.js - common script functions 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
/**
10
 * @module script/common
11
 */
12

13
const assert = require('bsert');
68✔
14
const secp256k1 = require('bcrypto/lib/secp256k1');
68✔
15
const ScriptNum = require('./scriptnum');
68✔
16

17
/** @typedef {import('../types').SighashType} SighashType */
18
/** @typedef {import('../types').VerifyFlags} VerifyFlags */
19

20
/**
21
 * Opcodes by value.
22
 * @const {Object}
23
 */
24

25
exports.opcodes = {
68✔
26
  // Push
27
  OP_0: 0x00,
28

29
  OP_PUSHDATA1: 0x4c,
30
  OP_PUSHDATA2: 0x4d,
31
  OP_PUSHDATA4: 0x4e,
32

33
  OP_1NEGATE: 0x4f,
34

35
  OP_RESERVED: 0x50,
36

37
  OP_1: 0x51,
38
  OP_2: 0x52,
39
  OP_3: 0x53,
40
  OP_4: 0x54,
41
  OP_5: 0x55,
42
  OP_6: 0x56,
43
  OP_7: 0x57,
44
  OP_8: 0x58,
45
  OP_9: 0x59,
46
  OP_10: 0x5a,
47
  OP_11: 0x5b,
48
  OP_12: 0x5c,
49
  OP_13: 0x5d,
50
  OP_14: 0x5e,
51
  OP_15: 0x5f,
52
  OP_16: 0x60,
53

54
  // Control
55
  OP_NOP: 0x61,
56
  OP_VER: 0x62,
57
  OP_IF: 0x63,
58
  OP_NOTIF: 0x64,
59
  OP_VERIF: 0x65,
60
  OP_VERNOTIF: 0x66,
61
  OP_ELSE: 0x67,
62
  OP_ENDIF: 0x68,
63
  OP_VERIFY: 0x69,
64
  OP_RETURN: 0x6a,
65

66
  // Stack
67
  OP_TOALTSTACK: 0x6b,
68
  OP_FROMALTSTACK: 0x6c,
69
  OP_2DROP: 0x6d,
70
  OP_2DUP: 0x6e,
71
  OP_3DUP: 0x6f,
72
  OP_2OVER: 0x70,
73
  OP_2ROT: 0x71,
74
  OP_2SWAP: 0x72,
75
  OP_IFDUP: 0x73,
76
  OP_DEPTH: 0x74,
77
  OP_DROP: 0x75,
78
  OP_DUP: 0x76,
79
  OP_NIP: 0x77,
80
  OP_OVER: 0x78,
81
  OP_PICK: 0x79,
82
  OP_ROLL: 0x7a,
83
  OP_ROT: 0x7b,
84
  OP_SWAP: 0x7c,
85
  OP_TUCK: 0x7d,
86

87
  // Splice
88
  OP_CAT: 0x7e,
89
  OP_SUBSTR: 0x7f,
90
  OP_LEFT: 0x80,
91
  OP_RIGHT: 0x81,
92
  OP_SIZE: 0x82,
93

94
  // Bit
95
  OP_INVERT: 0x83,
96
  OP_AND: 0x84,
97
  OP_OR: 0x85,
98
  OP_XOR: 0x86,
99
  OP_EQUAL: 0x87,
100
  OP_EQUALVERIFY: 0x88,
101
  OP_RESERVED1: 0x89,
102
  OP_RESERVED2: 0x8a,
103

104
  // Numeric
105
  OP_1ADD: 0x8b,
106
  OP_1SUB: 0x8c,
107
  OP_2MUL: 0x8d,
108
  OP_2DIV: 0x8e,
109
  OP_NEGATE: 0x8f,
110
  OP_ABS: 0x90,
111
  OP_NOT: 0x91,
112
  OP_0NOTEQUAL: 0x92,
113
  OP_ADD: 0x93,
114
  OP_SUB: 0x94,
115
  OP_MUL: 0x95,
116
  OP_DIV: 0x96,
117
  OP_MOD: 0x97,
118
  OP_LSHIFT: 0x98,
119
  OP_RSHIFT: 0x99,
120
  OP_BOOLAND: 0x9a,
121
  OP_BOOLOR: 0x9b,
122
  OP_NUMEQUAL: 0x9c,
123
  OP_NUMEQUALVERIFY: 0x9d,
124
  OP_NUMNOTEQUAL: 0x9e,
125
  OP_LESSTHAN: 0x9f,
126
  OP_GREATERTHAN: 0xa0,
127
  OP_LESSTHANOREQUAL: 0xa1,
128
  OP_GREATERTHANOREQUAL: 0xa2,
129
  OP_MIN: 0xa3,
130
  OP_MAX: 0xa4,
131
  OP_WITHIN: 0xa5,
132

133
  // Crypto
134
  OP_RIPEMD160: 0xa6,
135
  OP_SHA1: 0xa7,
136
  OP_SHA256: 0xa8,
137
  OP_HASH160: 0xa9,
138
  OP_HASH256: 0xaa,
139
  OP_CODESEPARATOR: 0xab,
140
  OP_CHECKSIG: 0xac,
141
  OP_CHECKSIGVERIFY: 0xad,
142
  OP_CHECKMULTISIG: 0xae,
143
  OP_CHECKMULTISIGVERIFY: 0xaf,
144

145
  // Expansion
146
  OP_NOP1: 0xb0,
147
  OP_CHECKLOCKTIMEVERIFY: 0xb1,
148
  OP_CHECKSEQUENCEVERIFY: 0xb2,
149
  OP_NOP4: 0xb3,
150
  OP_NOP5: 0xb4,
151
  OP_NOP6: 0xb5,
152
  OP_NOP7: 0xb6,
153
  OP_NOP8: 0xb7,
154
  OP_NOP9: 0xb8,
155
  OP_NOP10: 0xb9,
156

157
  // More Crypto
158
  OP_BLAKE160: 0xc0,
159
  OP_BLAKE256: 0xc1,
160
  OP_SHA3: 0xc2,
161
  OP_KECCAK: 0xc3,
162

163
  // More Ops
164
  OP_TYPE: 0xd0,
165

166
  // Custom
167
  OP_INVALIDOPCODE: 0xff
168
};
169

170
/**
171
 * Opcodes by value.
172
 * @const {Object}
173
 */
174

175
exports.opcodesByVal = {
68✔
176
  // Push
177
  0x00: 'OP_0',
178

179
  0x4c: 'OP_PUSHDATA1',
180
  0x4d: 'OP_PUSHDATA2',
181
  0x4e: 'OP_PUSHDATA4',
182

183
  0x4f: 'OP_1NEGATE',
184

185
  0x50: 'OP_RESERVED',
186

187
  0x51: 'OP_1',
188
  0x52: 'OP_2',
189
  0x53: 'OP_3',
190
  0x54: 'OP_4',
191
  0x55: 'OP_5',
192
  0x56: 'OP_6',
193
  0x57: 'OP_7',
194
  0x58: 'OP_8',
195
  0x59: 'OP_9',
196
  0x5a: 'OP_10',
197
  0x5b: 'OP_11',
198
  0x5c: 'OP_12',
199
  0x5d: 'OP_13',
200
  0x5e: 'OP_14',
201
  0x5f: 'OP_15',
202
  0x60: 'OP_16',
203

204
  // Control
205
  0x61: 'OP_NOP',
206
  0x62: 'OP_VER',
207
  0x63: 'OP_IF',
208
  0x64: 'OP_NOTIF',
209
  0x65: 'OP_VERIF',
210
  0x66: 'OP_VERNOTIF',
211
  0x67: 'OP_ELSE',
212
  0x68: 'OP_ENDIF',
213
  0x69: 'OP_VERIFY',
214
  0x6a: 'OP_RETURN',
215

216
  // Stack
217
  0x6b: 'OP_TOALTSTACK',
218
  0x6c: 'OP_FROMALTSTACK',
219
  0x6d: 'OP_2DROP',
220
  0x6e: 'OP_2DUP',
221
  0x6f: 'OP_3DUP',
222
  0x70: 'OP_2OVER',
223
  0x71: 'OP_2ROT',
224
  0x72: 'OP_2SWAP',
225
  0x73: 'OP_IFDUP',
226
  0x74: 'OP_DEPTH',
227
  0x75: 'OP_DROP',
228
  0x76: 'OP_DUP',
229
  0x77: 'OP_NIP',
230
  0x78: 'OP_OVER',
231
  0x79: 'OP_PICK',
232
  0x7a: 'OP_ROLL',
233
  0x7b: 'OP_ROT',
234
  0x7c: 'OP_SWAP',
235
  0x7d: 'OP_TUCK',
236

237
  // Splice
238
  0x7e: 'OP_CAT',
239
  0x7f: 'OP_SUBSTR',
240
  0x80: 'OP_LEFT',
241
  0x81: 'OP_RIGHT',
242
  0x82: 'OP_SIZE',
243

244
  // Bit
245
  0x83: 'OP_INVERT',
246
  0x84: 'OP_AND',
247
  0x85: 'OP_OR',
248
  0x86: 'OP_XOR',
249
  0x87: 'OP_EQUAL',
250
  0x88: 'OP_EQUALVERIFY',
251
  0x89: 'OP_RESERVED1',
252
  0x8a: 'OP_RESERVED2',
253

254
  // Numeric
255
  0x8b: 'OP_1ADD',
256
  0x8c: 'OP_1SUB',
257
  0x8d: 'OP_2MUL',
258
  0x8e: 'OP_2DIV',
259
  0x8f: 'OP_NEGATE',
260
  0x90: 'OP_ABS',
261
  0x91: 'OP_NOT',
262
  0x92: 'OP_0NOTEQUAL',
263
  0x93: 'OP_ADD',
264
  0x94: 'OP_SUB',
265
  0x95: 'OP_MUL',
266
  0x96: 'OP_DIV',
267
  0x97: 'OP_MOD',
268
  0x98: 'OP_LSHIFT',
269
  0x99: 'OP_RSHIFT',
270
  0x9a: 'OP_BOOLAND',
271
  0x9b: 'OP_BOOLOR',
272
  0x9c: 'OP_NUMEQUAL',
273
  0x9d: 'OP_NUMEQUALVERIFY',
274
  0x9e: 'OP_NUMNOTEQUAL',
275
  0x9f: 'OP_LESSTHAN',
276
  0xa0: 'OP_GREATERTHAN',
277
  0xa1: 'OP_LESSTHANOREQUAL',
278
  0xa2: 'OP_GREATERTHANOREQUAL',
279
  0xa3: 'OP_MIN',
280
  0xa4: 'OP_MAX',
281
  0xa5: 'OP_WITHIN',
282

283
  // Crypto
284
  0xa6: 'OP_RIPEMD160',
285
  0xa7: 'OP_SHA1',
286
  0xa8: 'OP_SHA256',
287
  0xa9: 'OP_HASH160',
288
  0xaa: 'OP_HASH256',
289
  0xab: 'OP_CODESEPARATOR',
290
  0xac: 'OP_CHECKSIG',
291
  0xad: 'OP_CHECKSIGVERIFY',
292
  0xae: 'OP_CHECKMULTISIG',
293
  0xaf: 'OP_CHECKMULTISIGVERIFY',
294

295
  // Expansion
296
  0xb0: 'OP_NOP1',
297
  0xb1: 'OP_CHECKLOCKTIMEVERIFY',
298
  0xb2: 'OP_CHECKSEQUENCEVERIFY',
299
  0xb3: 'OP_NOP4',
300
  0xb4: 'OP_NOP5',
301
  0xb5: 'OP_NOP6',
302
  0xb6: 'OP_NOP7',
303
  0xb7: 'OP_NOP8',
304
  0xb8: 'OP_NOP9',
305
  0xb9: 'OP_NOP10',
306

307
  // More Crypto
308
  0xc0: 'OP_BLAKE160',
309
  0xc1: 'OP_BLAKE256',
310
  0xc2: 'OP_SHA3',
311
  0xc3: 'OP_KECCAK',
312

313
  // More Ops
314
  0xd0: 'OP_TYPE',
315

316
  // Custom
317
  0xff: 'OP_INVALIDOPCODE'
318
};
319

320
/**
321
 * Small ints (1 indexed, 1==0).
322
 * @const {Buffer[]}
323
 */
324

325
exports.small = [
68✔
326
  Buffer.from([0x81]),
327
  Buffer.from([]),
328
  Buffer.from([0x01]),
329
  Buffer.from([0x02]),
330
  Buffer.from([0x03]),
331
  Buffer.from([0x04]),
332
  Buffer.from([0x05]),
333
  Buffer.from([0x06]),
334
  Buffer.from([0x07]),
335
  Buffer.from([0x08]),
336
  Buffer.from([0x09]),
337
  Buffer.from([0x0a]),
338
  Buffer.from([0x0b]),
339
  Buffer.from([0x0c]),
340
  Buffer.from([0x0d]),
341
  Buffer.from([0x0e]),
342
  Buffer.from([0x0f]),
343
  Buffer.from([0x10])
344
];
345

346
/**
347
 * Script and locktime flags. See {@link VerifyFlags}.
348
 * @enum {VerifyFlags}
349
 */
350

351
exports.flags = {
68✔
352
  VERIFY_NONE: 0,
353
  VERIFY_MINIMALDATA: 1 << 1,
354
  VERIFY_DISCOURAGE_UPGRADABLE_NOPS: 1 << 2,
355
  VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM: 1 << 3,
356
  VERIFY_MINIMALIF: 1 << 4,
357
  VERIFY_NULLFAIL: 1 << 5
358
};
359

360
/**
361
 * Consensus verify flags (used for block validation).
362
 * @const {VerifyFlags}
363
 * @default
364
 */
365

366
exports.flags.MANDATORY_VERIFY_FLAGS = 0
68✔
367
  | exports.flags.VERIFY_MINIMALDATA
368
  | exports.flags.VERIFY_MINIMALIF
369
  | exports.flags.VERIFY_NULLFAIL;
370

371
/**
372
 * Standard verify flags (used for mempool validation).
373
 * @const {VerifyFlags}
374
 * @default
375
 */
376

377
exports.flags.STANDARD_VERIFY_FLAGS = 0
68✔
378
  | exports.flags.MANDATORY_VERIFY_FLAGS
379
  | exports.flags.VERIFY_DISCOURAGE_UPGRADABLE_NOPS
380
  | exports.flags.VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM;
381

382
/**
383
 * Standard flags without mandatory bits.
384
 * @const {VerifyFlags}
385
 * @default
386
 */
387

388
exports.flags.ONLY_STANDARD_VERIFY_FLAGS =
68✔
389
  exports.flags.STANDARD_VERIFY_FLAGS & ~exports.flags.MANDATORY_VERIFY_FLAGS;
390

391
/**
392
 * Sighash Types.
393
 * @enum {SighashType}
394
 * @default
395
 */
396

397
exports.hashType = {
68✔
398
  /*
399
   * Sign all outputs.
400
   */
401

402
  ALL: 1,
403

404
  /*
405
   * Do not sign outputs (zero sequences).
406
   */
407

408
  NONE: 2,
409

410
  /*
411
   * Sign output at the same index (zero sequences).
412
   */
413

414
  SINGLE: 3,
415

416
  /*
417
   * Sign output at the reversed index (zero sequences).
418
   * Input at index 0 would sign the output at the last
419
   * index, input at index 1 would sign the second to
420
   * last index and so on.
421
   */
422

423
  SINGLEREVERSE: 4,
424

425
  /*
426
   * Sign no inputs.
427
   */
428

429
  NOINPUT: 0x40,
430

431
  /*
432
   * Sign only the current input (mask).
433
   */
434

435
  ANYONECANPAY: 0x80
436
};
437

438
/**
439
 * Sighash types by value.
440
 * @const {Object}
441
 */
442

443
exports.hashTypeByVal = {
68✔
444
  1: 'ALL',
445
  2: 'NONE',
446
  3: 'SINGLE',
447
  4: 'SINGLEREVERSE',
448
  0x40: 'NOINPUT',
449
  0x80: 'ANYONECANPAY'
450
};
451

452
/**
453
 * Output script types.
454
 * @enum {Number}
455
 */
456

457
exports.types = {
68✔
458
  NONSTANDARD: 0,
459
  PUBKEY: 1,
460
  PUBKEYHASH: 2,
461
  MULTISIG: 3
462
};
463

464
/**
465
 * Output script types by value.
466
 * @const {Object}
467
 */
468

469
exports.typesByVal = {
68✔
470
  0: 'NONSTANDARD',
471
  1: 'PUBKEY',
472
  2: 'PUBKEYHASH',
473
  3: 'MULTISIG'
474
};
475

476
/**
477
 * Test whether the data element is a compressed key.
478
 * @param {Buffer} key
479
 * @returns {Boolean}
480
 */
481

482
exports.isKeyEncoding = function isKeyEncoding(key) {
68✔
483
  assert(Buffer.isBuffer(key));
53,812✔
484

485
  if (key.length !== 33)
53,812✔
486
    return false;
6✔
487

488
  if (key[0] !== 0x02 && key[0] !== 0x03)
53,806!
UNCOV
489
    return false;
×
490

491
  return true;
53,806✔
492
};
493

494
/**
495
 * Test a signature to see if it abides by BIP66.
496
 * @see https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki
497
 * @param {Buffer} sig
498
 * @returns {Boolean}
499
 */
500

501
exports.isSignatureEncoding = function isSignatureEncoding(sig) {
68✔
502
  assert(Buffer.isBuffer(sig));
59,944✔
503

504
  if (sig.length !== 65)
59,944✔
505
    return false;
6,149✔
506

507
  let type = sig[64];
53,795✔
508

509
  type &= ~exports.hashType.NOINPUT;
53,795✔
510
  type &= ~exports.hashType.ANYONECANPAY;
53,795✔
511

512
  if (type < exports.hashType.ALL || type > exports.hashType.SINGLEREVERSE)
53,795✔
513
    return false;
5✔
514

515
  if (!secp256k1.isLowS(sig.slice(0, -1)))
53,790!
UNCOV
516
    return false;
×
517

518
  return true;
53,790✔
519
};
520

521
/**
522
 * Format stack item into bitcoind asm format.
523
 * @param {Buffer} item
524
 * @param {Boolean?} decode - Attempt to decode hash types.
525
 * @returns {String} Human-readable string.
526
 */
527

528
exports.toASM = function toASM(item, decode) {
68✔
UNCOV
529
  if (item.length <= 4) {
×
UNCOV
530
    const num = ScriptNum.decode(item);
×
531
    return num.toString(10);
×
532
  }
533

534
  if (decode && exports.isSignatureEncoding(item)) {
×
UNCOV
535
    const type = item[item.length - 1];
×
536

537
    let symbol = exports.hashTypeByVal[type & 0x1f] || '';
×
538

UNCOV
539
    if (symbol) {
×
540
      if (type & exports.hashType.NOINPUT)
×
541
        symbol += '|NOINPUT';
×
542

543
      if (type & exports.hashType.ANYONECANPAY)
×
UNCOV
544
        symbol += '|ANYONECANPAY';
×
545

546
      symbol = `[${symbol}]`;
×
547
    }
548

549
    return item.slice(0, -1).toString('hex') + symbol;
×
550
  }
551

UNCOV
552
  return item.toString('hex');
×
553
};
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

© 2026 Coveralls, Inc