@lodestar/beacon-node 1.48.0-dev.a4083281b7 → 1.48.0-dev.a427d3dbb5
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/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/blocks/index.js +4 -4
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/metrics.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/metrics.js +12 -1
- package/lib/chain/archiveStore/historicalState/metrics.js.map +1 -1
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +3 -2
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/chain.d.ts +2 -2
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +13 -11
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/errors/blockError.d.ts +16 -2
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js.map +1 -1
- package/lib/chain/errors/dataColumnSidecarError.d.ts +15 -2
- package/lib/chain/errors/dataColumnSidecarError.d.ts.map +1 -1
- package/lib/chain/errors/dataColumnSidecarError.js.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.d.ts +10 -0
- package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/interface.d.ts +2 -2
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +26 -4
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.js +38 -13
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +10 -0
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/network/gossip/encoding.d.ts.map +1 -1
- package/lib/network/gossip/encoding.js +0 -6
- package/lib/network/gossip/encoding.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +2 -1
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/gossip/topic.js +4 -20
- package/lib/network/gossip/topic.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +6 -7
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/index.d.ts +49 -3
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +232 -98
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/protocols.d.ts.map +1 -1
- package/lib/network/reqresp/protocols.js +6 -22
- package/lib/network/reqresp/protocols.js.map +1 -1
- package/package.json +14 -14
- package/src/api/impl/beacon/blocks/index.ts +8 -4
- package/src/chain/archiveStore/historicalState/metrics.ts +14 -1
- package/src/chain/blocks/index.ts +13 -2
- package/src/chain/chain.ts +22 -11
- package/src/chain/errors/blockError.ts +20 -8
- package/src/chain/errors/dataColumnSidecarError.ts +24 -8
- package/src/chain/errors/executionPayloadEnvelope.ts +14 -2
- package/src/chain/interface.ts +2 -2
- package/src/chain/validation/block.ts +26 -4
- package/src/chain/validation/dataColumnSidecar.ts +47 -14
- package/src/chain/validation/executionPayloadEnvelope.ts +10 -0
- package/src/network/gossip/encoding.ts +0 -6
- package/src/network/gossip/topic.ts +3 -25
- package/src/network/processor/gossipHandlers.ts +11 -11
- package/src/network/processor/index.ts +263 -148
- package/src/network/reqresp/protocols.ts +7 -24
|
@@ -134,8 +134,9 @@ export async function validateGossipBlock(
|
|
|
134
134
|
if (parentBlock.slot >= blockSlot) {
|
|
135
135
|
throw new BlockGossipError(GossipAction.REJECT, {
|
|
136
136
|
code: BlockErrorCode.NOT_LATER_THAN_PARENT,
|
|
137
|
-
parentSlot: parentBlock.slot,
|
|
138
137
|
slot: blockSlot,
|
|
138
|
+
root: blockRoot,
|
|
139
|
+
parentSlot: parentBlock.slot,
|
|
139
140
|
});
|
|
140
141
|
}
|
|
141
142
|
|
|
@@ -150,6 +151,8 @@ export async function validateGossipBlock(
|
|
|
150
151
|
if (blobKzgCommitmentsLen > maxBlobsPerBlock) {
|
|
151
152
|
throw new BlockGossipError(GossipAction.REJECT, {
|
|
152
153
|
code: BlockErrorCode.TOO_MANY_KZG_COMMITMENTS,
|
|
154
|
+
slot: blockSlot,
|
|
155
|
+
root: blockRoot,
|
|
153
156
|
blobKzgCommitmentsLen,
|
|
154
157
|
commitmentLimit: maxBlobsPerBlock,
|
|
155
158
|
});
|
|
@@ -167,6 +170,8 @@ export async function validateGossipBlock(
|
|
|
167
170
|
if (blobKzgCommitmentsLen > maxBlobsPerBlock) {
|
|
168
171
|
throw new BlockGossipError(GossipAction.REJECT, {
|
|
169
172
|
code: BlockErrorCode.TOO_MANY_KZG_COMMITMENTS,
|
|
173
|
+
slot: blockSlot,
|
|
174
|
+
root: blockRoot,
|
|
170
175
|
blobKzgCommitmentsLen,
|
|
171
176
|
commitmentLimit: maxBlobsPerBlock,
|
|
172
177
|
});
|
|
@@ -176,6 +181,8 @@ export async function validateGossipBlock(
|
|
|
176
181
|
if (!byteArrayEquals(bid.parentBlockRoot, block.parentRoot)) {
|
|
177
182
|
throw new BlockGossipError(GossipAction.REJECT, {
|
|
178
183
|
code: BlockErrorCode.BID_PARENT_ROOT_MISMATCH,
|
|
184
|
+
slot: blockSlot,
|
|
185
|
+
root: blockRoot,
|
|
179
186
|
bidParentRoot: toRootHex(bid.parentBlockRoot),
|
|
180
187
|
blockParentRoot: parentRoot,
|
|
181
188
|
});
|
|
@@ -185,6 +192,8 @@ export async function validateGossipBlock(
|
|
|
185
192
|
if (body.deposits.length !== 0) {
|
|
186
193
|
throw new BlockGossipError(GossipAction.REJECT, {
|
|
187
194
|
code: BlockErrorCode.NON_ZERO_DEPOSITS,
|
|
195
|
+
slot: blockSlot,
|
|
196
|
+
root: blockRoot,
|
|
188
197
|
count: body.deposits.length,
|
|
189
198
|
});
|
|
190
199
|
}
|
|
@@ -249,6 +258,8 @@ export async function validateGossipBlock(
|
|
|
249
258
|
if (executionPayload.timestamp !== computeTimeAtSlot(config, blockSlot, chain.genesisTime)) {
|
|
250
259
|
throw new BlockGossipError(GossipAction.REJECT, {
|
|
251
260
|
code: BlockErrorCode.INCORRECT_TIMESTAMP,
|
|
261
|
+
slot: blockSlot,
|
|
262
|
+
root: blockRoot,
|
|
252
263
|
timestamp: executionPayload.timestamp,
|
|
253
264
|
expectedTimestamp,
|
|
254
265
|
});
|
|
@@ -258,7 +269,12 @@ export async function validateGossipBlock(
|
|
|
258
269
|
|
|
259
270
|
// [REJECT] The proposer index is a valid validator index
|
|
260
271
|
if (proposerIndex >= state.validatorCount) {
|
|
261
|
-
throw new BlockGossipError(GossipAction.REJECT, {
|
|
272
|
+
throw new BlockGossipError(GossipAction.REJECT, {
|
|
273
|
+
code: BlockErrorCode.UNKNOWN_PROPOSER,
|
|
274
|
+
slot: blockSlot,
|
|
275
|
+
root: blockRoot,
|
|
276
|
+
proposerIndex,
|
|
277
|
+
});
|
|
262
278
|
}
|
|
263
279
|
|
|
264
280
|
// [REJECT] The proposer signature, signed_beacon_block.signature, is valid with respect to the proposer_index pubkey.
|
|
@@ -270,7 +286,12 @@ export async function validateGossipBlock(
|
|
|
270
286
|
// shuffling, the block MAY be queued for later processing while proposers for the block's branch are calculated --
|
|
271
287
|
// in such a case do not REJECT, instead IGNORE this message.
|
|
272
288
|
if (state.getBeaconProposer(blockSlot) !== proposerIndex) {
|
|
273
|
-
throw new BlockGossipError(GossipAction.REJECT, {
|
|
289
|
+
throw new BlockGossipError(GossipAction.REJECT, {
|
|
290
|
+
code: BlockErrorCode.INCORRECT_PROPOSER,
|
|
291
|
+
slot: blockSlot,
|
|
292
|
+
root: blockRoot,
|
|
293
|
+
proposerIndex,
|
|
294
|
+
});
|
|
274
295
|
}
|
|
275
296
|
|
|
276
297
|
// Simple implementation of a pending block queue. Keeping the block here recycles the queue logic, and keeps the
|
|
@@ -315,7 +336,8 @@ export async function verifyBlockProposerSignature(
|
|
|
315
336
|
if (!(await chain.bls.verifySignatureSets([signatureSet], {verifyOnMainThread: opts.verifyOnMainThread ?? true}))) {
|
|
316
337
|
throw new BlockGossipError(GossipAction.REJECT, {
|
|
317
338
|
code: BlockErrorCode.PROPOSAL_SIGNATURE_INVALID,
|
|
318
|
-
blockSlot,
|
|
339
|
+
slot: blockSlot,
|
|
340
|
+
root: blockRoot,
|
|
319
341
|
});
|
|
320
342
|
}
|
|
321
343
|
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
computeStartSlotAtEpoch,
|
|
12
12
|
getBlockHeaderProposerSignatureSetByHeaderSlot,
|
|
13
13
|
} from "@lodestar/state-transition";
|
|
14
|
-
import {DataColumnSidecar, Root, Slot, SubnetID, ValidatorIndex, fulu, gloas, ssz} from "@lodestar/types";
|
|
14
|
+
import {DataColumnSidecar, Root, RootHex, Slot, SubnetID, ValidatorIndex, fulu, gloas, ssz} from "@lodestar/types";
|
|
15
15
|
import {byteArrayEquals, toRootHex, verifyMerkleBranch} from "@lodestar/utils";
|
|
16
16
|
import {BeaconMetrics} from "../../metrics/metrics/beacon.js";
|
|
17
17
|
import {Metrics} from "../../metrics/metrics.js";
|
|
@@ -39,12 +39,14 @@ export async function validateGossipFuluDataColumnSidecar(
|
|
|
39
39
|
const blockRootHex = toRootHex(ssz.phase0.BeaconBlockHeader.hashTreeRoot(blockHeader));
|
|
40
40
|
|
|
41
41
|
// 1) [REJECT] The sidecar is valid as verified by verify_data_column_sidecar
|
|
42
|
-
verifyFuluDataColumnSidecar(chain.config, dataColumnSidecar);
|
|
42
|
+
verifyFuluDataColumnSidecar(chain.config, dataColumnSidecar, blockRootHex);
|
|
43
43
|
|
|
44
44
|
// 2) [REJECT] The sidecar is for the correct subnet -- i.e. compute_subnet_for_data_column_sidecar(sidecar.index) == subnet_id
|
|
45
45
|
if (computeSubnetForDataColumnSidecar(chain.config, dataColumnSidecar) !== gossipSubnet) {
|
|
46
46
|
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
47
47
|
code: DataColumnSidecarErrorCode.INVALID_SUBNET,
|
|
48
|
+
slot: blockHeader.slot,
|
|
49
|
+
root: blockRootHex,
|
|
48
50
|
columnIndex: dataColumnSidecar.index,
|
|
49
51
|
gossipSubnet: gossipSubnet,
|
|
50
52
|
});
|
|
@@ -100,8 +102,9 @@ export async function validateGossipFuluDataColumnSidecar(
|
|
|
100
102
|
if (parentBlock.slot >= blockHeader.slot) {
|
|
101
103
|
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
102
104
|
code: DataColumnSidecarErrorCode.NOT_LATER_THAN_PARENT,
|
|
103
|
-
parentSlot: parentBlock.slot,
|
|
104
105
|
slot: blockHeader.slot,
|
|
106
|
+
root: blockRootHex,
|
|
107
|
+
parentSlot: parentBlock.slot,
|
|
105
108
|
});
|
|
106
109
|
}
|
|
107
110
|
|
|
@@ -140,6 +143,8 @@ export async function validateGossipFuluDataColumnSidecar(
|
|
|
140
143
|
if (proposerIndex !== expectedProposerIndex) {
|
|
141
144
|
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
142
145
|
code: DataColumnSidecarErrorCode.INCORRECT_PROPOSER,
|
|
146
|
+
slot: blockHeader.slot,
|
|
147
|
+
root: blockRootHex,
|
|
143
148
|
actualProposerIndex: proposerIndex,
|
|
144
149
|
expectedProposerIndex,
|
|
145
150
|
});
|
|
@@ -161,9 +166,9 @@ export async function validateGossipFuluDataColumnSidecar(
|
|
|
161
166
|
) {
|
|
162
167
|
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
163
168
|
code: DataColumnSidecarErrorCode.PROPOSAL_SIGNATURE_INVALID,
|
|
164
|
-
blockRoot: blockRootHex,
|
|
165
|
-
index: dataColumnSidecar.index,
|
|
166
169
|
slot: blockHeader.slot,
|
|
170
|
+
root: blockRootHex,
|
|
171
|
+
index: dataColumnSidecar.index,
|
|
167
172
|
});
|
|
168
173
|
}
|
|
169
174
|
|
|
@@ -185,7 +190,8 @@ export async function validateGossipFuluDataColumnSidecar(
|
|
|
185
190
|
if (!valid) {
|
|
186
191
|
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
187
192
|
code: DataColumnSidecarErrorCode.INCLUSION_PROOF_INVALID,
|
|
188
|
-
slot:
|
|
193
|
+
slot: blockHeader.slot,
|
|
194
|
+
root: blockRootHex,
|
|
189
195
|
columnIndex: dataColumnSidecar.index,
|
|
190
196
|
});
|
|
191
197
|
}
|
|
@@ -204,6 +210,7 @@ export async function validateGossipFuluDataColumnSidecar(
|
|
|
204
210
|
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
205
211
|
code: DataColumnSidecarErrorCode.INVALID_KZG_PROOF,
|
|
206
212
|
slot: blockHeader.slot,
|
|
213
|
+
root: blockRootHex,
|
|
207
214
|
columnIndex: dataColumnSidecar.index,
|
|
208
215
|
});
|
|
209
216
|
} finally {
|
|
@@ -240,6 +247,7 @@ export async function validateGossipGloasDataColumnSidecar(
|
|
|
240
247
|
if (block.slot !== dataColumnSidecar.slot) {
|
|
241
248
|
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
242
249
|
code: DataColumnSidecarErrorCode.INCORRECT_SIDECAR_SLOT,
|
|
250
|
+
root: blockRootHex,
|
|
243
251
|
columnIndex: dataColumnSidecar.index,
|
|
244
252
|
expected: block.slot,
|
|
245
253
|
actual: dataColumnSidecar.slot,
|
|
@@ -248,12 +256,14 @@ export async function validateGossipGloasDataColumnSidecar(
|
|
|
248
256
|
|
|
249
257
|
// [REJECT] The sidecar must pass verify_data_column_sidecar against the block commitments
|
|
250
258
|
const kzgCommitments = payloadInput.getBlobKzgCommitments();
|
|
251
|
-
verifyGloasDataColumnSidecar(dataColumnSidecar, kzgCommitments);
|
|
259
|
+
verifyGloasDataColumnSidecar(dataColumnSidecar, kzgCommitments, blockRootHex);
|
|
252
260
|
|
|
253
261
|
// [REJECT] The sidecar must be on the correct subnet
|
|
254
262
|
if (computeSubnetForDataColumnSidecar(chain.config, dataColumnSidecar) !== gossipSubnet) {
|
|
255
263
|
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
256
264
|
code: DataColumnSidecarErrorCode.INVALID_SUBNET,
|
|
265
|
+
slot: dataColumnSidecar.slot,
|
|
266
|
+
root: blockRootHex,
|
|
257
267
|
columnIndex: dataColumnSidecar.index,
|
|
258
268
|
gossipSubnet,
|
|
259
269
|
});
|
|
@@ -272,6 +282,7 @@ export async function validateGossipGloasDataColumnSidecar(
|
|
|
272
282
|
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
273
283
|
code: DataColumnSidecarErrorCode.INVALID_KZG_PROOF,
|
|
274
284
|
slot: dataColumnSidecar.slot,
|
|
285
|
+
root: blockRootHex,
|
|
275
286
|
columnIndex: dataColumnSidecar.index,
|
|
276
287
|
});
|
|
277
288
|
} finally {
|
|
@@ -283,11 +294,17 @@ export async function validateGossipGloasDataColumnSidecar(
|
|
|
283
294
|
* SPEC FUNCTION
|
|
284
295
|
* https://github.com/ethereum/consensus-specs/blob/v1.6.0-alpha.4/specs/fulu/p2p-interface.md#verify_data_column_sidecar
|
|
285
296
|
*/
|
|
286
|
-
function verifyFuluDataColumnSidecar(
|
|
297
|
+
function verifyFuluDataColumnSidecar(
|
|
298
|
+
config: ChainForkConfig,
|
|
299
|
+
dataColumnSidecar: fulu.DataColumnSidecar,
|
|
300
|
+
blockRootHex: RootHex
|
|
301
|
+
): void {
|
|
302
|
+
const slot = dataColumnSidecar.signedBlockHeader.message.slot;
|
|
287
303
|
if (dataColumnSidecar.index >= NUMBER_OF_COLUMNS) {
|
|
288
304
|
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
289
305
|
code: DataColumnSidecarErrorCode.INVALID_INDEX,
|
|
290
|
-
slot
|
|
306
|
+
slot,
|
|
307
|
+
root: blockRootHex,
|
|
291
308
|
columnIndex: dataColumnSidecar.index,
|
|
292
309
|
});
|
|
293
310
|
}
|
|
@@ -295,18 +312,20 @@ function verifyFuluDataColumnSidecar(config: ChainForkConfig, dataColumnSidecar:
|
|
|
295
312
|
if (dataColumnSidecar.kzgCommitments.length === 0) {
|
|
296
313
|
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
297
314
|
code: DataColumnSidecarErrorCode.NO_COMMITMENTS,
|
|
298
|
-
slot
|
|
315
|
+
slot,
|
|
316
|
+
root: blockRootHex,
|
|
299
317
|
columnIndex: dataColumnSidecar.index,
|
|
300
318
|
});
|
|
301
319
|
}
|
|
302
320
|
|
|
303
|
-
const epoch = computeEpochAtSlot(
|
|
321
|
+
const epoch = computeEpochAtSlot(slot);
|
|
304
322
|
const maxBlobsPerBlock = config.getMaxBlobsPerBlock(epoch);
|
|
305
323
|
|
|
306
324
|
if (dataColumnSidecar.kzgCommitments.length > maxBlobsPerBlock) {
|
|
307
325
|
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
308
326
|
code: DataColumnSidecarErrorCode.TOO_MANY_KZG_COMMITMENTS,
|
|
309
|
-
slot
|
|
327
|
+
slot,
|
|
328
|
+
root: blockRootHex,
|
|
310
329
|
columnIndex: dataColumnSidecar.index,
|
|
311
330
|
count: dataColumnSidecar.kzgCommitments.length,
|
|
312
331
|
limit: maxBlobsPerBlock,
|
|
@@ -319,6 +338,8 @@ function verifyFuluDataColumnSidecar(config: ChainForkConfig, dataColumnSidecar:
|
|
|
319
338
|
) {
|
|
320
339
|
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
321
340
|
code: DataColumnSidecarErrorCode.MISMATCHED_LENGTHS,
|
|
341
|
+
slot,
|
|
342
|
+
root: blockRootHex,
|
|
322
343
|
columnLength: dataColumnSidecar.column.length,
|
|
323
344
|
commitmentsLength: dataColumnSidecar.kzgCommitments.length,
|
|
324
345
|
proofsLength: dataColumnSidecar.kzgProofs.length,
|
|
@@ -330,12 +351,17 @@ function verifyFuluDataColumnSidecar(config: ChainForkConfig, dataColumnSidecar:
|
|
|
330
351
|
* SPEC FUNCTION
|
|
331
352
|
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.3/specs/gloas/p2p-interface.md#modified-verify_data_column_sidecar
|
|
332
353
|
*/
|
|
333
|
-
function verifyGloasDataColumnSidecar(
|
|
354
|
+
function verifyGloasDataColumnSidecar(
|
|
355
|
+
dataColumnSidecar: gloas.DataColumnSidecar,
|
|
356
|
+
kzgCommitments: Uint8Array[],
|
|
357
|
+
blockRootHex: RootHex
|
|
358
|
+
): void {
|
|
334
359
|
const slot = getDataColumnSidecarSlot(dataColumnSidecar);
|
|
335
360
|
if (dataColumnSidecar.index >= NUMBER_OF_COLUMNS) {
|
|
336
361
|
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
337
362
|
code: DataColumnSidecarErrorCode.INVALID_INDEX,
|
|
338
363
|
slot,
|
|
364
|
+
root: blockRootHex,
|
|
339
365
|
columnIndex: dataColumnSidecar.index,
|
|
340
366
|
});
|
|
341
367
|
}
|
|
@@ -344,6 +370,7 @@ function verifyGloasDataColumnSidecar(dataColumnSidecar: gloas.DataColumnSidecar
|
|
|
344
370
|
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
345
371
|
code: DataColumnSidecarErrorCode.NO_COMMITMENTS,
|
|
346
372
|
slot,
|
|
373
|
+
root: blockRootHex,
|
|
347
374
|
columnIndex: dataColumnSidecar.index,
|
|
348
375
|
});
|
|
349
376
|
}
|
|
@@ -354,6 +381,8 @@ function verifyGloasDataColumnSidecar(dataColumnSidecar: gloas.DataColumnSidecar
|
|
|
354
381
|
) {
|
|
355
382
|
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
356
383
|
code: DataColumnSidecarErrorCode.MISMATCHED_LENGTHS,
|
|
384
|
+
slot,
|
|
385
|
+
root: blockRootHex,
|
|
357
386
|
columnLength: dataColumnSidecar.column.length,
|
|
358
387
|
commitmentsLength: kzgCommitments.length,
|
|
359
388
|
proofsLength: dataColumnSidecar.kzgProofs.length,
|
|
@@ -465,8 +494,8 @@ export async function validateFuluBlockDataColumnSidecars(
|
|
|
465
494
|
) {
|
|
466
495
|
throw new DataColumnSidecarValidationError({
|
|
467
496
|
code: DataColumnSidecarErrorCode.PROPOSAL_SIGNATURE_INVALID,
|
|
468
|
-
blockRoot: rootHex,
|
|
469
497
|
slot: blockSlot,
|
|
498
|
+
root: rootHex,
|
|
470
499
|
index: dataColumnSidecars[0].index,
|
|
471
500
|
});
|
|
472
501
|
}
|
|
@@ -499,6 +528,7 @@ export async function validateFuluBlockDataColumnSidecars(
|
|
|
499
528
|
{
|
|
500
529
|
code: DataColumnSidecarErrorCode.INVALID_INDEX,
|
|
501
530
|
slot: blockSlot,
|
|
531
|
+
root: toRootHex(blockRoot),
|
|
502
532
|
columnIndex: columnSidecar.index,
|
|
503
533
|
},
|
|
504
534
|
"DataColumnSidecar has invalid index"
|
|
@@ -543,6 +573,7 @@ export async function validateFuluBlockDataColumnSidecars(
|
|
|
543
573
|
{
|
|
544
574
|
code: DataColumnSidecarErrorCode.INCLUSION_PROOF_INVALID,
|
|
545
575
|
slot: blockSlot,
|
|
576
|
+
root: toRootHex(blockRoot),
|
|
546
577
|
columnIndex: columnSidecar.index,
|
|
547
578
|
},
|
|
548
579
|
"DataColumnSidecar has invalid inclusion proof"
|
|
@@ -623,6 +654,7 @@ export async function validateGloasBlockDataColumnSidecars(
|
|
|
623
654
|
if (columnSidecar.slot !== blockSlot) {
|
|
624
655
|
throw new DataColumnSidecarValidationError({
|
|
625
656
|
code: DataColumnSidecarErrorCode.INCORRECT_SIDECAR_SLOT,
|
|
657
|
+
root: toRootHex(blockRoot),
|
|
626
658
|
columnIndex: columnSidecar.index,
|
|
627
659
|
expected: blockSlot,
|
|
628
660
|
actual: columnSidecar.slot,
|
|
@@ -644,6 +676,7 @@ export async function validateGloasBlockDataColumnSidecars(
|
|
|
644
676
|
{
|
|
645
677
|
code: DataColumnSidecarErrorCode.INVALID_INDEX,
|
|
646
678
|
slot: blockSlot,
|
|
679
|
+
root: toRootHex(blockRoot),
|
|
647
680
|
columnIndex: columnSidecar.index,
|
|
648
681
|
},
|
|
649
682
|
"DataColumnSidecar has invalid index"
|
|
@@ -82,6 +82,8 @@ async function validateExecutionPayloadEnvelope(
|
|
|
82
82
|
if (block.slot !== payload.slotNumber) {
|
|
83
83
|
throw new ExecutionPayloadEnvelopeError(GossipAction.REJECT, {
|
|
84
84
|
code: ExecutionPayloadEnvelopeErrorCode.SLOT_MISMATCH,
|
|
85
|
+
slot: payload.slotNumber,
|
|
86
|
+
root: blockRootHex,
|
|
85
87
|
envelopeSlot: payload.slotNumber,
|
|
86
88
|
blockSlot: block.slot,
|
|
87
89
|
});
|
|
@@ -91,6 +93,8 @@ async function validateExecutionPayloadEnvelope(
|
|
|
91
93
|
if (envelope.builderIndex !== payloadInput.getBuilderIndex()) {
|
|
92
94
|
throw new ExecutionPayloadEnvelopeError(GossipAction.REJECT, {
|
|
93
95
|
code: ExecutionPayloadEnvelopeErrorCode.BUILDER_INDEX_MISMATCH,
|
|
96
|
+
slot: payload.slotNumber,
|
|
97
|
+
root: blockRootHex,
|
|
94
98
|
envelopeBuilderIndex: envelope.builderIndex,
|
|
95
99
|
bidBuilderIndex: payloadInput.getBuilderIndex(),
|
|
96
100
|
});
|
|
@@ -100,6 +104,8 @@ async function validateExecutionPayloadEnvelope(
|
|
|
100
104
|
if (toRootHex(payload.blockHash) !== payloadInput.getBlockHashHex()) {
|
|
101
105
|
throw new ExecutionPayloadEnvelopeError(GossipAction.REJECT, {
|
|
102
106
|
code: ExecutionPayloadEnvelopeErrorCode.BLOCK_HASH_MISMATCH,
|
|
107
|
+
slot: payload.slotNumber,
|
|
108
|
+
root: blockRootHex,
|
|
103
109
|
envelopeBlockHash: toRootHex(payload.blockHash),
|
|
104
110
|
bidBlockHash: payloadInput.getBlockHashHex(),
|
|
105
111
|
});
|
|
@@ -110,6 +116,8 @@ async function validateExecutionPayloadEnvelope(
|
|
|
110
116
|
if (!byteArrayEquals(requestsRoot, payloadInput.getBid().executionRequestsRoot)) {
|
|
111
117
|
throw new ExecutionPayloadEnvelopeError(GossipAction.REJECT, {
|
|
112
118
|
code: ExecutionPayloadEnvelopeErrorCode.EXECUTION_REQUESTS_ROOT_MISMATCH,
|
|
119
|
+
slot: payload.slotNumber,
|
|
120
|
+
root: blockRootHex,
|
|
113
121
|
envelopeRequestsRoot: toRootHex(requestsRoot),
|
|
114
122
|
bidRequestsRoot: toRootHex(payloadInput.getBid().executionRequestsRoot),
|
|
115
123
|
});
|
|
@@ -141,6 +149,8 @@ async function validateExecutionPayloadEnvelope(
|
|
|
141
149
|
if (!(await chain.bls.verifySignatureSets([signatureSet], {verifyOnMainThread: true}))) {
|
|
142
150
|
throw new ExecutionPayloadEnvelopeError(GossipAction.REJECT, {
|
|
143
151
|
code: ExecutionPayloadEnvelopeErrorCode.INVALID_SIGNATURE,
|
|
152
|
+
slot: payload.slotNumber,
|
|
153
|
+
root: blockRootHex,
|
|
144
154
|
});
|
|
145
155
|
}
|
|
146
156
|
}
|
|
@@ -123,9 +123,6 @@ export class DataTransformSnappy implements DataTransform {
|
|
|
123
123
|
if (uncompressedDataLength > maxSize) {
|
|
124
124
|
throw Error(`ssz_snappy decoded data length ${uncompressedDataLength} > ${maxSize}`);
|
|
125
125
|
}
|
|
126
|
-
if (uncompressedDataLength > sszType.maxSize) {
|
|
127
|
-
throw Error(`ssz_snappy decoded data length ${uncompressedDataLength} > ${sszType.maxSize}`);
|
|
128
|
-
}
|
|
129
126
|
|
|
130
127
|
// Only after sanity length checks, we can decompress the data
|
|
131
128
|
// Using Buffer.alloc() instead of Buffer.allocUnsafe() to mitigate high GC pressure observed in some environments
|
|
@@ -146,9 +143,6 @@ export class DataTransformSnappy implements DataTransform {
|
|
|
146
143
|
if (data.length > maxSize) {
|
|
147
144
|
throw Error(`ssz_snappy encoded data length ${data.length} > ${maxSize}`);
|
|
148
145
|
}
|
|
149
|
-
if (data.length > sszType.maxSize) {
|
|
150
|
-
throw Error(`ssz_snappy encoded data length ${data.length} > ${sszType.maxSize}`);
|
|
151
|
-
}
|
|
152
146
|
|
|
153
147
|
// Using Buffer.alloc() instead of Buffer.allocUnsafe() to mitigate high GC pressure observed in some environments
|
|
154
148
|
const compressedData = Buffer.alloc(snappyWasm.max_compress_len(data.length));
|
|
@@ -4,17 +4,11 @@ import {
|
|
|
4
4
|
ATTESTATION_SUBNET_COUNT,
|
|
5
5
|
ForkName,
|
|
6
6
|
ForkSeq,
|
|
7
|
-
MAX_ATTESTER_SLASHING_SIZE,
|
|
8
|
-
MAX_DATA_COLUMN_SIDECAR_SIZE,
|
|
9
|
-
MAX_SIGNED_AGGREGATE_AND_PROOF_SIZE,
|
|
10
|
-
MAX_SIGNED_EXECUTION_PAYLOAD_BID_SIZE,
|
|
11
|
-
MAX_SIGNED_EXECUTION_PAYLOAD_BID_SIZE_HEZE,
|
|
12
7
|
SYNC_COMMITTEE_SUBNET_COUNT,
|
|
13
8
|
isForkPostAltair,
|
|
14
9
|
isForkPostElectra,
|
|
15
10
|
isForkPostFulu,
|
|
16
11
|
isForkPostGloas,
|
|
17
|
-
isForkPostHeze,
|
|
18
12
|
} from "@lodestar/params";
|
|
19
13
|
import {Attestation, SingleAttestation, ssz, sszTypesFor} from "@lodestar/types";
|
|
20
14
|
import {GossipAction, GossipActionError, GossipErrorCode} from "../../chain/errors/gossipValidation.js";
|
|
@@ -139,27 +133,11 @@ export function getGossipSSZType(topic: GossipTopic) {
|
|
|
139
133
|
}
|
|
140
134
|
|
|
141
135
|
/**
|
|
142
|
-
* Return the maximum uncompressed SSZ byte length accepted for a gossip object
|
|
136
|
+
* Return the maximum uncompressed SSZ byte length accepted for a gossip object, the SSZ type max size
|
|
137
|
+
* or MAX_PAYLOAD_SIZE, whichever is smaller.
|
|
143
138
|
*/
|
|
144
139
|
export function getGossipSSZMaxSize(topic: GossipTopic, maxPayloadSize: number, sszType?: CompositeTypeAny): number {
|
|
145
|
-
|
|
146
|
-
// Gloas progressive containers have broad theoretical SSZ max sizes; use the preset p2p bounds instead.
|
|
147
|
-
switch (topic.type) {
|
|
148
|
-
case GossipType.beacon_block:
|
|
149
|
-
return maxPayloadSize;
|
|
150
|
-
case GossipType.beacon_aggregate_and_proof:
|
|
151
|
-
return isForkPostGloas(fork) ? MAX_SIGNED_AGGREGATE_AND_PROOF_SIZE : (sszType ?? getGossipSSZType(topic)).maxSize;
|
|
152
|
-
case GossipType.attester_slashing:
|
|
153
|
-
return isForkPostGloas(fork) ? MAX_ATTESTER_SLASHING_SIZE : (sszType ?? getGossipSSZType(topic)).maxSize;
|
|
154
|
-
case GossipType.data_column_sidecar:
|
|
155
|
-
return isForkPostGloas(fork) ? MAX_DATA_COLUMN_SIDECAR_SIZE : (sszType ?? getGossipSSZType(topic)).maxSize;
|
|
156
|
-
case GossipType.execution_payload:
|
|
157
|
-
return maxPayloadSize;
|
|
158
|
-
case GossipType.execution_payload_bid:
|
|
159
|
-
return isForkPostHeze(fork) ? MAX_SIGNED_EXECUTION_PAYLOAD_BID_SIZE_HEZE : MAX_SIGNED_EXECUTION_PAYLOAD_BID_SIZE;
|
|
160
|
-
default:
|
|
161
|
-
return (sszType ?? getGossipSSZType(topic)).maxSize;
|
|
162
|
-
}
|
|
140
|
+
return Math.min((sszType ?? getGossipSSZType(topic)).maxSize, maxPayloadSize);
|
|
163
141
|
}
|
|
164
142
|
|
|
165
143
|
/**
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
ssz,
|
|
28
28
|
sszTypesFor,
|
|
29
29
|
} from "@lodestar/types";
|
|
30
|
-
import {LogLevel, Logger,
|
|
30
|
+
import {LogLevel, Logger, toHex, toRootHex} from "@lodestar/utils";
|
|
31
31
|
import {
|
|
32
32
|
BlockInput,
|
|
33
33
|
BlockInputColumns,
|
|
@@ -157,7 +157,6 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
157
157
|
const slot = signedBlock.message.slot;
|
|
158
158
|
const forkTypes = config.getForkTypes(slot);
|
|
159
159
|
const blockRootHex = toRootHex(forkTypes.BeaconBlock.hashTreeRoot(signedBlock.message));
|
|
160
|
-
const blockShortHex = prettyBytes(blockRootHex);
|
|
161
160
|
const delaySec = chain.clock.secFromSlot(slot, seenTimestampSec);
|
|
162
161
|
const recvToValLatency = Date.now() / 1000 - seenTimestampSec;
|
|
163
162
|
|
|
@@ -167,6 +166,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
167
166
|
|
|
168
167
|
const logCtx = {
|
|
169
168
|
slot,
|
|
169
|
+
root: blockRootHex,
|
|
170
170
|
currentSlot: chain.clock.currentSlot,
|
|
171
171
|
peerId: peerIdStr,
|
|
172
172
|
delaySec,
|
|
@@ -227,7 +227,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
227
227
|
return blockInput;
|
|
228
228
|
} catch (e) {
|
|
229
229
|
if (e instanceof BlockGossipError) {
|
|
230
|
-
logger.debug("Gossip block has error", {slot, root:
|
|
230
|
+
logger.debug("Gossip block has error", {slot, root: blockRootHex, code: e.type.code});
|
|
231
231
|
if (
|
|
232
232
|
(e.type.code === BlockErrorCode.PARENT_BLOCK_UNKNOWN ||
|
|
233
233
|
e.type.code === BlockErrorCode.PARENT_PAYLOAD_UNKNOWN) &&
|
|
@@ -249,7 +249,12 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
249
249
|
throw e;
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
-
chain.persistInvalidSszValue(
|
|
252
|
+
chain.persistInvalidSszValue(
|
|
253
|
+
forkTypes.SignedBeaconBlock,
|
|
254
|
+
signedBlock,
|
|
255
|
+
`gossip_reject_slot_${slot}`,
|
|
256
|
+
blockRootHex
|
|
257
|
+
);
|
|
253
258
|
}
|
|
254
259
|
|
|
255
260
|
// REJECT or unexpected (non-BlockGossipError) error: drop the optimistically-added entries from
|
|
@@ -279,7 +284,6 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
279
284
|
const slot = blobBlockHeader.slot;
|
|
280
285
|
const fork = config.getForkName(slot);
|
|
281
286
|
const blockRootHex = toRootHex(ssz.phase0.BeaconBlockHeader.hashTreeRoot(blobBlockHeader));
|
|
282
|
-
const blockShortHex = prettyBytes(blockRootHex);
|
|
283
287
|
|
|
284
288
|
const delaySec = chain.clock.secFromSlot(slot, seenTimestampSec);
|
|
285
289
|
const recvToValLatency = Date.now() / 1000 - seenTimestampSec;
|
|
@@ -332,7 +336,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
332
336
|
if (e instanceof BlobSidecarGossipError) {
|
|
333
337
|
// Don't trigger this yet if full block and blobs haven't arrived yet
|
|
334
338
|
if (e.type.code === BlobSidecarErrorCode.PARENT_UNKNOWN) {
|
|
335
|
-
logger.debug("Gossip blob has error", {slot, root:
|
|
339
|
+
logger.debug("Gossip blob has error", {slot, root: blockRootHex, code: e.type.code});
|
|
336
340
|
// no need to trigger `unknownBlockParent` event here, as we already did it in `validateBeaconBlock()`
|
|
337
341
|
//
|
|
338
342
|
// TODO(fulu): is this note above correct? Could have random blob that we see that could trigger
|
|
@@ -696,11 +700,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
696
700
|
logLevel = LogLevel.error;
|
|
697
701
|
}
|
|
698
702
|
metrics?.gossipBlock.processBlockErrors.inc({error: e instanceof BlockError ? e.type.code : "NOT_BLOCK_ERROR"});
|
|
699
|
-
logger[logLevel](
|
|
700
|
-
"Error processing block",
|
|
701
|
-
{slot, peer: peerIdStr, blockRoot: prettyBytes(blockInput.blockRootHex)},
|
|
702
|
-
e as Error
|
|
703
|
-
);
|
|
703
|
+
logger[logLevel]("Error processing block", {slot, root: blockInput.blockRootHex, peer: peerIdStr}, e as Error);
|
|
704
704
|
// TODO(fulu): Revisit when we prune block inputs
|
|
705
705
|
chain.seenBlockInputCache.prune(blockInput.blockRootHex);
|
|
706
706
|
});
|