@lodestar/state-transition 1.43.0-dev.2870b59b6a → 1.43.0-dev.2fba242f5d

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 (86) hide show
  1. package/lib/block/index.d.ts +2 -2
  2. package/lib/block/index.d.ts.map +1 -1
  3. package/lib/block/index.js +11 -4
  4. package/lib/block/index.js.map +1 -1
  5. package/lib/block/processParentExecutionPayload.d.ts +20 -0
  6. package/lib/block/processParentExecutionPayload.d.ts.map +1 -0
  7. package/lib/block/processParentExecutionPayload.js +100 -0
  8. package/lib/block/processParentExecutionPayload.js.map +1 -0
  9. package/lib/block/processWithdrawals.d.ts.map +1 -1
  10. package/lib/block/processWithdrawals.js +13 -5
  11. package/lib/block/processWithdrawals.js.map +1 -1
  12. package/lib/cache/epochCache.d.ts +3 -1
  13. package/lib/cache/epochCache.d.ts.map +1 -1
  14. package/lib/cache/epochCache.js +31 -13
  15. package/lib/cache/epochCache.js.map +1 -1
  16. package/lib/cache/epochTransitionCache.d.ts +5 -0
  17. package/lib/cache/epochTransitionCache.d.ts.map +1 -1
  18. package/lib/cache/epochTransitionCache.js +1 -0
  19. package/lib/cache/epochTransitionCache.js.map +1 -1
  20. package/lib/epoch/index.d.ts +3 -1
  21. package/lib/epoch/index.d.ts.map +1 -1
  22. package/lib/epoch/index.js +8 -1
  23. package/lib/epoch/index.js.map +1 -1
  24. package/lib/epoch/processPtcWindow.d.ts +11 -0
  25. package/lib/epoch/processPtcWindow.d.ts.map +1 -0
  26. package/lib/epoch/processPtcWindow.js +28 -0
  27. package/lib/epoch/processPtcWindow.js.map +1 -0
  28. package/lib/signatureSets/executionPayloadEnvelope.js +1 -1
  29. package/lib/signatureSets/executionPayloadEnvelope.js.map +1 -1
  30. package/lib/signatureSets/index.d.ts +1 -0
  31. package/lib/signatureSets/index.d.ts.map +1 -1
  32. package/lib/signatureSets/index.js +1 -0
  33. package/lib/signatureSets/index.js.map +1 -1
  34. package/lib/signatureSets/proposerPreferences.d.ts +4 -0
  35. package/lib/signatureSets/proposerPreferences.d.ts.map +1 -0
  36. package/lib/signatureSets/proposerPreferences.js +8 -0
  37. package/lib/signatureSets/proposerPreferences.js.map +1 -0
  38. package/lib/slot/upgradeStateToGloas.d.ts.map +1 -1
  39. package/lib/slot/upgradeStateToGloas.js +3 -1
  40. package/lib/slot/upgradeStateToGloas.js.map +1 -1
  41. package/lib/stateTransition.d.ts +1 -2
  42. package/lib/stateTransition.d.ts.map +1 -1
  43. package/lib/stateTransition.js +1 -2
  44. package/lib/stateTransition.js.map +1 -1
  45. package/lib/stateView/beaconStateView.d.ts +13 -11
  46. package/lib/stateView/beaconStateView.d.ts.map +1 -1
  47. package/lib/stateView/beaconStateView.js +51 -37
  48. package/lib/stateView/beaconStateView.js.map +1 -1
  49. package/lib/stateView/interface.d.ts +21 -11
  50. package/lib/stateView/interface.d.ts.map +1 -1
  51. package/lib/stateView/interface.js.map +1 -1
  52. package/lib/util/computeAnchorCheckpoint.d.ts +1 -1
  53. package/lib/util/computeAnchorCheckpoint.d.ts.map +1 -1
  54. package/lib/util/computeAnchorCheckpoint.js +6 -19
  55. package/lib/util/computeAnchorCheckpoint.js.map +1 -1
  56. package/lib/util/execution.d.ts +4 -2
  57. package/lib/util/execution.d.ts.map +1 -1
  58. package/lib/util/execution.js +7 -0
  59. package/lib/util/execution.js.map +1 -1
  60. package/lib/util/gloas.d.ts +7 -3
  61. package/lib/util/gloas.d.ts.map +1 -1
  62. package/lib/util/gloas.js +25 -3
  63. package/lib/util/gloas.js.map +1 -1
  64. package/package.json +8 -8
  65. package/src/block/index.ts +12 -4
  66. package/src/block/processParentExecutionPayload.ts +116 -0
  67. package/src/block/processWithdrawals.ts +15 -5
  68. package/src/cache/epochCache.ts +32 -30
  69. package/src/cache/epochTransitionCache.ts +7 -0
  70. package/src/epoch/index.ts +9 -0
  71. package/src/epoch/processPtcWindow.ts +38 -0
  72. package/src/signatureSets/executionPayloadEnvelope.ts +1 -1
  73. package/src/signatureSets/index.ts +1 -0
  74. package/src/signatureSets/proposerPreferences.ts +12 -0
  75. package/src/slot/upgradeStateToGloas.ts +5 -1
  76. package/src/stateTransition.ts +1 -2
  77. package/src/stateView/beaconStateView.ts +67 -50
  78. package/src/stateView/interface.ts +28 -14
  79. package/src/util/computeAnchorCheckpoint.ts +6 -19
  80. package/src/util/execution.ts +11 -1
  81. package/src/util/gloas.ts +46 -4
  82. package/lib/block/processExecutionPayloadEnvelope.d.ts +0 -9
  83. package/lib/block/processExecutionPayloadEnvelope.d.ts.map +0 -1
  84. package/lib/block/processExecutionPayloadEnvelope.js +0 -106
  85. package/lib/block/processExecutionPayloadEnvelope.js.map +0 -1
  86. package/src/block/processExecutionPayloadEnvelope.ts +0 -175
