@lodestar/state-transition 1.41.0 → 1.42.0-dev.2f0347050b

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 (69) hide show
  1. package/lib/block/isValidIndexedAttestation.d.ts.map +1 -1
  2. package/lib/block/isValidIndexedAttestation.js +2 -3
  3. package/lib/block/isValidIndexedAttestation.js.map +1 -1
  4. package/lib/block/processAttestationsAltair.d.ts +2 -1
  5. package/lib/block/processAttestationsAltair.d.ts.map +1 -1
  6. package/lib/block/processAttestationsAltair.js +5 -3
  7. package/lib/block/processAttestationsAltair.js.map +1 -1
  8. package/lib/block/processExecutionPayloadEnvelope.d.ts +3 -1
  9. package/lib/block/processExecutionPayloadEnvelope.d.ts.map +1 -1
  10. package/lib/block/processExecutionPayloadEnvelope.js +11 -28
  11. package/lib/block/processExecutionPayloadEnvelope.js.map +1 -1
  12. package/lib/block/processVoluntaryExit.d.ts.map +1 -1
  13. package/lib/block/processVoluntaryExit.js +49 -47
  14. package/lib/block/processVoluntaryExit.js.map +1 -1
  15. package/lib/signatureSets/executionPayloadEnvelope.d.ts +5 -1
  16. package/lib/signatureSets/executionPayloadEnvelope.d.ts.map +1 -1
  17. package/lib/signatureSets/executionPayloadEnvelope.js +10 -1
  18. package/lib/signatureSets/executionPayloadEnvelope.js.map +1 -1
  19. package/lib/signatureSets/index.d.ts +2 -1
  20. package/lib/signatureSets/index.d.ts.map +1 -1
  21. package/lib/signatureSets/index.js +2 -2
  22. package/lib/signatureSets/index.js.map +1 -1
  23. package/lib/signatureSets/voluntaryExits.d.ts +7 -3
  24. package/lib/signatureSets/voluntaryExits.d.ts.map +1 -1
  25. package/lib/signatureSets/voluntaryExits.js +30 -9
  26. package/lib/signatureSets/voluntaryExits.js.map +1 -1
  27. package/lib/slot/upgradeStateToAltair.d.ts.map +1 -1
  28. package/lib/slot/upgradeStateToAltair.js +2 -1
  29. package/lib/slot/upgradeStateToAltair.js.map +1 -1
  30. package/lib/stateView/beaconStateView.d.ts +8 -10
  31. package/lib/stateView/beaconStateView.d.ts.map +1 -1
  32. package/lib/stateView/beaconStateView.js +11 -34
  33. package/lib/stateView/beaconStateView.js.map +1 -1
  34. package/lib/stateView/index.d.ts +1 -0
  35. package/lib/stateView/index.d.ts.map +1 -1
  36. package/lib/stateView/index.js +1 -0
  37. package/lib/stateView/index.js.map +1 -1
  38. package/lib/stateView/interface.d.ts +14 -9
  39. package/lib/stateView/interface.d.ts.map +1 -1
  40. package/lib/stateView/stateViewFactory.d.ts +40 -0
  41. package/lib/stateView/stateViewFactory.d.ts.map +1 -0
  42. package/lib/stateView/stateViewFactory.js +46 -0
  43. package/lib/stateView/stateViewFactory.js.map +1 -0
  44. package/lib/util/execution.js +1 -1
  45. package/lib/util/execution.js.map +1 -1
  46. package/lib/util/rootCache.d.ts +2 -2
  47. package/lib/util/rootCache.d.ts.map +1 -1
  48. package/lib/util/rootCache.js +2 -3
  49. package/lib/util/rootCache.js.map +1 -1
  50. package/lib/util/shuffling.d.ts +2 -1
  51. package/lib/util/shuffling.d.ts.map +1 -1
  52. package/lib/util/shuffling.js +2 -2
  53. package/lib/util/shuffling.js.map +1 -1
  54. package/package.json +7 -7
  55. package/src/block/isValidIndexedAttestation.ts +2 -3
  56. package/src/block/processAttestationsAltair.ts +7 -4
  57. package/src/block/processExecutionPayloadEnvelope.ts +18 -35
  58. package/src/block/processVoluntaryExit.ts +77 -54
  59. package/src/signatureSets/executionPayloadEnvelope.ts +26 -2
  60. package/src/signatureSets/index.ts +3 -1
  61. package/src/signatureSets/voluntaryExits.ts +51 -9
  62. package/src/slot/upgradeStateToAltair.ts +2 -1
  63. package/src/stateView/beaconStateView.ts +27 -50
  64. package/src/stateView/index.ts +1 -0
  65. package/src/stateView/interface.ts +15 -6
  66. package/src/stateView/stateViewFactory.ts +78 -0
  67. package/src/util/execution.ts +1 -1
  68. package/src/util/rootCache.ts +4 -5
  69. package/src/util/shuffling.ts +5 -4
