@lodestar/beacon-node 1.43.0-dev.e341cdc614 → 1.43.0-dev.f758dd5f38
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 +0 -4
- package/lib/api/impl/validator/index.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.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/importExecutionPayload.d.ts +14 -13
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +59 -83
- 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 +0 -1
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +14 -20
- 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/writePayloadEnvelopeInputToDb.d.ts +1 -1
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts.map +1 -1
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js +2 -11
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js.map +1 -1
- package/lib/chain/chain.d.ts +5 -4
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +9 -2
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +3 -3
- package/lib/chain/emitter.d.ts.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 -19
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +4 -3
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +46 -16
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +4 -2
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +48 -23
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +11 -4
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +20 -18
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +4 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.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 +19 -9
- 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.js +3 -3
- 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/node/notifier.js +7 -1
- package/lib/node/notifier.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 +17 -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 +0 -4
- package/src/chain/archiveStore/archiveStore.ts +5 -5
- package/src/chain/archiveStore/interface.ts +4 -4
- package/src/chain/archiveStore/strategies/frequencyStateArchiveStrategy.ts +4 -4
- package/src/chain/archiveStore/utils/archiveBlocks.ts +153 -94
- package/src/chain/blocks/importExecutionPayload.ts +73 -103
- package/src/chain/blocks/index.ts +0 -1
- package/src/chain/blocks/types.ts +14 -25
- package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +129 -0
- package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +9 -18
- package/src/chain/chain.ts +22 -16
- package/src/chain/emitter.ts +3 -3
- package/src/chain/errors/executionPayloadBid.ts +6 -0
- package/src/chain/errors/executionPayloadEnvelope.ts +6 -0
- package/src/chain/forkChoice/index.ts +8 -24
- package/src/chain/interface.ts +4 -2
- package/src/chain/prepareNextSlot.ts +60 -17
- package/src/chain/produceBlock/produceBlockBody.ts +66 -20
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +22 -20
- package/src/chain/stateCache/persistentCheckpointsCache.ts +4 -1
- package/src/chain/validation/executionPayloadBid.ts +14 -0
- package/src/chain/validation/executionPayloadEnvelope.ts +20 -10
- 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 +3 -3
- package/src/node/nodejs.ts +4 -2
- package/src/node/notifier.ts +8 -1
- package/src/util/sszBytes.ts +21 -3
|
@@ -7,6 +7,7 @@ export enum ExecutionPayloadBidErrorCode {
|
|
|
7
7
|
BID_ALREADY_KNOWN = "EXECUTION_PAYLOAD_BID_ERROR_BID_ALREADY_KNOWN",
|
|
8
8
|
BID_TOO_LOW = "EXECUTION_PAYLOAD_BID_ERROR_BID_TOO_LOW",
|
|
9
9
|
BID_TOO_HIGH = "EXECUTION_PAYLOAD_BID_ERROR_BID_TOO_HIGH",
|
|
10
|
+
TOO_MANY_KZG_COMMITMENTS = "EXECUTION_PAYLOAD_BID_ERROR_TOO_MANY_KZG_COMMITMENTS",
|
|
10
11
|
UNKNOWN_BLOCK_ROOT = "EXECUTION_PAYLOAD_BID_ERROR_UNKNOWN_BLOCK_ROOT",
|
|
11
12
|
INVALID_SLOT = "EXECUTION_PAYLOAD_BID_ERROR_INVALID_SLOT",
|
|
12
13
|
INVALID_SIGNATURE = "EXECUTION_PAYLOAD_BID_ERROR_INVALID_SIGNATURE",
|
|
@@ -28,6 +29,11 @@ export type ExecutionPayloadBidErrorType =
|
|
|
28
29
|
}
|
|
29
30
|
| {code: ExecutionPayloadBidErrorCode.BID_TOO_LOW; bidValue: number; currentHighestBid: number}
|
|
30
31
|
| {code: ExecutionPayloadBidErrorCode.BID_TOO_HIGH; bidValue: number; builderBalance: number}
|
|
32
|
+
| {
|
|
33
|
+
code: ExecutionPayloadBidErrorCode.TOO_MANY_KZG_COMMITMENTS;
|
|
34
|
+
blobKzgCommitmentsLen: number;
|
|
35
|
+
commitmentLimit: number;
|
|
36
|
+
}
|
|
31
37
|
| {code: ExecutionPayloadBidErrorCode.UNKNOWN_BLOCK_ROOT; parentBlockRoot: RootHex}
|
|
32
38
|
| {code: ExecutionPayloadBidErrorCode.INVALID_SLOT; builderIndex: BuilderIndex; slot: Slot}
|
|
33
39
|
| {code: ExecutionPayloadBidErrorCode.INVALID_SIGNATURE; builderIndex: BuilderIndex; slot: Slot};
|
|
@@ -11,6 +11,7 @@ export enum ExecutionPayloadEnvelopeErrorCode {
|
|
|
11
11
|
SLOT_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_SLOT_MISMATCH",
|
|
12
12
|
BUILDER_INDEX_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_BUILDER_INDEX_MISMATCH",
|
|
13
13
|
BLOCK_HASH_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_BLOCK_HASH_MISMATCH",
|
|
14
|
+
EXECUTION_REQUESTS_ROOT_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_EXECUTION_REQUESTS_ROOT_MISMATCH",
|
|
14
15
|
INVALID_SIGNATURE = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_INVALID_SIGNATURE",
|
|
15
16
|
PAYLOAD_ENVELOPE_INPUT_MISSING = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_PAYLOAD_ENVELOPE_INPUT_MISSING",
|
|
16
17
|
}
|
|
@@ -36,6 +37,11 @@ export type ExecutionPayloadEnvelopeErrorType =
|
|
|
36
37
|
envelopeBlockHash: RootHex;
|
|
37
38
|
bidBlockHash: RootHex | null;
|
|
38
39
|
}
|
|
40
|
+
| {
|
|
41
|
+
code: ExecutionPayloadEnvelopeErrorCode.EXECUTION_REQUESTS_ROOT_MISMATCH;
|
|
42
|
+
envelopeRequestsRoot: RootHex;
|
|
43
|
+
bidRequestsRoot: RootHex;
|
|
44
|
+
}
|
|
39
45
|
| {code: ExecutionPayloadEnvelopeErrorCode.INVALID_SIGNATURE}
|
|
40
46
|
| {code: ExecutionPayloadEnvelopeErrorCode.PAYLOAD_ENVELOPE_INPUT_MISSING; blockRoot: RootHex};
|
|
41
47
|
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
ProtoArray,
|
|
9
9
|
ProtoBlock,
|
|
10
10
|
ForkChoiceOpts as RawForkChoiceOpts,
|
|
11
|
-
getCheckpointPayloadStatus,
|
|
12
11
|
} from "@lodestar/fork-choice";
|
|
13
12
|
import {ZERO_HASH_HEX} from "@lodestar/params";
|
|
14
13
|
import {
|
|
@@ -104,16 +103,6 @@ export function initializeForkChoiceFromFinalizedState(
|
|
|
104
103
|
|
|
105
104
|
const isForkPostGloas = computeEpochAtSlot(state.slot) >= config.GLOAS_FORK_EPOCH;
|
|
106
105
|
|
|
107
|
-
// Determine justified checkpoint payload status
|
|
108
|
-
const justifiedPayloadStatus = isForkPostGloas
|
|
109
|
-
? PayloadStatus.PENDING
|
|
110
|
-
: getCheckpointPayloadStatus(config, state, justifiedCheckpoint.epoch);
|
|
111
|
-
|
|
112
|
-
// Determine finalized checkpoint payload status
|
|
113
|
-
const finalizedPayloadStatus = isForkPostGloas
|
|
114
|
-
? PayloadStatus.PENDING
|
|
115
|
-
: getCheckpointPayloadStatus(config, state, finalizedCheckpoint.epoch);
|
|
116
|
-
|
|
117
106
|
return new forkchoiceConstructor(
|
|
118
107
|
config,
|
|
119
108
|
|
|
@@ -123,8 +112,6 @@ export function initializeForkChoiceFromFinalizedState(
|
|
|
123
112
|
finalizedCheckpoint,
|
|
124
113
|
justifiedBalances,
|
|
125
114
|
justifiedBalancesGetter,
|
|
126
|
-
justifiedPayloadStatus,
|
|
127
|
-
finalizedPayloadStatus,
|
|
128
115
|
{
|
|
129
116
|
onJustified: (cp) => emitter.emit(ChainEvent.forkChoiceJustified, cp),
|
|
130
117
|
onFinalized: (cp) => emitter.emit(ChainEvent.forkChoiceFinalized, cp),
|
|
@@ -150,7 +137,9 @@ export function initializeForkChoiceFromFinalizedState(
|
|
|
150
137
|
|
|
151
138
|
...(isStatePostBellatrix(state) && state.isExecutionStateType && state.isMergeTransitionComplete
|
|
152
139
|
? {
|
|
153
|
-
executionPayloadBlockHash:
|
|
140
|
+
executionPayloadBlockHash: isStatePostGloas(state)
|
|
141
|
+
? toRootHex(state.latestBlockHash)
|
|
142
|
+
: toRootHex(state.latestExecutionPayloadHeader.blockHash),
|
|
154
143
|
// TODO GLOAS: executionPayloadNumber is not tracked in BeaconState post-gloas (EIP-7732 removed
|
|
155
144
|
// latestExecutionPayloadHeader). Using 0 as unavailable fallback until a solution is found.
|
|
156
145
|
executionPayloadNumber: isStatePostGloas(state) ? 0 : state.payloadBlockNumber,
|
|
@@ -159,7 +148,7 @@ export function initializeForkChoiceFromFinalizedState(
|
|
|
159
148
|
: {executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}),
|
|
160
149
|
|
|
161
150
|
dataAvailabilityStatus: DataAvailabilityStatus.PreData,
|
|
162
|
-
payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL,
|
|
151
|
+
payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL,
|
|
163
152
|
parentBlockHash: isStatePostGloas(state) ? toRootHex(state.latestBlockHash) : null,
|
|
164
153
|
},
|
|
165
154
|
currentSlot
|
|
@@ -206,19 +195,12 @@ export function initializeForkChoiceFromUnfinalizedState(
|
|
|
206
195
|
|
|
207
196
|
const isForkPostGloas = computeEpochAtSlot(unfinalizedState.slot) >= config.GLOAS_FORK_EPOCH;
|
|
208
197
|
|
|
209
|
-
// For unfinalized state, use getCheckpointPayloadStatus to determine the correct status.
|
|
210
|
-
// It checks state.execution_payload_availability to determine EMPTY vs FULL.
|
|
211
|
-
const justifiedPayloadStatus = getCheckpointPayloadStatus(config, unfinalizedState, justifiedCheckpoint.epoch);
|
|
212
|
-
const finalizedPayloadStatus = getCheckpointPayloadStatus(config, unfinalizedState, finalizedCheckpoint.epoch);
|
|
213
|
-
|
|
214
198
|
const store = new ForkChoiceStore(
|
|
215
199
|
currentSlot,
|
|
216
200
|
justifiedCheckpoint,
|
|
217
201
|
finalizedCheckpoint,
|
|
218
202
|
justifiedBalances,
|
|
219
203
|
justifiedBalancesGetter,
|
|
220
|
-
justifiedPayloadStatus,
|
|
221
|
-
finalizedPayloadStatus,
|
|
222
204
|
{
|
|
223
205
|
onJustified: (cp) => emitter.emit(ChainEvent.forkChoiceJustified, cp),
|
|
224
206
|
onFinalized: (cp) => emitter.emit(ChainEvent.forkChoiceFinalized, cp),
|
|
@@ -247,7 +229,9 @@ export function initializeForkChoiceFromUnfinalizedState(
|
|
|
247
229
|
unfinalizedState.isExecutionStateType &&
|
|
248
230
|
unfinalizedState.isMergeTransitionComplete
|
|
249
231
|
? {
|
|
250
|
-
executionPayloadBlockHash:
|
|
232
|
+
executionPayloadBlockHash: isStatePostGloas(unfinalizedState)
|
|
233
|
+
? toRootHex(unfinalizedState.latestBlockHash)
|
|
234
|
+
: toRootHex(unfinalizedState.latestExecutionPayloadHeader.blockHash),
|
|
251
235
|
// TODO GLOAS: executionPayloadNumber is not tracked in BeaconState post-gloas (EIP-7732 removed
|
|
252
236
|
// latestExecutionPayloadHeader). Using 0 as unavailable fallback until a solution is found.
|
|
253
237
|
executionPayloadNumber: isStatePostGloas(unfinalizedState) ? 0 : unfinalizedState.payloadBlockNumber,
|
|
@@ -256,7 +240,7 @@ export function initializeForkChoiceFromUnfinalizedState(
|
|
|
256
240
|
: {executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}),
|
|
257
241
|
|
|
258
242
|
dataAvailabilityStatus: DataAvailabilityStatus.PreData,
|
|
259
|
-
payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL,
|
|
243
|
+
payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL,
|
|
260
244
|
parentBlockHash: isStatePostGloas(unfinalizedState) ? toRootHex(unfinalizedState.latestBlockHash) : null,
|
|
261
245
|
};
|
|
262
246
|
|
package/src/chain/interface.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {Type} from "@chainsafe/ssz";
|
|
2
2
|
import {BeaconConfig} from "@lodestar/config";
|
|
3
|
-
import {CheckpointWithHex,
|
|
3
|
+
import {CheckpointWithHex, IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
|
|
4
4
|
import {EpochShuffling, IBeaconStateView, PubkeyCache} from "@lodestar/state-transition";
|
|
5
5
|
import {
|
|
6
6
|
BeaconBlock,
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
altair,
|
|
19
19
|
capella,
|
|
20
20
|
deneb,
|
|
21
|
+
electra,
|
|
21
22
|
gloas,
|
|
22
23
|
phase0,
|
|
23
24
|
rewards,
|
|
@@ -195,7 +196,7 @@ export interface IBeaconChain {
|
|
|
195
196
|
): {state: IBeaconStateView; executionOptimistic: boolean; finalized: boolean} | null;
|
|
196
197
|
/** Return state bytes by checkpoint */
|
|
197
198
|
getStateOrBytesByCheckpoint(
|
|
198
|
-
checkpoint:
|
|
199
|
+
checkpoint: CheckpointWithHex
|
|
199
200
|
): Promise<{state: IBeaconStateView | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null>;
|
|
200
201
|
|
|
201
202
|
/**
|
|
@@ -231,6 +232,7 @@ export interface IBeaconChain {
|
|
|
231
232
|
blockSlot: Slot,
|
|
232
233
|
blockRootHex: string
|
|
233
234
|
): Promise<gloas.SignedExecutionPayloadEnvelope | null>;
|
|
235
|
+
getParentExecutionRequests(parentBlockSlot: Slot, parentBlockRootHex: RootHex): Promise<electra.ExecutionRequests>;
|
|
234
236
|
|
|
235
237
|
produceCommonBlockBody(blockAttributes: BlockAttributes): Promise<CommonBlockBody>;
|
|
236
238
|
produceBlock(blockAttributes: BlockAttributes & {commonBlockBodyPromise: Promise<CommonBlockBody>}): Promise<{
|
|
@@ -8,8 +8,9 @@ import {
|
|
|
8
8
|
computeEpochAtSlot,
|
|
9
9
|
computeTimeAtSlot,
|
|
10
10
|
isStatePostBellatrix,
|
|
11
|
+
isStatePostGloas,
|
|
11
12
|
} from "@lodestar/state-transition";
|
|
12
|
-
import {Slot} from "@lodestar/types";
|
|
13
|
+
import {Bytes32, Slot, electra} from "@lodestar/types";
|
|
13
14
|
import {Logger, fromHex, isErrorAborted, sleep} from "@lodestar/utils";
|
|
14
15
|
import {GENESIS_SLOT, ZERO_HASH_HEX} from "../constants/constants.js";
|
|
15
16
|
import {BuilderStatus} from "../execution/builder/http.js";
|
|
@@ -81,6 +82,8 @@ export class PrepareNextSlotScheduler {
|
|
|
81
82
|
// calling updateHead() here before we produce a block to reduce reorg possibility
|
|
82
83
|
const headBlock = this.chain.recomputeForkChoiceHead(ForkchoiceCaller.prepareNextSlot);
|
|
83
84
|
const {slot: headSlot, blockRoot: headRoot} = headBlock;
|
|
85
|
+
// may be updated below if we predict a proposer-boost-reorg
|
|
86
|
+
let updatedHead = headBlock;
|
|
84
87
|
|
|
85
88
|
// PS: previously this was comparing slots, but that gave no leway on the skipped
|
|
86
89
|
// slots on epoch bounday. Making it more fluid.
|
|
@@ -123,7 +126,6 @@ export class PrepareNextSlotScheduler {
|
|
|
123
126
|
const proposerIndex = prepareState.getBeaconProposer(prepareSlot);
|
|
124
127
|
const feeRecipient = this.chain.beaconProposerCache.get(proposerIndex);
|
|
125
128
|
let updatedPrepareState = prepareState;
|
|
126
|
-
let updatedHeadRoot = headRoot;
|
|
127
129
|
|
|
128
130
|
if (feeRecipient) {
|
|
129
131
|
// If we are proposing next slot, we need to predict if we can proposer-boost-reorg or not
|
|
@@ -146,7 +148,7 @@ export class PrepareNextSlotScheduler {
|
|
|
146
148
|
{dontTransferCache: !isEpochTransition},
|
|
147
149
|
RegenCaller.predictProposerHead
|
|
148
150
|
);
|
|
149
|
-
|
|
151
|
+
updatedHead = proposerHead;
|
|
150
152
|
}
|
|
151
153
|
|
|
152
154
|
// Update the builder status, if enabled shoot an api call to check status
|
|
@@ -156,29 +158,56 @@ export class PrepareNextSlotScheduler {
|
|
|
156
158
|
this.logger.error("Builder disabled as the check status api failed", {prepareSlot}, e as Error);
|
|
157
159
|
});
|
|
158
160
|
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (!isStatePostBellatrix(updatedPrepareState)) {
|
|
164
|
+
throw new Error("Expected Bellatrix state for payload attributes");
|
|
165
|
+
}
|
|
159
166
|
|
|
167
|
+
let parentBlockHash: Bytes32;
|
|
168
|
+
let isExtendingPayload = false;
|
|
169
|
+
if (isStatePostGloas(updatedPrepareState)) {
|
|
170
|
+
isExtendingPayload = this.chain.forkChoice.shouldExtendPayload(updatedHead.blockRoot);
|
|
171
|
+
parentBlockHash = isExtendingPayload
|
|
172
|
+
? updatedPrepareState.latestExecutionPayloadBid.blockHash
|
|
173
|
+
: updatedPrepareState.latestExecutionPayloadBid.parentBlockHash;
|
|
174
|
+
} else {
|
|
175
|
+
parentBlockHash = updatedPrepareState.latestExecutionPayloadHeader.blockHash;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Reused by the SSE emit below to avoid a second DB lookup on cache miss
|
|
179
|
+
let parentExecutionRequests: electra.ExecutionRequests | undefined;
|
|
180
|
+
|
|
181
|
+
if (feeRecipient) {
|
|
160
182
|
const preparationTime =
|
|
161
183
|
computeTimeAtSlot(this.config, prepareSlot, this.chain.genesisTime) - Date.now() / 1000;
|
|
162
184
|
this.metrics?.blockPayload.payloadAdvancePrepTime.observe(preparationTime);
|
|
163
|
-
if (!isStatePostBellatrix(updatedPrepareState)) {
|
|
164
|
-
throw new Error("Expected Bellatrix state for payload preparation");
|
|
165
|
-
}
|
|
166
185
|
|
|
167
186
|
const safeBlockHash = getSafeExecutionBlockHash(this.chain.forkChoice);
|
|
168
187
|
const finalizedBlockHash =
|
|
169
188
|
this.chain.forkChoice.getFinalizedBlock().executionPayloadBlockHash ?? ZERO_HASH_HEX;
|
|
189
|
+
|
|
190
|
+
if (isExtendingPayload) {
|
|
191
|
+
parentExecutionRequests = await this.chain.getParentExecutionRequests(
|
|
192
|
+
updatedHead.slot,
|
|
193
|
+
updatedHead.blockRoot
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
170
197
|
// awaiting here instead of throwing an async call because there is no other task
|
|
171
|
-
// left for scheduler and this gives nice
|
|
198
|
+
// left for scheduler and this gives nice semantics to catch and log errors in the
|
|
172
199
|
// try/catch wrapper here.
|
|
173
200
|
await prepareExecutionPayload(
|
|
174
201
|
this.chain,
|
|
175
202
|
this.logger,
|
|
176
203
|
fork as ForkPostBellatrix, // State is of execution type
|
|
177
|
-
fromHex(
|
|
204
|
+
fromHex(updatedHead.blockRoot),
|
|
205
|
+
parentBlockHash,
|
|
178
206
|
safeBlockHash,
|
|
179
207
|
finalizedBlockHash,
|
|
180
208
|
updatedPrepareState,
|
|
181
|
-
feeRecipient
|
|
209
|
+
feeRecipient,
|
|
210
|
+
parentExecutionRequests
|
|
182
211
|
);
|
|
183
212
|
this.logger.verbose("PrepareNextSlotScheduler prepared new payload", {
|
|
184
213
|
prepareSlot,
|
|
@@ -187,24 +216,38 @@ export class PrepareNextSlotScheduler {
|
|
|
187
216
|
});
|
|
188
217
|
}
|
|
189
218
|
|
|
190
|
-
if (
|
|
191
|
-
|
|
219
|
+
if (ForkSeq[fork] >= ForkSeq.gloas) {
|
|
220
|
+
// Cutoff = slot of the parent of the block we'll actually build on (post-reorg).
|
|
221
|
+
// Steady state: cache holds just 2 entries — head (parent for next-slot production)
|
|
222
|
+
// and head.parent (proposer-boost-reorg fallback). Anything older is evicted.
|
|
223
|
+
const updatedHeadParent = this.chain.forkChoice.getBlockHexDefaultStatus(updatedHead.parentRoot);
|
|
224
|
+
if (updatedHeadParent) {
|
|
225
|
+
this.chain.seenPayloadEnvelopeInputCache.pruneBelow(updatedHeadParent.slot);
|
|
226
|
+
}
|
|
192
227
|
}
|
|
193
228
|
|
|
194
229
|
this.computeStateHashTreeRoot(updatedPrepareState, isEpochTransition);
|
|
195
230
|
|
|
196
|
-
// If emitPayloadAttributes is true emit a SSE payloadAttributes event
|
|
231
|
+
// If emitPayloadAttributes is true emit a SSE payloadAttributes event for
|
|
232
|
+
// every slot. Without the flag, only emit the event if we are proposing in the next slot.
|
|
197
233
|
if (
|
|
198
|
-
this.chain.opts.emitPayloadAttributes === true &&
|
|
234
|
+
(feeRecipient || this.chain.opts.emitPayloadAttributes === true) &&
|
|
199
235
|
this.chain.emitter.listenerCount(routes.events.EventType.payloadAttributes)
|
|
200
236
|
) {
|
|
237
|
+
// if we didn't fetch above (not proposing), SSE still needs it here
|
|
238
|
+
if (!parentExecutionRequests && isExtendingPayload) {
|
|
239
|
+
parentExecutionRequests = await this.chain.getParentExecutionRequests(
|
|
240
|
+
updatedHead.slot,
|
|
241
|
+
updatedHead.blockRoot
|
|
242
|
+
);
|
|
243
|
+
}
|
|
201
244
|
const data = getPayloadAttributesForSSE(fork as ForkPostBellatrix, this.chain, {
|
|
202
245
|
prepareState: updatedPrepareState,
|
|
203
246
|
prepareSlot,
|
|
204
|
-
parentBlockRoot: fromHex(
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
247
|
+
parentBlockRoot: fromHex(updatedHead.blockRoot),
|
|
248
|
+
parentBlockHash,
|
|
249
|
+
feeRecipient: feeRecipient ?? "0x0000000000000000000000000000000000000000",
|
|
250
|
+
parentExecutionRequests,
|
|
208
251
|
});
|
|
209
252
|
this.chain.emitter.emit(routes.events.EventType.payloadAttributes, {data, version: fork});
|
|
210
253
|
}
|
|
@@ -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 {
|
|
@@ -214,15 +214,24 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
214
214
|
});
|
|
215
215
|
|
|
216
216
|
// Get execution payload from EL
|
|
217
|
+
const isExtendingPayload = this.forkChoice.shouldExtendPayload(toRootHex(parentBlockRoot));
|
|
218
|
+
const parentBlockHash = isExtendingPayload
|
|
219
|
+
? currentState.latestExecutionPayloadBid.blockHash
|
|
220
|
+
: currentState.latestExecutionPayloadBid.parentBlockHash;
|
|
221
|
+
const parentExecutionRequests = isExtendingPayload
|
|
222
|
+
? await this.getParentExecutionRequests(parentBlock.slot, parentBlock.blockRoot)
|
|
223
|
+
: ssz.electra.ExecutionRequests.defaultValue();
|
|
217
224
|
const prepareRes = await prepareExecutionPayload(
|
|
218
225
|
this,
|
|
219
226
|
this.logger,
|
|
220
227
|
fork,
|
|
221
228
|
parentBlockRoot,
|
|
229
|
+
parentBlockHash,
|
|
222
230
|
safeBlockHash,
|
|
223
231
|
finalizedBlockHash ?? ZERO_HASH_HEX,
|
|
224
232
|
currentState,
|
|
225
|
-
feeRecipient
|
|
233
|
+
feeRecipient,
|
|
234
|
+
parentExecutionRequests
|
|
226
235
|
);
|
|
227
236
|
|
|
228
237
|
const {prepType, payloadId} = prepareRes;
|
|
@@ -255,8 +264,8 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
255
264
|
|
|
256
265
|
// Create self-build execution payload bid
|
|
257
266
|
const bid: gloas.ExecutionPayloadBid = {
|
|
258
|
-
parentBlockHash
|
|
259
|
-
parentBlockRoot
|
|
267
|
+
parentBlockHash,
|
|
268
|
+
parentBlockRoot,
|
|
260
269
|
blockHash: executionPayload.blockHash,
|
|
261
270
|
prevRandao: currentState.getRandaoMix(currentState.epoch),
|
|
262
271
|
feeRecipient: executionPayload.feeRecipient,
|
|
@@ -266,6 +275,7 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
266
275
|
value: 0,
|
|
267
276
|
executionPayment: 0,
|
|
268
277
|
blobKzgCommitments: blobsBundle.commitments,
|
|
278
|
+
executionRequestsRoot: ssz.electra.ExecutionRequests.hashTreeRoot(executionRequests),
|
|
269
279
|
};
|
|
270
280
|
const signedBid: gloas.SignedExecutionPayloadBid = {
|
|
271
281
|
message: bid,
|
|
@@ -277,6 +287,7 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
277
287
|
gloasBody.signedExecutionPayloadBid = signedBid;
|
|
278
288
|
// TODO GLOAS: Get payload attestations from pool for previous slot
|
|
279
289
|
gloasBody.payloadAttestations = [];
|
|
290
|
+
gloasBody.parentExecutionRequests = parentExecutionRequests;
|
|
280
291
|
blockBody = gloasBody as AssembledBodyType<T>;
|
|
281
292
|
|
|
282
293
|
// Store execution payload data required to construct execution payload envelope later
|
|
@@ -334,6 +345,7 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
334
345
|
this.logger,
|
|
335
346
|
fork,
|
|
336
347
|
parentBlockRoot,
|
|
348
|
+
currentState.latestExecutionPayloadHeader.blockHash,
|
|
337
349
|
safeBlockHash,
|
|
338
350
|
finalizedBlockHash ?? ZERO_HASH_HEX,
|
|
339
351
|
currentState,
|
|
@@ -442,6 +454,7 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
442
454
|
this.logger,
|
|
443
455
|
fork,
|
|
444
456
|
parentBlockRoot,
|
|
457
|
+
currentState.latestExecutionPayloadHeader.blockHash,
|
|
445
458
|
safeBlockHash,
|
|
446
459
|
finalizedBlockHash ?? ZERO_HASH_HEX,
|
|
447
460
|
currentState,
|
|
@@ -607,17 +620,18 @@ export async function prepareExecutionPayload(
|
|
|
607
620
|
logger: Logger,
|
|
608
621
|
fork: ForkPostBellatrix,
|
|
609
622
|
parentBlockRoot: Root,
|
|
623
|
+
parentBlockHash: Bytes32,
|
|
610
624
|
safeBlockHash: RootHex,
|
|
611
625
|
finalizedBlockHash: RootHex,
|
|
612
626
|
state: IBeaconStateViewBellatrix,
|
|
613
|
-
suggestedFeeRecipient: string
|
|
627
|
+
suggestedFeeRecipient: string,
|
|
628
|
+
parentExecutionRequests?: electra.ExecutionRequests
|
|
614
629
|
): Promise<{prepType: PayloadPreparationType; payloadId: PayloadId}> {
|
|
615
|
-
const parentHash = state.latestBlockHash;
|
|
616
630
|
const timestamp = computeTimeAtSlot(chain.config, state.slot, state.genesisTime);
|
|
617
631
|
const prevRandao = state.getRandaoMix(state.epoch);
|
|
618
632
|
|
|
619
633
|
const payloadIdCached = chain.executionEngine.payloadIdCache.get({
|
|
620
|
-
headBlockHash: toRootHex(
|
|
634
|
+
headBlockHash: toRootHex(parentBlockHash),
|
|
621
635
|
finalizedBlockHash,
|
|
622
636
|
timestamp: numToQuantity(timestamp),
|
|
623
637
|
prevRandao: toHex(prevRandao),
|
|
@@ -646,12 +660,14 @@ export async function prepareExecutionPayload(
|
|
|
646
660
|
prepareState: state,
|
|
647
661
|
prepareSlot: state.slot,
|
|
648
662
|
parentBlockRoot,
|
|
663
|
+
parentBlockHash,
|
|
649
664
|
feeRecipient: suggestedFeeRecipient,
|
|
665
|
+
parentExecutionRequests,
|
|
650
666
|
});
|
|
651
667
|
|
|
652
668
|
payloadId = await chain.executionEngine.notifyForkchoiceUpdate(
|
|
653
669
|
fork,
|
|
654
|
-
toRootHex(
|
|
670
|
+
toRootHex(parentBlockHash),
|
|
655
671
|
safeBlockHash,
|
|
656
672
|
finalizedBlockHash,
|
|
657
673
|
attributes
|
|
@@ -703,20 +719,33 @@ export function getPayloadAttributesForSSE(
|
|
|
703
719
|
prepareState,
|
|
704
720
|
prepareSlot,
|
|
705
721
|
parentBlockRoot,
|
|
722
|
+
parentBlockHash,
|
|
706
723
|
feeRecipient,
|
|
707
|
-
|
|
724
|
+
parentExecutionRequests,
|
|
725
|
+
}: {
|
|
726
|
+
prepareState: IBeaconStateViewBellatrix;
|
|
727
|
+
prepareSlot: Slot;
|
|
728
|
+
parentBlockRoot: Root;
|
|
729
|
+
parentBlockHash: Bytes32;
|
|
730
|
+
feeRecipient: string;
|
|
731
|
+
parentExecutionRequests?: electra.ExecutionRequests;
|
|
732
|
+
}
|
|
708
733
|
): SSEPayloadAttributes {
|
|
709
|
-
const parentHash = prepareState.latestBlockHash;
|
|
710
734
|
const payloadAttributes = preparePayloadAttributes(fork, chain, {
|
|
711
735
|
prepareState,
|
|
712
736
|
prepareSlot,
|
|
713
737
|
parentBlockRoot,
|
|
738
|
+
parentBlockHash,
|
|
714
739
|
feeRecipient,
|
|
740
|
+
parentExecutionRequests,
|
|
715
741
|
});
|
|
716
742
|
|
|
717
743
|
let parentBlockNumber: number;
|
|
718
744
|
if (isForkPostGloas(fork)) {
|
|
719
|
-
const parentBlock = chain.forkChoice.getBlockHexAndBlockHash(
|
|
745
|
+
const parentBlock = chain.forkChoice.getBlockHexAndBlockHash(
|
|
746
|
+
toRootHex(parentBlockRoot),
|
|
747
|
+
toRootHex(parentBlockHash)
|
|
748
|
+
);
|
|
720
749
|
if (parentBlock?.executionPayloadBlockHash == null) {
|
|
721
750
|
throw Error(`Parent block not found in fork choice root=${toRootHex(parentBlockRoot)}`);
|
|
722
751
|
}
|
|
@@ -730,7 +759,7 @@ export function getPayloadAttributesForSSE(
|
|
|
730
759
|
proposalSlot: prepareSlot,
|
|
731
760
|
parentBlockNumber,
|
|
732
761
|
parentBlockRoot,
|
|
733
|
-
parentBlockHash
|
|
762
|
+
parentBlockHash,
|
|
734
763
|
payloadAttributes,
|
|
735
764
|
};
|
|
736
765
|
return ssePayloadAttributes;
|
|
@@ -745,12 +774,16 @@ function preparePayloadAttributes(
|
|
|
745
774
|
prepareState,
|
|
746
775
|
prepareSlot,
|
|
747
776
|
parentBlockRoot,
|
|
777
|
+
parentBlockHash,
|
|
748
778
|
feeRecipient,
|
|
779
|
+
parentExecutionRequests,
|
|
749
780
|
}: {
|
|
750
781
|
prepareState: IBeaconStateViewBellatrix;
|
|
751
782
|
prepareSlot: Slot;
|
|
752
783
|
parentBlockRoot: Root;
|
|
784
|
+
parentBlockHash: Bytes32;
|
|
753
785
|
feeRecipient: string;
|
|
786
|
+
parentExecutionRequests?: electra.ExecutionRequests;
|
|
754
787
|
}
|
|
755
788
|
): SSEPayloadAttributes["payloadAttributes"] {
|
|
756
789
|
const timestamp = computeTimeAtSlot(chain.config, prepareSlot, prepareState.genesisTime);
|
|
@@ -766,13 +799,22 @@ function preparePayloadAttributes(
|
|
|
766
799
|
throw new Error("Expected Capella state for withdrawals");
|
|
767
800
|
}
|
|
768
801
|
|
|
769
|
-
if (isStatePostGloas(prepareState)
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
802
|
+
if (isStatePostGloas(prepareState)) {
|
|
803
|
+
const isExtendingPayload = byteArrayEquals(parentBlockHash, prepareState.latestExecutionPayloadBid.blockHash);
|
|
804
|
+
if (isExtendingPayload) {
|
|
805
|
+
if (parentExecutionRequests === undefined) {
|
|
806
|
+
throw new Error("parentExecutionRequests required when extending full parent");
|
|
807
|
+
}
|
|
808
|
+
(payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
|
|
809
|
+
prepareState.getExpectedWithdrawalsForFullParent(parentExecutionRequests);
|
|
810
|
+
} else {
|
|
811
|
+
// When the parent block is empty, state.payloadExpectedWithdrawals holds a batch
|
|
812
|
+
// already deducted from CL balances but never credited on the EL (the envelope
|
|
813
|
+
// was not delivered). The next payload must carry those same withdrawals to
|
|
814
|
+
// restore CL/EL consistency, otherwise validators permanently lose that balance.
|
|
815
|
+
(payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
|
|
816
|
+
prepareState.payloadExpectedWithdrawals;
|
|
817
|
+
}
|
|
776
818
|
} else {
|
|
777
819
|
// withdrawals logic is now fork aware as it changes on electra fork post capella
|
|
778
820
|
(payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
|
|
@@ -784,6 +826,10 @@ function preparePayloadAttributes(
|
|
|
784
826
|
(payloadAttributes as deneb.SSEPayloadAttributes["payloadAttributes"]).parentBeaconBlockRoot = parentBlockRoot;
|
|
785
827
|
}
|
|
786
828
|
|
|
829
|
+
if (ForkSeq[fork] >= ForkSeq.gloas) {
|
|
830
|
+
(payloadAttributes as gloas.SSEPayloadAttributes["payloadAttributes"]).slotNumber = prepareSlot;
|
|
831
|
+
}
|
|
832
|
+
|
|
787
833
|
return payloadAttributes;
|
|
788
834
|
}
|
|
789
835
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {CheckpointWithHex} from "@lodestar/fork-choice";
|
|
2
2
|
import {computeStartSlotAtEpoch} from "@lodestar/state-transition";
|
|
3
|
-
import {RootHex} from "@lodestar/types";
|
|
3
|
+
import {RootHex, Slot} from "@lodestar/types";
|
|
4
4
|
import {Logger} from "@lodestar/utils";
|
|
5
5
|
import {Metrics} from "../../metrics/metrics.js";
|
|
6
6
|
import {SerializedCache} from "../../util/serializedCache.js";
|
|
@@ -21,8 +21,15 @@ export type SeenPayloadEnvelopeInputModules = {
|
|
|
21
21
|
/**
|
|
22
22
|
* Cache for tracking PayloadEnvelopeInput instances, keyed by beacon block root.
|
|
23
23
|
*
|
|
24
|
-
* Created during block import when a block is processed.
|
|
25
|
-
*
|
|
24
|
+
* Created during block import when a block is processed. Two pruning paths:
|
|
25
|
+
* - `prepareNextSlot` calls `pruneBelow(headParentSlot)` every slot once the head we'll build
|
|
26
|
+
* on is known.
|
|
27
|
+
* - `onFinalized` calls `pruneBelow(finalizedSlot)` on every finalization for bulk cleanup.
|
|
28
|
+
*
|
|
29
|
+
* Steady state (linear chain, healthy progression): the cache holds ~2 entries — the head
|
|
30
|
+
* (parent for next-slot production) and its parent (proposer-boost-reorg fallback). It can
|
|
31
|
+
* transiently hold more during forks, range-sync bursts, or when `prepareNextSlot` skips
|
|
32
|
+
* ticks; subsequent ticks settle it back.
|
|
26
33
|
*/
|
|
27
34
|
export class SeenPayloadEnvelopeInput {
|
|
28
35
|
private readonly chainEvents: ChainEventEmitter;
|
|
@@ -58,16 +65,7 @@ export class SeenPayloadEnvelopeInput {
|
|
|
58
65
|
}
|
|
59
66
|
|
|
60
67
|
private onFinalized = (checkpoint: CheckpointWithHex): void => {
|
|
61
|
-
|
|
62
|
-
const finalizedSlot = computeStartSlotAtEpoch(checkpoint.epoch);
|
|
63
|
-
let deletedCount = 0;
|
|
64
|
-
for (const [, input] of this.payloadInputs) {
|
|
65
|
-
if (input.slot < finalizedSlot) {
|
|
66
|
-
this.evictPayloadInput(input);
|
|
67
|
-
deletedCount++;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
this.logger?.debug("SeenPayloadEnvelopeInput.onFinalized deleted cached entries", {deletedCount});
|
|
68
|
+
this.pruneBelow(computeStartSlotAtEpoch(checkpoint.epoch));
|
|
71
69
|
};
|
|
72
70
|
|
|
73
71
|
add(props: CreateFromBlockProps): PayloadEnvelopeInput {
|
|
@@ -88,17 +86,21 @@ export class SeenPayloadEnvelopeInput {
|
|
|
88
86
|
return this.payloadInputs.get(blockRootHex)?.hasPayloadEnvelope() ?? false;
|
|
89
87
|
}
|
|
90
88
|
|
|
91
|
-
prune(blockRootHex: RootHex): void {
|
|
92
|
-
const payloadInput = this.payloadInputs.get(blockRootHex);
|
|
93
|
-
if (payloadInput) {
|
|
94
|
-
this.evictPayloadInput(payloadInput);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
89
|
size(): number {
|
|
99
90
|
return this.payloadInputs.size;
|
|
100
91
|
}
|
|
101
92
|
|
|
93
|
+
pruneBelow(slot: Slot): void {
|
|
94
|
+
let deletedCount = 0;
|
|
95
|
+
for (const [, input] of this.payloadInputs) {
|
|
96
|
+
if (input.slot < slot) {
|
|
97
|
+
this.evictPayloadInput(input);
|
|
98
|
+
deletedCount++;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
this.logger?.debug("SeenPayloadEnvelopeInput.pruneBelow deleted entries", {slot, deletedCount});
|
|
102
|
+
}
|
|
103
|
+
|
|
102
104
|
private evictPayloadInput(payloadInput: PayloadEnvelopeInput): void {
|
|
103
105
|
this.serializedCache.delete(payloadInput.getSerializedCacheKeys());
|
|
104
106
|
this.payloadInputs.delete(payloadInput.blockRootHex);
|
|
@@ -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());
|
|
@@ -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, {
|