@lodestar/beacon-node 1.44.0-dev.6ef8199cfa → 1.44.0-dev.762dd5f186
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 +66 -33
- 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 +1 -26
- package/lib/api/impl/beacon/pool/index.js.map +1 -1
- package/lib/api/impl/config/constants.d.ts +5 -0
- package/lib/api/impl/config/constants.d.ts.map +1 -1
- package/lib/api/impl/config/constants.js +6 -1
- package/lib/api/impl/config/constants.js.map +1 -1
- package/lib/api/impl/debug/index.d.ts.map +1 -1
- package/lib/api/impl/debug/index.js +69 -12
- 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 +28 -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 +117 -72
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts +0 -1
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +0 -4
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +19 -4
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +5 -3
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +3 -3
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -1
- package/lib/chain/chain.d.ts +3 -3
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +11 -3
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +2 -1
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/emitter.js.map +1 -1
- package/lib/chain/errors/blockError.d.ts +0 -7
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js +0 -3
- package/lib/chain/errors/blockError.js.map +1 -1
- package/lib/chain/errors/executionPayloadBid.d.ts +23 -1
- package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadBid.js +4 -0
- package/lib/chain/errors/executionPayloadBid.js.map +1 -1
- package/lib/chain/errors/payloadAttestation.d.ts +6 -0
- package/lib/chain/errors/payloadAttestation.d.ts.map +1 -1
- package/lib/chain/errors/payloadAttestation.js +1 -0
- package/lib/chain/errors/payloadAttestation.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts +4 -4
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +24 -11
- 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/interface.js.map +1 -1
- package/lib/chain/opPools/executionPayloadBidPool.d.ts +4 -4
- package/lib/chain/opPools/executionPayloadBidPool.d.ts.map +1 -1
- package/lib/chain/opPools/executionPayloadBidPool.js +6 -4
- package/lib/chain/opPools/executionPayloadBidPool.js.map +1 -1
- package/lib/chain/options.d.ts.map +1 -1
- package/lib/chain/options.js +1 -0
- package/lib/chain/options.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +2 -10
- 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 +81 -27
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +2 -1
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/interface.js +2 -0
- package/lib/chain/regen/interface.js.map +1 -1
- package/lib/chain/regen/queued.d.ts +0 -1
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +0 -4
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +8 -2
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts +0 -5
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.js +0 -5
- package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +1 -4
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +5 -2
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/types.d.ts +0 -2
- package/lib/chain/stateCache/types.d.ts.map +1 -1
- package/lib/chain/stateCache/types.js.map +1 -1
- package/lib/chain/validation/block.d.ts +5 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +4 -14
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts +7 -3
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +81 -16
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +1 -3
- 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 +24 -4
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts +1 -0
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +16 -0
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/execution/builder/index.d.ts +1 -2
- package/lib/execution/builder/index.d.ts.map +1 -1
- package/lib/execution/builder/index.js +0 -1
- package/lib/execution/builder/index.js.map +1 -1
- package/lib/execution/engine/http.js +1 -1
- package/lib/execution/engine/http.js.map +1 -1
- package/lib/execution/engine/interface.d.ts +2 -2
- package/lib/execution/engine/interface.d.ts.map +1 -1
- package/lib/execution/engine/interface.js +6 -2
- package/lib/execution/engine/interface.js.map +1 -1
- package/lib/execution/engine/mock.d.ts.map +1 -1
- package/lib/execution/engine/mock.js +3 -5
- package/lib/execution/engine/mock.js.map +1 -1
- package/lib/execution/engine/types.d.ts +15 -7
- package/lib/execution/engine/types.d.ts.map +1 -1
- package/lib/execution/engine/types.js +47 -9
- package/lib/execution/engine/types.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +5 -1
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +14 -3
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +770 -3
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/interface.d.ts +1 -0
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/network.d.ts +1 -0
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +5 -0
- package/lib/network/network.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +21 -6
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/index.d.ts +2 -2
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +25 -23
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRange.js +9 -5
- package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +13 -3
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts +2 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +16 -6
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.d.ts +2 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js +15 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js.map +1 -1
- package/lib/network/reqresp/handlers/index.js +4 -4
- package/lib/network/reqresp/handlers/index.js.map +1 -1
- package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts.map +1 -1
- package/lib/network/reqresp/utils/dataColumnResponseValidation.js +23 -5
- package/lib/network/reqresp/utils/dataColumnResponseValidation.js.map +1 -1
- package/lib/sync/types.d.ts +9 -1
- package/lib/sync/types.d.ts.map +1 -1
- package/lib/sync/types.js +9 -2
- package/lib/sync/types.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +64 -30
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/util/dataColumns.d.ts.map +1 -1
- package/lib/util/dataColumns.js +16 -11
- package/lib/util/dataColumns.js.map +1 -1
- package/lib/util/sszBytes.js +1 -1
- package/package.json +15 -17
- package/src/api/impl/beacon/blocks/index.ts +76 -42
- package/src/api/impl/beacon/pool/index.ts +4 -42
- package/src/api/impl/config/constants.ts +10 -0
- package/src/api/impl/debug/index.ts +73 -12
- package/src/api/impl/lodestar/index.ts +30 -0
- package/src/api/impl/validator/index.ts +137 -86
- package/src/chain/archiveStore/archiveStore.ts +0 -5
- package/src/chain/blocks/importBlock.ts +29 -7
- package/src/chain/blocks/importExecutionPayload.ts +8 -2
- package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +3 -5
- package/src/chain/chain.ts +14 -4
- package/src/chain/emitter.ts +3 -2
- package/src/chain/errors/blockError.ts +0 -4
- package/src/chain/errors/executionPayloadBid.ts +20 -1
- package/src/chain/errors/payloadAttestation.ts +2 -0
- package/src/chain/forkChoice/index.ts +27 -4
- package/src/chain/interface.ts +1 -2
- package/src/chain/opPools/executionPayloadBidPool.ts +10 -9
- package/src/chain/options.ts +1 -0
- package/src/chain/prepareNextSlot.ts +2 -11
- package/src/chain/produceBlock/produceBlockBody.ts +114 -40
- package/src/chain/regen/interface.ts +2 -1
- package/src/chain/regen/queued.ts +0 -5
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +8 -3
- package/src/chain/stateCache/fifoBlockStateCache.ts +0 -6
- package/src/chain/stateCache/persistentCheckpointsCache.ts +6 -2
- package/src/chain/stateCache/types.ts +0 -2
- package/src/chain/validation/block.ts +12 -16
- package/src/chain/validation/executionPayloadBid.ts +90 -19
- package/src/chain/validation/executionPayloadEnvelope.ts +1 -3
- package/src/chain/validation/payloadAttestationMessage.ts +26 -4
- package/src/chain/validatorMonitor.ts +18 -0
- package/src/execution/builder/index.ts +1 -4
- package/src/execution/engine/http.ts +1 -1
- package/src/execution/engine/interface.ts +12 -2
- package/src/execution/engine/mock.ts +6 -5
- package/src/execution/engine/types.ts +75 -14
- package/src/metrics/metrics/lodestar.ts +15 -3
- package/src/network/interface.ts +1 -0
- package/src/network/network.ts +11 -0
- package/src/network/processor/gossipHandlers.ts +26 -6
- package/src/network/processor/index.ts +27 -27
- package/src/network/reqresp/handlers/beaconBlocksByRange.ts +12 -5
- package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +17 -3
- package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +1 -1
- package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +22 -6
- package/src/network/reqresp/handlers/executionPayloadEnvelopesByRoot.ts +20 -1
- package/src/network/reqresp/handlers/index.ts +4 -4
- package/src/network/reqresp/utils/dataColumnResponseValidation.ts +22 -5
- package/src/sync/types.ts +11 -2
- package/src/sync/unknownBlock.ts +70 -31
- package/src/util/dataColumns.ts +17 -12
- package/src/util/sszBytes.ts +1 -1
- package/lib/execution/builder/utils.d.ts +0 -5
- package/lib/execution/builder/utils.d.ts.map +0 -1
- package/lib/execution/builder/utils.js +0 -17
- package/lib/execution/builder/utils.js.map +0 -1
- package/src/execution/builder/utils.ts +0 -19
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import {routes} from "@lodestar/api";
|
|
1
2
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
3
|
import {
|
|
3
4
|
ExecutionStatus,
|
|
4
5
|
ForkChoice,
|
|
6
|
+
ForkChoiceStateGetter,
|
|
5
7
|
ForkChoiceStore,
|
|
6
8
|
JustifiedBalancesGetter,
|
|
7
9
|
PayloadStatus,
|
|
@@ -45,6 +47,7 @@ export function initializeForkChoice(
|
|
|
45
47
|
isFinalizedState: boolean,
|
|
46
48
|
opts: ForkChoiceOpts,
|
|
47
49
|
justifiedBalancesGetter: JustifiedBalancesGetter,
|
|
50
|
+
stateGetter: ForkChoiceStateGetter,
|
|
48
51
|
metrics: Metrics | null,
|
|
49
52
|
logger?: Logger
|
|
50
53
|
): ForkChoice {
|
|
@@ -56,6 +59,7 @@ export function initializeForkChoice(
|
|
|
56
59
|
state,
|
|
57
60
|
opts,
|
|
58
61
|
justifiedBalancesGetter,
|
|
62
|
+
stateGetter,
|
|
59
63
|
metrics,
|
|
60
64
|
logger
|
|
61
65
|
)
|
|
@@ -66,6 +70,7 @@ export function initializeForkChoice(
|
|
|
66
70
|
state,
|
|
67
71
|
opts,
|
|
68
72
|
justifiedBalancesGetter,
|
|
73
|
+
stateGetter,
|
|
69
74
|
metrics,
|
|
70
75
|
logger
|
|
71
76
|
);
|
|
@@ -81,6 +86,7 @@ export function initializeForkChoiceFromFinalizedState(
|
|
|
81
86
|
state: IBeaconStateView,
|
|
82
87
|
opts: ForkChoiceOpts,
|
|
83
88
|
justifiedBalancesGetter: JustifiedBalancesGetter,
|
|
89
|
+
stateGetter: ForkChoiceStateGetter,
|
|
84
90
|
metrics: Metrics | null,
|
|
85
91
|
logger?: Logger
|
|
86
92
|
): ForkChoice {
|
|
@@ -112,9 +118,12 @@ export function initializeForkChoiceFromFinalizedState(
|
|
|
112
118
|
finalizedCheckpoint,
|
|
113
119
|
justifiedBalances,
|
|
114
120
|
justifiedBalancesGetter,
|
|
121
|
+
stateGetter,
|
|
115
122
|
{
|
|
116
123
|
onJustified: (cp) => emitter.emit(ChainEvent.forkChoiceJustified, cp),
|
|
117
124
|
onFinalized: (cp) => emitter.emit(ChainEvent.forkChoiceFinalized, cp),
|
|
125
|
+
onFastConfirmation: ({block, slot, currentSlot}) =>
|
|
126
|
+
emitter.emit(routes.events.EventType.fastConfirmation, {block, slot, currentSlot}),
|
|
118
127
|
}
|
|
119
128
|
),
|
|
120
129
|
|
|
@@ -140,9 +149,11 @@ export function initializeForkChoiceFromFinalizedState(
|
|
|
140
149
|
executionPayloadBlockHash: isStatePostGloas(state)
|
|
141
150
|
? toRootHex(state.latestBlockHash)
|
|
142
151
|
: toRootHex(state.latestExecutionPayloadHeader.blockHash),
|
|
143
|
-
// TODO GLOAS: executionPayloadNumber
|
|
144
|
-
// latestExecutionPayloadHeader). Using 0 as unavailable fallback
|
|
152
|
+
// TODO GLOAS: executionPayloadNumber/GasLimit are not tracked in BeaconState post-gloas
|
|
153
|
+
// (EIP-7732 removed latestExecutionPayloadHeader). Using 0 as unavailable fallback —
|
|
154
|
+
// see initializeForkChoiceFromUnfinalizedState for the same caveat on validation.
|
|
145
155
|
executionPayloadNumber: isStatePostGloas(state) ? 0 : state.payloadBlockNumber,
|
|
156
|
+
executionPayloadGasLimit: isStatePostGloas(state) ? 0 : state.latestExecutionPayloadHeader.gasLimit,
|
|
146
157
|
executionStatus: blockHeader.slot === GENESIS_SLOT ? ExecutionStatus.Valid : ExecutionStatus.Syncing,
|
|
147
158
|
}
|
|
148
159
|
: {executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}),
|
|
@@ -170,6 +181,7 @@ export function initializeForkChoiceFromUnfinalizedState(
|
|
|
170
181
|
unfinalizedState: IBeaconStateView,
|
|
171
182
|
opts: ForkChoiceOpts,
|
|
172
183
|
justifiedBalancesGetter: JustifiedBalancesGetter,
|
|
184
|
+
stateGetter: ForkChoiceStateGetter,
|
|
173
185
|
metrics: Metrics | null,
|
|
174
186
|
logger?: Logger
|
|
175
187
|
): ForkChoice {
|
|
@@ -201,9 +213,12 @@ export function initializeForkChoiceFromUnfinalizedState(
|
|
|
201
213
|
finalizedCheckpoint,
|
|
202
214
|
justifiedBalances,
|
|
203
215
|
justifiedBalancesGetter,
|
|
216
|
+
stateGetter,
|
|
204
217
|
{
|
|
205
218
|
onJustified: (cp) => emitter.emit(ChainEvent.forkChoiceJustified, cp),
|
|
206
219
|
onFinalized: (cp) => emitter.emit(ChainEvent.forkChoiceFinalized, cp),
|
|
220
|
+
onFastConfirmation: ({block, slot, currentSlot}) =>
|
|
221
|
+
emitter.emit(routes.events.EventType.fastConfirmation, {block, slot, currentSlot}),
|
|
207
222
|
}
|
|
208
223
|
);
|
|
209
224
|
|
|
@@ -232,9 +247,17 @@ export function initializeForkChoiceFromUnfinalizedState(
|
|
|
232
247
|
executionPayloadBlockHash: isStatePostGloas(unfinalizedState)
|
|
233
248
|
? toRootHex(unfinalizedState.latestBlockHash)
|
|
234
249
|
: toRootHex(unfinalizedState.latestExecutionPayloadHeader.blockHash),
|
|
235
|
-
// TODO GLOAS: executionPayloadNumber
|
|
236
|
-
// latestExecutionPayloadHeader). Using 0 as unavailable fallback until
|
|
250
|
+
// TODO GLOAS: executionPayloadNumber/GasLimit are not tracked in BeaconState post-gloas
|
|
251
|
+
// (EIP-7732 removed latestExecutionPayloadHeader). Using 0 as unavailable fallback until
|
|
252
|
+
// a solution is found. The 0 doesn't gate validation in practice: at boot the head's
|
|
253
|
+
// PENDING variant's `executionPayloadBlockHash` is the *parent's* payload hash (per the
|
|
254
|
+
// PENDING/EMPTY convention), so gossip bids that reference the head's *own* payload
|
|
255
|
+
// hash won't match this variant anyway and will IGNORE until `onExecutionPayload`
|
|
256
|
+
// upgrades the head to FULL with real values.
|
|
237
257
|
executionPayloadNumber: isStatePostGloas(unfinalizedState) ? 0 : unfinalizedState.payloadBlockNumber,
|
|
258
|
+
executionPayloadGasLimit: isStatePostGloas(unfinalizedState)
|
|
259
|
+
? 0
|
|
260
|
+
: unfinalizedState.latestExecutionPayloadHeader.gasLimit,
|
|
238
261
|
executionStatus: blockHeader.slot === GENESIS_SLOT ? ExecutionStatus.Valid : ExecutionStatus.Syncing,
|
|
239
262
|
}
|
|
240
263
|
: {executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}),
|
package/src/chain/interface.ts
CHANGED
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
altair,
|
|
19
19
|
capella,
|
|
20
20
|
deneb,
|
|
21
|
-
electra,
|
|
22
21
|
gloas,
|
|
23
22
|
phase0,
|
|
24
23
|
rewards,
|
|
@@ -236,7 +235,7 @@ export interface IBeaconChain {
|
|
|
236
235
|
blockSlot: Slot,
|
|
237
236
|
blockRootHex: string
|
|
238
237
|
): Promise<gloas.SignedExecutionPayloadEnvelope | null>;
|
|
239
|
-
getParentExecutionRequests(parentBlockSlot: Slot, parentBlockRootHex: RootHex): Promise<
|
|
238
|
+
getParentExecutionRequests(parentBlockSlot: Slot, parentBlockRootHex: RootHex): Promise<gloas.ExecutionRequests>;
|
|
240
239
|
|
|
241
240
|
produceCommonBlockBody(blockAttributes: BlockAttributes): Promise<CommonBlockBody>;
|
|
242
241
|
produceBlock(blockAttributes: BlockAttributes & {commonBlockBodyPromise: Promise<CommonBlockBody>}): Promise<{
|
|
@@ -12,13 +12,13 @@ type BlockRootHex = string;
|
|
|
12
12
|
type BlockHashHex = string;
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* Store the best execution payload bid per slot / (parent block root, parent block hash).
|
|
15
|
+
* Store the best signed execution payload bid per slot / (parent block root, parent block hash).
|
|
16
16
|
*/
|
|
17
17
|
export class ExecutionPayloadBidPool {
|
|
18
18
|
private readonly bidByParentHashByParentRootBySlot = new MapDef<
|
|
19
19
|
Slot,
|
|
20
|
-
MapDef<BlockRootHex, Map<BlockHashHex, gloas.
|
|
21
|
-
>(() => new MapDef<BlockRootHex, Map<BlockHashHex, gloas.
|
|
20
|
+
MapDef<BlockRootHex, Map<BlockHashHex, gloas.SignedExecutionPayloadBid>>
|
|
21
|
+
>(() => new MapDef<BlockRootHex, Map<BlockHashHex, gloas.SignedExecutionPayloadBid>>(() => new Map()));
|
|
22
22
|
private lowestPermissibleSlot = 0;
|
|
23
23
|
|
|
24
24
|
get size(): number {
|
|
@@ -31,8 +31,8 @@ export class ExecutionPayloadBidPool {
|
|
|
31
31
|
return count;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
add(bid: gloas.
|
|
35
|
-
const {slot, parentBlockRoot, parentBlockHash, value} = bid;
|
|
34
|
+
add(bid: gloas.SignedExecutionPayloadBid): InsertOutcome {
|
|
35
|
+
const {slot, parentBlockRoot, parentBlockHash, value} = bid.message;
|
|
36
36
|
const lowestPermissibleSlot = this.lowestPermissibleSlot;
|
|
37
37
|
|
|
38
38
|
if (slot < lowestPermissibleSlot) {
|
|
@@ -45,7 +45,7 @@ export class ExecutionPayloadBidPool {
|
|
|
45
45
|
const existing = bidByParentHash.get(parentHashHex);
|
|
46
46
|
|
|
47
47
|
if (existing) {
|
|
48
|
-
const existingValue = existing.value;
|
|
48
|
+
const existingValue = existing.message.value;
|
|
49
49
|
const newValue = value;
|
|
50
50
|
if (newValue > existingValue) {
|
|
51
51
|
bidByParentHash.set(parentHashHex, bid);
|
|
@@ -59,14 +59,15 @@ export class ExecutionPayloadBidPool {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
/**
|
|
62
|
-
* Return the highest-value bid matching slot, parent block hash, and parent block root.
|
|
62
|
+
* Return the highest-value signed 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
|
-
parentBlockHash: BlockHashHex,
|
|
67
|
+
parentBlockHash: BlockHashHex | null,
|
|
68
68
|
parentBlockRoot: BlockRootHex
|
|
69
|
-
): gloas.
|
|
69
|
+
): gloas.SignedExecutionPayloadBid | null {
|
|
70
|
+
if (parentBlockHash === null) return null;
|
|
70
71
|
const bidByParentHash = this.bidByParentHashByParentRootBySlot.get(slot)?.get(parentBlockRoot);
|
|
71
72
|
return bidByParentHash?.get(parentBlockHash) ?? null;
|
|
72
73
|
}
|
package/src/chain/options.ts
CHANGED
|
@@ -105,6 +105,7 @@ export const defaultChainOptions: IChainOptions = {
|
|
|
105
105
|
proposerBoost: true,
|
|
106
106
|
proposerBoostReorg: true,
|
|
107
107
|
computeUnrealized: true,
|
|
108
|
+
fastConfirmation: false,
|
|
108
109
|
suggestedFeeRecipient: defaultValidatorOptions.suggestedFeeRecipient,
|
|
109
110
|
serveHistoricalState: false,
|
|
110
111
|
assertCorrectProgressiveBalances: false,
|
|
@@ -169,7 +169,8 @@ export class PrepareNextSlotScheduler {
|
|
|
169
169
|
// Apply parent payload once here as it's reused by EL prep and SSE emit below
|
|
170
170
|
let stateAfterParentPayload: IBeaconStateViewBellatrix = updatedPrepareState;
|
|
171
171
|
if (isStatePostGloas(updatedPrepareState)) {
|
|
172
|
-
|
|
172
|
+
// Spec: should_build_on_full(store, head) — see produceBlockBody.ts for context.
|
|
173
|
+
if (this.chain.forkChoice.shouldBuildOnFull(updatedHead, prepareSlot)) {
|
|
173
174
|
parentBlockHash = updatedPrepareState.latestExecutionPayloadBid.blockHash;
|
|
174
175
|
// Skip applying parent payload unless we're proposing the next slot or have to emit payload_attributes events
|
|
175
176
|
if (feeRecipient !== undefined || this.chain.opts.emitPayloadAttributes === true) {
|
|
@@ -216,16 +217,6 @@ export class PrepareNextSlotScheduler {
|
|
|
216
217
|
});
|
|
217
218
|
}
|
|
218
219
|
|
|
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.pruneBelowParent(updatedHeadParent);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
220
|
this.computeStateHashTreeRoot(updatedPrepareState, isEpochTransition);
|
|
230
221
|
|
|
231
222
|
// If emitPayloadAttributes is true emit a SSE payloadAttributes event for
|
|
@@ -18,9 +18,9 @@ import {
|
|
|
18
18
|
G2_POINT_AT_INFINITY,
|
|
19
19
|
IBeaconStateView,
|
|
20
20
|
type IBeaconStateViewBellatrix,
|
|
21
|
-
type IBeaconStateViewGloas,
|
|
22
21
|
computeEpochAtSlot,
|
|
23
22
|
computeTimeAtSlot,
|
|
23
|
+
getExpectedGasLimit,
|
|
24
24
|
isStatePostBellatrix,
|
|
25
25
|
isStatePostCapella,
|
|
26
26
|
isStatePostGloas,
|
|
@@ -50,16 +50,10 @@ import {
|
|
|
50
50
|
gloas,
|
|
51
51
|
ssz,
|
|
52
52
|
} from "@lodestar/types";
|
|
53
|
-
import {Logger, byteArrayEquals, fromHex, sleep, toHex, toPubkeyHex, toRootHex} from "@lodestar/utils";
|
|
53
|
+
import {GWEI_TO_WEI, Logger, byteArrayEquals, fromHex, sleep, toHex, toPubkeyHex, toRootHex} from "@lodestar/utils";
|
|
54
54
|
import {ZERO_HASH_HEX} from "../../constants/index.js";
|
|
55
55
|
import {numToQuantity} from "../../execution/engine/utils.js";
|
|
56
|
-
import {
|
|
57
|
-
IExecutionBuilder,
|
|
58
|
-
IExecutionEngine,
|
|
59
|
-
PayloadAttributes,
|
|
60
|
-
PayloadId,
|
|
61
|
-
getExpectedGasLimit,
|
|
62
|
-
} from "../../execution/index.js";
|
|
56
|
+
import {IExecutionBuilder, IExecutionEngine, PayloadAttributes, PayloadId} from "../../execution/index.js";
|
|
63
57
|
import {getShufflingDependentRoot} from "../../util/dependentRoot.js";
|
|
64
58
|
import {fromGraffitiBytes} from "../../util/graffiti.js";
|
|
65
59
|
import {kzg} from "../../util/kzg.js";
|
|
@@ -97,6 +91,8 @@ export type BlockAttributes = {
|
|
|
97
91
|
slot: Slot;
|
|
98
92
|
parentBlock: ProtoBlock;
|
|
99
93
|
feeRecipient?: string;
|
|
94
|
+
/** When provided, build block with this builder bid instead of a self-build bid */
|
|
95
|
+
builderBid?: gloas.SignedExecutionPayloadBid;
|
|
100
96
|
};
|
|
101
97
|
|
|
102
98
|
export enum BlockType {
|
|
@@ -112,7 +108,7 @@ export type ProduceFullGloas = {
|
|
|
112
108
|
type: BlockType.Full;
|
|
113
109
|
fork: ForkPostGloas;
|
|
114
110
|
executionPayload: ExecutionPayload<ForkPostGloas>;
|
|
115
|
-
executionRequests:
|
|
111
|
+
executionRequests: gloas.ExecutionRequests;
|
|
116
112
|
blobsBundle: BlobsBundle<ForkPostGloas>;
|
|
117
113
|
cells: fulu.Cell[][];
|
|
118
114
|
parentBlockRoot: Root;
|
|
@@ -156,6 +152,28 @@ export type ProduceResult =
|
|
|
156
152
|
| ProduceFullPhase0
|
|
157
153
|
| ProduceBlinded;
|
|
158
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Drop voluntary exits that `parent_execution_requests` have invalidated (e.g. a withdrawal
|
|
157
|
+
* request initiating an exit on the same validator). Op pool selected against the unapplied
|
|
158
|
+
* state, so re-validate against the post-apply state to avoid producing an invalid block.
|
|
159
|
+
*
|
|
160
|
+
* `getStateAfterParentPayload` is a thunk so the post-apply state is only materialized when
|
|
161
|
+
* actually needed (i.e. when extending the parent payload and there are exits to filter).
|
|
162
|
+
*/
|
|
163
|
+
function maybeFilterInvalidatedVoluntaryExits(
|
|
164
|
+
commonBlockBody: CommonBlockBody,
|
|
165
|
+
isExtendingPayload: boolean,
|
|
166
|
+
getStateAfterParentPayload: () => IBeaconStateViewBellatrix
|
|
167
|
+
): CommonBlockBody["voluntaryExits"] {
|
|
168
|
+
if (!isExtendingPayload || commonBlockBody.voluntaryExits.length === 0) {
|
|
169
|
+
return commonBlockBody.voluntaryExits;
|
|
170
|
+
}
|
|
171
|
+
const state = getStateAfterParentPayload();
|
|
172
|
+
return commonBlockBody.voluntaryExits.filter((signedVoluntaryExit) =>
|
|
173
|
+
state.isValidVoluntaryExit(signedVoluntaryExit, false)
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
159
177
|
export async function produceBlockBody<T extends BlockType>(
|
|
160
178
|
this: BeaconChain,
|
|
161
179
|
blockType: T,
|
|
@@ -178,6 +196,7 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
178
196
|
proposerIndex,
|
|
179
197
|
proposerPubKey,
|
|
180
198
|
commonBlockBodyPromise,
|
|
199
|
+
builderBid,
|
|
181
200
|
} = blockAttr;
|
|
182
201
|
let executionPayloadValue: Wei;
|
|
183
202
|
let blockBody: AssembledBodyType<T>;
|
|
@@ -198,7 +217,43 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
198
217
|
};
|
|
199
218
|
this.logger.verbose("Producing beacon block body", logMeta);
|
|
200
219
|
|
|
201
|
-
if (
|
|
220
|
+
if (builderBid !== undefined) {
|
|
221
|
+
if (!isStatePostGloas(currentState)) {
|
|
222
|
+
throw new Error("Expected Gloas state for builder bid block production");
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const isExtendingPayload = byteArrayEquals(
|
|
226
|
+
builderBid.message.parentBlockHash,
|
|
227
|
+
currentState.latestExecutionPayloadBid.blockHash
|
|
228
|
+
);
|
|
229
|
+
const parentExecutionRequests = isExtendingPayload
|
|
230
|
+
? await this.getParentExecutionRequests(parentBlock.slot, parentBlock.blockRoot)
|
|
231
|
+
: ssz.gloas.ExecutionRequests.defaultValue();
|
|
232
|
+
executionPayloadValue = BigInt(builderBid.message.value) * GWEI_TO_WEI;
|
|
233
|
+
|
|
234
|
+
const commonBlockBody = await commonBlockBodyPromise;
|
|
235
|
+
const gloasBody = Object.assign({}, commonBlockBody) as gloas.BeaconBlockBody;
|
|
236
|
+
gloasBody.signedExecutionPayloadBid = builderBid;
|
|
237
|
+
gloasBody.payloadAttestations = this.payloadAttestationPool.getPayloadAttestationsForBlock(
|
|
238
|
+
parentBlock.blockRoot,
|
|
239
|
+
blockSlot - 1
|
|
240
|
+
);
|
|
241
|
+
gloasBody.parentExecutionRequests = parentExecutionRequests;
|
|
242
|
+
gloasBody.voluntaryExits = maybeFilterInvalidatedVoluntaryExits(commonBlockBody, isExtendingPayload, () =>
|
|
243
|
+
currentState.withParentPayloadApplied(parentExecutionRequests)
|
|
244
|
+
);
|
|
245
|
+
blockBody = gloasBody as AssembledBodyType<T>;
|
|
246
|
+
|
|
247
|
+
this.logger.verbose("Produced block with builder bid", {
|
|
248
|
+
slot: blockSlot,
|
|
249
|
+
builderIndex: builderBid.message.builderIndex,
|
|
250
|
+
bidValue: builderBid.message.value,
|
|
251
|
+
parentBlockHash: toRootHex(builderBid.message.parentBlockHash),
|
|
252
|
+
parentBlockRoot: toRootHex(builderBid.message.parentBlockRoot),
|
|
253
|
+
blockHash: toRootHex(builderBid.message.blockHash),
|
|
254
|
+
isExtendingPayload,
|
|
255
|
+
});
|
|
256
|
+
} else if (isForkPostGloas(fork)) {
|
|
202
257
|
if (!isStatePostGloas(currentState)) {
|
|
203
258
|
throw new Error("Expected Gloas state for Gloas block production");
|
|
204
259
|
}
|
|
@@ -215,25 +270,22 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
215
270
|
|
|
216
271
|
const endExecutionPayload = this.metrics?.executionBlockProductionTimeSteps.startTimer();
|
|
217
272
|
|
|
218
|
-
this.logger.verbose("Preparing execution payload from engine", {
|
|
219
|
-
slot: blockSlot,
|
|
220
|
-
parentBlockRoot: toRootHex(parentBlockRoot),
|
|
221
|
-
feeRecipient,
|
|
222
|
-
});
|
|
223
|
-
|
|
224
273
|
// Get execution payload from EL
|
|
225
274
|
let parentBlockHash: Bytes32;
|
|
226
|
-
let parentExecutionRequests:
|
|
275
|
+
let parentExecutionRequests: gloas.ExecutionRequests;
|
|
227
276
|
// Apply parent payload once here as it's reused by EL prep and voluntary exit filtering below
|
|
228
277
|
let stateAfterParentPayload: IBeaconStateViewBellatrix = currentState;
|
|
229
|
-
|
|
230
|
-
|
|
278
|
+
// Spec: should_build_on_full(store, head). `parentBlock` is the proposer's head
|
|
279
|
+
// (set by chain.getProposerHead(slot)). Returns false when the PTC majority signalled
|
|
280
|
+
// the blob data is not available or the payload was not timely, forcing a build on EMPTY (reorg).
|
|
281
|
+
const isBuildingOnFull = this.forkChoice.shouldBuildOnFull(parentBlock, blockSlot);
|
|
282
|
+
if (isBuildingOnFull) {
|
|
231
283
|
parentBlockHash = currentState.latestExecutionPayloadBid.blockHash;
|
|
232
284
|
parentExecutionRequests = await this.getParentExecutionRequests(parentBlock.slot, parentBlock.blockRoot);
|
|
233
285
|
stateAfterParentPayload = currentState.withParentPayloadApplied(parentExecutionRequests);
|
|
234
286
|
} else {
|
|
235
287
|
parentBlockHash = currentState.latestExecutionPayloadBid.parentBlockHash;
|
|
236
|
-
parentExecutionRequests = ssz.
|
|
288
|
+
parentExecutionRequests = ssz.gloas.ExecutionRequests.defaultValue();
|
|
237
289
|
}
|
|
238
290
|
const prepareRes = await prepareExecutionPayload(
|
|
239
291
|
this,
|
|
@@ -250,6 +302,16 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
250
302
|
const {prepType, payloadId} = prepareRes;
|
|
251
303
|
Object.assign(logMeta, {executionPayloadPrepType: prepType});
|
|
252
304
|
|
|
305
|
+
this.logger.verbose("Prepared execution payload from engine", {
|
|
306
|
+
slot: blockSlot,
|
|
307
|
+
parentBlockRoot: toRootHex(parentBlockRoot),
|
|
308
|
+
parentBlockHash: toRootHex(parentBlockHash),
|
|
309
|
+
feeRecipient,
|
|
310
|
+
prepType,
|
|
311
|
+
payloadId,
|
|
312
|
+
isBuildingOnFull,
|
|
313
|
+
});
|
|
314
|
+
|
|
253
315
|
if (prepType !== PayloadPreparationType.Cached) {
|
|
254
316
|
await sleep(PAYLOAD_GENERATION_TIME_MS);
|
|
255
317
|
}
|
|
@@ -282,13 +344,13 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
282
344
|
blockHash: executionPayload.blockHash,
|
|
283
345
|
prevRandao: currentState.getRandaoMix(currentState.epoch),
|
|
284
346
|
feeRecipient: executionPayload.feeRecipient,
|
|
285
|
-
gasLimit:
|
|
347
|
+
gasLimit: executionPayload.gasLimit,
|
|
286
348
|
builderIndex: BUILDER_INDEX_SELF_BUILD,
|
|
287
349
|
slot: blockSlot,
|
|
288
350
|
value: 0,
|
|
289
351
|
executionPayment: 0,
|
|
290
352
|
blobKzgCommitments: blobsBundle.commitments,
|
|
291
|
-
executionRequestsRoot: ssz.
|
|
353
|
+
executionRequestsRoot: ssz.gloas.ExecutionRequests.hashTreeRoot(executionRequests as gloas.ExecutionRequests),
|
|
292
354
|
};
|
|
293
355
|
const signedBid: gloas.SignedExecutionPayloadBid = {
|
|
294
356
|
message: bid,
|
|
@@ -303,20 +365,17 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
303
365
|
blockSlot - 1
|
|
304
366
|
);
|
|
305
367
|
gloasBody.parentExecutionRequests = parentExecutionRequests;
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
stateAfterParentPayload.isValidVoluntaryExit(signedVoluntaryExit, false)
|
|
312
|
-
);
|
|
313
|
-
}
|
|
368
|
+
gloasBody.voluntaryExits = maybeFilterInvalidatedVoluntaryExits(
|
|
369
|
+
commonBlockBody,
|
|
370
|
+
isBuildingOnFull,
|
|
371
|
+
() => stateAfterParentPayload
|
|
372
|
+
);
|
|
314
373
|
blockBody = gloasBody as AssembledBodyType<T>;
|
|
315
374
|
|
|
316
375
|
// Store execution payload data required to construct execution payload envelope later
|
|
317
376
|
const gloasResult = produceResult as ProduceFullGloas;
|
|
318
377
|
gloasResult.executionPayload = executionPayload as ExecutionPayload<ForkPostGloas>;
|
|
319
|
-
gloasResult.executionRequests = executionRequests;
|
|
378
|
+
gloasResult.executionRequests = executionRequests as gloas.ExecutionRequests;
|
|
320
379
|
gloasResult.blobsBundle = blobsBundle;
|
|
321
380
|
gloasResult.cells = cells;
|
|
322
381
|
gloasResult.parentBlockRoot = fromHex(parentBlock.blockRoot);
|
|
@@ -331,6 +390,7 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
331
390
|
fetchedTime,
|
|
332
391
|
executionBlockHash: toRootHex(executionPayload.blockHash),
|
|
333
392
|
blobs: blobsBundle.commitments.length,
|
|
393
|
+
gasLimit: executionPayload.gasLimit,
|
|
334
394
|
});
|
|
335
395
|
|
|
336
396
|
Object.assign(logMeta, {
|
|
@@ -869,9 +929,9 @@ function preparePayloadAttributes(
|
|
|
869
929
|
(payloadAttributes as gloas.SSEPayloadAttributes["payloadAttributes"]).slotNumber = prepareSlot;
|
|
870
930
|
(payloadAttributes as gloas.SSEPayloadAttributes["payloadAttributes"]).targetGasLimit = getProposerTargetGasLimit(
|
|
871
931
|
chain,
|
|
872
|
-
prepareState,
|
|
873
932
|
prepareSlot,
|
|
874
|
-
parentBlockRoot
|
|
933
|
+
parentBlockRoot,
|
|
934
|
+
parentBlockHash
|
|
875
935
|
);
|
|
876
936
|
}
|
|
877
937
|
|
|
@@ -886,14 +946,20 @@ function preparePayloadAttributes(
|
|
|
886
946
|
* (same `(slot, dependent_root)` lookup as gossip bid validation). When no matching
|
|
887
947
|
* preferences are pooled, target the parent payload's gas limit so the gas limit stays
|
|
888
948
|
* unchanged (`is_gas_limit_target_compatible` then requires `gas_limit == parent_gas_limit`).
|
|
949
|
+
*
|
|
950
|
+
* The parent payload's gas_limit is read from fork choice — the variant matching
|
|
951
|
+
* `(parentBlockRoot, parentBlockHash)` carries the correct value for both FULL parents
|
|
952
|
+
* (FULL.executionPayloadGasLimit = delivered payload's gas_limit) and EMPTY parents
|
|
953
|
+
* (EMPTY.executionPayloadGasLimit = inherited grandparent's gas_limit).
|
|
889
954
|
*/
|
|
890
955
|
function getProposerTargetGasLimit(
|
|
891
956
|
chain: {forkChoice: IForkChoice; proposerPreferencesPool: ProposerPreferencesPool},
|
|
892
|
-
state: IBeaconStateViewGloas,
|
|
893
957
|
prepareSlot: Slot,
|
|
894
|
-
parentBlockRoot: Root
|
|
958
|
+
parentBlockRoot: Root,
|
|
959
|
+
parentBlockHash: Bytes32
|
|
895
960
|
): number {
|
|
896
|
-
const
|
|
961
|
+
const parentBlockRootHex = toRootHex(parentBlockRoot);
|
|
962
|
+
const parentBlock = chain.forkChoice.getBlockHexDefaultStatus(parentBlockRootHex);
|
|
897
963
|
const dependentRootHex = (() => {
|
|
898
964
|
if (parentBlock === null) {
|
|
899
965
|
return null;
|
|
@@ -911,9 +977,17 @@ function getProposerTargetGasLimit(
|
|
|
911
977
|
})();
|
|
912
978
|
|
|
913
979
|
const pref = dependentRootHex !== null ? chain.proposerPreferencesPool.get(prepareSlot, dependentRootHex) : null;
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
980
|
+
if (pref !== null) {
|
|
981
|
+
return pref.message.targetGasLimit;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
const parentPayloadVariant = chain.forkChoice.getBlockHexAndBlockHash(parentBlockRootHex, toRootHex(parentBlockHash));
|
|
985
|
+
if (parentPayloadVariant === null || parentPayloadVariant.executionPayloadBlockHash === null) {
|
|
986
|
+
throw new Error(
|
|
987
|
+
`Cannot resolve parent payload gas_limit for proposer targetGasLimit fallback parentBlockRoot=${parentBlockRootHex} parentBlockHash=${toRootHex(parentBlockHash)}`
|
|
988
|
+
);
|
|
989
|
+
}
|
|
990
|
+
return parentPayloadVariant.executionPayloadGasLimit;
|
|
917
991
|
}
|
|
918
992
|
|
|
919
993
|
export async function produceCommonBlockBody<T extends BlockType>(
|
|
@@ -17,10 +17,12 @@ export enum RegenCaller {
|
|
|
17
17
|
predictProposerHead = "predictProposerHead",
|
|
18
18
|
produceAttestationData = "produceAttestationData",
|
|
19
19
|
processBlocksInEpoch = "processBlocksInEpoch",
|
|
20
|
+
importExecutionPayload = "importExecutionPayload",
|
|
20
21
|
validateGossipAggregateAndProof = "validateGossipAggregateAndProof",
|
|
21
22
|
validateGossipAttestation = "validateGossipAttestation",
|
|
22
23
|
validateGossipVoluntaryExit = "validateGossipVoluntaryExit",
|
|
23
24
|
validateGossipExecutionPayloadBid = "validateGossipExecutionPayloadBid",
|
|
25
|
+
validateGossipPayloadAttestationMessage = "validateGossipPayloadAttestationMessage",
|
|
24
26
|
validateGossipProposerPreferences = "validateGossipProposerPreferences",
|
|
25
27
|
onForkChoiceFinalized = "onForkChoiceFinalized",
|
|
26
28
|
restApi = "restApi",
|
|
@@ -45,7 +47,6 @@ export interface IStateRegenerator extends IStateRegeneratorInternal {
|
|
|
45
47
|
getCheckpointStateSync(cp: CheckpointHex): IBeaconStateView | null;
|
|
46
48
|
getClosestHeadState(head: ProtoBlock): IBeaconStateView | null;
|
|
47
49
|
pruneOnCheckpoint(finalizedEpoch: Epoch, justifiedEpoch: Epoch, headStateRoot: RootHex): void;
|
|
48
|
-
pruneOnFinalized(finalizedEpoch: Epoch): void;
|
|
49
50
|
processState(blockRootHex: RootHex, postState: IBeaconStateView): void;
|
|
50
51
|
addCheckpointState(cp: phase0.Checkpoint, item: IBeaconStateView): void;
|
|
51
52
|
updateHeadState(newHead: ProtoBlock, maybeHeadState: IBeaconStateView): void;
|
|
@@ -143,11 +143,6 @@ export class QueuedStateRegenerator implements IStateRegenerator {
|
|
|
143
143
|
this.blockStateCache.prune(headStateRoot);
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
pruneOnFinalized(finalizedEpoch: number): void {
|
|
147
|
-
this.checkpointStateCache.pruneFinalized(finalizedEpoch);
|
|
148
|
-
this.blockStateCache.deleteAllBeforeEpoch(finalizedEpoch);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
146
|
processState(blockRootHex: RootHex, postState: IBeaconStateView): void {
|
|
152
147
|
this.blockStateCache.add(postState);
|
|
153
148
|
this.checkpointStateCache.processState(blockRootHex, postState).catch((e) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {CheckpointWithHex, IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
|
|
2
|
+
import {CheckpointWithHex, IForkChoice, PayloadStatus, ProtoBlock} from "@lodestar/fork-choice";
|
|
3
3
|
import {computeStartSlotAtEpoch} from "@lodestar/state-transition";
|
|
4
4
|
import {RootHex} from "@lodestar/types";
|
|
5
5
|
import {Logger} from "@lodestar/utils";
|
|
@@ -154,9 +154,14 @@ export class SeenPayloadEnvelopeInput {
|
|
|
154
154
|
|
|
155
155
|
pruneBelowParent(parentBlock: ProtoBlock): void {
|
|
156
156
|
for (const block of this.forkChoice.getAllAncestorBlocks(parentBlock.blockRoot, parentBlock.payloadStatus)) {
|
|
157
|
-
|
|
157
|
+
// Only evict once the payload is FULL (revealed/imported) — on an EMPTY/PENDING branch we may
|
|
158
|
+
// still need to download the FULL envelope (see #9475), and evicting would make payload-by-root
|
|
159
|
+
// sync throw "Missing PayloadEnvelopeInput for known block".
|
|
160
|
+
if (block.slot < parentBlock.slot && block.payloadStatus === PayloadStatus.FULL) {
|
|
158
161
|
const input = this.payloadInputs.get(block.blockRoot);
|
|
159
|
-
|
|
162
|
+
// ...and don't evict while columns are still being gathered: writeDataColumnsToDb awaits the
|
|
163
|
+
// same hasComputedAllData() before persisting. Such entries are pruned by a later call.
|
|
164
|
+
if (input?.hasComputedAllData()) {
|
|
160
165
|
this.evictPayloadInput(input);
|
|
161
166
|
this.logger?.verbose("SeenPayloadEnvelopeInput.pruneBelowParent deleted", {
|
|
162
167
|
slot: block.slot,
|
|
@@ -167,12 +167,6 @@ export class FIFOBlockStateCache implements BlockStateCache {
|
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
/**
|
|
171
|
-
* No need for this implementation
|
|
172
|
-
* This is only to conform to the old api
|
|
173
|
-
*/
|
|
174
|
-
deleteAllBeforeEpoch(): void {}
|
|
175
|
-
|
|
176
170
|
/**
|
|
177
171
|
* ONLY FOR DEBUGGING PURPOSES. For lodestar debug API.
|
|
178
172
|
*/
|
|
@@ -414,11 +414,12 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
|
|
|
414
414
|
|
|
415
415
|
/**
|
|
416
416
|
* Prune all checkpoint states before the provided finalized epoch.
|
|
417
|
+
* Driven sequentially from processState() so it never interleaves with persist.
|
|
417
418
|
*/
|
|
418
|
-
pruneFinalized(finalizedEpoch: Epoch): void {
|
|
419
|
+
private async pruneFinalized(finalizedEpoch: Epoch): Promise<void> {
|
|
419
420
|
for (const epoch of this.epochIndex.keys()) {
|
|
420
421
|
if (epoch < finalizedEpoch) {
|
|
421
|
-
this.deleteAllEpochItems(epoch).catch((e) =>
|
|
422
|
+
await this.deleteAllEpochItems(epoch).catch((e) =>
|
|
422
423
|
this.logger.debug("Error delete all epoch items", {epoch, finalizedEpoch}, e as Error)
|
|
423
424
|
);
|
|
424
425
|
}
|
|
@@ -476,6 +477,9 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
|
|
|
476
477
|
* As of Mar 2024, it takes <=350ms to persist a holesky state on fast server
|
|
477
478
|
*/
|
|
478
479
|
async processState(blockRootHex: RootHex, state: IBeaconStateView): Promise<number> {
|
|
480
|
+
// prune finalized in the same flow so a finalized cp state is pruned, never persisted
|
|
481
|
+
await this.pruneFinalized(state.finalizedCheckpoint.epoch);
|
|
482
|
+
|
|
479
483
|
let persistCount = 0;
|
|
480
484
|
// it's important to sort the epochs in ascending order, in case of big reorg we always want to keep the most recent checkpoint states
|
|
481
485
|
const sortedEpochs = Array.from(this.epochIndex.keys()).sort((a, b) => a - b);
|
|
@@ -30,7 +30,6 @@ export interface BlockStateCache {
|
|
|
30
30
|
clear(): void;
|
|
31
31
|
size: number;
|
|
32
32
|
prune(headStateRootHex: RootHex): void;
|
|
33
|
-
deleteAllBeforeEpoch(finalizedEpoch: Epoch): void;
|
|
34
33
|
dumpSummary(): routes.lodestar.StateCacheItem[];
|
|
35
34
|
/** Expose beacon states stored in cache. Use with caution */
|
|
36
35
|
getStates(): IterableIterator<IBeaconStateView>;
|
|
@@ -67,7 +66,6 @@ export interface CheckpointStateCache {
|
|
|
67
66
|
getOrReloadLatest(rootHex: RootHex, maxEpoch: Epoch): Promise<IBeaconStateView | null>;
|
|
68
67
|
updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch): number | null;
|
|
69
68
|
prune(finalizedEpoch: Epoch, justifiedEpoch: Epoch): void;
|
|
70
|
-
pruneFinalized(finalizedEpoch: Epoch): void;
|
|
71
69
|
processState(blockRootHex: RootHex, state: IBeaconStateView): Promise<number>;
|
|
72
70
|
clear(): void;
|
|
73
71
|
dumpSummary(): routes.lodestar.StateCacheItem[];
|