@lodestar/state-transition 1.46.0-dev.5aeaa12d3c → 1.46.0-dev.5e77d154c5

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 (235) hide show
  1. package/lib/block/externalData.js +2 -4
  2. package/lib/block/externalData.js.map +1 -1
  3. package/lib/block/index.js.map +1 -1
  4. package/lib/block/initiateValidatorExit.js.map +1 -1
  5. package/lib/block/isValidIndexedAttestation.js.map +1 -1
  6. package/lib/block/isValidIndexedPayloadAttestation.js.map +1 -1
  7. package/lib/block/processAttestationPhase0.js.map +1 -1
  8. package/lib/block/processAttestations.js.map +1 -1
  9. package/lib/block/processAttestationsAltair.js.map +1 -1
  10. package/lib/block/processAttesterSlashing.js.map +1 -1
  11. package/lib/block/processBlobKzgCommitments.js.map +1 -1
  12. package/lib/block/processBlockHeader.js.map +1 -1
  13. package/lib/block/processBlsToExecutionChange.js.map +1 -1
  14. package/lib/block/processBuilderDepositRequest.js.map +1 -1
  15. package/lib/block/processBuilderExitRequest.js.map +1 -1
  16. package/lib/block/processConsolidationRequest.js.map +1 -1
  17. package/lib/block/processDeposit.js.map +1 -1
  18. package/lib/block/processDepositRequest.js.map +1 -1
  19. package/lib/block/processEth1Data.js.map +1 -1
  20. package/lib/block/processExecutionPayload.js.map +1 -1
  21. package/lib/block/processExecutionPayloadBid.d.ts +2 -2
  22. package/lib/block/processExecutionPayloadBid.d.ts.map +1 -1
  23. package/lib/block/processExecutionPayloadBid.js +8 -3
  24. package/lib/block/processExecutionPayloadBid.js.map +1 -1
  25. package/lib/block/processOperations.js.map +1 -1
  26. package/lib/block/processParentExecutionPayload.js.map +1 -1
  27. package/lib/block/processPayloadAttestation.js.map +1 -1
  28. package/lib/block/processProposerSlashing.js.map +1 -1
  29. package/lib/block/processRandao.js.map +1 -1
  30. package/lib/block/processSyncCommittee.js.map +1 -1
  31. package/lib/block/processVoluntaryExit.js +1 -2
  32. package/lib/block/processVoluntaryExit.js.map +1 -1
  33. package/lib/block/processWithdrawalRequest.d.ts.map +1 -1
  34. package/lib/block/processWithdrawalRequest.js +2 -2
  35. package/lib/block/processWithdrawalRequest.js.map +1 -1
  36. package/lib/block/processWithdrawals.js.map +1 -1
  37. package/lib/block/slashValidator.js.map +1 -1
  38. package/lib/block/types.js +1 -2
  39. package/lib/block/types.js.map +1 -1
  40. package/lib/cache/effectiveBalanceIncrements.js.map +1 -1
  41. package/lib/cache/epochCache.js +1 -2
  42. package/lib/cache/epochCache.js.map +1 -1
  43. package/lib/cache/epochTransitionCache.js.map +1 -1
  44. package/lib/cache/pubkeyCache.js.map +1 -1
  45. package/lib/cache/rewardCache.js.map +1 -1
  46. package/lib/cache/stateCache.d.ts +2 -1
  47. package/lib/cache/stateCache.d.ts.map +1 -1
  48. package/lib/cache/stateCache.js +3 -2
  49. package/lib/cache/stateCache.js.map +1 -1
  50. package/lib/cache/syncCommitteeCache.js.map +1 -1
  51. package/lib/cache/types.d.ts +1 -0
  52. package/lib/cache/types.d.ts.map +1 -1
  53. package/lib/epoch/computeUnrealizedCheckpoints.js.map +1 -1
  54. package/lib/epoch/getAttestationDeltas.js.map +1 -1
  55. package/lib/epoch/getRewardsAndPenalties.js.map +1 -1
  56. package/lib/epoch/index.js +1 -2
  57. package/lib/epoch/index.js.map +1 -1
  58. package/lib/epoch/processBuilderPendingPayments.js.map +1 -1
  59. package/lib/epoch/processEffectiveBalanceUpdates.js.map +1 -1
  60. package/lib/epoch/processEth1DataReset.js.map +1 -1
  61. package/lib/epoch/processHistoricalRootsUpdate.js.map +1 -1
  62. package/lib/epoch/processHistoricalSummariesUpdate.js.map +1 -1
  63. package/lib/epoch/processInactivityUpdates.js.map +1 -1
  64. package/lib/epoch/processJustificationAndFinalization.js.map +1 -1
  65. package/lib/epoch/processParticipationFlagUpdates.js.map +1 -1
  66. package/lib/epoch/processParticipationRecordUpdates.js.map +1 -1
  67. package/lib/epoch/processPendingAttestations.js.map +1 -1
  68. package/lib/epoch/processPendingConsolidations.js.map +1 -1
  69. package/lib/epoch/processPendingDeposits.js.map +1 -1
  70. package/lib/epoch/processProposerLookahead.js.map +1 -1
  71. package/lib/epoch/processPtcWindow.js.map +1 -1
  72. package/lib/epoch/processRandaoMixesReset.js.map +1 -1
  73. package/lib/epoch/processRegistryUpdates.js.map +1 -1
  74. package/lib/epoch/processRewardsAndPenalties.js.map +1 -1
  75. package/lib/epoch/processSlashings.js.map +1 -1
  76. package/lib/epoch/processSlashingsReset.js.map +1 -1
  77. package/lib/epoch/processSyncCommitteeUpdates.js.map +1 -1
  78. package/lib/index.d.ts +2 -2
  79. package/lib/index.d.ts.map +1 -1
  80. package/lib/index.js +1 -1
  81. package/lib/index.js.map +1 -1
  82. package/lib/lightClient/proofs.js.map +1 -1
  83. package/lib/lightClient/spec/index.js.map +1 -1
  84. package/lib/lightClient/spec/isBetterUpdate.js.map +1 -1
  85. package/lib/lightClient/spec/processLightClientUpdate.js.map +1 -1
  86. package/lib/lightClient/spec/store.js.map +1 -1
  87. package/lib/lightClient/spec/utils.d.ts +0 -2
  88. package/lib/lightClient/spec/utils.d.ts.map +1 -1
  89. package/lib/lightClient/spec/utils.js +8 -2
  90. package/lib/lightClient/spec/utils.js.map +1 -1
  91. package/lib/lightClient/spec/validateLightClientBootstrap.js.map +1 -1
  92. package/lib/lightClient/spec/validateLightClientUpdate.js.map +1 -1
  93. package/lib/metrics.d.ts.map +1 -1
  94. package/lib/metrics.js +3 -2
  95. package/lib/metrics.js.map +1 -1
  96. package/lib/rewards/attestationsRewards.js.map +1 -1
  97. package/lib/rewards/blockRewards.js.map +1 -1
  98. package/lib/rewards/syncCommitteeRewards.js.map +1 -1
  99. package/lib/signatureSets/attesterSlashings.js.map +1 -1
  100. package/lib/signatureSets/blsToExecutionChange.js.map +1 -1
  101. package/lib/signatureSets/executionPayloadBid.d.ts +2 -2
  102. package/lib/signatureSets/executionPayloadBid.d.ts.map +1 -1
  103. package/lib/signatureSets/executionPayloadBid.js +7 -5
  104. package/lib/signatureSets/executionPayloadBid.js.map +1 -1
  105. package/lib/signatureSets/executionPayloadEnvelope.js.map +1 -1
  106. package/lib/signatureSets/index.js.map +1 -1
  107. package/lib/signatureSets/indexedAttestation.js.map +1 -1
  108. package/lib/signatureSets/indexedPayloadAttestation.js.map +1 -1
  109. package/lib/signatureSets/proposer.js.map +1 -1
  110. package/lib/signatureSets/proposerPreferences.js.map +1 -1
  111. package/lib/signatureSets/proposerSlashings.js.map +1 -1
  112. package/lib/signatureSets/randao.js.map +1 -1
  113. package/lib/signatureSets/voluntaryExits.js.map +1 -1
  114. package/lib/slot/index.d.ts +1 -0
  115. package/lib/slot/index.d.ts.map +1 -1
  116. package/lib/slot/index.js +1 -0
  117. package/lib/slot/index.js.map +1 -1
  118. package/lib/slot/upgradeStateToAltair.js.map +1 -1
  119. package/lib/slot/upgradeStateToBellatrix.js.map +1 -1
  120. package/lib/slot/upgradeStateToCapella.js.map +1 -1
  121. package/lib/slot/upgradeStateToDeneb.js.map +1 -1
  122. package/lib/slot/upgradeStateToElectra.js.map +1 -1
  123. package/lib/slot/upgradeStateToFulu.js.map +1 -1
  124. package/lib/slot/upgradeStateToGloas.js.map +1 -1
  125. package/lib/slot/upgradeStateToHeze.d.ts +7 -0
  126. package/lib/slot/upgradeStateToHeze.d.ts.map +1 -0
  127. package/lib/slot/upgradeStateToHeze.js +83 -0
  128. package/lib/slot/upgradeStateToHeze.js.map +1 -0
  129. package/lib/stateTransition.d.ts.map +1 -1
  130. package/lib/stateTransition.js +6 -5
  131. package/lib/stateTransition.js.map +1 -1
  132. package/lib/stateView/beaconStateView.js.map +1 -1
  133. package/lib/stateView/interface.d.ts +8 -3
  134. package/lib/stateView/interface.d.ts.map +1 -1
  135. package/lib/stateView/interface.js +4 -1
  136. package/lib/stateView/interface.js.map +1 -1
  137. package/lib/stateView/nativeBeaconStateView.js.map +1 -1
  138. package/lib/stateView/stateViewFactory.js.map +1 -1
  139. package/lib/testUtils/infura.js.map +1 -1
  140. package/lib/testUtils/interop.js.map +1 -1
  141. package/lib/testUtils/params.d.ts.map +1 -1
  142. package/lib/testUtils/state.js +1 -1
  143. package/lib/testUtils/state.js.map +1 -1
  144. package/lib/testUtils/testFileCache.js.map +1 -1
  145. package/lib/testUtils/util.d.ts +1 -1
  146. package/lib/testUtils/util.d.ts.map +1 -1
  147. package/lib/testUtils/util.js +2 -2
  148. package/lib/testUtils/util.js.map +1 -1
  149. package/lib/types.d.ts +2 -2
  150. package/lib/types.d.ts.map +1 -1
  151. package/lib/util/aggregator.js.map +1 -1
  152. package/lib/util/altair.js.map +1 -1
  153. package/lib/util/array.js.map +1 -1
  154. package/lib/util/attestation.js.map +1 -1
  155. package/lib/util/attesterStatus.js.map +1 -1
  156. package/lib/util/balance.js.map +1 -1
  157. package/lib/util/blindedBlock.js.map +1 -1
  158. package/lib/util/blockRoot.js.map +1 -1
  159. package/lib/util/capella.js.map +1 -1
  160. package/lib/util/clock.d.ts +6 -0
  161. package/lib/util/clock.d.ts.map +1 -1
  162. package/lib/util/clock.js +1 -2
  163. package/lib/util/clock.js.map +1 -1
  164. package/lib/util/computeAnchorCheckpoint.js.map +1 -1
  165. package/lib/util/deposit.d.ts.map +1 -1
  166. package/lib/util/deposit.js +10 -8
  167. package/lib/util/deposit.js.map +1 -1
  168. package/lib/util/domain.js.map +1 -1
  169. package/lib/util/electra.js.map +1 -1
  170. package/lib/util/epoch.js.map +1 -1
  171. package/lib/util/epochShuffling.js.map +1 -1
  172. package/lib/util/execution.js.map +1 -1
  173. package/lib/util/finality.js.map +1 -1
  174. package/lib/util/fulu.js.map +1 -1
  175. package/lib/util/genesis.d.ts.map +1 -1
  176. package/lib/util/genesis.js +7 -2
  177. package/lib/util/genesis.js.map +1 -1
  178. package/lib/util/gloas.d.ts +2 -1
  179. package/lib/util/gloas.d.ts.map +1 -1
  180. package/lib/util/gloas.js +7 -4
  181. package/lib/util/gloas.js.map +1 -1
  182. package/lib/util/interop.js.map +1 -1
  183. package/lib/util/loadState/findModifiedInactivityScores.js.map +1 -1
  184. package/lib/util/loadState/findModifiedValidators.js.map +1 -1
  185. package/lib/util/loadState/loadState.d.ts.map +1 -1
  186. package/lib/util/loadState/loadState.js +36 -5
  187. package/lib/util/loadState/loadState.js.map +1 -1
  188. package/lib/util/loadState/loadValidator.js.map +1 -1
  189. package/lib/util/pendingDepositsLookup.js.map +1 -1
  190. package/lib/util/rootCache.js.map +1 -1
  191. package/lib/util/seed.js.map +1 -1
  192. package/lib/util/shuffling.js +1 -2
  193. package/lib/util/shuffling.js.map +1 -1
  194. package/lib/util/signatureSets.js +1 -2
  195. package/lib/util/signatureSets.js.map +1 -1
  196. package/lib/util/signingRoot.js.map +1 -1
  197. package/lib/util/slot.js.map +1 -1
  198. package/lib/util/ssz.d.ts +5 -0
  199. package/lib/util/ssz.d.ts.map +1 -1
  200. package/lib/util/ssz.js +8 -1
  201. package/lib/util/ssz.js.map +1 -1
  202. package/lib/util/sszBytes.js.map +1 -1
  203. package/lib/util/syncCommittee.js.map +1 -1
  204. package/lib/util/targetUnslashedBalance.js.map +1 -1
  205. package/lib/util/validator.d.ts +5 -0
  206. package/lib/util/validator.d.ts.map +1 -1
  207. package/lib/util/validator.js +9 -0
  208. package/lib/util/validator.js.map +1 -1
  209. package/lib/util/weakSubjectivity.d.ts +1 -0
  210. package/lib/util/weakSubjectivity.d.ts.map +1 -1
  211. package/lib/util/weakSubjectivity.js +20 -8
  212. package/lib/util/weakSubjectivity.js.map +1 -1
  213. package/package.json +9 -9
  214. package/src/block/processExecutionPayloadBid.ts +18 -8
  215. package/src/block/processWithdrawalRequest.ts +6 -2
  216. package/src/cache/stateCache.ts +5 -2
  217. package/src/cache/types.ts +1 -0
  218. package/src/index.ts +4 -0
  219. package/src/lightClient/spec/utils.ts +9 -2
  220. package/src/metrics.ts +3 -2
  221. package/src/signatureSets/executionPayloadBid.ts +7 -9
  222. package/src/slot/index.ts +1 -0
  223. package/src/slot/upgradeStateToHeze.ts +91 -0
  224. package/src/stateTransition.ts +5 -0
  225. package/src/stateView/interface.ts +13 -2
  226. package/src/testUtils/state.ts +1 -1
  227. package/src/testUtils/util.ts +2 -2
  228. package/src/types.ts +2 -0
  229. package/src/util/deposit.ts +11 -9
  230. package/src/util/genesis.ts +8 -2
  231. package/src/util/gloas.ts +9 -5
  232. package/src/util/loadState/loadState.ts +50 -11
  233. package/src/util/ssz.ts +9 -1
  234. package/src/util/validator.ts +17 -0
  235. package/src/util/weakSubjectivity.ts +61 -22
