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

handshake-org / hsd / 15874541409

25 Jun 2025 10:58AM UTC coverage: 71.662% (+0.02%) from 71.643%
15874541409

push

github

nodech
pkg: update latest version.

8215 of 13317 branches covered (61.69%)

Branch coverage included in aggregate %.

26151 of 34639 relevant lines covered (75.5%)

34134.76 hits per line

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

81.15
/lib/protocol/consensus.js
1
/*!
2
 * consensus.js - consensus constants and helpers 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 protocol/consensus
11
 */
12

13
const assert = require('bsert');
68✔
14
const BN = require('bcrypto/lib/bn.js');
68✔
15

16
/** @typedef {import('../types').Hash} Hash */
17
/** @typedef {import('../types').Amount} Amount */
18

19
/**
20
 * Coin exponent.
21
 * @const {Number}
22
 * @default
23
 */
24

25
exports.EXP = 6;
68✔
26

27
/**
28
 * One handshake in dollarydoos.
29
 * @const {Amount}
30
 * @default
31
 */
32

33
exports.COIN = Math.pow(10, exports.EXP);
68✔
34

35
/**
36
 * Maximum creators amount in dollarydoos (consensus).
37
 * @const {Amount}
38
 * @default
39
 */
40

41
exports.MAX_CREATORS = 102e6 * exports.COIN;
68✔
42

43
/**
44
 * Maximum sponsors amount in dollarydoos (consensus).
45
 * @const {Amount}
46
 * @default
47
 */
48

49
exports.MAX_SPONSORS = 102e6 * exports.COIN;
68✔
50

51
/**
52
 * Maximum TLD holder amount in dollarydoos (consensus).
53
 * @const {Amount}
54
 * @default
55
 */
56

57
exports.MAX_TLD = 51e6 * exports.COIN;
68✔
58

59
/**
60
 * Maximum domain holder amount in dollarydoos (consensus).
61
 * @const {Amount}
62
 * @default
63
 */
64

65
exports.MAX_DOMAIN = 51e6 * exports.COIN;
68✔
66

67
/**
68
 * Maximum CA/naming amount in dollarydoos (consensus).
69
 * @const {Amount}
70
 * @default
71
 */
72

73
exports.MAX_CA_NAMING = 102e6 * exports.COIN;
68✔
74

75
/**
76
 * Maximum airdrop amount in dollarydoos (consensus).
77
 * @const {Amount}
78
 * @default
79
 */
80

81
exports.MAX_AIRDROP = 0.952e9 * exports.COIN;
68✔
82

83
/**
84
 * Maximum initial supply in dollarydoos (consensus).
85
 * @const {Amount}
86
 * @default
87
 */
88

89
exports.MAX_INITIAL = 1.36e9 * exports.COIN;
68✔
90

91
assert(exports.MAX_CREATORS
68✔
92
     + exports.MAX_SPONSORS
93
     + exports.MAX_TLD
94
     + exports.MAX_DOMAIN
95
     + exports.MAX_CA_NAMING
96
     + exports.MAX_AIRDROP === exports.MAX_INITIAL);
97

98
/**
99
 * Maximum amount of subsidies in dollarydoos (consensus).
100
 * @const {Amount}
101
 * @default
102
 */
103

104
exports.MAX_SUBSIDY = 0.68e9 * exports.COIN;
68✔
105

106
assert(exports.MAX_INITIAL / 2 === exports.MAX_SUBSIDY);
68✔
107

108
/**
109
 * Maximum amount of money in dollarydoos (consensus).
110
 * @const {Amount}
111
 * @default
112
 */
113

114
exports.MAX_MONEY = 2.04e9 * exports.COIN;
68✔
115

116
assert(exports.MAX_INITIAL + exports.MAX_SUBSIDY === exports.MAX_MONEY);
68✔
117

118
/**
119
 * Base block subsidy (consensus).
120
 * @const {Amount}
121
 * @default
122
 */
123

124
exports.BASE_REWARD = 2000 * exports.COIN;
68✔
125

126
assert(2 * exports.BASE_REWARD * 170000 === exports.MAX_SUBSIDY);
68✔
127

128
/**
129
 * Block subsidy specifically for the genesis block.
130
 *
131
 * Explanation:
132
 * The max miner subsidy is 680000000, but due
133
 * to the halving interval it actually ends up
134
 * as 679999995.79, so add 2.21 coins to the
135
 * genesis reward output to make MAX_MONEY a
136
 * thoroughly true value.
137
 *
138
 * This, combined with the 3 1/4 year halving
139
 * interval, causes the supply to run dry
140
 * after about 100 years (around the year 2119,
141
 * or height=5,270,000).
142
 *
143
 * @const {Amount}
144
 * @default
145
 */
146

147
exports.GENESIS_REWARD = exports.BASE_REWARD + ((2.21 * exports.COIN) | 0);
68✔
148

149
/**
150
 * Genesis key.
151
 * @const {Buffer}
152
 */
