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