@lodestar/beacon-node 1.42.0-dev.83dedda569 → 1.42.0-dev.84f3b9f030
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 +13 -1
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +1 -0
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts +3 -3
- package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/getHistoricalState.js +6 -4
- package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts +2 -2
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -0
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/types.d.ts +2 -0
- package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/types.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/worker.js +1 -4
- package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
- package/lib/chain/archiveStore/interface.d.ts +1 -0
- package/lib/chain/archiveStore/interface.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +17 -17
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +10 -8
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +76 -48
- 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 +2 -1
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +20 -14
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +2 -2
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
- package/lib/chain/options.d.ts +1 -0
- 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/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +15 -8
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/package.json +15 -15
- package/src/api/impl/beacon/blocks/index.ts +15 -1
- package/src/chain/archiveStore/archiveStore.ts +1 -0
- package/src/chain/archiveStore/historicalState/getHistoricalState.ts +6 -5
- package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +2 -1
- package/src/chain/archiveStore/historicalState/types.ts +2 -0
- package/src/chain/archiveStore/historicalState/worker.ts +1 -5
- package/src/chain/archiveStore/interface.ts +1 -0
- package/src/chain/blocks/importBlock.ts +18 -17
- package/src/chain/blocks/importExecutionPayload.ts +84 -53
- package/src/chain/blocks/index.ts +2 -1
- package/src/chain/blocks/types.ts +25 -14
- package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +4 -4
- package/src/chain/options.ts +2 -0
- package/src/network/processor/gossipHandlers.ts +16 -8
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
|
-
import {
|
|
2
|
+
import {ExecutionStatus, PayloadExecutionStatus} from "@lodestar/fork-choice";
|
|
3
|
+
import {SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
3
4
|
import {getExecutionPayloadEnvelopeSignatureSet} from "@lodestar/state-transition";
|
|
4
5
|
import {byteArrayEquals, fromHex, toRootHex} from "@lodestar/utils";
|
|
5
6
|
import {ExecutionPayloadStatus} from "../../execution/index.js";
|
|
@@ -51,18 +52,33 @@ export class PayloadError extends Error {
|
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
54
|
|
|
55
|
+
function toForkChoiceExecutionStatus(status: ExecutionPayloadStatus): PayloadExecutionStatus {
|
|
56
|
+
switch (status) {
|
|
57
|
+
case ExecutionPayloadStatus.VALID:
|
|
58
|
+
return ExecutionStatus.Valid;
|
|
59
|
+
// TODO GLOAS: Handle optimistic import for payload
|
|
60
|
+
case ExecutionPayloadStatus.SYNCING:
|
|
61
|
+
case ExecutionPayloadStatus.ACCEPTED:
|
|
62
|
+
return ExecutionStatus.Syncing;
|
|
63
|
+
default:
|
|
64
|
+
throw new Error(`Unexpected execution payload status for fork choice: ${status}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
54
68
|
/**
|
|
55
69
|
* Import an execution payload envelope after all data is available.
|
|
56
70
|
*
|
|
57
71
|
* This function:
|
|
58
|
-
* 1.
|
|
59
|
-
* 2.
|
|
60
|
-
* 3.
|
|
61
|
-
* 4.
|
|
62
|
-
* 5.
|
|
63
|
-
* 6.
|
|
64
|
-
* 7.
|
|
65
|
-
* 8.
|
|
72
|
+
* 1. Emits `execution_payload_available` if payload is for current slot
|
|
73
|
+
* 2. Gets the ProtoBlock from fork choice
|
|
74
|
+
* 3. Applies write-queue backpressure (waitForSpace) early, before verification
|
|
75
|
+
* 4. Regenerates the block state
|
|
76
|
+
* 5. Runs EL verification (notifyNewPayload) in parallel with signature verification and processExecutionPayloadEnvelope
|
|
77
|
+
* 6. Persists verified payload envelope to hot DB
|
|
78
|
+
* 7. Updates fork choice
|
|
79
|
+
* 8. Caches the post-execution payload state
|
|
80
|
+
* 9. Records metrics for column sources
|
|
81
|
+
* 10. Emits `execution_payload` for recent enough payloads after successful import
|
|
66
82
|
*
|
|
67
83
|
*/
|
|
68
84
|
export async function importExecutionPayload(
|
|
@@ -70,10 +86,24 @@ export async function importExecutionPayload(
|
|
|
70
86
|
payloadInput: PayloadEnvelopeInput,
|
|
71
87
|
opts: ImportPayloadOpts = {}
|
|
72
88
|
): Promise<void> {
|
|
73
|
-
const
|
|
89
|
+
const signedEnvelope = payloadInput.getPayloadEnvelope();
|
|
90
|
+
const envelope = signedEnvelope.message;
|
|
74
91
|
const blockRootHex = payloadInput.blockRootHex;
|
|
92
|
+
const blockHashHex = payloadInput.getBlockHashHex();
|
|
93
|
+
const fork = this.config.getForkName(envelope.slot);
|
|
75
94
|
|
|
76
|
-
// 1.
|
|
95
|
+
// 1. Emit `execution_payload_available` event at the start of import. At this point the payload input
|
|
96
|
+
// is already complete, so the payload and required data are available for payload attestation.
|
|
97
|
+
// This event is only about availability, not validity of the execution payload, hence we can emit
|
|
98
|
+
// it before getting a response from the execution client on whether the payload is valid or not.
|
|
99
|
+
if (this.clock.currentSlot === envelope.slot) {
|
|
100
|
+
this.emitter.emit(routes.events.EventType.executionPayloadAvailable, {
|
|
101
|
+
slot: envelope.slot,
|
|
102
|
+
blockRoot: blockRootHex,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// 2. Get ProtoBlock for parent root lookup
|
|
77
107
|
const protoBlock = this.forkChoice.getBlockHexDefaultStatus(blockRootHex);
|
|
78
108
|
if (!protoBlock) {
|
|
79
109
|
throw new PayloadError({
|
|
@@ -82,11 +112,11 @@ export async function importExecutionPayload(
|
|
|
82
112
|
});
|
|
83
113
|
}
|
|
84
114
|
|
|
85
|
-
//
|
|
115
|
+
// 3. Apply backpressure from the write queue early, before doing verification work.
|
|
86
116
|
// The actual DB write is deferred until after verification succeeds.
|
|
87
117
|
await this.unfinalizedPayloadEnvelopeWrites.waitForSpace();
|
|
88
118
|
|
|
89
|
-
//
|
|
119
|
+
// 4. Get pre-state for processExecutionPayloadEnvelope
|
|
90
120
|
// We need the block state (post-block, pre-payload) to process the envelope
|
|
91
121
|
const blockState = await this.regen.getBlockSlotState(
|
|
92
122
|
protoBlock,
|
|
@@ -95,16 +125,16 @@ export async function importExecutionPayload(
|
|
|
95
125
|
RegenCaller.processBlock
|
|
96
126
|
);
|
|
97
127
|
|
|
98
|
-
//
|
|
128
|
+
// 5. Run verification steps in parallel
|
|
99
129
|
// Note: No data availability check needed here - importExecutionPayload is only
|
|
100
130
|
// called when payloadInput.isComplete() is true, so all data is already available.
|
|
101
131
|
const [execResult, signatureValid, postPayloadResult] = await Promise.all([
|
|
102
132
|
this.executionEngine.notifyNewPayload(
|
|
103
|
-
|
|
104
|
-
envelope.
|
|
133
|
+
fork,
|
|
134
|
+
envelope.payload,
|
|
105
135
|
payloadInput.getVersionedHashes(),
|
|
106
136
|
fromHex(protoBlock.parentRoot),
|
|
107
|
-
envelope.
|
|
137
|
+
envelope.executionRequests
|
|
108
138
|
),
|
|
109
139
|
|
|
110
140
|
opts.validSignature === true
|
|
@@ -114,7 +144,7 @@ export async function importExecutionPayload(
|
|
|
114
144
|
this.config,
|
|
115
145
|
this.pubkeyCache,
|
|
116
146
|
blockState,
|
|
117
|
-
|
|
147
|
+
signedEnvelope,
|
|
118
148
|
payloadInput.proposerIndex
|
|
119
149
|
);
|
|
120
150
|
return this.bls.verifySignatureSets([signatureSet]);
|
|
@@ -125,7 +155,7 @@ export async function importExecutionPayload(
|
|
|
125
155
|
(async () => {
|
|
126
156
|
try {
|
|
127
157
|
return {
|
|
128
|
-
postPayloadState: blockState.processExecutionPayloadEnvelope(
|
|
158
|
+
postPayloadState: blockState.processExecutionPayloadEnvelope(signedEnvelope, {
|
|
129
159
|
verifySignature: false,
|
|
130
160
|
verifyStateRoot: false,
|
|
131
161
|
}),
|
|
@@ -142,12 +172,12 @@ export async function importExecutionPayload(
|
|
|
142
172
|
})(),
|
|
143
173
|
]);
|
|
144
174
|
|
|
145
|
-
//
|
|
175
|
+
// 5a. Check signature verification result
|
|
146
176
|
if (!signatureValid) {
|
|
147
177
|
throw new PayloadError({code: PayloadErrorCode.INVALID_SIGNATURE});
|
|
148
178
|
}
|
|
149
179
|
|
|
150
|
-
//
|
|
180
|
+
// 5b. Handle EL response
|
|
151
181
|
switch (execResult.status) {
|
|
152
182
|
case ExecutionPayloadStatus.VALID:
|
|
153
183
|
break;
|
|
@@ -161,12 +191,7 @@ export async function importExecutionPayload(
|
|
|
161
191
|
|
|
162
192
|
case ExecutionPayloadStatus.ACCEPTED:
|
|
163
193
|
case ExecutionPayloadStatus.SYNCING:
|
|
164
|
-
|
|
165
|
-
throw new PayloadError({
|
|
166
|
-
code: PayloadErrorCode.EXECUTION_ENGINE_ERROR,
|
|
167
|
-
execStatus: execResult.status,
|
|
168
|
-
errorMessage: execResult.validationError ?? "EL syncing, payload not yet validated",
|
|
169
|
-
});
|
|
194
|
+
break;
|
|
170
195
|
|
|
171
196
|
case ExecutionPayloadStatus.INVALID_BLOCK_HASH:
|
|
172
197
|
case ExecutionPayloadStatus.ELERROR:
|
|
@@ -178,59 +203,65 @@ export async function importExecutionPayload(
|
|
|
178
203
|
});
|
|
179
204
|
}
|
|
180
205
|
|
|
181
|
-
//
|
|
206
|
+
// 5c. Verify envelope state root matches post-state
|
|
182
207
|
const postPayloadState = postPayloadResult.postPayloadState;
|
|
183
208
|
const postPayloadStateRoot = postPayloadState.hashTreeRoot();
|
|
184
|
-
if (!byteArrayEquals(envelope.
|
|
209
|
+
if (!byteArrayEquals(envelope.stateRoot, postPayloadStateRoot)) {
|
|
185
210
|
throw new PayloadError({
|
|
186
211
|
code: PayloadErrorCode.STATE_TRANSITION_ERROR,
|
|
187
|
-
message: `Envelope state root mismatch expected=${toRootHex(envelope.
|
|
212
|
+
message: `Envelope state root mismatch expected=${toRootHex(envelope.stateRoot)} actual=${toRootHex(postPayloadStateRoot)}`,
|
|
188
213
|
});
|
|
189
214
|
}
|
|
190
215
|
|
|
191
|
-
//
|
|
216
|
+
// 6. Persist payload envelope to hot DB (performed asynchronously to avoid blocking)
|
|
192
217
|
this.unfinalizedPayloadEnvelopeWrites.push(payloadInput).catch((e) => {
|
|
193
218
|
if (!isQueueErrorAborted(e)) {
|
|
194
219
|
this.logger.error(
|
|
195
220
|
"Error pushing payload envelope to unfinalized write queue",
|
|
196
|
-
{slot:
|
|
221
|
+
{slot: envelope.slot, root: blockRootHex},
|
|
197
222
|
e as Error
|
|
198
223
|
);
|
|
199
224
|
}
|
|
200
225
|
});
|
|
201
226
|
|
|
202
|
-
//
|
|
227
|
+
// 7. Update fork choice
|
|
203
228
|
this.forkChoice.onExecutionPayload(
|
|
204
229
|
blockRootHex,
|
|
205
|
-
|
|
206
|
-
envelope.
|
|
207
|
-
toRootHex(postPayloadStateRoot)
|
|
230
|
+
blockHashHex,
|
|
231
|
+
envelope.payload.blockNumber,
|
|
232
|
+
toRootHex(postPayloadStateRoot),
|
|
233
|
+
toForkChoiceExecutionStatus(execResult.status)
|
|
208
234
|
);
|
|
209
235
|
|
|
210
|
-
//
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
236
|
+
// 8. Cache payload state
|
|
237
|
+
this.regen.processPayloadState(postPayloadState);
|
|
238
|
+
if (postPayloadState.slot % SLOTS_PER_EPOCH === 0) {
|
|
239
|
+
const {checkpoint} = postPayloadState.computeAnchorCheckpoint();
|
|
240
|
+
this.regen.addCheckpointState(checkpoint, postPayloadState, true);
|
|
241
|
+
}
|
|
215
242
|
|
|
216
|
-
//
|
|
243
|
+
// 9. Record metrics for payload envelope and column sources
|
|
217
244
|
this.metrics?.importPayload.bySource.inc({source: payloadInput.getPayloadEnvelopeSource().source});
|
|
218
245
|
for (const {source} of payloadInput.getSampledColumnsWithSource()) {
|
|
219
246
|
this.metrics?.importPayload.columnsBySource.inc({source});
|
|
220
247
|
}
|
|
221
248
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
// 9. Emit event after payload is fully verified and imported to fork choice, only for recent enough payloads
|
|
229
|
-
const currentSlot = this.clock.currentSlot;
|
|
230
|
-
if (currentSlot - payloadInput.slot < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
|
|
231
|
-
this.emitter.emit(routes.events.EventType.executionPayloadAvailable, {
|
|
232
|
-
slot: payloadInput.slot,
|
|
249
|
+
// 10. Emit event after payload is fully verified and imported to fork choice, only for recent enough payloads
|
|
250
|
+
if (this.clock.currentSlot - envelope.slot < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
|
|
251
|
+
this.emitter.emit(routes.events.EventType.executionPayload, {
|
|
252
|
+
slot: envelope.slot,
|
|
253
|
+
builderIndex: envelope.builderIndex,
|
|
254
|
+
blockHash: blockHashHex,
|
|
233
255
|
blockRoot: blockRootHex,
|
|
256
|
+
stateRoot: toRootHex(envelope.stateRoot),
|
|
257
|
+
// TODO GLOAS: revisit once we support optimistic import
|
|
258
|
+
executionOptimistic: false,
|
|
234
259
|
});
|
|
235
260
|
}
|
|
261
|
+
|
|
262
|
+
this.logger.verbose("Execution payload imported", {
|
|
263
|
+
slot: envelope.slot,
|
|
264
|
+
root: blockRootHex,
|
|
265
|
+
blockHash: blockHashHex,
|
|
266
|
+
});
|
|
236
267
|
}
|
|
@@ -88,7 +88,8 @@ export async function processBlocks(
|
|
|
88
88
|
const fullyVerifiedBlocks = relevantBlocks.map(
|
|
89
89
|
(block, i): FullyVerifiedBlock => ({
|
|
90
90
|
blockInput: block,
|
|
91
|
-
|
|
91
|
+
postBlockState: postStates[i],
|
|
92
|
+
postEnvelopeState: null,
|
|
92
93
|
parentBlockSlot: parentSlots[i],
|
|
93
94
|
executionStatus: executionStatuses[i],
|
|
94
95
|
// start supporting optimistic syncing/processing
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {
|
|
2
|
+
import {BlockExecutionStatus, PayloadExecutionStatus} from "@lodestar/fork-choice";
|
|
3
3
|
import {ForkSeq} from "@lodestar/params";
|
|
4
4
|
import {DataAvailabilityStatus, IBeaconStateView, computeEpochAtSlot} from "@lodestar/state-transition";
|
|
5
5
|
import type {IndexedAttestation, Slot, fulu} from "@lodestar/types";
|
|
@@ -88,24 +88,35 @@ export type ImportBlockOpts = {
|
|
|
88
88
|
seenTimestampSec?: number;
|
|
89
89
|
};
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
* A wrapper around a `SignedBeaconBlock` that indicates that this block is fully verified and ready to import
|
|
93
|
-
*/
|
|
94
|
-
export type FullyVerifiedBlock = {
|
|
91
|
+
type FullyVerifiedBlockBase = {
|
|
95
92
|
blockInput: IBlockInput;
|
|
96
|
-
|
|
93
|
+
postBlockState: IBeaconStateView;
|
|
97
94
|
parentBlockSlot: Slot;
|
|
98
95
|
proposerBalanceDelta: number;
|
|
99
|
-
/**
|
|
100
|
-
* If the execution payload couldnt be verified because of EL syncing status,
|
|
101
|
-
* used in optimistic sync or for merge block
|
|
102
|
-
*/
|
|
103
|
-
executionStatus: MaybeValidExecutionStatus;
|
|
104
96
|
dataAvailabilityStatus: DataAvailabilityStatus;
|
|
105
|
-
/**
|
|
106
|
-
* Pre-computed indexed attestations from signature verification to avoid duplicate work
|
|
107
|
-
*/
|
|
97
|
+
/** Pre-computed indexed attestations from signature verification to avoid duplicate work */
|
|
108
98
|
indexedAttestations: IndexedAttestation[];
|
|
109
99
|
/** Seen timestamp seconds */
|
|
110
100
|
seenTimestampSec: number;
|
|
111
101
|
};
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* A wrapper around a `SignedBeaconBlock` that indicates that this block is fully verified and ready to import.
|
|
105
|
+
*
|
|
106
|
+
* Discriminated union on `postEnvelopeState`:
|
|
107
|
+
* - `null` → block has no pre-verified envelope; `executionStatus` is any `BlockExecutionStatus`
|
|
108
|
+
* - non-null → envelope was pre-verified during state transition; `executionStatus` is narrowed to
|
|
109
|
+
* `Valid | Syncing` (matching what `forkChoice.onExecutionPayload` expects)
|
|
110
|
+
*/
|
|
111
|
+
export type FullyVerifiedBlock = FullyVerifiedBlockBase &
|
|
112
|
+
(
|
|
113
|
+
| {
|
|
114
|
+
postEnvelopeState: null;
|
|
115
|
+
/** If the execution payload couldn't be verified because of EL syncing status, used in optimistic sync or for merge block */
|
|
116
|
+
executionStatus: BlockExecutionStatus;
|
|
117
|
+
}
|
|
118
|
+
| {
|
|
119
|
+
postEnvelopeState: IBeaconStateView;
|
|
120
|
+
executionStatus: PayloadExecutionStatus;
|
|
121
|
+
}
|
|
122
|
+
);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
2
|
import {
|
|
3
|
+
BlockExecutionStatus,
|
|
3
4
|
ExecutionStatus,
|
|
4
5
|
IForkChoice,
|
|
5
6
|
LVHInvalidResponse,
|
|
6
7
|
LVHValidResponse,
|
|
7
|
-
MaybeValidExecutionStatus,
|
|
8
8
|
ProtoBlock,
|
|
9
9
|
} from "@lodestar/fork-choice";
|
|
10
10
|
import {ForkSeq} from "@lodestar/params";
|
|
@@ -33,7 +33,7 @@ type ExecAbortType = {blockIndex: number; execError: BlockError};
|
|
|
33
33
|
export type SegmentExecStatus =
|
|
34
34
|
| {
|
|
35
35
|
execAborted: null;
|
|
36
|
-
executionStatuses:
|
|
36
|
+
executionStatuses: BlockExecutionStatus[];
|
|
37
37
|
executionTime: number;
|
|
38
38
|
}
|
|
39
39
|
| {execAborted: ExecAbortType; invalidSegmentLVH?: LVHInvalidResponse};
|
|
@@ -62,7 +62,7 @@ export async function verifyBlocksExecutionPayload(
|
|
|
62
62
|
signal: AbortSignal,
|
|
63
63
|
opts: BlockProcessOpts & ImportBlockOpts
|
|
64
64
|
): Promise<SegmentExecStatus> {
|
|
65
|
-
const executionStatuses:
|
|
65
|
+
const executionStatuses: BlockExecutionStatus[] = [];
|
|
66
66
|
const recvToValLatency = Date.now() / 1000 - (opts.seenTimestampSec ?? Date.now() / 1000);
|
|
67
67
|
const lastBlock = blockInputs.at(-1);
|
|
68
68
|
|
|
@@ -103,7 +103,7 @@ export async function verifyBlocksExecutionPayload(
|
|
|
103
103
|
return getSegmentErrorResponse({verifyResponse, blockIndex}, parentBlock, blockInputs);
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
// If we are here then its because executionStatus is one of
|
|
106
|
+
// If we are here then its because executionStatus is one of BlockExecutionStatus
|
|
107
107
|
const {executionStatus} = verifyResponse;
|
|
108
108
|
executionStatuses.push(executionStatus);
|
|
109
109
|
}
|
package/src/chain/options.ts
CHANGED
|
@@ -47,6 +47,7 @@ export type IChainOptions = BlockProcessOpts &
|
|
|
47
47
|
minSameMessageSignatureSetsToBatch: number;
|
|
48
48
|
archiveDateEpochs?: number;
|
|
49
49
|
nHistoricalStatesFileDataStore?: boolean;
|
|
50
|
+
nativeStateView?: boolean;
|
|
50
51
|
};
|
|
51
52
|
|
|
52
53
|
export type BlockProcessOpts = {
|
|
@@ -124,6 +125,7 @@ export const defaultChainOptions: IChainOptions = {
|
|
|
124
125
|
// - users can prune the persisted checkpoint state files manually to save disc space
|
|
125
126
|
// - it helps debug easier when network is unfinalized
|
|
126
127
|
nHistoricalStatesFileDataStore: true,
|
|
128
|
+
nativeStateView: false,
|
|
127
129
|
maxBlockStates: DEFAULT_MAX_BLOCK_STATES,
|
|
128
130
|
maxCPStateEpochsInMemory: DEFAULT_MAX_CP_STATE_EPOCHS_IN_MEMORY,
|
|
129
131
|
maxCPStateEpochsOnDisk: DEFAULT_MAX_CP_STATE_ON_DISK,
|
|
@@ -841,16 +841,17 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
841
841
|
seenTimestampSec,
|
|
842
842
|
}: GossipHandlerParamGeneric<GossipType.execution_payload>) => {
|
|
843
843
|
const {serializedData} = gossipData;
|
|
844
|
-
const
|
|
844
|
+
const signedEnvelope = sszDeserialize(topic, serializedData);
|
|
845
|
+
const envelope = signedEnvelope.message;
|
|
845
846
|
// TODO GLOAS: handle BLOCK_ROOT_UNKNOWN error to trigger sync
|
|
846
|
-
await validateGossipExecutionPayloadEnvelope(chain,
|
|
847
|
+
await validateGossipExecutionPayloadEnvelope(chain, signedEnvelope);
|
|
847
848
|
|
|
848
|
-
const slot =
|
|
849
|
+
const slot = envelope.slot;
|
|
849
850
|
const delaySec = seenTimestampSec - computeTimeAtSlot(config, slot, chain.genesisTime);
|
|
850
851
|
metrics?.gossipExecutionPayloadEnvelope.elapsedTimeTillReceived.observe({source: OpSource.gossip}, delaySec);
|
|
851
|
-
chain.validatorMonitor?.registerExecutionPayloadEnvelope(OpSource.gossip, delaySec,
|
|
852
|
+
chain.validatorMonitor?.registerExecutionPayloadEnvelope(OpSource.gossip, delaySec, signedEnvelope);
|
|
852
853
|
|
|
853
|
-
const blockRootHex = toRootHex(
|
|
854
|
+
const blockRootHex = toRootHex(envelope.beaconBlockRoot);
|
|
854
855
|
const payloadInput = chain.seenPayloadEnvelopeInputCache.get(blockRootHex);
|
|
855
856
|
|
|
856
857
|
if (!payloadInput) {
|
|
@@ -861,16 +862,23 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
861
862
|
});
|
|
862
863
|
}
|
|
863
864
|
|
|
864
|
-
chain.serializedCache.set(
|
|
865
|
+
chain.serializedCache.set(signedEnvelope, serializedData);
|
|
865
866
|
|
|
866
867
|
payloadInput.addPayloadEnvelope({
|
|
867
|
-
envelope:
|
|
868
|
+
envelope: signedEnvelope,
|
|
868
869
|
source: PayloadEnvelopeInputSource.gossip,
|
|
869
870
|
seenTimestampSec,
|
|
870
871
|
peerIdStr,
|
|
871
872
|
});
|
|
872
873
|
|
|
873
|
-
|
|
874
|
+
chain.emitter.emit(routes.events.EventType.executionPayloadGossip, {
|
|
875
|
+
slot,
|
|
876
|
+
builderIndex: envelope.builderIndex,
|
|
877
|
+
blockHash: toRootHex(envelope.payload.blockHash),
|
|
878
|
+
blockRoot: blockRootHex,
|
|
879
|
+
stateRoot: toRootHex(envelope.stateRoot),
|
|
880
|
+
});
|
|
881
|
+
|
|
874
882
|
chain.processExecutionPayload(payloadInput, {validSignature: true}).catch((e) => {
|
|
875
883
|
chain.logger.debug("Error processing execution payload from gossip", {slot, root: blockRootHex}, e as Error);
|
|
876
884
|
});
|