@lodestar/state-transition 1.35.0-dev.fcf8d024ea → 1.35.0-dev.feed916580

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 (237) hide show
  1. package/lib/cache/types.d.ts +2 -2
  2. package/lib/util/genesis.js +3 -0
  3. package/lib/util/genesis.js.map +1 -1
  4. package/lib/util/slot.d.ts +1 -0
  5. package/lib/util/slot.js +5 -1
  6. package/lib/util/slot.js.map +1 -1
  7. package/package.json +11 -13
  8. package/lib/block/externalData.d.ts.map +0 -1
  9. package/lib/block/index.d.ts.map +0 -1
  10. package/lib/block/initiateValidatorExit.d.ts.map +0 -1
  11. package/lib/block/isValidIndexedAttestation.d.ts.map +0 -1
  12. package/lib/block/processAttestationPhase0.d.ts.map +0 -1
  13. package/lib/block/processAttestations.d.ts.map +0 -1
  14. package/lib/block/processAttestationsAltair.d.ts.map +0 -1
  15. package/lib/block/processAttesterSlashing.d.ts.map +0 -1
  16. package/lib/block/processBlobKzgCommitments.d.ts.map +0 -1
  17. package/lib/block/processBlockHeader.d.ts.map +0 -1
  18. package/lib/block/processBlsToExecutionChange.d.ts.map +0 -1
  19. package/lib/block/processConsolidationRequest.d.ts.map +0 -1
  20. package/lib/block/processDeposit.d.ts.map +0 -1
  21. package/lib/block/processDepositRequest.d.ts.map +0 -1
  22. package/lib/block/processEth1Data.d.ts.map +0 -1
  23. package/lib/block/processExecutionPayload.d.ts.map +0 -1
  24. package/lib/block/processOperations.d.ts.map +0 -1
  25. package/lib/block/processProposerSlashing.d.ts.map +0 -1
  26. package/lib/block/processRandao.d.ts.map +0 -1
  27. package/lib/block/processSyncCommittee.d.ts.map +0 -1
  28. package/lib/block/processVoluntaryExit.d.ts.map +0 -1
  29. package/lib/block/processWithdrawalRequest.d.ts.map +0 -1
  30. package/lib/block/processWithdrawals.d.ts.map +0 -1
  31. package/lib/block/slashValidator.d.ts.map +0 -1
  32. package/lib/block/types.d.ts.map +0 -1
  33. package/lib/cache/effectiveBalanceIncrements.d.ts.map +0 -1
  34. package/lib/cache/epochCache.d.ts.map +0 -1
  35. package/lib/cache/epochTransitionCache.d.ts.map +0 -1
  36. package/lib/cache/pubkeyCache.d.ts.map +0 -1
  37. package/lib/cache/rewardCache.d.ts.map +0 -1
  38. package/lib/cache/stateCache.d.ts.map +0 -1
  39. package/lib/cache/syncCommitteeCache.d.ts.map +0 -1
  40. package/lib/cache/types.d.ts.map +0 -1
  41. package/lib/constants/constants.d.ts.map +0 -1
  42. package/lib/constants/index.d.ts.map +0 -1
  43. package/lib/epoch/computeUnrealizedCheckpoints.d.ts.map +0 -1
  44. package/lib/epoch/getAttestationDeltas.d.ts.map +0 -1
  45. package/lib/epoch/getRewardsAndPenalties.d.ts.map +0 -1
  46. package/lib/epoch/index.d.ts.map +0 -1
  47. package/lib/epoch/processEffectiveBalanceUpdates.d.ts.map +0 -1
  48. package/lib/epoch/processEth1DataReset.d.ts.map +0 -1
  49. package/lib/epoch/processHistoricalRootsUpdate.d.ts.map +0 -1
  50. package/lib/epoch/processHistoricalSummariesUpdate.d.ts.map +0 -1
  51. package/lib/epoch/processInactivityUpdates.d.ts.map +0 -1
  52. package/lib/epoch/processJustificationAndFinalization.d.ts.map +0 -1
  53. package/lib/epoch/processParticipationFlagUpdates.d.ts.map +0 -1
  54. package/lib/epoch/processParticipationRecordUpdates.d.ts.map +0 -1
  55. package/lib/epoch/processPendingAttestations.d.ts.map +0 -1
  56. package/lib/epoch/processPendingConsolidations.d.ts.map +0 -1
  57. package/lib/epoch/processPendingDeposits.d.ts.map +0 -1
  58. package/lib/epoch/processProposerLookahead.d.ts.map +0 -1
  59. package/lib/epoch/processRandaoMixesReset.d.ts.map +0 -1
  60. package/lib/epoch/processRegistryUpdates.d.ts.map +0 -1
  61. package/lib/epoch/processRewardsAndPenalties.d.ts.map +0 -1
  62. package/lib/epoch/processSlashings.d.ts.map +0 -1
  63. package/lib/epoch/processSlashingsReset.d.ts.map +0 -1
  64. package/lib/epoch/processSyncCommitteeUpdates.d.ts.map +0 -1
  65. package/lib/index.d.ts.map +0 -1
  66. package/lib/metrics.d.ts.map +0 -1
  67. package/lib/signatureSets/attesterSlashings.d.ts.map +0 -1
  68. package/lib/signatureSets/blsToExecutionChange.d.ts.map +0 -1
  69. package/lib/signatureSets/index.d.ts.map +0 -1
  70. package/lib/signatureSets/indexedAttestation.d.ts.map +0 -1
  71. package/lib/signatureSets/proposer.d.ts.map +0 -1
  72. package/lib/signatureSets/proposerSlashings.d.ts.map +0 -1
  73. package/lib/signatureSets/randao.d.ts.map +0 -1
  74. package/lib/signatureSets/voluntaryExits.d.ts.map +0 -1
  75. package/lib/slot/index.d.ts.map +0 -1
  76. package/lib/slot/upgradeStateToAltair.d.ts.map +0 -1
  77. package/lib/slot/upgradeStateToBellatrix.d.ts.map +0 -1
  78. package/lib/slot/upgradeStateToCapella.d.ts.map +0 -1
  79. package/lib/slot/upgradeStateToDeneb.d.ts.map +0 -1
  80. package/lib/slot/upgradeStateToElectra.d.ts.map +0 -1
  81. package/lib/slot/upgradeStateToFulu.d.ts.map +0 -1
  82. package/lib/slot/upgradeStateToGloas.d.ts.map +0 -1
  83. package/lib/stateTransition.d.ts.map +0 -1
  84. package/lib/types.d.ts.map +0 -1
  85. package/lib/util/aggregator.d.ts.map +0 -1
  86. package/lib/util/altair.d.ts.map +0 -1
  87. package/lib/util/array.d.ts.map +0 -1
  88. package/lib/util/attestation.d.ts.map +0 -1
  89. package/lib/util/attesterStatus.d.ts.map +0 -1
  90. package/lib/util/balance.d.ts.map +0 -1
  91. package/lib/util/blindedBlock.d.ts.map +0 -1
  92. package/lib/util/blockRoot.d.ts.map +0 -1
  93. package/lib/util/calculateCommitteeAssignments.d.ts.map +0 -1
  94. package/lib/util/capella.d.ts.map +0 -1
  95. package/lib/util/computeAnchorCheckpoint.d.ts.map +0 -1
  96. package/lib/util/deposit.d.ts.map +0 -1
  97. package/lib/util/domain.d.ts.map +0 -1
  98. package/lib/util/electra.d.ts.map +0 -1
  99. package/lib/util/epoch.d.ts.map +0 -1
  100. package/lib/util/epochShuffling.d.ts.map +0 -1
  101. package/lib/util/execution.d.ts.map +0 -1
  102. package/lib/util/finality.d.ts.map +0 -1
  103. package/lib/util/fulu.d.ts.map +0 -1
  104. package/lib/util/genesis.d.ts.map +0 -1
  105. package/lib/util/index.d.ts.map +0 -1
  106. package/lib/util/interop.d.ts.map +0 -1
  107. package/lib/util/loadState/findModifiedInactivityScores.d.ts.map +0 -1
  108. package/lib/util/loadState/findModifiedValidators.d.ts.map +0 -1
  109. package/lib/util/loadState/index.d.ts.map +0 -1
  110. package/lib/util/loadState/loadState.d.ts.map +0 -1
  111. package/lib/util/loadState/loadValidator.d.ts.map +0 -1
  112. package/lib/util/rootCache.d.ts.map +0 -1
  113. package/lib/util/seed.d.ts.map +0 -1
  114. package/lib/util/shufflingDecisionRoot.d.ts.map +0 -1
  115. package/lib/util/signatureSets.d.ts.map +0 -1
  116. package/lib/util/signingRoot.d.ts.map +0 -1
  117. package/lib/util/slot.d.ts.map +0 -1
  118. package/lib/util/sszBytes.d.ts.map +0 -1
  119. package/lib/util/syncCommittee.d.ts.map +0 -1
  120. package/lib/util/targetUnslashedBalance.d.ts.map +0 -1
  121. package/lib/util/validator.d.ts.map +0 -1
  122. package/lib/util/weakSubjectivity.d.ts.map +0 -1
  123. package/src/block/externalData.ts +0 -26
  124. package/src/block/index.ts +0 -81
  125. package/src/block/initiateValidatorExit.ts +0 -62
  126. package/src/block/isValidIndexedAttestation.ts +0 -70
  127. package/src/block/processAttestationPhase0.ts +0 -158
  128. package/src/block/processAttestations.ts +0 -25
  129. package/src/block/processAttestationsAltair.ts +0 -184
  130. package/src/block/processAttesterSlashing.ts +0 -59
  131. package/src/block/processBlobKzgCommitments.ts +0 -21
  132. package/src/block/processBlockHeader.ts +0 -54
  133. package/src/block/processBlsToExecutionChange.ts +0 -78
  134. package/src/block/processConsolidationRequest.ts +0 -147
  135. package/src/block/processDeposit.ts +0 -166
  136. package/src/block/processDepositRequest.ts +0 -19
  137. package/src/block/processEth1Data.ts +0 -86
  138. package/src/block/processExecutionPayload.ts +0 -84
  139. package/src/block/processOperations.ts +0 -83
  140. package/src/block/processProposerSlashing.ts +0 -66
  141. package/src/block/processRandao.ts +0 -27
  142. package/src/block/processSyncCommittee.ts +0 -117
  143. package/src/block/processVoluntaryExit.ts +0 -55
  144. package/src/block/processWithdrawalRequest.ts +0 -98
  145. package/src/block/processWithdrawals.ts +0 -207
  146. package/src/block/slashValidator.ts +0 -98
  147. package/src/block/types.ts +0 -9
  148. package/src/cache/effectiveBalanceIncrements.ts +0 -39
  149. package/src/cache/epochCache.ts +0 -1213
  150. package/src/cache/epochTransitionCache.ts +0 -542
  151. package/src/cache/pubkeyCache.ts +0 -33
  152. package/src/cache/rewardCache.ts +0 -19
  153. package/src/cache/stateCache.ts +0 -268
  154. package/src/cache/syncCommitteeCache.ts +0 -96
  155. package/src/cache/types.ts +0 -18
  156. package/src/constants/constants.ts +0 -12
  157. package/src/constants/index.ts +0 -1
  158. package/src/epoch/computeUnrealizedCheckpoints.ts +0 -55
  159. package/src/epoch/getAttestationDeltas.ts +0 -169
  160. package/src/epoch/getRewardsAndPenalties.ts +0 -137
  161. package/src/epoch/index.ts +0 -202
  162. package/src/epoch/processEffectiveBalanceUpdates.ts +0 -111
  163. package/src/epoch/processEth1DataReset.ts +0 -17
  164. package/src/epoch/processHistoricalRootsUpdate.ts +0 -25
  165. package/src/epoch/processHistoricalSummariesUpdate.ts +0 -23
  166. package/src/epoch/processInactivityUpdates.ts +0 -60
  167. package/src/epoch/processJustificationAndFinalization.ts +0 -90
  168. package/src/epoch/processParticipationFlagUpdates.ts +0 -27
  169. package/src/epoch/processParticipationRecordUpdates.ts +0 -14
  170. package/src/epoch/processPendingAttestations.ts +0 -75
  171. package/src/epoch/processPendingConsolidations.ts +0 -59
  172. package/src/epoch/processPendingDeposits.ts +0 -136
  173. package/src/epoch/processProposerLookahead.ts +0 -39
  174. package/src/epoch/processRandaoMixesReset.ts +0 -18
  175. package/src/epoch/processRegistryUpdates.ts +0 -65
  176. package/src/epoch/processRewardsAndPenalties.ts +0 -58
  177. package/src/epoch/processSlashings.ts +0 -97
  178. package/src/epoch/processSlashingsReset.ts +0 -20
  179. package/src/epoch/processSyncCommitteeUpdates.ts +0 -44
  180. package/src/index.ts +0 -67
  181. package/src/metrics.ts +0 -169
  182. package/src/signatureSets/attesterSlashings.ts +0 -39
  183. package/src/signatureSets/blsToExecutionChange.ts +0 -43
  184. package/src/signatureSets/index.ts +0 -73
  185. package/src/signatureSets/indexedAttestation.ts +0 -51
  186. package/src/signatureSets/proposer.ts +0 -47
  187. package/src/signatureSets/proposerSlashings.ts +0 -41
  188. package/src/signatureSets/randao.ts +0 -31
  189. package/src/signatureSets/voluntaryExits.ts +0 -44
  190. package/src/slot/index.ts +0 -32
  191. package/src/slot/upgradeStateToAltair.ts +0 -149
  192. package/src/slot/upgradeStateToBellatrix.ts +0 -63
  193. package/src/slot/upgradeStateToCapella.ts +0 -71
  194. package/src/slot/upgradeStateToDeneb.ts +0 -40
  195. package/src/slot/upgradeStateToElectra.ts +0 -126
  196. package/src/slot/upgradeStateToFulu.ts +0 -31
  197. package/src/slot/upgradeStateToGloas.ts +0 -29
  198. package/src/stateTransition.ts +0 -305
  199. package/src/types.ts +0 -26
  200. package/src/util/aggregator.ts +0 -33
  201. package/src/util/altair.ts +0 -13
  202. package/src/util/array.ts +0 -53
  203. package/src/util/attestation.ts +0 -36
  204. package/src/util/attesterStatus.ts +0 -83
  205. package/src/util/balance.ts +0 -83
  206. package/src/util/blindedBlock.ts +0 -144
  207. package/src/util/blockRoot.ts +0 -72
  208. package/src/util/calculateCommitteeAssignments.ts +0 -43
  209. package/src/util/capella.ts +0 -8
  210. package/src/util/computeAnchorCheckpoint.ts +0 -38
  211. package/src/util/deposit.ts +0 -22
  212. package/src/util/domain.ts +0 -31
  213. package/src/util/electra.ts +0 -68
  214. package/src/util/epoch.ts +0 -135
  215. package/src/util/epochShuffling.ts +0 -185
  216. package/src/util/execution.ts +0 -177
  217. package/src/util/finality.ts +0 -17
  218. package/src/util/fulu.ts +0 -43
  219. package/src/util/genesis.ts +0 -340
  220. package/src/util/index.ts +0 -29
  221. package/src/util/interop.ts +0 -22
  222. package/src/util/loadState/findModifiedInactivityScores.ts +0 -47
  223. package/src/util/loadState/findModifiedValidators.ts +0 -46
  224. package/src/util/loadState/index.ts +0 -2
  225. package/src/util/loadState/loadState.ts +0 -225
  226. package/src/util/loadState/loadValidator.ts +0 -77
  227. package/src/util/rootCache.ts +0 -37
  228. package/src/util/seed.ts +0 -381
  229. package/src/util/shufflingDecisionRoot.ts +0 -78
  230. package/src/util/signatureSets.ts +0 -65
  231. package/src/util/signingRoot.ts +0 -13
  232. package/src/util/slot.ts +0 -22
  233. package/src/util/sszBytes.ts +0 -52
  234. package/src/util/syncCommittee.ts +0 -69
  235. package/src/util/targetUnslashedBalance.ts +0 -30
  236. package/src/util/validator.ts +0 -105
  237. package/src/util/weakSubjectivity.ts +0 -186
