@lodestar/beacon-node 1.44.0-dev.6ef8199cfa → 1.44.0-dev.b506aab66d

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.
Files changed (59) hide show
  1. package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/pool/index.js +1 -1
  3. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  4. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  5. package/lib/chain/blocks/importBlock.js +1 -1
  6. package/lib/chain/blocks/importBlock.js.map +1 -1
  7. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  8. package/lib/chain/blocks/importExecutionPayload.js +4 -2
  9. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  10. package/lib/chain/errors/executionPayloadBid.d.ts +6 -1
  11. package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
  12. package/lib/chain/errors/executionPayloadBid.js +1 -0
  13. package/lib/chain/errors/executionPayloadBid.js.map +1 -1
  14. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  15. package/lib/chain/forkChoice/index.js +14 -4
  16. package/lib/chain/forkChoice/index.js.map +1 -1
  17. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  18. package/lib/chain/prepareNextSlot.js +2 -1
  19. package/lib/chain/prepareNextSlot.js.map +1 -1
  20. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  21. package/lib/chain/produceBlock/produceBlockBody.js +25 -11
  22. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  23. package/lib/chain/validation/executionPayloadBid.d.ts +7 -3
  24. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  25. package/lib/chain/validation/executionPayloadBid.js +24 -8
  26. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  27. package/lib/chain/validatorMonitor.d.ts +1 -0
  28. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  29. package/lib/chain/validatorMonitor.js +16 -0
  30. package/lib/chain/validatorMonitor.js.map +1 -1
  31. package/lib/execution/builder/index.d.ts +1 -2
  32. package/lib/execution/builder/index.d.ts.map +1 -1
  33. package/lib/execution/builder/index.js +0 -1
  34. package/lib/execution/builder/index.js.map +1 -1
  35. package/lib/metrics/metrics/lodestar.d.ts +1 -1
  36. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  37. package/lib/metrics/metrics/lodestar.js +4 -3
  38. package/lib/metrics/metrics/lodestar.js.map +1 -1
  39. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  40. package/lib/network/processor/gossipHandlers.js +11 -3
  41. package/lib/network/processor/gossipHandlers.js.map +1 -1
  42. package/package.json +14 -14
  43. package/src/api/impl/beacon/pool/index.ts +2 -1
  44. package/src/chain/blocks/importBlock.ts +2 -1
  45. package/src/chain/blocks/importExecutionPayload.ts +7 -1
  46. package/src/chain/errors/executionPayloadBid.ts +4 -1
  47. package/src/chain/forkChoice/index.ts +14 -4
  48. package/src/chain/prepareNextSlot.ts +2 -1
  49. package/src/chain/produceBlock/produceBlockBody.ts +31 -19
  50. package/src/chain/validation/executionPayloadBid.ts +30 -12
  51. package/src/chain/validatorMonitor.ts +18 -0
  52. package/src/execution/builder/index.ts +1 -4
  53. package/src/metrics/metrics/lodestar.ts +4 -3
  54. package/src/network/processor/gossipHandlers.ts +15 -3
  55. package/lib/execution/builder/utils.d.ts +0 -5
  56. package/lib/execution/builder/utils.d.ts.map +0 -1
  57. package/lib/execution/builder/utils.js +0 -17
  58. package/lib/execution/builder/utils.js.map +0 -1
  59. package/src/execution/builder/utils.ts +0 -19