@@ -193,11 +193,11 @@ export function nextSyncCommitteeGindexAtFork(fork: ForkName): number {
193
193
  return NEXT_SYNC_COMMITTEE_GINDEX;
194
194
  }
195
195
 
196
- export function getGindexDepth(gindex: number): number {
196
+ function getGindexDepth(gindex: number): number {
197
197
  return Math.floor(Math.log2(gindex));
198
198
  }
199
199
 
200
- export function getGindexIndex(gindex: number): number {
200
+ function getGindexIndex(gindex: number): number {
201
201
  return gindex - 2 ** getGindexDepth(gindex);
202
202
  }
203
203
 
@@ -263,6 +263,7 @@ export function upgradeLightClientHeader(
263
263
  // Break if no further upgrades is required else fall through
264
264
  if (ForkSeq[targetFork] <= ForkSeq.fulu) break;
265
265
 
266
+ // biome-ignore lint/suspicious/noFallthroughSwitchClause: We need fall-through behavior here
266
267
  case ForkName.gloas:
267
268
  if (isGloasLightClientHeader(upgradedHeader)) {
268
269
  break;
@@ -272,6 +273,12 @@ export function upgradeLightClientHeader(
272
273
 
273
274
  // Break if no further upgrades is required else fall through
274
275
  if (ForkSeq[targetFork] <= ForkSeq.gloas) break;
276
+
277
+ case ForkName.heze:
278
+ // No changes to LightClientHeader in Heze
279
+
280
+ // Break if no further upgrades is required else fall through
281
+ if (ForkSeq[targetFork] <= ForkSeq.heze) break;
275
282
  }
276
283
  return upgradedHeader;
277
284
  }
package/src/metrics.ts CHANGED
@@ -3,6 +3,7 @@ import {ProposerRewardType} from "./block/types.js";
3
3
  import {EpochTransitionStep} from "./epoch/index.js";
4
4
  import {StateCloneSource, StateHashTreeRootSource} from "./stateTransition.js";
5
5
  import {CachedBeaconStateAllForks} from "./types.js";
6
+ import {isViewDUNodesPopulated} from "./util/ssz.js";
6
7
 
7
8
  export type BeaconStateTransitionMetrics = ReturnType<typeof getMetrics>;
8
9
 
@@ -159,9 +160,9 @@ export function onPostStateMetrics(postState: CachedBeaconStateAllForks, metrics
159
160
  // This cache is populated during epoch transition, and should be preserved for performance.
160
161
  // If the cache is missing too often, means that our clone strategy is not working well.
161
162
  function isValidatorsNodesPopulated(state: CachedBeaconStateAllForks): boolean {
162
- return (state.validators as unknown as {nodesPopulated?: boolean}).nodesPopulated === true;
163
+ return isViewDUNodesPopulated(state.validators);
163
164
  }
164
165
 
165
166
  function isBalancesNodesPopulated(state: CachedBeaconStateAllForks): boolean {
166
- return (state.balances as unknown as {nodesPopulated?: boolean}).nodesPopulated === true;
167
+ return isViewDUNodesPopulated(state.balances);
167
168
  }
@@ -1,14 +1,12 @@
1
1
  import {BeaconConfig} from "@lodestar/config";
2
- import {DOMAIN_BEACON_BUILDER} from "@lodestar/params";
3
- import {Slot, gloas, ssz} from "@lodestar/types";
2
+ import {DOMAIN_BEACON_BUILDER, isForkPostGloas} from "@lodestar/params";
3
+ import {ExecutionPayloadBid, ssz, sszTypesFor} from "@lodestar/types";
4
4
  import {computeSigningRoot} from "../util/index.js";
5
5
 
6
- export function getExecutionPayloadBidSigningRoot(
7
- config: BeaconConfig,
8
- stateSlot: Slot,
9
- bid: gloas.ExecutionPayloadBid
10
- ): Uint8Array {
11
- const domain = config.getDomain(stateSlot, DOMAIN_BEACON_BUILDER);
6
+ export function getExecutionPayloadBidSigningRoot(config: BeaconConfig, bid: ExecutionPayloadBid): Uint8Array {
7
+ const fork = config.getForkName(bid.slot);
8
+ const domain = config.getDomain(bid.slot, DOMAIN_BEACON_BUILDER);
9
+ const sszType = isForkPostGloas(fork) ? sszTypesFor(fork).ExecutionPayloadBid : ssz.gloas.ExecutionPayloadBid;
12
10
 
13
- return computeSigningRoot(ssz.gloas.ExecutionPayloadBid, bid, domain);
11
+ return computeSigningRoot(sszType, bid, domain);
14
12
  }
package/src/slot/index.ts CHANGED
@@ -10,6 +10,7 @@ export {upgradeStateToDeneb} from "./upgradeStateToDeneb.js";
10
10
  export {upgradeStateToElectra} from "./upgradeStateToElectra.js";
11
11
  export {upgradeStateToFulu} from "./upgradeStateToFulu.js";
12
12
  export {upgradeStateToGloas} from "./upgradeStateToGloas.js";
13
+ export {upgradeStateToHeze} from "./upgradeStateToHeze.js";
13
14
 
14
15
  /**
15
16
  * Dial state to next slot. Common for all forks
@@ -0,0 +1,91 @@
1
+ import {ssz} from "@lodestar/types";
2
+ import {getCachedBeaconState} from "../cache/stateCache.js";
3
+ import {CachedBeaconStateGloas, CachedBeaconStateHeze} from "../types.js";
4
+
5
+ /**
6
+ * Upgrade a state from Gloas to Heze.
7
+ * Spec: heze/fork.md `upgrade_to_heze`.
8
+ */
9
+ export function upgradeStateToHeze(stateGloas: CachedBeaconStateGloas): CachedBeaconStateHeze {
10
+ const {config} = stateGloas;
11
+
12
+ ssz.gloas.BeaconState.commitViewDU(stateGloas);
13
+ const stateHezeCloned = stateGloas;
14
+
15
+ const stateHezeView = ssz.heze.BeaconState.defaultViewDU();
16
+
17
+ stateHezeView.genesisTime = stateHezeCloned.genesisTime;
18
+ stateHezeView.genesisValidatorsRoot = stateHezeCloned.genesisValidatorsRoot;
19
+ stateHezeView.slot = stateHezeCloned.slot;
20
+ stateHezeView.fork = ssz.phase0.Fork.toViewDU({
21
+ previousVersion: stateGloas.fork.currentVersion,
22
+ currentVersion: config.HEZE_FORK_VERSION,
23
+ epoch: stateGloas.epochCtx.epoch,
24
+ });
25
+ stateHezeView.latestBlockHeader = stateHezeCloned.latestBlockHeader;
26
+ stateHezeView.blockRoots = stateHezeCloned.blockRoots;
27
+ stateHezeView.stateRoots = stateHezeCloned.stateRoots;
28
+ stateHezeView.historicalRoots = stateHezeCloned.historicalRoots;
29
+ stateHezeView.eth1Data = stateHezeCloned.eth1Data;
30
+ stateHezeView.eth1DataVotes = stateHezeCloned.eth1DataVotes;
31
+ stateHezeView.eth1DepositIndex = stateHezeCloned.eth1DepositIndex;
32
+ stateHezeView.validators = stateHezeCloned.validators;
33
+ stateHezeView.balances = stateHezeCloned.balances;
34
+ stateHezeView.randaoMixes = stateHezeCloned.randaoMixes;
35
+ stateHezeView.slashings = stateHezeCloned.slashings;
36
+ stateHezeView.previousEpochParticipation = stateHezeCloned.previousEpochParticipation;
37
+ stateHezeView.currentEpochParticipation = stateHezeCloned.currentEpochParticipation;
38
+ stateHezeView.justificationBits = stateHezeCloned.justificationBits;
39
+ stateHezeView.previousJustifiedCheckpoint = stateHezeCloned.previousJustifiedCheckpoint;
40
+ stateHezeView.currentJustifiedCheckpoint = stateHezeCloned.currentJustifiedCheckpoint;
41
+ stateHezeView.finalizedCheckpoint = stateHezeCloned.finalizedCheckpoint;
42
+ stateHezeView.inactivityScores = stateHezeCloned.inactivityScores;
43
+ stateHezeView.currentSyncCommittee = stateHezeCloned.currentSyncCommittee;
44
+ stateHezeView.nextSyncCommittee = stateHezeCloned.nextSyncCommittee;
45
+ stateHezeView.latestBlockHash = stateHezeCloned.latestBlockHash;
46
+ stateHezeView.nextWithdrawalIndex = stateHezeCloned.nextWithdrawalIndex;
47
+ stateHezeView.nextWithdrawalValidatorIndex = stateHezeCloned.nextWithdrawalValidatorIndex;
48
+ stateHezeView.historicalSummaries = stateHezeCloned.historicalSummaries;
49
+ stateHezeView.depositRequestsStartIndex = stateHezeCloned.depositRequestsStartIndex;
50
+ stateHezeView.depositBalanceToConsume = stateHezeCloned.depositBalanceToConsume;
51
+ stateHezeView.exitBalanceToConsume = stateHezeCloned.exitBalanceToConsume;
52
+ stateHezeView.earliestExitEpoch = stateHezeCloned.earliestExitEpoch;
53
+ stateHezeView.consolidationBalanceToConsume = stateHezeCloned.consolidationBalanceToConsume;
54
+ stateHezeView.earliestConsolidationEpoch = stateHezeCloned.earliestConsolidationEpoch;
55
+ stateHezeView.pendingDeposits = stateHezeCloned.pendingDeposits;
56
+ stateHezeView.pendingPartialWithdrawals = stateHezeCloned.pendingPartialWithdrawals;
57
+ stateHezeView.pendingConsolidations = stateHezeCloned.pendingConsolidations;
58
+ stateHezeView.proposerLookahead = stateHezeCloned.proposerLookahead;
59
+ stateHezeView.builders = stateHezeCloned.builders;
60
+ stateHezeView.nextWithdrawalBuilderIndex = stateHezeCloned.nextWithdrawalBuilderIndex;
61
+ stateHezeView.executionPayloadAvailability = stateHezeCloned.executionPayloadAvailability;
62
+ stateHezeView.builderPendingPayments = stateHezeCloned.builderPendingPayments;
63
+ stateHezeView.builderPendingWithdrawals = stateHezeCloned.builderPendingWithdrawals;
64
+
65
+ // [Modified in Heze:EIP7805] inclusion_list_bits = Bitvector[INCLUSION_LIST_COMMITTEE_SIZE]() (default zero)
66
+ const oldBid = stateHezeCloned.latestExecutionPayloadBid;
67
+ const newBid = ssz.heze.ExecutionPayloadBid.defaultViewDU();
68
+ newBid.parentBlockHash = oldBid.parentBlockHash;
69
+ newBid.parentBlockRoot = oldBid.parentBlockRoot;
70
+ newBid.blockHash = oldBid.blockHash;
71
+ newBid.prevRandao = oldBid.prevRandao;
72
+ newBid.feeRecipient = oldBid.feeRecipient;
73
+ newBid.gasLimit = oldBid.gasLimit;
74
+ newBid.builderIndex = oldBid.builderIndex;
75
+ newBid.slot = oldBid.slot;
76
+ newBid.value = oldBid.value;
77
+ newBid.executionPayment = oldBid.executionPayment;
78
+ newBid.blobKzgCommitments = oldBid.blobKzgCommitments;
79
+ newBid.executionRequestsRoot = oldBid.executionRequestsRoot;
80
+ stateHezeView.latestExecutionPayloadBid = newBid;
81
+
82
+ stateHezeView.payloadExpectedWithdrawals = stateHezeCloned.payloadExpectedWithdrawals;
83
+ stateHezeView.ptcWindow = stateHezeCloned.ptcWindow;
84
+
85
+ const stateHeze = getCachedBeaconState(stateHezeView, stateGloas);
86
+ stateHeze.commit();
87
+ // biome-ignore lint/complexity/useLiteralKeys: It is a protected attribute
88
+ stateHeze["clearCache"]();
89
+
90
+ return stateHeze;
91
+ }
@@ -16,6 +16,7 @@ import {
16
16
  upgradeStateToDeneb,
17
17
  upgradeStateToElectra,
18
18
  upgradeStateToGloas,
19
+ upgradeStateToHeze,
19
20
  } from "./slot/index.js";
20
21
  import {upgradeStateToFulu} from "./slot/upgradeStateToFulu.js";
21
22
  import {
@@ -26,6 +27,7 @@ import {
26
27
  CachedBeaconStateDeneb,
27
28
  CachedBeaconStateElectra,
28
29
  CachedBeaconStateFulu,
30
+ CachedBeaconStateGloas,
29
31
  CachedBeaconStatePhase0,
30
32
  } from "./types.js";
31
33
  import {computeEpochAtSlot} from "./util/index.js";
@@ -278,6 +280,9 @@ function processSlotsWithTransientCache(
278
280
  if (stateEpoch === config.GLOAS_FORK_EPOCH) {
279
281
  postState = upgradeStateToGloas(postState as CachedBeaconStateFulu) as CachedBeaconStateAllForks;
280
282
  }
283
+ if (stateEpoch === config.HEZE_FORK_EPOCH) {
284
+ postState = upgradeStateToHeze(postState as CachedBeaconStateGloas) as CachedBeaconStateAllForks;
285
+ }
281
286
 
282
287
  {
283
288
  const timer = metrics?.epochTransitionStepTime.startTimer({step: EpochTransitionStep.finalProcessEpoch});
@@ -9,6 +9,7 @@ import {
9
9
  ForkPostElectra,
10
10
  ForkPostFulu,
11
11
  ForkPostGloas,
12
+ ForkPostHeze,
12
13
  isForkPostAltair,
13
14
  isForkPostBellatrix,
14
15
  isForkPostCapella,
@@ -16,6 +17,7 @@ import {
16
17
  isForkPostElectra,
17
18
  isForkPostFulu,
18
19
  isForkPostGloas,
20
+ isForkPostHeze,
19
21
  } from "@lodestar/params";
20
22
  import {
21
23
  BeaconBlock,
@@ -267,14 +269,19 @@ export interface IBeaconStateViewGloas extends IBeaconStateViewFulu {
267
269
  withParentPayloadApplied(executionRequests: gloas.ExecutionRequests): IBeaconStateViewGloas;
268
270
  }
269
271
 
272
+ /** Heze+ state fields — use isStatePostHeze() guard */
273
+ export interface IBeaconStateViewHeze extends IBeaconStateViewGloas {
274
+ forkName: ForkPostHeze;
275
+ }
276
+
270
277
  /**
271
278
  * Type constraint for the concrete BeaconStateView class.
272
- * Requires all fields from the latest fork interface (IBeaconStateViewGloas) but keeps
279
+ * Requires all fields from the latest fork interface (IBeaconStateViewHeze) but keeps
273
280
  * forkName as ForkName since the class wraps any fork's state.
274
281
  * Sub-interfaces retain their narrowed forkName discriminants for caller-side type guards.
275
282
  */
276
283
  export type IBeaconStateViewLatestFork = Omit<
277
- IBeaconStateViewGloas,
284
+ IBeaconStateViewHeze,
278
285
  "forkName" | "latestExecutionPayloadHeader" | "payloadBlockNumber"
279
286
  > & {
280
287
  forkName: ForkName;
@@ -337,3 +344,7 @@ export function isStatePostFulu(state: IBeaconStateView): state is IBeaconStateV
337
344
  export function isStatePostGloas(state: IBeaconStateView): state is IBeaconStateViewGloas {
338
345
  return isForkPostGloas(state.forkName);
339
346
  }
347
+
348
+ export function isStatePostHeze(state: IBeaconStateView): state is IBeaconStateViewHeze {
349
+ return isForkPostHeze(state.forkName);
350
+ }
@@ -54,7 +54,7 @@ export function generateState(opts?: TestBeaconState): BeaconStatePhase0 {
54
54
  eth1Data: {
55
55
  depositRoot: Buffer.alloc(32),
56
56
  blockHash: Buffer.alloc(32),
57
- depositCount: 0,
57
+ depositCount: 0n,
58
58
  },
59
59
  eth1DataVotes: [],
60
60
  eth1DepositIndex: 0,
@@ -437,13 +437,13 @@ function buildPerformanceStatePhase0(pubkeysArg?: Uint8Array[]): phase0.BeaconSt
437
437
  historicalRoots: [],
438
438
  // Eth1
439
439
  eth1Data: {
440
- depositCount: pubkeys.length,
440
+ depositCount: BigInt(pubkeys.length),
441
441
  depositRoot: fromHexString("0xcb1f89a924cfd31224823db5a41b1643f10faa7aedf231f1e28887f6ee98c047"),
442
442
  blockHash: fromHexString("0x701fb2869ce16d0f1d14f6705725adb0dec6799da29006dfc6fff83960298f21"),
443
443
  },
444
444
  // minus one so that inserting 1 from block works
445
445
  eth1DataVotes: newFilledArray(EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH - 1, {
446
- depositCount: 1,
446
+ depositCount: 1n,
447
447
  depositRoot: Buffer.alloc(32, 1),
448
448
  blockHash: Buffer.alloc(32, 1),
449
449
  }),
package/src/types.ts CHANGED
@@ -10,6 +10,7 @@ export type {
10
10
  CachedBeaconStateExecutions,
11
11
  CachedBeaconStateFulu,
12
12
  CachedBeaconStateGloas,
13
+ CachedBeaconStateHeze,
13
14
  CachedBeaconStatePhase0,
14
15
  } from "./cache/stateCache.js";
15
16
  export type {
@@ -22,6 +23,7 @@ export type {
22
23
  BeaconStateExecutions,
23
24
  BeaconStateFulu,
24
25
  BeaconStateGloas,
26
+ BeaconStateHeze,
25
27
  BeaconStatePhase0,
26
28
  ShufflingGetter,
27
29
  } from "./cache/types.js";
@@ -4,19 +4,21 @@ import {CachedBeaconStateAllForks, CachedBeaconStateElectra} from "../types.js";
4
4
 
5
5
  export function getEth1DepositCount(state: CachedBeaconStateAllForks, eth1Data?: phase0.Eth1Data): UintNum64 {
6
6
  const eth1DataToUse = eth1Data ?? state.eth1Data;
7
+ // Proposer can set any value, use in bigint until the result is bounded by MAX_DEPOSITS
8
+ const depositCount = eth1DataToUse.depositCount;
9
+ const eth1DepositIndex = BigInt(state.eth1DepositIndex);
10
+ const maxDeposits = BigInt(MAX_DEPOSITS);
7
11
  if (state.config.getForkSeq(state.slot) >= ForkSeq.electra) {
8
12
  const electraState = state as CachedBeaconStateElectra;
9
- // eth1DataIndexLimit = min(UintNum64, UintBn64) can be safely casted as UintNum64
10
- // since the result lies within upper and lower bound of UintNum64
11
- const eth1DataIndexLimit: UintNum64 =
12
- eth1DataToUse.depositCount < electraState.depositRequestsStartIndex
13
- ? eth1DataToUse.depositCount
14
- : Number(electraState.depositRequestsStartIndex);
13
+ const eth1DataIndexLimit =
14
+ depositCount < electraState.depositRequestsStartIndex ? depositCount : electraState.depositRequestsStartIndex;
15
15
 
16
- if (state.eth1DepositIndex < eth1DataIndexLimit) {
17
- return Math.min(MAX_DEPOSITS, eth1DataIndexLimit - state.eth1DepositIndex);
16
+ if (eth1DepositIndex < eth1DataIndexLimit) {
17
+ const available = eth1DataIndexLimit - eth1DepositIndex;
18
+ return Number(available < maxDeposits ? available : maxDeposits);
18
19
  }
19
20
  return 0;
20
21
  }
21
- return Math.min(MAX_DEPOSITS, eth1DataToUse.depositCount - state.eth1DepositIndex);
22
+ const available = depositCount - eth1DepositIndex;
23
+ return Number(available < maxDeposits ? available : maxDeposits);
22
24
  }
@@ -139,7 +139,7 @@ export function applyDeposits(
139
139
  const fullDepositDataRootArr = fullDepositDataRootList ? fullDepositDataRootList.getAllReadonlyValues() : null;
140
140
 
141
141
  if (fullDepositDataRootArr) {
142
- const depositCount = state.eth1Data.depositCount;
142
+ const depositCount = Number(state.eth1Data.depositCount);
143
143
  for (let index = 0; index < depositCount; index++) {
144
144
  depositDataRootList.push(fullDepositDataRootArr[index]);
145
145
  }
@@ -160,7 +160,7 @@ export function applyDeposits(
160
160
  );
161
161
  }
162
162
 
163
- state.eth1Data.depositCount += 1;
163
+ state.eth1Data.depositCount += 1n;
164
164
 
165
165
  const fork = config.getForkSeq(GENESIS_SLOT);
166
166
  processDeposit(fork, state, deposit);
@@ -334,6 +334,12 @@ export function initializeBeaconStateFromEth1(
334
334
  stateGloas.fork.currentVersion = config.GLOAS_FORK_VERSION;
335
335
  }
336
336
 
337
+ if (fork >= ForkSeq.heze) {
338
+ const stateHeze = state as CompositeViewDU<typeof ssz.heze.BeaconState>;
339
+ stateHeze.fork.previousVersion = config.HEZE_FORK_VERSION;
340
+ stateHeze.fork.currentVersion = config.HEZE_FORK_VERSION;
341
+ }
342
+
337
343
  state.commit();
338
344
 
339
345
  return state;
package/src/util/gloas.ts CHANGED
@@ -87,15 +87,19 @@ export function isActiveBuilder(builder: gloas.Builder, finalizedEpoch: Epoch):
87
87
  * From https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md
88
88
  */
89
89
  export function getExpectedGasLimit(parentGasLimit: number, targetGasLimit: number): number {
90
- const maxGasLimitDifference = Math.max(Math.floor(parentGasLimit / 1024), 1) - 1;
90
+ return Number(getExpectedGasLimitBigint(BigInt(parentGasLimit), BigInt(targetGasLimit)));
91
+ }
92
+
93
+ export function getExpectedGasLimitBigint(parentGasLimit: bigint, targetGasLimit: bigint): bigint {
94
+ const maxGasLimitDifference = (parentGasLimit / 1024n > 1n ? parentGasLimit / 1024n : 1n) - 1n;
91
95
 
92
96
  if (targetGasLimit > parentGasLimit) {
93
97
  const gasDiff = targetGasLimit - parentGasLimit;
94
- return parentGasLimit + Math.min(gasDiff, maxGasLimitDifference);
98
+ return parentGasLimit + (gasDiff < maxGasLimitDifference ? gasDiff : maxGasLimitDifference);
95
99
  }
96
100
 
97
101
  const gasDiff = parentGasLimit - targetGasLimit;
98
- return parentGasLimit - Math.min(gasDiff, maxGasLimitDifference);
102
+ return parentGasLimit - (gasDiff < maxGasLimitDifference ? gasDiff : maxGasLimitDifference);
99
103
  }
100
104
 
101
105
  /**
@@ -104,8 +108,8 @@ export function getExpectedGasLimit(parentGasLimit: number, targetGasLimit: numb
104
108
  * adjustment step of the parent, otherwise it must hit the clamped boundary.
105
109
  * Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.8/specs/gloas/builder.md#new-is_gas_limit_target_compatible
106
110
  */
107
- export function isGasLimitTargetCompatible(parentGasLimit: number, gasLimit: number, targetGasLimit: number): boolean {
108
- return gasLimit === getExpectedGasLimit(parentGasLimit, targetGasLimit);
111
+ export function isGasLimitTargetCompatible(parentGasLimit: bigint, gasLimit: bigint, targetGasLimit: bigint): boolean {
112
+ return gasLimit === getExpectedGasLimitBigint(parentGasLimit, targetGasLimit);
109
113
  }
110
114
 
111
115
  /**
@@ -25,10 +25,29 @@ export function loadState(
25
25
  ): MigrateStateOutput {
26
26
  // casting only to make typescript happy
27
27
  const stateType = getStateTypeFromBytes(config, stateBytes) as typeof ssz.capella.BeaconState;
28
+ const fork = getForkFromStateBytes(config, stateBytes);
29
+ const seedFork = config.getForkSeq(seedState.slot);
30
+
28
31
  const dataView = new DataView(stateBytes.buffer, stateBytes.byteOffset, stateBytes.byteLength);
29
32
  const fieldRanges = stateType.getFieldRanges(dataView, 0, stateBytes.length);
30
33
  const allFields = Object.keys(stateType.fields);
31
34
  const validatorsFieldIndex = allFields.indexOf("validators");
35
+ const validatorsRange = fieldRanges[validatorsFieldIndex];
36
+ const newValidatorsBytes = stateBytes.subarray(validatorsRange.start, validatorsRange.end);
37
+
38
+ // EIP-7688 replaces List with ProgressiveList for validators and inactivityScores at gloas,
39
+ // changing the merkle tree shape. Seed nodes cannot be reused when one state is pre-gloas
40
+ // and the other post-gloas.
41
+ const crossesGloasFork =
42
+ (fork >= ForkSeq.gloas && seedFork < ForkSeq.gloas) || (fork < ForkSeq.gloas && seedFork >= ForkSeq.gloas);
43
+ if (crossesGloasFork) {
44
+ const migratedState = stateType.deserializeToViewDU(stateBytes) as BeaconStateAllForks;
45
+ // modified validators must still be reported so that the pubkey cache is refreshed for
46
+ // any index that differs from the seed state, which may not be an ancestor of this state
47
+ const modifiedValidators = findModifiedAndAppendedValidators(seedState, newValidatorsBytes, seedValidatorsBytes);
48
+ return {state: migratedState, modifiedValidators};
49
+ }
50
+
32
51
  // start with default view has the same performance to start with seed state
33
52
  // and it is not fork dependent
34
53
  const migratedState = deserializeContainerIgnoreFields(
@@ -39,19 +58,10 @@ export function loadState(
39
58
  ) as BeaconStateAllForks;
40
59
 
41
60
  // validators are rarely changed
42
- const validatorsRange = fieldRanges[validatorsFieldIndex];
43
- const modifiedValidators = loadValidators(
44
- migratedState,
45
- seedState,
46
- stateBytes.subarray(validatorsRange.start, validatorsRange.end),
47
- seedValidatorsBytes
48
- );
61
+ const modifiedValidators = loadValidators(migratedState, seedState, newValidatorsBytes, seedValidatorsBytes);
49
62
 
50
63
  // inactivityScores are rarely changed
51
64
  // this saves ~500ms of hashTreeRoot() time of state
52
- const fork = getForkFromStateBytes(config, stateBytes);
53
- const seedFork = config.getForkSeq(seedState.slot);
54
-
55
65
  if (fork >= ForkSeq.altair && seedFork >= ForkSeq.altair) {
56
66
  const inactivityScoresIndex = allFields.indexOf("inactivityScores");
57
67
  const inactivityScoresRange = fieldRanges[inactivityScoresIndex];
@@ -141,7 +151,9 @@ function loadInactivityScores(
141
151
  }
142
152
  } else {
143
153
  if (newValidator - 1 < 0) {
144
- migratedState.inactivityScores = ssz.altair.InactivityScores.defaultViewDU();
154
+ // use the state's own field type, the list shape differs between altair (List) and gloas (ProgressiveList)
155
+ const inactivityScoresType = (migratedState.type as typeof ssz.altair.BeaconState).fields.inactivityScores;
156
+ migratedState.inactivityScores = inactivityScoresType.defaultViewDU();
145
157
  } else {
146
158
  migratedState.inactivityScores = migratedState.inactivityScores.sliceTo(newValidator - 1);
147
159
  }
@@ -177,6 +189,33 @@ function loadInactivityScores(
177
189
  * @param migratedState state to be migrated, the validators are loaded to this state
178
190
  * @returns modified validator indices
179
191
  */
192
+ /**
193
+ * Find indices of validators whose serialized bytes differ from the seed state, plus indices
194
+ * appended past the seed state's validator count. Unlike loadValidators() this only diffs
195
+ * bytes and does not share the seed state's tree.
196
+ */
197
+ function findModifiedAndAppendedValidators(
198
+ seedState: BeaconStateAllForks,
199
+ newValidatorsBytes: Uint8Array,
200
+ seedStateValidatorsBytes?: Uint8Array
201
+ ): number[] {
202
+ const seedValidatorCount = seedState.validators.length;
203
+ const newValidatorCount = Math.floor(newValidatorsBytes.length / VALIDATOR_BYTES_SIZE);
204
+ const minValidatorCount = Math.min(seedValidatorCount, newValidatorCount);
205
+ const seedValidatorsBytes = seedStateValidatorsBytes ?? seedState.validators.serialize();
206
+ const modifiedValidators: number[] = [];
207
+ findModifiedValidators(
208
+ seedValidatorsBytes.subarray(0, minValidatorCount * VALIDATOR_BYTES_SIZE),
209
+ newValidatorsBytes.subarray(0, minValidatorCount * VALIDATOR_BYTES_SIZE),
210
+ modifiedValidators
211
+ );
212
+
213
+ for (let validatorIndex = seedValidatorCount; validatorIndex < newValidatorCount; validatorIndex++) {
214
+ modifiedValidators.push(validatorIndex);
215
+ }
216
+ return modifiedValidators;
217
+ }
218
+
180
219
  function loadValidators(
181
220
  migratedState: BeaconStateAllForks,
182
221
  seedState: BeaconStateAllForks,
package/src/util/ssz.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import {BranchNode, LeafNode, Node, zeroNode} from "@chainsafe/persistent-merkle-tree";
2
2
  import {progressiveSubtreeFillToContents} from "@chainsafe/ssz";
3
3
 
4
- // TODO: move these utils to @chainsafe/ssz (progressive.ts, next to progressiveSubtreeFillToContents)
4
+ // TODO: move these utils to @chainsafe/ssz, see https://github.com/ChainSafe/ssz/issues/542
5
5
 
6
6
  /** Root node (chunks + length mix-in) of a zero-filled ProgressiveListBasicType of `length` items */
7
7
  export function zeroProgressiveListBasicRootNode(itemsPerChunk: number, length: number): Node {
@@ -15,6 +15,14 @@ export function zeroProgressiveListBasicRootNode(itemsPerChunk: number, length:
15
15
  return new BranchNode(zeroProgressiveNode(numSubtrees), LeafNode.fromUint32(length));
16
16
  }
17
17
 
18
+ /**
19
+ * Check if an array-type ViewDU (ListBasic, ListComposite or their progressive equivalents) has its
20
+ * internal nodes cache populated. The flag is a private attribute maintained by all of these classes.
21
+ */
22
+ export function isViewDUNodesPopulated(view: unknown): boolean {
23
+ return (view as {nodesPopulated?: boolean}).nodesPopulated === true;
24
+ }
25
+
18
26
  /**
19
27
  * Root node of a progressive list from its chunk/element nodes + length mix-in.
20
28
  * `nodes` are packed 32-byte chunk leaves for basic lists, or element root nodes for composite lists.
@@ -128,6 +128,23 @@ export function getConsolidationChurnLimit(fork: ForkSeq, epochCtx: EpochCache):
128
128
  return getBalanceChurnLimitFromCache(epochCtx) - getActivationExitChurnLimit(epochCtx);
129
129
  }
130
130
 
131
+ // NOTE: duplicates the quotient/min choices in get{Exit,Activation,Consolidation}ChurnLimit.
132
+ export function getGloasChurnLimits(
133
+ config: ChainForkConfig,
134
+ totalActiveBalanceIncrements: number
135
+ ): {exit: number; activation: number; consolidation: number} {
136
+ const exit = getBalanceChurnLimit(
137
+ totalActiveBalanceIncrements,
138
+ config.CHURN_LIMIT_QUOTIENT_GLOAS,
139
+ config.MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA
140
+ );
141
+ return {
142
+ exit,
143
+ activation: Math.min(config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT_GLOAS, exit),
144
+ consolidation: getBalanceChurnLimit(totalActiveBalanceIncrements, config.CONSOLIDATION_CHURN_LIMIT_QUOTIENT, 0),
145
+ };
146
+ }
147
+
131
148
  export function getMaxEffectiveBalance(withdrawalCredentials: Uint8Array): number {
132
149
  // Compounding withdrawal credential only available since Electra
133
150
  if (hasCompoundingWithdrawalCredential(withdrawalCredentials)) {