153

154
exports.GENESIS_KEY =
68✔
155
  Buffer.from('f0237ae2e8f860f7d79124fc513f012e5aaa8d23', 'hex');
156

157
/**
158
 * Maximum block base size (consensus).
159
 * @const {Number}
160
 * @default
161
 */
162

163
exports.MAX_BLOCK_SIZE = 1000000;
68✔
164

165
/**
166
 * Maximum block serialization size (protocol).
167
 * @const {Number}
168
 * @default
169
 */
170

171
exports.MAX_RAW_BLOCK_SIZE = 4000000;
68✔
172

173
/**
174
 * Maximum block weight (consensus).
175
 * @const {Number}
176
 * @default
177
 */
178

179
exports.MAX_BLOCK_WEIGHT = 4000000;
68✔
180

181
/**
182
 * Maximum block sigops cost (consensus).
183
 * @const {Number}
184
 * @default
185
 */
186

187
exports.MAX_BLOCK_SIGOPS = 80000;
68✔
188

189
/**
190
 * Maximum block tree opens.
191
 * @const {Number}
192
 * @default
193
 */
194

195
exports.MAX_BLOCK_OPENS = 300;
68✔
196

197
/**
198
 * Maximum block tree updates.
199
 * @const {Number}
200
 * @default
201
 */
202

203
exports.MAX_BLOCK_UPDATES = 600;
68✔
204

205
/**
206
 * Maximum block tree renewals.
207
 * @const {Number}
208
 * @default
209
 */
210

211
exports.MAX_BLOCK_RENEWALS = 600;
68✔
212

213
/**
214
 * Size of set to pick median time from.
215
 * @const {Number}
216
 * @default
217
 */
218

219
exports.MEDIAN_TIMESPAN = 11;
68✔
220

221
/**
222
 * Amount to multiply base/non-witness sizes by.
223
 * @const {Number}
224
 * @default
225
 */
226

227
exports.WITNESS_SCALE_FACTOR = 4;
68✔
228

229
/**
230
 * Maximum TX base size (consensus).
231
 * @const {Number}
232
 * @default
233
 */
234

235
exports.MAX_TX_SIZE = 1000000;
68✔
236

237
/**
238
 * Maximum TX weight (consensus).
239
 * @const {Number}
240
 * @default
241
 */
242

243
exports.MAX_TX_WEIGHT = 4000000;
68✔
244

245
/**
246
 * Locktime flag.
247
 * @const {Number}
248
 * @default
249
 */
250

251
exports.LOCKTIME_FLAG = (1 << 31) >>> 0;
68✔
252

253
/**
254
 * Locktime mask.
255
 * @const {Number}
256
 * @default
257
 */
258

259
exports.LOCKTIME_MASK = exports.LOCKTIME_FLAG - 1;
68✔
260

261
/**
262
 * Locktime granularity.
263
 * @const {Number}
264
 * @default
265
 */
266

267
exports.LOCKTIME_GRANULARITY = 9;
68✔
268

269
/**
270
 * Locktime multiplier.
271
 * @const {Number}
272
 * @default
273
 */
274

275
exports.LOCKTIME_MULT = 2 ** exports.LOCKTIME_GRANULARITY;
68✔
276

277
/**
278
 * Highest nSequence bit -- disables
279
 * sequence locktimes (consensus).
280
 * @const {Number}
281
 */
282

283
exports.SEQUENCE_DISABLE_FLAG = (1 << 31) >>> 0;
68✔
284

285
/**
286
 * Sequence time: height or time (consensus).
287
 * @const {Number}
288
 * @default
289
 */
290

291
exports.SEQUENCE_TYPE_FLAG = 1 << 22;
68✔
292

293
/**
294
 * Sequence granularity for time (consensus).
295
 * @const {Number}
296
 * @default
297
 */
298

299
exports.SEQUENCE_GRANULARITY = 9;
68✔
300

301
/**
302
 * Sequence mask (consensus).
303
 * @const {Number}
304
 * @default
305
 */
306

307
exports.SEQUENCE_MASK = 0x0000ffff;
68✔
308

309
/**
310
 * Max serialized script size (consensus).
311
 * @const {Number}
312
 * @default
313
 */
314

315
exports.MAX_SCRIPT_SIZE = 10000;
68✔
316

317
/**
318
 * Max stack size during execution (consensus).
319
 * @const {Number}
320
 * @default
321
 */
322

323
exports.MAX_SCRIPT_STACK = 1000;
68✔
324

325
/**
326
 * Max script element size (consensus).
327
 * @const {Number}
328
 * @default
329
 */
330

331
exports.MAX_SCRIPT_PUSH = 520;
68✔
332

333
/**
334
 * Max opcodes executed (consensus).
335
 * @const {Number}
336
 * @default
337
 */
338

339
exports.MAX_SCRIPT_OPS = 201;
68✔
340

341
/**
342
 * Max `n` value for multisig (consensus).
343
 * @const {Number}
344
 * @default
345
 */
