@feelyourprotocol/block 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 (133) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +466 -0
  3. package/dist/cjs/block/block.d.ts +147 -0
  4. package/dist/cjs/block/block.d.ts.map +1 -0
  5. package/dist/cjs/block/block.js +415 -0
  6. package/dist/cjs/block/block.js.map +1 -0
  7. package/dist/cjs/block/constructors.d.ts +77 -0
  8. package/dist/cjs/block/constructors.d.ts.map +1 -0
  9. package/dist/cjs/block/constructors.js +298 -0
  10. package/dist/cjs/block/constructors.js.map +1 -0
  11. package/dist/cjs/block/index.d.ts +3 -0
  12. package/dist/cjs/block/index.d.ts.map +1 -0
  13. package/dist/cjs/block/index.js +19 -0
  14. package/dist/cjs/block/index.js.map +1 -0
  15. package/dist/cjs/consensus/clique.d.ts +52 -0
  16. package/dist/cjs/consensus/clique.d.ts.map +1 -0
  17. package/dist/cjs/consensus/clique.js +144 -0
  18. package/dist/cjs/consensus/clique.js.map +1 -0
  19. package/dist/cjs/consensus/ethash.d.ts +9 -0
  20. package/dist/cjs/consensus/ethash.d.ts.map +1 -0
  21. package/dist/cjs/consensus/ethash.js +13 -0
  22. package/dist/cjs/consensus/ethash.js.map +1 -0
  23. package/dist/cjs/consensus/index.d.ts +3 -0
  24. package/dist/cjs/consensus/index.d.ts.map +1 -0
  25. package/dist/cjs/consensus/index.js +29 -0
  26. package/dist/cjs/consensus/index.js.map +1 -0
  27. package/dist/cjs/from-beacon-payload.d.ts +36 -0
  28. package/dist/cjs/from-beacon-payload.d.ts.map +1 -0
  29. package/dist/cjs/from-beacon-payload.js +48 -0
  30. package/dist/cjs/from-beacon-payload.js.map +1 -0
  31. package/dist/cjs/header/constructors.d.ts +39 -0
  32. package/dist/cjs/header/constructors.d.ts.map +1 -0
  33. package/dist/cjs/header/constructors.js +127 -0
  34. package/dist/cjs/header/constructors.js.map +1 -0
  35. package/dist/cjs/header/header.d.ts +134 -0
  36. package/dist/cjs/header/header.d.ts.map +1 -0
  37. package/dist/cjs/header/header.js +699 -0
  38. package/dist/cjs/header/header.js.map +1 -0
  39. package/dist/cjs/header/index.d.ts +3 -0
  40. package/dist/cjs/header/index.d.ts.map +1 -0
  41. package/dist/cjs/header/index.js +19 -0
  42. package/dist/cjs/header/index.js.map +1 -0
  43. package/dist/cjs/helpers.d.ts +59 -0
  44. package/dist/cjs/helpers.d.ts.map +1 -0
  45. package/dist/cjs/helpers.js +172 -0
  46. package/dist/cjs/helpers.js.map +1 -0
  47. package/dist/cjs/index.d.ts +8 -0
  48. package/dist/cjs/index.d.ts.map +1 -0
  49. package/dist/cjs/index.js +31 -0
  50. package/dist/cjs/index.js.map +1 -0
  51. package/dist/cjs/package.json +3 -0
  52. package/dist/cjs/params.d.ts +3 -0
  53. package/dist/cjs/params.d.ts.map +1 -0
  54. package/dist/cjs/params.js +97 -0
  55. package/dist/cjs/params.js.map +1 -0
  56. package/dist/cjs/types.d.ts +228 -0
  57. package/dist/cjs/types.d.ts.map +1 -0
  58. package/dist/cjs/types.js +3 -0
  59. package/dist/cjs/types.js.map +1 -0
  60. package/dist/esm/block/block.d.ts +147 -0
  61. package/dist/esm/block/block.d.ts.map +1 -0
  62. package/dist/esm/block/block.js +411 -0
  63. package/dist/esm/block/block.js.map +1 -0
  64. package/dist/esm/block/constructors.d.ts +77 -0
  65. package/dist/esm/block/constructors.d.ts.map +1 -0
  66. package/dist/esm/block/constructors.js +286 -0
  67. package/dist/esm/block/constructors.js.map +1 -0
  68. package/dist/esm/block/index.d.ts +3 -0
  69. package/dist/esm/block/index.d.ts.map +1 -0
  70. package/dist/esm/block/index.js +3 -0
  71. package/dist/esm/block/index.js.map +1 -0
  72. package/dist/esm/consensus/clique.d.ts +52 -0
  73. package/dist/esm/consensus/clique.d.ts.map +1 -0
  74. package/dist/esm/consensus/clique.js +132 -0
  75. package/dist/esm/consensus/clique.js.map +1 -0
  76. package/dist/esm/consensus/ethash.d.ts +9 -0
  77. package/dist/esm/consensus/ethash.d.ts.map +1 -0
  78. package/dist/esm/consensus/ethash.js +10 -0
  79. package/dist/esm/consensus/ethash.js.map +1 -0
  80. package/dist/esm/consensus/index.d.ts +3 -0
  81. package/dist/esm/consensus/index.d.ts.map +1 -0
  82. package/dist/esm/consensus/index.js +3 -0
  83. package/dist/esm/consensus/index.js.map +1 -0
  84. package/dist/esm/from-beacon-payload.d.ts +36 -0
  85. package/dist/esm/from-beacon-payload.d.ts.map +1 -0
  86. package/dist/esm/from-beacon-payload.js +45 -0
  87. package/dist/esm/from-beacon-payload.js.map +1 -0
  88. package/dist/esm/header/constructors.d.ts +39 -0
  89. package/dist/esm/header/constructors.d.ts.map +1 -0
  90. package/dist/esm/header/constructors.js +120 -0
  91. package/dist/esm/header/constructors.js.map +1 -0
  92. package/dist/esm/header/header.d.ts +134 -0
  93. package/dist/esm/header/header.d.ts.map +1 -0
  94. package/dist/esm/header/header.js +695 -0
  95. package/dist/esm/header/header.js.map +1 -0
  96. package/dist/esm/header/index.d.ts +3 -0
  97. package/dist/esm/header/index.d.ts.map +1 -0
  98. package/dist/esm/header/index.js +3 -0
  99. package/dist/esm/header/index.js.map +1 -0
  100. package/dist/esm/helpers.d.ts +59 -0
  101. package/dist/esm/helpers.d.ts.map +1 -0
  102. package/dist/esm/helpers.js +161 -0
  103. package/dist/esm/helpers.js.map +1 -0
  104. package/dist/esm/index.d.ts +8 -0
  105. package/dist/esm/index.d.ts.map +1 -0
  106. package/dist/esm/index.js +8 -0
  107. package/dist/esm/index.js.map +1 -0
  108. package/dist/esm/package.json +3 -0
  109. package/dist/esm/params.d.ts +3 -0
  110. package/dist/esm/params.d.ts.map +1 -0
  111. package/dist/esm/params.js +94 -0
  112. package/dist/esm/params.js.map +1 -0
  113. package/dist/esm/types.d.ts +228 -0
  114. package/dist/esm/types.d.ts.map +1 -0
  115. package/dist/esm/types.js +2 -0
  116. package/dist/esm/types.js.map +1 -0
  117. package/dist/tsconfig.prod.cjs.tsbuildinfo +1 -0
  118. package/dist/tsconfig.prod.esm.tsbuildinfo +1 -0
  119. package/package.json +75 -0
  120. package/src/block/block.ts +526 -0
  121. package/src/block/constructors.ts +407 -0
  122. package/src/block/index.ts +2 -0
  123. package/src/consensus/clique.ts +171 -0
  124. package/src/consensus/ethash.ts +11 -0
  125. package/src/consensus/index.ts +12 -0
  126. package/src/from-beacon-payload.ts +82 -0
  127. package/src/header/constructors.ts +169 -0
  128. package/src/header/header.ts +890 -0
  129. package/src/header/index.ts +2 -0
  130. package/src/helpers.ts +223 -0
  131. package/src/index.ts +13 -0
  132. package/src/params.ts +95 -0
  133. package/src/types.ts +254 -0
