@feelyourprotocol/common 8141.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +409 -0
  3. package/dist/cjs/chains.d.ts +6 -0
  4. package/dist/cjs/chains.d.ts.map +1 -0
  5. package/dist/cjs/chains.js +637 -0
  6. package/dist/cjs/chains.js.map +1 -0
  7. package/dist/cjs/common.d.ts +318 -0
  8. package/dist/cjs/common.d.ts.map +1 -0
  9. package/dist/cjs/common.js +789 -0
  10. package/dist/cjs/common.js.map +1 -0
  11. package/dist/cjs/constructors.d.ts +27 -0
  12. package/dist/cjs/constructors.d.ts.map +1 -0
  13. package/dist/cjs/constructors.js +53 -0
  14. package/dist/cjs/constructors.js.map +1 -0
  15. package/dist/cjs/crc.d.ts +8 -0
  16. package/dist/cjs/crc.d.ts.map +1 -0
  17. package/dist/cjs/crc.js +63 -0
  18. package/dist/cjs/crc.js.map +1 -0
  19. package/dist/cjs/eips.d.ts +3 -0
  20. package/dist/cjs/eips.d.ts.map +1 -0
  21. package/dist/cjs/eips.js +589 -0
  22. package/dist/cjs/eips.js.map +1 -0
  23. package/dist/cjs/enums.d.ts +65 -0
  24. package/dist/cjs/enums.d.ts.map +1 -0
  25. package/dist/cjs/enums.js +80 -0
  26. package/dist/cjs/enums.js.map +1 -0
  27. package/dist/cjs/gethGenesis.d.ts +145 -0
  28. package/dist/cjs/gethGenesis.d.ts.map +1 -0
  29. package/dist/cjs/gethGenesis.js +26 -0
  30. package/dist/cjs/gethGenesis.js.map +1 -0
  31. package/dist/cjs/hardforks.d.ts +3 -0
  32. package/dist/cjs/hardforks.d.ts.map +1 -0
  33. package/dist/cjs/hardforks.js +207 -0
  34. package/dist/cjs/hardforks.js.map +1 -0
  35. package/dist/cjs/index.d.ts +9 -0
  36. package/dist/cjs/index.d.ts.map +1 -0
  37. package/dist/cjs/index.js +25 -0
  38. package/dist/cjs/index.js.map +1 -0
  39. package/dist/cjs/interfaces.d.ts +132 -0
  40. package/dist/cjs/interfaces.d.ts.map +1 -0
  41. package/dist/cjs/interfaces.js +13 -0
  42. package/dist/cjs/interfaces.js.map +1 -0
  43. package/dist/cjs/package.json +3 -0
  44. package/dist/cjs/types.d.ts +167 -0
  45. package/dist/cjs/types.d.ts.map +1 -0
  46. package/dist/cjs/types.js +3 -0
  47. package/dist/cjs/types.js.map +1 -0
  48. package/dist/cjs/utils.d.ts +60 -0
  49. package/dist/cjs/utils.d.ts.map +1 -0
  50. package/dist/cjs/utils.js +263 -0
  51. package/dist/cjs/utils.js.map +1 -0
  52. package/dist/esm/chains.d.ts +6 -0
  53. package/dist/esm/chains.d.ts.map +1 -0
  54. package/dist/esm/chains.js +634 -0
  55. package/dist/esm/chains.js.map +1 -0
  56. package/dist/esm/common.d.ts +318 -0
  57. package/dist/esm/common.d.ts.map +1 -0
  58. package/dist/esm/common.js +785 -0
  59. package/dist/esm/common.js.map +1 -0
  60. package/dist/esm/constructors.d.ts +27 -0
  61. package/dist/esm/constructors.d.ts.map +1 -0
  62. package/dist/esm/constructors.js +49 -0
  63. package/dist/esm/constructors.js.map +1 -0
  64. package/dist/esm/crc.d.ts +8 -0
  65. package/dist/esm/crc.d.ts.map +1 -0
  66. package/dist/esm/crc.js +59 -0
  67. package/dist/esm/crc.js.map +1 -0
  68. package/dist/esm/eips.d.ts +3 -0
  69. package/dist/esm/eips.d.ts.map +1 -0
  70. package/dist/esm/eips.js +586 -0
  71. package/dist/esm/eips.js.map +1 -0
  72. package/dist/esm/enums.d.ts +65 -0
  73. package/dist/esm/enums.d.ts.map +1 -0
  74. package/dist/esm/enums.js +77 -0
  75. package/dist/esm/enums.js.map +1 -0
  76. package/dist/esm/gethGenesis.d.ts +145 -0
  77. package/dist/esm/gethGenesis.d.ts.map +1 -0
  78. package/dist/esm/gethGenesis.js +23 -0
  79. package/dist/esm/gethGenesis.js.map +1 -0
  80. package/dist/esm/hardforks.d.ts +3 -0
  81. package/dist/esm/hardforks.d.ts.map +1 -0
  82. package/dist/esm/hardforks.js +204 -0
  83. package/dist/esm/hardforks.js.map +1 -0
  84. package/dist/esm/index.d.ts +9 -0
  85. package/dist/esm/index.d.ts.map +1 -0
  86. package/dist/esm/index.js +9 -0
  87. package/dist/esm/index.js.map +1 -0
  88. package/dist/esm/interfaces.d.ts +132 -0
  89. package/dist/esm/interfaces.d.ts.map +1 -0
  90. package/dist/esm/interfaces.js +10 -0
  91. package/dist/esm/interfaces.js.map +1 -0
  92. package/dist/esm/package.json +3 -0
  93. package/dist/esm/types.d.ts +167 -0
  94. package/dist/esm/types.d.ts.map +1 -0
  95. package/dist/esm/types.js +2 -0
  96. package/dist/esm/types.js.map +1 -0
  97. package/dist/esm/utils.d.ts +60 -0
  98. package/dist/esm/utils.d.ts.map +1 -0
  99. package/dist/esm/utils.js +258 -0
  100. package/dist/esm/utils.js.map +1 -0
  101. package/dist/tsconfig.prod.cjs.tsbuildinfo +1 -0
  102. package/dist/tsconfig.prod.esm.tsbuildinfo +1 -0
  103. package/package.json +77 -0
  104. package/src/chains.ts +638 -0
  105. package/src/common.ts +913 -0
  106. package/src/constructors.ts +60 -0
  107. package/src/crc.ts +63 -0
  108. package/src/eips.ts +588 -0
  109. package/src/enums.ts +104 -0
  110. package/src/gethGenesis.ts +175 -0
  111. package/src/hardforks.ts +205 -0
  112. package/src/index.ts +8 -0
  113. package/src/interfaces.ts +191 -0
  114. package/src/types.ts +193 -0
  115. package/src/utils.ts +324 -0