@@ -1,9 +1,10 @@
1
1
  import {CompactMultiProof, ProofType, Tree, createProof} from "@chainsafe/persistent-merkle-tree";
2
- import {ByteViews} from "@chainsafe/ssz";
2
+ import {BitArray, ByteViews} from "@chainsafe/ssz";
3
3
  import {BeaconConfig} from "@lodestar/config";
4
4
  import {ForkSeq, SLOTS_PER_HISTORICAL_ROOT, isForkPostGloas} from "@lodestar/params";
5
5
  import {
6
6
  BeaconBlock,
7
+ BeaconState,
7
8
  BlindedBeaconBlock,
8
9
  BuilderIndex,
9
10
  Bytes32,
@@ -28,11 +29,11 @@ import {
28
29
  } from "@lodestar/types";
29
30
  import {Checkpoint, Fork} from "@lodestar/types/phase0";
30
31
  import {processExecutionPayloadEnvelope} from "../block/index.js";
32
+ import {ProcessExecutionPayloadEnvelopeOpts} from "../block/processExecutionPayloadEnvelope.js";
31
33
  import {VoluntaryExitValidity, getVoluntaryExitValidity} from "../block/processVoluntaryExit.js";
32
34
  import {getExpectedWithdrawals} from "../block/processWithdrawals.js";
33
35
  import {EffectiveBalanceIncrements} from "../cache/effectiveBalanceIncrements.js";
34
36
  import {EpochTransitionCacheOpts} from "../cache/epochTransitionCache.js";
35
- import {PubkeyCache, createPubkeyCache} from "../cache/pubkeyCache.js";
36
37
  import {RewardCache} from "../cache/rewardCache.js";
37
38
  import {
38
39
  CachedBeaconStateAllForks,
@@ -46,7 +47,6 @@ import {
46
47
  isStateValidatorsNodesPopulated,
47
48
  } from "../cache/stateCache.js";
48
49
  import {SyncCommitteeCache} from "../cache/syncCommitteeCache.js";
49
- import {BeaconStateAllForks} from "../cache/types.js";
50
50
  import {computeUnrealizedCheckpoints} from "../epoch/computeUnrealizedCheckpoints.js";
51
51
  import {getFinalizedRootProof, getSyncCommitteesWitness} from "../lightClient/proofs.js";
52
52
  import {SyncCommitteeWitness} from "../lightClient/types.js";
@@ -63,7 +63,6 @@ import {isExecutionEnabled, isExecutionStateType, isMergeTransitionComplete} fro
63
63
  import {canBuilderCoverBid} from "../util/gloas.js";
64
64
  import {loadState} from "../util/loadState/loadState.js";
65
65
  import {getRandaoMix} from "../util/seed.js";
66
- import {getStateTypeFromBytes} from "../util/sszBytes.js";
67
66
  import {getLatestWeakSubjectivityCheckpointEpoch} from "../util/weakSubjectivity.js";
68
67
  import {IBeaconStateView} from "./interface.js";
69
68
 
@@ -91,7 +90,7 @@ export class BeaconStateView implements IBeaconStateView {
91
90
  // fulu
92
91
  private _proposerLookahead: fulu.ProposerLookahead | null = null;
93
92
  // gloas
94
- private _executionPayloadAvailability: boolean[] | null = null;
93
+ private _executionPayloadAvailability: BitArray | null = null;
95
94
  private _latestExecutionPayloadBid: ExecutionPayloadBid | null = null;
96
95
 
97
96
  constructor(readonly cachedState: CachedBeaconStateAllForks) {
@@ -356,15 +355,15 @@ export class BeaconStateView implements IBeaconStateView {
356
355
 
357
356
  // gloas
358
357
 
359
- get executionPayloadAvailability(): boolean[] {
358
+ get executionPayloadAvailability(): BitArray {
360
359
  if (this.config.getForkSeq(this.cachedState.slot) < ForkSeq.gloas) {
361
360
  throw new Error("executionPayloadAvailability is not available before GLOAS");
362
361
  }
363
362
 
364
363
  if (this._executionPayloadAvailability === null) {
365
- this._executionPayloadAvailability = (this.cachedState as CachedBeaconStateGloas).executionPayloadAvailability
366
- .toValue()
367
- .toBoolArray();
364
+ this._executionPayloadAvailability = (
365
+ this.cachedState as CachedBeaconStateGloas
366
+ ).executionPayloadAvailability.toValue();
368
367
  }
369
368
 
370
369
  return this._executionPayloadAvailability;
@@ -403,7 +402,7 @@ export class BeaconStateView implements IBeaconStateView {
403
402
  * Return the index of the validator in the PTC committee for the given slot.
404
403
  * return -1 if validator is not in the PTC committee for the given slot.
405
404
  */
406
- validatorPTCCommitteeIndex(validatorIndex: ValidatorIndex, slot: Slot): number {
405
+ getIndexInPayloadTimelinessCommittee(validatorIndex: ValidatorIndex, slot: Slot): number {
407
406
  if (this.config.getForkSeq(this.cachedState.slot) < ForkSeq.gloas) {
408
407
  throw new Error("PTC committees are not supported before GLOAS");
409
408
  }
@@ -502,6 +501,10 @@ export class BeaconStateView implements IBeaconStateView {
502
501
  return this.cachedState.epochCtx.syncProposerReward;
503
502
  }
504
503
 
504
+ getIndexedSyncCommittee(slot: Slot): SyncCommitteeCache {
505
+ return this.cachedState.epochCtx.getIndexedSyncCommittee(slot);
506
+ }
507
+
505
508
  getIndexedSyncCommitteeAtEpoch(epoch: Epoch): SyncCommitteeCache {
506
509
  return this.cachedState.epochCtx.getIndexedSyncCommitteeAtEpoch(epoch);
507
510
  }
@@ -712,6 +715,10 @@ export class BeaconStateView implements IBeaconStateView {
712
715
  return new BeaconStateView(cachedState);
713
716
  }
714
717
 
718
+ toValue(): BeaconState {
719
+ return this.cachedState.toValue();
720
+ }
721
+
715
722
  serialize(): Uint8Array {
716
723
  return this.cachedState.serialize();
717
724
  }
@@ -761,49 +768,19 @@ export class BeaconStateView implements IBeaconStateView {
761
768
  return new BeaconStateView(newState);
762
769
  }
763
770
 
764
- processExecutionPayloadEnvelope(signedEnvelope: gloas.SignedExecutionPayloadEnvelope, verify: boolean): void {
771
+ processExecutionPayloadEnvelope(
772
+ signedEnvelope: gloas.SignedExecutionPayloadEnvelope,
773
+ opts?: ProcessExecutionPayloadEnvelopeOpts
774
+ ): BeaconStateView {
765
775
  const fork = this.config.getForkName(this.cachedState.slot);
766
776
  if (!isForkPostGloas(fork)) {
767
777
  throw Error(`processExecutionPayloadEnvelope is only available for gloas+ forks, got fork=${fork}`);
768
778
  }
769
- processExecutionPayloadEnvelope(this.cachedState as CachedBeaconStateGloas, signedEnvelope, verify);
770
- }
771
- }
772
-
773
- /**
774
- * Create BeaconStateView for historical state regen, no need to sync pubkey cache there.
775
- */
776
- export function createBeaconStateViewForHistoricalRegen(
777
- config: BeaconConfig,
778
- stateBytes: Uint8Array
779
- ): IBeaconStateView {
780
- const state = getStateTypeFromBytes(config, stateBytes).deserializeToViewDU(stateBytes);
781
-
782
- const pubkeyCache = createPubkeyCache();
783
- syncPubkeyCache(state, pubkeyCache);
784
- const cachedState = createCachedBeaconState(
785
- state,
786
- {
787
- config,
788
- pubkeyCache,
789
- },
790
- {
791
- skipSyncPubkeys: true,
792
- }
793
- );
794
-
795
- return new BeaconStateView(cachedState);
796
- }
797
-
798
- /**
799
- * Populate a PubkeyIndexMap with any new entries based on a BeaconState
800
- */
801
- function syncPubkeyCache(state: BeaconStateAllForks, pubkeyCache: PubkeyCache): void {
802
- // Get the validators sub tree once for all the loop
803
-
804
- const newCount = state.validators.length;
805
- for (let i = pubkeyCache.size; i < newCount; i++) {
806
- const pubkey = state.validators.getReadonly(i).pubkey;
807
- pubkeyCache.set(i, pubkey);
779
+ const postPayloadState = processExecutionPayloadEnvelope(
780
+ this.cachedState as CachedBeaconStateGloas,
781
+ signedEnvelope,
782
+ opts
783
+ );
784
+ return new BeaconStateView(postPayloadState);
808
785
  }
809
786
  }
@@ -1,2 +1,3 @@
1
1
  export * from "./beaconStateView.js";
2
2
  export * from "./interface.js";
3
+ export * from "./stateViewFactory.js";
@@ -1,7 +1,8 @@
1
1
  import {CompactMultiProof} from "@chainsafe/persistent-merkle-tree";
2
- import {ByteViews} from "@chainsafe/ssz";
2
+ import {BitArray, ByteViews} from "@chainsafe/ssz";
3
3
  import {
4
4
  BeaconBlock,
5
+ BeaconState,
5
6
  BlindedBeaconBlock,
6
7
  BuilderIndex,
7
8
  Bytes32,
@@ -23,6 +24,7 @@ import {
23
24
  rewards,
24
25
  } from "@lodestar/types";
25
26
  import {Checkpoint, Fork} from "@lodestar/types/phase0";
27
+ import {ProcessExecutionPayloadEnvelopeOpts} from "../block/processExecutionPayloadEnvelope.js";
26
28
  import {VoluntaryExitValidity} from "../block/processVoluntaryExit.js";
27
29
  import {EffectiveBalanceIncrements} from "../cache/effectiveBalanceIncrements.js";
28
30
  import {EpochTransitionCacheOpts} from "../cache/epochTransitionCache.js";
@@ -92,11 +94,11 @@ export interface IBeaconStateView {
92
94
  proposerLookahead: fulu.ProposerLookahead;
93
95
 
94
96
  // gloas
95
- executionPayloadAvailability: boolean[];
97
+ executionPayloadAvailability: BitArray;
96
98
  latestExecutionPayloadBid: ExecutionPayloadBid;
97
99
  getBuilder(index: BuilderIndex): gloas.Builder;
98
100
  canBuilderCoverBid(builderIndex: BuilderIndex, bidAmount: number): boolean;
99
- validatorPTCCommitteeIndex(validatorIndex: ValidatorIndex, slot: Slot): number;
101
+ getIndexInPayloadTimelinessCommittee(validatorIndex: ValidatorIndex, slot: Slot): number;
100
102
 
101
103
  // Shuffling and committees
102
104
  getShufflingAtEpoch(epoch: Epoch): EpochShuffling;
@@ -109,12 +111,11 @@ export interface IBeaconStateView {
109
111
  getCurrentShuffling(): EpochShuffling;
110
112
  getNextShuffling(): EpochShuffling;
111
113
 
112
- // utils: proposers, anchor checkpoint
114
+ // Proposer shuffling
113
115
  previousProposers: ValidatorIndex[] | null;
114
116
  currentProposers: ValidatorIndex[];
115
117
  nextProposers: ValidatorIndex[];
116
118
  getBeaconProposer(slot: Slot): ValidatorIndex;
117
- computeAnchorCheckpoint(): {checkpoint: phase0.Checkpoint; blockHeader: phase0.BeaconBlockHeader};
118
119
 
119
120
  // Sync committees
120
121
  currentSyncCommittee: altair.SyncCommittee;
@@ -122,6 +123,8 @@ export interface IBeaconStateView {
122
123
  currentSyncCommitteeIndexed: SyncCommitteeCache;
123
124
  syncProposerReward: number;
124
125
  getIndexedSyncCommitteeAtEpoch(epoch: Epoch): SyncCommitteeCache;
126
+ /** Get indexed sync committee with slot+1 offset for duty lookups */
127
+ getIndexedSyncCommittee(slot: Slot): SyncCommitteeCache;
125
128
 
126
129
  // Validators and balances
127
130
  effectiveBalanceIncrements: EffectiveBalanceIncrements;
@@ -148,6 +151,7 @@ export interface IBeaconStateView {
148
151
  expectedWithdrawals: capella.Withdrawal[];
149
152
  processedBuilderWithdrawalsCount: number;
150
153
  processedPartialWithdrawalsCount: number;
154
+ processedBuildersSweepCount: number;
151
155
  processedValidatorSweepCount: number;
152
156
  };
153
157
 
@@ -179,6 +183,7 @@ export interface IBeaconStateView {
179
183
  justifiedCheckpoint: phase0.Checkpoint;
180
184
  finalizedCheckpoint: phase0.Checkpoint;
181
185
  };
186
+ computeAnchorCheckpoint(): {checkpoint: phase0.Checkpoint; blockHeader: phase0.BeaconBlockHeader};
182
187
 
183
188
  // this is for backward compatible
184
189
  clonedCount: number;
@@ -189,6 +194,7 @@ export interface IBeaconStateView {
189
194
 
190
195
  // Serialization
191
196
  loadOtherState(stateBytes: Uint8Array, seedValidatorsBytes?: Uint8Array): IBeaconStateView;
197
+ toValue(): BeaconState;
192
198
  serialize(): Uint8Array;
193
199
  serializedSize(): number;
194
200
  serializeToBytes(output: ByteViews, offset: number): number;
@@ -209,5 +215,8 @@ export interface IBeaconStateView {
209
215
  epochTransitionCacheOpts?: EpochTransitionCacheOpts & {dontTransferCache?: boolean},
210
216
  modules?: StateTransitionModules
211
217
  ): IBeaconStateView;
212
- processExecutionPayloadEnvelope(signedEnvelope: gloas.SignedExecutionPayloadEnvelope, verify: boolean): void;
218
+ processExecutionPayloadEnvelope(
219
+ signedEnvelope: gloas.SignedExecutionPayloadEnvelope,
220
+ opts?: ProcessExecutionPayloadEnvelopeOpts
221
+ ): IBeaconStateView;
213
222
  }
@@ -0,0 +1,78 @@
1
+ import {BeaconConfig} from "@lodestar/config";
2
+ import {PubkeyCache, createPubkeyCache} from "../cache/pubkeyCache.js";
3
+ import {createCachedBeaconState} from "../cache/stateCache.js";
4
+ import {BeaconStateAllForks} from "../cache/types.js";
5
+ import {getStateTypeFromBytes} from "../util/sszBytes.js";
6
+ import {BeaconStateView} from "./beaconStateView.js";
7
+ import {IBeaconStateView} from "./interface.js";
8
+
9
+ // ---- createBeaconStateView (startup path) ----
10
+
11
+ type NodeJSOpts = {
12
+ useNative: false;
13
+ anchorState: BeaconStateAllForks;
14
+ config: BeaconConfig;
15
+ pubkeyCache: PubkeyCache;
16
+ };
17
+
18
+ type NativeOpts = {
19
+ useNative: true;
20
+ stateBytes: Uint8Array;
21
+ };
22
+
23
+ /**
24
+ * Create a BeaconStateView from a pre-deserialized state. Used at node startup.
25
+ *
26
+ * The caller is responsible for creating and populating `pubkeyCache` (it is also
27
+ * passed separately to BeaconNode.init, so it must live outside this factory).
28
+ *
29
+ * Set `useNative: true` to use the native (Zig) implementation once available.
30
+ */
31
+ export function createBeaconStateView(opts: NodeJSOpts | NativeOpts): IBeaconStateView {
32
+ if (opts.useNative) {
33
+ throw new Error("Native (Zig) BeaconStateView not yet implemented");
34
+ }
35
+ const {anchorState, config, pubkeyCache} = opts;
36
+ const cachedState = createCachedBeaconState(anchorState, {config, pubkeyCache}, {skipSyncPubkeys: true});
37
+ return new BeaconStateView(cachedState);
38
+ }
39
+
40
+ // ---- createBeaconStateViewForHistoricalRegen (regen path) ----
41
+
42
+ // Reused across all historical state regen calls in the worker thread
43
+ const pubkeyCacheRegen = createPubkeyCache();
44
+
45
+ function syncPubkeyCache(state: BeaconStateAllForks, pubkeyCache: PubkeyCache): void {
46
+ const newCount = state.validators.length;
47
+ for (let i = pubkeyCache.size; i < newCount; i++) {
48
+ const pubkey = state.validators.getReadonly(i).pubkey;
49
+ pubkeyCache.set(i, pubkey);
50
+ }
51
+ }
52
+
53
+ type RegenNodeJSOpts = {
54
+ useNative: false;
55
+ config: BeaconConfig;
56
+ stateBytes: Uint8Array;
57
+ };
58
+
59
+ type RegenNativeOpts = {
60
+ useNative: true;
61
+ stateBytes: Uint8Array;
62
+ };
63
+
64
+ /**
65
+ * Create a BeaconStateView from raw SSZ bytes. Used in the historical state regen worker thread.
66
+ *
67
+ * Set `useNative: true` to use the native (Zig) implementation once available.
68
+ */
69
+ export function createBeaconStateViewForHistoricalRegen(opts: RegenNodeJSOpts | RegenNativeOpts): IBeaconStateView {
70
+ if (opts.useNative) {
71
+ throw new Error("Native (Zig) BeaconStateView not yet implemented");
72
+ }
73
+ const {config, stateBytes} = opts;
74
+ const state = getStateTypeFromBytes(config, stateBytes).deserializeToViewDU(stateBytes);
75
+ syncPubkeyCache(state, pubkeyCacheRegen);
76
+ const cachedState = createCachedBeaconState(state, {config, pubkeyCache: pubkeyCacheRegen}, {skipSyncPubkeys: true});
77
+ return new BeaconStateView(cachedState);
78
+ }
@@ -143,7 +143,7 @@ export function executionPayloadToPayloadHeader(fork: ForkSeq, payload: Executio
143
143
  }
144
144
 
145
145
  if (fork >= ForkSeq.deneb) {
146
- // https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/beacon-chain.md#process_execution_payload
146
+ // https://github.com/ethereum/consensus-specs/blob/v1.3.0-rc.2/specs/eip4844/beacon-chain.md#process_execution_payload
147
147
  (bellatrixPayloadFields as deneb.ExecutionPayloadHeader).blobGasUsed = (
148
148
  payload as deneb.ExecutionPayloadHeader | deneb.ExecutionPayload
149
149
  ).blobGasUsed;
@@ -1,6 +1,5 @@
1
1
  import {Epoch, Root, Slot, phase0} from "@lodestar/types";
2
- import {CachedBeaconStateAllForks} from "../types.js";
3
- import {getBlockRoot, getBlockRootAtSlot} from "./blockRoot.js";
2
+ import {IBeaconStateView} from "../stateView/interface.js";
4
3
 
5
4
  /**
6
5
  * Cache to prevent accessing the state tree to fetch block roots repeteadly.
@@ -12,7 +11,7 @@ export class RootCache {
12
11
  private readonly blockRootEpochCache = new Map<Epoch, Root>();
13
12
  private readonly blockRootSlotCache = new Map<Slot, Root>();
14
13
 
15
- constructor(private readonly state: CachedBeaconStateAllForks) {
14
+ constructor(private readonly state: IBeaconStateView) {
16
15
  this.currentJustifiedCheckpoint = state.currentJustifiedCheckpoint;
17
16
  this.previousJustifiedCheckpoint = state.previousJustifiedCheckpoint;
18
17
  }
@@ -20,7 +19,7 @@ export class RootCache {
20
19
  getBlockRoot(epoch: Epoch): Root {
21
20
  let root = this.blockRootEpochCache.get(epoch);
22
21
  if (!root) {
23
- root = getBlockRoot(this.state, epoch);
22
+ root = this.state.getBlockRootAtEpoch(epoch);
24
23
  this.blockRootEpochCache.set(epoch, root);
25
24
  }
26
25
  return root;
@@ -29,7 +28,7 @@ export class RootCache {
29
28
  getBlockRootAtSlot(slot: Slot): Root {
30
29
  let root = this.blockRootSlotCache.get(slot);
31
30
  if (!root) {
32
- root = getBlockRootAtSlot(this.state, slot);
31
+ root = this.state.getBlockRootAtSlot(slot);
33
32
  this.blockRootSlotCache.set(slot, root);
34
33
  }
35
34
  return root;
@@ -11,6 +11,7 @@ import {
11
11
  } from "@lodestar/types";
12
12
  import {LodestarError} from "@lodestar/utils";
13
13
  import {CachedBeaconStateAllForks} from "../cache/stateCache.js";
14
+ import {IBeaconStateView} from "../stateView/interface.js";
14
15
  import {getBlockRootAtSlot} from "./blockRoot.js";
15
16
  import {computeStartSlotAtEpoch} from "./epoch.js";
16
17
  import {EpochShuffling} from "./epochShuffling.js";
@@ -22,21 +23,21 @@ import {EpochShuffling} from "./epochShuffling.js";
22
23
  * Returns `null` on the one-off scenario where the genesis block decides its own shuffling.
23
24
  * It should be set to the latest block applied to this `state` or the genesis block root.
24
25
  */
25
- export function proposerShufflingDecisionRoot(fork: ForkName, state: CachedBeaconStateAllForks): Root | null {
26
+ export function proposerShufflingDecisionRoot(fork: ForkName, state: IBeaconStateView): Root | null {
26
27
  const decisionSlot = proposerShufflingDecisionSlot(fork, state);
27
28
  if (state.slot === decisionSlot) {
28
29
  return null;
29
30
  }
30
- return getBlockRootAtSlot(state, decisionSlot);
31
+ return state.getBlockRootAtSlot(decisionSlot);
31
32
  }
32
33
 
33
34
  /**
34
35
  * Returns the slot at which the proposer shuffling was decided. The block root at this slot
35
36
  * can be used to key the proposer shuffling for the current epoch.
36
37
  */
37
- function proposerShufflingDecisionSlot(fork: ForkName, state: CachedBeaconStateAllForks): Slot {
38
+ function proposerShufflingDecisionSlot(fork: ForkName, state: IBeaconStateView): Slot {
38
39
  // After fulu, the decision slot is in previous epoch due to deterministic proposer lookahead
39
- const epoch = isForkPostFulu(fork) ? state.epochCtx.epoch - 1 : state.epochCtx.epoch;
40
+ const epoch = isForkPostFulu(fork) ? state.epoch - 1 : state.epoch;
40
41
  const startSlot = computeStartSlotAtEpoch(epoch);
41
42
  return Math.max(startSlot - 1, 0);
42
43
  }