@@ -1,7 +1,7 @@
1
1
  import {CompactMultiProof, ProofType, Tree, createProof} from "@chainsafe/persistent-merkle-tree";
2
2
  import {BitArray, ByteViews} from "@chainsafe/ssz";
3
3
  import {BeaconConfig} from "@lodestar/config";
4
- import {ForkName, ForkSeq, SLOTS_PER_HISTORICAL_ROOT, isForkPostGloas} from "@lodestar/params";
4
+ import {ForkName, ForkSeq, SLOTS_PER_HISTORICAL_ROOT} from "@lodestar/params";
5
5
  import {
6
6
  BeaconBlock,
7
7
  BeaconState,
@@ -28,8 +28,7 @@ import {
28
28
  rewards,
29
29
  } from "@lodestar/types";
30
30
  import {Checkpoint, Fork} from "@lodestar/types/phase0";
31
- import {processExecutionPayloadEnvelope} from "../block/index.js";
32
- import {ProcessExecutionPayloadEnvelopeOpts} from "../block/processExecutionPayloadEnvelope.js";
31
+ import {applyParentExecutionPayload} from "../block/processParentExecutionPayload.js";
33
32
  import {VoluntaryExitValidity, getVoluntaryExitValidity} from "../block/processVoluntaryExit.js";
34
33
  import {getExpectedWithdrawals} from "../block/processWithdrawals.js";
35
34
  import {EffectiveBalanceIncrements} from "../cache/effectiveBalanceIncrements.js";
@@ -59,12 +58,17 @@ import {getBlockRootAtSlot} from "../util/blockRoot.js";
59
58
  import {computeAnchorCheckpoint} from "../util/computeAnchorCheckpoint.js";
60
59
  import {computeEpochAtSlot, computeStartSlotAtEpoch} from "../util/epoch.js";
61
60
  import {EpochShuffling} from "../util/epochShuffling.js";
62
- import {isExecutionEnabled, isExecutionStateType, isMergeTransitionComplete} from "../util/execution.js";
61
+ import {
62
+ isExecutionEnabled,
63
+ isExecutionStateType,
64
+ isGloasStateType,
65
+ isMergeTransitionComplete,
66
+ } from "../util/execution.js";
63
67
  import {canBuilderCoverBid} from "../util/gloas.js";
64
68
  import {loadState} from "../util/loadState/loadState.js";
65
69
  import {getRandaoMix} from "../util/seed.js";
66
70
  import {getLatestWeakSubjectivityCheckpointEpoch} from "../util/weakSubjectivity.js";
67
- import {IBeaconStateView, IBeaconStateViewLatestFork} from "./interface.js";
71
+ import {IBeaconStateView, IBeaconStateViewGloas, IBeaconStateViewLatestFork, isStatePostGloas} from "./interface.js";
68
72
 
69
73
  export class BeaconStateView implements IBeaconStateViewLatestFork {
70
74
  private readonly config: BeaconConfig;
@@ -79,8 +83,6 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
79
83
  private _currentEpochParticipation: Uint8Array | null = null;
80
84
  // bellatrix
81
85
  private _latestExecutionPayloadHeader: ExecutionPayloadHeader | null = null;
82
- // Caches the cross-fork latestBlockHash value
83
- private _latestBlockHash: Bytes32 | null = null;
84
86
  // capella
85
87
  private _historicalSummaries: capella.HistoricalSummaries | null = null;
86
88
  // electra
@@ -213,9 +215,13 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
213
215
  // bellatrix
214
216
 
215
217
  get latestExecutionPayloadHeader(): ExecutionPayloadHeader {
216
- if (this.config.getForkSeq(this.cachedState.slot) < ForkSeq.bellatrix) {
218
+ const forkSeq = this.config.getForkSeq(this.cachedState.slot);
219
+ if (forkSeq < ForkSeq.bellatrix) {
217
220
  throw new Error("latestExecutionPayloadHeader is not available before Bellatrix");
218
221
  }
222
+ if (forkSeq >= ForkSeq.gloas) {
223
+ throw new Error("latestExecutionPayloadHeader is not available after Gloas");
224
+ }
219
225
 
220
226
  if (this._latestExecutionPayloadHeader === null) {
221
227
  this._latestExecutionPayloadHeader = (
@@ -226,30 +232,6 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
226
232
  return this._latestExecutionPayloadHeader;
227
233
  }
228
234
 
229
- /**
230
- * Cross-fork accessor for the execution block hash of the most recently included payload.
231
- * Pre-gloas: reads from latestExecutionPayloadHeader.blockHash.
232
- * Gloas+: reads the dedicated latestBlockHash field (EIP-7732).
233
- */
234
- get latestBlockHash(): Bytes32 {
235
- const forkSeq = this.config.getForkSeq(this.cachedState.slot);
236
- if (forkSeq < ForkSeq.bellatrix) {
237
- throw new Error("latestBlockHash is not available before Bellatrix");
238
- }
239
-
240
- if (this._latestBlockHash === null) {
241
- if (forkSeq >= ForkSeq.gloas) {
242
- this._latestBlockHash = (this.cachedState as CachedBeaconStateGloas).latestBlockHash;
243
- } else {
244
- this._latestBlockHash = (
245
- this.cachedState as CachedBeaconStateExecutions
246
- ).latestExecutionPayloadHeader.blockHash;
247
- }
248
- }
249
-
250
- return this._latestBlockHash;
251
- }
252
-
253
235
  /**
254
236
  * The execution block number of the most recently included payload.
255
237
  * Named payloadBlockNumber (not latestBlockNumber) to mirror ExecutionPayloadHeader.blockNumber pre-gloas.
@@ -360,6 +342,13 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
360
342
 
361
343
  // gloas
362
344
 
345
+ get latestBlockHash(): Bytes32 {
346
+ if (this.config.getForkSeq(this.cachedState.slot) < ForkSeq.gloas) {
347
+ throw new Error("latestBlockHash is not available before Gloas");
348
+ }
349
+ return (this.cachedState as CachedBeaconStateGloas).latestBlockHash;
350
+ }
351
+
363
352
  get executionPayloadAvailability(): BitArray {
364
353
  if (this.config.getForkSeq(this.cachedState.slot) < ForkSeq.gloas) {
365
354
  throw new Error("executionPayloadAvailability is not available before Gloas");
@@ -416,6 +405,23 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
416
405
  return canBuilderCoverBid(this.cachedState as CachedBeaconStateGloas, builderIndex, bidAmount);
417
406
  }
418
407
 
408
+ /**
409
+ * Return the PTCs for an epoch
410
+ */
411
+ getEpochPTCs(epoch: Epoch): Uint32Array[] {
412
+ if (this.config.getForkSeq(this.cachedState.slot) < ForkSeq.gloas) {
413
+ throw new Error("PTC committees are not supported before Gloas");
414
+ }
415
+
416
+ const epochCtx = (this.cachedState as CachedBeaconStateGloas).epochCtx;
417
+ if (epoch === epochCtx.epoch) {
418
+ return epochCtx.payloadTimelinessCommittees;
419
+ }
420
+ if (epoch === epochCtx.nextEpoch) {
421
+ return epochCtx.nextPayloadTimelinessCommittees;
422
+ }
423
+ throw new Error(`PTC committees are not available for epoch=${epoch}`);
424
+ }
419
425
  /**
420
426
  * Return the index of the validator in the PTC committee for the given slot.
421
427
  * return -1 if validator is not in the PTC committee for the given slot.
@@ -589,7 +595,10 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
589
595
  }
590
596
 
591
597
  get isMergeTransitionComplete(): boolean {
592
- return isExecutionStateType(this.cachedState) && isMergeTransitionComplete(this.cachedState);
598
+ return (
599
+ (isExecutionStateType(this.cachedState) || isGloasStateType(this.cachedState)) &&
600
+ isMergeTransitionComplete(this.cachedState)
601
+ );
593
602
  }
594
603
 
595
604
  // Block production
@@ -711,7 +720,11 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
711
720
 
712
721
  // Serialization
713
722
 
714
- loadOtherState(stateBytes: Uint8Array, seedValidatorsBytes?: Uint8Array): IBeaconStateView {
723
+ loadOtherState(
724
+ stateBytes: Uint8Array,
725
+ seedValidatorsBytes?: Uint8Array,
726
+ opts?: {preloadValidatorsAndBalances?: boolean}
727
+ ): IBeaconStateView {
715
728
  const {state} = loadState(this.config, this.cachedState, stateBytes, seedValidatorsBytes);
716
729
 
717
730
  const cachedState = createCachedBeaconState(
@@ -726,9 +739,10 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
726
739
  }
727
740
  );
728
741
 
729
- // load all cache in order for consumers (usually regen.getState()) to process blocks faster
730
- cachedState.validators.getAllReadonlyValues();
731
- cachedState.balances.getAll();
742
+ if (opts?.preloadValidatorsAndBalances) {
743
+ cachedState.validators.getAllReadonlyValues();
744
+ cachedState.balances.getAll();
745
+ }
732
746
 
733
747
  return new BeaconStateView(cachedState);
734
748
  }
@@ -786,19 +800,22 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
786
800
  return new BeaconStateView(newState);
787
801
  }
788
802
 
789
- processExecutionPayloadEnvelope(
790
- signedEnvelope: gloas.SignedExecutionPayloadEnvelope,
791
- opts?: ProcessExecutionPayloadEnvelopeOpts
792
- ): BeaconStateView {
793
- const fork = this.config.getForkName(this.cachedState.slot);
794
- if (!isForkPostGloas(fork)) {
795
- throw Error(`processExecutionPayloadEnvelope is only available for gloas+ forks, got fork=${fork}`);
803
+ /**
804
+ * Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.5/specs/gloas/validator.md#executionpayload
805
+ */
806
+ withParentPayloadApplied(executionRequests: electra.ExecutionRequests): IBeaconStateViewGloas {
807
+ if (this.config.getForkSeq(this.cachedState.slot) < ForkSeq.gloas) {
808
+ throw new Error("withParentPayloadApplied is not available before Gloas");
796
809
  }
797
- const postPayloadState = processExecutionPayloadEnvelope(
798
- this.cachedState as CachedBeaconStateGloas,
799
- signedEnvelope,
800
- opts
801
- );
802
- return new BeaconStateView(postPayloadState);
810
+ const stateCopy = this.cachedState.clone(true) as CachedBeaconStateGloas;
811
+
812
+ applyParentExecutionPayload(stateCopy, executionRequests);
813
+
814
+ const stateView = new BeaconStateView(stateCopy);
815
+ if (!isStatePostGloas(stateView)) {
816
+ throw new Error("Expected gloas state after clone");
817
+ }
818
+
819
+ return stateView;
803
820
  }
804
821
  }
@@ -41,7 +41,6 @@ import {
41
41
  rewards,
42
42
  } from "@lodestar/types";
43
43
  import {Checkpoint, Fork} from "@lodestar/types/phase0";
44
- import {ProcessExecutionPayloadEnvelopeOpts} from "../block/processExecutionPayloadEnvelope.js";
45
44
  import {VoluntaryExitValidity} from "../block/processVoluntaryExit.js";
46
45
  import {EffectiveBalanceIncrements} from "../cache/effectiveBalanceIncrements.js";
47
46
  import {EpochTransitionCacheOpts} from "../cache/epochTransitionCache.js";
@@ -138,7 +137,13 @@ export interface IBeaconStateView {
138
137
  isStateValidatorsNodesPopulated(): boolean;
139
138
 
140
139
  // Serialization
141
- loadOtherState(stateBytes: Uint8Array, seedValidatorsBytes?: Uint8Array): IBeaconStateView;
140
+ /** Set `preloadValidatorsAndBalances` only when the whole state will be consumed
141
+ * immediately (e.g. CP reload before block replay). */
142
+ loadOtherState(
143
+ stateBytes: Uint8Array,
144
+ seedValidatorsBytes?: Uint8Array,
145
+ opts?: {preloadValidatorsAndBalances?: boolean}
146
+ ): IBeaconStateView;
142
147
  toValue(): BeaconState;
143
148
  serialize(): Uint8Array;
144
149
  serializedSize(): number;
@@ -187,13 +192,6 @@ export interface IBeaconStateViewAltair extends IBeaconStateView {
187
192
  export interface IBeaconStateViewBellatrix extends IBeaconStateViewAltair {
188
193
  forkName: ForkPostBellatrix;
189
194
  latestExecutionPayloadHeader: ExecutionPayloadHeader;
190
- /**
191
- * Cross-fork accessor for the execution block hash of the most recently included payload.
192
- * Pre-gloas: returns latestExecutionPayloadHeader.blockHash (bellatrix–fulu).
193
- * Gloas+: returns the dedicated latestBlockHash state field (EIP-7732).
194
- * Throws before bellatrix.
195
- */
196
- latestBlockHash: Bytes32;
197
195
  /**
198
196
  * The execution block number of the most recently included payload.
199
197
  * Named payloadBlockNumber (not latestBlockNumber) to mirror ExecutionPayloadHeader.blockNumber pre-gloas.
@@ -244,16 +242,25 @@ export interface IBeaconStateViewFulu extends IBeaconStateViewElectra {
244
242
  /** Gloas+ state fields — use isStatePostGloas() guard */
245
243
  export interface IBeaconStateViewGloas extends IBeaconStateViewFulu {
246
244
  forkName: ForkPostGloas;
245
+ /** Removed from BeaconState in gloas. Use `latestBlockHash` instead. */
246
+ latestExecutionPayloadHeader: never;
247
+ /** Removed from BeaconState in gloas. */
248
+ payloadBlockNumber: never;
249
+ latestBlockHash: Bytes32;
247
250
  executionPayloadAvailability: BitArray;
248
251
  latestExecutionPayloadBid: ExecutionPayloadBid;
249
252
  payloadExpectedWithdrawals: capella.Withdrawal[];
250
253
  getBuilder(index: BuilderIndex): gloas.Builder;
251
254
  canBuilderCoverBid(builderIndex: BuilderIndex, bidAmount: number): boolean;
255
+ getEpochPTCs(epoch: Epoch): Uint32Array[];
252
256
  getIndexInPayloadTimelinessCommittee(validatorIndex: ValidatorIndex, slot: Slot): number;
253
- processExecutionPayloadEnvelope(
254
- signedEnvelope: gloas.SignedExecutionPayloadEnvelope,
255
- opts?: ProcessExecutionPayloadEnvelopeOpts
256
- ): IBeaconStateView;
257
+ /**
258
+ * Clone the state and apply parent execution payload effects.
259
+ * Used during block production and prepareNextSlot so that withdrawals and
260
+ * operation selection (e.g. voluntary exits) see the same post-apply state that the block
261
+ * processor will see at import.
262
+ */
263
+ withParentPayloadApplied(executionRequests: electra.ExecutionRequests): IBeaconStateViewGloas;
257
264
  }
258
265
 
259
266
  /**
@@ -262,7 +269,14 @@ export interface IBeaconStateViewGloas extends IBeaconStateViewFulu {
262
269
  * forkName as ForkName since the class wraps any fork's state.
263
270
  * Sub-interfaces retain their narrowed forkName discriminants for caller-side type guards.
264
271
  */
265
- export type IBeaconStateViewLatestFork = Omit<IBeaconStateViewGloas, "forkName"> & {forkName: ForkName};
272
+ export type IBeaconStateViewLatestFork = Omit<
273
+ IBeaconStateViewGloas,
274
+ "forkName" | "latestExecutionPayloadHeader" | "payloadBlockNumber"
275
+ > & {
276
+ forkName: ForkName;
277
+ latestExecutionPayloadHeader: ExecutionPayloadHeader;
278
+ payloadBlockNumber: number;
279
+ };
266
280
  export function isStatePostAltair(state: IBeaconStateView): state is IBeaconStateViewAltair {
267
281
  return isForkPostAltair(state.forkName);
268
282
  }
@@ -1,34 +1,21 @@
1
1
  import {ChainForkConfig} from "@lodestar/config";
2
- import {GENESIS_SLOT, ZERO_HASH} from "@lodestar/params";
2
+ import {ZERO_HASH} from "@lodestar/params";
3
3
  import {phase0, ssz} from "@lodestar/types";
4
4
  import {BeaconStateAllForks} from "../types.js";
5
- import {blockToHeader} from "./blockRoot.js";
6
5
  import {computeCheckpointEpochAtStateSlot} from "./epoch.js";
7
6
 
8
7
  export function computeAnchorCheckpoint(
9
- config: ChainForkConfig,
8
+ _config: ChainForkConfig,
10
9
  anchorState: BeaconStateAllForks
11
10
  ): {checkpoint: phase0.Checkpoint; blockHeader: phase0.BeaconBlockHeader} {
12
- let blockHeader: phase0.BeaconBlockHeader;
13
- let root: Uint8Array;
14
- const blockTypes = config.getForkTypes(anchorState.latestBlockHeader.slot);
15
-
16
- if (anchorState.latestBlockHeader.slot === GENESIS_SLOT) {
17
- const block = blockTypes.BeaconBlock.defaultValue();
18
- block.stateRoot = anchorState.hashTreeRoot();
19
- blockHeader = blockToHeader(config, block);
20
- root = ssz.phase0.BeaconBlockHeader.hashTreeRoot(blockHeader);
21
- } else {
22
- blockHeader = ssz.phase0.BeaconBlockHeader.clone(anchorState.latestBlockHeader);
23
- if (ssz.Root.equals(blockHeader.stateRoot, ZERO_HASH)) {
24
- blockHeader.stateRoot = anchorState.hashTreeRoot();
25
- }
26
- root = ssz.phase0.BeaconBlockHeader.hashTreeRoot(blockHeader);
11
+ const blockHeader = ssz.phase0.BeaconBlockHeader.clone(anchorState.latestBlockHeader);
12
+ if (ssz.Root.equals(blockHeader.stateRoot, ZERO_HASH)) {
13
+ blockHeader.stateRoot = anchorState.hashTreeRoot();
27
14
  }
28
15
 
29
16
  return {
30
17
  checkpoint: {
31
- root,
18
+ root: ssz.phase0.BeaconBlockHeader.hashTreeRoot(blockHeader),
32
19
  // the checkpoint epoch = computeEpochAtSlot(anchorState.slot) + 1 if slot is not at epoch boundary
33
20
  // this is similar to a process_slots() call
34
21
  epoch: computeCheckpointEpochAtStateSlot(anchorState.slot),
@@ -18,6 +18,7 @@ import {
18
18
  BeaconStateBellatrix,
19
19
  BeaconStateCapella,
20
20
  BeaconStateExecutions,
21
+ BeaconStateGloas,
21
22
  CachedBeaconStateAllForks,
22
23
  CachedBeaconStateExecutions,
23
24
  } from "../types.js";
@@ -46,7 +47,11 @@ export function isExecutionEnabled(state: BeaconStateExecutions, block: BeaconBl
46
47
  * Merge is complete when the state includes execution layer data:
47
48
  * state.latestExecutionPayloadHeader NOT EMPTY or state is post-capella
48
49
  */
49
- export function isMergeTransitionComplete(state: BeaconStateExecutions): boolean {
50
+ export function isMergeTransitionComplete(state: BeaconStateExecutions | BeaconStateGloas): boolean {
51
+ if (isGloasStateType(state)) {
52
+ return true;
53
+ }
54
+
50
55
  if (isCapellaStateType(state)) {
51
56
  // All networks have completed the merge transition before capella
52
57
  return true;
@@ -71,6 +76,11 @@ export function isCapellaStateType(state: BeaconStateAllForks): state is BeaconS
71
76
  );
72
77
  }
73
78
 
79
+ /** Type guard for gloas.BeaconState */
80
+ export function isGloasStateType(state: BeaconStateAllForks): state is BeaconStateGloas {
81
+ return (state as BeaconStateGloas).latestBlockHash !== undefined;
82
+ }
83
+
74
84
  /** Type guard for bellatrix.CachedBeaconState */
75
85
  export function isExecutionCachedStateType(state: CachedBeaconStateAllForks): state is CachedBeaconStateExecutions {
76
86
  return (state as CachedBeaconStateExecutions).latestExecutionPayloadHeader !== undefined;
package/src/util/gloas.ts CHANGED
@@ -6,16 +6,20 @@ import {
6
6
  EFFECTIVE_BALANCE_INCREMENT,
7
7
  FAR_FUTURE_EPOCH,
8
8
  MIN_DEPOSIT_AMOUNT,
9
+ MIN_SEED_LOOKAHEAD,
10
+ PTC_SIZE,
9
11
  SLOTS_PER_EPOCH,
10
12
  } from "@lodestar/params";
11
13
  import {BuilderIndex, Epoch, ValidatorIndex, gloas} from "@lodestar/types";
12
14
  import {AttestationData} from "@lodestar/types/phase0";
13
15
  import {byteArrayEquals} from "@lodestar/utils";
14
- import {IBeaconStateViewGloas} from "../stateView/interface.js";
15
- import {CachedBeaconStateGloas} from "../types.js";
16
+ import {CachedBeaconStateFulu, CachedBeaconStateGloas} from "../types.js";
16
17
  import {getBlockRootAtSlot} from "./blockRoot.js";
17
18
  import {computeEpochAtSlot} from "./epoch.js";
19
+ import {computeEpochShuffling} from "./epochShuffling.js";
18
20
  import {RootCache} from "./rootCache.js";
21
+ import {computePayloadTimelinessCommitteesForEpoch} from "./seed.js";
22
+ import {getActiveValidatorIndices} from "./validator.js";
19
23
 
20
24
  export function isBuilderWithdrawalCredential(withdrawalCredentials: Uint8Array): boolean {
21
25
  return withdrawalCredentials[0] === BUILDER_WITHDRAWAL_PREFIX;
@@ -168,6 +172,44 @@ export function isAttestationSameSlotRootCache(rootCache: RootCache, data: Attes
168
172
  return isMatchingBlockRoot && isCurrentBlockRoot;
169
173
  }
170
174
 
171
- export function isParentBlockFull(state: CachedBeaconStateGloas | IBeaconStateViewGloas): boolean {
172
- return byteArrayEquals(state.latestExecutionPayloadBid.blockHash, state.latestBlockHash);
175
+ export function initializePtcWindow(state: CachedBeaconStateFulu): Uint32Array[] {
176
+ const ptcWindow: Uint32Array[] = Array.from({length: SLOTS_PER_EPOCH}, () => new Uint32Array(PTC_SIZE));
177
+ const currentEpoch = state.epochCtx.epoch;
178
+
179
+ for (let epochOffset = 0; epochOffset <= MIN_SEED_LOOKAHEAD; epochOffset++) {
180
+ const epoch = currentEpoch + epochOffset;
181
+ const shuffling =
182
+ state.epochCtx.getShufflingAtEpochOrNull(epoch) ??
183
+ computeEpochShuffling(state, getActiveValidatorIndices(state, epoch), epoch);
184
+
185
+ ptcWindow.push(
186
+ ...computePayloadTimelinessCommitteesForEpoch(
187
+ state,
188
+ epoch,
189
+ shuffling.committees,
190
+ state.epochCtx.effectiveBalanceIncrements
191
+ )
192
+ );
193
+ }
194
+
195
+ return ptcWindow;
196
+ }
197
+
198
+ export function getPtcWindowEpochCacheData(state: CachedBeaconStateGloas): {
199
+ previousPayloadTimelinessCommittees: Uint32Array[];
200
+ payloadTimelinessCommittees: Uint32Array[];
201
+ nextPayloadTimelinessCommittees: Uint32Array[];
202
+ } {
203
+ const toUint32Arrays = (views: ReturnType<typeof state.ptcWindow.getReadonlyByRange>) =>
204
+ views.map((v) => Uint32Array.from(v.getAll()));
205
+
206
+ const previousPtcWindow = state.ptcWindow.getReadonlyByRange(0, SLOTS_PER_EPOCH);
207
+ const currentPtcWindow = state.ptcWindow.getReadonlyByRange(SLOTS_PER_EPOCH, SLOTS_PER_EPOCH);
208
+ const nextPtcWindow = state.ptcWindow.getReadonlyByRange(2 * SLOTS_PER_EPOCH, SLOTS_PER_EPOCH);
209
+
210
+ return {
211
+ previousPayloadTimelinessCommittees: toUint32Arrays(previousPtcWindow),
212
+ payloadTimelinessCommittees: toUint32Arrays(currentPtcWindow),
213
+ nextPayloadTimelinessCommittees: toUint32Arrays(nextPtcWindow),
214
+ };
173
215
  }
@@ -1,9 +0,0 @@
1
- import { gloas } from "@lodestar/types";
2
- import { CachedBeaconStateGloas } from "../types.js";
3
- export type ProcessExecutionPayloadEnvelopeOpts = {
4
- verifySignature?: boolean;
5
- verifyStateRoot?: boolean;
6
- dontTransferCache?: boolean;
7
- };
8
- export declare function processExecutionPayloadEnvelope(state: CachedBeaconStateGloas, signedEnvelope: gloas.SignedExecutionPayloadEnvelope, opts?: ProcessExecutionPayloadEnvelopeOpts): CachedBeaconStateGloas;
9
- //# sourceMappingURL=processExecutionPayloadEnvelope.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"processExecutionPayloadEnvelope.d.ts","sourceRoot":"","sources":["../../src/block/processExecutionPayloadEnvelope.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,KAAK,EAAM,MAAM,iBAAiB,CAAC;AAI3C,OAAO,EAAC,sBAAsB,EAAC,MAAM,aAAa,CAAC;AAOnD,MAAM,MAAM,mCAAmC,GAAG;IAChD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAKF,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,sBAAsB,EAC7B,cAAc,EAAE,KAAK,CAAC,8BAA8B,EACpD,IAAI,CAAC,EAAE,mCAAmC,GACzC,sBAAsB,CA0DxB"}
@@ -1,106 +0,0 @@
1
- import { SLOTS_PER_EPOCH, SLOTS_PER_HISTORICAL_ROOT } from "@lodestar/params";
2
- import { ssz } from "@lodestar/types";
3
- import { byteArrayEquals, toHex, toRootHex } from "@lodestar/utils";
4
- import { getExecutionPayloadEnvelopeSignatureSet } from "../signatureSets/executionPayloadEnvelope.js";
5
- import { BeaconStateView } from "../stateView/beaconStateView.js";
6
- import { computeTimeAtSlot } from "../util/index.js";
7
- import { verifySignatureSet } from "../util/signatureSets.js";
8
- import { processConsolidationRequest } from "./processConsolidationRequest.js";
9
- import { getPendingValidatorPubkeys, processDepositRequest } from "./processDepositRequest.js";
10
- import { processWithdrawalRequest } from "./processWithdrawalRequest.js";
11
- // Unlike other block processing functions which mutate state in-place, this function
12
- // clones the state and returns the post-state, similar to stateTransition().
13
- // This function does not call execution engine to verify payload. Need to call it from other place.
14
- export function processExecutionPayloadEnvelope(state, signedEnvelope, opts) {
15
- const { verifySignature = true, verifyStateRoot = true } = opts ?? {};
16
- const envelope = signedEnvelope.message;
17
- const payload = envelope.payload;
18
- const fork = state.config.getForkSeq(envelope.slot);
19
- if (verifySignature && !verifyExecutionPayloadEnvelopeSignature(state, signedEnvelope)) {
20
- throw Error(`Execution payload envelope has invalid signature builderIndex=${envelope.builderIndex}`);
21
- }
22
- // .clone() before mutating state, similar to stateTransition()
23
- const postState = state.clone(opts?.dontTransferCache);
24
- validateExecutionPayloadEnvelope(postState, envelope);
25
- const requests = envelope.executionRequests;
26
- if (requests.deposits.length > 0) {
27
- // Build cache of pending validator pubkeys once, shared across all deposit requests
28
- const pendingValidatorPubkeys = getPendingValidatorPubkeys(postState.config, postState);
29
- for (const deposit of requests.deposits) {
30
- processDepositRequest(fork, postState, deposit, pendingValidatorPubkeys);
31
- }
32
- }
33
- for (const withdrawal of requests.withdrawals) {
34
- processWithdrawalRequest(fork, postState, withdrawal);
35
- }
36
- for (const consolidation of requests.consolidations) {
37
- processConsolidationRequest(postState, consolidation);
38
- }
39
- // Queue the builder payment
40
- const paymentIndex = SLOTS_PER_EPOCH + (postState.slot % SLOTS_PER_EPOCH);
41
- const payment = postState.builderPendingPayments.get(paymentIndex).clone();
42
- const amount = payment.withdrawal.amount;
43
- if (amount > 0) {
44
- postState.builderPendingWithdrawals.push(payment.withdrawal);
45
- }
46
- postState.builderPendingPayments.set(paymentIndex, ssz.gloas.BuilderPendingPayment.defaultViewDU());
47
- // Cache the execution payload hash
48
- postState.executionPayloadAvailability.set(postState.slot % SLOTS_PER_HISTORICAL_ROOT, true);
49
- postState.latestBlockHash = payload.blockHash;
50
- postState.commit();
51
- if (verifyStateRoot && !byteArrayEquals(envelope.stateRoot, postState.hashTreeRoot())) {
52
- throw new Error(`Envelope's state root does not match state envelope=${toRootHex(envelope.stateRoot)} state=${toRootHex(postState.hashTreeRoot())}`);
53
- }
54
- return postState;
55
- }
56
- function validateExecutionPayloadEnvelope(state, envelope) {
57
- const payload = envelope.payload;
58
- // Cache latest block header state root
59
- if (byteArrayEquals(state.latestBlockHeader.stateRoot, ssz.Root.defaultValue())) {
60
- const previousStateRoot = state.hashTreeRoot();
61
- state.latestBlockHeader.stateRoot = previousStateRoot;
62
- }
63
- // Verify consistency with the beacon block
64
- if (!byteArrayEquals(envelope.beaconBlockRoot, state.latestBlockHeader.hashTreeRoot())) {
65
- throw new Error(`Envelope's block is not the latest block header envelope=${toRootHex(envelope.beaconBlockRoot)} latestBlockHeader=${toRootHex(state.latestBlockHeader.hashTreeRoot())}`);
66
- }
67
- if (envelope.slot !== state.slot) {
68
- throw new Error(`Slot mismatch between envelope and state envelope=${envelope.slot} state=${state.slot}`);
69
- }
70
- // Verify consistency with the committed bid
71
- const committedBid = state.latestExecutionPayloadBid;
72
- if (envelope.builderIndex !== committedBid.builderIndex) {
73
- throw new Error(`Builder index mismatch between envelope and committed bid envelope=${envelope.builderIndex} committedBid=${committedBid.builderIndex}`);
74
- }
75
- if (!byteArrayEquals(committedBid.prevRandao, payload.prevRandao)) {
76
- throw new Error(`Prev randao mismatch between committed bid and payload committedBid=${toHex(committedBid.prevRandao)} payload=${toHex(payload.prevRandao)}`);
77
- }
78
- // Verify consistency with expected withdrawals
79
- const payloadWithdrawalsRoot = ssz.capella.Withdrawals.hashTreeRoot(payload.withdrawals);
80
- const expectedWithdrawalsRoot = state.payloadExpectedWithdrawals.hashTreeRoot();
81
- if (!byteArrayEquals(payloadWithdrawalsRoot, expectedWithdrawalsRoot)) {
82
- throw new Error(`Withdrawals mismatch between payload and expected withdrawals payload=${toRootHex(payloadWithdrawalsRoot)} expected=${toRootHex(expectedWithdrawalsRoot)}`);
83
- }
84
- // Verify the gas_limit
85
- if (Number(committedBid.gasLimit) !== payload.gasLimit) {
86
- throw new Error(`Gas limit mismatch between envelope's payload and committed bid envelope=${payload.gasLimit} committedBid=${Number(committedBid.gasLimit)}`);
87
- }
88
- // Verify the block hash
89
- if (!byteArrayEquals(committedBid.blockHash, payload.blockHash)) {
90
- throw new Error(`Block hash mismatch between envelope's payload and committed bid envelope=${toRootHex(payload.blockHash)} committedBid=${toRootHex(committedBid.blockHash)}`);
91
- }
92
- // Verify consistency of the parent hash with respect to the previous execution payload
93
- if (!byteArrayEquals(payload.parentHash, state.latestBlockHash)) {
94
- throw new Error(`Parent hash mismatch between envelope's payload and state envelope=${toRootHex(payload.parentHash)} state=${toRootHex(state.latestBlockHash)}`);
95
- }
96
- // Verify timestamp
97
- if (payload.timestamp !== computeTimeAtSlot(state.config, state.slot, state.genesisTime)) {
98
- throw new Error(`Timestamp mismatch between envelope's payload and state envelope=${payload.timestamp} state=${computeTimeAtSlot(state.config, state.slot, state.genesisTime)}`);
99
- }
100
- // Skipped: Verify the execution payload is valid
101
- }
102
- function verifyExecutionPayloadEnvelopeSignature(state, signedEnvelope) {
103
- const signatureSet = getExecutionPayloadEnvelopeSignatureSet(state.config, state.epochCtx.pubkeyCache, new BeaconStateView(state), signedEnvelope, state.latestBlockHeader.proposerIndex);
104
- return verifySignatureSet(signatureSet);
105
- }
106
- //# sourceMappingURL=processExecutionPayloadEnvelope.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"processExecutionPayloadEnvelope.js","sourceRoot":"","sources":["../../src/block/processExecutionPayloadEnvelope.ts"],"names":[],"mappings":"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"}