@@ -0,0 +1,785 @@
1
+ import { BIGINT_0, EthereumJSErrorWithoutCode, TypeOutput, bytesToHex, concatBytes, hexToBytes, intToBytes, toType, } from '@feelyourprotocol/util';
2
+ import { EventEmitter } from 'eventemitter3';
3
+ import { crc32 } from "./crc.js";
4
+ import { eipsDict } from "./eips.js";
5
+ import { Hardfork } from "./enums.js";
6
+ import { hardforksDict } from "./hardforks.js";
7
+ /**
8
+ * Common class to access chain and hardfork parameters and to provide
9
+ * a unified and shared view on the network and hardfork state.
10
+ *
11
+ * Use the {@link createCustomCommon} constructor for creating simple
12
+ * custom chain {@link Common} objects (more complete custom chain setups
13
+ * can be created via the main constructor).
14
+ *
15
+ * Use the {@link createCommonFromGethGenesis} constructor for creating
16
+ * a Common object from a Geth genesis file.
17
+ */
18
+ export class Common {
19
+ constructor(opts) {
20
+ this._eips = [];
21
+ this._paramsCache = {};
22
+ this._activatedEIPsCache = [];
23
+ this.events = new EventEmitter();
24
+ this._chainParams = JSON.parse(JSON.stringify(opts.chain)); // copy
25
+ this.DEFAULT_HARDFORK = this._chainParams.defaultHardfork ?? Hardfork.Prague;
26
+ // Assign hardfork changes in the sequence of the applied hardforks
27
+ this.HARDFORK_CHANGES = this.hardforks().map((hf) => [
28
+ hf.name,
29
+ // Allow to even override an existing hardfork specification
30
+ (this._chainParams.customHardforks && this._chainParams.customHardforks[hf.name]) ??
31
+ hardforksDict[hf.name],
32
+ ]);
33
+ this._hardfork = this.DEFAULT_HARDFORK;
34
+ this._params = opts.params ? JSON.parse(JSON.stringify(opts.params)) : {}; // copy
35
+ if (opts.hardfork !== undefined) {
36
+ this.setHardfork(opts.hardfork);
37
+ }
38
+ if (opts.eips) {
39
+ this.setEIPs(opts.eips);
40
+ }
41
+ this.customCrypto = opts.customCrypto ?? {};
42
+ if (Object.keys(this._paramsCache).length === 0) {
43
+ this._buildParamsCache();
44
+ this._buildActivatedEIPsCache();
45
+ }
46
+ }
47
+ /**
48
+ * Update the internal Common EIP params set. Existing values
49
+ * will get preserved unless there is a new value for a parameter
50
+ * provided with params.
51
+ *
52
+ * Example Format:
53
+ *
54
+ * ```ts
55
+ * {
56
+ * 1559: {
57
+ * initialBaseFee: 1000000000,
58
+ * }
59
+ * }
60
+ * ```
61
+ *
62
+ * @param params
63
+ */
64
+ updateParams(params) {
65
+ for (const [eip, paramsConfig] of Object.entries(params)) {
66
+ if (!(eip in this._params)) {
67
+ this._params[eip] = JSON.parse(JSON.stringify(paramsConfig)); // copy
68
+ }
69
+ else {
70
+ this._params[eip] = JSON.parse(JSON.stringify({ ...this._params[eip], ...params[eip] })); // copy
71
+ }
72
+ }
73
+ this._buildParamsCache();
74
+ }
75
+ /**
76
+ * Fully resets the internal Common EIP params set with the values provided.
77
+ *
78
+ * Example Format:
79
+ *
80
+ * ```ts
81
+ * {
82
+ * 1559: {
83
+ * initialBaseFee: 1000000000,
84
+ * }
85
+ * }
86
+ * ```
87
+ *
88
+ * @param params
89
+ */
90
+ resetParams(params) {
91
+ this._params = JSON.parse(JSON.stringify(params)); // copy
92
+ this._buildParamsCache();
93
+ }
94
+ /**
95
+ * Sets the hardfork to get params for
96
+ * @param hardfork String identifier (e.g. 'byzantium') or {@link Hardfork} enum
97
+ */
98
+ setHardfork(hardfork) {
99
+ let existing = false;
100
+ for (const hfChanges of this.HARDFORK_CHANGES) {
101
+ if (hfChanges[0] === hardfork) {
102
+ if (this._hardfork !== hardfork) {
103
+ this._hardfork = hardfork;
104
+ this._buildParamsCache();
105
+ this._buildActivatedEIPsCache();
106
+ this.events.emit('hardforkChanged', hardfork);
107
+ }
108
+ existing = true;
109
+ }
110
+ }
111
+ if (!existing) {
112
+ throw EthereumJSErrorWithoutCode(`Hardfork with name ${hardfork} not supported`);
113
+ }
114
+ }
115
+ /**
116
+ * Returns the hardfork either based on block number (older HFs) or
117
+ * timestamp (Shanghai upwards).
118
+ *
119
+ * @param opts Block number or timestamp
120
+ * @returns The name of the HF
121
+ */
122
+ getHardforkBy(opts) {
123
+ const blockNumber = toType(opts.blockNumber, TypeOutput.BigInt);
124
+ const timestamp = toType(opts.timestamp, TypeOutput.BigInt);
125
+ // Filter out hardforks with no block number, no timestamp (i.e. unapplied hardforks)
126
+ const hfs = this.hardforks().filter((hf) => hf.block !== null || hf.timestamp !== undefined);
127
+ // Find the first hardfork that has a block number greater than `blockNumber`
128
+ // If timestamp is not provided, it also skips timestamps hardforks to continue
129
+ // discovering/checking number hardforks.
130
+ let hfIndex = hfs.findIndex((hf) => (blockNumber !== undefined && hf.block !== null && BigInt(hf.block) > blockNumber) ||
131
+ (timestamp !== undefined && hf.timestamp !== undefined && BigInt(hf.timestamp) > timestamp));
132
+ if (hfIndex === -1) {
133
+ // all hardforks apply, set hfIndex to the last one as that's the candidate
134
+ hfIndex = hfs.length;
135
+ }
136
+ else if (hfIndex === 0) {
137
+ // cannot have a case where a block number is before all applied hardforks
138
+ // since the chain has to start with a hardfork
139
+ throw Error('Must have at least one hardfork at block 0');
140
+ }
141
+ // If timestamp is not provided, we need to rollback to the last hf with block
142
+ if (timestamp === undefined) {
143
+ const stepBack = hfs
144
+ .slice(0, hfIndex)
145
+ .reverse()
146
+ .findIndex((hf) => hf.block !== null);
147
+ hfIndex = hfIndex - stepBack;
148
+ }
149
+ // Move hfIndex one back to arrive at candidate hardfork
150
+ hfIndex = hfIndex - 1;
151
+ const hfStartIndex = hfIndex;
152
+ // Move the hfIndex to the end of the hardforks that might be scheduled on the same block/timestamp
153
+ // This won't anyway be the case with Merge hfs
154
+ for (; hfIndex < hfs.length - 1; hfIndex++) {
155
+ // break out if hfIndex + 1 is not scheduled at hfIndex
156
+ if (hfs[hfIndex].block !== hfs[hfIndex + 1].block ||
157
+ hfs[hfIndex].timestamp !== hfs[hfIndex + 1].timestamp) {
158
+ break;
159
+ }
160
+ }
161
+ if (timestamp !== undefined) {
162
+ const minTimeStamp = hfs
163
+ .slice(0, hfStartIndex)
164
+ .reduce((acc, hf) => Math.max(Number(hf.timestamp ?? '0'), acc), 0);
165
+ if (minTimeStamp > timestamp) {
166
+ throw Error(`Maximum HF determined by timestamp is lower than the block number HF`);
167
+ }
168
+ const maxTimeStamp = hfs
169
+ .slice(hfIndex + 1)
170
+ .reduce((acc, hf) => Math.min(Number(hf.timestamp ?? timestamp), acc), Number(timestamp));
171
+ if (maxTimeStamp < timestamp) {
172
+ throw Error(`Maximum HF determined by block number is lower than timestamp HF`);
173
+ }
174
+ }
175
+ const hardfork = hfs[hfIndex];
176
+ return hardfork.name;
177
+ }
178
+ /**
179
+ * Sets a new hardfork either based on block number (older HFs) or
180
+ * timestamp (Shanghai upwards).
181
+ *
182
+ * @param opts Block number or timestamp
183
+ * @returns The name of the HF set
184
+ */
185
+ setHardforkBy(opts) {
186
+ const hardfork = this.getHardforkBy(opts);
187
+ this.setHardfork(hardfork);
188
+ return hardfork;
189
+ }
190
+ /**
191
+ * Internal helper function, returns the params for the given hardfork for the chain set
192
+ * @param hardfork Hardfork name
193
+ * @returns Dictionary with hardfork params or null if hardfork not on chain
194
+ */
195
+ _getHardfork(hardfork) {
196
+ const hfs = this.hardforks();
197
+ for (const hf of hfs) {
198
+ if (hf['name'] === hardfork)
199
+ return hf;
200
+ }
201
+ return null;
202
+ }
203
+ /**
204
+ * Sets the active EIPs
205
+ * @param eips
206
+ */
207
+ setEIPs(eips = []) {
208
+ for (const eip of eips) {
209
+ if (!(eip in eipsDict)) {
210
+ throw EthereumJSErrorWithoutCode(`${eip} not supported`);
211
+ }
212
+ const minHF = this.gteHardfork(eipsDict[eip]['minimumHardfork']);
213
+ if (!minHF) {
214
+ throw EthereumJSErrorWithoutCode(`${eip} cannot be activated on hardfork ${this.hardfork()}, minimumHardfork: ${minHF}`);
215
+ }
216
+ }
217
+ this._eips = eips;
218
+ this._buildParamsCache();
219
+ this._buildActivatedEIPsCache();
220
+ for (const eip of eips) {
221
+ if (eipsDict[eip].requiredEIPs !== undefined) {
222
+ for (const elem of eipsDict[eip].requiredEIPs) {
223
+ if (!(eips.includes(elem) || this.isActivatedEIP(elem))) {
224
+ throw EthereumJSErrorWithoutCode(`${eip} requires EIP ${elem}, but is not included in the EIP list`);
225
+ }
226
+ }
227
+ }
228
+ }
229
+ }
230
+ /**
231
+ * Internal helper for _buildParamsCache()
232
+ */
233
+ _mergeWithParamsCache(params) {
234
+ for (const [key, value] of Object.entries(params)) {
235
+ this._paramsCache[key] = value;
236
+ }
237
+ }
238
+ /**
239
+ * Build up a cache for all parameter values for the current HF and all activated EIPs
240
+ */
241
+ _buildParamsCache() {
242
+ this._paramsCache = {};
243
+ // Iterate through all hardforks up to hardfork set
244
+ const hardfork = this.hardfork();
245
+ for (const hfChanges of this.HARDFORK_CHANGES) {
246
+ // EIP-referencing HF config (e.g. for berlin)
247
+ if ('eips' in hfChanges[1]) {
248
+ const hfEIPs = hfChanges[1].eips ?? [];
249
+ for (const eip of hfEIPs) {
250
+ if (this._params[eip] !== undefined && this._params[eip] !== null) {
251
+ this._mergeWithParamsCache(this._params[eip]);
252
+ }
253
+ }
254
+ }
255
+ // Hardfork-scoped params (e.g. for bpo1, bpo2)
256
+ // override the baseline EIP values when present
257
+ const hfScopedParams = this._params[hfChanges[0]];
258
+ if (hfScopedParams !== undefined && hfScopedParams !== null) {
259
+ this._mergeWithParamsCache(hfScopedParams);
260
+ }
261
+ // Parameter-inlining HF config (e.g. for istanbul or custom blobSchedule)
262
+ if (hfChanges[1].params !== undefined && hfChanges[1].params !== null) {
263
+ this._mergeWithParamsCache(hfChanges[1].params);
264
+ }
265
+ if (hfChanges[0] === hardfork)
266
+ break;
267
+ }
268
+ // Iterate through all additionally activated EIPs
269
+ for (const eip of this._eips) {
270
+ if (this._params[eip] !== undefined && this._params[eip] !== null) {
271
+ this._mergeWithParamsCache(this._params[eip]);
272
+ }
273
+ }
274
+ }
275
+ /**
276
+ * Builds the cache of EIPs activated either via hardforks or constructor `eips`.
277
+ */
278
+ _buildActivatedEIPsCache() {
279
+ this._activatedEIPsCache = [];
280
+ for (const [name, hf] of this.HARDFORK_CHANGES) {
281
+ if (this.gteHardfork(name) && 'eips' in hf) {
282
+ this._activatedEIPsCache = this._activatedEIPsCache.concat(hf.eips ?? []);
283
+ }
284
+ }
285
+ this._activatedEIPsCache = this._activatedEIPsCache.concat(this._eips);
286
+ }
287
+ /**
288
+ * Returns a parameter for the current chain setup
289
+ *
290
+ * If the parameter is present in an EIP, the EIP always takes precedence.
291
+ * Otherwise the parameter is taken from the latest applied HF with
292
+ * a change on the respective parameter.
293
+ *
294
+ * @param name Parameter name (e.g. 'minGasLimit')
295
+ * @returns The value requested (throws if not found)
296
+ */
297
+ param(name) {
298
+ // TODO: consider the case that different active EIPs
299
+ // can change the same parameter
300
+ if (!(name in this._paramsCache)) {
301
+ throw EthereumJSErrorWithoutCode(`Missing parameter value for ${name}`);
302
+ }
303
+ const value = this._paramsCache[name];
304
+ return BigInt(value ?? 0);
305
+ }
306
+ /**
307
+ * Returns the parameter corresponding to a hardfork
308
+ * @param name Parameter name (e.g. 'minGasLimit')
309
+ * @param hardfork Hardfork name
310
+ * @returns The value requested (throws if not found)
311
+ */
312
+ paramByHardfork(name, hardfork) {
313
+ let value;
314
+ for (const hfChanges of this.HARDFORK_CHANGES) {
315
+ // EIP-referencing HF config (e.g. for berlin)
316
+ if ('eips' in hfChanges[1]) {
317
+ const hfEIPs = hfChanges[1]['eips'];
318
+ for (const eip of hfEIPs) {
319
+ const eipParams = this._params[eip];
320
+ const eipValue = eipParams?.[name];
321
+ if (eipValue !== undefined) {
322
+ value = eipValue;
323
+ }
324
+ }
325
+ // Parameter-inlining HF config (e.g. for istanbul)
326
+ }
327
+ else {
328
+ const hfValue = hfChanges[1].params?.[name];
329
+ if (hfValue !== undefined) {
330
+ value = hfValue;
331
+ }
332
+ }
333
+ if (hfChanges[0] === hardfork)
334
+ break;
335
+ }
336
+ if (value === undefined) {
337
+ throw EthereumJSErrorWithoutCode(`Missing parameter value for ${name}`);
338
+ }
339
+ return BigInt(value ?? 0);
340
+ }
341
+ /**
342
+ * Returns a parameter corresponding to an EIP
343
+ * @param name Parameter name (e.g. 'minGasLimit' for 'gasConfig' topic)
344
+ * @param eip Number of the EIP
345
+ * @returns The value requested (throws if not found)
346
+ */
347
+ paramByEIP(name, eip) {
348
+ if (!(eip in eipsDict)) {
349
+ throw EthereumJSErrorWithoutCode(`${eip} not supported`);
350
+ }
351
+ const eipParams = this._params[eip];
352
+ if (eipParams?.[name] === undefined) {
353
+ throw EthereumJSErrorWithoutCode(`Missing parameter value for ${name}`);
354
+ }
355
+ const value = eipParams[name];
356
+ return BigInt(value ?? 0);
357
+ }
358
+ /**
359
+ * Returns a parameter for the hardfork active on block number or
360
+ * optional provided total difficulty (Merge HF)
361
+ * @param name Parameter name
362
+ * @param blockNumber Block number
363
+ * @returns The value requested or `BigInt(0)` if not found
364
+ */
365
+ paramByBlock(name, blockNumber, timestamp) {
366
+ const hardfork = this.getHardforkBy({ blockNumber, timestamp });
367
+ return this.paramByHardfork(name, hardfork);
368
+ }
369
+ /**
370
+ * Returns the blob gas schedule for the current hardfork
371
+ * @returns The blob gas schedule
372
+ */
373
+ getBlobGasSchedule() {
374
+ if (this.gteHardfork(Hardfork.Bpo1)) {
375
+ return {
376
+ targetBlobGasPerBlock: this.param('target') * this.param('blobGasPerBlob'),
377
+ maxBlobGasPerBlock: this.param('max') * this.param('blobGasPerBlob'),
378
+ blobGasPriceUpdateFraction: this.param('blobGasPriceUpdateFraction'),
379
+ };
380
+ }
381
+ return {
382
+ targetBlobGasPerBlock: this.param('targetBlobGasPerBlock'),
383
+ maxBlobGasPerBlock: this.param('maxBlobGasPerBlock'),
384
+ blobGasPriceUpdateFraction: this.param('blobGasPriceUpdateFraction'),
385
+ };
386
+ }
387
+ /**
388
+ * Checks if an EIP is activated by either being included in the EIPs
389
+ * manually passed in with the {@link CommonOpts.eips} or in a
390
+ * hardfork currently being active
391
+ *
392
+ * Note: this method only works for EIPs being supported
393
+ * by the {@link CommonOpts.eips} constructor option
394
+ * @param eip
395
+ */
396
+ isActivatedEIP(eip) {
397
+ if (this._activatedEIPsCache.includes(eip)) {
398
+ return true;
399
+ }
400
+ return false;
401
+ }
402
+ /**
403
+ * Checks if set or provided hardfork is active on block number
404
+ * @param hardfork Hardfork name or null (for HF set)
405
+ * @param blockNumber
406
+ * @returns True if HF is active on block number
407
+ */
408
+ hardforkIsActiveOnBlock(hardfork, blockNumber) {
409
+ blockNumber = toType(blockNumber, TypeOutput.BigInt);
410
+ hardfork = hardfork ?? this._hardfork;
411
+ const hfBlock = this.hardforkBlock(hardfork);
412
+ if (typeof hfBlock === 'bigint' && hfBlock !== BIGINT_0 && blockNumber >= hfBlock) {
413
+ return true;
414
+ }
415
+ return false;
416
+ }
417
+ /**
418
+ * Alias to hardforkIsActiveOnBlock when hardfork is set
419
+ * @param blockNumber
420
+ * @returns True if HF is active on block number
421
+ */
422
+ activeOnBlock(blockNumber) {
423
+ return this.hardforkIsActiveOnBlock(null, blockNumber);
424
+ }
425
+ /**
426
+ * Sequence based check if given or set HF1 is greater than or equal HF2
427
+ * @param hardfork1 Hardfork name or null (if set)
428
+ * @param hardfork2 Hardfork name
429
+ * @returns True if HF1 gte HF2
430
+ */
431
+ hardforkGteHardfork(hardfork1, hardfork2) {
432
+ hardfork1 = hardfork1 ?? this._hardfork;
433
+ const hardforks = this.hardforks();
434
+ let posHf1 = -1, posHf2 = -1;
435
+ let index = 0;
436
+ for (const hf of hardforks) {
437
+ if (hf['name'] === hardfork1)
438
+ posHf1 = index;
439
+ if (hf['name'] === hardfork2)
440
+ posHf2 = index;
441
+ index += 1;
442
+ }
443
+ return posHf1 >= posHf2 && posHf2 !== -1;
444
+ }
445
+ /**
446
+ * Alias to hardforkGteHardfork when hardfork is set
447
+ * @param hardfork Hardfork name
448
+ * @returns True if hardfork set is greater than hardfork provided
449
+ */
450
+ gteHardfork(hardfork) {
451
+ return this.hardforkGteHardfork(null, hardfork);
452
+ }
453
+ /**
454
+ * Returns the hardfork change block for hardfork provided or set
455
+ * @param hardfork Hardfork name, optional if HF set
456
+ * @returns Block number or null if unscheduled
457
+ */
458
+ hardforkBlock(hardfork) {
459
+ hardfork = hardfork ?? this._hardfork;
460
+ const block = this._getHardfork(hardfork)?.['block'];
461
+ if (block === undefined || block === null) {
462
+ return null;
463
+ }
464
+ return BigInt(block);
465
+ }
466
+ /**
467
+ * Returns the timestamp at which a given hardfork is scheduled (if any).
468
+ * @param hardfork Hardfork name, optional if HF set
469
+ * @returns Timestamp or null if the hardfork is not timestamp-based
470
+ */
471
+ hardforkTimestamp(hardfork) {
472
+ hardfork = hardfork ?? this._hardfork;
473
+ const timestamp = this._getHardfork(hardfork)?.['timestamp'];
474
+ if (timestamp === undefined || timestamp === null) {
475
+ return null;
476
+ }
477
+ return BigInt(timestamp);
478
+ }
479
+ /**
480
+ * Returns the hardfork change block for eip
481
+ * @param eip EIP number
482
+ * @returns Block number or null if unscheduled
483
+ */
484
+ eipBlock(eip) {
485
+ for (const hfChanges of this.HARDFORK_CHANGES) {
486
+ const hf = hfChanges[1];
487
+ if ('eips' in hf) {
488
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
489
+ if (hf['eips'].includes(eip)) {
490
+ return this.hardforkBlock(hfChanges[0]);
491
+ }
492
+ }
493
+ }
494
+ return null;
495
+ }
496
+ /**
497
+ * Returns the scheduled timestamp of the EIP (if scheduled and scheduled by timestamp)
498
+ * @param eip EIP number
499
+ * @returns Scheduled timestamp. If this EIP is unscheduled, or the EIP is scheduled by block number, then it returns `null`.
500
+ */
501
+ eipTimestamp(eip) {
502
+ for (const hfChanges of this.HARDFORK_CHANGES) {
503
+ const hf = hfChanges[1];
504
+ if ('eips' in hf) {
505
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
506
+ if (hf['eips'].includes(eip)) {
507
+ return this.hardforkTimestamp(hfChanges[0]);
508
+ }
509
+ }
510
+ }
511
+ return null;
512
+ }
513
+ /**
514
+ * Returns the block number or timestamp at which the next hardfork will occur.
515
+ * For pre-merge hardforks, returns the block number.
516
+ * For post-merge hardforks, returns the timestamp.
517
+ * Returns null if there is no next hardfork.
518
+ * @param hardfork Hardfork name, optional if HF set
519
+ * @returns Block number or timestamp, or null if not available
520
+ */
521
+ nextHardforkBlockOrTimestamp(hardfork) {
522
+ const targetHardfork = hardfork ?? this._hardfork;
523
+ const hfs = this.hardforks();
524
+ // Find the index of the target hardfork
525
+ let targetHfIndex = hfs.findIndex((hf) => hf.name === targetHardfork);
526
+ // Special handling for The Merge (Paris) hardfork
527
+ if (targetHardfork === Hardfork.Paris) {
528
+ // The Merge is determined by total difficulty, not block number
529
+ // So we look at the previous hardfork's parameters instead
530
+ targetHfIndex -= 1;
531
+ }
532
+ // If we couldn't find a valid hardfork index, return null
533
+ if (targetHfIndex < 0) {
534
+ return null;
535
+ }
536
+ // Get the current hardfork's block/timestamp
537
+ const currentHf = hfs[targetHfIndex];
538
+ const currentBlockOrTimestamp = currentHf.timestamp ?? currentHf.block;
539
+ if (currentBlockOrTimestamp === null || currentBlockOrTimestamp === undefined) {
540
+ return null;
541
+ }
542
+ // Find the next hardfork that has a different block/timestamp
543
+ const nextHf = hfs.slice(targetHfIndex + 1).find((hf) => {
544
+ const nextBlockOrTimestamp = hf.timestamp ?? hf.block;
545
+ return (nextBlockOrTimestamp !== null &&
546
+ nextBlockOrTimestamp !== undefined &&
547
+ nextBlockOrTimestamp !== currentBlockOrTimestamp);
548
+ });
549
+ // If no next hf found with valid block or timestamp return null
550
+ if (nextHf === undefined) {
551
+ return null;
552
+ }
553
+ // Get the block/timestamp for the next hardfork
554
+ const nextBlockOrTimestamp = nextHf.timestamp ?? nextHf.block;
555
+ if (nextBlockOrTimestamp === null || nextBlockOrTimestamp === undefined) {
556
+ return null;
557
+ }
558
+ return BigInt(nextBlockOrTimestamp);
559
+ }
560
+ /**
561
+ * Internal helper function to calculate a fork hash
562
+ * @param hardfork Hardfork name
563
+ * @param genesisHash Genesis block hash of the chain
564
+ * @returns Fork hash as hex string
565
+ */
566
+ _calcForkHash(hardfork, genesisHash) {
567
+ let hfBytes = new Uint8Array(0);
568
+ let prevBlockOrTime = 0;
569
+ for (const hf of this.hardforks()) {
570
+ const { block, timestamp, name } = hf;
571
+ // Timestamp to be used for timestamp based hfs even if we may bundle
572
+ // block number with them retrospectively
573
+ let blockOrTime = timestamp ?? block;
574
+ blockOrTime = blockOrTime !== null ? Number(blockOrTime) : null;
575
+ // Skip for chainstart (0), not applied HFs (null) and
576
+ // when already applied on same blockOrTime HFs
577
+ // and on the merge since forkhash doesn't change on merge hf
578
+ if (typeof blockOrTime === 'number' &&
579
+ blockOrTime !== 0 &&
580
+ blockOrTime !== prevBlockOrTime &&
581
+ name !== Hardfork.Paris) {
582
+ const hfBlockBytes = hexToBytes(`0x${blockOrTime.toString(16).padStart(16, '0')}`);
583
+ hfBytes = concatBytes(hfBytes, hfBlockBytes);
584
+ prevBlockOrTime = blockOrTime;
585
+ }
586
+ if (hf.name === hardfork)
587
+ break;
588
+ }
589
+ const inputBytes = concatBytes(genesisHash, hfBytes);
590
+ // CRC32 delivers result as signed (negative) 32-bit integer,
591
+ // convert to hex string
592
+ const forkhash = bytesToHex(intToBytes(crc32(inputBytes) >>> 0));
593
+ return forkhash;
594
+ }
595
+ /**
596
+ * Returns an eth/64 compliant fork hash (EIP-2124)
597
+ * @param hardfork Hardfork name, optional if HF set
598
+ * @param genesisHash Genesis block hash of the network, optional if already defined and not needed to be calculated
599
+ * @returns Fork hash as a hex string
600
+ */
601
+ forkHash(hardfork, genesisHash) {
602
+ hardfork = hardfork ?? this._hardfork;
603
+ const data = this._getHardfork(hardfork);
604
+ if (data === null || (data?.block === null && data?.timestamp === undefined)) {
605
+ const msg = 'No fork hash calculation possible for future hardfork';
606
+ throw EthereumJSErrorWithoutCode(msg);
607
+ }
608
+ if (data?.forkHash !== null && data?.forkHash !== undefined) {
609
+ return data.forkHash;
610
+ }
611
+ if (!genesisHash)
612
+ throw EthereumJSErrorWithoutCode('genesisHash required for forkHash calculation');
613
+ return this._calcForkHash(hardfork, genesisHash);
614
+ }
615
+ /**
616
+ *
617
+ * @param forkHash Fork hash as a hex string
618
+ * @returns Array with hardfork data (name, block, forkHash)
619
+ */
620
+ hardforkForForkHash(forkHash) {
621
+ const resArray = this.hardforks().filter((hf) => {
622
+ return hf.forkHash === forkHash;
623
+ });
624
+ return resArray.length >= 1 ? resArray[resArray.length - 1] : null;
625
+ }
626
+ /**
627
+ * Sets any missing forkHashes on this {@link Common} instance.
628
+ * @param genesisHash The genesis block hash
629
+ */
630
+ setForkHashes(genesisHash) {
631
+ for (const hf of this.hardforks()) {
632
+ const blockOrTime = hf.timestamp ?? hf.block;
633
+ if ((hf.forkHash === null || hf.forkHash === undefined) &&
634
+ blockOrTime !== null &&
635
+ blockOrTime !== undefined) {
636
+ hf.forkHash = this.forkHash(hf.name, genesisHash);
637
+ }
638
+ }
639
+ }
640
+ /**
641
+ * Returns the Genesis parameters of the current chain
642
+ * @returns Genesis dictionary
643
+ */
644
+ genesis() {
645
+ return this._chainParams.genesis;
646
+ }
647
+ /**
648
+ * Returns the hardfork definitions for the current chain.
649
+ * @returns Array of hardfork transition configs
650
+ */
651
+ hardforks() {
652
+ const hfs = this._chainParams.hardforks;
653
+ if (this._chainParams.customHardforks !== undefined) {
654
+ // Add transition configs for custom hardforks that aren't already in the hardforks array
655
+ const existingNames = new Set(hfs.map((hf) => hf.name));
656
+ const customHfEntries = Object.keys(this._chainParams.customHardforks)
657
+ .filter((name) => !existingNames.has(name))
658
+ .map((name) => ({
659
+ name,
660
+ block: null, // Custom hardforks without explicit transition config default to null (inactive by block)
661
+ }));
662
+ return [...hfs, ...customHfEntries];
663
+ }
664
+ return hfs;
665
+ }
666
+ /**
667
+ * Returns bootstrap nodes for the current chain.
668
+ * @returns Array of bootstrap node configs
669
+ */
670
+ bootstrapNodes() {
671
+ return this._chainParams.bootstrapNodes;
672
+ }
673
+ /**
674
+ * Returns DNS networks for the current chain
675
+ * @returns {String[]} Array of DNS ENR urls
676
+ */
677
+ dnsNetworks() {
678
+ return this._chainParams.dnsNetworks;
679
+ }
680
+ /**
681
+ * Returns the hardfork set
682
+ * @returns Hardfork name
683
+ */
684
+ hardfork() {
685
+ return this._hardfork;
686
+ }
687
+ /**
688
+ * Returns the Id of current chain
689
+ * @returns chain Id
690
+ */
691
+ chainId() {
692
+ return BigInt(this._chainParams.chainId);
693
+ }
694
+ /**
695
+ * Returns the name of current chain
696
+ * @returns chain name (lower case)
697
+ */
698
+ chainName() {
699
+ return this._chainParams.name;
700
+ }
701
+ /**
702
+ * Returns the additionally activated EIPs
703
+ * (by using the `eips` constructor option)
704
+ * @returns List of EIPs
705
+ */
706
+ eips() {
707
+ return this._eips;
708
+ }
709
+ /**
710
+ * Returns the consensus type of the network
711
+ * Possible values: "pow"|"poa"|"pos"
712
+ *
713
+ * Note: This value can update along a Hardfork.
714
+ */
715
+ consensusType() {
716
+ const hardfork = this.hardfork();
717
+ let value;
718
+ for (const hfChanges of this.HARDFORK_CHANGES) {
719
+ if ('consensus' in hfChanges[1]) {
720
+ value = hfChanges[1]['consensus']['type'];
721
+ }
722
+ if (hfChanges[0] === hardfork)
723
+ break;
724
+ }
725
+ return value ?? this._chainParams['consensus']['type'];
726
+ }
727
+ /**
728
+ * Returns the concrete consensus implementation
729
+ * algorithm or protocol for the network
730
+ * e.g. "ethash" for "pow" consensus type,
731
+ * "clique" for "poa" consensus type or
732
+ * "casper" for "pos" consensus type.
733
+ *
734
+ * Note: This value can update along a Hardfork.
735
+ */
736
+ consensusAlgorithm() {
737
+ const hardfork = this.hardfork();
738
+ let value;
739
+ for (const hfChanges of this.HARDFORK_CHANGES) {
740
+ if ('consensus' in hfChanges[1]) {
741
+ value = hfChanges[1]['consensus']['algorithm'];
742
+ }
743
+ if (hfChanges[0] === hardfork)
744
+ break;
745
+ }
746
+ return value ?? this._chainParams['consensus']['algorithm'];
747
+ }
748
+ /**
749
+ * Returns a dictionary with consensus configuration
750
+ * parameters based on the consensus algorithm
751
+ *
752
+ * Expected returns (parameters must be present in
753
+ * the respective chain JSON files):
754
+ *
755
+ * ethash: empty object
756
+ * clique: period, epoch
757
+ * casper: empty object
758
+ *
759
+ * Note: This value can update along a Hardfork.
760
+ */
761
+ consensusConfig() {
762
+ const hardfork = this.hardfork();
763
+ let value;
764
+ for (const hfChanges of this.HARDFORK_CHANGES) {
765
+ if ('consensus' in hfChanges[1]) {
766
+ // The config parameter is named after the respective consensus algorithm
767
+ const config = hfChanges[1];
768
+ const algorithm = config['consensus']['algorithm'];
769
+ value = config['consensus'][algorithm];
770
+ }
771
+ if (hfChanges[0] === hardfork)
772
+ break;
773
+ }
774
+ return (value ?? this._chainParams['consensus'][this.consensusAlgorithm()] ?? {});
775
+ }
776
+ /**
777
+ * Returns a deep copy of this {@link Common} instance.
778
+ */
779
+ copy() {
780
+ const copy = Object.assign(Object.create(Object.getPrototypeOf(this)), this);
781
+ copy.events = new EventEmitter();
782
+ return copy;
783
+ }
784
+ }
785
+ //# sourceMappingURL=common.js.map