@@ -1,1213 +0,0 @@
1
- import {PublicKey} from "@chainsafe/blst";
2
- import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
3
- import {BeaconConfig, ChainConfig, createBeaconConfig} from "@lodestar/config";
4
- import {
5
- ATTESTATION_SUBNET_COUNT,
6
- DOMAIN_BEACON_PROPOSER,
7
- EFFECTIVE_BALANCE_INCREMENT,
8
- FAR_FUTURE_EPOCH,
9
- ForkSeq,
10
- GENESIS_EPOCH,
11
- PROPOSER_WEIGHT,
12
- SLOTS_PER_EPOCH,
13
- WEIGHT_DENOMINATOR,
14
- } from "@lodestar/params";
15
- import {
16
- Attestation,
17
- BLSSignature,
18
- CommitteeIndex,
19
- Epoch,
20
- IndexedAttestation,
21
- RootHex,
22
- Slot,
23
- SubnetID,
24
- SyncPeriod,
25
- ValidatorIndex,
26
- electra,
27
- phase0,
28
- } from "@lodestar/types";
29
- import {LodestarError} from "@lodestar/utils";
30
- import {getTotalSlashingsByIncrement} from "../epoch/processSlashings.js";
31
- import {AttesterDuty, calculateCommitteeAssignments} from "../util/calculateCommitteeAssignments.js";
32
- import {
33
- EpochShuffling,
34
- IShufflingCache,
35
- calculateShufflingDecisionRoot,
36
- computeEpochShuffling,
37
- } from "../util/epochShuffling.js";
38
- import {
39
- computeActivationExitEpoch,
40
- computeEpochAtSlot,
41
- computeProposers,
42
- computeStartSlotAtEpoch,
43
- computeSyncPeriodAtEpoch,
44
- getActivationChurnLimit,
45
- getChurnLimit,
46
- getSeed,
47
- isActiveValidator,
48
- isAggregatorFromCommitteeLength,
49
- } from "../util/index.js";
50
- import {computeBaseRewardPerIncrement, computeSyncParticipantReward} from "../util/syncCommittee.js";
51
- import {sumTargetUnslashedBalanceIncrements} from "../util/targetUnslashedBalance.js";
52
- import {EffectiveBalanceIncrements, getEffectiveBalanceIncrementsWithLen} from "./effectiveBalanceIncrements.js";
53
- import {EpochTransitionCache} from "./epochTransitionCache.js";
54
- import {Index2PubkeyCache, syncPubkeys} from "./pubkeyCache.js";
55
- import {CachedBeaconStateAllForks, CachedBeaconStateFulu} from "./stateCache.js";
56
- import {
57
- SyncCommitteeCache,
58
- SyncCommitteeCacheEmpty,
59
- computeSyncCommitteeCache,
60
- getSyncCommitteeCache,
61
- } from "./syncCommitteeCache.js";
62
- import {BeaconStateAllForks, BeaconStateAltair} from "./types.js";
63
-
64
- /** `= PROPOSER_WEIGHT / (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT)` */
65
- export const PROPOSER_WEIGHT_FACTOR = PROPOSER_WEIGHT / (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT);
66
-
67
- export type EpochCacheImmutableData = {
68
- config: BeaconConfig;
69
- pubkey2index: PubkeyIndexMap;
70
- index2pubkey: Index2PubkeyCache;
71
- shufflingCache?: IShufflingCache;
72
- };
73
-
74
- export type EpochCacheOpts = {
75
- skipSyncCommitteeCache?: boolean;
76
- skipSyncPubkeys?: boolean;
77
- };
78
-
79
- /** Defers computing proposers by persisting only the seed, and dropping it once indexes are computed */
80
- type ProposersDeferred = {computed: false; seed: Uint8Array} | {computed: true; indexes: ValidatorIndex[]};
81
-
82
- /**
83
- * EpochCache is the parent object of:
84
- * - Any data-structures not part of the spec'ed BeaconState
85
- * - Necessary to only compute data once
86
- * - Must be kept at all times through an epoch
87
- *
88
- * The performance gains with EpochCache are fundamental for the BeaconNode to be able to participate in a
89
- * production network with 100_000s of validators. In summary, it contains:
90
- *
91
- * Expensive data constant through the epoch:
92
- * - pubkey cache
93
- * - proposer indexes
94
- * - shufflings
95
- * - sync committee indexed
96
- * Counters (maybe) mutated through the epoch:
97
- * - churnLimit
98
- * - exitQueueEpoch
99
- * - exitQueueChurn
100
- * Time data faster than recomputing from the state:
101
- * - epoch
102
- * - syncPeriod
103
- **/
104
- export class EpochCache {
105
- config: BeaconConfig;
106
- /**
107
- * Unique globally shared pubkey registry. There should only exist one for the entire application.
108
- *
109
- * TODO: this is a hack, we need a safety mechanism in case a bad eth1 majority vote is in,
110
- * or handle non finalized data differently, or use an immutable.js structure for cheap copies
111
- *
112
- * $VALIDATOR_COUNT x 192 char String -> Number Map
113
- */
114
- pubkey2index: PubkeyIndexMap;
115
- /**
116
- * Unique globally shared pubkey registry. There should only exist one for the entire application.
117
- *
118
- * $VALIDATOR_COUNT x BLST deserialized pubkey (Jacobian coordinates)
119
- */
120
- index2pubkey: Index2PubkeyCache;
121
- /**
122
- * ShufflingCache is passed in from `beacon-node` so should be available at runtime but may not be
123
- * present during testing.
124
- */
125
- shufflingCache?: IShufflingCache;
126
-
127
- /**
128
- * Indexes of the block proposers for the current epoch.
129
- * For pre-fulu, this is computed and cached from the current shuffling.
130
- * For post-fulu, this is copied from the state.proposerLookahead.
131
- *
132
- * 32 x Number
133
- */
134
- proposers: ValidatorIndex[];
135
-
136
- /** Proposers for previous epoch, initialized to null in first epoch */
137
- proposersPrevEpoch: ValidatorIndex[] | null;
138
-
139
- /**
140
- * The next proposer seed is only used in the getBeaconProposersNextEpoch call. It cannot be moved into
141
- * getBeaconProposersNextEpoch because it needs state as input and all data needed by getBeaconProposersNextEpoch
142
- * should be in the epoch context.
143
- *
144
- * For pre-fulu, this is lazily computed from the next epoch's shuffling.
145
- * For post-fulu, this is copied from the state.proposerLookahead.
146
- */
147
- proposersNextEpoch: ProposersDeferred;
148
-
149
- /**
150
- * Epoch decision roots to look up correct shuffling from the Shuffling Cache
151
- */
152
- previousDecisionRoot: RootHex;
153
- currentDecisionRoot: RootHex;
154
- nextDecisionRoot: RootHex;
155
- /**
156
- * Shuffling of validator indexes. Immutable through the epoch, then it's replaced entirely.
157
- * Note: Per spec definition, shuffling will always be defined. They are never called before loadState()
158
- *
159
- * $VALIDATOR_COUNT x Number
160
- */
161
- previousShuffling: EpochShuffling;
162
- /** Same as previousShuffling */
163
- currentShuffling: EpochShuffling;
164
- /** Same as previousShuffling */
165
- nextShuffling: EpochShuffling | null;
166
- /**
167
- * Cache nextActiveIndices so that in afterProcessEpoch the next shuffling can be build synchronously
168
- * in case it is not built or the ShufflingCache is not available
169
- */
170
- nextActiveIndices: Uint32Array;
171
- /**
172
- * Effective balances, for altair processAttestations()
173
- */
174
- effectiveBalanceIncrements: EffectiveBalanceIncrements;
175
- /**
176
- * Total state.slashings by increment, for processSlashing()
177
- */
178
- totalSlashingsByIncrement: number;
179
- syncParticipantReward: number;
180
- syncProposerReward: number;
181
- /**
182
- * Update freq: once per epoch after `process_effective_balance_updates()`
183
- */
184
- baseRewardPerIncrement: number;
185
- /**
186
- * Total active balance for current epoch, to be used instead of getTotalBalance()
187
- */
188
- totalActiveBalanceIncrements: number;
189
-
190
- /**
191
- * Rate at which validators can enter or leave the set per epoch. Depends only on activeIndexes, so it does not
192
- * change through the epoch. It's used in initiateValidatorExit(). Must be update after changing active indexes.
193
- */
194
- churnLimit: number;
195
-
196
- /**
197
- * Fork limited actual activationChurnLimit
198
- */
199
- activationChurnLimit: number;
200
- /**
201
- * Closest epoch with available churn for validators to exit at. May be updated every block as validators are
202
- * initiateValidatorExit(). This value may vary on each fork of the state.
203
- *
204
- * NOTE: Changes block to block
205
- * NOTE: No longer used by initiateValidatorExit post-electra
206
- */
207
- exitQueueEpoch: Epoch;
208
- /**
209
- * Number of validators initiating an exit at exitQueueEpoch. May be updated every block as validators are
210
- * initiateValidatorExit(). This value may vary on each fork of the state.
211
- *
212
- * NOTE: Changes block to block
213
- * NOTE: No longer used by initiateValidatorExit post-electra
214
- */
215
- exitQueueChurn: number;
216
-
217
- /**
218
- * Total cumulative balance increments through epoch for current target.
219
- * Required for unrealized checkpoints issue pull-up tips N+1. Otherwise must run epoch transition every block
220
- * This value is equivalent to:
221
- * - Forward current state to end-of-epoch
222
- * - Run beforeProcessEpoch
223
- * - epochTransitionCache.currEpochUnslashedTargetStakeByIncrement
224
- */
225
- currentTargetUnslashedBalanceIncrements: number;
226
- /**
227
- * Total cumulative balance increments through epoch for previous target.
228
- * Required for unrealized checkpoints issue pull-up tips N+1. Otherwise must run epoch transition every block
229
- * This value is equivalent to:
230
- * - Forward current state to end-of-epoch
231
- * - Run beforeProcessEpoch
232
- * - epochTransitionCache.prevEpochUnslashedStake.targetStakeByIncrement
233
- */
234
- previousTargetUnslashedBalanceIncrements: number;
235
-
236
- /** TODO: Indexed SyncCommitteeCache */
237
- currentSyncCommitteeIndexed: SyncCommitteeCache;
238
- /** TODO: Indexed SyncCommitteeCache */
239
- nextSyncCommitteeIndexed: SyncCommitteeCache;
240
-
241
- // TODO: Helper stats
242
- syncPeriod: SyncPeriod;
243
-
244
- epoch: Epoch;
245
-
246
- get nextEpoch(): Epoch {
247
- return this.epoch + 1;
248
- }
249
-
250
- constructor(data: {
251
- config: BeaconConfig;
252
- pubkey2index: PubkeyIndexMap;
253
- index2pubkey: Index2PubkeyCache;
254
- shufflingCache?: IShufflingCache;
255
- proposers: number[];
256
- proposersPrevEpoch: number[] | null;
257
- proposersNextEpoch: ProposersDeferred;
258
- previousDecisionRoot: RootHex;
259
- currentDecisionRoot: RootHex;
260
- nextDecisionRoot: RootHex;
261
- previousShuffling: EpochShuffling;
262
- currentShuffling: EpochShuffling;
263
- nextShuffling: EpochShuffling | null;
264
- nextActiveIndices: Uint32Array;
265
- effectiveBalanceIncrements: EffectiveBalanceIncrements;
266
- totalSlashingsByIncrement: number;
267
- syncParticipantReward: number;
268
- syncProposerReward: number;
269
- baseRewardPerIncrement: number;
270
- totalActiveBalanceIncrements: number;
271
- churnLimit: number;
272
- activationChurnLimit: number;
273
- exitQueueEpoch: Epoch;
274
- exitQueueChurn: number;
275
- currentTargetUnslashedBalanceIncrements: number;
276
- previousTargetUnslashedBalanceIncrements: number;
277
- currentSyncCommitteeIndexed: SyncCommitteeCache;
278
- nextSyncCommitteeIndexed: SyncCommitteeCache;
279
- epoch: Epoch;
280
- syncPeriod: SyncPeriod;
281
- }) {
282
- this.config = data.config;
283
- this.pubkey2index = data.pubkey2index;
284
- this.index2pubkey = data.index2pubkey;
285
- this.shufflingCache = data.shufflingCache;
286
- this.proposers = data.proposers;
287
- this.proposersPrevEpoch = data.proposersPrevEpoch;
288
- this.proposersNextEpoch = data.proposersNextEpoch;
289
- this.previousDecisionRoot = data.previousDecisionRoot;
290
- this.currentDecisionRoot = data.currentDecisionRoot;
291
- this.nextDecisionRoot = data.nextDecisionRoot;
292
- this.previousShuffling = data.previousShuffling;
293
- this.currentShuffling = data.currentShuffling;
294
- this.nextShuffling = data.nextShuffling;
295
- this.nextActiveIndices = data.nextActiveIndices;
296
- this.effectiveBalanceIncrements = data.effectiveBalanceIncrements;
297
- this.totalSlashingsByIncrement = data.totalSlashingsByIncrement;
298
- this.syncParticipantReward = data.syncParticipantReward;
299
- this.syncProposerReward = data.syncProposerReward;
300
- this.baseRewardPerIncrement = data.baseRewardPerIncrement;
301
- this.totalActiveBalanceIncrements = data.totalActiveBalanceIncrements;
302
- this.churnLimit = data.churnLimit;
303
- this.activationChurnLimit = data.activationChurnLimit;
304
- this.exitQueueEpoch = data.exitQueueEpoch;
305
- this.exitQueueChurn = data.exitQueueChurn;
306
- this.currentTargetUnslashedBalanceIncrements = data.currentTargetUnslashedBalanceIncrements;
307
- this.previousTargetUnslashedBalanceIncrements = data.previousTargetUnslashedBalanceIncrements;
308
- this.currentSyncCommitteeIndexed = data.currentSyncCommitteeIndexed;
309
- this.nextSyncCommitteeIndexed = data.nextSyncCommitteeIndexed;
310
- this.epoch = data.epoch;
311
- this.syncPeriod = data.syncPeriod;
312
- }
313
-
314
- /**
315
- * Create an epoch cache
316
- * @param state a finalized beacon state. Passing in unfinalized state may cause unexpected behaviour
317
- *
318
- * SLOW CODE - 🐢
319
- */
320
- static createFromState(
321
- state: BeaconStateAllForks,
322
- {config, pubkey2index, index2pubkey, shufflingCache}: EpochCacheImmutableData,
323
- opts?: EpochCacheOpts
324
- ): EpochCache {
325
- const currentEpoch = computeEpochAtSlot(state.slot);
326
- const isGenesis = currentEpoch === GENESIS_EPOCH;
327
- const previousEpoch = isGenesis ? GENESIS_EPOCH : currentEpoch - 1;
328
- const nextEpoch = currentEpoch + 1;
329
-
330
- let totalActiveBalanceIncrements = 0;
331
- let exitQueueEpoch = computeActivationExitEpoch(currentEpoch);
332
- let exitQueueChurn = 0;
333
-
334
- const validators = state.validators.getAllReadonlyValues();
335
- const validatorCount = validators.length;
336
-
337
- // syncPubkeys here to ensure EpochCacheImmutableData is popualted before computing the rest of caches
338
- // - computeSyncCommitteeCache() needs a fully populated pubkey2index cache
339
- if (!opts?.skipSyncPubkeys) {
340
- syncPubkeys(validators, pubkey2index, index2pubkey);
341
- }
342
-
343
- const effectiveBalanceIncrements = getEffectiveBalanceIncrementsWithLen(validatorCount);
344
- const totalSlashingsByIncrement = getTotalSlashingsByIncrement(state);
345
- const previousActiveIndicesAsNumberArray: ValidatorIndex[] = [];
346
- const currentActiveIndicesAsNumberArray: ValidatorIndex[] = [];
347
- const nextActiveIndicesAsNumberArray: ValidatorIndex[] = [];
348
-
349
- // BeaconChain could provide a shuffling cache to avoid re-computing shuffling every epoch
350
- // in that case, we don't need to compute shufflings again
351
- const previousDecisionRoot = calculateShufflingDecisionRoot(config, state, previousEpoch);
352
- const cachedPreviousShuffling = shufflingCache?.getSync(previousEpoch, previousDecisionRoot);
353
- const currentDecisionRoot = calculateShufflingDecisionRoot(config, state, currentEpoch);
354
- const cachedCurrentShuffling = shufflingCache?.getSync(currentEpoch, currentDecisionRoot);
355
- const nextDecisionRoot = calculateShufflingDecisionRoot(config, state, nextEpoch);
356
- const cachedNextShuffling = shufflingCache?.getSync(nextEpoch, nextDecisionRoot);
357
-
358
- for (let i = 0; i < validatorCount; i++) {
359
- const validator = validators[i];
360
-
361
- // Note: Not usable for fork-choice balances since in-active validators are not zero'ed
362
- effectiveBalanceIncrements[i] = Math.floor(validator.effectiveBalance / EFFECTIVE_BALANCE_INCREMENT);
363
-
364
- // we only need to track active indices for previous, current and next epoch if we have to compute shufflings
365
- // skip doing that if we already have cached shufflings
366
- if (cachedPreviousShuffling == null && isActiveValidator(validator, previousEpoch)) {
367
- previousActiveIndicesAsNumberArray.push(i);
368
- }
369
- if (isActiveValidator(validator, currentEpoch)) {
370
- if (cachedCurrentShuffling == null) {
371
- currentActiveIndicesAsNumberArray.push(i);
372
- }
373
- // We track totalActiveBalanceIncrements as ETH to fit total network balance in a JS number (53 bits)
374
- totalActiveBalanceIncrements += effectiveBalanceIncrements[i];
375
- }
376
- if (cachedNextShuffling == null && isActiveValidator(validator, nextEpoch)) {
377
- nextActiveIndicesAsNumberArray.push(i);
378
- }
379
-
380
- const {exitEpoch} = validator;
381
- if (exitEpoch !== FAR_FUTURE_EPOCH) {
382
- if (exitEpoch > exitQueueEpoch) {
383
- exitQueueEpoch = exitEpoch;
384
- exitQueueChurn = 1;
385
- } else if (exitEpoch === exitQueueEpoch) {
386
- exitQueueChurn += 1;
387
- }
388
- }
389
- }
390
-
391
- // Spec: `EFFECTIVE_BALANCE_INCREMENT` Gwei minimum to avoid divisions by zero
392
- // 1 = 1 unit of EFFECTIVE_BALANCE_INCREMENT
393
- if (totalActiveBalanceIncrements < 1) {
394
- totalActiveBalanceIncrements = 1;
395
- } else if (totalActiveBalanceIncrements >= Number.MAX_SAFE_INTEGER) {
396
- throw Error("totalActiveBalanceIncrements >= Number.MAX_SAFE_INTEGER. MAX_EFFECTIVE_BALANCE is too low.");
397
- }
398
-
399
- const nextActiveIndices = new Uint32Array(nextActiveIndicesAsNumberArray);
400
- let previousShuffling: EpochShuffling;
401
- let currentShuffling: EpochShuffling;
402
- let nextShuffling: EpochShuffling;
403
-
404
- if (!shufflingCache) {
405
- // Only for testing. shufflingCache should always be available in prod
406
- previousShuffling = computeEpochShuffling(
407
- state,
408
- new Uint32Array(previousActiveIndicesAsNumberArray),
409
- previousEpoch
410
- );
411
-
412
- currentShuffling = isGenesis
413
- ? previousShuffling
414
- : computeEpochShuffling(state, new Uint32Array(currentActiveIndicesAsNumberArray), currentEpoch);
415
-
416
- nextShuffling = computeEpochShuffling(state, nextActiveIndices, nextEpoch);
417
- } else {
418
- currentShuffling = cachedCurrentShuffling
419
- ? cachedCurrentShuffling
420
- : shufflingCache.getSync(currentEpoch, currentDecisionRoot, {
421
- state,
422
- activeIndices: new Uint32Array(currentActiveIndicesAsNumberArray),
423
- });
424
-
425
- previousShuffling = cachedPreviousShuffling
426
- ? cachedPreviousShuffling
427
- : isGenesis
428
- ? currentShuffling
429
- : shufflingCache.getSync(previousEpoch, previousDecisionRoot, {
430
- state,
431
- activeIndices: new Uint32Array(previousActiveIndicesAsNumberArray),
432
- });
433
-
434
- nextShuffling = cachedNextShuffling
435
- ? cachedNextShuffling
436
- : shufflingCache.getSync(nextEpoch, nextDecisionRoot, {
437
- state,
438
- activeIndices: nextActiveIndices,
439
- });
440
- }
441
-
442
- const currentProposerSeed = getSeed(state, currentEpoch, DOMAIN_BEACON_PROPOSER);
443
-
444
- let proposers: number[];
445
- if (currentEpoch >= config.FULU_FORK_EPOCH) {
446
- // Overwrite proposers with state.proposerLookahead
447
- proposers = (state as CachedBeaconStateFulu).proposerLookahead.getAll().slice(0, SLOTS_PER_EPOCH);
448
- } else {
449
- // We need to calculate Pre-fulu
450
- // Allow to create CachedBeaconState for empty states, or no active validators
451
- proposers =
452
- currentShuffling.activeIndices.length > 0
453
- ? computeProposers(
454
- config.getForkSeqAtEpoch(currentEpoch),
455
- currentProposerSeed,
456
- currentShuffling,
457
- effectiveBalanceIncrements
458
- )
459
- : [];
460
- }
461
-
462
- const proposersNextEpoch: ProposersDeferred = {
463
- computed: false,
464
- seed: getSeed(state, nextEpoch, DOMAIN_BEACON_PROPOSER),
465
- };
466
-
467
- // Only after altair, compute the indices of the current sync committee
468
- const afterAltairFork = currentEpoch >= config.ALTAIR_FORK_EPOCH;
469
-
470
- // Values syncParticipantReward, syncProposerReward, baseRewardPerIncrement are only used after altair.
471
- // However, since they are very cheap to compute they are computed always to simplify upgradeState function.
472
- const syncParticipantReward = computeSyncParticipantReward(totalActiveBalanceIncrements);
473
- const syncProposerReward = Math.floor(syncParticipantReward * PROPOSER_WEIGHT_FACTOR);
474
- const baseRewardPerIncrement = computeBaseRewardPerIncrement(totalActiveBalanceIncrements);
475
-
476
- let currentSyncCommitteeIndexed: SyncCommitteeCache;
477
- let nextSyncCommitteeIndexed: SyncCommitteeCache;
478
- // Allow to skip populating sync committee for initializeBeaconStateFromEth1()
479
- if (afterAltairFork && !opts?.skipSyncCommitteeCache) {
480
- const altairState = state as BeaconStateAltair;
481
- currentSyncCommitteeIndexed = computeSyncCommitteeCache(altairState.currentSyncCommittee, pubkey2index);
482
- nextSyncCommitteeIndexed = computeSyncCommitteeCache(altairState.nextSyncCommittee, pubkey2index);
483
- } else {
484
- currentSyncCommitteeIndexed = new SyncCommitteeCacheEmpty();
485
- nextSyncCommitteeIndexed = new SyncCommitteeCacheEmpty();
486
- }
487
-
488
- // Precompute churnLimit for efficient initiateValidatorExit() during block proposing MUST be recompute everytime the
489
- // active validator indices set changes in size. Validators change active status only when:
490
- // - validator.activation_epoch is set. Only changes in process_registry_updates() if validator can be activated. If
491
- // the value changes it will be set to `epoch + 1 + MAX_SEED_LOOKAHEAD`.
492
- // - validator.exit_epoch is set. Only changes in initiate_validator_exit() if validator exits. If the value changes,
493
- // it will be set to at least `epoch + 1 + MAX_SEED_LOOKAHEAD`.
494
- // ```
495
- // is_active_validator = validator.activation_epoch <= epoch < validator.exit_epoch
496
- // ```
497
- // So the returned value of is_active_validator(epoch) is guaranteed to not change during `MAX_SEED_LOOKAHEAD` epochs.
498
- //
499
- // activeIndices size is dependent on the state epoch. The epoch is advanced after running the epoch transition, and
500
- // the first block of the epoch process_block() call. So churnLimit must be computed at the end of the before epoch
501
- // transition and the result is valid until the end of the next epoch transition
502
- const churnLimit = getChurnLimit(config, currentShuffling.activeIndices.length);
503
- const activationChurnLimit = getActivationChurnLimit(
504
- config,
505
- config.getForkSeq(state.slot),
506
- currentShuffling.activeIndices.length
507
- );
508
- if (exitQueueChurn >= churnLimit) {
509
- exitQueueEpoch += 1;
510
- exitQueueChurn = 0;
511
- }
512
-
513
- // TODO: describe issue. Compute progressive target balances
514
- // Compute balances from zero, note this state could be mid-epoch so target balances != 0
515
- let previousTargetUnslashedBalanceIncrements = 0;
516
- let currentTargetUnslashedBalanceIncrements = 0;
517
-
518
- if (config.getForkSeq(state.slot) >= ForkSeq.altair) {
519
- const {previousEpochParticipation, currentEpochParticipation} = state as BeaconStateAltair;
520
- previousTargetUnslashedBalanceIncrements = sumTargetUnslashedBalanceIncrements(
521
- previousEpochParticipation.getAll(),
522
- previousEpoch,
523
- validators
524
- );
525
- currentTargetUnslashedBalanceIncrements = sumTargetUnslashedBalanceIncrements(
526
- currentEpochParticipation.getAll(),
527
- currentEpoch,
528
- validators
529
- );
530
- }
531
-
532
- return new EpochCache({
533
- config,
534
- pubkey2index,
535
- index2pubkey,
536
- shufflingCache,
537
- proposers,
538
- // On first epoch, set to null to prevent unnecessary work since this is only used for metrics
539
- proposersPrevEpoch: null,
540
- proposersNextEpoch,
541
- previousDecisionRoot,
542
- currentDecisionRoot,
543
- nextDecisionRoot,
544
- previousShuffling,
545
- currentShuffling,
546
- nextShuffling,
547
- nextActiveIndices,
548
- effectiveBalanceIncrements,
549
- totalSlashingsByIncrement,
550
- syncParticipantReward,
551
- syncProposerReward,
552
- baseRewardPerIncrement,
553
- totalActiveBalanceIncrements,
554
- churnLimit,
555
- activationChurnLimit,
556
- exitQueueEpoch,
557
- exitQueueChurn,
558
- previousTargetUnslashedBalanceIncrements,
559
- currentTargetUnslashedBalanceIncrements,
560
- currentSyncCommitteeIndexed,
561
- nextSyncCommitteeIndexed,
562
- epoch: currentEpoch,
563
- syncPeriod: computeSyncPeriodAtEpoch(currentEpoch),
564
- });
565
- }
566
-
567
- /**
568
- * Copies a given EpochCache while avoiding copying its immutable parts.
569
- */
570
- clone(): EpochCache {
571
- // warning: pubkey cache is not copied, it is shared, as eth1 is not expected to reorder validators.
572
- // Shallow copy all data from current epoch context to the next
573
- // All data is completely replaced, or only-appended
574
- return new EpochCache({
575
- config: this.config,
576
- // Common append-only structures shared with all states, no need to clone
577
- pubkey2index: this.pubkey2index,
578
- index2pubkey: this.index2pubkey,
579
- shufflingCache: this.shufflingCache,
580
- // Immutable data
581
- proposers: this.proposers,
582
- proposersPrevEpoch: this.proposersPrevEpoch,
583
- proposersNextEpoch: this.proposersNextEpoch,
584
- previousDecisionRoot: this.previousDecisionRoot,
585
- currentDecisionRoot: this.currentDecisionRoot,
586
- nextDecisionRoot: this.nextDecisionRoot,
587
- previousShuffling: this.previousShuffling,
588
- currentShuffling: this.currentShuffling,
589
- nextShuffling: this.nextShuffling,
590
- nextActiveIndices: this.nextActiveIndices,
591
- // Uint8Array, requires cloning, but it is cloned only when necessary before an epoch transition
592
- // See EpochCache.beforeEpochTransition()
593
- effectiveBalanceIncrements: this.effectiveBalanceIncrements,
594
- totalSlashingsByIncrement: this.totalSlashingsByIncrement,
595
- // Basic types (numbers) cloned implicitly
596
- syncParticipantReward: this.syncParticipantReward,
597
- syncProposerReward: this.syncProposerReward,
598
- baseRewardPerIncrement: this.baseRewardPerIncrement,
599
- totalActiveBalanceIncrements: this.totalActiveBalanceIncrements,
600
- churnLimit: this.churnLimit,
601
- activationChurnLimit: this.activationChurnLimit,
602
- exitQueueEpoch: this.exitQueueEpoch,
603
- exitQueueChurn: this.exitQueueChurn,
604
- previousTargetUnslashedBalanceIncrements: this.previousTargetUnslashedBalanceIncrements,
605
- currentTargetUnslashedBalanceIncrements: this.currentTargetUnslashedBalanceIncrements,
606
- currentSyncCommitteeIndexed: this.currentSyncCommitteeIndexed,
607
- nextSyncCommitteeIndexed: this.nextSyncCommitteeIndexed,
608
- epoch: this.epoch,
609
- syncPeriod: this.syncPeriod,
610
- });
611
- }
612
-
613
- /**
614
- * Called to re-use information, such as the shuffling of the next epoch, after transitioning into a
615
- * new epoch. Also handles pre-computation of values that may change during the upcoming epoch and
616
- * that get used in the following epoch transition. Often those pre-computations are not used by the
617
- * chain but are courtesy values that are served via the API for epoch look ahead of duties.
618
- *
619
- * Steps for afterProcessEpoch
620
- * 1) update previous/current/next values of cached items
621
- *
622
- * At fork boundary, this runs pre-fork logic and it happens before `upgradeState*` is called.
623
- */
624
- afterProcessEpoch(state: CachedBeaconStateAllForks, epochTransitionCache: EpochTransitionCache): void {
625
- // Because the slot was incremented before entering this function the "next epoch" is actually the "current epoch"
626
- // in this context but that is not actually true because the state transition happens in the last 4 seconds of the
627
- // epoch. For the context of this function "upcoming epoch" is used to denote the epoch that will begin after this
628
- // function returns. The epoch that is "next" once the state transition is complete is referred to as the
629
- // epochAfterUpcoming for the same reason to help minimize confusion.
630
- const upcomingEpoch = this.nextEpoch;
631
- const epochAfterUpcoming = upcomingEpoch + 1;
632
-
633
- // move current to previous
634
- this.previousShuffling = this.currentShuffling;
635
- this.previousDecisionRoot = this.currentDecisionRoot;
636
-
637
- // move next to current or calculate upcoming
638
- this.currentDecisionRoot = this.nextDecisionRoot;
639
- if (this.nextShuffling) {
640
- // was already pulled from the ShufflingCache to the EpochCache (should be in most cases)
641
- this.currentShuffling = this.nextShuffling;
642
- } else {
643
- this.shufflingCache?.metrics?.shufflingCache.nextShufflingNotOnEpochCache.inc();
644
- this.currentShuffling =
645
- this.shufflingCache?.getSync(upcomingEpoch, this.currentDecisionRoot, {
646
- state,
647
- // have to use the "nextActiveIndices" that were saved in the last transition here to calculate
648
- // the upcoming shuffling if it is not already built (similar condition to the below computation)
649
- activeIndices: this.nextActiveIndices,
650
- }) ??
651
- // allow for this case during testing where the ShufflingCache is not present, may affect perf testing
652
- // so should be taken into account when structuring tests. Should not affect unit or other tests though
653
- computeEpochShuffling(state, this.nextActiveIndices, upcomingEpoch);
654
- }
655
-
656
- // handle next values
657
- this.nextDecisionRoot = epochTransitionCache.nextShufflingDecisionRoot;
658
- this.nextActiveIndices = epochTransitionCache.nextShufflingActiveIndices;
659
- if (this.shufflingCache) {
660
- if (!epochTransitionCache.asyncShufflingCalculation) {
661
- this.nextShuffling = this.shufflingCache.getSync(epochAfterUpcoming, this.nextDecisionRoot, {
662
- state,
663
- activeIndices: this.nextActiveIndices,
664
- });
665
- } else {
666
- this.nextShuffling = null;
667
- // This promise will resolve immediately after the synchronous code of the state-transition runs. Until
668
- // the build is done on a worker thread it will be calculated immediately after the epoch transition
669
- // completes. Once the work is done concurrently it should be ready by time this get runs so the promise
670
- // will resolve directly on the next spin of the event loop because the epoch transition and shuffling take
671
- // about the same time to calculate so theoretically its ready now. Do not await here though in case it
672
- // is not ready yet as the transition must not be asynchronous.
673
- this.shufflingCache
674
- .get(epochAfterUpcoming, this.nextDecisionRoot)
675
- .then((shuffling) => {
676
- if (!shuffling) {
677
- throw new Error("EpochShuffling not returned from get in afterProcessEpoch");
678
- }
679
- this.nextShuffling = shuffling;
680
- })
681
- .catch((err) => {
682
- this.shufflingCache?.logger?.error(
683
- "EPOCH_CONTEXT_SHUFFLING_BUILD_ERROR",
684
- {epoch: epochAfterUpcoming, decisionRoot: epochTransitionCache.nextShufflingDecisionRoot},
685
- err
686
- );
687
- });
688
- }
689
- } else {
690
- // Only for testing. shufflingCache should always be available in prod
691
- this.nextShuffling = computeEpochShuffling(state, this.nextActiveIndices, epochAfterUpcoming);
692
- }
693
-
694
- // TODO: DEDUPLICATE from createEpochCache
695
- //
696
- // Precompute churnLimit for efficient initiateValidatorExit() during block proposing MUST be recompute every time the
697
- // active validator indices set changes in size. Validators change active status only when:
698
- // - validator.activation_epoch is set. Only changes in process_registry_updates() if validator can be activated. If
699
- // the value changes it will be set to `epoch + 1 + MAX_SEED_LOOKAHEAD`.
700
- // - validator.exit_epoch is set. Only changes in initiate_validator_exit() if validator exits. If the value changes,
701
- // it will be set to at least `epoch + 1 + MAX_SEED_LOOKAHEAD`.
702
- // ```
703
- // is_active_validator = validator.activation_epoch <= epoch < validator.exit_epoch
704
- // ```
705
- // So the returned value of is_active_validator(epoch) is guaranteed to not change during `MAX_SEED_LOOKAHEAD` epochs.
706
- //
707
- // activeIndices size is dependent on the state epoch. The epoch is advanced after running the epoch transition, and
708
- // the first block of the epoch process_block() call. So churnLimit must be computed at the end of the before epoch
709
- // transition and the result is valid until the end of the next epoch transition
710
- this.churnLimit = getChurnLimit(this.config, this.currentShuffling.activeIndices.length);
711
- this.activationChurnLimit = getActivationChurnLimit(
712
- this.config,
713
- this.config.getForkSeq(state.slot),
714
- this.currentShuffling.activeIndices.length
715
- );
716
-
717
- // Maybe advance exitQueueEpoch at the end of the epoch if there haven't been any exists for a while
718
- const exitQueueEpoch = computeActivationExitEpoch(upcomingEpoch);
719
- if (exitQueueEpoch > this.exitQueueEpoch) {
720
- this.exitQueueEpoch = exitQueueEpoch;
721
- this.exitQueueChurn = 0;
722
- }
723
-
724
- this.totalActiveBalanceIncrements = epochTransitionCache.nextEpochTotalActiveBalanceByIncrement;
725
- if (upcomingEpoch >= this.config.ALTAIR_FORK_EPOCH) {
726
- this.syncParticipantReward = computeSyncParticipantReward(this.totalActiveBalanceIncrements);
727
- this.syncProposerReward = Math.floor(this.syncParticipantReward * PROPOSER_WEIGHT_FACTOR);
728
- this.baseRewardPerIncrement = computeBaseRewardPerIncrement(this.totalActiveBalanceIncrements);
729
- }
730
-
731
- this.previousTargetUnslashedBalanceIncrements = this.currentTargetUnslashedBalanceIncrements;
732
- this.currentTargetUnslashedBalanceIncrements = 0;
733
-
734
- // Advance time units
735
- // state.slot is advanced right before calling this function
736
- // ```
737
- // postState.slot++;
738
- // afterProcessEpoch(postState, epochTransitionCache);
739
- // ```
740
- this.epoch = computeEpochAtSlot(state.slot);
741
- this.syncPeriod = computeSyncPeriodAtEpoch(this.epoch);
742
- }
743
-
744
- /**
745
- * At fork boundary, this runs post-fork logic and it happens after `upgradeState*` is called.
746
- */
747
- finalProcessEpoch(state: CachedBeaconStateAllForks): void {
748
- // this.epoch was updated at the end of afterProcessEpoch()
749
- const upcomingEpoch = this.epoch;
750
- const epochAfterUpcoming = upcomingEpoch + 1;
751
-
752
- this.proposersPrevEpoch = this.proposers;
753
- if (upcomingEpoch >= this.config.FULU_FORK_EPOCH) {
754
- // Populate proposer cache with lookahead from state
755
- const proposerLookahead = (state as CachedBeaconStateFulu).proposerLookahead.getAll();
756
- this.proposers = proposerLookahead.slice(0, SLOTS_PER_EPOCH);
757
-
758
- if (proposerLookahead.length >= SLOTS_PER_EPOCH * 2) {
759
- this.proposersNextEpoch = {
760
- computed: true,
761
- indexes: proposerLookahead.slice(SLOTS_PER_EPOCH, SLOTS_PER_EPOCH * 2),
762
- };
763
- } else {
764
- // This should not happen unless MIN_SEED_LOOKAHEAD is set to 0
765
- // this ensures things don't break if the proposer lookahead is not long enough
766
- this.proposersNextEpoch = {computed: false, seed: getSeed(state, epochAfterUpcoming, DOMAIN_BEACON_PROPOSER)};
767
- }
768
- } else {
769
- // Need to calculate proposers pre-fulu
770
- const upcomingProposerSeed = getSeed(state, upcomingEpoch, DOMAIN_BEACON_PROPOSER);
771
- // next epoch was moved to current epoch so use current here
772
- this.proposers = computeProposers(
773
- this.config.getForkSeqAtEpoch(upcomingEpoch),
774
- upcomingProposerSeed,
775
- this.currentShuffling,
776
- this.effectiveBalanceIncrements
777
- );
778
- // Only pre-compute the seed since it's very cheap. Do the expensive computeProposers() call only on demand.
779
- this.proposersNextEpoch = {computed: false, seed: getSeed(state, epochAfterUpcoming, DOMAIN_BEACON_PROPOSER)};
780
- }
781
- }
782
-
783
- beforeEpochTransition(): void {
784
- // Clone (copy) before being mutated in processEffectiveBalanceUpdates
785
- // NOTE: Force to use Uint16Array.slice (copy) instead of Buffer.call (not copy)
786
- this.effectiveBalanceIncrements = Uint16Array.prototype.slice.call(this.effectiveBalanceIncrements, 0);
787
- }
788
-
789
- /**
790
- * Return the beacon committee at slot for index.
791
- */
792
- getBeaconCommittee(slot: Slot, index: CommitteeIndex): Uint32Array {
793
- return this.getBeaconCommittees(slot, [index])[0];
794
- }
795
-
796
- /**
797
- * Return a Uint32Array[] representing committees of indices
798
- */
799
- getBeaconCommittees(slot: Slot, indices: CommitteeIndex[]): Uint32Array[] {
800
- if (indices.length === 0) {
801
- throw new Error("Attempt to get committees without providing CommitteeIndex");
802
- }
803
-
804
- const slotCommittees = this.getShufflingAtSlot(slot).committees[slot % SLOTS_PER_EPOCH];
805
- const committees = [];
806
-
807
- for (const index of indices) {
808
- if (index >= slotCommittees.length) {
809
- throw new EpochCacheError({
810
- code: EpochCacheErrorCode.COMMITTEE_INDEX_OUT_OF_RANGE,
811
- index,
812
- maxIndex: slotCommittees.length,
813
- });
814
- }
815
- committees.push(slotCommittees[index]);
816
- }
817
-
818
- return committees;
819
- }
820
-
821
- getCommitteeCountPerSlot(epoch: Epoch): number {
822
- return this.getShufflingAtEpoch(epoch).committeesPerSlot;
823
- }
824
-
825
- /**
826
- * Compute the correct subnet for a slot/committee index
827
- */
828
- computeSubnetForSlot(slot: number, committeeIndex: number): SubnetID {
829
- const slotsSinceEpochStart = slot % SLOTS_PER_EPOCH;
830
- const committeesPerSlot = this.getCommitteeCountPerSlot(computeEpochAtSlot(slot));
831
- const committeesSinceEpochStart = committeesPerSlot * slotsSinceEpochStart;
832
- return (committeesSinceEpochStart + committeeIndex) % ATTESTATION_SUBNET_COUNT;
833
- }
834
-
835
- /**
836
- * Read from proposers instead of state.proposer_lookahead because we set it in `finalProcessEpoch()`
837
- * See https://github.com/ethereum/consensus-specs/blob/e9266b2145c09b63ba0039a9f477cfe8a629c78b/specs/fulu/beacon-chain.md#modified-get_beacon_proposer_index
838
- */
839
- getBeaconProposer(slot: Slot): ValidatorIndex {
840
- const epoch = computeEpochAtSlot(slot);
841
- if (epoch !== this.currentShuffling.epoch) {
842
- throw new EpochCacheError({
843
- code: EpochCacheErrorCode.PROPOSER_EPOCH_MISMATCH,
844
- currentEpoch: this.currentShuffling.epoch,
845
- requestedEpoch: epoch,
846
- });
847
- }
848
- return this.proposers[slot % SLOTS_PER_EPOCH];
849
- }
850
-
851
- getBeaconProposers(): ValidatorIndex[] {
852
- return this.proposers;
853
- }
854
-
855
- getBeaconProposersPrevEpoch(): ValidatorIndex[] | null {
856
- return this.proposersPrevEpoch;
857
- }
858
-
859
- /**
860
- * We allow requesting proposal duties 1 epoch in the future as in normal network conditions it's possible to predict
861
- * the correct shuffling with high probability. While knowing the proposers in advance is not useful for consensus,
862
- * users want to know it to plan manteinance and avoid missing block proposals.
863
- *
864
- * **How to predict future proposers**
865
- *
866
- * Proposer duties for epoch N are guaranteed to be known at epoch N. Proposer duties depend exclusively on:
867
- * 1. seed (from randao_mix): known 2 epochs ahead
868
- * 2. active validator set: known 4 epochs ahead
869
- * 3. effective balance: not known ahead
870
- *
871
- * ```python
872
- * def get_beacon_proposer_index(state: BeaconState) -> ValidatorIndex:
873
- * epoch = get_current_epoch(state)
874
- * seed = hash(get_seed(state, epoch, DOMAIN_BEACON_PROPOSER) + uint_to_bytes(state.slot))
875
- * indices = get_active_validator_indices(state, epoch)
876
- * return compute_proposer_index(state, indices, seed)
877
- * ```
878
- *
879
- * **1**: If `MIN_SEED_LOOKAHEAD = 1` the randao_mix used for the seed is from 2 epochs ago. So at epoch N, the seed
880
- * is known and unchangable for duties at epoch N+1 and N+2 for proposer duties.
881
- *
882
- * ```python
883
- * def get_seed(state: BeaconState, epoch: Epoch, domain_type: DomainType) -> Bytes32:
884
- * mix = get_randao_mix(state, Epoch(epoch - MIN_SEED_LOOKAHEAD - 1))
885
- * return hash(domain_type + uint_to_bytes(epoch) + mix)
886
- * ```
887
- *
888
- * **2**: The active validator set can be predicted `MAX_SEED_LOOKAHEAD` in advance due to how activations are
889
- * processed. We already compute the active validator set for the next epoch to optimize epoch processing, so it's
890
- * reused here.
891
- *
892
- * **3**: Effective balance is not known ahead of time, but it rarely changes. Even if it changes, only a few
893
- * balances are sampled to adjust the probability of the next selection (32 per epoch on average). So to invalidate
894
- * the prediction the effective of one of those 32 samples should change and change the random_byte inequality.
895
- */
896
- getBeaconProposersNextEpoch(): ValidatorIndex[] {
897
- if (!this.proposersNextEpoch.computed) {
898
- // this is lazily computed pre-fulu
899
- const indexes = computeProposers(
900
- this.config.getForkSeqAtEpoch(this.nextEpoch),
901
- this.proposersNextEpoch.seed,
902
- this.getShufflingAtEpoch(this.nextEpoch),
903
- this.effectiveBalanceIncrements
904
- );
905
- this.proposersNextEpoch = {computed: true, indexes};
906
- }
907
-
908
- // this is eagerly computed post-fulu
909
- return this.proposersNextEpoch.indexes;
910
- }
911
-
912
- /**
913
- * Return the indexed attestation corresponding to ``attestation``.
914
- */
915
- getIndexedAttestation(fork: ForkSeq, attestation: Attestation): IndexedAttestation {
916
- const {data} = attestation;
917
- const attestingIndices = this.getAttestingIndices(fork, attestation);
918
-
919
- // sort in-place
920
- attestingIndices.sort((a, b) => a - b);
921
- return {
922
- attestingIndices: attestingIndices,
923
- data: data,
924
- signature: attestation.signature,
925
- };
926
- }
927
-
928
- /**
929
- * Return indices of validators who attestested in `attestation`
930
- */
931
- getAttestingIndices(fork: ForkSeq, attestation: Attestation): number[] {
932
- if (fork < ForkSeq.electra) {
933
- const {aggregationBits, data} = attestation;
934
- const validatorIndices = this.getBeaconCommittee(data.slot, data.index);
935
-
936
- return aggregationBits.intersectValues(validatorIndices);
937
- }
938
- const {aggregationBits, committeeBits, data} = attestation as electra.Attestation;
939
-
940
- // There is a naming conflict on the term `committeeIndices`
941
- // In Lodestar it usually means a list of validator indices of participants in a committee
942
- // In the spec it means a list of committee indices according to committeeBits
943
- // This `committeeIndices` refers to the latter
944
- // TODO Electra: resolve the naming conflicts
945
- const committeeIndices = committeeBits.getTrueBitIndexes();
946
-
947
- const validatorsByCommittee = this.getBeaconCommittees(data.slot, committeeIndices);
948
-
949
- // Create a new Uint32Array to flatten `validatorsByCommittee`
950
- const totalLength = validatorsByCommittee.reduce((acc, curr) => acc + curr.length, 0);
951
- const committeeValidators = new Uint32Array(totalLength);
952
-
953
- let offset = 0;
954
- for (const committee of validatorsByCommittee) {
955
- committeeValidators.set(committee, offset);
956
- offset += committee.length;
957
- }
958
-
959
- return aggregationBits.intersectValues(committeeValidators);
960
- }
961
-
962
- getCommitteeAssignments(
963
- epoch: Epoch,
964
- requestedValidatorIndices: ValidatorIndex[]
965
- ): Map<ValidatorIndex, AttesterDuty> {
966
- const shuffling = this.getShufflingAtEpoch(epoch);
967
- return calculateCommitteeAssignments(shuffling, requestedValidatorIndices);
968
- }
969
-
970
- /**
971
- * Return the committee assignment in the ``epoch`` for ``validator_index``.
972
- * ``assignment`` returned is a tuple of the following form:
973
- * ``assignment[0]`` is the list of validators in the committee
974
- * ``assignment[1]`` is the index to which the committee is assigned
975
- * ``assignment[2]`` is the slot at which the committee is assigned
976
- * Return null if no assignment..
977
- */
978
- getCommitteeAssignment(epoch: Epoch, validatorIndex: ValidatorIndex): phase0.CommitteeAssignment | null {
979
- if (epoch > this.currentShuffling.epoch + 1) {
980
- throw Error(
981
- `Requesting committee assignment for more than 1 epoch ahead: ${epoch} > ${this.currentShuffling.epoch} + 1`
982
- );
983
- }
984
-
985
- const epochStartSlot = computeStartSlotAtEpoch(epoch);
986
- const committeeCountPerSlot = this.getCommitteeCountPerSlot(epoch);
987
- for (let slot = epochStartSlot; slot < epochStartSlot + SLOTS_PER_EPOCH; slot++) {
988
- for (let i = 0; i < committeeCountPerSlot; i++) {
989
- const committee = this.getBeaconCommittee(slot, i);
990
- if (committee.includes(validatorIndex)) {
991
- return {
992
- validators: Array.from(committee),
993
- committeeIndex: i,
994
- slot,
995
- };
996
- }
997
- }
998
- }
999
- return null;
1000
- }
1001
-
1002
- isAggregator(slot: Slot, index: CommitteeIndex, slotSignature: BLSSignature): boolean {
1003
- const committee = this.getBeaconCommittee(slot, index);
1004
- return isAggregatorFromCommitteeLength(committee.length, slotSignature);
1005
- }
1006
-
1007
- /**
1008
- * Return pubkey given the validator index.
1009
- */
1010
- getPubkey(index: ValidatorIndex): PublicKey | undefined {
1011
- return this.index2pubkey[index];
1012
- }
1013
-
1014
- getValidatorIndex(pubkey: Uint8Array): ValidatorIndex | null {
1015
- return this.pubkey2index.get(pubkey);
1016
- }
1017
-
1018
- addPubkey(index: ValidatorIndex, pubkey: Uint8Array): void {
1019
- this.pubkey2index.set(pubkey, index);
1020
- this.index2pubkey[index] = PublicKey.fromBytes(pubkey); // Optimize for aggregation
1021
- }
1022
-
1023
- getShufflingAtSlot(slot: Slot): EpochShuffling {
1024
- const epoch = computeEpochAtSlot(slot);
1025
- return this.getShufflingAtEpoch(epoch);
1026
- }
1027
-
1028
- getShufflingAtSlotOrNull(slot: Slot): EpochShuffling | null {
1029
- const epoch = computeEpochAtSlot(slot);
1030
- return this.getShufflingAtEpochOrNull(epoch);
1031
- }
1032
-
1033
- getShufflingAtEpoch(epoch: Epoch): EpochShuffling {
1034
- const shuffling = this.getShufflingAtEpochOrNull(epoch);
1035
- if (shuffling === null) {
1036
- if (epoch === this.nextEpoch) {
1037
- throw new EpochCacheError({
1038
- code: EpochCacheErrorCode.NEXT_SHUFFLING_NOT_AVAILABLE,
1039
- epoch: epoch,
1040
- decisionRoot: this.getShufflingDecisionRoot(this.nextEpoch),
1041
- });
1042
- }
1043
- throw new EpochCacheError({
1044
- code: EpochCacheErrorCode.COMMITTEE_EPOCH_OUT_OF_RANGE,
1045
- currentEpoch: this.currentShuffling.epoch,
1046
- requestedEpoch: epoch,
1047
- });
1048
- }
1049
-
1050
- return shuffling;
1051
- }
1052
-
1053
- getShufflingDecisionRoot(epoch: Epoch): RootHex {
1054
- switch (epoch) {
1055
- case this.epoch - 1:
1056
- return this.previousDecisionRoot;
1057
- case this.epoch:
1058
- return this.currentDecisionRoot;
1059
- case this.nextEpoch:
1060
- return this.nextDecisionRoot;
1061
- default:
1062
- throw new EpochCacheError({
1063
- code: EpochCacheErrorCode.DECISION_ROOT_EPOCH_OUT_OF_RANGE,
1064
- currentEpoch: this.epoch,
1065
- requestedEpoch: epoch,
1066
- });
1067
- }
1068
- }
1069
-
1070
- getShufflingAtEpochOrNull(epoch: Epoch): EpochShuffling | null {
1071
- switch (epoch) {
1072
- case this.epoch - 1:
1073
- return this.previousShuffling;
1074
- case this.epoch:
1075
- return this.currentShuffling;
1076
- case this.nextEpoch:
1077
- if (!this.nextShuffling) {
1078
- this.nextShuffling =
1079
- this.shufflingCache?.getSync(this.nextEpoch, this.getShufflingDecisionRoot(this.nextEpoch)) ?? null;
1080
- }
1081
- return this.nextShuffling;
1082
- default:
1083
- return null;
1084
- }
1085
- }
1086
-
1087
- /**
1088
- * Note: The range of slots a validator has to perform duties is off by one.
1089
- * The previous slot wording means that if your validator is in a sync committee for a period that runs from slot
1090
- * 100 to 200,then you would actually produce signatures in slot 99 - 199.
1091
- */
1092
- getIndexedSyncCommittee(slot: Slot): SyncCommitteeCache {
1093
- // See note above for the +1 offset
1094
- return this.getIndexedSyncCommitteeAtEpoch(computeEpochAtSlot(slot + 1));
1095
- }
1096
-
1097
- /**
1098
- * **DO NOT USE FOR GOSSIP VALIDATION**: Sync committee duties are offset by one slot. @see {@link EpochCache.getIndexedSyncCommittee}
1099
- *
1100
- * Get indexed sync committee at epoch without offsets
1101
- */
1102
- getIndexedSyncCommitteeAtEpoch(epoch: Epoch): SyncCommitteeCache {
1103
- switch (computeSyncPeriodAtEpoch(epoch)) {
1104
- case this.syncPeriod:
1105
- return this.currentSyncCommitteeIndexed;
1106
- case this.syncPeriod + 1:
1107
- return this.nextSyncCommitteeIndexed;
1108
- default:
1109
- throw new EpochCacheError({code: EpochCacheErrorCode.NO_SYNC_COMMITTEE, epoch});
1110
- }
1111
- }
1112
-
1113
- /** On processSyncCommitteeUpdates rotate next to current and set nextSyncCommitteeIndexed */
1114
- rotateSyncCommitteeIndexed(nextSyncCommitteeIndices: Uint32Array): void {
1115
- this.currentSyncCommitteeIndexed = this.nextSyncCommitteeIndexed;
1116
- this.nextSyncCommitteeIndexed = getSyncCommitteeCache(nextSyncCommitteeIndices);
1117
- }
1118
-
1119
- /** On phase0 -> altair fork, set both current and nextSyncCommitteeIndexed */
1120
- setSyncCommitteesIndexed(nextSyncCommitteeIndices: Uint32Array): void {
1121
- this.nextSyncCommitteeIndexed = getSyncCommitteeCache(nextSyncCommitteeIndices);
1122
- this.currentSyncCommitteeIndexed = this.nextSyncCommitteeIndexed;
1123
- }
1124
-
1125
- effectiveBalanceIncrementsSet(index: number, effectiveBalance: number): void {
1126
- if (this.isPostElectra()) {
1127
- // TODO: electra
1128
- // getting length and setting getEffectiveBalanceIncrementsByteLen is not fork safe
1129
- // so each time we add an index, we should new the Uint8Array to keep it forksafe
1130
- // one simple optimization could be to increment the length once per block rather
1131
- // on each add/set
1132
- //
1133
- // there could still be some unused length remaining from the prev ELECTRA padding
1134
- const newLength =
1135
- index >= this.effectiveBalanceIncrements.length ? index + 1 : this.effectiveBalanceIncrements.length;
1136
- const effectiveBalanceIncrements = this.effectiveBalanceIncrements;
1137
- this.effectiveBalanceIncrements = new Uint16Array(newLength);
1138
- this.effectiveBalanceIncrements.set(effectiveBalanceIncrements, 0);
1139
- } else {
1140
- if (index >= this.effectiveBalanceIncrements.length) {
1141
- // Clone and extend effectiveBalanceIncrements
1142
- const effectiveBalanceIncrements = this.effectiveBalanceIncrements;
1143
- this.effectiveBalanceIncrements = new Uint16Array(getEffectiveBalanceIncrementsByteLen(index + 1));
1144
- this.effectiveBalanceIncrements.set(effectiveBalanceIncrements, 0);
1145
- }
1146
- }
1147
-
1148
- this.effectiveBalanceIncrements[index] = Math.floor(effectiveBalance / EFFECTIVE_BALANCE_INCREMENT);
1149
- }
1150
-
1151
- isPostElectra(): boolean {
1152
- return this.epoch >= this.config.ELECTRA_FORK_EPOCH;
1153
- }
1154
- }
1155
-
1156
- function getEffectiveBalanceIncrementsByteLen(validatorCount: number): number {
1157
- // TODO: Research what's the best number to minimize both memory cost and copy costs
1158
- return 1024 * Math.ceil(validatorCount / 1024);
1159
- }
1160
-
1161
- export enum EpochCacheErrorCode {
1162
- COMMITTEE_INDEX_OUT_OF_RANGE = "EPOCH_CONTEXT_ERROR_COMMITTEE_INDEX_OUT_OF_RANGE",
1163
- COMMITTEE_EPOCH_OUT_OF_RANGE = "EPOCH_CONTEXT_ERROR_COMMITTEE_EPOCH_OUT_OF_RANGE",
1164
- DECISION_ROOT_EPOCH_OUT_OF_RANGE = "EPOCH_CONTEXT_ERROR_DECISION_ROOT_EPOCH_OUT_OF_RANGE",
1165
- NEXT_SHUFFLING_NOT_AVAILABLE = "EPOCH_CONTEXT_ERROR_NEXT_SHUFFLING_NOT_AVAILABLE",
1166
- NO_SYNC_COMMITTEE = "EPOCH_CONTEXT_ERROR_NO_SYNC_COMMITTEE",
1167
- PROPOSER_EPOCH_MISMATCH = "EPOCH_CONTEXT_ERROR_PROPOSER_EPOCH_MISMATCH",
1168
- }
1169
-
1170
- type EpochCacheErrorType =
1171
- | {
1172
- code: EpochCacheErrorCode.COMMITTEE_INDEX_OUT_OF_RANGE;
1173
- index: number;
1174
- maxIndex: number;
1175
- }
1176
- | {
1177
- code: EpochCacheErrorCode.COMMITTEE_EPOCH_OUT_OF_RANGE;
1178
- requestedEpoch: Epoch;
1179
- currentEpoch: Epoch;
1180
- }
1181
- | {
1182
- code: EpochCacheErrorCode.DECISION_ROOT_EPOCH_OUT_OF_RANGE;
1183
- requestedEpoch: Epoch;
1184
- currentEpoch: Epoch;
1185
- }
1186
- | {
1187
- code: EpochCacheErrorCode.NEXT_SHUFFLING_NOT_AVAILABLE;
1188
- epoch: Epoch;
1189
- decisionRoot: RootHex;
1190
- }
1191
- | {
1192
- code: EpochCacheErrorCode.NO_SYNC_COMMITTEE;
1193
- epoch: Epoch;
1194
- }
1195
- | {
1196
- code: EpochCacheErrorCode.PROPOSER_EPOCH_MISMATCH;
1197
- requestedEpoch: Epoch;
1198
- currentEpoch: Epoch;
1199
- };
1200
-
1201
- export class EpochCacheError extends LodestarError<EpochCacheErrorType> {}
1202
-
1203
- export function createEmptyEpochCacheImmutableData(
1204
- chainConfig: ChainConfig,
1205
- state: Pick<BeaconStateAllForks, "genesisValidatorsRoot">
1206
- ): EpochCacheImmutableData {
1207
- return {
1208
- config: createBeaconConfig(chainConfig, state.genesisValidatorsRoot),
1209
- // This is a test state, there's no need to have a global shared cache of keys
1210
- pubkey2index: new PubkeyIndexMap(),
1211
- index2pubkey: [],
1212
- };
1213
- }