@lodestar/beacon-node 1.43.0-dev.549a5b8115 → 1.43.0-dev.657dd16e61
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 +10 -0
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/debug/index.d.ts.map +1 -1
- package/lib/api/impl/debug/index.js +0 -1
- package/lib/api/impl/debug/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +2 -1
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.d.ts +3 -0
- package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.js +4 -1
- package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +16 -29
- 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 +3 -5
- 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 +30 -17
- 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 +5 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +2 -1
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
- package/lib/chain/blocks/utils/chainSegment.js +8 -0
- package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
- package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +5 -6
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +0 -4
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +5 -2
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts +2 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.js +16 -7
- package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +2 -2
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +5 -2
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +10 -9
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +0 -11
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/emitter.js +0 -4
- package/lib/chain/emitter.js.map +1 -1
- package/lib/chain/errors/proposerPreferences.d.ts +8 -1
- package/lib/chain/errors/proposerPreferences.d.ts.map +1 -1
- package/lib/chain/errors/proposerPreferences.js +1 -0
- package/lib/chain/errors/proposerPreferences.js.map +1 -1
- package/lib/chain/initState.d.ts.map +1 -1
- package/lib/chain/initState.js +6 -1
- package/lib/chain/initState.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +16 -18
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +12 -3
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +33 -20
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +1 -4
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/regen/regen.d.ts.map +1 -1
- package/lib/chain/regen/regen.js +1 -4
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +7 -4
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +42 -14
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
- package/lib/chain/seenCache/seenProposerPreferences.d.ts +8 -7
- package/lib/chain/seenCache/seenProposerPreferences.d.ts.map +1 -1
- package/lib/chain/seenCache/seenProposerPreferences.js +11 -10
- package/lib/chain/seenCache/seenProposerPreferences.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +11 -8
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/proposerPreferences.d.ts.map +1 -1
- package/lib/chain/validation/proposerPreferences.js +39 -17
- package/lib/chain/validation/proposerPreferences.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +2 -0
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +24 -7
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/index.js +5 -5
- package/lib/network/processor/index.js.map +1 -1
- package/lib/node/nodejs.js +2 -2
- package/lib/node/nodejs.js.map +1 -1
- package/lib/node/notifier.js +1 -7
- package/lib/node/notifier.js.map +1 -1
- package/lib/sync/constants.d.ts +3 -1
- package/lib/sync/constants.d.ts.map +1 -1
- package/lib/sync/constants.js +3 -4
- package/lib/sync/constants.js.map +1 -1
- package/lib/sync/range/batch.d.ts +16 -0
- package/lib/sync/range/batch.d.ts.map +1 -1
- package/lib/sync/range/batch.js +97 -21
- package/lib/sync/range/batch.js.map +1 -1
- package/lib/sync/range/chain.d.ts +6 -0
- package/lib/sync/range/chain.d.ts.map +1 -1
- package/lib/sync/range/chain.js +50 -7
- package/lib/sync/range/chain.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts +0 -2
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +2 -47
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +36 -21
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRoot.js +10 -0
- package/lib/sync/utils/downloadByRoot.js.map +1 -1
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +8 -6
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +15 -15
- package/src/api/impl/beacon/blocks/index.ts +13 -0
- package/src/api/impl/debug/index.ts +0 -1
- package/src/api/impl/validator/index.ts +2 -1
- package/src/chain/blocks/blockInput/blockInput.ts +4 -1
- package/src/chain/blocks/importBlock.ts +16 -49
- package/src/chain/blocks/importExecutionPayload.ts +3 -5
- package/src/chain/blocks/index.ts +20 -9
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +5 -1
- package/src/chain/blocks/types.ts +2 -1
- package/src/chain/blocks/utils/chainSegment.ts +8 -0
- package/src/chain/blocks/verifyBlock.ts +7 -5
- package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +6 -4
- package/src/chain/blocks/verifyBlocksSanityChecks.ts +16 -6
- package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +7 -2
- package/src/chain/chain.ts +12 -9
- package/src/chain/emitter.ts +0 -11
- package/src/chain/errors/proposerPreferences.ts +9 -1
- package/src/chain/initState.ts +9 -1
- package/src/chain/prepareNextSlot.ts +21 -29
- package/src/chain/produceBlock/produceBlockBody.ts +41 -25
- package/src/chain/regen/queued.ts +2 -7
- package/src/chain/regen/regen.ts +2 -7
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +55 -16
- package/src/chain/seenCache/seenProposerPreferences.ts +14 -11
- package/src/chain/validation/executionPayloadBid.ts +11 -8
- package/src/chain/validation/proposerPreferences.ts +37 -18
- package/src/network/processor/gossipHandlers.ts +30 -7
- package/src/network/processor/index.ts +5 -5
- package/src/node/nodejs.ts +2 -2
- package/src/node/notifier.ts +1 -8
- package/src/sync/constants.ts +4 -4
- package/src/sync/range/batch.ts +124 -24
- package/src/sync/range/chain.ts +57 -7
- package/src/sync/unknownBlock.ts +2 -50
- package/src/sync/utils/downloadByRange.ts +37 -21
- package/src/sync/utils/downloadByRoot.ts +12 -0
- package/src/util/sszBytes.ts +8 -6
|
@@ -9,14 +9,7 @@ import {
|
|
|
9
9
|
NotReorgedReason,
|
|
10
10
|
getSafeExecutionBlockHash,
|
|
11
11
|
} from "@lodestar/fork-choice";
|
|
12
|
-
import {
|
|
13
|
-
ForkPostAltair,
|
|
14
|
-
ForkPostElectra,
|
|
15
|
-
ForkPostGloas,
|
|
16
|
-
ForkSeq,
|
|
17
|
-
MAX_SEED_LOOKAHEAD,
|
|
18
|
-
SLOTS_PER_EPOCH,
|
|
19
|
-
} from "@lodestar/params";
|
|
12
|
+
import {ForkPostAltair, ForkPostElectra, ForkSeq, MAX_SEED_LOOKAHEAD, SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
20
13
|
import {
|
|
21
14
|
IBeaconStateView,
|
|
22
15
|
RootCache,
|
|
@@ -27,17 +20,7 @@ import {
|
|
|
27
20
|
isStatePostAltair,
|
|
28
21
|
isStatePostBellatrix,
|
|
29
22
|
} from "@lodestar/state-transition";
|
|
30
|
-
import {
|
|
31
|
-
Attestation,
|
|
32
|
-
BeaconBlock,
|
|
33
|
-
SignedBeaconBlock,
|
|
34
|
-
altair,
|
|
35
|
-
capella,
|
|
36
|
-
electra,
|
|
37
|
-
isGloasBeaconBlock,
|
|
38
|
-
phase0,
|
|
39
|
-
ssz,
|
|
40
|
-
} from "@lodestar/types";
|
|
23
|
+
import {Attestation, BeaconBlock, altair, capella, electra, isGloasBeaconBlock, phase0, ssz} from "@lodestar/types";
|
|
41
24
|
import {isErrorAborted, toRootHex} from "@lodestar/utils";
|
|
42
25
|
import {ZERO_HASH_HEX} from "../../constants/index.js";
|
|
43
26
|
import {callInNextEventLoop} from "../../util/eventLoop.js";
|
|
@@ -86,8 +69,8 @@ export async function importBlock(
|
|
|
86
69
|
fullyVerifiedBlock: FullyVerifiedBlock,
|
|
87
70
|
opts: ImportBlockOpts
|
|
88
71
|
): Promise<void> {
|
|
89
|
-
const {blockInput, postState, parentBlockSlot,
|
|
90
|
-
|
|
72
|
+
const {blockInput, postState, parentBlockSlot, dataAvailabilityStatus, indexedAttestations} = fullyVerifiedBlock;
|
|
73
|
+
let {executionStatus} = fullyVerifiedBlock;
|
|
91
74
|
const block = blockInput.getBlock();
|
|
92
75
|
const source = blockInput.getBlockSource();
|
|
93
76
|
const {slot: blockSlot} = block.message;
|
|
@@ -122,12 +105,23 @@ export async function importBlock(
|
|
|
122
105
|
|
|
123
106
|
// Should compute checkpoint balances before forkchoice.onBlock
|
|
124
107
|
this.checkpointBalancesCache.processState(blockRootHex, postState);
|
|
108
|
+
if (fork >= ForkSeq.gloas) {
|
|
109
|
+
const parentRootHex = toRootHex(block.message.parentRoot);
|
|
110
|
+
const parentBlock = this.forkChoice.getBlockHexDefaultStatus(parentRootHex);
|
|
111
|
+
if (parentBlock === null) {
|
|
112
|
+
throw Error(`Parent block not found in forkChoice, parentRoot=${parentRootHex}`);
|
|
113
|
+
}
|
|
114
|
+
if (parentBlock.executionStatus === ExecutionStatus.Invalid) {
|
|
115
|
+
throw Error(`Parent block has invalid execution status, parentRoot=${parentRootHex}`);
|
|
116
|
+
}
|
|
117
|
+
executionStatus = parentBlock.executionStatus;
|
|
118
|
+
}
|
|
125
119
|
const blockSummary = this.forkChoice.onBlock(
|
|
126
120
|
block.message,
|
|
127
121
|
postState,
|
|
128
122
|
blockDelaySec,
|
|
129
123
|
currentSlot,
|
|
130
|
-
|
|
124
|
+
executionStatus,
|
|
131
125
|
dataAvailabilityStatus
|
|
132
126
|
);
|
|
133
127
|
|
|
@@ -135,33 +129,6 @@ export async function importBlock(
|
|
|
135
129
|
// Some block event handlers require state being in state cache so need to do this before emitting EventType.block
|
|
136
130
|
this.regen.processState(blockRootHex, postState);
|
|
137
131
|
|
|
138
|
-
// For range sync, PayloadEnvelope is created before reaching this
|
|
139
|
-
// we also don't need to trigger getBlobs() in that case
|
|
140
|
-
if (fork >= ForkSeq.gloas && !opts.fromRangeSync) {
|
|
141
|
-
const payloadInput = this.seenPayloadEnvelopeInputCache.add({
|
|
142
|
-
blockRootHex,
|
|
143
|
-
block: block as SignedBeaconBlock<ForkPostGloas>,
|
|
144
|
-
forkName: blockInput.forkName,
|
|
145
|
-
sampledColumns: this.custodyConfig.sampledColumns,
|
|
146
|
-
custodyColumns: this.custodyConfig.custodyColumns,
|
|
147
|
-
timeCreatedSec: fullyVerifiedBlock.seenTimestampSec,
|
|
148
|
-
});
|
|
149
|
-
this.logger.debug("Created PayloadEnvelopeInput for block", {
|
|
150
|
-
slot: blockSlot,
|
|
151
|
-
root: blockRootHex,
|
|
152
|
-
source: source.source,
|
|
153
|
-
...(opts.seenTimestampSec !== undefined ? {recvToImport: Date.now() / 1000 - opts.seenTimestampSec} : {}),
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
// Immediately attempt fetch of data columns from execution engine as the bid contains kzg commitments
|
|
157
|
-
// which is all the information we need so there is no reason to delay until execution payload arrives
|
|
158
|
-
// TODO GLOAS: If we want EL retries after this initial attempt, add an explicit retry policy here
|
|
159
|
-
// (for example later in the slot). Do not couple retries to incoming gossip columns.
|
|
160
|
-
// Columns fetched here feed payloadInput.addColumn, which resolves waitForAllData for any
|
|
161
|
-
// in-flight importExecutionPayload. No processExecutionPayload trigger needed from this path.
|
|
162
|
-
this.getBlobsTracker.triggerGetBlobs(payloadInput);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
132
|
this.metrics?.importBlock.bySource.inc({source: source.source});
|
|
166
133
|
this.logger.verbose("Added block to forkchoice and state cache", {slot: blockSlot, root: blockRootHex});
|
|
167
134
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
2
|
import {ExecutionStatus, PayloadExecutionStatus, getSafeExecutionBlockHash} from "@lodestar/fork-choice";
|
|
3
3
|
import {DataAvailabilityStatus, isStatePostGloas} from "@lodestar/state-transition";
|
|
4
|
-
import {
|
|
4
|
+
import {isErrorAborted} from "@lodestar/utils";
|
|
5
5
|
import {ZERO_HASH_HEX} from "../../constants/index.js";
|
|
6
6
|
import {ExecutionPayloadStatus} from "../../execution/index.js";
|
|
7
7
|
import {isQueueErrorAborted} from "../../util/queue/index.js";
|
|
@@ -61,7 +61,6 @@ function toForkChoiceExecutionStatus(status: ExecutionPayloadStatus): PayloadExe
|
|
|
61
61
|
switch (status) {
|
|
62
62
|
case ExecutionPayloadStatus.VALID:
|
|
63
63
|
return ExecutionStatus.Valid;
|
|
64
|
-
// TODO GLOAS: Handle optimistic import for payload
|
|
65
64
|
case ExecutionPayloadStatus.SYNCING:
|
|
66
65
|
case ExecutionPayloadStatus.ACCEPTED:
|
|
67
66
|
return ExecutionStatus.Syncing;
|
|
@@ -160,7 +159,7 @@ export async function importExecutionPayload(
|
|
|
160
159
|
fork,
|
|
161
160
|
envelope.payload,
|
|
162
161
|
payloadInput.getVersionedHashes(),
|
|
163
|
-
|
|
162
|
+
envelope.parentBeaconBlockRoot,
|
|
164
163
|
envelope.executionRequests
|
|
165
164
|
),
|
|
166
165
|
|
|
@@ -255,8 +254,7 @@ export async function importExecutionPayload(
|
|
|
255
254
|
builderIndex: envelope.builderIndex,
|
|
256
255
|
blockHash: blockHashHex,
|
|
257
256
|
blockRoot: blockRootHex,
|
|
258
|
-
|
|
259
|
-
executionOptimistic: false,
|
|
257
|
+
executionOptimistic: execStatus === ExecutionStatus.Syncing,
|
|
260
258
|
});
|
|
261
259
|
}
|
|
262
260
|
|
|
@@ -65,7 +65,7 @@ export async function processBlocks(
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
try {
|
|
68
|
-
const {relevantBlocks, parentSlots, parentBlock} = verifyBlocksSanityChecks(this, blocks, opts);
|
|
68
|
+
const {relevantBlocks, parentSlots, parentBlock} = verifyBlocksSanityChecks(this, blocks, payloadEnvelopes, opts);
|
|
69
69
|
|
|
70
70
|
// No relevant blocks, skip verifyBlocksInEpoch()
|
|
71
71
|
if (relevantBlocks.length === 0 || parentBlock === null) {
|
|
@@ -109,8 +109,10 @@ export async function processBlocks(
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
const {executionStatuses} = segmentExecStatus;
|
|
112
|
-
const
|
|
113
|
-
|
|
112
|
+
const verifiedBlocksBySlot = new Map<Slot, FullyVerifiedBlock>();
|
|
113
|
+
for (let i = 0; i < relevantBlocks.length; i++) {
|
|
114
|
+
const block = relevantBlocks[i];
|
|
115
|
+
verifiedBlocksBySlot.set(block.getBlock().message.slot, {
|
|
114
116
|
blockInput: block,
|
|
115
117
|
postState: postStates[i],
|
|
116
118
|
parentBlockSlot: parentSlots[i],
|
|
@@ -121,14 +123,23 @@ export async function processBlocks(
|
|
|
121
123
|
indexedAttestations: indexedAttestationsByBlock[i],
|
|
122
124
|
// TODO: Make this param mandatory and capture in gossip
|
|
123
125
|
seenTimestampSec: opts.seenTimestampSec ?? Math.floor(Date.now() / 1000),
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
+
});
|
|
127
|
+
}
|
|
126
128
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
129
|
+
// Iterate slots from the original `blocks` input (which spans the entire batch including
|
|
130
|
+
// slots filtered out of `relevantBlocks`). The first batch of a checkpoint sync may contain
|
|
131
|
+
// a payload at the anchor slot whose block is already in fork-choice (added by
|
|
132
|
+
// initializeForkChoice as PENDING+EMPTY) and therefore not in verifiedBlocksBySlot — the
|
|
133
|
+
// payload still needs to be imported here to populate the anchor's FULL variant so
|
|
134
|
+
// subsequent slots can find their parent payload.
|
|
135
|
+
const slots = Array.from(new Set(blocks.map((b) => b.getBlock().message.slot)));
|
|
136
|
+
for (const slot of slots) {
|
|
137
|
+
const fullyVerifiedBlock = verifiedBlocksBySlot.get(slot);
|
|
138
|
+
if (fullyVerifiedBlock !== undefined) {
|
|
139
|
+
// TODO: Consider batching importBlock too if it takes significant time
|
|
140
|
+
await importBlock.call(this, fullyVerifiedBlock, opts);
|
|
141
|
+
}
|
|
130
142
|
|
|
131
|
-
const slot = fullyVerifiedBlock.blockInput.getBlock().message.slot;
|
|
132
143
|
const payloadInput = payloadEnvelopes?.get(slot);
|
|
133
144
|
if (payloadInput?.hasPayloadEnvelope()) {
|
|
134
145
|
if (!payloadInput.isComplete()) {
|
|
@@ -156,6 +156,7 @@ export class PayloadEnvelopeInput {
|
|
|
156
156
|
throw new Error("Payload envelope beacon_block_root mismatch");
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
// TODO GLOAS: track source by metrics, maybe inside the seen cache
|
|
159
160
|
const source: SourceMeta = {
|
|
160
161
|
source: props.source,
|
|
161
162
|
seenTimestampSec: props.seenTimestampSec,
|
|
@@ -310,8 +311,11 @@ export class PayloadEnvelopeInput {
|
|
|
310
311
|
return this.state.hasAllData;
|
|
311
312
|
}
|
|
312
313
|
|
|
314
|
+
/**
|
|
315
|
+
* Strictly checks missing sampled columns. Does NOT short-circuit on `state.hasAllData`.
|
|
316
|
+
*/
|
|
313
317
|
getMissingSampledColumnMeta(): MissingColumnMeta {
|
|
314
|
-
if (this.state.
|
|
318
|
+
if (this.state.hasComputedAllData) {
|
|
315
319
|
return {missing: [], versionedHashes: this.versionedHashes};
|
|
316
320
|
}
|
|
317
321
|
|
|
@@ -94,7 +94,8 @@ export type ImportBlockOpts = {
|
|
|
94
94
|
*
|
|
95
95
|
* `executionStatus` reflects the outcome of execution payload verification at block-import time:
|
|
96
96
|
* - pre-gloas: Valid | Syncing | PreMerge (from EL notifyNewPayload against the in-block payload)
|
|
97
|
-
* - post-gloas:
|
|
97
|
+
* - post-gloas: inherited from parent's chain (Valid/Syncing) by importBlock; payload arrives
|
|
98
|
+
* separately as an envelope and creates the FULL variant later via onExecutionPayload
|
|
98
99
|
*/
|
|
99
100
|
export type FullyVerifiedBlock = {
|
|
100
101
|
blockInput: IBlockInput;
|
|
@@ -41,6 +41,14 @@ export function assertLinearChainSegment(
|
|
|
41
41
|
// - EMPTY variant (no envelope for slot): execution hash is unchanged
|
|
42
42
|
// null only for pre-merge parents, which cannot precede gloas blocks.
|
|
43
43
|
let currentExecHash: string | null = parentBlock.executionPayloadBlockHash;
|
|
44
|
+
// Checkpoint sync first batch: parent is the anchor PENDING whose executionPayloadBlockHash
|
|
45
|
+
// is the inherited parentBlockHash semantic (= grandparent's payload), not its own payload.
|
|
46
|
+
// If parent's own payload envelope arrives in this batch, advance currentExecHash to that
|
|
47
|
+
// payload's blockHash so the segment validation sees the true EL chain head.
|
|
48
|
+
const parentPayloadInput = payloadEnvelopes?.get(parentBlock.slot);
|
|
49
|
+
if (parentPayloadInput?.hasPayloadEnvelope()) {
|
|
50
|
+
currentExecHash = parentPayloadInput.getBlockHashHex();
|
|
51
|
+
}
|
|
44
52
|
// Track the execution hash before the last FULL advancement so we can recover
|
|
45
53
|
// if the next block reveals that envelope was orphaned.
|
|
46
54
|
let prevExecHash: string | null = currentExecHash;
|
|
@@ -125,15 +125,17 @@ export async function verifyBlocksInEpoch(
|
|
|
125
125
|
}> =
|
|
126
126
|
fork >= ForkSeq.gloas
|
|
127
127
|
? (async () => {
|
|
128
|
-
|
|
129
|
-
for
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
128
|
+
// Validate DA for ALL payloads in the Map, not just those paired with blockInputs.
|
|
129
|
+
// A checkpoint-sync batch may include a payload for a slot whose block was filtered
|
|
130
|
+
// out of relevantBlocks (e.g., the anchor at the finalized slot); that payload still
|
|
131
|
+
// needs DA validation so it can be imported in processBlocks.
|
|
132
|
+
const payloadInputsForDa: PayloadEnvelopeInput[] =
|
|
133
|
+
payloadEnvelopes !== null ? Array.from(payloadEnvelopes.values()) : [];
|
|
133
134
|
const {dataAvailabilityStatuses, availableTime} = await verifyPayloadsDataAvailability(
|
|
134
135
|
payloadInputsForDa,
|
|
135
136
|
abortController.signal
|
|
136
137
|
);
|
|
138
|
+
|
|
137
139
|
const payloadDAStatuses = new Map<Slot, DataAvailabilityStatus>();
|
|
138
140
|
for (let i = 0; i < payloadInputsForDa.length; i++) {
|
|
139
141
|
payloadDAStatuses.set(payloadInputsForDa[i].slot, dataAvailabilityStatuses[i]);
|
|
@@ -46,8 +46,7 @@ type VerifyBlockExecutionResponse =
|
|
|
46
46
|
| VerifyExecutionErrorResponse
|
|
47
47
|
| {executionStatus: ExecutionStatus.Valid; lvhResponse: LVHValidResponse; execError: null}
|
|
48
48
|
| {executionStatus: ExecutionStatus.Syncing; lvhResponse?: LVHValidResponse; execError: null}
|
|
49
|
-
| {executionStatus: ExecutionStatus.PreMerge; lvhResponse: undefined; execError: null}
|
|
50
|
-
| {executionStatus: ExecutionStatus.PayloadSeparated; lvhResponse: undefined; execError: null};
|
|
49
|
+
| {executionStatus: ExecutionStatus.PreMerge; lvhResponse: undefined; execError: null};
|
|
51
50
|
|
|
52
51
|
/**
|
|
53
52
|
* Verifies 1 or more execution payloads from a linear sequence of blocks.
|
|
@@ -145,9 +144,10 @@ export async function verifyBlockExecutionPayload(
|
|
|
145
144
|
): Promise<VerifyBlockExecutionResponse> {
|
|
146
145
|
const block = blockInput.getBlock();
|
|
147
146
|
|
|
148
|
-
// Gloas block doesn't have execution payload. Return
|
|
147
|
+
// Gloas block doesn't have execution payload. Return Syncing as a placeholder; the actual
|
|
148
|
+
// status for gloas PENDING/EMPTY is derived from parent's chain in importBlock.
|
|
149
149
|
if (isBlockInputNoData(blockInput)) {
|
|
150
|
-
return {executionStatus: ExecutionStatus.
|
|
150
|
+
return {executionStatus: ExecutionStatus.Syncing, lvhResponse: undefined, execError: null};
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
/** Not null if execution is enabled */
|
|
@@ -198,6 +198,7 @@ export async function verifyBlockExecutionPayload(
|
|
|
198
198
|
executionStatus,
|
|
199
199
|
latestValidExecHash: execResult.latestValidHash,
|
|
200
200
|
invalidateFromParentBlockRoot: blockInput.parentRootHex,
|
|
201
|
+
invalidateFromParentBlockHash: toRootHex(executionPayloadEnabled.parentHash),
|
|
201
202
|
};
|
|
202
203
|
const execError = new BlockError(block, {
|
|
203
204
|
code: BlockErrorCode.EXECUTION_ENGINE_ERROR,
|
|
@@ -281,6 +282,7 @@ function getSegmentErrorResponse(
|
|
|
281
282
|
executionStatus: ExecutionStatus.Invalid,
|
|
282
283
|
latestValidExecHash: lvhResponse.latestValidExecHash,
|
|
283
284
|
invalidateFromParentBlockRoot: parentBlock.blockRoot,
|
|
285
|
+
invalidateFromParentBlockHash: parentBlock.executionPayloadBlockHash,
|
|
284
286
|
};
|
|
285
287
|
}
|
|
286
288
|
}
|
|
@@ -7,6 +7,7 @@ import {IClock} from "../../util/clock.js";
|
|
|
7
7
|
import {BlockError, BlockErrorCode} from "../errors/index.js";
|
|
8
8
|
import {IChainOptions} from "../options.js";
|
|
9
9
|
import {IBlockInput} from "./blockInput/types.js";
|
|
10
|
+
import {PayloadEnvelopeInput} from "./payloadEnvelopeInput/payloadEnvelopeInput.js";
|
|
10
11
|
import {ImportBlockOpts} from "./types.js";
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -30,6 +31,7 @@ export function verifyBlocksSanityChecks(
|
|
|
30
31
|
blacklistedBlocks: Map<RootHex, Slot | null>;
|
|
31
32
|
},
|
|
32
33
|
blocks: IBlockInput[],
|
|
34
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
|
|
33
35
|
opts: ImportBlockOpts
|
|
34
36
|
): {
|
|
35
37
|
relevantBlocks: IBlockInput[];
|
|
@@ -100,13 +102,21 @@ export function verifyBlocksSanityChecks(
|
|
|
100
102
|
const parentBlockHash = toRootHex(block.message.body.signedExecutionPayloadBid.message.parentBlockHash);
|
|
101
103
|
const parentBlockWithPayload = chain.forkChoice.getBlockHexAndBlockHash(parentRoot, parentBlockHash);
|
|
102
104
|
if (!parentBlockWithPayload) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
// Checkpoint sync: parent's FULL variant may not be in fork-choice yet because the
|
|
106
|
+
// anchor block is initialized with PENDING+EMPTY only. The parent's payload arrives
|
|
107
|
+
// in the same batch via payloadEnvelopes and will be imported by processBlocks. If
|
|
108
|
+
// a matching payload is in the Map, accept the parent as known.
|
|
109
|
+
const parentPayloadInput = payloadEnvelopes?.get(parentBlockDefaultStatus.slot);
|
|
110
|
+
if (parentPayloadInput?.getBlockHashHex() !== parentBlockHash) {
|
|
111
|
+
throw new BlockError(block, {
|
|
112
|
+
code: BlockErrorCode.PARENT_PAYLOAD_UNKNOWN,
|
|
113
|
+
parentRoot,
|
|
114
|
+
parentBlockHash,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
parentBlock = parentBlockWithPayload;
|
|
108
119
|
}
|
|
109
|
-
parentBlock = parentBlockWithPayload;
|
|
110
120
|
}
|
|
111
121
|
// Parent is known to the fork-choice
|
|
112
122
|
parentBlockSlot = parentBlock.slot;
|
|
@@ -20,7 +20,7 @@ export type VerifyExecutionPayloadEnvelopeOpts = {
|
|
|
20
20
|
* performed outside this function, see `verifyExecutionPayloadEnvelopeSignature` and
|
|
21
21
|
* `importExecutionPayload` which run both in parallel with this check.
|
|
22
22
|
*
|
|
23
|
-
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.
|
|
23
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/fork-choice.md#new-verify_execution_payload_envelope
|
|
24
24
|
*/
|
|
25
25
|
export function verifyExecutionPayloadEnvelope(
|
|
26
26
|
config: BeaconConfig,
|
|
@@ -43,6 +43,11 @@ export function verifyExecutionPayloadEnvelope(
|
|
|
43
43
|
`Envelope's block is not the latest block header envelope=${toRootHex(envelope.beaconBlockRoot)} latestBlockHeader=${toRootHex(headerRoot)}`
|
|
44
44
|
);
|
|
45
45
|
}
|
|
46
|
+
if (!byteArrayEquals(envelope.parentBeaconBlockRoot, state.latestBlockHeader.parentRoot)) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
`Envelope's parent_beacon_block_root mismatch envelope=${toRootHex(envelope.parentBeaconBlockRoot)} state=${toRootHex(state.latestBlockHeader.parentRoot)}`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
46
51
|
|
|
47
52
|
// Verify consistency with the committed bid
|
|
48
53
|
const bid = state.latestExecutionPayloadBid;
|
|
@@ -108,7 +113,7 @@ export function verifyExecutionPayloadEnvelope(
|
|
|
108
113
|
/**
|
|
109
114
|
* Verify the BLS signature of an execution payload envelope.
|
|
110
115
|
*
|
|
111
|
-
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.
|
|
116
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/fork-choice.md#new-verify_execution_payload_envelope_signature
|
|
112
117
|
*/
|
|
113
118
|
export async function verifyExecutionPayloadEnvelopeSignature(
|
|
114
119
|
config: BeaconConfig,
|
package/src/chain/chain.ts
CHANGED
|
@@ -335,15 +335,6 @@ export class BeaconChain implements IBeaconChain {
|
|
|
335
335
|
metrics,
|
|
336
336
|
logger,
|
|
337
337
|
});
|
|
338
|
-
this.seenPayloadEnvelopeInputCache = new SeenPayloadEnvelopeInput({
|
|
339
|
-
config,
|
|
340
|
-
clock,
|
|
341
|
-
chainEvents: emitter,
|
|
342
|
-
signal,
|
|
343
|
-
serializedCache: this.serializedCache,
|
|
344
|
-
metrics,
|
|
345
|
-
logger,
|
|
346
|
-
});
|
|
347
338
|
|
|
348
339
|
this._earliestAvailableSlot = anchorState.slot;
|
|
349
340
|
|
|
@@ -423,6 +414,18 @@ export class BeaconChain implements IBeaconChain {
|
|
|
423
414
|
this.payloadEnvelopeProcessor = new PayloadEnvelopeProcessor(this, metrics, signal);
|
|
424
415
|
|
|
425
416
|
this.forkChoice = forkChoice;
|
|
417
|
+
|
|
418
|
+
this.seenPayloadEnvelopeInputCache = new SeenPayloadEnvelopeInput({
|
|
419
|
+
config,
|
|
420
|
+
clock,
|
|
421
|
+
forkChoice,
|
|
422
|
+
chainEvents: emitter,
|
|
423
|
+
signal,
|
|
424
|
+
serializedCache: this.serializedCache,
|
|
425
|
+
metrics,
|
|
426
|
+
logger,
|
|
427
|
+
});
|
|
428
|
+
|
|
426
429
|
this.clock = clock;
|
|
427
430
|
this.regen = regen;
|
|
428
431
|
this.bls = bls;
|
package/src/chain/emitter.ts
CHANGED
|
@@ -4,7 +4,6 @@ import {routes} from "@lodestar/api";
|
|
|
4
4
|
import {CheckpointWithHex} from "@lodestar/fork-choice";
|
|
5
5
|
import {IBeaconStateView} from "@lodestar/state-transition";
|
|
6
6
|
import {DataColumnSidecar, RootHex, deneb, phase0} from "@lodestar/types";
|
|
7
|
-
import {SignedExecutionPayloadEnvelope} from "@lodestar/types/gloas";
|
|
8
7
|
import {PeerIdStr} from "../util/peerId.js";
|
|
9
8
|
import {BlockInputSource, IBlockInput} from "./blocks/blockInput/types.js";
|
|
10
9
|
import {PayloadEnvelopeInput} from "./blocks/payloadEnvelopeInput/payloadEnvelopeInput.js";
|
|
@@ -60,10 +59,6 @@ export enum ChainEvent {
|
|
|
60
59
|
* Post-gloas, missing parent could be a SignedBeaconBlock and/or a SignedExecutionPayloadEnvelope
|
|
61
60
|
*/
|
|
62
61
|
blockUnknownParent = "blockUnknownParent",
|
|
63
|
-
/**
|
|
64
|
-
* Trigger BlockInputSync to find a SignedBeaconBlock given a SignedExecutionPayloadEnvelop received
|
|
65
|
-
*/
|
|
66
|
-
envelopeUnknownBlock = "envelopeUnknownBlock",
|
|
67
62
|
/**
|
|
68
63
|
* Trigger BlockInputSync to find a SignedBeaconBlock with specified block root.
|
|
69
64
|
*/
|
|
@@ -92,11 +87,6 @@ type ApiEvents = {[K in routes.events.EventType]: (data: routes.events.EventData
|
|
|
92
87
|
|
|
93
88
|
export type ChainEventData = {
|
|
94
89
|
[ChainEvent.blockUnknownParent]: {blockInput: IBlockInput; peer: PeerIdStr; source: BlockInputSource};
|
|
95
|
-
[ChainEvent.envelopeUnknownBlock]: {
|
|
96
|
-
envelope: SignedExecutionPayloadEnvelope;
|
|
97
|
-
peer?: PeerIdStr;
|
|
98
|
-
source: BlockInputSource;
|
|
99
|
-
};
|
|
100
90
|
[ChainEvent.unknownBlockRoot]: {rootHex: RootHex; peer?: PeerIdStr; source: BlockInputSource};
|
|
101
91
|
[ChainEvent.incompleteBlockInput]: {blockInput: IBlockInput; peer: PeerIdStr; source: BlockInputSource};
|
|
102
92
|
[ChainEvent.incompletePayloadEnvelope]: {
|
|
@@ -124,7 +114,6 @@ export type IChainEvents = ApiEvents & {
|
|
|
124
114
|
// Sync events that are chain->chain. Initiated from network requests but do not cross the network
|
|
125
115
|
// barrier so are considered ChainEvent(s).
|
|
126
116
|
[ChainEvent.blockUnknownParent]: (data: ChainEventData[ChainEvent.blockUnknownParent]) => void;
|
|
127
|
-
[ChainEvent.envelopeUnknownBlock]: (data: ChainEventData[ChainEvent.envelopeUnknownBlock]) => void;
|
|
128
117
|
[ChainEvent.unknownBlockRoot]: (data: ChainEventData[ChainEvent.unknownBlockRoot]) => void;
|
|
129
118
|
[ChainEvent.incompleteBlockInput]: (data: ChainEventData[ChainEvent.incompleteBlockInput]) => void;
|
|
130
119
|
[ChainEvent.incompletePayloadEnvelope]: (data: ChainEventData[ChainEvent.incompletePayloadEnvelope]) => void;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {Slot, ValidatorIndex} from "@lodestar/types";
|
|
1
|
+
import {RootHex, Slot, ValidatorIndex} from "@lodestar/types";
|
|
2
2
|
import {GossipActionError} from "./gossipValidation.js";
|
|
3
3
|
|
|
4
4
|
export enum ProposerPreferencesErrorCode {
|
|
5
5
|
INVALID_EPOCH = "PROPOSER_PREFERENCES_ERROR_INVALID_EPOCH",
|
|
6
6
|
PROPOSAL_SLOT_PASSED = "PROPOSER_PREFERENCES_ERROR_PROPOSAL_SLOT_PASSED",
|
|
7
|
+
UNKNOWN_DEPENDENT_ROOT = "PROPOSER_PREFERENCES_ERROR_UNKNOWN_DEPENDENT_ROOT",
|
|
7
8
|
INVALID_PROPOSER = "PROPOSER_PREFERENCES_ERROR_INVALID_PROPOSER",
|
|
8
9
|
ALREADY_KNOWN = "PROPOSER_PREFERENCES_ERROR_ALREADY_KNOWN",
|
|
9
10
|
INVALID_SIGNATURE = "PROPOSER_PREFERENCES_ERROR_INVALID_SIGNATURE",
|
|
@@ -20,15 +21,22 @@ export type ProposerPreferencesErrorType =
|
|
|
20
21
|
proposalSlot: Slot;
|
|
21
22
|
currentSlot: Slot;
|
|
22
23
|
}
|
|
24
|
+
| {
|
|
25
|
+
code: ProposerPreferencesErrorCode.UNKNOWN_DEPENDENT_ROOT;
|
|
26
|
+
proposalSlot: Slot;
|
|
27
|
+
dependentRoot: RootHex;
|
|
28
|
+
}
|
|
23
29
|
| {
|
|
24
30
|
code: ProposerPreferencesErrorCode.INVALID_PROPOSER;
|
|
25
31
|
proposalSlot: Slot;
|
|
26
32
|
validatorIndex: ValidatorIndex;
|
|
33
|
+
dependentRoot: RootHex;
|
|
27
34
|
}
|
|
28
35
|
| {
|
|
29
36
|
code: ProposerPreferencesErrorCode.ALREADY_KNOWN;
|
|
30
37
|
proposalSlot: Slot;
|
|
31
38
|
validatorIndex: ValidatorIndex;
|
|
39
|
+
dependentRoot: RootHex;
|
|
32
40
|
}
|
|
33
41
|
| {
|
|
34
42
|
code: ProposerPreferencesErrorCode.INVALID_SIGNATURE;
|
package/src/chain/initState.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {ZERO_HASH} from "@lodestar/params";
|
|
2
|
+
import {ForkPostGloas, ForkSeq, ZERO_HASH} from "@lodestar/params";
|
|
3
3
|
import {
|
|
4
4
|
BeaconStateAllForks,
|
|
5
|
+
BeaconStateGloas,
|
|
5
6
|
IBeaconStateView,
|
|
6
7
|
computeEpochAtSlot,
|
|
7
8
|
computeStartSlotAtEpoch,
|
|
@@ -52,6 +53,13 @@ export function createGenesisBlock(config: ChainForkConfig, genesisState: Beacon
|
|
|
52
53
|
const genesisBlock = types.SignedBeaconBlock.defaultValue();
|
|
53
54
|
const stateRoot = genesisState.hashTreeRoot();
|
|
54
55
|
genesisBlock.message.stateRoot = stateRoot;
|
|
56
|
+
|
|
57
|
+
if (config.getForkSeq(GENESIS_SLOT) >= ForkSeq.gloas) {
|
|
58
|
+
const gloasBlock = genesisBlock as SignedBeaconBlock<ForkPostGloas>;
|
|
59
|
+
const gloasState = genesisState as BeaconStateGloas;
|
|
60
|
+
gloasBlock.message.body.signedExecutionPayloadBid.message = gloasState.latestExecutionPayloadBid.toValue();
|
|
61
|
+
}
|
|
62
|
+
|
|
55
63
|
return genesisBlock;
|
|
56
64
|
}
|
|
57
65
|
|
|
@@ -4,13 +4,14 @@ import {getSafeExecutionBlockHash} from "@lodestar/fork-choice";
|
|
|
4
4
|
import {ForkPostBellatrix, ForkSeq, SLOTS_PER_EPOCH, isForkPostBellatrix} from "@lodestar/params";
|
|
5
5
|
import {
|
|
6
6
|
IBeaconStateView,
|
|
7
|
+
IBeaconStateViewBellatrix,
|
|
7
8
|
StateHashTreeRootSource,
|
|
8
9
|
computeEpochAtSlot,
|
|
9
10
|
computeTimeAtSlot,
|
|
10
11
|
isStatePostBellatrix,
|
|
11
12
|
isStatePostGloas,
|
|
12
13
|
} from "@lodestar/state-transition";
|
|
13
|
-
import {Bytes32, Slot
|
|
14
|
+
import {Bytes32, Slot} from "@lodestar/types";
|
|
14
15
|
import {Logger, fromHex, isErrorAborted, sleep} from "@lodestar/utils";
|
|
15
16
|
import {GENESIS_SLOT, ZERO_HASH_HEX} from "../constants/constants.js";
|
|
16
17
|
import {BuilderStatus} from "../execution/builder/http.js";
|
|
@@ -165,19 +166,26 @@ export class PrepareNextSlotScheduler {
|
|
|
165
166
|
}
|
|
166
167
|
|
|
167
168
|
let parentBlockHash: Bytes32;
|
|
168
|
-
|
|
169
|
+
// Apply parent payload once here as it's reused by EL prep and SSE emit below
|
|
170
|
+
let stateAfterParentPayload: IBeaconStateViewBellatrix = updatedPrepareState;
|
|
169
171
|
if (isStatePostGloas(updatedPrepareState)) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
172
|
+
if (this.chain.forkChoice.shouldExtendPayload(updatedHead.blockRoot)) {
|
|
173
|
+
parentBlockHash = updatedPrepareState.latestExecutionPayloadBid.blockHash;
|
|
174
|
+
// Skip applying parent payload unless we're proposing the next slot or have to emit payload_attributes events
|
|
175
|
+
if (feeRecipient !== undefined || this.chain.opts.emitPayloadAttributes === true) {
|
|
176
|
+
const parentExecutionRequests = await this.chain.getParentExecutionRequests(
|
|
177
|
+
updatedHead.slot,
|
|
178
|
+
updatedHead.blockRoot
|
|
179
|
+
);
|
|
180
|
+
stateAfterParentPayload = updatedPrepareState.withParentPayloadApplied(parentExecutionRequests);
|
|
181
|
+
}
|
|
182
|
+
} else {
|
|
183
|
+
parentBlockHash = updatedPrepareState.latestExecutionPayloadBid.parentBlockHash;
|
|
184
|
+
}
|
|
174
185
|
} else {
|
|
175
186
|
parentBlockHash = updatedPrepareState.latestExecutionPayloadHeader.blockHash;
|
|
176
187
|
}
|
|
177
188
|
|
|
178
|
-
// Reused by the SSE emit below to avoid a second DB lookup on cache miss
|
|
179
|
-
let parentExecutionRequests: electra.ExecutionRequests | undefined;
|
|
180
|
-
|
|
181
189
|
if (feeRecipient) {
|
|
182
190
|
const preparationTime =
|
|
183
191
|
computeTimeAtSlot(this.config, prepareSlot, this.chain.genesisTime) - Date.now() / 1000;
|
|
@@ -187,13 +195,6 @@ export class PrepareNextSlotScheduler {
|
|
|
187
195
|
const finalizedBlockHash =
|
|
188
196
|
this.chain.forkChoice.getFinalizedBlock().executionPayloadBlockHash ?? ZERO_HASH_HEX;
|
|
189
197
|
|
|
190
|
-
if (isExtendingPayload) {
|
|
191
|
-
parentExecutionRequests = await this.chain.getParentExecutionRequests(
|
|
192
|
-
updatedHead.slot,
|
|
193
|
-
updatedHead.blockRoot
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
198
|
// awaiting here instead of throwing an async call because there is no other task
|
|
198
199
|
// left for scheduler and this gives nice semantics to catch and log errors in the
|
|
199
200
|
// try/catch wrapper here.
|
|
@@ -205,9 +206,8 @@ export class PrepareNextSlotScheduler {
|
|
|
205
206
|
parentBlockHash,
|
|
206
207
|
safeBlockHash,
|
|
207
208
|
finalizedBlockHash,
|
|
208
|
-
|
|
209
|
-
feeRecipient
|
|
210
|
-
parentExecutionRequests
|
|
209
|
+
stateAfterParentPayload,
|
|
210
|
+
feeRecipient
|
|
211
211
|
);
|
|
212
212
|
this.logger.verbose("PrepareNextSlotScheduler prepared new payload", {
|
|
213
213
|
prepareSlot,
|
|
@@ -222,7 +222,7 @@ export class PrepareNextSlotScheduler {
|
|
|
222
222
|
// and head.parent (proposer-boost-reorg fallback). Anything older is evicted.
|
|
223
223
|
const updatedHeadParent = this.chain.forkChoice.getBlockHexDefaultStatus(updatedHead.parentRoot);
|
|
224
224
|
if (updatedHeadParent) {
|
|
225
|
-
this.chain.seenPayloadEnvelopeInputCache.
|
|
225
|
+
this.chain.seenPayloadEnvelopeInputCache.pruneBelowParent(updatedHeadParent);
|
|
226
226
|
}
|
|
227
227
|
}
|
|
228
228
|
|
|
@@ -234,20 +234,12 @@ export class PrepareNextSlotScheduler {
|
|
|
234
234
|
(feeRecipient || this.chain.opts.emitPayloadAttributes === true) &&
|
|
235
235
|
this.chain.emitter.listenerCount(routes.events.EventType.payloadAttributes)
|
|
236
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
|
-
}
|
|
244
237
|
const data = getPayloadAttributesForSSE(fork as ForkPostBellatrix, this.chain, {
|
|
245
|
-
prepareState:
|
|
238
|
+
prepareState: stateAfterParentPayload,
|
|
246
239
|
prepareSlot,
|
|
247
240
|
parentBlockRoot: fromHex(updatedHead.blockRoot),
|
|
248
241
|
parentBlockHash,
|
|
249
242
|
feeRecipient: feeRecipient ?? "0x0000000000000000000000000000000000000000",
|
|
250
|
-
parentExecutionRequests,
|
|
251
243
|
});
|
|
252
244
|
this.chain.emitter.emit(routes.events.EventType.payloadAttributes, {data, version: fork});
|
|
253
245
|
}
|