@@ -0,0 +1,695 @@
1
+ import { Common, ConsensusAlgorithm, ConsensusType, Hardfork, Mainnet } from '@feelyourprotocol/common';
2
+ import { RLP } from '@feelyourprotocol/rlp';
3
+ import { Address, BIGINT_0, BIGINT_1, BIGINT_2, BIGINT_7, EthereumJSErrorWithoutCode, KECCAK256_RLP, KECCAK256_RLP_ARRAY, SHA256_NULL, TypeOutput, bigIntToHex, bigIntToUnpaddedBytes, bytesToHex, bytesToUtf8, createZeroAddress, equalsBytes, hexToBytes, toType, } from '@feelyourprotocol/util';
4
+ import { keccak_256 } from '@noble/hashes/sha3.js';
5
+ import { CLIQUE_EXTRA_SEAL, CLIQUE_EXTRA_VANITY, cliqueIsEpochTransition, } from "../consensus/clique.js";
6
+ import { computeBlobGasPrice } from "../helpers.js";
7
+ import { paramsBlock } from "../params.js";
8
+ const DEFAULT_GAS_LIMIT = BigInt('0xffffffffffffff');
9
+ /**
10
+ * An object that represents the block header.
11
+ */
12
+ export class BlockHeader {
13
+ /**
14
+ * EIP-4399: After merge to PoS, `mixHash` supplanted as `prevRandao`
15
+ */
16
+ get prevRandao() {
17
+ if (!this.common.isActivatedEIP(4399)) {
18
+ const msg = this._errorMsg('The prevRandao parameter can only be accessed when EIP-4399 is activated');
19
+ throw EthereumJSErrorWithoutCode(msg);
20
+ }
21
+ return this.mixHash;
22
+ }
23
+ /**
24
+ * This constructor takes the values, validates them, assigns them and freezes the object.
25
+ *
26
+ * @deprecated Use the public static factory methods to assist in creating a Header object from
27
+ * varying data types. For a default empty header, use {@link createBlockHeader}.
28
+ *
29
+ */
30
+ constructor(headerData, opts = {}) {
31
+ this.cache = {
32
+ hash: undefined,
33
+ };
34
+ if (opts.common) {
35
+ this.common = opts.common.copy();
36
+ }
37
+ else {
38
+ this.common = new Common({
39
+ chain: Mainnet, // default
40
+ });
41
+ }
42
+ this.common.updateParams(opts.params ?? paramsBlock);
43
+ this.keccakFunction = this.common.customCrypto.keccak256 ?? keccak_256;
44
+ const skipValidateConsensusFormat = opts.skipConsensusFormatValidation ?? false;
45
+ const defaults = {
46
+ parentHash: new Uint8Array(32),
47
+ uncleHash: KECCAK256_RLP_ARRAY,
48
+ coinbase: createZeroAddress(),
49
+ stateRoot: new Uint8Array(32),
50
+ transactionsTrie: KECCAK256_RLP,
51
+ receiptTrie: KECCAK256_RLP,
52
+ logsBloom: new Uint8Array(256),
53
+ difficulty: BIGINT_0,
54
+ number: BIGINT_0,
55
+ gasLimit: DEFAULT_GAS_LIMIT,
56
+ gasUsed: BIGINT_0,
57
+ timestamp: BIGINT_0,
58
+ extraData: new Uint8Array(0),
59
+ mixHash: new Uint8Array(32),
60
+ nonce: new Uint8Array(8),
61
+ };
62
+ const parentHash = toType(headerData.parentHash, TypeOutput.Uint8Array) ?? defaults.parentHash;
63
+ const uncleHash = toType(headerData.uncleHash, TypeOutput.Uint8Array) ?? defaults.uncleHash;
64
+ const coinbase = new Address(toType(headerData.coinbase ?? defaults.coinbase, TypeOutput.Uint8Array));
65
+ const stateRoot = toType(headerData.stateRoot, TypeOutput.Uint8Array) ?? defaults.stateRoot;
66
+ const transactionsTrie = toType(headerData.transactionsTrie, TypeOutput.Uint8Array) ?? defaults.transactionsTrie;
67
+ const receiptTrie = toType(headerData.receiptTrie, TypeOutput.Uint8Array) ?? defaults.receiptTrie;
68
+ const logsBloom = toType(headerData.logsBloom, TypeOutput.Uint8Array) ?? defaults.logsBloom;
69
+ const difficulty = toType(headerData.difficulty, TypeOutput.BigInt) ?? defaults.difficulty;
70
+ const number = toType(headerData.number, TypeOutput.BigInt) ?? defaults.number;
71
+ const gasLimit = toType(headerData.gasLimit, TypeOutput.BigInt) ?? defaults.gasLimit;
72
+ const gasUsed = toType(headerData.gasUsed, TypeOutput.BigInt) ?? defaults.gasUsed;
73
+ const timestamp = toType(headerData.timestamp, TypeOutput.BigInt) ?? defaults.timestamp;
74
+ const extraData = toType(headerData.extraData, TypeOutput.Uint8Array) ?? defaults.extraData;
75
+ const mixHash = toType(headerData.mixHash, TypeOutput.Uint8Array) ?? defaults.mixHash;
76
+ const nonce = toType(headerData.nonce, TypeOutput.Uint8Array) ?? defaults.nonce;
77
+ const setHardfork = opts.setHardfork ?? false;
78
+ if (setHardfork === true) {
79
+ this.common.setHardforkBy({
80
+ blockNumber: number,
81
+ timestamp,
82
+ });
83
+ }
84
+ // Hardfork defaults which couldn't be paired with earlier defaults
85
+ const hardforkDefaults = {
86
+ baseFeePerGas: this.common.isActivatedEIP(1559)
87
+ ? number === this.common.hardforkBlock(Hardfork.London)
88
+ ? this.common.param('initialBaseFee')
89
+ : BIGINT_7
90
+ : undefined,
91
+ withdrawalsRoot: this.common.isActivatedEIP(4895) ? KECCAK256_RLP : undefined,
92
+ blobGasUsed: this.common.isActivatedEIP(4844) ? BIGINT_0 : undefined,
93
+ excessBlobGas: this.common.isActivatedEIP(4844) ? BIGINT_0 : undefined,
94
+ parentBeaconBlockRoot: this.common.isActivatedEIP(4788) ? new Uint8Array(32) : undefined,
95
+ // Note: as of devnet-4 we stub the null SHA256 hash, but for devnet5 this will actually
96
+ // be the correct hash for empty requests.
97
+ requestsHash: this.common.isActivatedEIP(7685) ? SHA256_NULL : undefined,
98
+ blockAccessListHash: this.common.isActivatedEIP(7928) ? new Uint8Array(32) : undefined,
99
+ slotNumber: this.common.isActivatedEIP(7843) ? BIGINT_0 : undefined,
100
+ };
101
+ const baseFeePerGas = toType(headerData.baseFeePerGas, TypeOutput.BigInt) ?? hardforkDefaults.baseFeePerGas;
102
+ const withdrawalsRoot = toType(headerData.withdrawalsRoot, TypeOutput.Uint8Array) ?? hardforkDefaults.withdrawalsRoot;
103
+ const blobGasUsed = toType(headerData.blobGasUsed, TypeOutput.BigInt) ?? hardforkDefaults.blobGasUsed;
104
+ const excessBlobGas = toType(headerData.excessBlobGas, TypeOutput.BigInt) ?? hardforkDefaults.excessBlobGas;
105
+ const parentBeaconBlockRoot = toType(headerData.parentBeaconBlockRoot, TypeOutput.Uint8Array) ??
106
+ hardforkDefaults.parentBeaconBlockRoot;
107
+ const requestsHash = toType(headerData.requestsHash, TypeOutput.Uint8Array) ?? hardforkDefaults.requestsHash;
108
+ const blockAccessListHash = toType(headerData.blockAccessListHash, TypeOutput.Uint8Array) ??
109
+ hardforkDefaults.blockAccessListHash;
110
+ const slotNumber = toType(headerData.slotNumber, TypeOutput.BigInt) ?? hardforkDefaults.slotNumber;
111
+ if (!this.common.isActivatedEIP(1559) && baseFeePerGas !== undefined) {
112
+ throw EthereumJSErrorWithoutCode('A base fee for a block can only be set with EIP1559 being activated');
113
+ }
114
+ if (!this.common.isActivatedEIP(4895) && withdrawalsRoot !== undefined) {
115
+ throw EthereumJSErrorWithoutCode('A withdrawalsRoot for a header can only be provided with EIP4895 being activated');
116
+ }
117
+ if (!this.common.isActivatedEIP(4844)) {
118
+ if (blobGasUsed !== undefined) {
119
+ throw EthereumJSErrorWithoutCode('blob gas used can only be provided with EIP4844 activated');
120
+ }
121
+ if (excessBlobGas !== undefined) {
122
+ throw EthereumJSErrorWithoutCode('excess blob gas can only be provided with EIP4844 activated');
123
+ }
124
+ }
125
+ if (!this.common.isActivatedEIP(4788) && parentBeaconBlockRoot !== undefined) {
126
+ throw EthereumJSErrorWithoutCode('A parentBeaconBlockRoot for a header can only be provided with EIP4788 being activated');
127
+ }
128
+ if (!this.common.isActivatedEIP(7685) && requestsHash !== undefined) {
129
+ throw EthereumJSErrorWithoutCode('requestsHash can only be provided with EIP 7685 activated');
130
+ }
131
+ if (!this.common.isActivatedEIP(7928) && blockAccessListHash !== undefined) {
132
+ throw EthereumJSErrorWithoutCode('blockAccessListHash can only be provided with EIP 7928 activated');
133
+ }
134
+ if (!this.common.isActivatedEIP(7843) && slotNumber !== undefined) {
135
+ throw EthereumJSErrorWithoutCode('slotNumber can only be provided with EIP 7843 activated');
136
+ }
137
+ this.parentHash = parentHash;
138
+ this.uncleHash = uncleHash;
139
+ this.coinbase = coinbase;
140
+ this.stateRoot = stateRoot;
141
+ this.transactionsTrie = transactionsTrie;
142
+ this.receiptTrie = receiptTrie;
143
+ this.logsBloom = logsBloom;
144
+ this.difficulty = difficulty;
145
+ this.number = number;
146
+ this.gasLimit = gasLimit;
147
+ this.gasUsed = gasUsed;
148
+ this.timestamp = timestamp;
149
+ this.extraData = extraData;
150
+ this.mixHash = mixHash;
151
+ this.nonce = nonce;
152
+ this.baseFeePerGas = baseFeePerGas;
153
+ this.withdrawalsRoot = withdrawalsRoot;
154
+ this.blobGasUsed = blobGasUsed;
155
+ this.excessBlobGas = excessBlobGas;
156
+ this.parentBeaconBlockRoot = parentBeaconBlockRoot;
157
+ this.requestsHash = requestsHash;
158
+ this.blockAccessListHash = blockAccessListHash;
159
+ this.slotNumber = slotNumber;
160
+ this._genericFormatValidation();
161
+ this._validateDAOExtraData();
162
+ // Now we have set all the values of this Header, we possibly have set a dummy
163
+ // `difficulty` value (defaults to 0). If we have a `calcDifficultyFromHeader`
164
+ // block option parameter, we instead set difficulty to this value.
165
+ if (opts.calcDifficultyFromHeader &&
166
+ this.common.consensusAlgorithm() === ConsensusAlgorithm.Ethash) {
167
+ this.difficulty = this.ethashCanonicalDifficulty(opts.calcDifficultyFromHeader);
168
+ }
169
+ // Validate consensus format after block is sealed (if applicable) so extraData checks will pass
170
+ if (skipValidateConsensusFormat === false)
171
+ this._consensusFormatValidation();
172
+ const freeze = opts?.freeze ?? true;
173
+ if (freeze) {
174
+ Object.freeze(this);
175
+ }
176
+ }
177
+ /**
178
+ * Validates correct buffer lengths, throws if invalid.
179
+ */
180
+ _genericFormatValidation() {
181
+ const { parentHash, stateRoot, transactionsTrie, receiptTrie, mixHash, nonce } = this;
182
+ if (parentHash.length !== 32) {
183
+ const msg = this._errorMsg(`parentHash must be 32 bytes, received ${parentHash.length} bytes`);
184
+ throw EthereumJSErrorWithoutCode(msg);
185
+ }
186
+ if (stateRoot.length !== 32) {
187
+ const msg = this._errorMsg(`stateRoot must be 32 bytes, received ${stateRoot.length} bytes`);
188
+ throw EthereumJSErrorWithoutCode(msg);
189
+ }
190
+ if (transactionsTrie.length !== 32) {
191
+ const msg = this._errorMsg(`transactionsTrie must be 32 bytes, received ${transactionsTrie.length} bytes`);
192
+ throw EthereumJSErrorWithoutCode(msg);
193
+ }
194
+ if (receiptTrie.length !== 32) {
195
+ const msg = this._errorMsg(`receiptTrie must be 32 bytes, received ${receiptTrie.length} bytes`);
196
+ throw EthereumJSErrorWithoutCode(msg);
197
+ }
198
+ if (mixHash.length !== 32) {
199
+ const msg = this._errorMsg(`mixHash must be 32 bytes, received ${mixHash.length} bytes`);
200
+ throw EthereumJSErrorWithoutCode(msg);
201
+ }
202
+ if (nonce.length !== 8) {
203
+ const msg = this._errorMsg(`nonce must be 8 bytes, received ${nonce.length} bytes`);
204
+ throw EthereumJSErrorWithoutCode(msg);
205
+ }
206
+ // check if the block used too much gas
207
+ if (this.gasUsed > this.gasLimit) {
208
+ const msg = this._errorMsg(`Invalid block: too much gas used. Used: ${this.gasUsed}, gas limit: ${this.gasLimit}`);
209
+ throw EthereumJSErrorWithoutCode(msg);
210
+ }
211
+ // Validation for EIP-1559 blocks
212
+ if (this.common.isActivatedEIP(1559)) {
213
+ if (typeof this.baseFeePerGas !== 'bigint') {
214
+ const msg = this._errorMsg('EIP1559 block has no base fee field');
215
+ throw EthereumJSErrorWithoutCode(msg);
216
+ }
217
+ const londonHfBlock = this.common.hardforkBlock(Hardfork.London);
218
+ if (typeof londonHfBlock === 'bigint' &&
219
+ londonHfBlock !== BIGINT_0 &&
220
+ this.number === londonHfBlock) {
221
+ const initialBaseFee = this.common.param('initialBaseFee');
222
+ if (this.baseFeePerGas !== initialBaseFee) {
223
+ const msg = this._errorMsg('Initial EIP1559 block does not have initial base fee');
224
+ throw EthereumJSErrorWithoutCode(msg);
225
+ }
226
+ }
227
+ }
228
+ if (this.common.isActivatedEIP(4895)) {
229
+ if (this.withdrawalsRoot === undefined) {
230
+ const msg = this._errorMsg('EIP4895 block has no withdrawalsRoot field');
231
+ throw EthereumJSErrorWithoutCode(msg);
232
+ }
233
+ if (this.withdrawalsRoot?.length !== 32) {
234
+ const msg = this._errorMsg(`withdrawalsRoot must be 32 bytes, received ${this.withdrawalsRoot.length} bytes`);
235
+ throw EthereumJSErrorWithoutCode(msg);
236
+ }
237
+ }
238
+ if (this.common.isActivatedEIP(4788)) {
239
+ if (this.parentBeaconBlockRoot === undefined) {
240
+ const msg = this._errorMsg('EIP4788 block has no parentBeaconBlockRoot field');
241
+ throw EthereumJSErrorWithoutCode(msg);
242
+ }
243
+ if (this.parentBeaconBlockRoot?.length !== 32) {
244
+ const msg = this._errorMsg(`parentBeaconBlockRoot must be 32 bytes, received ${this.parentBeaconBlockRoot.length} bytes`);
245
+ throw EthereumJSErrorWithoutCode(msg);
246
+ }
247
+ }
248
+ if (this.common.isActivatedEIP(7685)) {
249
+ if (this.requestsHash === undefined) {
250
+ const msg = this._errorMsg('EIP7685 block has no requestsHash field');
251
+ throw EthereumJSErrorWithoutCode(msg);
252
+ }
253
+ }
254
+ if (this.common.isActivatedEIP(7928)) {
255
+ if (this.blockAccessListHash === undefined) {
256
+ const msg = this._errorMsg('EIP7928 block has no blockAccessListHash field');
257
+ throw EthereumJSErrorWithoutCode(msg);
258
+ }
259
+ if (this.blockAccessListHash?.length !== 32) {
260
+ const msg = this._errorMsg(`blockAccessListHash must be 32 bytes, received ${this.blockAccessListHash.length} bytes`);
261
+ throw EthereumJSErrorWithoutCode(msg);
262
+ }
263
+ }
264
+ if (this.common.isActivatedEIP(7843)) {
265
+ if (this.slotNumber === undefined) {
266
+ const msg = this._errorMsg('EIP7843 block has no slotNumber field');
267
+ throw EthereumJSErrorWithoutCode(msg);
268
+ }
269
+ }
270
+ }
271
+ /**
272
+ * Checks static parameters related to consensus algorithm
273
+ * @throws if any check fails
274
+ */
275
+ _consensusFormatValidation() {
276
+ const { nonce, uncleHash, difficulty, extraData, number } = this;
277
+ // Consensus type dependent checks
278
+ if (this.common.consensusAlgorithm() === ConsensusAlgorithm.Ethash) {
279
+ // PoW/Ethash
280
+ if (number > BIGINT_0 && this.extraData.length > this.common.param('maxExtraDataSize')) {
281
+ // Check length of data on all post-genesis blocks
282
+ const msg = this._errorMsg('invalid amount of extra data');
283
+ throw EthereumJSErrorWithoutCode(msg);
284
+ }
285
+ }
286
+ if (this.common.consensusAlgorithm() === ConsensusAlgorithm.Clique) {
287
+ // PoA/Clique
288
+ const minLength = CLIQUE_EXTRA_VANITY + CLIQUE_EXTRA_SEAL;
289
+ if (!cliqueIsEpochTransition(this)) {
290
+ // ExtraData length on epoch transition
291
+ if (this.extraData.length !== minLength) {
292
+ const msg = this._errorMsg(`extraData must be ${minLength} bytes on non-epoch transition blocks, received ${this.extraData.length} bytes`);
293
+ throw EthereumJSErrorWithoutCode(msg);
294
+ }
295
+ }
296
+ else {
297
+ const signerLength = this.extraData.length - minLength;
298
+ if (signerLength % 20 !== 0) {
299
+ const msg = this._errorMsg(`invalid signer list length in extraData, received signer length of ${signerLength} (not divisible by 20)`);
300
+ throw EthereumJSErrorWithoutCode(msg);
301
+ }
302
+ // coinbase (beneficiary) on epoch transition
303
+ if (!this.coinbase.isZero()) {
304
+ const msg = this._errorMsg(`coinbase must be filled with zeros on epoch transition blocks, received ${this.coinbase}`);
305
+ throw EthereumJSErrorWithoutCode(msg);
306
+ }
307
+ }
308
+ // MixHash format
309
+ if (!equalsBytes(this.mixHash, new Uint8Array(32))) {
310
+ const msg = this._errorMsg(`mixHash must be filled with zeros, received ${this.mixHash}`);
311
+ throw EthereumJSErrorWithoutCode(msg);
312
+ }
313
+ }
314
+ // Validation for PoS blocks (EIP-3675)
315
+ if (this.common.consensusType() === ConsensusType.ProofOfStake) {
316
+ let error = false;
317
+ let errorMsg = '';
318
+ if (!equalsBytes(uncleHash, KECCAK256_RLP_ARRAY)) {
319
+ errorMsg += `, uncleHash: ${bytesToHex(uncleHash)} (expected: ${bytesToHex(KECCAK256_RLP_ARRAY)})`;
320
+ error = true;
321
+ }
322
+ if (number !== BIGINT_0) {
323
+ // Skip difficulty, nonce, and extraData check for PoS genesis block as genesis block may have non-zero difficulty (if TD is > 0)
324
+ if (difficulty !== BIGINT_0) {
325
+ errorMsg += `, difficulty: ${difficulty} (expected: 0)`;
326
+ error = true;
327
+ }
328
+ if (extraData.length > 32) {
329
+ errorMsg += `, extraData: ${bytesToHex(extraData)} (cannot exceed 32 bytes length, received ${extraData.length} bytes)`;
330
+ error = true;
331
+ }
332
+ if (!equalsBytes(nonce, new Uint8Array(8))) {
333
+ errorMsg += `, nonce: ${bytesToHex(nonce)} (expected: ${bytesToHex(new Uint8Array(8))})`;
334
+ error = true;
335
+ }
336
+ }
337
+ if (error) {
338
+ const msg = this._errorMsg(`Invalid PoS block: ${errorMsg}`);
339
+ throw EthereumJSErrorWithoutCode(msg);
340
+ }
341
+ }
342
+ }
343
+ /**
344
+ * Validates if the block gasLimit remains in the boundaries set by the protocol.
345
+ * Throws if out of bounds.
346
+ *
347
+ * @param parentBlockHeader - the header from the parent `Block` of this header
348
+ */
349
+ validateGasLimit(parentBlockHeader) {
350
+ let parentGasLimit = parentBlockHeader.gasLimit;
351
+ // EIP-1559: assume double the parent gas limit on fork block
352
+ // to adopt to the new gas target centered logic
353
+ const londonHardforkBlock = this.common.hardforkBlock(Hardfork.London);
354
+ if (typeof londonHardforkBlock === 'bigint' &&
355
+ londonHardforkBlock !== BIGINT_0 &&
356
+ this.number === londonHardforkBlock) {
357
+ const elasticity = this.common.param('elasticityMultiplier');
358
+ parentGasLimit = parentGasLimit * elasticity;
359
+ }
360
+ const gasLimit = this.gasLimit;
361
+ const a = parentGasLimit / this.common.param('gasLimitBoundDivisor');
362
+ const maxGasLimit = parentGasLimit + a;
363
+ const minGasLimit = parentGasLimit - a;
364
+ if (gasLimit >= maxGasLimit) {
365
+ const msg = this._errorMsg(`gas limit increased too much. Gas limit: ${gasLimit}, max gas limit: ${maxGasLimit}`);
366
+ throw EthereumJSErrorWithoutCode(msg);
367
+ }
368
+ if (gasLimit <= minGasLimit) {
369
+ const msg = this._errorMsg(`gas limit decreased too much. Gas limit: ${gasLimit}, min gas limit: ${minGasLimit}`);
370
+ throw EthereumJSErrorWithoutCode(msg);
371
+ }
372
+ if (gasLimit < this.common.param('minGasLimit')) {
373
+ const msg = this._errorMsg(`gas limit decreased below minimum gas limit. Gas limit: ${gasLimit}, minimum gas limit: ${this.common.param('minGasLimit')}`);
374
+ throw EthereumJSErrorWithoutCode(msg);
375
+ }
376
+ }
377
+ /**
378
+ * Calculates the base fee for a potential next block
379
+ */
380
+ calcNextBaseFee() {
381
+ if (!this.common.isActivatedEIP(1559)) {
382
+ const msg = this._errorMsg('calcNextBaseFee() can only be called with EIP1559 being activated');
383
+ throw EthereumJSErrorWithoutCode(msg);
384
+ }
385
+ let nextBaseFee;
386
+ const elasticity = this.common.param('elasticityMultiplier');
387
+ const parentGasTarget = this.gasLimit / elasticity;
388
+ if (parentGasTarget === this.gasUsed) {
389
+ nextBaseFee = this.baseFeePerGas;
390
+ }
391
+ else if (this.gasUsed > parentGasTarget) {
392
+ const gasUsedDelta = this.gasUsed - parentGasTarget;
393
+ const baseFeeMaxChangeDenominator = this.common.param('baseFeeMaxChangeDenominator');
394
+ const calculatedDelta = (this.baseFeePerGas * gasUsedDelta) / parentGasTarget / baseFeeMaxChangeDenominator;
395
+ nextBaseFee = (calculatedDelta > BIGINT_1 ? calculatedDelta : BIGINT_1) + this.baseFeePerGas;
396
+ }
397
+ else {
398
+ const gasUsedDelta = parentGasTarget - this.gasUsed;
399
+ const baseFeeMaxChangeDenominator = this.common.param('baseFeeMaxChangeDenominator');
400
+ const calculatedDelta = (this.baseFeePerGas * gasUsedDelta) / parentGasTarget / baseFeeMaxChangeDenominator;
401
+ nextBaseFee =
402
+ this.baseFeePerGas - calculatedDelta > BIGINT_0
403
+ ? this.baseFeePerGas - calculatedDelta
404
+ : BIGINT_0;
405
+ }
406
+ return nextBaseFee;
407
+ }
408
+ /**
409
+ * Returns the price per unit of blob gas for a blob transaction in the current/pending block
410
+ * @returns the price in gwei per unit of blob gas spent
411
+ */
412
+ getBlobGasPrice() {
413
+ if (this.excessBlobGas === undefined) {
414
+ throw EthereumJSErrorWithoutCode('header must have excessBlobGas field populated');
415
+ }
416
+ return computeBlobGasPrice(this.excessBlobGas, this.common);
417
+ }
418
+ /**
419
+ * Returns the total fee for blob gas spent for including blobs in block.
420
+ *
421
+ * @param numBlobs number of blobs in the transaction/block
422
+ * @returns the total blob gas fee for numBlobs blobs
423
+ */
424
+ calcDataFee(numBlobs) {
425
+ const blobGasPerBlob = this.common.param('blobGasPerBlob');
426
+ const blobGasUsed = blobGasPerBlob * BigInt(numBlobs);
427
+ const blobGasPrice = this.getBlobGasPrice();
428
+ return blobGasUsed * blobGasPrice;
429
+ }
430
+ /**
431
+ * Calculates the excess blob gas for next (hopefully) post EIP 4844 block.
432
+ */
433
+ calcNextExcessBlobGas(childCommon) {
434
+ const excessBlobGas = this.excessBlobGas ?? BIGINT_0;
435
+ const blobGasUsed = this.blobGasUsed ?? BIGINT_0;
436
+ const { targetBlobGasPerBlock: targetPerBlock, maxBlobGasPerBlock: maxPerBlock } = childCommon.getBlobGasSchedule();
437
+ // Early exit (strictly < per spec)
438
+ if (excessBlobGas + blobGasUsed < targetPerBlock) {
439
+ return BIGINT_0;
440
+ }
441
+ // EIP-7918 reserve price check
442
+ if (childCommon.isActivatedEIP(7918)) {
443
+ const blobBaseCost = childCommon.param('blobBaseCost');
444
+ const gasPerBlob = childCommon.param('blobGasPerBlob');
445
+ const baseFee = this.baseFeePerGas ?? BIGINT_0;
446
+ const blobFee = computeBlobGasPrice(excessBlobGas, childCommon);
447
+ if (blobBaseCost * baseFee > gasPerBlob * blobFee) {
448
+ const increase = (blobGasUsed * (maxPerBlock - targetPerBlock)) / maxPerBlock;
449
+ return excessBlobGas + increase;
450
+ }
451
+ }
452
+ // Original 4844 path
453
+ return excessBlobGas + blobGasUsed - targetPerBlock;
454
+ }
455
+ /**
456
+ * Calculate the blob gas price of the block built on top of this one
457
+ * @returns The blob gas price
458
+ */
459
+ calcNextBlobGasPrice(childCommon) {
460
+ return computeBlobGasPrice(this.calcNextExcessBlobGas(childCommon), childCommon);
461
+ }
462
+ /**
463
+ * Returns a Uint8Array Array of the raw Bytes in this header, in order.
464
+ */
465
+ raw() {
466
+ const rawItems = [
467
+ this.parentHash,
468
+ this.uncleHash,
469
+ this.coinbase.bytes,
470
+ this.stateRoot,
471
+ this.transactionsTrie,
472
+ this.receiptTrie,
473
+ this.logsBloom,
474
+ bigIntToUnpaddedBytes(this.difficulty),
475
+ bigIntToUnpaddedBytes(this.number),
476
+ bigIntToUnpaddedBytes(this.gasLimit),
477
+ bigIntToUnpaddedBytes(this.gasUsed),
478
+ bigIntToUnpaddedBytes(this.timestamp ?? BIGINT_0),
479
+ this.extraData,
480
+ this.mixHash,
481
+ this.nonce,
482
+ ];
483
+ if (this.common.isActivatedEIP(1559)) {
484
+ rawItems.push(bigIntToUnpaddedBytes(this.baseFeePerGas));
485
+ }
486
+ if (this.common.isActivatedEIP(4895)) {
487
+ rawItems.push(this.withdrawalsRoot);
488
+ }
489
+ if (this.common.isActivatedEIP(4844)) {
490
+ rawItems.push(bigIntToUnpaddedBytes(this.blobGasUsed));
491
+ rawItems.push(bigIntToUnpaddedBytes(this.excessBlobGas));
492
+ }
493
+ if (this.common.isActivatedEIP(4788)) {
494
+ rawItems.push(this.parentBeaconBlockRoot);
495
+ }
496
+ if (this.common.isActivatedEIP(7685)) {
497
+ rawItems.push(this.requestsHash);
498
+ }
499
+ if (this.common.isActivatedEIP(7928)) {
500
+ rawItems.push(this.blockAccessListHash);
501
+ }
502
+ if (this.common.isActivatedEIP(7843)) {
503
+ rawItems.push(bigIntToUnpaddedBytes(this.slotNumber));
504
+ }
505
+ return rawItems;
506
+ }
507
+ /**
508
+ * Returns the hash of the block header.
509
+ */
510
+ hash() {
511
+ var _a;
512
+ if (Object.isFrozen(this)) {
513
+ (_a = this.cache).hash ?? (_a.hash = this.keccakFunction(RLP.encode(this.raw())));
514
+ return this.cache.hash;
515
+ }
516
+ return this.keccakFunction(RLP.encode(this.raw()));
517
+ }
518
+ /**
519
+ * Checks if the block header is a genesis header.
520
+ */
521
+ isGenesis() {
522
+ return this.number === BIGINT_0;
523
+ }
524
+ /**
525
+ * Returns the canonical difficulty for this block.
526
+ *
527
+ * @param parentBlockHeader - the header from the parent `Block` of this header
528
+ */
529
+ ethashCanonicalDifficulty(parentBlockHeader) {
530
+ if (this.common.consensusType() !== ConsensusType.ProofOfWork) {
531
+ const msg = this._errorMsg('difficulty calculation is only supported on PoW chains');
532
+ throw EthereumJSErrorWithoutCode(msg);
533
+ }
534
+ if (this.common.consensusAlgorithm() !== ConsensusAlgorithm.Ethash) {
535
+ const msg = this._errorMsg('difficulty calculation currently only supports the ethash algorithm');
536
+ throw EthereumJSErrorWithoutCode(msg);
537
+ }
538
+ const blockTs = this.timestamp;
539
+ const { timestamp: parentTs, difficulty: parentDif } = parentBlockHeader;
540
+ const minimumDifficulty = this.common.param('minimumDifficulty');
541
+ const offset = parentDif / this.common.param('difficultyBoundDivisor');
542
+ let num = this.number;
543
+ // We use a ! here as TS cannot follow this hardfork-dependent logic, but it always gets assigned
544
+ let dif;
545
+ if (this.common.gteHardfork(Hardfork.Byzantium)) {
546
+ // max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99) (EIP100)
547
+ const uncleAddend = equalsBytes(parentBlockHeader.uncleHash, KECCAK256_RLP_ARRAY) ? 1 : 2;
548
+ let a = BigInt(uncleAddend) - (blockTs - parentTs) / BigInt(9);
549
+ const cutoff = BigInt(-99);
550
+ // MAX(cutoff, a)
551
+ if (cutoff > a) {
552
+ a = cutoff;
553
+ }
554
+ dif = parentDif + offset * a;
555
+ }
556
+ if (this.common.gteHardfork(Hardfork.Byzantium)) {
557
+ // Get delay as parameter from common
558
+ num = num - this.common.param('difficultyBombDelay');
559
+ if (num < BIGINT_0) {
560
+ num = BIGINT_0;
561
+ }
562
+ }
563
+ else if (this.common.gteHardfork(Hardfork.Homestead)) {
564
+ // 1 - (block_timestamp - parent_timestamp) // 10
565
+ let a = BIGINT_1 - (blockTs - parentTs) / BigInt(10);
566
+ const cutoff = BigInt(-99);
567
+ // MAX(cutoff, a)
568
+ if (cutoff > a) {
569
+ a = cutoff;
570
+ }
571
+ dif = parentDif + offset * a;
572
+ }
573
+ else {
574
+ // pre-homestead
575
+ if (parentTs + this.common.param('durationLimit') > blockTs) {
576
+ dif = offset + parentDif;
577
+ }
578
+ else {
579
+ dif = parentDif - offset;
580
+ }
581
+ }
582
+ const exp = num / BigInt(100000) - BIGINT_2;
583
+ if (exp >= 0) {
584
+ dif = dif + BIGINT_2 ** exp;
585
+ }
586
+ if (dif < minimumDifficulty) {
587
+ dif = minimumDifficulty;
588
+ }
589
+ return dif;
590
+ }
591
+ /**
592
+ * Returns the rlp encoding of the block header.
593
+ */
594
+ serialize() {
595
+ return RLP.encode(this.raw());
596
+ }
597
+ /**
598
+ * Returns the block header in JSON format.
599
+ */
600
+ toJSON() {
601
+ const withdrawalAttr = this.withdrawalsRoot
602
+ ? { withdrawalsRoot: bytesToHex(this.withdrawalsRoot) }
603
+ : {};
604
+ const JSONDict = {
605
+ parentHash: bytesToHex(this.parentHash),
606
+ uncleHash: bytesToHex(this.uncleHash),
607
+ coinbase: this.coinbase.toString(),
608
+ stateRoot: bytesToHex(this.stateRoot),
609
+ transactionsTrie: bytesToHex(this.transactionsTrie),
610
+ ...withdrawalAttr,
611
+ receiptTrie: bytesToHex(this.receiptTrie),
612
+ logsBloom: bytesToHex(this.logsBloom),
613
+ difficulty: bigIntToHex(this.difficulty),
614
+ number: bigIntToHex(this.number),
615
+ gasLimit: bigIntToHex(this.gasLimit),
616
+ gasUsed: bigIntToHex(this.gasUsed),
617
+ timestamp: bigIntToHex(this.timestamp),
618
+ extraData: bytesToHex(this.extraData),
619
+ mixHash: bytesToHex(this.mixHash),
620
+ nonce: bytesToHex(this.nonce),
621
+ };
622
+ if (this.common.isActivatedEIP(1559)) {
623
+ JSONDict.baseFeePerGas = bigIntToHex(this.baseFeePerGas);
624
+ }
625
+ if (this.common.isActivatedEIP(4844)) {
626
+ JSONDict.blobGasUsed = bigIntToHex(this.blobGasUsed);
627
+ JSONDict.excessBlobGas = bigIntToHex(this.excessBlobGas);
628
+ }
629
+ if (this.common.isActivatedEIP(4788)) {
630
+ JSONDict.parentBeaconBlockRoot = bytesToHex(this.parentBeaconBlockRoot);
631
+ }
632
+ if (this.common.isActivatedEIP(7685)) {
633
+ JSONDict.requestsHash = bytesToHex(this.requestsHash);
634
+ }
635
+ if (this.common.isActivatedEIP(7928)) {
636
+ JSONDict.blockAccessListHash = bytesToHex(this.blockAccessListHash);
637
+ }
638
+ if (this.common.isActivatedEIP(7843)) {
639
+ JSONDict.slotNumber = bigIntToHex(this.slotNumber);
640
+ }
641
+ return JSONDict;
642
+ }
643
+ /**
644
+ * Validates extra data is DAO_ExtraData for DAO_ForceExtraDataRange blocks after DAO
645
+ * activation block (see: https://blog.slock.it/hard-fork-specification-24b889e70703)
646
+ */
647
+ _validateDAOExtraData() {
648
+ if (!this.common.hardforkIsActiveOnBlock(Hardfork.Dao, this.number)) {
649
+ return;
650
+ }
651
+ const DAOActivationBlock = this.common.hardforkBlock(Hardfork.Dao);
652
+ if (DAOActivationBlock === null || this.number < DAOActivationBlock) {
653
+ return;
654
+ }
655
+ const DAO_ExtraData = hexToBytes('0x64616f2d686172642d666f726b');
656
+ const DAO_ForceExtraDataRange = BigInt(9);
657
+ const drift = this.number - DAOActivationBlock;
658
+ if (drift <= DAO_ForceExtraDataRange && !equalsBytes(this.extraData, DAO_ExtraData)) {
659
+ const msg = this._errorMsg(`extraData should be 'dao-hard-fork', got ${bytesToUtf8(this.extraData)} (hex: ${bytesToHex(this.extraData)})`);
660
+ throw EthereumJSErrorWithoutCode(msg);
661
+ }
662
+ }
663
+ /**
664
+ * Return a compact error string representation of the object
665
+ */
666
+ errorStr() {
667
+ let hash = '';
668
+ try {
669
+ hash = bytesToHex(this.hash());
670
+ }
671
+ catch {
672
+ hash = 'error';
673
+ }
674
+ let hf = '';
675
+ try {
676
+ hf = this.common.hardfork();
677
+ }
678
+ catch {
679
+ hf = 'error';
680
+ }
681
+ let errorStr = `block header number=${this.number} hash=${hash} `;
682
+ errorStr += `hf=${hf} baseFeePerGas=${this.baseFeePerGas ?? 'none'}`;
683
+ return errorStr;
684
+ }
685
+ /**
686
+ * Helper function to create an annotated error message
687
+ *
688
+ * @param msg Base error message
689
+ * @hidden
690
+ */
691
+ _errorMsg(msg) {
692
+ return `${msg} (${this.errorStr()})`;
693
+ }
694
+ }
695
+ //# sourceMappingURL=header.js.map