@@ -140,9 +140,11 @@ export function initializeForkChoiceFromFinalizedState(
140
140
  executionPayloadBlockHash: isStatePostGloas(state)
141
141
  ? toRootHex(state.latestBlockHash)
142
142
  : toRootHex(state.latestExecutionPayloadHeader.blockHash),
143
- // TODO GLOAS: executionPayloadNumber is not tracked in BeaconState post-gloas (EIP-7732 removed
144
- // latestExecutionPayloadHeader). Using 0 as unavailable fallback until a solution is found.
143
+ // TODO GLOAS: executionPayloadNumber/GasLimit are not tracked in BeaconState post-gloas
144
+ // (EIP-7732 removed latestExecutionPayloadHeader). Using 0 as unavailable fallback
145
+ // see initializeForkChoiceFromUnfinalizedState for the same caveat on validation.
145
146
  executionPayloadNumber: isStatePostGloas(state) ? 0 : state.payloadBlockNumber,
147
+ executionPayloadGasLimit: isStatePostGloas(state) ? 0 : state.latestExecutionPayloadHeader.gasLimit,
146
148
  executionStatus: blockHeader.slot === GENESIS_SLOT ? ExecutionStatus.Valid : ExecutionStatus.Syncing,
147
149
  }
148
150
  : {executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}),
@@ -232,9 +234,17 @@ export function initializeForkChoiceFromUnfinalizedState(
232
234
  executionPayloadBlockHash: isStatePostGloas(unfinalizedState)
233
235
  ? toRootHex(unfinalizedState.latestBlockHash)
234
236
  : toRootHex(unfinalizedState.latestExecutionPayloadHeader.blockHash),
235
- // TODO GLOAS: executionPayloadNumber is not tracked in BeaconState post-gloas (EIP-7732 removed
236
- // latestExecutionPayloadHeader). Using 0 as unavailable fallback until a solution is found.
237
+ // TODO GLOAS: executionPayloadNumber/GasLimit are not tracked in BeaconState post-gloas
238
+ // (EIP-7732 removed latestExecutionPayloadHeader). Using 0 as unavailable fallback until
239
+ // a solution is found. The 0 doesn't gate validation in practice: at boot the head's
240
+ // PENDING variant's `executionPayloadBlockHash` is the *parent's* payload hash (per the
241
+ // PENDING/EMPTY convention), so gossip bids that reference the head's *own* payload
242
+ // hash won't match this variant anyway and will IGNORE until `onExecutionPayload`
243
+ // upgrades the head to FULL with real values.
237
244
  executionPayloadNumber: isStatePostGloas(unfinalizedState) ? 0 : unfinalizedState.payloadBlockNumber,
245
+ executionPayloadGasLimit: isStatePostGloas(unfinalizedState)
246
+ ? 0
247
+ : unfinalizedState.latestExecutionPayloadHeader.gasLimit,
238
248
  executionStatus: blockHeader.slot === GENESIS_SLOT ? ExecutionStatus.Valid : ExecutionStatus.Syncing,
239
249
  }
240
250
  : {executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}),
