@lodestar/beacon-node 1.43.0-dev.ade910fc78 → 1.43.0-dev.b741495bdc
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 +1 -4
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts +2 -2
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/utils.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +1 -4
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/GetBlobsTracker.d.ts +1 -1
- package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
- package/lib/chain/GetBlobsTracker.js +1 -2
- package/lib/chain/GetBlobsTracker.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/interface.d.ts +4 -4
- package/lib/chain/archiveStore/interface.d.ts.map +1 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts +4 -4
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts.map +1 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js +2 -4
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +2 -2
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +110 -58
- package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +23 -31
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +15 -14
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +63 -85
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +1 -2
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +3 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +20 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +5 -0
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeProcessor.js +6 -4
- package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +15 -21
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +24 -0
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -0
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +76 -0
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -0
- package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts +14 -0
- package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -0
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js +25 -0
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -0
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts +1 -1
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js +1 -1
- package/lib/chain/chain.d.ts +3 -3
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +16 -32
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +16 -4
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/emitter.js +5 -0
- package/lib/chain/emitter.js.map +1 -1
- package/lib/chain/errors/attestationError.d.ts +8 -1
- package/lib/chain/errors/attestationError.d.ts.map +1 -1
- package/lib/chain/errors/attestationError.js +4 -0
- package/lib/chain/errors/attestationError.js.map +1 -1
- package/lib/chain/errors/executionPayloadBid.d.ts +5 -0
- package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadBid.js +1 -0
- package/lib/chain/errors/executionPayloadBid.js.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.d.ts +5 -0
- package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.js +1 -0
- package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +11 -15
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +2 -2
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +22 -16
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts +3 -9
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js +5 -32
- package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +3 -8
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +30 -19
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/errors.d.ts +1 -11
- package/lib/chain/regen/errors.d.ts.map +1 -1
- package/lib/chain/regen/errors.js +0 -2
- package/lib/chain/regen/errors.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +6 -11
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/queued.d.ts +6 -10
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +3 -10
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/regen/regen.d.ts +0 -5
- package/lib/chain/regen/regen.d.ts.map +1 -1
- package/lib/chain/regen/regen.js +0 -8
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +1 -7
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +4 -9
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/types.d.ts +0 -6
- package/lib/chain/stateCache/types.d.ts.map +1 -1
- package/lib/chain/stateCache/types.js.map +1 -1
- package/lib/chain/validation/aggregateAndProof.js +12 -0
- package/lib/chain/validation/aggregateAndProof.js.map +1 -1
- package/lib/chain/validation/attestation.d.ts.map +1 -1
- package/lib/chain/validation/attestation.js +12 -0
- package/lib/chain/validation/attestation.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +13 -1
- 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 +21 -11
- 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 -3
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/db/repositories/executionPayloadEnvelopeArchive.js +1 -1
- package/lib/db/repositories/executionPayloadEnvelopeArchive.js.map +1 -1
- package/lib/execution/engine/http.d.ts.map +1 -1
- package/lib/execution/engine/http.js +21 -14
- package/lib/execution/engine/http.js.map +1 -1
- package/lib/execution/engine/interface.d.ts +1 -0
- package/lib/execution/engine/interface.d.ts.map +1 -1
- package/lib/execution/engine/mock.d.ts.map +1 -1
- package/lib/execution/engine/mock.js +6 -0
- package/lib/execution/engine/mock.js.map +1 -1
- package/lib/execution/engine/types.d.ts +20 -0
- package/lib/execution/engine/types.d.ts.map +1 -1
- package/lib/execution/engine/types.js +18 -0
- package/lib/execution/engine/types.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +3 -2
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/network.js +1 -1
- package/lib/network/network.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +22 -6
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +4 -2
- package/lib/node/nodejs.js.map +1 -1
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +16 -3
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +16 -16
- package/src/api/impl/beacon/blocks/index.ts +1 -4
- package/src/api/impl/beacon/state/utils.ts +2 -2
- package/src/api/impl/validator/index.ts +3 -6
- package/src/chain/GetBlobsTracker.ts +1 -2
- package/src/chain/archiveStore/archiveStore.ts +5 -5
- package/src/chain/archiveStore/interface.ts +4 -4
- package/src/chain/archiveStore/strategies/frequencyStateArchiveStrategy.ts +6 -8
- package/src/chain/archiveStore/utils/archiveBlocks.ts +153 -94
- package/src/chain/blocks/importBlock.ts +22 -35
- package/src/chain/blocks/importExecutionPayload.ts +77 -103
- package/src/chain/blocks/index.ts +1 -2
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +27 -0
- package/src/chain/blocks/payloadEnvelopeProcessor.ts +6 -5
- package/src/chain/blocks/types.ts +15 -26
- package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +129 -0
- package/src/chain/blocks/verifyPayloadsDataAvailability.ts +38 -0
- package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +1 -1
- package/src/chain/chain.ts +23 -48
- package/src/chain/emitter.ts +15 -3
- package/src/chain/errors/attestationError.ts +6 -1
- package/src/chain/errors/executionPayloadBid.ts +6 -0
- package/src/chain/errors/executionPayloadEnvelope.ts +6 -0
- package/src/chain/forkChoice/index.ts +8 -20
- package/src/chain/interface.ts +2 -2
- package/src/chain/prepareNextSlot.ts +25 -16
- package/src/chain/produceBlock/computeNewStateRoot.ts +6 -43
- package/src/chain/produceBlock/produceBlockBody.ts +41 -20
- package/src/chain/regen/errors.ts +1 -6
- package/src/chain/regen/interface.ts +6 -11
- package/src/chain/regen/queued.ts +6 -14
- package/src/chain/regen/regen.ts +0 -8
- package/src/chain/stateCache/persistentCheckpointsCache.ts +5 -15
- package/src/chain/stateCache/types.ts +0 -3
- package/src/chain/validation/aggregateAndProof.ts +13 -0
- package/src/chain/validation/attestation.ts +13 -0
- package/src/chain/validation/executionPayloadBid.ts +14 -0
- package/src/chain/validation/executionPayloadEnvelope.ts +22 -12
- package/src/chain/validation/payloadAttestationMessage.ts +5 -3
- package/src/db/repositories/executionPayloadEnvelopeArchive.ts +1 -1
- package/src/execution/engine/http.ts +21 -14
- package/src/execution/engine/interface.ts +1 -0
- package/src/execution/engine/mock.ts +8 -1
- package/src/execution/engine/types.ts +41 -0
- package/src/network/network.ts +1 -1
- package/src/network/processor/gossipHandlers.ts +26 -10
- package/src/node/nodejs.ts +4 -2
- package/src/util/sszBytes.ts +21 -3
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
IBeaconStateView,
|
|
20
20
|
type IBeaconStateViewBellatrix,
|
|
21
21
|
computeTimeAtSlot,
|
|
22
|
-
isParentBlockFull,
|
|
23
22
|
isStatePostBellatrix,
|
|
24
23
|
isStatePostCapella,
|
|
25
24
|
isStatePostGloas,
|
|
@@ -47,8 +46,9 @@ import {
|
|
|
47
46
|
electra,
|
|
48
47
|
fulu,
|
|
49
48
|
gloas,
|
|
49
|
+
ssz,
|
|
50
50
|
} from "@lodestar/types";
|
|
51
|
-
import {Logger, fromHex, sleep, toHex, toPubkeyHex, toRootHex} from "@lodestar/utils";
|
|
51
|
+
import {Logger, byteArrayEquals, fromHex, sleep, toHex, toPubkeyHex, toRootHex} from "@lodestar/utils";
|
|
52
52
|
import {ZERO_HASH_HEX} from "../../constants/index.js";
|
|
53
53
|
import {numToQuantity} from "../../execution/engine/utils.js";
|
|
54
54
|
import {
|
|
@@ -111,12 +111,6 @@ export type ProduceFullGloas = {
|
|
|
111
111
|
executionRequests: electra.ExecutionRequests;
|
|
112
112
|
blobsBundle: BlobsBundle<ForkPostGloas>;
|
|
113
113
|
cells: fulu.Cell[][];
|
|
114
|
-
/**
|
|
115
|
-
* Cached payload envelope state root computed during block production.
|
|
116
|
-
* This is the state root after running `processExecutionPayloadEnvelope` on the
|
|
117
|
-
* post-block state, and later used to construct the `ExecutionPayloadEnvelope`.
|
|
118
|
-
*/
|
|
119
|
-
payloadEnvelopeStateRoot: Root;
|
|
120
114
|
};
|
|
121
115
|
export type ProduceFullFulu = {
|
|
122
116
|
type: BlockType.Full;
|
|
@@ -220,11 +214,15 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
220
214
|
});
|
|
221
215
|
|
|
222
216
|
// Get execution payload from EL
|
|
217
|
+
const parentBlockHash = this.forkChoice.shouldExtendPayload(toRootHex(parentBlockRoot))
|
|
218
|
+
? currentState.latestExecutionPayloadBid.blockHash
|
|
219
|
+
: currentState.latestExecutionPayloadBid.parentBlockHash;
|
|
223
220
|
const prepareRes = await prepareExecutionPayload(
|
|
224
221
|
this,
|
|
225
222
|
this.logger,
|
|
226
223
|
fork,
|
|
227
224
|
parentBlockRoot,
|
|
225
|
+
parentBlockHash,
|
|
228
226
|
safeBlockHash,
|
|
229
227
|
finalizedBlockHash ?? ZERO_HASH_HEX,
|
|
230
228
|
currentState,
|
|
@@ -261,8 +259,8 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
261
259
|
|
|
262
260
|
// Create self-build execution payload bid
|
|
263
261
|
const bid: gloas.ExecutionPayloadBid = {
|
|
264
|
-
parentBlockHash
|
|
265
|
-
parentBlockRoot
|
|
262
|
+
parentBlockHash,
|
|
263
|
+
parentBlockRoot,
|
|
266
264
|
blockHash: executionPayload.blockHash,
|
|
267
265
|
prevRandao: currentState.getRandaoMix(currentState.epoch),
|
|
268
266
|
feeRecipient: executionPayload.feeRecipient,
|
|
@@ -272,6 +270,7 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
272
270
|
value: 0,
|
|
273
271
|
executionPayment: 0,
|
|
274
272
|
blobKzgCommitments: blobsBundle.commitments,
|
|
273
|
+
executionRequestsRoot: ssz.electra.ExecutionRequests.hashTreeRoot(executionRequests),
|
|
275
274
|
};
|
|
276
275
|
const signedBid: gloas.SignedExecutionPayloadBid = {
|
|
277
276
|
message: bid,
|
|
@@ -283,6 +282,7 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
283
282
|
gloasBody.signedExecutionPayloadBid = signedBid;
|
|
284
283
|
// TODO GLOAS: Get payload attestations from pool for previous slot
|
|
285
284
|
gloasBody.payloadAttestations = [];
|
|
285
|
+
// TODO GLOAS: set parentExecutionRequests in the block body
|
|
286
286
|
blockBody = gloasBody as AssembledBodyType<T>;
|
|
287
287
|
|
|
288
288
|
// Store execution payload data required to construct execution payload envelope later
|
|
@@ -340,6 +340,7 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
340
340
|
this.logger,
|
|
341
341
|
fork,
|
|
342
342
|
parentBlockRoot,
|
|
343
|
+
currentState.latestExecutionPayloadHeader.blockHash,
|
|
343
344
|
safeBlockHash,
|
|
344
345
|
finalizedBlockHash ?? ZERO_HASH_HEX,
|
|
345
346
|
currentState,
|
|
@@ -448,6 +449,7 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
448
449
|
this.logger,
|
|
449
450
|
fork,
|
|
450
451
|
parentBlockRoot,
|
|
452
|
+
currentState.latestExecutionPayloadHeader.blockHash,
|
|
451
453
|
safeBlockHash,
|
|
452
454
|
finalizedBlockHash ?? ZERO_HASH_HEX,
|
|
453
455
|
currentState,
|
|
@@ -613,17 +615,17 @@ export async function prepareExecutionPayload(
|
|
|
613
615
|
logger: Logger,
|
|
614
616
|
fork: ForkPostBellatrix,
|
|
615
617
|
parentBlockRoot: Root,
|
|
618
|
+
parentBlockHash: Bytes32,
|
|
616
619
|
safeBlockHash: RootHex,
|
|
617
620
|
finalizedBlockHash: RootHex,
|
|
618
621
|
state: IBeaconStateViewBellatrix,
|
|
619
622
|
suggestedFeeRecipient: string
|
|
620
623
|
): Promise<{prepType: PayloadPreparationType; payloadId: PayloadId}> {
|
|
621
|
-
const parentHash = state.latestBlockHash;
|
|
622
624
|
const timestamp = computeTimeAtSlot(chain.config, state.slot, state.genesisTime);
|
|
623
625
|
const prevRandao = state.getRandaoMix(state.epoch);
|
|
624
626
|
|
|
625
627
|
const payloadIdCached = chain.executionEngine.payloadIdCache.get({
|
|
626
|
-
headBlockHash: toRootHex(
|
|
628
|
+
headBlockHash: toRootHex(parentBlockHash),
|
|
627
629
|
finalizedBlockHash,
|
|
628
630
|
timestamp: numToQuantity(timestamp),
|
|
629
631
|
prevRandao: toHex(prevRandao),
|
|
@@ -652,12 +654,13 @@ export async function prepareExecutionPayload(
|
|
|
652
654
|
prepareState: state,
|
|
653
655
|
prepareSlot: state.slot,
|
|
654
656
|
parentBlockRoot,
|
|
657
|
+
parentBlockHash,
|
|
655
658
|
feeRecipient: suggestedFeeRecipient,
|
|
656
659
|
});
|
|
657
660
|
|
|
658
661
|
payloadId = await chain.executionEngine.notifyForkchoiceUpdate(
|
|
659
662
|
fork,
|
|
660
|
-
toRootHex(
|
|
663
|
+
toRootHex(parentBlockHash),
|
|
661
664
|
safeBlockHash,
|
|
662
665
|
finalizedBlockHash,
|
|
663
666
|
attributes
|
|
@@ -709,20 +712,30 @@ export function getPayloadAttributesForSSE(
|
|
|
709
712
|
prepareState,
|
|
710
713
|
prepareSlot,
|
|
711
714
|
parentBlockRoot,
|
|
715
|
+
parentBlockHash,
|
|
712
716
|
feeRecipient,
|
|
713
|
-
}: {
|
|
717
|
+
}: {
|
|
718
|
+
prepareState: IBeaconStateViewBellatrix;
|
|
719
|
+
prepareSlot: Slot;
|
|
720
|
+
parentBlockRoot: Root;
|
|
721
|
+
parentBlockHash: Bytes32;
|
|
722
|
+
feeRecipient: string;
|
|
723
|
+
}
|
|
714
724
|
): SSEPayloadAttributes {
|
|
715
|
-
const parentHash = prepareState.latestBlockHash;
|
|
716
725
|
const payloadAttributes = preparePayloadAttributes(fork, chain, {
|
|
717
726
|
prepareState,
|
|
718
727
|
prepareSlot,
|
|
719
728
|
parentBlockRoot,
|
|
729
|
+
parentBlockHash,
|
|
720
730
|
feeRecipient,
|
|
721
731
|
});
|
|
722
732
|
|
|
723
733
|
let parentBlockNumber: number;
|
|
724
734
|
if (isForkPostGloas(fork)) {
|
|
725
|
-
const parentBlock = chain.forkChoice.getBlockHexAndBlockHash(
|
|
735
|
+
const parentBlock = chain.forkChoice.getBlockHexAndBlockHash(
|
|
736
|
+
toRootHex(parentBlockRoot),
|
|
737
|
+
toRootHex(parentBlockHash)
|
|
738
|
+
);
|
|
726
739
|
if (parentBlock?.executionPayloadBlockHash == null) {
|
|
727
740
|
throw Error(`Parent block not found in fork choice root=${toRootHex(parentBlockRoot)}`);
|
|
728
741
|
}
|
|
@@ -736,7 +749,7 @@ export function getPayloadAttributesForSSE(
|
|
|
736
749
|
proposalSlot: prepareSlot,
|
|
737
750
|
parentBlockNumber,
|
|
738
751
|
parentBlockRoot,
|
|
739
|
-
parentBlockHash
|
|
752
|
+
parentBlockHash,
|
|
740
753
|
payloadAttributes,
|
|
741
754
|
};
|
|
742
755
|
return ssePayloadAttributes;
|
|
@@ -751,11 +764,13 @@ function preparePayloadAttributes(
|
|
|
751
764
|
prepareState,
|
|
752
765
|
prepareSlot,
|
|
753
766
|
parentBlockRoot,
|
|
767
|
+
parentBlockHash,
|
|
754
768
|
feeRecipient,
|
|
755
769
|
}: {
|
|
756
770
|
prepareState: IBeaconStateViewBellatrix;
|
|
757
771
|
prepareSlot: Slot;
|
|
758
772
|
parentBlockRoot: Root;
|
|
773
|
+
parentBlockHash: Bytes32;
|
|
759
774
|
feeRecipient: string;
|
|
760
775
|
}
|
|
761
776
|
): SSEPayloadAttributes["payloadAttributes"] {
|
|
@@ -772,13 +787,15 @@ function preparePayloadAttributes(
|
|
|
772
787
|
throw new Error("Expected Capella state for withdrawals");
|
|
773
788
|
}
|
|
774
789
|
|
|
775
|
-
if (isStatePostGloas(prepareState)
|
|
790
|
+
if (isStatePostGloas(prepareState)) {
|
|
791
|
+
const isExtendingPayload = byteArrayEquals(parentBlockHash, prepareState.latestExecutionPayloadBid.blockHash);
|
|
776
792
|
// When the parent block is empty, state.payloadExpectedWithdrawals holds a batch
|
|
777
793
|
// already deducted from CL balances but never credited on the EL (the envelope
|
|
778
794
|
// was not delivered). The next payload must carry those same withdrawals to
|
|
779
795
|
// restore CL/EL consistency, otherwise validators permanently lose that balance.
|
|
780
|
-
(payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
|
|
781
|
-
prepareState.
|
|
796
|
+
(payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals = isExtendingPayload
|
|
797
|
+
? prepareState.getExpectedWithdrawals().expectedWithdrawals
|
|
798
|
+
: prepareState.payloadExpectedWithdrawals;
|
|
782
799
|
} else {
|
|
783
800
|
// withdrawals logic is now fork aware as it changes on electra fork post capella
|
|
784
801
|
(payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
|
|
@@ -790,6 +807,10 @@ function preparePayloadAttributes(
|
|
|
790
807
|
(payloadAttributes as deneb.SSEPayloadAttributes["payloadAttributes"]).parentBeaconBlockRoot = parentBlockRoot;
|
|
791
808
|
}
|
|
792
809
|
|
|
810
|
+
if (ForkSeq[fork] >= ForkSeq.gloas) {
|
|
811
|
+
(payloadAttributes as gloas.SSEPayloadAttributes["payloadAttributes"]).slotNumber = prepareSlot;
|
|
812
|
+
}
|
|
813
|
+
|
|
793
814
|
return payloadAttributes;
|
|
794
815
|
}
|
|
795
816
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {PayloadStatus} from "@lodestar/fork-choice";
|
|
2
1
|
import {Root, RootHex, Slot} from "@lodestar/types";
|
|
3
2
|
|
|
4
3
|
export enum RegenErrorCode {
|
|
@@ -10,8 +9,6 @@ export enum RegenErrorCode {
|
|
|
10
9
|
BLOCK_NOT_IN_DB = "REGEN_ERROR_BLOCK_NOT_IN_DB",
|
|
11
10
|
STATE_TRANSITION_ERROR = "REGEN_ERROR_STATE_TRANSITION_ERROR",
|
|
12
11
|
INVALID_STATE_ROOT = "REGEN_ERROR_INVALID_STATE_ROOT",
|
|
13
|
-
UNEXPECTED_PAYLOAD_STATUS = "REGEN_ERROR_UNEXPECTED_PAYLOAD_STATUS",
|
|
14
|
-
INTERNAL_ERROR = "REGEN_ERROR_INTERNAL_ERROR",
|
|
15
12
|
}
|
|
16
13
|
|
|
17
14
|
export type RegenErrorType =
|
|
@@ -22,9 +19,7 @@ export type RegenErrorType =
|
|
|
22
19
|
| {code: RegenErrorCode.TOO_MANY_BLOCK_PROCESSED; stateRoot: RootHex | Root}
|
|
23
20
|
| {code: RegenErrorCode.BLOCK_NOT_IN_DB; blockRoot: RootHex | Root}
|
|
24
21
|
| {code: RegenErrorCode.STATE_TRANSITION_ERROR; error: Error}
|
|
25
|
-
| {code: RegenErrorCode.INVALID_STATE_ROOT; slot: Slot; expected: RootHex; actual: RootHex}
|
|
26
|
-
| {code: RegenErrorCode.UNEXPECTED_PAYLOAD_STATUS; blockRoot: RootHex | Root; payloadStatus: PayloadStatus}
|
|
27
|
-
| {code: RegenErrorCode.INTERNAL_ERROR; message: string};
|
|
22
|
+
| {code: RegenErrorCode.INVALID_STATE_ROOT; slot: Slot; expected: RootHex; actual: RootHex};
|
|
28
23
|
|
|
29
24
|
export class RegenError extends Error {
|
|
30
25
|
type: RegenErrorType;
|
|
@@ -2,7 +2,7 @@ import {routes} from "@lodestar/api";
|
|
|
2
2
|
import {ProtoBlock} from "@lodestar/fork-choice";
|
|
3
3
|
import {IBeaconStateView} from "@lodestar/state-transition";
|
|
4
4
|
import {BeaconBlock, Epoch, RootHex, Slot, phase0} from "@lodestar/types";
|
|
5
|
-
import {
|
|
5
|
+
import {CheckpointHex} from "../stateCache/types.js";
|
|
6
6
|
|
|
7
7
|
export enum RegenCaller {
|
|
8
8
|
getDuties = "getDuties",
|
|
@@ -40,20 +40,15 @@ export interface IStateRegenerator extends IStateRegeneratorInternal {
|
|
|
40
40
|
dumpCacheSummary(): routes.lodestar.StateCacheItem[];
|
|
41
41
|
getStateSync(stateRoot: RootHex): IBeaconStateView | null;
|
|
42
42
|
getPreStateSync(block: BeaconBlock): IBeaconStateView | null;
|
|
43
|
-
getCheckpointStateOrBytes(cp:
|
|
44
|
-
getCheckpointStateSync(cp:
|
|
43
|
+
getCheckpointStateOrBytes(cp: CheckpointHex): Promise<IBeaconStateView | Uint8Array | null>;
|
|
44
|
+
getCheckpointStateSync(cp: CheckpointHex): IBeaconStateView | null;
|
|
45
45
|
getClosestHeadState(head: ProtoBlock): IBeaconStateView | null;
|
|
46
46
|
pruneOnCheckpoint(finalizedEpoch: Epoch, justifiedEpoch: Epoch, headStateRoot: RootHex): void;
|
|
47
47
|
pruneOnFinalized(finalizedEpoch: Epoch): void;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* payloadPresent is true if this is payload state, false if block state.
|
|
52
|
-
* payloadPresent is always true for pre-gloas.
|
|
53
|
-
*/
|
|
54
|
-
addCheckpointState(cp: phase0.Checkpoint, item: IBeaconStateView, payloadPresent: boolean): void;
|
|
48
|
+
processState(blockRootHex: RootHex, postState: IBeaconStateView): void;
|
|
49
|
+
addCheckpointState(cp: phase0.Checkpoint, item: IBeaconStateView): void;
|
|
55
50
|
updateHeadState(newHead: ProtoBlock, maybeHeadState: IBeaconStateView): void;
|
|
56
|
-
updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch
|
|
51
|
+
updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch): number | null;
|
|
57
52
|
}
|
|
58
53
|
|
|
59
54
|
/**
|
|
@@ -5,7 +5,7 @@ import {BeaconBlock, Epoch, RootHex, Slot, isGloasBeaconBlock, phase0} from "@lo
|
|
|
5
5
|
import {Logger, toRootHex} from "@lodestar/utils";
|
|
6
6
|
import {Metrics} from "../../metrics/index.js";
|
|
7
7
|
import {JobItemQueue} from "../../util/queue/index.js";
|
|
8
|
-
import {BlockStateCache,
|
|
8
|
+
import {BlockStateCache, CheckpointHex, CheckpointStateCache} from "../stateCache/types.js";
|
|
9
9
|
import {RegenError, RegenErrorCode} from "./errors.js";
|
|
10
10
|
import {
|
|
11
11
|
IStateRegenerator,
|
|
@@ -125,14 +125,14 @@ export class QueuedStateRegenerator implements IStateRegenerator {
|
|
|
125
125
|
return null;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
async getCheckpointStateOrBytes(cp:
|
|
128
|
+
async getCheckpointStateOrBytes(cp: CheckpointHex): Promise<IBeaconStateView | Uint8Array | null> {
|
|
129
129
|
return this.checkpointStateCache.getStateOrBytes(cp);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
/**
|
|
133
133
|
* Get checkpoint state from cache
|
|
134
134
|
*/
|
|
135
|
-
getCheckpointStateSync(cp:
|
|
135
|
+
getCheckpointStateSync(cp: CheckpointHex): IBeaconStateView | null {
|
|
136
136
|
return this.checkpointStateCache.get(cp);
|
|
137
137
|
}
|
|
138
138
|
|
|
@@ -153,22 +153,14 @@ export class QueuedStateRegenerator implements IStateRegenerator {
|
|
|
153
153
|
this.blockStateCache.deleteAllBeforeEpoch(finalizedEpoch);
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
|
|
156
|
+
processState(blockRootHex: RootHex, postState: IBeaconStateView): void {
|
|
157
157
|
this.blockStateCache.add(postState);
|
|
158
158
|
this.checkpointStateCache.processState(blockRootHex, postState).catch((e) => {
|
|
159
159
|
this.logger.debug("Error processing block state", {blockRootHex, slot: postState.slot}, e);
|
|
160
160
|
});
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
|
|
164
|
-
* Process payload state for caching after importing execution payload.
|
|
165
|
-
*/
|
|
166
|
-
processPayloadState(payloadState: IBeaconStateView): void {
|
|
167
|
-
// Add payload state to block state cache (keyed by payload state root)
|
|
168
|
-
this.blockStateCache.add(payloadState);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
addCheckpointState(cp: phase0.Checkpoint, item: IBeaconStateView, _payloadPresent: boolean): void {
|
|
163
|
+
addCheckpointState(cp: phase0.Checkpoint, item: IBeaconStateView): void {
|
|
172
164
|
this.checkpointStateCache.add(cp, item);
|
|
173
165
|
}
|
|
174
166
|
|
|
@@ -205,7 +197,7 @@ export class QueuedStateRegenerator implements IStateRegenerator {
|
|
|
205
197
|
}
|
|
206
198
|
}
|
|
207
199
|
|
|
208
|
-
updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch
|
|
200
|
+
updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch): number | null {
|
|
209
201
|
return this.checkpointStateCache.updatePreComputedCheckpoint(rootHex, epoch);
|
|
210
202
|
}
|
|
211
203
|
|
package/src/chain/regen/regen.ts
CHANGED
|
@@ -332,11 +332,6 @@ async function processSlotsByCheckpoint(
|
|
|
332
332
|
* emitting "checkpoint" events after every epoch processed.
|
|
333
333
|
*
|
|
334
334
|
* Stops processing after no more full epochs can be processed.
|
|
335
|
-
*
|
|
336
|
-
* Output state variant:
|
|
337
|
-
* - Post-Gloas: If slots are processed, returns block state (payloadPresent=false).
|
|
338
|
-
* If no slots processed, returns preState as-is (preserves variant).
|
|
339
|
-
* - Pre-Gloas: Always payloadPresent=true (no block/payload distinction).
|
|
340
335
|
*/
|
|
341
336
|
export async function processSlotsToNearestCheckpoint(
|
|
342
337
|
modules: {
|
|
@@ -380,9 +375,6 @@ export async function processSlotsToNearestCheckpoint(
|
|
|
380
375
|
// This may becomes the "official" checkpoint state if the 1st block of epoch is skipped
|
|
381
376
|
const checkpointState = postState;
|
|
382
377
|
const cp = getCheckpointFromState(checkpointState);
|
|
383
|
-
// processSlots() only does epoch transitions, never processes payloads
|
|
384
|
-
// Pre-Gloas: payloadPresent is always true (execution payload embedded in block)
|
|
385
|
-
// Post-Gloas: result is a block state (payloadPresent=false)
|
|
386
378
|
checkpointStateCache.add(cp, checkpointState);
|
|
387
379
|
// consumers should not mutate state ever
|
|
388
380
|
emitter?.emit(ChainEvent.checkpoint, cp, checkpointState);
|
|
@@ -9,7 +9,7 @@ import {IClock} from "../../util/clock.js";
|
|
|
9
9
|
import {serializeState} from "../serializeState.js";
|
|
10
10
|
import {CPStateDatastore, DatastoreKey} from "./datastore/index.js";
|
|
11
11
|
import {MapTracker} from "./mapMetrics.js";
|
|
12
|
-
import {BlockStateCache, CacheItemType, CheckpointHex,
|
|
12
|
+
import {BlockStateCache, CacheItemType, CheckpointHex, CheckpointStateCache} from "./types.js";
|
|
13
13
|
|
|
14
14
|
export type PersistentCheckpointStateCacheOpts = {
|
|
15
15
|
/** Keep max n state epochs in memory, persist the rest to disk */
|
|
@@ -226,7 +226,10 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
|
|
|
226
226
|
}
|
|
227
227
|
sszTimer?.();
|
|
228
228
|
const timer = this.metrics?.cpStateCache.stateReloadDuration.startTimer();
|
|
229
|
-
|
|
229
|
+
// preload validators and balances for faster state transition
|
|
230
|
+
const newCachedState = seedState.loadOtherState(stateBytes, validatorsBytes, {
|
|
231
|
+
preloadValidatorsAndBalances: true,
|
|
232
|
+
});
|
|
230
233
|
// hashTreeRoot() calls the commit() inside
|
|
231
234
|
// there is no modification inside the state, it's just that we want to compute and cache all roots
|
|
232
235
|
const stateRoot = toRootHex(newCachedState.hashTreeRoot());
|
|
@@ -843,19 +846,6 @@ export function toCheckpointHex(checkpoint: phase0.Checkpoint): CheckpointHex {
|
|
|
843
846
|
};
|
|
844
847
|
}
|
|
845
848
|
|
|
846
|
-
/** TODO GLOAS: remove after rolling back regen dual-state changes */
|
|
847
|
-
export function fcCheckpointToHexPayload(checkpoint: {
|
|
848
|
-
epoch: Epoch;
|
|
849
|
-
rootHex: RootHex;
|
|
850
|
-
payloadStatus?: number;
|
|
851
|
-
}): CheckpointHexPayload {
|
|
852
|
-
return {
|
|
853
|
-
epoch: checkpoint.epoch,
|
|
854
|
-
rootHex: checkpoint.rootHex,
|
|
855
|
-
payloadPresent: true,
|
|
856
|
-
};
|
|
857
|
-
}
|
|
858
|
-
|
|
859
849
|
export function toCheckpointKey(cp: CheckpointHex): string {
|
|
860
850
|
return `${cp.rootHex}:${cp.epoch}`;
|
|
861
851
|
}
|
|
@@ -4,9 +4,6 @@ import {Epoch, RootHex, phase0} from "@lodestar/types";
|
|
|
4
4
|
|
|
5
5
|
export type CheckpointHex = {epoch: Epoch; rootHex: RootHex};
|
|
6
6
|
|
|
7
|
-
/** TODO GLOAS: payloadPresent is ignored — remove after rolling back regen dual-state changes */
|
|
8
|
-
export type CheckpointHexPayload = {epoch: Epoch; rootHex: RootHex; payloadPresent: boolean};
|
|
9
|
-
|
|
10
7
|
/**
|
|
11
8
|
* Lodestar currently keeps two state caches around.
|
|
12
9
|
*
|
|
@@ -90,6 +90,19 @@ async function validateAggregateAndProof(
|
|
|
90
90
|
});
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
// [REJECT] If `aggregate.data.index == 1` (payload present for a past
|
|
94
|
+
// block), the execution payload for `block` passes validation.
|
|
95
|
+
// [IGNORE] When `aggregate.data.index == 1` (payload present for a past block),
|
|
96
|
+
// the corresponding execution payload for `block` has been seen (a client MAY queue
|
|
97
|
+
// attestations for processing once the payload is retrieved and SHOULD request the
|
|
98
|
+
// payload envelope via `ExecutionPayloadEnvelopesByRoot`).
|
|
99
|
+
if (block !== null && attData.index === 1 && !chain.seenPayloadEnvelope(toRootHex(attData.beaconBlockRoot))) {
|
|
100
|
+
throw new AttestationError(GossipAction.IGNORE, {
|
|
101
|
+
code: AttestationErrorCode.EXECUTION_PAYLOAD_NOT_SEEN,
|
|
102
|
+
beaconBlockRoot: toRootHex(attData.beaconBlockRoot),
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
93
106
|
// [REJECT] len(committee_indices) == 1, where committee_indices = get_committee_indices(aggregate)
|
|
94
107
|
committeeIndex = (aggregate as electra.Attestation).committeeBits.getSingleTrueBit();
|
|
95
108
|
if (committeeIndex === null) {
|
|
@@ -315,6 +315,19 @@ async function validateAttestationNoSignatureCheck(
|
|
|
315
315
|
code: AttestationErrorCode.PREMATURELY_INDICATED_PAYLOAD_PRESENT,
|
|
316
316
|
});
|
|
317
317
|
}
|
|
318
|
+
|
|
319
|
+
// [REJECT] If `attestation.data.index == 1` (payload present for a past
|
|
320
|
+
// block), the execution payload for `block` passes validation.
|
|
321
|
+
// [IGNORE] When `attestation.data.index == 1` (payload present for a past block),
|
|
322
|
+
// the corresponding execution payload for `block` has been seen (a client MAY queue
|
|
323
|
+
// attestations for processing once the payload is retrieved and SHOULD request the
|
|
324
|
+
// payload envelope via `ExecutionPayloadEnvelopesByRoot`).
|
|
325
|
+
if (block !== null && attData.index === 1 && !chain.seenPayloadEnvelope(toRootHex(attData.beaconBlockRoot))) {
|
|
326
|
+
throw new AttestationError(GossipAction.IGNORE, {
|
|
327
|
+
code: AttestationErrorCode.EXECUTION_PAYLOAD_NOT_SEEN,
|
|
328
|
+
beaconBlockRoot: toRootHex(attData.beaconBlockRoot),
|
|
329
|
+
});
|
|
330
|
+
}
|
|
318
331
|
} else {
|
|
319
332
|
// [REJECT] attestation.data.index == 0
|
|
320
333
|
if (attData.index !== 0) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {PublicKey} from "@chainsafe/blst";
|
|
2
2
|
import {
|
|
3
|
+
computeEpochAtSlot,
|
|
3
4
|
createSingleSignatureSetFromComponents,
|
|
4
5
|
getExecutionPayloadBidSigningRoot,
|
|
5
6
|
isActiveBuilder,
|
|
@@ -76,6 +77,19 @@ async function validateExecutionPayloadBid(
|
|
|
76
77
|
// `SignedProposerPreferences` associated with `bid.slot`.
|
|
77
78
|
// TODO GLOAS: Implement this along with proposer preference
|
|
78
79
|
|
|
80
|
+
// [REJECT] The length of KZG commitments is less than or equal to the limitation defined in the
|
|
81
|
+
// consensus layer -- i.e. validate that
|
|
82
|
+
// `len(bid.blob_kzg_commitments) <= get_blob_parameters(compute_epoch_at_slot(bid.slot)).max_blobs_per_block`.
|
|
83
|
+
const blobKzgCommitmentsLen = bid.blobKzgCommitments.length;
|
|
84
|
+
const maxBlobsPerBlock = chain.config.getMaxBlobsPerBlock(computeEpochAtSlot(bid.slot));
|
|
85
|
+
if (blobKzgCommitmentsLen > maxBlobsPerBlock) {
|
|
86
|
+
throw new ExecutionPayloadBidError(GossipAction.REJECT, {
|
|
87
|
+
code: ExecutionPayloadBidErrorCode.TOO_MANY_KZG_COMMITMENTS,
|
|
88
|
+
blobKzgCommitmentsLen,
|
|
89
|
+
commitmentLimit: maxBlobsPerBlock,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
79
93
|
// [IGNORE] this is the first signed bid seen with a valid signature from the given builder for this slot.
|
|
80
94
|
if (chain.seenExecutionPayloadBids.isKnown(bid.slot, bid.builderIndex)) {
|
|
81
95
|
throw new ExecutionPayloadBidError(GossipAction.IGNORE, {
|
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
getExecutionPayloadEnvelopeSignatureSet,
|
|
5
5
|
isStatePostGloas,
|
|
6
6
|
} from "@lodestar/state-transition";
|
|
7
|
-
import {gloas} from "@lodestar/types";
|
|
8
|
-
import {toRootHex} from "@lodestar/utils";
|
|
7
|
+
import {gloas, ssz} from "@lodestar/types";
|
|
8
|
+
import {byteArrayEquals, toRootHex} from "@lodestar/utils";
|
|
9
9
|
import {ExecutionPayloadEnvelopeError, ExecutionPayloadEnvelopeErrorCode, GossipAction} from "../errors/index.js";
|
|
10
10
|
import {IBeaconChain} from "../index.js";
|
|
11
11
|
import {RegenCaller} from "../regen/index.js";
|
|
@@ -32,7 +32,7 @@ async function validateExecutionPayloadEnvelope(
|
|
|
32
32
|
const {payload} = envelope;
|
|
33
33
|
const blockRootHex = toRootHex(envelope.beaconBlockRoot);
|
|
34
34
|
|
|
35
|
-
// [IGNORE] The envelope's block root `envelope.
|
|
35
|
+
// [IGNORE] The envelope's block root `envelope.beacon_block_root` has been seen (via
|
|
36
36
|
// gossip or non-gossip sources) (a client MAY queue payload for processing once
|
|
37
37
|
// the block is retrieved).
|
|
38
38
|
// TODO GLOAS: Need to review this, we should queue the envelope for later
|
|
@@ -53,7 +53,7 @@ async function validateExecutionPayloadEnvelope(
|
|
|
53
53
|
throw new ExecutionPayloadEnvelopeError(GossipAction.IGNORE, {
|
|
54
54
|
code: ExecutionPayloadEnvelopeErrorCode.ENVELOPE_ALREADY_KNOWN,
|
|
55
55
|
blockRoot: blockRootHex,
|
|
56
|
-
slot:
|
|
56
|
+
slot: payload.slotNumber,
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -65,13 +65,13 @@ async function validateExecutionPayloadEnvelope(
|
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
// [IGNORE] The envelope is from a slot greater than or equal to the latest finalized slot -- i.e. validate that `
|
|
68
|
+
// [IGNORE] The envelope is from a slot greater than or equal to the latest finalized slot -- i.e. validate that `payload.slotNumber >= compute_start_slot_at_epoch(store.finalized_checkpoint.epoch)`
|
|
69
69
|
const finalizedCheckpoint = chain.forkChoice.getFinalizedCheckpoint();
|
|
70
70
|
const finalizedSlot = computeStartSlotAtEpoch(finalizedCheckpoint.epoch);
|
|
71
|
-
if (
|
|
71
|
+
if (payload.slotNumber < finalizedSlot) {
|
|
72
72
|
throw new ExecutionPayloadEnvelopeError(GossipAction.IGNORE, {
|
|
73
73
|
code: ExecutionPayloadEnvelopeErrorCode.BELONG_TO_FINALIZED_BLOCK,
|
|
74
|
-
envelopeSlot:
|
|
74
|
+
envelopeSlot: payload.slotNumber,
|
|
75
75
|
finalizedSlot,
|
|
76
76
|
});
|
|
77
77
|
}
|
|
@@ -80,11 +80,11 @@ async function validateExecutionPayloadEnvelope(
|
|
|
80
80
|
// TODO GLOAS: implement this. Technically if we cannot get proto block from fork choice,
|
|
81
81
|
// it is possible that the block didn't pass the validation
|
|
82
82
|
|
|
83
|
-
// [REJECT] `block.slot` equals `
|
|
84
|
-
if (block.slot !==
|
|
83
|
+
// [REJECT] `block.slot` equals `payload.slotNumber`.
|
|
84
|
+
if (block.slot !== payload.slotNumber) {
|
|
85
85
|
throw new ExecutionPayloadEnvelopeError(GossipAction.REJECT, {
|
|
86
86
|
code: ExecutionPayloadEnvelopeErrorCode.SLOT_MISMATCH,
|
|
87
|
-
envelopeSlot:
|
|
87
|
+
envelopeSlot: payload.slotNumber,
|
|
88
88
|
blockSlot: block.slot,
|
|
89
89
|
});
|
|
90
90
|
}
|
|
@@ -107,14 +107,24 @@ async function validateExecutionPayloadEnvelope(
|
|
|
107
107
|
});
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
//
|
|
110
|
+
// [REJECT] `hash_tree_root(envelope.execution_requests) == bid.execution_requests_root`
|
|
111
|
+
const requestsRoot = ssz.electra.ExecutionRequests.hashTreeRoot(envelope.executionRequests);
|
|
112
|
+
if (!byteArrayEquals(requestsRoot, payloadInput.getBid().executionRequestsRoot)) {
|
|
113
|
+
throw new ExecutionPayloadEnvelopeError(GossipAction.REJECT, {
|
|
114
|
+
code: ExecutionPayloadEnvelopeErrorCode.EXECUTION_REQUESTS_ROOT_MISMATCH,
|
|
115
|
+
envelopeRequestsRoot: toRootHex(requestsRoot),
|
|
116
|
+
bidRequestsRoot: toRootHex(payloadInput.getBid().executionRequestsRoot),
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Get the block state to verify the builder's signature.
|
|
111
121
|
const blockState = await chain.regen
|
|
112
122
|
.getState(block.stateRoot, RegenCaller.validateGossipPayloadEnvelope)
|
|
113
123
|
.catch(() => {
|
|
114
124
|
throw new ExecutionPayloadEnvelopeError(GossipAction.IGNORE, {
|
|
115
125
|
code: ExecutionPayloadEnvelopeErrorCode.UNKNOWN_BLOCK_STATE,
|
|
116
126
|
blockRoot: blockRootHex,
|
|
117
|
-
slot:
|
|
127
|
+
slot: payload.slotNumber,
|
|
118
128
|
});
|
|
119
129
|
});
|
|
120
130
|
if (!isStatePostGloas(blockState)) {
|
|
@@ -18,7 +18,8 @@ export async function validateApiPayloadAttestationMessage(
|
|
|
18
18
|
chain: IBeaconChain,
|
|
19
19
|
payloadAttestationMessage: gloas.PayloadAttestationMessage
|
|
20
20
|
): Promise<PayloadAttestationValidationResult> {
|
|
21
|
-
|
|
21
|
+
const prioritizeBls = true;
|
|
22
|
+
return validatePayloadAttestationMessage(chain, payloadAttestationMessage, prioritizeBls);
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export async function validateGossipPayloadAttestationMessage(
|
|
@@ -30,7 +31,8 @@ export async function validateGossipPayloadAttestationMessage(
|
|
|
30
31
|
|
|
31
32
|
async function validatePayloadAttestationMessage(
|
|
32
33
|
chain: IBeaconChain,
|
|
33
|
-
payloadAttestationMessage: gloas.PayloadAttestationMessage
|
|
34
|
+
payloadAttestationMessage: gloas.PayloadAttestationMessage,
|
|
35
|
+
prioritizeBls = false
|
|
34
36
|
): Promise<PayloadAttestationValidationResult> {
|
|
35
37
|
const {data, validatorIndex} = payloadAttestationMessage;
|
|
36
38
|
const epoch = computeEpochAtSlot(data.slot);
|
|
@@ -102,7 +104,7 @@ async function validatePayloadAttestationMessage(
|
|
|
102
104
|
payloadAttestationMessage.signature
|
|
103
105
|
);
|
|
104
106
|
|
|
105
|
-
if (!(await chain.bls.verifySignatureSets([signatureSet]))) {
|
|
107
|
+
if (!(await chain.bls.verifySignatureSets([signatureSet], {batchable: true, priority: prioritizeBls}))) {
|
|
106
108
|
throw new PayloadAttestationError(GossipAction.REJECT, {
|
|
107
109
|
code: PayloadAttestationErrorCode.INVALID_SIGNATURE,
|
|
108
110
|
});
|
|
@@ -19,7 +19,7 @@ export class ExecutionPayloadEnvelopeArchiveRepository extends Repository<Slot,
|
|
|
19
19
|
* Id is the slot from the envelope
|
|
20
20
|
*/
|
|
21
21
|
getId(value: gloas.SignedExecutionPayloadEnvelope): Slot {
|
|
22
|
-
return value.message.
|
|
22
|
+
return value.message.payload.slotNumber;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
encodeKey(id: Slot): Uint8Array {
|
|
@@ -216,13 +216,15 @@ export class ExecutionEngineHttp implements IExecutionEngine {
|
|
|
216
216
|
executionRequests?: ExecutionRequests
|
|
217
217
|
): Promise<ExecutePayloadResponse> {
|
|
218
218
|
const method =
|
|
219
|
-
ForkSeq[fork] >= ForkSeq.
|
|
220
|
-
? "
|
|
221
|
-
: ForkSeq[fork] >= ForkSeq.
|
|
222
|
-
? "
|
|
223
|
-
: ForkSeq[fork] >= ForkSeq.
|
|
224
|
-
? "
|
|
225
|
-
:
|
|
219
|
+
ForkSeq[fork] >= ForkSeq.gloas
|
|
220
|
+
? "engine_newPayloadV5"
|
|
221
|
+
: ForkSeq[fork] >= ForkSeq.electra
|
|
222
|
+
? "engine_newPayloadV4"
|
|
223
|
+
: ForkSeq[fork] >= ForkSeq.deneb
|
|
224
|
+
? "engine_newPayloadV3"
|
|
225
|
+
: ForkSeq[fork] >= ForkSeq.capella
|
|
226
|
+
? "engine_newPayloadV2"
|
|
227
|
+
: "engine_newPayloadV1";
|
|
226
228
|
|
|
227
229
|
const serializedExecutionPayload = serializeExecutionPayload(fork, executionPayload);
|
|
228
230
|
|
|
@@ -244,7 +246,7 @@ export class ExecutionEngineHttp implements IExecutionEngine {
|
|
|
244
246
|
}
|
|
245
247
|
const serializedExecutionRequests = serializeExecutionRequests(executionRequests);
|
|
246
248
|
engineRequest = {
|
|
247
|
-
method: "engine_newPayloadV4",
|
|
249
|
+
method: ForkSeq[fork] >= ForkSeq.gloas ? "engine_newPayloadV5" : "engine_newPayloadV4",
|
|
248
250
|
params: [
|
|
249
251
|
serializedExecutionPayload,
|
|
250
252
|
serializedVersionedHashes,
|
|
@@ -348,11 +350,13 @@ export class ExecutionEngineHttp implements IExecutionEngine {
|
|
|
348
350
|
// Once on capella, should this need to be permanently switched to v2 when payload attrs
|
|
349
351
|
// not provided
|
|
350
352
|
const method =
|
|
351
|
-
ForkSeq[fork] >= ForkSeq.
|
|
352
|
-
? "
|
|
353
|
-
: ForkSeq[fork] >= ForkSeq.
|
|
354
|
-
? "
|
|
355
|
-
:
|
|
353
|
+
ForkSeq[fork] >= ForkSeq.gloas
|
|
354
|
+
? "engine_forkchoiceUpdatedV4"
|
|
355
|
+
: ForkSeq[fork] >= ForkSeq.deneb
|
|
356
|
+
? "engine_forkchoiceUpdatedV3"
|
|
357
|
+
: ForkSeq[fork] >= ForkSeq.capella
|
|
358
|
+
? "engine_forkchoiceUpdatedV2"
|
|
359
|
+
: "engine_forkchoiceUpdatedV1";
|
|
356
360
|
const payloadAttributesRpc = payloadAttributes ? serializePayloadAttributes(payloadAttributes) : undefined;
|
|
357
361
|
// If we are just fcUing and not asking execution for payload, retry is not required
|
|
358
362
|
// and we can move on, as the next fcU will be issued soon on the new slot
|
|
@@ -438,9 +442,12 @@ export class ExecutionEngineHttp implements IExecutionEngine {
|
|
|
438
442
|
case ForkName.electra:
|
|
439
443
|
method = "engine_getPayloadV4";
|
|
440
444
|
break;
|
|
441
|
-
|
|
445
|
+
case ForkName.fulu:
|
|
442
446
|
method = "engine_getPayloadV5";
|
|
443
447
|
break;
|
|
448
|
+
default:
|
|
449
|
+
method = "engine_getPayloadV6";
|
|
450
|
+
break;
|
|
444
451
|
}
|
|
445
452
|
const payloadResponse = await this.rpc.fetchWithRetries<
|
|
446
453
|
EngineApiRpcReturnTypes[typeof method],
|