@lodestar/beacon-node 1.42.0-dev.78c54f483b → 1.42.0-dev.7bdb87e586
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 +24 -12
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/pool/index.js +4 -0
- package/lib/api/impl/beacon/pool/index.js.map +1 -1
- package/lib/api/impl/beacon/state/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/index.js +13 -10
- package/lib/api/impl/beacon/state/index.js.map +1 -1
- package/lib/api/impl/debug/index.js.map +1 -1
- package/lib/api/impl/lodestar/index.d.ts.map +1 -1
- package/lib/api/impl/lodestar/index.js +4 -0
- package/lib/api/impl/lodestar/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +7 -1
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/ColumnReconstructionTracker.d.ts +2 -1
- package/lib/chain/ColumnReconstructionTracker.d.ts.map +1 -1
- package/lib/chain/ColumnReconstructionTracker.js +5 -5
- package/lib/chain/ColumnReconstructionTracker.js.map +1 -1
- package/lib/chain/GetBlobsTracker.d.ts +2 -1
- package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
- package/lib/chain/GetBlobsTracker.js +14 -12
- package/lib/chain/GetBlobsTracker.js.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.d.ts +5 -5
- package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
- package/lib/chain/blocks/blockInput/types.d.ts +4 -4
- package/lib/chain/blocks/blockInput/types.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +19 -5
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +10 -8
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +67 -39
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +14 -6
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +33 -2
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +2 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +3 -2
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.js +4 -2
- package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
- package/lib/chain/chain.d.ts +3 -2
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +64 -24
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +29 -7
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/emitter.js +12 -3
- package/lib/chain/emitter.js.map +1 -1
- package/lib/chain/errors/dataColumnSidecarError.d.ts +31 -1
- package/lib/chain/errors/dataColumnSidecarError.d.ts.map +1 -1
- package/lib/chain/errors/dataColumnSidecarError.js +7 -0
- package/lib/chain/errors/dataColumnSidecarError.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +10 -8
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +4 -2
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/lightClient/index.d.ts +2 -2
- package/lib/chain/lightClient/index.d.ts.map +1 -1
- package/lib/chain/lightClient/index.js +7 -0
- package/lib/chain/lightClient/index.js.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +5 -2
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/opPools/executionPayloadBidPool.d.ts +2 -2
- package/lib/chain/opPools/executionPayloadBidPool.d.ts.map +1 -1
- package/lib/chain/opPools/executionPayloadBidPool.js +2 -2
- package/lib/chain/opPools/executionPayloadBidPool.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +7 -1
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts +2 -2
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +3 -3
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +10 -1
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js +2 -2
- package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +2 -2
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +2 -2
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.d.ts +11 -4
- package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.js +184 -5
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +7 -4
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +4 -1
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.js +4 -1
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/chain/validation/syncCommittee.d.ts.map +1 -1
- package/lib/chain/validation/syncCommittee.js +4 -0
- package/lib/chain/validation/syncCommittee.js.map +1 -1
- package/lib/chain/validation/syncCommitteeContributionAndProof.js +4 -1
- package/lib/chain/validation/syncCommitteeContributionAndProof.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +3 -3
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/db/buckets.d.ts +2 -2
- package/lib/db/buckets.d.ts.map +1 -1
- package/lib/db/buckets.js +2 -2
- package/lib/db/buckets.js.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.d.ts +2 -2
- package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
- package/lib/db/repositories/dataColumnSidecar.d.ts.map +1 -1
- package/lib/db/repositories/dataColumnSidecar.js +4 -2
- package/lib/db/repositories/dataColumnSidecar.js.map +1 -1
- package/lib/db/repositories/dataColumnSidecarArchive.d.ts.map +1 -1
- package/lib/db/repositories/dataColumnSidecarArchive.js +4 -2
- package/lib/db/repositories/dataColumnSidecarArchive.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +20 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +33 -0
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/interface.d.ts +3 -2
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/libp2p/index.d.ts.map +1 -1
- package/lib/network/libp2p/index.js +19 -13
- package/lib/network/libp2p/index.js.map +1 -1
- package/lib/network/network.d.ts +3 -2
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +3 -0
- package/lib/network/network.js.map +1 -1
- package/lib/network/options.d.ts.map +1 -1
- package/lib/network/options.js +7 -2
- package/lib/network/options.js.map +1 -1
- package/lib/network/processor/extractSlotRootFns.d.ts +1 -1
- package/lib/network/processor/extractSlotRootFns.d.ts.map +1 -1
- package/lib/network/processor/extractSlotRootFns.js +25 -5
- package/lib/network/processor/extractSlotRootFns.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +260 -73
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/index.d.ts +11 -1
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +234 -22
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/types.d.ts +3 -3
- package/lib/network/reqresp/types.d.ts.map +1 -1
- package/lib/network/reqresp/types.js +9 -3
- package/lib/network/reqresp/types.js.map +1 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +4 -1
- package/lib/node/nodejs.js.map +1 -1
- package/lib/node/notifier.d.ts.map +1 -1
- package/lib/node/notifier.js +2 -2
- package/lib/node/notifier.js.map +1 -1
- package/lib/sync/unknownBlock.js +2 -2
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts +3 -3
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +4 -2
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/lib/sync/utils/downloadByRoot.d.ts +3 -3
- package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRoot.js +10 -5
- package/lib/sync/utils/downloadByRoot.js.map +1 -1
- package/lib/util/blobs.d.ts +3 -3
- package/lib/util/blobs.d.ts.map +1 -1
- package/lib/util/blobs.js +21 -10
- package/lib/util/blobs.js.map +1 -1
- package/lib/util/dataColumns.d.ts +18 -11
- package/lib/util/dataColumns.d.ts.map +1 -1
- package/lib/util/dataColumns.js +51 -17
- package/lib/util/dataColumns.js.map +1 -1
- package/lib/util/execution.d.ts +6 -2
- package/lib/util/execution.d.ts.map +1 -1
- package/lib/util/execution.js +49 -25
- package/lib/util/execution.js.map +1 -1
- package/lib/util/sszBytes.d.ts +25 -1
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +189 -2
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +15 -15
- package/src/api/impl/beacon/blocks/index.ts +32 -15
- package/src/api/impl/beacon/pool/index.ts +4 -0
- package/src/api/impl/beacon/state/index.ts +15 -15
- package/src/api/impl/debug/index.ts +2 -2
- package/src/api/impl/lodestar/index.ts +4 -0
- package/src/api/impl/validator/index.ts +7 -0
- package/src/chain/ColumnReconstructionTracker.ts +6 -5
- package/src/chain/GetBlobsTracker.ts +14 -12
- package/src/chain/blocks/blockInput/blockInput.ts +8 -8
- package/src/chain/blocks/blockInput/types.ts +4 -4
- package/src/chain/blocks/importBlock.ts +29 -8
- package/src/chain/blocks/importExecutionPayload.ts +72 -42
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +53 -12
- package/src/chain/blocks/payloadEnvelopeInput/types.ts +2 -1
- package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +2 -1
- package/src/chain/blocks/verifyBlocksSignatures.ts +9 -2
- package/src/chain/chain.ts +73 -28
- package/src/chain/emitter.ts +25 -7
- package/src/chain/errors/dataColumnSidecarError.ts +32 -1
- package/src/chain/forkChoice/index.ts +11 -8
- package/src/chain/interface.ts +4 -2
- package/src/chain/lightClient/index.ts +15 -3
- package/src/chain/opPools/aggregatedAttestationPool.ts +6 -1
- package/src/chain/opPools/executionPayloadBidPool.ts +3 -3
- package/src/chain/prepareNextSlot.ts +8 -0
- package/src/chain/produceBlock/computeNewStateRoot.ts +2 -1
- package/src/chain/produceBlock/produceBlockBody.ts +25 -5
- package/src/chain/seenCache/seenGossipBlockInput.ts +2 -2
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +2 -2
- package/src/chain/validation/block.ts +2 -1
- package/src/chain/validation/dataColumnSidecar.ts +230 -7
- package/src/chain/validation/executionPayloadBid.ts +7 -3
- package/src/chain/validation/executionPayloadEnvelope.ts +8 -1
- package/src/chain/validation/payloadAttestationMessage.ts +4 -0
- package/src/chain/validation/syncCommittee.ts +5 -1
- package/src/chain/validation/syncCommitteeContributionAndProof.ts +5 -1
- package/src/chain/validatorMonitor.ts +3 -2
- package/src/db/buckets.ts +2 -2
- package/src/db/repositories/dataColumnSidecar.ts +4 -2
- package/src/db/repositories/dataColumnSidecarArchive.ts +4 -2
- package/src/metrics/metrics/lodestar.ts +34 -0
- package/src/network/interface.ts +3 -2
- package/src/network/libp2p/index.ts +21 -15
- package/src/network/network.ts +7 -4
- package/src/network/options.ts +7 -2
- package/src/network/processor/extractSlotRootFns.ts +32 -6
- package/src/network/processor/gossipHandlers.ts +325 -86
- package/src/network/processor/index.ts +304 -22
- package/src/network/reqresp/types.ts +13 -5
- package/src/node/nodejs.ts +5 -2
- package/src/node/notifier.ts +7 -2
- package/src/sync/unknownBlock.ts +3 -3
- package/src/sync/utils/downloadByRange.ts +9 -7
- package/src/sync/utils/downloadByRoot.ts +16 -12
- package/src/util/blobs.ts +35 -15
- package/src/util/dataColumns.ts +69 -25
- package/src/util/execution.ts +49 -30
- package/src/util/sszBytes.ts +245 -3
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
isForkPostElectra,
|
|
22
22
|
} from "@lodestar/params";
|
|
23
23
|
import {
|
|
24
|
-
|
|
24
|
+
type IBeaconStateViewAltair,
|
|
25
25
|
computeStartSlotAtEpoch,
|
|
26
26
|
computeSyncPeriodAtEpoch,
|
|
27
27
|
computeSyncPeriodAtSlot,
|
|
@@ -260,7 +260,11 @@ export class LightClientServer {
|
|
|
260
260
|
* - Persist state witness
|
|
261
261
|
* - Use block's syncAggregate
|
|
262
262
|
*/
|
|
263
|
-
onImportBlockHead(
|
|
263
|
+
onImportBlockHead(
|
|
264
|
+
block: BeaconBlock<ForkPostAltair>,
|
|
265
|
+
postState: IBeaconStateViewAltair,
|
|
266
|
+
parentBlockSlot: Slot
|
|
267
|
+
): void {
|
|
264
268
|
// TEMP: To disable this functionality for fork_choice spec tests.
|
|
265
269
|
// Since the tests have deep-reorgs attested data is not available often printing lots of error logs.
|
|
266
270
|
// While this function is only called for head blocks, best to disable.
|
|
@@ -268,6 +272,14 @@ export class LightClientServer {
|
|
|
268
272
|
return;
|
|
269
273
|
}
|
|
270
274
|
|
|
275
|
+
// TODO GLOAS: Light client updates for gloas are not yet updated in the spec.
|
|
276
|
+
// The block body no longer contains execution payload, so `blockToLightClientHeader`
|
|
277
|
+
// cannot construct a header from a gloas block. Skip all light client processing
|
|
278
|
+
// for post-gloas blocks, revisit once there is a spec for it.
|
|
279
|
+
if (this.config.getForkSeq(block.slot) >= ForkSeq.gloas) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
|
|
271
283
|
// What is the syncAggregate signing?
|
|
272
284
|
// From the state-transition
|
|
273
285
|
// ```
|
|
@@ -396,7 +408,7 @@ export class LightClientServer {
|
|
|
396
408
|
|
|
397
409
|
private async persistPostBlockImportData(
|
|
398
410
|
block: BeaconBlock<ForkPostAltair>,
|
|
399
|
-
postState:
|
|
411
|
+
postState: IBeaconStateViewAltair,
|
|
400
412
|
parentBlockSlot: Slot
|
|
401
413
|
): Promise<void> {
|
|
402
414
|
const blockSlot = block.slot;
|
|
@@ -26,6 +26,8 @@ import {
|
|
|
26
26
|
computeSlotsSinceEpochStart,
|
|
27
27
|
computeStartSlotAtEpoch,
|
|
28
28
|
getAttestationParticipationStatus,
|
|
29
|
+
isStatePostAltair,
|
|
30
|
+
isStatePostGloas,
|
|
29
31
|
} from "@lodestar/state-transition";
|
|
30
32
|
import {Attestation, Epoch, RootHex, Slot, electra, isElectraAttestation, phase0, ssz} from "@lodestar/types";
|
|
31
33
|
import {MapDef, assert, toRootHex} from "@lodestar/utils";
|
|
@@ -359,7 +361,7 @@ export class AggregatedAttestationPool {
|
|
|
359
361
|
inclusionDistance,
|
|
360
362
|
stateEpoch,
|
|
361
363
|
rootCache,
|
|
362
|
-
|
|
364
|
+
isStatePostGloas(state) ? state.executionPayloadAvailability : null
|
|
363
365
|
);
|
|
364
366
|
|
|
365
367
|
const weight =
|
|
@@ -742,6 +744,9 @@ export function getNotSeenValidatorsFn(
|
|
|
742
744
|
if (config.getForkName(stateSlot) === ForkName.phase0) {
|
|
743
745
|
throw new Error("getNotSeenValidatorsFn is not supported phase0 state");
|
|
744
746
|
}
|
|
747
|
+
if (!isStatePostAltair(state)) {
|
|
748
|
+
throw new Error("Expected Altair state for participation tracking");
|
|
749
|
+
}
|
|
745
750
|
|
|
746
751
|
// altair and future forks
|
|
747
752
|
// Get attestations to be included in an altair block.
|
|
@@ -59,13 +59,13 @@ export class ExecutionPayloadBidPool {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
/**
|
|
62
|
-
* Return the highest-value bid matching slot, parent block
|
|
62
|
+
* Return the highest-value bid matching slot, parent block hash, and parent block root.
|
|
63
63
|
* Used for gossip validation and block production.
|
|
64
64
|
*/
|
|
65
65
|
getBestBid(
|
|
66
|
-
|
|
66
|
+
slot: Slot,
|
|
67
67
|
parentBlockHash: BlockHashHex,
|
|
68
|
-
|
|
68
|
+
parentBlockRoot: BlockRootHex
|
|
69
69
|
): gloas.ExecutionPayloadBid | null {
|
|
70
70
|
const bidByParentHash = this.bidByParentHashByParentRootBySlot.get(slot)?.get(parentBlockRoot);
|
|
71
71
|
return bidByParentHash?.get(parentBlockHash) ?? null;
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
StateHashTreeRootSource,
|
|
8
8
|
computeEpochAtSlot,
|
|
9
9
|
computeTimeAtSlot,
|
|
10
|
+
isStatePostBellatrix,
|
|
10
11
|
} from "@lodestar/state-transition";
|
|
11
12
|
import {Slot} from "@lodestar/types";
|
|
12
13
|
import {Logger, fromHex, isErrorAborted, sleep} from "@lodestar/utils";
|
|
@@ -159,6 +160,9 @@ export class PrepareNextSlotScheduler {
|
|
|
159
160
|
const preparationTime =
|
|
160
161
|
computeTimeAtSlot(this.config, prepareSlot, this.chain.genesisTime) - Date.now() / 1000;
|
|
161
162
|
this.metrics?.blockPayload.payloadAdvancePrepTime.observe(preparationTime);
|
|
163
|
+
if (!isStatePostBellatrix(updatedPrepareState)) {
|
|
164
|
+
throw new Error("Expected Bellatrix state for payload preparation");
|
|
165
|
+
}
|
|
162
166
|
|
|
163
167
|
const safeBlockHash = getSafeExecutionBlockHash(this.chain.forkChoice);
|
|
164
168
|
const finalizedBlockHash =
|
|
@@ -183,6 +187,10 @@ export class PrepareNextSlotScheduler {
|
|
|
183
187
|
});
|
|
184
188
|
}
|
|
185
189
|
|
|
190
|
+
if (!isStatePostBellatrix(updatedPrepareState)) {
|
|
191
|
+
throw new Error("Expected Bellatrix state for payload attributes");
|
|
192
|
+
}
|
|
193
|
+
|
|
186
194
|
this.computeStateHashTreeRoot(updatedPrepareState, isEpochTransition);
|
|
187
195
|
|
|
188
196
|
// If emitPayloadAttributes is true emit a SSE payloadAttributes event
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
ExecutionPayloadStatus,
|
|
4
4
|
G2_POINT_AT_INFINITY,
|
|
5
5
|
IBeaconStateView,
|
|
6
|
+
IBeaconStateViewGloas,
|
|
6
7
|
StateHashTreeRootSource,
|
|
7
8
|
} from "@lodestar/state-transition";
|
|
8
9
|
import {BeaconBlock, BlindedBeaconBlock, Gwei, Root, gloas} from "@lodestar/types";
|
|
@@ -60,7 +61,7 @@ export function computeNewStateRoot(
|
|
|
60
61
|
*/
|
|
61
62
|
export function computeEnvelopeStateRoot(
|
|
62
63
|
metrics: Metrics | null,
|
|
63
|
-
postBlockState:
|
|
64
|
+
postBlockState: IBeaconStateViewGloas,
|
|
64
65
|
envelope: gloas.ExecutionPayloadEnvelope
|
|
65
66
|
): Root {
|
|
66
67
|
const signedEnvelope: gloas.SignedExecutionPayloadEnvelope = {
|
|
@@ -14,7 +14,15 @@ import {
|
|
|
14
14
|
isForkPostBellatrix,
|
|
15
15
|
isForkPostGloas,
|
|
16
16
|
} from "@lodestar/params";
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
G2_POINT_AT_INFINITY,
|
|
19
|
+
IBeaconStateView,
|
|
20
|
+
type IBeaconStateViewBellatrix,
|
|
21
|
+
computeTimeAtSlot,
|
|
22
|
+
isStatePostBellatrix,
|
|
23
|
+
isStatePostCapella,
|
|
24
|
+
isStatePostGloas,
|
|
25
|
+
} from "@lodestar/state-transition";
|
|
18
26
|
import {
|
|
19
27
|
BLSPubkey,
|
|
20
28
|
BLSSignature,
|
|
@@ -191,6 +199,10 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
191
199
|
this.logger.verbose("Producing beacon block body", logMeta);
|
|
192
200
|
|
|
193
201
|
if (isForkPostGloas(fork)) {
|
|
202
|
+
if (!isStatePostGloas(currentState)) {
|
|
203
|
+
throw new Error("Expected Gloas state for Gloas block production");
|
|
204
|
+
}
|
|
205
|
+
|
|
194
206
|
// TODO GLOAS: support non self-building here, the block type differentiation between
|
|
195
207
|
// full and blinded no longer makes sense in gloas, it might be a good idea to move
|
|
196
208
|
// this into a completely separate function and have pre/post gloas more separated
|
|
@@ -297,6 +309,10 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
297
309
|
shouldOverrideBuilder,
|
|
298
310
|
});
|
|
299
311
|
} else if (isForkPostBellatrix(fork)) {
|
|
312
|
+
if (!isStatePostBellatrix(currentState)) {
|
|
313
|
+
throw new Error("Expected Bellatrix state for execution block production");
|
|
314
|
+
}
|
|
315
|
+
|
|
300
316
|
const safeBlockHash = getSafeExecutionBlockHash(this.forkChoice);
|
|
301
317
|
const finalizedBlockHash = this.forkChoice.getFinalizedBlock().executionPayloadBlockHash ?? ZERO_HASH_HEX;
|
|
302
318
|
const feeRecipient = requestedFeeRecipient ?? this.beaconProposerCache.getOrDefault(proposerIndex);
|
|
@@ -598,7 +614,7 @@ export async function prepareExecutionPayload(
|
|
|
598
614
|
parentBlockRoot: Root,
|
|
599
615
|
safeBlockHash: RootHex,
|
|
600
616
|
finalizedBlockHash: RootHex,
|
|
601
|
-
state:
|
|
617
|
+
state: IBeaconStateViewBellatrix,
|
|
602
618
|
suggestedFeeRecipient: string
|
|
603
619
|
): Promise<{prepType: PayloadPreparationType; payloadId: PayloadId}> {
|
|
604
620
|
const parentHash = state.latestBlockHash;
|
|
@@ -666,7 +682,7 @@ async function prepareExecutionPayloadHeader(
|
|
|
666
682
|
config: ChainForkConfig;
|
|
667
683
|
},
|
|
668
684
|
fork: ForkPostBellatrix,
|
|
669
|
-
state:
|
|
685
|
+
state: IBeaconStateViewBellatrix,
|
|
670
686
|
proposerPubKey: BLSPubkey
|
|
671
687
|
): Promise<{
|
|
672
688
|
header: ExecutionPayloadHeader;
|
|
@@ -693,7 +709,7 @@ export function getPayloadAttributesForSSE(
|
|
|
693
709
|
prepareSlot,
|
|
694
710
|
parentBlockRoot,
|
|
695
711
|
feeRecipient,
|
|
696
|
-
}: {prepareState:
|
|
712
|
+
}: {prepareState: IBeaconStateViewBellatrix; prepareSlot: Slot; parentBlockRoot: Root; feeRecipient: string}
|
|
697
713
|
): SSEPayloadAttributes {
|
|
698
714
|
const parentHash = prepareState.latestBlockHash;
|
|
699
715
|
const payloadAttributes = preparePayloadAttributes(fork, chain, {
|
|
@@ -736,7 +752,7 @@ function preparePayloadAttributes(
|
|
|
736
752
|
parentBlockRoot,
|
|
737
753
|
feeRecipient,
|
|
738
754
|
}: {
|
|
739
|
-
prepareState:
|
|
755
|
+
prepareState: IBeaconStateViewBellatrix;
|
|
740
756
|
prepareSlot: Slot;
|
|
741
757
|
parentBlockRoot: Root;
|
|
742
758
|
feeRecipient: string;
|
|
@@ -751,6 +767,10 @@ function preparePayloadAttributes(
|
|
|
751
767
|
};
|
|
752
768
|
|
|
753
769
|
if (ForkSeq[fork] >= ForkSeq.capella) {
|
|
770
|
+
if (!isStatePostCapella(prepareState)) {
|
|
771
|
+
throw new Error("Expected Capella state for withdrawals");
|
|
772
|
+
}
|
|
773
|
+
|
|
754
774
|
// withdrawals logic is now fork aware as it changes on electra fork post capella
|
|
755
775
|
(payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
|
|
756
776
|
prepareState.getExpectedWithdrawals().expectedWithdrawals;
|
|
@@ -149,8 +149,8 @@ export class SeenBlockInput {
|
|
|
149
149
|
});
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
|
|
153
|
-
return this.blockInputs.
|
|
152
|
+
hasBlock(rootHex: RootHex): boolean {
|
|
153
|
+
return this.blockInputs.get(rootHex)?.hasBlock() ?? false;
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
get(rootHex: RootHex): IBlockInput | undefined {
|
|
@@ -84,8 +84,8 @@ export class SeenPayloadEnvelopeInput {
|
|
|
84
84
|
return this.payloadInputs.get(blockRootHex);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
return this.payloadInputs.
|
|
87
|
+
hasPayload(blockRootHex: RootHex): boolean {
|
|
88
|
+
return this.payloadInputs.get(blockRootHex)?.hasPayloadEnvelope() ?? false;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
prune(blockRootHex: RootHex): void {
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
computeTimeAtSlot,
|
|
7
7
|
getBlockProposerSignatureSet,
|
|
8
8
|
isExecutionBlockBodyType,
|
|
9
|
+
isStatePostBellatrix,
|
|
9
10
|
} from "@lodestar/state-transition";
|
|
10
11
|
import {SignedBeaconBlock, deneb, gloas, isGloasBeaconBlock} from "@lodestar/types";
|
|
11
12
|
import {byteArrayEquals, sleep, toRootHex} from "@lodestar/utils";
|
|
@@ -174,7 +175,7 @@ export async function validateGossipBlock(
|
|
|
174
175
|
if (isForkPostBellatrix(fork) && !isForkPostGloas(fork)) {
|
|
175
176
|
if (!isExecutionBlockBodyType(block.body)) throw Error("Not execution block body type");
|
|
176
177
|
const executionPayload = block.body.executionPayload;
|
|
177
|
-
if (blockState.isExecutionStateType && blockState.isExecutionEnabled(block)) {
|
|
178
|
+
if (isStatePostBellatrix(blockState) && blockState.isExecutionStateType && blockState.isExecutionEnabled(block)) {
|
|
178
179
|
const expectedTimestamp = computeTimeAtSlot(config, blockSlot, chain.genesisTime);
|
|
179
180
|
if (executionPayload.timestamp !== computeTimeAtSlot(config, blockSlot, chain.genesisTime)) {
|
|
180
181
|
throw new BlockGossipError(GossipAction.REJECT, {
|
|
@@ -10,11 +10,13 @@ import {
|
|
|
10
10
|
getBlockHeaderProposerSignatureSetByHeaderSlot,
|
|
11
11
|
getBlockHeaderProposerSignatureSetByParentStateSlot,
|
|
12
12
|
} from "@lodestar/state-transition";
|
|
13
|
-
import {DataColumnSidecar, Root, Slot, SubnetID, fulu, ssz} from "@lodestar/types";
|
|
13
|
+
import {DataColumnSidecar, Root, Slot, SubnetID, fulu, gloas, ssz} from "@lodestar/types";
|
|
14
14
|
import {byteArrayEquals, toRootHex, verifyMerkleBranch} from "@lodestar/utils";
|
|
15
15
|
import {BeaconMetrics} from "../../metrics/metrics/beacon.js";
|
|
16
16
|
import {Metrics} from "../../metrics/metrics.js";
|
|
17
|
+
import {getDataColumnSidecarSlot} from "../../util/dataColumns.js";
|
|
17
18
|
import {kzg} from "../../util/kzg.js";
|
|
19
|
+
import {PayloadEnvelopeInput} from "../blocks/payloadEnvelopeInput/index.js";
|
|
18
20
|
import {
|
|
19
21
|
DataColumnSidecarErrorCode,
|
|
20
22
|
DataColumnSidecarGossipError,
|
|
@@ -26,7 +28,7 @@ import {RegenCaller} from "../regen/interface.js";
|
|
|
26
28
|
|
|
27
29
|
// SPEC FUNCTION
|
|
28
30
|
// https://github.com/ethereum/consensus-specs/blob/v1.6.0-alpha.4/specs/fulu/p2p-interface.md#data_column_sidecar_subnet_id
|
|
29
|
-
export async function
|
|
31
|
+
export async function validateGossipFuluDataColumnSidecar(
|
|
30
32
|
chain: IBeaconChain,
|
|
31
33
|
dataColumnSidecar: fulu.DataColumnSidecar,
|
|
32
34
|
gossipSubnet: SubnetID,
|
|
@@ -36,7 +38,7 @@ export async function validateGossipDataColumnSidecar(
|
|
|
36
38
|
const blockRootHex = toRootHex(ssz.phase0.BeaconBlockHeader.hashTreeRoot(blockHeader));
|
|
37
39
|
|
|
38
40
|
// 1) [REJECT] The sidecar is valid as verified by verify_data_column_sidecar
|
|
39
|
-
|
|
41
|
+
verifyFuluDataColumnSidecar(chain.config, dataColumnSidecar);
|
|
40
42
|
|
|
41
43
|
// 2) [REJECT] The sidecar is for the correct subnet -- i.e. compute_subnet_for_data_column_sidecar(sidecar.index) == subnet_id
|
|
42
44
|
if (computeSubnetForDataColumnSidecar(chain.config, dataColumnSidecar) !== gossipSubnet) {
|
|
@@ -203,11 +205,75 @@ export async function validateGossipDataColumnSidecar(
|
|
|
203
205
|
// -- Handled in seenGossipBlockInput
|
|
204
206
|
}
|
|
205
207
|
|
|
208
|
+
// SPEC FUNCTION
|
|
209
|
+
// https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.3/specs/gloas/p2p-interface.md#data_column_sidecar_subnet_id
|
|
210
|
+
export async function validateGossipGloasDataColumnSidecar(
|
|
211
|
+
chain: IBeaconChain,
|
|
212
|
+
payloadInput: PayloadEnvelopeInput,
|
|
213
|
+
dataColumnSidecar: gloas.DataColumnSidecar,
|
|
214
|
+
gossipSubnet: SubnetID,
|
|
215
|
+
metrics: Metrics | null
|
|
216
|
+
): Promise<void> {
|
|
217
|
+
const blockRootHex = toRootHex(dataColumnSidecar.beaconBlockRoot);
|
|
218
|
+
const block = chain.forkChoice.getBlockHexDefaultStatus(blockRootHex);
|
|
219
|
+
|
|
220
|
+
// [IGNORE] A valid block for the sidecar's `slot` has been seen.
|
|
221
|
+
if (block === null) {
|
|
222
|
+
throw new DataColumnSidecarGossipError(GossipAction.IGNORE, {
|
|
223
|
+
code: DataColumnSidecarErrorCode.BLOCK_UNKNOWN,
|
|
224
|
+
blockRoot: blockRootHex,
|
|
225
|
+
slot: dataColumnSidecar.slot,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// [REJECT] The sidecar slot matches the slot of the block with root beacon_block_root.
|
|
230
|
+
if (block.slot !== dataColumnSidecar.slot) {
|
|
231
|
+
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
232
|
+
code: DataColumnSidecarErrorCode.INCORRECT_SIDECAR_SLOT,
|
|
233
|
+
columnIndex: dataColumnSidecar.index,
|
|
234
|
+
expected: block.slot,
|
|
235
|
+
actual: dataColumnSidecar.slot,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// [REJECT] The sidecar must pass verify_data_column_sidecar against the block commitments
|
|
240
|
+
const kzgCommitments = payloadInput.getBlobKzgCommitments();
|
|
241
|
+
verifyGloasDataColumnSidecar(dataColumnSidecar, kzgCommitments);
|
|
242
|
+
|
|
243
|
+
// [REJECT] The sidecar must be on the correct subnet
|
|
244
|
+
if (computeSubnetForDataColumnSidecar(chain.config, dataColumnSidecar) !== gossipSubnet) {
|
|
245
|
+
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
246
|
+
code: DataColumnSidecarErrorCode.INVALID_SUBNET,
|
|
247
|
+
columnIndex: dataColumnSidecar.index,
|
|
248
|
+
gossipSubnet,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// [REJECT] The sidecar kzg proofs must verify
|
|
253
|
+
const kzgProofTimer = metrics?.peerDas.dataColumnSidecarKzgProofsVerificationTime.startTimer();
|
|
254
|
+
try {
|
|
255
|
+
await verifyDataColumnSidecarKzgProofs(
|
|
256
|
+
kzgCommitments,
|
|
257
|
+
Array.from({length: dataColumnSidecar.column.length}, () => dataColumnSidecar.index),
|
|
258
|
+
dataColumnSidecar.column,
|
|
259
|
+
dataColumnSidecar.kzgProofs
|
|
260
|
+
);
|
|
261
|
+
} catch {
|
|
262
|
+
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
263
|
+
code: DataColumnSidecarErrorCode.INVALID_KZG_PROOF,
|
|
264
|
+
slot: dataColumnSidecar.slot,
|
|
265
|
+
columnIndex: dataColumnSidecar.index,
|
|
266
|
+
});
|
|
267
|
+
} finally {
|
|
268
|
+
kzgProofTimer?.();
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
206
272
|
/**
|
|
207
273
|
* SPEC FUNCTION
|
|
208
274
|
* https://github.com/ethereum/consensus-specs/blob/v1.6.0-alpha.4/specs/fulu/p2p-interface.md#verify_data_column_sidecar
|
|
209
275
|
*/
|
|
210
|
-
function
|
|
276
|
+
function verifyFuluDataColumnSidecar(config: ChainForkConfig, dataColumnSidecar: fulu.DataColumnSidecar): void {
|
|
211
277
|
if (dataColumnSidecar.index >= NUMBER_OF_COLUMNS) {
|
|
212
278
|
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
213
279
|
code: DataColumnSidecarErrorCode.INVALID_INDEX,
|
|
@@ -250,6 +316,41 @@ function verifyDataColumnSidecar(config: ChainForkConfig, dataColumnSidecar: ful
|
|
|
250
316
|
}
|
|
251
317
|
}
|
|
252
318
|
|
|
319
|
+
/**
|
|
320
|
+
* SPEC FUNCTION
|
|
321
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.3/specs/gloas/p2p-interface.md#modified-verify_data_column_sidecar
|
|
322
|
+
*/
|
|
323
|
+
function verifyGloasDataColumnSidecar(dataColumnSidecar: gloas.DataColumnSidecar, kzgCommitments: Uint8Array[]): void {
|
|
324
|
+
const slot = getDataColumnSidecarSlot(dataColumnSidecar);
|
|
325
|
+
if (dataColumnSidecar.index >= NUMBER_OF_COLUMNS) {
|
|
326
|
+
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
327
|
+
code: DataColumnSidecarErrorCode.INVALID_INDEX,
|
|
328
|
+
slot,
|
|
329
|
+
columnIndex: dataColumnSidecar.index,
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (dataColumnSidecar.column.length === 0) {
|
|
334
|
+
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
335
|
+
code: DataColumnSidecarErrorCode.NO_COMMITMENTS,
|
|
336
|
+
slot,
|
|
337
|
+
columnIndex: dataColumnSidecar.index,
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (
|
|
342
|
+
dataColumnSidecar.column.length !== kzgCommitments.length ||
|
|
343
|
+
dataColumnSidecar.column.length !== dataColumnSidecar.kzgProofs.length
|
|
344
|
+
) {
|
|
345
|
+
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
346
|
+
code: DataColumnSidecarErrorCode.MISMATCHED_LENGTHS,
|
|
347
|
+
columnLength: dataColumnSidecar.column.length,
|
|
348
|
+
commitmentsLength: kzgCommitments.length,
|
|
349
|
+
proofsLength: dataColumnSidecar.kzgProofs.length,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
253
354
|
/**
|
|
254
355
|
* SPEC FUNCTION
|
|
255
356
|
* https://github.com/ethereum/consensus-specs/blob/v1.6.0-alpha.4/specs/fulu/p2p-interface.md#verify_data_column_sidecar_kzg_proofs
|
|
@@ -287,19 +388,19 @@ export function verifyDataColumnSidecarInclusionProof(dataColumnSidecar: fulu.Da
|
|
|
287
388
|
}
|
|
288
389
|
|
|
289
390
|
/**
|
|
290
|
-
* Validate a subset of data column sidecars
|
|
391
|
+
* Validate a subset of fulu data column sidecars against a block
|
|
291
392
|
*
|
|
292
393
|
* Requires the block to be known to the node
|
|
293
394
|
*
|
|
294
395
|
* NOTE: chain is optional to skip signature verification. Helpful for testing purposes and so that can control whether
|
|
295
396
|
* signature gets checked depending on the reqresp method that is being checked
|
|
296
397
|
*/
|
|
297
|
-
export async function
|
|
398
|
+
export async function validateFuluBlockDataColumnSidecars(
|
|
298
399
|
chain: IBeaconChain | null,
|
|
299
400
|
blockSlot: Slot,
|
|
300
401
|
blockRoot: Root,
|
|
301
402
|
blockBlobCount: number,
|
|
302
|
-
dataColumnSidecars: fulu.
|
|
403
|
+
dataColumnSidecars: fulu.DataColumnSidecar[],
|
|
303
404
|
metrics?: BeaconMetrics["peerDas"] | null
|
|
304
405
|
): Promise<void> {
|
|
305
406
|
metrics?.dataColumnSidecarProcessingRequests.inc(dataColumnSidecars.length);
|
|
@@ -467,6 +568,128 @@ export async function validateBlockDataColumnSidecars(
|
|
|
467
568
|
"DataColumnSidecar has invalid KZG proof batch"
|
|
468
569
|
);
|
|
469
570
|
}
|
|
571
|
+
|
|
572
|
+
metrics?.dataColumnSidecarProcessingSuccesses.inc();
|
|
573
|
+
} finally {
|
|
574
|
+
verificationTimer?.();
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* Validate a subset of gloas data column sidecars against a block
|
|
580
|
+
* Gloas sidecars don't carry signed block headers, kzg commitments, or inclusion proofs
|
|
581
|
+
*/
|
|
582
|
+
export async function validateGloasBlockDataColumnSidecars(
|
|
583
|
+
blockSlot: Slot,
|
|
584
|
+
blockRoot: Root,
|
|
585
|
+
blockKzgCommitments: Uint8Array[],
|
|
586
|
+
dataColumnSidecars: gloas.DataColumnSidecar[],
|
|
587
|
+
metrics?: BeaconMetrics["peerDas"] | null
|
|
588
|
+
): Promise<void> {
|
|
589
|
+
metrics?.dataColumnSidecarProcessingRequests.inc(dataColumnSidecars.length);
|
|
590
|
+
const verificationTimer = metrics?.dataColumnSidecarGossipVerificationTime.startTimer();
|
|
591
|
+
try {
|
|
592
|
+
if (dataColumnSidecars.length === 0) {
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
if (blockKzgCommitments.length === 0) {
|
|
597
|
+
throw new DataColumnSidecarValidationError(
|
|
598
|
+
{
|
|
599
|
+
code: DataColumnSidecarErrorCode.INCORRECT_SIDECAR_COUNT,
|
|
600
|
+
slot: blockSlot,
|
|
601
|
+
expected: 0,
|
|
602
|
+
actual: dataColumnSidecars.length,
|
|
603
|
+
},
|
|
604
|
+
"Block has no blob commitments but data column sidecars were provided"
|
|
605
|
+
);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
const commitments: Uint8Array[] = [];
|
|
609
|
+
const cellIndices: number[] = [];
|
|
610
|
+
const cells: Uint8Array[] = [];
|
|
611
|
+
const proofs: Uint8Array[] = [];
|
|
612
|
+
for (const columnSidecar of dataColumnSidecars) {
|
|
613
|
+
if (columnSidecar.slot !== blockSlot) {
|
|
614
|
+
throw new DataColumnSidecarValidationError({
|
|
615
|
+
code: DataColumnSidecarErrorCode.INCORRECT_SIDECAR_SLOT,
|
|
616
|
+
columnIndex: columnSidecar.index,
|
|
617
|
+
expected: blockSlot,
|
|
618
|
+
actual: columnSidecar.slot,
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
if (!byteArrayEquals(columnSidecar.beaconBlockRoot, blockRoot)) {
|
|
623
|
+
throw new DataColumnSidecarValidationError({
|
|
624
|
+
code: DataColumnSidecarErrorCode.INCORRECT_BLOCK,
|
|
625
|
+
slot: blockSlot,
|
|
626
|
+
columnIndex: columnSidecar.index,
|
|
627
|
+
expected: toRootHex(blockRoot),
|
|
628
|
+
actual: toRootHex(columnSidecar.beaconBlockRoot),
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
if (columnSidecar.index >= NUMBER_OF_COLUMNS) {
|
|
633
|
+
throw new DataColumnSidecarValidationError(
|
|
634
|
+
{
|
|
635
|
+
code: DataColumnSidecarErrorCode.INVALID_INDEX,
|
|
636
|
+
slot: blockSlot,
|
|
637
|
+
columnIndex: columnSidecar.index,
|
|
638
|
+
},
|
|
639
|
+
"DataColumnSidecar has invalid index"
|
|
640
|
+
);
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
if (columnSidecar.column.length !== blockKzgCommitments.length) {
|
|
644
|
+
throw new DataColumnSidecarValidationError({
|
|
645
|
+
code: DataColumnSidecarErrorCode.INCORRECT_CELL_COUNT,
|
|
646
|
+
slot: blockSlot,
|
|
647
|
+
columnIndex: columnSidecar.index,
|
|
648
|
+
expected: blockKzgCommitments.length,
|
|
649
|
+
actual: columnSidecar.column.length,
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
if (columnSidecar.column.length !== columnSidecar.kzgProofs.length) {
|
|
654
|
+
throw new DataColumnSidecarValidationError({
|
|
655
|
+
code: DataColumnSidecarErrorCode.INCORRECT_KZG_PROOF_COUNT,
|
|
656
|
+
slot: blockSlot,
|
|
657
|
+
columnIndex: columnSidecar.index,
|
|
658
|
+
expected: columnSidecar.column.length,
|
|
659
|
+
actual: columnSidecar.kzgProofs.length,
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
commitments.push(...blockKzgCommitments);
|
|
664
|
+
cellIndices.push(...Array.from({length: columnSidecar.column.length}, () => columnSidecar.index));
|
|
665
|
+
cells.push(...columnSidecar.column);
|
|
666
|
+
proofs.push(...columnSidecar.kzgProofs);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
let reason: string | undefined;
|
|
670
|
+
// batch verification for the cases: downloadByRange and downloadByRoot
|
|
671
|
+
const kzgVerificationTimer = metrics?.kzgVerificationDataColumnBatchTime.startTimer();
|
|
672
|
+
try {
|
|
673
|
+
const valid = await kzg.asyncVerifyCellKzgProofBatch(commitments, cellIndices, cells, proofs);
|
|
674
|
+
if (!valid) {
|
|
675
|
+
reason = "Invalid KZG proof batch";
|
|
676
|
+
}
|
|
677
|
+
} catch (e) {
|
|
678
|
+
reason = (e as Error).message;
|
|
679
|
+
} finally {
|
|
680
|
+
kzgVerificationTimer?.();
|
|
681
|
+
}
|
|
682
|
+
if (reason !== undefined) {
|
|
683
|
+
throw new DataColumnSidecarValidationError(
|
|
684
|
+
{
|
|
685
|
+
code: DataColumnSidecarErrorCode.INVALID_KZG_PROOF_BATCH,
|
|
686
|
+
slot: blockSlot,
|
|
687
|
+
reason,
|
|
688
|
+
},
|
|
689
|
+
"DataColumnSidecar has invalid KZG proof batch"
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
|
|
470
693
|
metrics?.dataColumnSidecarProcessingSuccesses.inc();
|
|
471
694
|
} finally {
|
|
472
695
|
verificationTimer?.();
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
createSingleSignatureSetFromComponents,
|
|
4
4
|
getExecutionPayloadBidSigningRoot,
|
|
5
5
|
isActiveBuilder,
|
|
6
|
+
isStatePostGloas,
|
|
6
7
|
} from "@lodestar/state-transition";
|
|
7
8
|
import {gloas} from "@lodestar/types";
|
|
8
9
|
import {toRootHex} from "@lodestar/utils";
|
|
@@ -32,6 +33,9 @@ async function validateExecutionPayloadBid(
|
|
|
32
33
|
const parentBlockRootHex = toRootHex(bid.parentBlockRoot);
|
|
33
34
|
const parentBlockHashHex = toRootHex(bid.parentBlockHash);
|
|
34
35
|
const state = await chain.getHeadStateAtCurrentEpoch(RegenCaller.validateGossipExecutionPayloadBid);
|
|
36
|
+
if (!isStatePostGloas(state)) {
|
|
37
|
+
throw new Error(`Expected gloas+ state for execution payload bid validation, got fork=${state.forkName}`);
|
|
38
|
+
}
|
|
35
39
|
|
|
36
40
|
// [IGNORE] `bid.slot` is the current slot or the next slot.
|
|
37
41
|
const currentSlot = chain.clock.currentSlot;
|
|
@@ -83,9 +87,9 @@ async function validateExecutionPayloadBid(
|
|
|
83
87
|
});
|
|
84
88
|
}
|
|
85
89
|
|
|
86
|
-
// [IGNORE] this bid is the highest value bid seen for the
|
|
87
|
-
//
|
|
88
|
-
const bestBid = chain.executionPayloadBidPool.getBestBid(
|
|
90
|
+
// [IGNORE] this bid is the highest value bid seen for the tuple
|
|
91
|
+
// `(bid.slot, bid.parent_block_hash, bid.parent_block_root)`.
|
|
92
|
+
const bestBid = chain.executionPayloadBidPool.getBestBid(bid.slot, parentBlockHashHex, parentBlockRootHex);
|
|
89
93
|
if (bestBid !== null && bestBid.value >= bid.value) {
|
|
90
94
|
throw new ExecutionPayloadBidError(GossipAction.IGNORE, {
|
|
91
95
|
code: ExecutionPayloadBidErrorCode.BID_TOO_LOW,
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import {PayloadStatus} from "@lodestar/fork-choice";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
computeStartSlotAtEpoch,
|
|
4
|
+
getExecutionPayloadEnvelopeSignatureSet,
|
|
5
|
+
isStatePostGloas,
|
|
6
|
+
} from "@lodestar/state-transition";
|
|
3
7
|
import {gloas} from "@lodestar/types";
|
|
4
8
|
import {toRootHex} from "@lodestar/utils";
|
|
5
9
|
import {ExecutionPayloadEnvelopeError, ExecutionPayloadEnvelopeErrorCode, GossipAction} from "../errors/index.js";
|
|
@@ -113,6 +117,9 @@ async function validateExecutionPayloadEnvelope(
|
|
|
113
117
|
slot: envelope.slot,
|
|
114
118
|
});
|
|
115
119
|
});
|
|
120
|
+
if (!isStatePostGloas(blockState)) {
|
|
121
|
+
throw new Error(`Expected gloas+ state for execution payload envelope validation, got fork=${blockState.forkName}`);
|
|
122
|
+
}
|
|
116
123
|
|
|
117
124
|
const signatureSet = getExecutionPayloadEnvelopeSignatureSet(
|
|
118
125
|
chain.config,
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
computeEpochAtSlot,
|
|
3
3
|
createSingleSignatureSetFromComponents,
|
|
4
4
|
getPayloadAttestationDataSigningRoot,
|
|
5
|
+
isStatePostGloas,
|
|
5
6
|
} from "@lodestar/state-transition";
|
|
6
7
|
import {RootHex, gloas, ssz} from "@lodestar/types";
|
|
7
8
|
import {toRootHex} from "@lodestar/utils";
|
|
@@ -66,6 +67,9 @@ async function validatePayloadAttestationMessage(
|
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
const state = chain.getHeadState();
|
|
70
|
+
if (!isStatePostGloas(state)) {
|
|
71
|
+
throw new Error(`Expected gloas+ state for payload attestation validation, got fork=${state.forkName}`);
|
|
72
|
+
}
|
|
69
73
|
|
|
70
74
|
// [REJECT] The message's block `data.beacon_block_root` passes validation.
|
|
71
75
|
// TODO GLOAS: implement this. Technically if we cannot get proto block from fork choice,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {SYNC_COMMITTEE_SUBNET_COUNT, SYNC_COMMITTEE_SUBNET_SIZE} from "@lodestar/params";
|
|
2
|
-
import {IBeaconStateView} from "@lodestar/state-transition";
|
|
2
|
+
import {IBeaconStateView, isStatePostAltair} from "@lodestar/state-transition";
|
|
3
3
|
import {SubnetID, altair} from "@lodestar/types";
|
|
4
4
|
import {toRootHex} from "@lodestar/utils";
|
|
5
5
|
import {GossipAction, SyncCommitteeError, SyncCommitteeErrorCode} from "../errors/index.js";
|
|
@@ -148,6 +148,10 @@ function getIndicesInSubcommittee(
|
|
|
148
148
|
subnet: SubnetID,
|
|
149
149
|
data: Pick<altair.SyncCommitteeMessage, "slot" | "validatorIndex">
|
|
150
150
|
): IndexInSubcommittee[] | null {
|
|
151
|
+
if (!isStatePostAltair(headState)) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
|
|
151
155
|
const syncCommittee = headState.getIndexedSyncCommittee(data.slot);
|
|
152
156
|
const indexesInCommittee = syncCommittee.validatorIndexMap.get(data.validatorIndex);
|
|
153
157
|
if (indexesInCommittee === undefined) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {SYNC_COMMITTEE_SUBNET_SIZE} from "@lodestar/params";
|
|
2
|
-
import {IBeaconStateView, isSyncCommitteeAggregator} from "@lodestar/state-transition";
|
|
2
|
+
import {IBeaconStateView, isStatePostAltair, isSyncCommitteeAggregator} from "@lodestar/state-transition";
|
|
3
3
|
import {ValidatorIndex, altair} from "@lodestar/types";
|
|
4
4
|
import {GossipAction, SyncCommitteeError, SyncCommitteeErrorCode} from "../errors/index.js";
|
|
5
5
|
import {IBeaconChain} from "../interface.js";
|
|
@@ -107,6 +107,10 @@ function getContributionIndices(
|
|
|
107
107
|
state: IBeaconStateView,
|
|
108
108
|
contribution: altair.SyncCommitteeContribution
|
|
109
109
|
): ValidatorIndex[] {
|
|
110
|
+
if (!isStatePostAltair(state)) {
|
|
111
|
+
throw new Error("Expected Altair state for sync committee contribution");
|
|
112
|
+
}
|
|
113
|
+
|
|
110
114
|
const startIndex = contribution.subcommitteeIndex * SYNC_COMMITTEE_SUBNET_SIZE;
|
|
111
115
|
|
|
112
116
|
const syncCommittee = state.getIndexedSyncCommittee(contribution.slot);
|