346

347
exports.MAX_MULTISIG_PUBKEYS = 20;
68✔
348

349
/**
350
 * A hash of all zeroes.
351
 * @const {Buffer}
352
 * @default
353
 */
354

355
exports.ZERO_HASH = Buffer.alloc(32, 0x00);
68✔
356

357
/**
358
 * Block header size.
359
 * @const {Number}
360
 * @default
361
 */
362

363
exports.HEADER_SIZE = 236;
68✔
364

365
/**
366
 * Block header nonce size.
367
 * @const {Number}
368
 * @default
369
 */
370

371
exports.NONCE_SIZE = 24;
68✔
372

373
/**
374
 * Block header of all zeroes.
375
 * @const {Buffer}
376
 * @default
377
 */
378

379
exports.ZERO_HEADER = Buffer.alloc(exports.HEADER_SIZE, 0x00);
68✔
380

381
/**
382
 * Block header nonce of all zeroes.
383
 * @const {Buffer}
384
 * @default
385
 */
386

387
exports.ZERO_NONCE = Buffer.alloc(exports.NONCE_SIZE, 0x00);
68✔
388

389
/**
390
 * Convert a compact number to a big number.
391
 * Used for `block.bits` -> `target` conversion.
392
 * @param {Number} compact
393
 * @returns {BN}
394
 */
395

396
exports.fromCompact = function fromCompact(compact) {
68✔
397
  if (compact === 0)
58,455!
398
    return new BN(0);
×
399

400
  const exponent = compact >>> 24;
58,455✔
401
  const negative = (compact >>> 23) & 1;
58,455✔
402

403
  let mantissa = compact & 0x7fffff;
58,455✔
404
  let num;
405

406
  if (exponent <= 3) {
58,455!
407
    mantissa >>>= 8 * (3 - exponent);
×
408
    num = new BN(mantissa);
×
409
  } else {
410
    num = new BN(mantissa);
58,455✔
411
    num.iushln(8 * (exponent - 3));
58,455✔
412
  }
413

414
  if (negative)
58,455!
415
    num.ineg();
×
416

417
  return num;
58,455✔
418
};
419

420
/**
421
 * Convert a big number to a compact number.
422
 * Used for `target` -> `block.bits` conversion.
423
 * @param {BN} num
424
 * @returns {Number}
425
 */
426

427
exports.toCompact = function toCompact(num) {
68✔
428
  if (num.isZero())
1!
429
    return 0;
×
430

431
  let exponent = num.byteLength();
1✔
432
  let mantissa;
433

434
  if (exponent <= 3) {
1!
435
    mantissa = num.toNumber();
×
436
    mantissa <<= 8 * (3 - exponent);
×
437
  } else {
438
    mantissa = num.ushrn(8 * (exponent - 3)).toNumber();
1✔
439
  }
440

441
  if (mantissa & 0x800000) {
1!
442
    mantissa >>>= 8;
1✔
443
    exponent += 1;
1✔
444
  }
445

446
  let compact = (exponent << 24) | mantissa;
1✔
447

448
  if (num.isNeg())
1!
449
    compact |= 0x800000;
×
450

451
  compact >>>= 0;
1✔
452

453
  return compact;
1✔
454
};
455

456
/**
457
 * Verify proof-of-work.
458
 * @param {Hash} hash
459
 * @param {Number} bits
460
 * @returns {Boolean}
461
 */
462

463
exports.verifyPOW = function verifyPOW(hash, bits) {
68✔
464
  const target = exports.fromCompact(bits);
20,176✔
465

466
  if (target.isNeg() || target.isZero())
20,176!
467
    return false;
×
468

469
  if (target.bitLength() > 256)
20,176!
470
    return false;
×
471

472
  const num = new BN(hash, 'be');
20,176✔
473

474
  if (num.gt(target))
20,176!
475
    return false;
×
476

477
  return true;
20,176✔
478
};
479

480
/**
481
 * Calculate block subsidy.
482
 * @param {Number} height - Reward era by height.
483
 * @param {Number} interval - halving interval.
484
 * @returns {Amount}
485
 */
486

487
exports.getReward = function getReward(height, interval) {
68✔
488
  assert((height >>> 0) === height, 'Bad height for reward.');
5,330,001✔
489
  assert((interval >>> 0) === interval);
5,330,001✔
490

491
  const halvings = Math.floor(height / interval);
5,330,001✔
492

493
  if (halvings >= 52)
5,330,001!
494
    return 0;
×
495

496
  return Math.floor(exports.BASE_REWARD / Math.pow(2, halvings));
5,330,001✔
497
};
498

499
/**
500
 * Test version bit.
501
 * @param {Number} version
502
 * @param {Number} bit
503
 * @returns {Boolean}
504
 */
505

506
exports.hasBit = function hasBit(version, bit) {
68✔
507
  return (version & (1 << bit)) !== 0;
24,371✔
508
};
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