@@ -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
- if (this.chain.forkChoice.shouldExtendPayload(updatedHead.blockRoot)) {
172
+ // Spec: should_build_on_full(store, head) — see produceBlockBody.ts for context.
173
+ if (this.chain.forkChoice.shouldBuildOnFull(updatedHead)) {
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) {
@@ -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,
@@ -53,13 +53,7 @@ import {
53
53
  import {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";
@@ -226,8 +220,11 @@ export async function produceBlockBody<T extends BlockType>(
226
220
  let parentExecutionRequests: electra.ExecutionRequests;
227
221
  // Apply parent payload once here as it's reused by EL prep and voluntary exit filtering below
228
222
  let stateAfterParentPayload: IBeaconStateViewBellatrix = currentState;
229
- const isExtendingPayload = this.forkChoice.shouldExtendPayload(toRootHex(parentBlockRoot));
230
- if (isExtendingPayload) {
223
+ // Spec: should_build_on_full(store, head). `parentBlock` is the proposer's head
224
+ // (set by chain.getProposerHead(slot)). Returns false when the PTC majority
225
+ // signalled the blob data is not available, forcing a build on EMPTY (reorg).
226
+ const isBuildingOnFull = this.forkChoice.shouldBuildOnFull(parentBlock);
227
+ if (isBuildingOnFull) {
231
228
  parentBlockHash = currentState.latestExecutionPayloadBid.blockHash;
232
229
  parentExecutionRequests = await this.getParentExecutionRequests(parentBlock.slot, parentBlock.blockRoot);
233
230
  stateAfterParentPayload = currentState.withParentPayloadApplied(parentExecutionRequests);
@@ -306,7 +303,7 @@ export async function produceBlockBody<T extends BlockType>(
306
303
  // Drop voluntary exits that parent_execution_requests have invalidated (e.g. a withdrawal
307
304
  // request initiating an exit on the same validator). Op pool selected against the unapplied
308
305
  // state, so re-validate against the post-apply state to avoid producing an invalid block.
309
- if (isExtendingPayload && commonBlockBody.voluntaryExits.length > 0) {
306
+ if (isBuildingOnFull && commonBlockBody.voluntaryExits.length > 0) {
310
307
  gloasBody.voluntaryExits = commonBlockBody.voluntaryExits.filter((signedVoluntaryExit) =>
311
308
  stateAfterParentPayload.isValidVoluntaryExit(signedVoluntaryExit, false)
312
309
  );
@@ -331,6 +328,7 @@ export async function produceBlockBody<T extends BlockType>(
331
328
  fetchedTime,
332
329
  executionBlockHash: toRootHex(executionPayload.blockHash),
333
330
  blobs: blobsBundle.commitments.length,
331
+ gasLimit: executionPayload.gasLimit,
334
332
  });
335
333
 
336
334
  Object.assign(logMeta, {
@@ -869,9 +867,9 @@ function preparePayloadAttributes(
869
867
  (payloadAttributes as gloas.SSEPayloadAttributes["payloadAttributes"]).slotNumber = prepareSlot;
870
868
  (payloadAttributes as gloas.SSEPayloadAttributes["payloadAttributes"]).targetGasLimit = getProposerTargetGasLimit(
871
869
  chain,
872
- prepareState,
873
870
  prepareSlot,
874
- parentBlockRoot
871
+ parentBlockRoot,
872
+ parentBlockHash
875
873
  );
876
874
  }
877
875
 
@@ -886,14 +884,20 @@ function preparePayloadAttributes(
886
884
  * (same `(slot, dependent_root)` lookup as gossip bid validation). When no matching
887
885
  * preferences are pooled, target the parent payload's gas limit so the gas limit stays
888
886
  * unchanged (`is_gas_limit_target_compatible` then requires `gas_limit == parent_gas_limit`).
887
+ *
888
+ * The parent payload's gas_limit is read from fork choice — the variant matching
889
+ * `(parentBlockRoot, parentBlockHash)` carries the correct value for both FULL parents
890
+ * (FULL.executionPayloadGasLimit = delivered payload's gas_limit) and EMPTY parents
891
+ * (EMPTY.executionPayloadGasLimit = inherited grandparent's gas_limit).
889
892
  */
890
893
  function getProposerTargetGasLimit(
891
894
  chain: {forkChoice: IForkChoice; proposerPreferencesPool: ProposerPreferencesPool},
892
- state: IBeaconStateViewGloas,
893
895
  prepareSlot: Slot,
894
- parentBlockRoot: Root
896
+ parentBlockRoot: Root,
897
+ parentBlockHash: Bytes32
895
898
  ): number {
896
- const parentBlock = chain.forkChoice.getBlockHexDefaultStatus(toRootHex(parentBlockRoot));
899
+ const parentBlockRootHex = toRootHex(parentBlockRoot);
900
+ const parentBlock = chain.forkChoice.getBlockHexDefaultStatus(parentBlockRootHex);
897
901
  const dependentRootHex = (() => {
898
902
  if (parentBlock === null) {
899
903
  return null;
@@ -911,9 +915,17 @@ function getProposerTargetGasLimit(
911
915
  })();
912
916
 
913
917
  const pref = dependentRootHex !== null ? chain.proposerPreferencesPool.get(prepareSlot, dependentRootHex) : null;
914
- // TODO GLOAS: state.latestExecutionPayloadBid is the latest *bid*, not the latest *executed*
915
- // payload — for EMPTY parents this drifts. Consider having a default value like Prysm's DefaultBuilderGasLimit.
916
- return Number(pref ? pref.message.targetGasLimit : state.latestExecutionPayloadBid.gasLimit);
918
+ if (pref !== null) {
919
+ return pref.message.targetGasLimit;
920
+ }
921
+
922
+ const parentPayloadVariant = chain.forkChoice.getBlockHexAndBlockHash(parentBlockRootHex, toRootHex(parentBlockHash));
923
+ if (parentPayloadVariant === null || parentPayloadVariant.executionPayloadBlockHash === null) {
924
+ throw new Error(
925
+ `Cannot resolve parent payload gas_limit for proposer targetGasLimit fallback parentBlockRoot=${parentBlockRootHex} parentBlockHash=${toRootHex(parentBlockHash)}`
926
+ );
927
+ }
928
+ return parentPayloadVariant.executionPayloadGasLimit;
917
929
  }
918
930
 
919
931
  export async function produceCommonBlockBody<T extends BlockType>(
@@ -4,9 +4,10 @@ import {
4
4
  createSingleSignatureSetFromComponents,
5
5
  getExecutionPayloadBidSigningRoot,
6
6
  isActiveBuilder,
7
+ isGasLimitTargetCompatible,
7
8
  isStatePostGloas,
8
9
  } from "@lodestar/state-transition";
9
- import {gloas} from "@lodestar/types";
10
+ import {ValidatorIndex, gloas} from "@lodestar/types";
10
11
  import {byteArrayEquals, toHex, toRootHex} from "@lodestar/utils";
11
12
  import {getShufflingDependentRoot} from "../../util/dependentRoot.js";
12
13
  import {ExecutionPayloadBidError, ExecutionPayloadBidErrorCode, GossipAction} from "../errors/index.js";
@@ -16,21 +17,21 @@ import {RegenCaller} from "../regen/index.js";
16
17
  export async function validateApiExecutionPayloadBid(
17
18
  chain: IBeaconChain,
18
19
  signedExecutionPayloadBid: gloas.SignedExecutionPayloadBid
19
- ): Promise<void> {
20
+ ): Promise<{proposerIndex: ValidatorIndex}> {
20
21
  return validateExecutionPayloadBid(chain, signedExecutionPayloadBid);
21
22
  }
22
23
 
23
24
  export async function validateGossipExecutionPayloadBid(
24
25
  chain: IBeaconChain,
25
26
  signedExecutionPayloadBid: gloas.SignedExecutionPayloadBid
26
- ): Promise<void> {
27
+ ): Promise<{proposerIndex: ValidatorIndex}> {
27
28
  return validateExecutionPayloadBid(chain, signedExecutionPayloadBid);
28
29
  }
29
30
 
30
31
  async function validateExecutionPayloadBid(
31
32
  chain: IBeaconChain,
32
33
  signedExecutionPayloadBid: gloas.SignedExecutionPayloadBid
33
- ): Promise<void> {
34
+ ): Promise<{proposerIndex: ValidatorIndex}> {
34
35
  const bid = signedExecutionPayloadBid.message;
35
36
  const parentBlockRootHex = toRootHex(bid.parentBlockRoot);
36
37
  const parentBlockHashHex = toRootHex(bid.parentBlockHash);
@@ -128,14 +129,33 @@ async function validateExecutionPayloadBid(
128
129
  });
129
130
  }
130
131
 
131
- // [REJECT] `bid.gas_limit == proposer_preferences.target_gas_limit`.
132
+ // [IGNORE] `bid.parent_block_hash` is the block hash of a known execution payload in fork
133
+ // choice. Looks up the variant of `bid.parent_block_root` whose payload hash matches
134
+ // `bid.parent_block_hash` — works for both FULL parents (FULL variant carries the delivered
135
+ // payload's hash) and EMPTY parents (EMPTY/PENDING variants carry the inherited parent
136
+ // payload's hash, since the new block doesn't have its own payload). Variant carries the
137
+ // executed payload's gas_limit, which we use as `parent_gas_limit` below.
138
+ const parentPayloadVariant = chain.forkChoice.getBlockHexAndBlockHash(parentBlockRootHex, parentBlockHashHex);
139
+ if (parentPayloadVariant === null || parentPayloadVariant.executionPayloadBlockHash === null) {
140
+ throw new ExecutionPayloadBidError(GossipAction.IGNORE, {
141
+ code: ExecutionPayloadBidErrorCode.UNKNOWN_PARENT_BLOCK_HASH,
142
+ parentBlockHash: parentBlockHashHex,
143
+ });
144
+ }
145
+
146
+ // [IGNORE] `is_gas_limit_target_compatible(parent_gas_limit, bid.gas_limit, target_gas_limit)`,
147
+ // where `parent_gas_limit` is the `gas_limit` of the parent execution payload and
148
+ // `target_gas_limit` is `proposer_preferences.target_gas_limit`.
132
149
  const bidGasLimit = Number(bid.gasLimit);
133
- if (bidGasLimit !== proposerPreferences.message.targetGasLimit) {
134
- throw new ExecutionPayloadBidError(GossipAction.REJECT, {
150
+ const parentGasLimit = parentPayloadVariant.executionPayloadGasLimit;
151
+ const targetGasLimit = proposerPreferences.message.targetGasLimit;
152
+ if (!isGasLimitTargetCompatible(parentGasLimit, bidGasLimit, targetGasLimit)) {
153
+ throw new ExecutionPayloadBidError(GossipAction.IGNORE, {
135
154
  code: ExecutionPayloadBidErrorCode.PROPOSER_PREFERENCES_GAS_LIMIT_MISMATCH,
136
155
  builderIndex: bid.builderIndex,
137
156
  bidGasLimit,
138
- expectedGasLimit: proposerPreferences.message.targetGasLimit,
157
+ parentGasLimit,
158
+ targetGasLimit,
139
159
  });
140
160
  }
141
161
 
@@ -183,10 +203,6 @@ async function validateExecutionPayloadBid(
183
203
  });
184
204
  }
185
205
 
186
- // [IGNORE] `bid.parent_block_hash` is the block hash of a known execution
187
- // payload in fork choice.
188
- // TODO GLOAS: implement this
189
-
190
206
  // [REJECT] `signed_execution_payload_bid.signature` is valid with respect to the `bid.builder_index`.
191
207
  const signatureSet = createSingleSignatureSetFromComponents(
192
208
  PublicKey.fromBytes(builder.pubkey),
@@ -204,4 +220,6 @@ async function validateExecutionPayloadBid(
204
220
 
205
221
  // Valid
206
222
  chain.seenExecutionPayloadBids.add(bid.slot, bid.builderIndex);
223
+
224
+ return {proposerIndex: proposerPreferences.message.validatorIndex};
207
225
  }
@@ -66,6 +66,7 @@ export type ValidatorMonitor = {
66
66
  delaySec: Seconds,
67
67
  envelope: gloas.SignedExecutionPayloadEnvelope
68
68
  ): void;
69
+ registerExecutionPayloadBid(src: OpSource, proposerIndex: ValidatorIndex, bid: gloas.ExecutionPayloadBid): void;
69
70
  registerImportedBlock(block: BeaconBlock, data: {proposerBalanceDelta: number}): void;
70
71
  onPoolSubmitUnaggregatedAttestation(
71
72
  seenTimestampSec: number,
@@ -459,6 +460,23 @@ export function createValidatorMonitor(
459
460
  // TODO GLOAS: implement execution payload envelope monitoring
460
461
  },
461
462
 
463
+ registerExecutionPayloadBid(src, proposerIndex, bid) {
464
+ if (!validators.has(proposerIndex)) {
465
+ return;
466
+ }
467
+ log("Received an execution payload bid for monitored proposer", {
468
+ slot: bid.slot,
469
+ proposerIndex,
470
+ src,
471
+ builderIndex: bid.builderIndex,
472
+ gasLimit: bid.gasLimit,
473
+ value: bid.value.toString(),
474
+ parentBlockRoot: toRootHex(bid.parentBlockRoot),
475
+ parentBlockHash: toRootHex(bid.parentBlockHash),
476
+ blockHash: toRootHex(bid.blockHash),
477
+ });
478
+ },
479
+
462
480
  registerImportedBlock(block, {proposerBalanceDelta}) {
463
481
  const validator = validators.get(block.proposerIndex);
464
482
  if (validator) {
@@ -1,11 +1,8 @@
1
1
  import {ChainForkConfig} from "@lodestar/config";
2
2
  import {Logger} from "@lodestar/logger";
3
3
  import {Metrics} from "../../metrics/metrics.js";
4
- import {IExecutionBuilder} from "./interface.js";
5
-
6
- export {getExpectedGasLimit} from "./utils.js";
7
-
8
4
  import {ExecutionBuilderHttp, ExecutionBuilderHttpOpts, defaultExecutionBuilderHttpOpts} from "./http.js";
5
+ import {IExecutionBuilder} from "./interface.js";
9
6
 
10
7
  export {ExecutionBuilderHttp, defaultExecutionBuilderHttpOpts};
11
8
 
@@ -987,10 +987,11 @@ export function createLodestarMetrics(
987
987
  }),
988
988
  },
989
989
  importPayload: {
990
- bySource: register.gauge<{source: PayloadEnvelopeInputSource}>({
991
- name: "lodestar_import_payload_by_source_total",
992
- help: "Total number of imported execution payload envelopes by source",
990
+ elapsedTimeTillImported: register.histogram<{source: PayloadEnvelopeInputSource}>({
991
+ name: "lodestar_import_payload_elapsed_time_till_imported_seconds",
992
+ help: "Time elapsed between slot time and the time execution payload envelope is imported (added to fork choice)",
993
993
  labelNames: ["source"],
994
+ buckets: [1, 2, 3, 6, 9, 12],
994
995
  }),
995
996
  columnsBySource: register.gauge<{source: PayloadEnvelopeInputSource}>({
996
997
  name: "lodestar_import_payload_columns_by_source_total",
@@ -1117,7 +1117,16 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
1117
1117
  }
1118
1118
 
1119
1119
  const slot = envelope.payload.slotNumber;
1120
- const delaySec = seenTimestampSec - computeTimeAtSlot(config, slot, chain.genesisTime);
1120
+ const delaySec = chain.clock.secFromSlot(slot, seenTimestampSec);
1121
+
1122
+ logger.debug("Received gossip payload envelope", {
1123
+ currentSlot: chain.clock.currentSlot,
1124
+ peerId: peerIdStr,
1125
+ slot,
1126
+ blockRoot: toRootHex(envelope.beaconBlockRoot),
1127
+ delaySec,
1128
+ });
1129
+
1121
1130
  metrics?.gossipExecutionPayloadEnvelope.elapsedTimeTillReceived.observe({source: OpSource.gossip}, delaySec);
1122
1131
  chain.validatorMonitor?.registerExecutionPayloadEnvelope(OpSource.gossip, delaySec, signedEnvelope);
1123
1132
 
@@ -1206,7 +1215,8 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
1206
1215
  chain.forkChoice.notifyPtcMessages(
1207
1216
  toRootHex(payloadAttestationMessage.data.beaconBlockRoot),
1208
1217
  validationResult.validatorCommitteeIndices,
1209
- payloadAttestationMessage.data.payloadPresent
1218
+ payloadAttestationMessage.data.payloadPresent,
1219
+ payloadAttestationMessage.data.blobDataAvailable
1210
1220
  );
1211
1221
  },
1212
1222
  [GossipType.execution_payload_bid]: async ({
@@ -1215,7 +1225,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
1215
1225
  }: GossipHandlerParamGeneric<GossipType.execution_payload_bid>) => {
1216
1226
  const {serializedData} = gossipData;
1217
1227
  const executionPayloadBid = sszDeserialize(topic, serializedData);
1218
- await validateGossipExecutionPayloadBid(chain, executionPayloadBid);
1228
+ const {proposerIndex} = await validateGossipExecutionPayloadBid(chain, executionPayloadBid);
1219
1229
 
1220
1230
  // Handle valid payload bid by storing in a bid pool
1221
1231
  try {
@@ -1225,6 +1235,8 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
1225
1235
  logger.error("Error adding to executionPayloadBid pool", {}, e as Error);
1226
1236
  }
1227
1237
 
1238
+ chain.validatorMonitor?.registerExecutionPayloadBid(OpSource.gossip, proposerIndex, executionPayloadBid.message);
1239
+
1228
1240
  chain.emitter.emit(routes.events.EventType.executionPayloadBid, {
1229
1241
  version: config.getForkName(executionPayloadBid.message.slot),
1230
1242
  data: executionPayloadBid,
@@ -1,5 +0,0 @@
1
- /**
2
- * Calculates expected gas limit based on parent gas limit and target gas limit
3
- */
4
- export declare function getExpectedGasLimit(parentGasLimit: number, targetGasLimit: number): number;
5
- //# sourceMappingURL=utils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/execution/builder/utils.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAU1F"}
@@ -1,17 +0,0 @@
1
- /**
2
- * From https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md
3
- */
4
- const gasLimitAdjustmentFactor = 1024;
5
- /**
6
- * Calculates expected gas limit based on parent gas limit and target gas limit
7
- */
8
- export function getExpectedGasLimit(parentGasLimit, targetGasLimit) {
9
- const maxGasLimitDifference = Math.max(Math.floor(parentGasLimit / gasLimitAdjustmentFactor) - 1, 0);
10
- if (targetGasLimit > parentGasLimit) {
11
- const gasDiff = targetGasLimit - parentGasLimit;
12
- return parentGasLimit + Math.min(gasDiff, maxGasLimitDifference);
13
- }
14
- const gasDiff = parentGasLimit - targetGasLimit;
15
- return parentGasLimit - Math.min(gasDiff, maxGasLimitDifference);
16
- }
17
- //# sourceMappingURL=utils.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/execution/builder/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,wBAAwB,GAAG,IAAI,CAAC;AAEtC;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,cAAsB,EAAE,cAAsB,EAAU;IAC1F,MAAM,qBAAqB,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,GAAG,wBAAwB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAErG,IAAI,cAAc,GAAG,cAAc,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,cAAc,GAAG,cAAc,CAAC;QAChD,OAAO,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC;IACnE,CAAC;IAED,MAAM,OAAO,GAAG,cAAc,GAAG,cAAc,CAAC;IAChD,OAAO,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC;AAAA,CAClE"}
@@ -1,19 +0,0 @@
1
- /**
2
- * From https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md
3
- */
4
- const gasLimitAdjustmentFactor = 1024;
5
-
6
- /**
7
- * Calculates expected gas limit based on parent gas limit and target gas limit
8
- */
9
- export function getExpectedGasLimit(parentGasLimit: number, targetGasLimit: number): number {
10
- const maxGasLimitDifference = Math.max(Math.floor(parentGasLimit / gasLimitAdjustmentFactor) - 1, 0);
11
-
12
- if (targetGasLimit > parentGasLimit) {
13
- const gasDiff = targetGasLimit - parentGasLimit;
14
- return parentGasLimit + Math.min(gasDiff, maxGasLimitDifference);
15
- }
16
-
17
- const gasDiff = parentGasLimit - targetGasLimit;
18
- return parentGasLimit - Math.min(gasDiff, maxGasLimitDifference);
19
- }