@lodestar/beacon-node 1.43.0-dev.2fba242f5d → 1.43.0-dev.3bcc6d0ad5
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/debug/index.d.ts.map +1 -1
- package/lib/api/impl/debug/index.js +1 -0
- package/lib/api/impl/debug/index.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +2 -14
- 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 -1
- 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 +17 -30
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +1 -2
- 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 +0 -8
- 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 +6 -5
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +4 -0
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +2 -5
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts +1 -2
- package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.js +7 -16
- package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +4 -1
- 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 +4 -1
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/node/nodejs.js +2 -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/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +4 -15
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/package.json +15 -15
- package/src/api/impl/debug/index.ts +1 -0
- package/src/chain/blocks/importBlock.ts +3 -14
- package/src/chain/blocks/importExecutionPayload.ts +3 -1
- package/src/chain/blocks/index.ts +9 -20
- package/src/chain/blocks/types.ts +1 -2
- package/src/chain/blocks/utils/chainSegment.ts +0 -8
- package/src/chain/blocks/verifyBlock.ts +5 -7
- package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +4 -6
- package/src/chain/blocks/verifyBlocksSanityChecks.ts +6 -16
- package/src/chain/regen/queued.ts +7 -2
- package/src/chain/regen/regen.ts +7 -2
- package/src/node/nodejs.ts +2 -2
- package/src/node/notifier.ts +8 -1
- package/src/sync/utils/downloadByRange.ts +3 -15
|
@@ -69,8 +69,8 @@ export async function importBlock(
|
|
|
69
69
|
fullyVerifiedBlock: FullyVerifiedBlock,
|
|
70
70
|
opts: ImportBlockOpts
|
|
71
71
|
): Promise<void> {
|
|
72
|
-
const {blockInput, postState, parentBlockSlot, dataAvailabilityStatus, indexedAttestations} =
|
|
73
|
-
|
|
72
|
+
const {blockInput, postState, parentBlockSlot, executionStatus, dataAvailabilityStatus, indexedAttestations} =
|
|
73
|
+
fullyVerifiedBlock;
|
|
74
74
|
const block = blockInput.getBlock();
|
|
75
75
|
const source = blockInput.getBlockSource();
|
|
76
76
|
const {slot: blockSlot} = block.message;
|
|
@@ -105,23 +105,12 @@ export async function importBlock(
|
|
|
105
105
|
|
|
106
106
|
// Should compute checkpoint balances before forkchoice.onBlock
|
|
107
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
|
-
}
|
|
119
108
|
const blockSummary = this.forkChoice.onBlock(
|
|
120
109
|
block.message,
|
|
121
110
|
postState,
|
|
122
111
|
blockDelaySec,
|
|
123
112
|
currentSlot,
|
|
124
|
-
executionStatus,
|
|
113
|
+
fork >= ForkSeq.gloas ? ExecutionStatus.PayloadSeparated : executionStatus,
|
|
125
114
|
dataAvailabilityStatus
|
|
126
115
|
);
|
|
127
116
|
|
|
@@ -61,6 +61,7 @@ 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
|
|
64
65
|
case ExecutionPayloadStatus.SYNCING:
|
|
65
66
|
case ExecutionPayloadStatus.ACCEPTED:
|
|
66
67
|
return ExecutionStatus.Syncing;
|
|
@@ -254,7 +255,8 @@ export async function importExecutionPayload(
|
|
|
254
255
|
builderIndex: envelope.builderIndex,
|
|
255
256
|
blockHash: blockHashHex,
|
|
256
257
|
blockRoot: blockRootHex,
|
|
257
|
-
|
|
258
|
+
// TODO GLOAS: revisit once we support optimistic import
|
|
259
|
+
executionOptimistic: false,
|
|
258
260
|
});
|
|
259
261
|
}
|
|
260
262
|
|
|
@@ -65,7 +65,7 @@ export async function processBlocks(
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
try {
|
|
68
|
-
const {relevantBlocks, parentSlots, parentBlock} = verifyBlocksSanityChecks(this, blocks,
|
|
68
|
+
const {relevantBlocks, parentSlots, parentBlock} = verifyBlocksSanityChecks(this, blocks, opts);
|
|
69
69
|
|
|
70
70
|
// No relevant blocks, skip verifyBlocksInEpoch()
|
|
71
71
|
if (relevantBlocks.length === 0 || parentBlock === null) {
|
|
@@ -109,10 +109,8 @@ export async function processBlocks(
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
const {executionStatuses} = segmentExecStatus;
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
const block = relevantBlocks[i];
|
|
115
|
-
verifiedBlocksBySlot.set(block.getBlock().message.slot, {
|
|
112
|
+
const fullyVerifiedBlocks = relevantBlocks.map(
|
|
113
|
+
(block, i): FullyVerifiedBlock => ({
|
|
116
114
|
blockInput: block,
|
|
117
115
|
postState: postStates[i],
|
|
118
116
|
parentBlockSlot: parentSlots[i],
|
|
@@ -123,23 +121,14 @@ export async function processBlocks(
|
|
|
123
121
|
indexedAttestations: indexedAttestationsByBlock[i],
|
|
124
122
|
// TODO: Make this param mandatory and capture in gossip
|
|
125
123
|
seenTimestampSec: opts.seenTimestampSec ?? Math.floor(Date.now() / 1000),
|
|
126
|
-
})
|
|
127
|
-
|
|
124
|
+
})
|
|
125
|
+
);
|
|
128
126
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
-
}
|
|
127
|
+
for (const fullyVerifiedBlock of fullyVerifiedBlocks) {
|
|
128
|
+
// TODO: Consider batching importBlock too if it takes significant time
|
|
129
|
+
await importBlock.call(this, fullyVerifiedBlock, opts);
|
|
142
130
|
|
|
131
|
+
const slot = fullyVerifiedBlock.blockInput.getBlock().message.slot;
|
|
143
132
|
const payloadInput = payloadEnvelopes?.get(slot);
|
|
144
133
|
if (payloadInput?.hasPayloadEnvelope()) {
|
|
145
134
|
if (!payloadInput.isComplete()) {
|
|
@@ -94,8 +94,7 @@ 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:
|
|
98
|
-
* separately as an envelope and creates the FULL variant later via onExecutionPayload
|
|
97
|
+
* - post-gloas: PayloadSeparated (payload arrives separately as an envelope and is imported later)
|
|
99
98
|
*/
|
|
100
99
|
export type FullyVerifiedBlock = {
|
|
101
100
|
blockInput: IBlockInput;
|
|
@@ -41,14 +41,6 @@ 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
|
-
}
|
|
52
44
|
// Track the execution hash before the last FULL advancement so we can recover
|
|
53
45
|
// if the next block reveals that envelope was orphaned.
|
|
54
46
|
let prevExecHash: string | null = currentExecHash;
|
|
@@ -125,17 +125,15 @@ export async function verifyBlocksInEpoch(
|
|
|
125
125
|
}> =
|
|
126
126
|
fork >= ForkSeq.gloas
|
|
127
127
|
? (async () => {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
payloadEnvelopes !== null ? Array.from(payloadEnvelopes.values()) : [];
|
|
128
|
+
const payloadInputsForDa: PayloadEnvelopeInput[] = [];
|
|
129
|
+
for (const input of blockInputs) {
|
|
130
|
+
const pi = payloadEnvelopes?.get(input.slot);
|
|
131
|
+
if (pi !== undefined) payloadInputsForDa.push(pi);
|
|
132
|
+
}
|
|
134
133
|
const {dataAvailabilityStatuses, availableTime} = await verifyPayloadsDataAvailability(
|
|
135
134
|
payloadInputsForDa,
|
|
136
135
|
abortController.signal
|
|
137
136
|
);
|
|
138
|
-
|
|
139
137
|
const payloadDAStatuses = new Map<Slot, DataAvailabilityStatus>();
|
|
140
138
|
for (let i = 0; i < payloadInputsForDa.length; i++) {
|
|
141
139
|
payloadDAStatuses.set(payloadInputsForDa[i].slot, dataAvailabilityStatuses[i]);
|
|
@@ -46,7 +46,8 @@ 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}
|
|
49
|
+
| {executionStatus: ExecutionStatus.PreMerge; lvhResponse: undefined; execError: null}
|
|
50
|
+
| {executionStatus: ExecutionStatus.PayloadSeparated; lvhResponse: undefined; execError: null};
|
|
50
51
|
|
|
51
52
|
/**
|
|
52
53
|
* Verifies 1 or more execution payloads from a linear sequence of blocks.
|
|
@@ -144,10 +145,9 @@ export async function verifyBlockExecutionPayload(
|
|
|
144
145
|
): Promise<VerifyBlockExecutionResponse> {
|
|
145
146
|
const block = blockInput.getBlock();
|
|
146
147
|
|
|
147
|
-
// Gloas block doesn't have execution payload. Return
|
|
148
|
-
// status for gloas PENDING/EMPTY is derived from parent's chain in importBlock.
|
|
148
|
+
// Gloas block doesn't have execution payload. Return right away
|
|
149
149
|
if (isBlockInputNoData(blockInput)) {
|
|
150
|
-
return {executionStatus: ExecutionStatus.
|
|
150
|
+
return {executionStatus: ExecutionStatus.PayloadSeparated, lvhResponse: undefined, execError: null};
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
/** Not null if execution is enabled */
|
|
@@ -198,7 +198,6 @@ export async function verifyBlockExecutionPayload(
|
|
|
198
198
|
executionStatus,
|
|
199
199
|
latestValidExecHash: execResult.latestValidHash,
|
|
200
200
|
invalidateFromParentBlockRoot: blockInput.parentRootHex,
|
|
201
|
-
invalidateFromParentBlockHash: toRootHex(executionPayloadEnabled.parentHash),
|
|
202
201
|
};
|
|
203
202
|
const execError = new BlockError(block, {
|
|
204
203
|
code: BlockErrorCode.EXECUTION_ENGINE_ERROR,
|
|
@@ -282,7 +281,6 @@ function getSegmentErrorResponse(
|
|
|
282
281
|
executionStatus: ExecutionStatus.Invalid,
|
|
283
282
|
latestValidExecHash: lvhResponse.latestValidExecHash,
|
|
284
283
|
invalidateFromParentBlockRoot: parentBlock.blockRoot,
|
|
285
|
-
invalidateFromParentBlockHash: parentBlock.executionPayloadBlockHash,
|
|
286
284
|
};
|
|
287
285
|
}
|
|
288
286
|
}
|
|
@@ -7,7 +7,6 @@ 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";
|
|
11
10
|
import {ImportBlockOpts} from "./types.js";
|
|
12
11
|
|
|
13
12
|
/**
|
|
@@ -31,7 +30,6 @@ export function verifyBlocksSanityChecks(
|
|
|
31
30
|
blacklistedBlocks: Map<RootHex, Slot | null>;
|
|
32
31
|
},
|
|
33
32
|
blocks: IBlockInput[],
|
|
34
|
-
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
|
|
35
33
|
opts: ImportBlockOpts
|
|
36
34
|
): {
|
|
37
35
|
relevantBlocks: IBlockInput[];
|
|
@@ -102,21 +100,13 @@ export function verifyBlocksSanityChecks(
|
|
|
102
100
|
const parentBlockHash = toRootHex(block.message.body.signedExecutionPayloadBid.message.parentBlockHash);
|
|
103
101
|
const parentBlockWithPayload = chain.forkChoice.getBlockHexAndBlockHash(parentRoot, parentBlockHash);
|
|
104
102
|
if (!parentBlockWithPayload) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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;
|
|
103
|
+
throw new BlockError(block, {
|
|
104
|
+
code: BlockErrorCode.PARENT_PAYLOAD_UNKNOWN,
|
|
105
|
+
parentRoot,
|
|
106
|
+
parentBlockHash,
|
|
107
|
+
});
|
|
119
108
|
}
|
|
109
|
+
parentBlock = parentBlockWithPayload;
|
|
120
110
|
}
|
|
121
111
|
// Parent is known to the fork-choice
|
|
122
112
|
parentBlockSlot = parentBlock.slot;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
2
|
import {IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
|
|
3
3
|
import {IBeaconStateView, computeEpochAtSlot} from "@lodestar/state-transition";
|
|
4
|
-
import {BeaconBlock, Epoch, RootHex, Slot, phase0} from "@lodestar/types";
|
|
4
|
+
import {BeaconBlock, Epoch, RootHex, Slot, isGloasBeaconBlock, phase0} from "@lodestar/types";
|
|
5
5
|
import {Logger, toRootHex} from "@lodestar/utils";
|
|
6
6
|
import {Metrics} from "../../metrics/index.js";
|
|
7
7
|
import {JobItemQueue} from "../../util/queue/index.js";
|
|
@@ -88,7 +88,12 @@ export class QueuedStateRegenerator implements IStateRegenerator {
|
|
|
88
88
|
*/
|
|
89
89
|
getPreStateSync(block: BeaconBlock): IBeaconStateView | null {
|
|
90
90
|
const parentRoot = toRootHex(block.parentRoot);
|
|
91
|
-
const parentBlock =
|
|
91
|
+
const parentBlock = isGloasBeaconBlock(block)
|
|
92
|
+
? this.forkChoice.getBlockHexAndBlockHash(
|
|
93
|
+
parentRoot,
|
|
94
|
+
toRootHex(block.body.signedExecutionPayloadBid.message.parentBlockHash)
|
|
95
|
+
)
|
|
96
|
+
: this.forkChoice.getBlockHexDefaultStatus(parentRoot);
|
|
92
97
|
if (!parentBlock) {
|
|
93
98
|
throw new RegenError({
|
|
94
99
|
code: RegenErrorCode.BLOCK_NOT_IN_FORKCHOICE,
|
package/src/chain/regen/regen.ts
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
computeEpochAtSlot,
|
|
10
10
|
computeStartSlotAtEpoch,
|
|
11
11
|
} from "@lodestar/state-transition";
|
|
12
|
-
import {BeaconBlock, RootHex, SignedBeaconBlock, Slot} from "@lodestar/types";
|
|
12
|
+
import {BeaconBlock, RootHex, SignedBeaconBlock, Slot, isGloasBeaconBlock} from "@lodestar/types";
|
|
13
13
|
import {Logger, fromHex, toRootHex} from "@lodestar/utils";
|
|
14
14
|
import {IBeaconDb} from "../../db/index.js";
|
|
15
15
|
import {Metrics} from "../../metrics/index.js";
|
|
@@ -57,7 +57,12 @@ export class StateRegenerator implements IStateRegeneratorInternal {
|
|
|
57
57
|
regenCaller: RegenCaller
|
|
58
58
|
): Promise<IBeaconStateView> {
|
|
59
59
|
const parentRoot = toRootHex(block.parentRoot);
|
|
60
|
-
const parentBlock =
|
|
60
|
+
const parentBlock = isGloasBeaconBlock(block)
|
|
61
|
+
? this.modules.forkChoice.getBlockHexAndBlockHash(
|
|
62
|
+
parentRoot,
|
|
63
|
+
toRootHex(block.body.signedExecutionPayloadBid.message.parentBlockHash)
|
|
64
|
+
)
|
|
65
|
+
: this.modules.forkChoice.getBlockHexDefaultStatus(parentRoot);
|
|
61
66
|
if (!parentBlock) {
|
|
62
67
|
throw new RegenError({
|
|
63
68
|
code: RegenErrorCode.BLOCK_NOT_IN_FORKCHOICE,
|
package/src/node/nodejs.ts
CHANGED
|
@@ -221,7 +221,7 @@ export class BeaconNode {
|
|
|
221
221
|
|
|
222
222
|
let executionEngineOpts = opts.executionEngine;
|
|
223
223
|
if (opts.executionEngine.mode === "mock") {
|
|
224
|
-
const
|
|
224
|
+
const eth1BlockHash =
|
|
225
225
|
isStatePostBellatrix(anchorState) && anchorState.isExecutionStateType
|
|
226
226
|
? isStatePostGloas(anchorState)
|
|
227
227
|
? toRootHex(anchorState.latestBlockHash)
|
|
@@ -230,7 +230,7 @@ export class BeaconNode {
|
|
|
230
230
|
executionEngineOpts = {
|
|
231
231
|
...opts.executionEngine,
|
|
232
232
|
genesisBlockHash: ZERO_HASH_HEX,
|
|
233
|
-
eth1BlockHash
|
|
233
|
+
eth1BlockHash,
|
|
234
234
|
genesisTime: anchorState.genesisTime,
|
|
235
235
|
config,
|
|
236
236
|
};
|
package/src/node/notifier.ts
CHANGED
|
@@ -167,7 +167,14 @@ function getHeadExecutionInfo(
|
|
|
167
167
|
return [];
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
|
|
170
|
+
// A PayloadSeparated head is a gloas beacon block imported before its payload envelope
|
|
171
|
+
// arrives, in that case the exec-block row surfaces the inherited parent anchor (from the
|
|
172
|
+
// bid), which is already validated. Normalize to "valid" to avoid leaking internal
|
|
173
|
+
// fork-choice bookkeeping into the log. Once the payload envelope arrives and the FULL
|
|
174
|
+
// variant becomes head, executionStatus is Valid/Syncing naturally.
|
|
175
|
+
// TODO GLOAS: revisit once optimistic sync is implemented
|
|
176
|
+
const executionStatusStr =
|
|
177
|
+
headInfo.executionStatus === ExecutionStatus.PayloadSeparated ? "valid" : headInfo.executionStatus.toLowerCase();
|
|
171
178
|
|
|
172
179
|
// Add execution status to notifier only if head is on/post bellatrix
|
|
173
180
|
if (isStatePostBellatrix(headState) && headState.isExecutionStateType) {
|
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
deneb,
|
|
15
15
|
fulu,
|
|
16
16
|
gloas,
|
|
17
|
-
isGloasBeaconBlock,
|
|
18
17
|
isGloasDataColumnSidecar,
|
|
19
18
|
phase0,
|
|
20
19
|
} from "@lodestar/types";
|
|
@@ -362,7 +361,7 @@ export async function requestByRange({
|
|
|
362
361
|
let blocks: undefined | SignedBeaconBlock[];
|
|
363
362
|
let blobSidecars: undefined | deneb.BlobSidecars;
|
|
364
363
|
let columnSidecars: undefined | DataColumnSidecar[];
|
|
365
|
-
|
|
364
|
+
let payloadEnvelopes: undefined | gloas.SignedExecutionPayloadEnvelope[];
|
|
366
365
|
|
|
367
366
|
const requests: Promise<unknown>[] = [];
|
|
368
367
|
|
|
@@ -370,17 +369,6 @@ export async function requestByRange({
|
|
|
370
369
|
requests.push(
|
|
371
370
|
network.sendBeaconBlocksByRange(peerIdStr, blocksRequest).then((blockResponse) => {
|
|
372
371
|
blocks = blockResponse;
|
|
373
|
-
const firstBlock = blockResponse.at(0);
|
|
374
|
-
if (firstBlock && isGloasBeaconBlock(firstBlock.message)) {
|
|
375
|
-
return network
|
|
376
|
-
.sendExecutionPayloadEnvelopesByRoot(peerIdStr, [
|
|
377
|
-
firstBlock.message.body.signedExecutionPayloadBid.message.parentBlockRoot,
|
|
378
|
-
])
|
|
379
|
-
.then((envelopeResponse) => {
|
|
380
|
-
payloadEnvelopes?.unshift(...envelopeResponse);
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
return undefined;
|
|
384
372
|
})
|
|
385
373
|
);
|
|
386
374
|
}
|
|
@@ -404,7 +392,7 @@ export async function requestByRange({
|
|
|
404
392
|
if (envelopesRequest) {
|
|
405
393
|
requests.push(
|
|
406
394
|
network.sendExecutionPayloadEnvelopesByRange(peerIdStr, envelopesRequest).then((envelopeResponse) => {
|
|
407
|
-
payloadEnvelopes
|
|
395
|
+
payloadEnvelopes = envelopeResponse;
|
|
408
396
|
})
|
|
409
397
|
);
|
|
410
398
|
}
|
|
@@ -1191,7 +1179,7 @@ export function validateEnvelopesByRangeResponse(
|
|
|
1191
1179
|
const slot = payloadEnvelope.message.payload.slotNumber;
|
|
1192
1180
|
const batchBlockRoot = batchBlockRoots.get(slot);
|
|
1193
1181
|
|
|
1194
|
-
// Envelopes for slots not in the batch are silently ignored (orphaned payloads
|
|
1182
|
+
// Envelopes for slots not in the batch are silently ignored (orphaned payloads)
|
|
1195
1183
|
if (batchBlockRoot === undefined) {
|
|
1196
1184
|
continue;
|
|
1197
1185
|
}
|