@lodestar/state-transition 1.35.0-dev.a70bac5bd3 → 1.35.0-dev.ba92bd8a88

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 (284) hide show
  1. package/README.md +1 -1
  2. package/lib/block/externalData.d.ts.map +1 -0
  3. package/lib/block/index.d.ts +2 -2
  4. package/lib/block/index.d.ts.map +1 -0
  5. package/lib/block/index.js +2 -2
  6. package/lib/block/index.js.map +1 -1
  7. package/lib/block/initiateValidatorExit.d.ts.map +1 -0
  8. package/lib/block/isValidIndexedAttestation.d.ts.map +1 -0
  9. package/lib/block/processAttestationPhase0.d.ts.map +1 -0
  10. package/lib/block/processAttestationPhase0.js +1 -2
  11. package/lib/block/processAttestationPhase0.js.map +1 -1
  12. package/lib/block/processAttestations.d.ts.map +1 -0
  13. package/lib/block/processAttestationsAltair.d.ts +1 -1
  14. package/lib/block/processAttestationsAltair.d.ts.map +1 -0
  15. package/lib/block/processAttestationsAltair.js +1 -1
  16. package/lib/block/processAttestationsAltair.js.map +1 -1
  17. package/lib/block/processAttesterSlashing.d.ts.map +1 -0
  18. package/lib/block/processAttesterSlashing.js.map +1 -1
  19. package/lib/block/processBlobKzgCommitments.d.ts.map +1 -0
  20. package/lib/block/processBlockHeader.d.ts.map +1 -0
  21. package/lib/block/processBlsToExecutionChange.d.ts.map +1 -0
  22. package/lib/block/processBlsToExecutionChange.js.map +1 -1
  23. package/lib/block/processConsolidationRequest.d.ts.map +1 -0
  24. package/lib/block/processConsolidationRequest.js.map +1 -1
  25. package/lib/block/processDeposit.d.ts +2 -2
  26. package/lib/block/processDeposit.d.ts.map +1 -0
  27. package/lib/block/processDeposit.js +1 -1
  28. package/lib/block/processDeposit.js.map +1 -1
  29. package/lib/block/processDepositRequest.d.ts.map +1 -0
  30. package/lib/block/processDepositRequest.js.map +1 -1
  31. package/lib/block/processEth1Data.d.ts.map +1 -0
  32. package/lib/block/processExecutionPayload.d.ts.map +1 -0
  33. package/lib/block/processOperations.d.ts.map +1 -0
  34. package/lib/block/processOperations.js.map +1 -1
  35. package/lib/block/processProposerSlashing.d.ts.map +1 -0
  36. package/lib/block/processRandao.d.ts.map +1 -0
  37. package/lib/block/processSyncCommittee.d.ts.map +1 -0
  38. package/lib/block/processSyncCommittee.js +1 -2
  39. package/lib/block/processSyncCommittee.js.map +1 -1
  40. package/lib/block/processVoluntaryExit.d.ts.map +1 -0
  41. package/lib/block/processWithdrawalRequest.d.ts.map +1 -0
  42. package/lib/block/processWithdrawalRequest.js.map +1 -1
  43. package/lib/block/processWithdrawals.d.ts.map +1 -0
  44. package/lib/block/processWithdrawals.js.map +1 -1
  45. package/lib/block/slashValidator.d.ts.map +1 -0
  46. package/lib/block/slashValidator.js.map +1 -1
  47. package/lib/block/types.d.ts.map +1 -0
  48. package/lib/cache/effectiveBalanceIncrements.d.ts.map +1 -0
  49. package/lib/cache/epochCache.d.ts.map +1 -0
  50. package/lib/cache/epochCache.js +130 -0
  51. package/lib/cache/epochCache.js.map +1 -1
  52. package/lib/cache/epochTransitionCache.d.ts.map +1 -0
  53. package/lib/cache/epochTransitionCache.js.map +1 -1
  54. package/lib/cache/pubkeyCache.d.ts.map +1 -0
  55. package/lib/cache/rewardCache.d.ts.map +1 -0
  56. package/lib/cache/stateCache.d.ts.map +1 -0
  57. package/lib/cache/syncCommitteeCache.d.ts.map +1 -0
  58. package/lib/cache/types.d.ts.map +1 -0
  59. package/lib/constants/constants.d.ts.map +1 -0
  60. package/lib/constants/index.d.ts.map +1 -0
  61. package/lib/epoch/computeUnrealizedCheckpoints.d.ts.map +1 -0
  62. package/lib/epoch/getAttestationDeltas.d.ts.map +1 -0
  63. package/lib/epoch/getRewardsAndPenalties.d.ts.map +1 -0
  64. package/lib/epoch/index.d.ts.map +1 -0
  65. package/lib/epoch/index.js.map +1 -1
  66. package/lib/epoch/processEffectiveBalanceUpdates.d.ts.map +1 -0
  67. package/lib/epoch/processEth1DataReset.d.ts.map +1 -0
  68. package/lib/epoch/processHistoricalRootsUpdate.d.ts.map +1 -0
  69. package/lib/epoch/processHistoricalSummariesUpdate.d.ts.map +1 -0
  70. package/lib/epoch/processInactivityUpdates.d.ts.map +1 -0
  71. package/lib/epoch/processJustificationAndFinalization.d.ts.map +1 -0
  72. package/lib/epoch/processParticipationFlagUpdates.d.ts.map +1 -0
  73. package/lib/epoch/processParticipationRecordUpdates.d.ts.map +1 -0
  74. package/lib/epoch/processPendingAttestations.d.ts.map +1 -0
  75. package/lib/epoch/processPendingConsolidations.d.ts.map +1 -0
  76. package/lib/epoch/processPendingDeposits.d.ts.map +1 -0
  77. package/lib/epoch/processProposerLookahead.d.ts.map +1 -0
  78. package/lib/epoch/processRandaoMixesReset.d.ts.map +1 -0
  79. package/lib/epoch/processRegistryUpdates.d.ts.map +1 -0
  80. package/lib/epoch/processRewardsAndPenalties.d.ts.map +1 -0
  81. package/lib/epoch/processSlashings.d.ts.map +1 -0
  82. package/lib/epoch/processSlashings.js.map +1 -1
  83. package/lib/epoch/processSlashingsReset.d.ts.map +1 -0
  84. package/lib/epoch/processSyncCommitteeUpdates.d.ts.map +1 -0
  85. package/lib/index.d.ts +17 -17
  86. package/lib/index.d.ts.map +1 -0
  87. package/lib/index.js +16 -16
  88. package/lib/index.js.map +1 -1
  89. package/lib/metrics.d.ts.map +1 -0
  90. package/lib/signatureSets/attesterSlashings.d.ts.map +1 -0
  91. package/lib/signatureSets/blsToExecutionChange.d.ts.map +1 -0
  92. package/lib/signatureSets/blsToExecutionChange.js.map +1 -1
  93. package/lib/signatureSets/index.d.ts +1 -1
  94. package/lib/signatureSets/index.d.ts.map +1 -0
  95. package/lib/signatureSets/index.js +1 -1
  96. package/lib/signatureSets/index.js.map +1 -1
  97. package/lib/signatureSets/indexedAttestation.d.ts.map +1 -0
  98. package/lib/signatureSets/proposer.d.ts.map +1 -0
  99. package/lib/signatureSets/proposerSlashings.d.ts.map +1 -0
  100. package/lib/signatureSets/randao.d.ts.map +1 -0
  101. package/lib/signatureSets/voluntaryExits.d.ts.map +1 -0
  102. package/lib/slot/index.d.ts.map +1 -0
  103. package/lib/slot/upgradeStateToAltair.d.ts.map +1 -0
  104. package/lib/slot/upgradeStateToBellatrix.d.ts.map +1 -0
  105. package/lib/slot/upgradeStateToCapella.d.ts.map +1 -0
  106. package/lib/slot/upgradeStateToDeneb.d.ts +1 -2
  107. package/lib/slot/upgradeStateToDeneb.d.ts.map +1 -0
  108. package/lib/slot/upgradeStateToDeneb.js.map +1 -1
  109. package/lib/slot/upgradeStateToElectra.d.ts.map +1 -0
  110. package/lib/slot/upgradeStateToFulu.d.ts.map +1 -0
  111. package/lib/slot/upgradeStateToGloas.d.ts.map +1 -0
  112. package/lib/slot/upgradeStateToGloas.js +2 -2
  113. package/lib/slot/upgradeStateToGloas.js.map +1 -1
  114. package/lib/stateTransition.d.ts.map +1 -0
  115. package/lib/types.d.ts +2 -2
  116. package/lib/types.d.ts.map +1 -0
  117. package/lib/util/aggregator.d.ts.map +1 -0
  118. package/lib/util/altair.d.ts.map +1 -0
  119. package/lib/util/array.d.ts.map +1 -0
  120. package/lib/util/attestation.d.ts.map +1 -0
  121. package/lib/util/attesterStatus.d.ts.map +1 -0
  122. package/lib/util/balance.d.ts.map +1 -0
  123. package/lib/util/blindedBlock.d.ts.map +1 -0
  124. package/lib/util/blindedBlock.js.map +1 -1
  125. package/lib/util/blockRoot.d.ts.map +1 -0
  126. package/lib/util/calculateCommitteeAssignments.d.ts.map +1 -0
  127. package/lib/util/capella.d.ts.map +1 -0
  128. package/lib/util/computeAnchorCheckpoint.d.ts.map +1 -0
  129. package/lib/util/deposit.d.ts.map +1 -0
  130. package/lib/util/domain.d.ts.map +1 -0
  131. package/lib/util/electra.d.ts.map +1 -0
  132. package/lib/util/epoch.d.ts.map +1 -0
  133. package/lib/util/epochShuffling.d.ts.map +1 -0
  134. package/lib/util/execution.d.ts.map +1 -0
  135. package/lib/util/execution.js.map +1 -1
  136. package/lib/util/finality.d.ts.map +1 -0
  137. package/lib/util/fulu.d.ts.map +1 -0
  138. package/lib/util/genesis.d.ts.map +1 -0
  139. package/lib/util/genesis.js +4 -4
  140. package/lib/util/genesis.js.map +1 -1
  141. package/lib/util/index.d.ts +5 -5
  142. package/lib/util/index.d.ts.map +1 -0
  143. package/lib/util/index.js +5 -5
  144. package/lib/util/index.js.map +1 -1
  145. package/lib/util/interop.d.ts.map +1 -0
  146. package/lib/util/interop.js +1 -1
  147. package/lib/util/interop.js.map +1 -1
  148. package/lib/util/loadState/findModifiedInactivityScores.d.ts.map +1 -0
  149. package/lib/util/loadState/findModifiedValidators.d.ts.map +1 -0
  150. package/lib/util/loadState/index.d.ts.map +1 -0
  151. package/lib/util/loadState/loadState.d.ts.map +1 -0
  152. package/lib/util/loadState/loadValidator.d.ts.map +1 -0
  153. package/lib/util/rootCache.d.ts.map +1 -0
  154. package/lib/util/rootCache.js +5 -2
  155. package/lib/util/rootCache.js.map +1 -1
  156. package/lib/util/seed.d.ts.map +1 -0
  157. package/lib/util/seed.js +1 -2
  158. package/lib/util/seed.js.map +1 -1
  159. package/lib/util/shufflingDecisionRoot.d.ts.map +1 -0
  160. package/lib/util/signatureSets.d.ts.map +1 -0
  161. package/lib/util/signingRoot.d.ts.map +1 -0
  162. package/lib/util/slot.d.ts.map +1 -0
  163. package/lib/util/sszBytes.d.ts.map +1 -0
  164. package/lib/util/syncCommittee.d.ts.map +1 -0
  165. package/lib/util/targetUnslashedBalance.d.ts.map +1 -0
  166. package/lib/util/validator.d.ts.map +1 -0
  167. package/lib/util/weakSubjectivity.d.ts.map +1 -0
  168. package/lib/util/weakSubjectivity.js.map +1 -1
  169. package/package.json +13 -11
  170. package/src/block/externalData.ts +26 -0
  171. package/src/block/index.ts +81 -0
  172. package/src/block/initiateValidatorExit.ts +62 -0
  173. package/src/block/isValidIndexedAttestation.ts +70 -0
  174. package/src/block/processAttestationPhase0.ts +158 -0
  175. package/src/block/processAttestations.ts +25 -0
  176. package/src/block/processAttestationsAltair.ts +184 -0
  177. package/src/block/processAttesterSlashing.ts +59 -0
  178. package/src/block/processBlobKzgCommitments.ts +21 -0
  179. package/src/block/processBlockHeader.ts +54 -0
  180. package/src/block/processBlsToExecutionChange.ts +78 -0
  181. package/src/block/processConsolidationRequest.ts +147 -0
  182. package/src/block/processDeposit.ts +166 -0
  183. package/src/block/processDepositRequest.ts +19 -0
  184. package/src/block/processEth1Data.ts +86 -0
  185. package/src/block/processExecutionPayload.ts +84 -0
  186. package/src/block/processOperations.ts +83 -0
  187. package/src/block/processProposerSlashing.ts +66 -0
  188. package/src/block/processRandao.ts +27 -0
  189. package/src/block/processSyncCommittee.ts +117 -0
  190. package/src/block/processVoluntaryExit.ts +55 -0
  191. package/src/block/processWithdrawalRequest.ts +98 -0
  192. package/src/block/processWithdrawals.ts +207 -0
  193. package/src/block/slashValidator.ts +98 -0
  194. package/src/block/types.ts +9 -0
  195. package/src/cache/effectiveBalanceIncrements.ts +39 -0
  196. package/src/cache/epochCache.ts +1213 -0
  197. package/src/cache/epochTransitionCache.ts +542 -0
  198. package/src/cache/pubkeyCache.ts +33 -0
  199. package/src/cache/rewardCache.ts +19 -0
  200. package/src/cache/stateCache.ts +268 -0
  201. package/src/cache/syncCommitteeCache.ts +96 -0
  202. package/src/cache/types.ts +18 -0
  203. package/src/constants/constants.ts +12 -0
  204. package/src/constants/index.ts +1 -0
  205. package/src/epoch/computeUnrealizedCheckpoints.ts +55 -0
  206. package/src/epoch/getAttestationDeltas.ts +169 -0
  207. package/src/epoch/getRewardsAndPenalties.ts +137 -0
  208. package/src/epoch/index.ts +202 -0
  209. package/src/epoch/processEffectiveBalanceUpdates.ts +111 -0
  210. package/src/epoch/processEth1DataReset.ts +17 -0
  211. package/src/epoch/processHistoricalRootsUpdate.ts +25 -0
  212. package/src/epoch/processHistoricalSummariesUpdate.ts +23 -0
  213. package/src/epoch/processInactivityUpdates.ts +60 -0
  214. package/src/epoch/processJustificationAndFinalization.ts +90 -0
  215. package/src/epoch/processParticipationFlagUpdates.ts +27 -0
  216. package/src/epoch/processParticipationRecordUpdates.ts +14 -0
  217. package/src/epoch/processPendingAttestations.ts +75 -0
  218. package/src/epoch/processPendingConsolidations.ts +59 -0
  219. package/src/epoch/processPendingDeposits.ts +136 -0
  220. package/src/epoch/processProposerLookahead.ts +39 -0
  221. package/src/epoch/processRandaoMixesReset.ts +18 -0
  222. package/src/epoch/processRegistryUpdates.ts +65 -0
  223. package/src/epoch/processRewardsAndPenalties.ts +58 -0
  224. package/src/epoch/processSlashings.ts +97 -0
  225. package/src/epoch/processSlashingsReset.ts +20 -0
  226. package/src/epoch/processSyncCommitteeUpdates.ts +44 -0
  227. package/src/index.ts +67 -0
  228. package/src/metrics.ts +169 -0
  229. package/src/signatureSets/attesterSlashings.ts +39 -0
  230. package/src/signatureSets/blsToExecutionChange.ts +43 -0
  231. package/src/signatureSets/index.ts +73 -0
  232. package/src/signatureSets/indexedAttestation.ts +51 -0
  233. package/src/signatureSets/proposer.ts +47 -0
  234. package/src/signatureSets/proposerSlashings.ts +41 -0
  235. package/src/signatureSets/randao.ts +31 -0
  236. package/src/signatureSets/voluntaryExits.ts +44 -0
  237. package/src/slot/index.ts +32 -0
  238. package/src/slot/upgradeStateToAltair.ts +149 -0
  239. package/src/slot/upgradeStateToBellatrix.ts +63 -0
  240. package/src/slot/upgradeStateToCapella.ts +71 -0
  241. package/src/slot/upgradeStateToDeneb.ts +40 -0
  242. package/src/slot/upgradeStateToElectra.ts +126 -0
  243. package/src/slot/upgradeStateToFulu.ts +31 -0
  244. package/src/slot/upgradeStateToGloas.ts +29 -0
  245. package/src/stateTransition.ts +305 -0
  246. package/src/types.ts +26 -0
  247. package/src/util/aggregator.ts +33 -0
  248. package/src/util/altair.ts +13 -0
  249. package/src/util/array.ts +53 -0
  250. package/src/util/attestation.ts +36 -0
  251. package/src/util/attesterStatus.ts +83 -0
  252. package/src/util/balance.ts +83 -0
  253. package/src/util/blindedBlock.ts +144 -0
  254. package/src/util/blockRoot.ts +72 -0
  255. package/src/util/calculateCommitteeAssignments.ts +43 -0
  256. package/src/util/capella.ts +8 -0
  257. package/src/util/computeAnchorCheckpoint.ts +38 -0
  258. package/src/util/deposit.ts +22 -0
  259. package/src/util/domain.ts +31 -0
  260. package/src/util/electra.ts +68 -0
  261. package/src/util/epoch.ts +135 -0
  262. package/src/util/epochShuffling.ts +185 -0
  263. package/src/util/execution.ts +177 -0
  264. package/src/util/finality.ts +17 -0
  265. package/src/util/fulu.ts +43 -0
  266. package/src/util/genesis.ts +343 -0
  267. package/src/util/index.ts +29 -0
  268. package/src/util/interop.ts +22 -0
  269. package/src/util/loadState/findModifiedInactivityScores.ts +47 -0
  270. package/src/util/loadState/findModifiedValidators.ts +46 -0
  271. package/src/util/loadState/index.ts +2 -0
  272. package/src/util/loadState/loadState.ts +225 -0
  273. package/src/util/loadState/loadValidator.ts +77 -0
  274. package/src/util/rootCache.ts +37 -0
  275. package/src/util/seed.ts +381 -0
  276. package/src/util/shufflingDecisionRoot.ts +78 -0
  277. package/src/util/signatureSets.ts +65 -0
  278. package/src/util/signingRoot.ts +13 -0
  279. package/src/util/slot.ts +27 -0
  280. package/src/util/sszBytes.ts +52 -0
  281. package/src/util/syncCommittee.ts +69 -0
  282. package/src/util/targetUnslashedBalance.ts +30 -0
  283. package/src/util/validator.ts +105 -0
  284. package/src/util/weakSubjectivity.ts +186 -0
@@ -0,0 +1,30 @@
1
+ import {EFFECTIVE_BALANCE_INCREMENT, TIMELY_TARGET_FLAG_INDEX} from "@lodestar/params";
2
+ import {Epoch, phase0} from "@lodestar/types";
3
+ import {isActiveValidator} from "./validator.js";
4
+
5
+ /** Same to https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.5/specs/altair/beacon-chain.md#has_flag */
6
+ const TIMELY_TARGET = 1 << TIMELY_TARGET_FLAG_INDEX;
7
+
8
+ /**
9
+ * TODO: describe issue. Compute progressive target balances
10
+ * Compute balances from zero, note this state could be mid-epoch so target balances != 0
11
+ * @param participation from `state.previousEpochParticipation.getAll()`
12
+ * @param epoch either currentEpoch or previousEpoch
13
+ * @param validators from `state.validators.getAllReadonlyValues()`
14
+ */
15
+ export function sumTargetUnslashedBalanceIncrements(
16
+ participation: number[],
17
+ epoch: Epoch,
18
+ validators: phase0.Validator[]
19
+ ): number {
20
+ let total = 0;
21
+ for (let i = 0; i < participation.length; i++) {
22
+ if ((participation[i] & TIMELY_TARGET) === TIMELY_TARGET) {
23
+ const validator = validators[i];
24
+ if (isActiveValidator(validator, epoch) && !validator.slashed) {
25
+ total += Math.floor(validator.effectiveBalance / EFFECTIVE_BALANCE_INCREMENT);
26
+ }
27
+ }
28
+ }
29
+ return total;
30
+ }
@@ -0,0 +1,105 @@
1
+ import {ChainForkConfig} from "@lodestar/config";
2
+ import {
3
+ EFFECTIVE_BALANCE_INCREMENT,
4
+ ForkSeq,
5
+ MAX_EFFECTIVE_BALANCE_ELECTRA,
6
+ MIN_ACTIVATION_BALANCE,
7
+ } from "@lodestar/params";
8
+ import {Epoch, ValidatorIndex, phase0} from "@lodestar/types";
9
+ import {intDiv} from "@lodestar/utils";
10
+ import {BeaconStateAllForks, CachedBeaconStateElectra, EpochCache} from "../types.js";
11
+ import {hasCompoundingWithdrawalCredential} from "./electra.js";
12
+
13
+ /**
14
+ * Check if [[validator]] is active
15
+ */
16
+ export function isActiveValidator(validator: phase0.Validator, epoch: Epoch): boolean {
17
+ return validator.activationEpoch <= epoch && epoch < validator.exitEpoch;
18
+ }
19
+
20
+ /**
21
+ * Check if [[validator]] is slashable
22
+ */
23
+ export function isSlashableValidator(validator: phase0.Validator, epoch: Epoch): boolean {
24
+ return !validator.slashed && validator.activationEpoch <= epoch && epoch < validator.withdrawableEpoch;
25
+ }
26
+
27
+ /**
28
+ * Return the sequence of active validator indices at [[epoch]].
29
+ *
30
+ * NAIVE - SLOW CODE 🐢
31
+ */
32
+ export function getActiveValidatorIndices(state: BeaconStateAllForks, epoch: Epoch): Uint32Array {
33
+ const indices: ValidatorIndex[] = [];
34
+
35
+ const validatorsArr = state.validators.getAllReadonlyValues();
36
+ for (let i = 0; i < validatorsArr.length; i++) {
37
+ if (isActiveValidator(validatorsArr[i], epoch)) {
38
+ indices.push(i);
39
+ }
40
+ }
41
+
42
+ return new Uint32Array(indices);
43
+ }
44
+
45
+ export function getActivationChurnLimit(config: ChainForkConfig, fork: ForkSeq, activeValidatorCount: number): number {
46
+ if (fork >= ForkSeq.deneb) {
47
+ return Math.min(config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT, getChurnLimit(config, activeValidatorCount));
48
+ }
49
+ return getChurnLimit(config, activeValidatorCount);
50
+ }
51
+
52
+ export function getChurnLimit(config: ChainForkConfig, activeValidatorCount: number): number {
53
+ return Math.max(config.MIN_PER_EPOCH_CHURN_LIMIT, intDiv(activeValidatorCount, config.CHURN_LIMIT_QUOTIENT));
54
+ }
55
+
56
+ /**
57
+ * Get combined churn limit of activation-exit and consolidation
58
+ */
59
+ export function getBalanceChurnLimit(
60
+ totalActiveBalanceIncrements: number,
61
+ churnLimitQuotient: number,
62
+ minPerEpochChurnLimit: number
63
+ ): number {
64
+ const churnLimitByTotalActiveBalance = Math.floor(
65
+ (totalActiveBalanceIncrements / churnLimitQuotient) * EFFECTIVE_BALANCE_INCREMENT
66
+ );
67
+
68
+ const churn = Math.max(churnLimitByTotalActiveBalance, minPerEpochChurnLimit);
69
+
70
+ return churn - (churn % EFFECTIVE_BALANCE_INCREMENT);
71
+ }
72
+
73
+ export function getBalanceChurnLimitFromCache(epochCtx: EpochCache): number {
74
+ return getBalanceChurnLimit(
75
+ epochCtx.totalActiveBalanceIncrements,
76
+ epochCtx.config.CHURN_LIMIT_QUOTIENT,
77
+ epochCtx.config.MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA
78
+ );
79
+ }
80
+
81
+ export function getActivationExitChurnLimit(epochCtx: EpochCache): number {
82
+ return Math.min(epochCtx.config.MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT, getBalanceChurnLimitFromCache(epochCtx));
83
+ }
84
+
85
+ export function getConsolidationChurnLimit(epochCtx: EpochCache): number {
86
+ return getBalanceChurnLimitFromCache(epochCtx) - getActivationExitChurnLimit(epochCtx);
87
+ }
88
+
89
+ export function getMaxEffectiveBalance(withdrawalCredentials: Uint8Array): number {
90
+ // Compounding withdrawal credential only available since Electra
91
+ if (hasCompoundingWithdrawalCredential(withdrawalCredentials)) {
92
+ return MAX_EFFECTIVE_BALANCE_ELECTRA;
93
+ }
94
+ return MIN_ACTIVATION_BALANCE;
95
+ }
96
+
97
+ export function getPendingBalanceToWithdraw(state: CachedBeaconStateElectra, validatorIndex: ValidatorIndex): number {
98
+ let total = 0;
99
+ for (const item of state.pendingPartialWithdrawals.getAllReadonly()) {
100
+ if (item.validatorIndex === validatorIndex) {
101
+ total += Number(item.amount);
102
+ }
103
+ }
104
+ return total;
105
+ }
@@ -0,0 +1,186 @@
1
+ import {BeaconConfig, ChainForkConfig} from "@lodestar/config";
2
+ import {
3
+ EFFECTIVE_BALANCE_INCREMENT,
4
+ MAX_DEPOSITS,
5
+ MAX_EFFECTIVE_BALANCE,
6
+ SLOTS_PER_EPOCH,
7
+ isForkPostElectra,
8
+ } from "@lodestar/params";
9
+ import {Epoch, Root, ssz} from "@lodestar/types";
10
+ import {Checkpoint} from "@lodestar/types/phase0";
11
+ import {toRootHex} from "@lodestar/utils";
12
+ import {ZERO_HASH} from "../constants/constants.js";
13
+ import {BeaconStateAllForks, CachedBeaconStateAllForks} from "../types.js";
14
+ import {computeCheckpointEpochAtStateSlot, computeEpochAtSlot, getCurrentEpoch} from "./epoch.js";
15
+ import {getCurrentSlot} from "./slot.js";
16
+ import {
17
+ getActiveValidatorIndices,
18
+ getBalanceChurnLimit,
19
+ getBalanceChurnLimitFromCache,
20
+ getChurnLimit,
21
+ } from "./validator.js";
22
+
23
+ export const ETH_TO_GWEI = 10 ** 9;
24
+ const SAFETY_DECAY = 10;
25
+
26
+ /**
27
+ * Returns the epoch of the latest weak subjectivity checkpoint for the given
28
+ `state` and `safetyDecay`. The default `safetyDecay` used should be 10% (= 0.1)
29
+ */
30
+ export function getLatestWeakSubjectivityCheckpointEpoch(
31
+ config: ChainForkConfig,
32
+ state: CachedBeaconStateAllForks
33
+ ): Epoch {
34
+ return state.epochCtx.epoch - computeWeakSubjectivityPeriodCachedState(config, state);
35
+ }
36
+
37
+ /**
38
+ Returns the weak subjectivity period for the current `state`.
39
+ This computation takes into account the effect of:
40
+ - validator set churn (bounded by `get_validator_churn_limit()` per epoch), and
41
+ - validator balance top-ups (bounded by `MAX_DEPOSITS * SLOTS_PER_EPOCH` per epoch).
42
+ A detailed calculation can be found at:
43
+ https://github.com/runtimeverification/beacon-chain-verification/blob/master/weak-subjectivity/weak-subjectivity-analysis.pdf
44
+ */
45
+ export function computeWeakSubjectivityPeriodCachedState(
46
+ config: ChainForkConfig,
47
+ state: CachedBeaconStateAllForks
48
+ ): number {
49
+ const activeValidatorCount = state.epochCtx.currentShuffling.activeIndices.length;
50
+ const fork = state.config.getForkName(state.slot);
51
+
52
+ return isForkPostElectra(fork)
53
+ ? computeWeakSubjectivityPeriodFromConstituentsElectra(
54
+ state.epochCtx.totalActiveBalanceIncrements,
55
+ getBalanceChurnLimitFromCache(state.epochCtx),
56
+ config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY
57
+ )
58
+ : computeWeakSubjectivityPeriodFromConstituentsPhase0(
59
+ activeValidatorCount,
60
+ state.epochCtx.totalActiveBalanceIncrements,
61
+ getChurnLimit(config, activeValidatorCount),
62
+ config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY
63
+ );
64
+ }
65
+
66
+ /**
67
+ * Same to computeWeakSubjectivityPeriodCachedState but for normal state
68
+ * This is called only 1 time at app startup so it's ok to calculate totalActiveBalanceIncrements manually
69
+ */
70
+ export function computeWeakSubjectivityPeriod(config: ChainForkConfig, state: BeaconStateAllForks): number {
71
+ const activeIndices = getActiveValidatorIndices(state, getCurrentEpoch(state));
72
+ const validators = state.validators.getAllReadonlyValues();
73
+ const fork = config.getForkName(state.slot);
74
+
75
+ let totalActiveBalanceIncrements = 0;
76
+ for (const index of activeIndices) {
77
+ totalActiveBalanceIncrements += Math.floor(validators[index].effectiveBalance / EFFECTIVE_BALANCE_INCREMENT);
78
+ }
79
+ if (totalActiveBalanceIncrements <= 1) {
80
+ totalActiveBalanceIncrements = 1;
81
+ }
82
+
83
+ return isForkPostElectra(fork)
84
+ ? computeWeakSubjectivityPeriodFromConstituentsElectra(
85
+ totalActiveBalanceIncrements,
86
+ getBalanceChurnLimit(
87
+ totalActiveBalanceIncrements,
88
+ config.CHURN_LIMIT_QUOTIENT,
89
+ config.MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA
90
+ ),
91
+ config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY
92
+ )
93
+ : computeWeakSubjectivityPeriodFromConstituentsPhase0(
94
+ activeIndices.length,
95
+ totalActiveBalanceIncrements,
96
+ getChurnLimit(config, activeIndices.length),
97
+ config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY
98
+ );
99
+ }
100
+
101
+ export function computeWeakSubjectivityPeriodFromConstituentsPhase0(
102
+ activeValidatorCount: number,
103
+ totalBalanceByIncrement: number,
104
+ churnLimit: number,
105
+ minWithdrawabilityDelay: number
106
+ ): number {
107
+ const N = activeValidatorCount;
108
+ // originally const t = Number(totalBalance / BigInt(N) / BigInt(ETH_TO_GWEI));
109
+ // totalBalanceByIncrement = totalBalance / MAX_EFFECTIVE_BALANCE and MAX_EFFECTIVE_BALANCE = ETH_TO_GWEI atm
110
+ // we need to change this calculation just in case MAX_EFFECTIVE_BALANCE != ETH_TO_GWEI
111
+ const t = Math.floor(totalBalanceByIncrement / N);
112
+ const T = MAX_EFFECTIVE_BALANCE / ETH_TO_GWEI;
113
+ const delta = churnLimit;
114
+ const Delta = MAX_DEPOSITS * SLOTS_PER_EPOCH;
115
+ const D = SAFETY_DECAY;
116
+
117
+ let wsPeriod = minWithdrawabilityDelay;
118
+ if (T * (200 + 3 * D) < t * (200 + 12 * D)) {
119
+ const epochsForValidatorSetChurn = Math.floor(
120
+ (N * (t * (200 + 12 * D) - T * (200 + 3 * D))) / (600 * delta * (2 * t + T))
121
+ );
122
+ const epochsForBalanceTopUps = Math.floor((N * (200 + 3 * D)) / (600 * Delta));
123
+ wsPeriod +=
124
+ epochsForValidatorSetChurn > epochsForBalanceTopUps ? epochsForValidatorSetChurn : epochsForBalanceTopUps;
125
+ } else {
126
+ wsPeriod += Math.floor((3 * N * D * t) / (200 * Delta * (T - t)));
127
+ }
128
+ return wsPeriod;
129
+ }
130
+
131
+ export function computeWeakSubjectivityPeriodFromConstituentsElectra(
132
+ totalBalanceByIncrement: number,
133
+ // Note this is not the same as churnLimit in `computeWeakSubjectivityPeriodFromConstituentsPhase0`
134
+ balanceChurnLimit: number,
135
+ minWithdrawabilityDelay: number
136
+ ): number {
137
+ // Keep t as increment for now. Multiply final result by EFFECTIVE_BALANCE_INCREMENT
138
+ const t = totalBalanceByIncrement;
139
+ const delta = balanceChurnLimit;
140
+ const epochsForValidatorSetChurn = Math.floor(((SAFETY_DECAY * t) / (2 * delta * 100)) * EFFECTIVE_BALANCE_INCREMENT);
141
+
142
+ return minWithdrawabilityDelay + epochsForValidatorSetChurn;
143
+ }
144
+
145
+ export function getLatestBlockRoot(state: BeaconStateAllForks): Root {
146
+ const header = ssz.phase0.BeaconBlockHeader.clone(state.latestBlockHeader);
147
+ if (ssz.Root.equals(header.stateRoot, ZERO_HASH)) {
148
+ header.stateRoot = state.hashTreeRoot();
149
+ }
150
+ return ssz.phase0.BeaconBlockHeader.hashTreeRoot(header);
151
+ }
152
+
153
+ export function isWithinWeakSubjectivityPeriod(
154
+ config: BeaconConfig,
155
+ wsState: BeaconStateAllForks,
156
+ wsCheckpoint: Checkpoint
157
+ ): boolean {
158
+ try {
159
+ ensureWithinWeakSubjectivityPeriod(config, wsState, wsCheckpoint);
160
+ return true;
161
+ } catch (_) {
162
+ return false;
163
+ }
164
+ }
165
+
166
+ export function ensureWithinWeakSubjectivityPeriod(
167
+ config: BeaconConfig,
168
+ wsState: BeaconStateAllForks,
169
+ wsCheckpoint: Checkpoint
170
+ ): void {
171
+ const wsStateEpoch = computeCheckpointEpochAtStateSlot(wsState.slot);
172
+ const blockRoot = getLatestBlockRoot(wsState);
173
+ if (!ssz.Root.equals(blockRoot, wsCheckpoint.root)) {
174
+ throw new Error(`Roots do not match. expected=${toRootHex(wsCheckpoint.root)}, actual=${toRootHex(blockRoot)}`);
175
+ }
176
+ if (!ssz.Epoch.equals(wsStateEpoch, wsCheckpoint.epoch)) {
177
+ throw new Error(`Epochs do not match. expected=${wsCheckpoint.epoch}, actual=${wsStateEpoch}`);
178
+ }
179
+ const wsPeriod = computeWeakSubjectivityPeriod(config, wsState);
180
+ const clockEpoch = computeEpochAtSlot(getCurrentSlot(config, wsState.genesisTime));
181
+ if (clockEpoch > wsStateEpoch + wsPeriod) {
182
+ throw new Error(
183
+ `The downloaded state with epoch ${wsStateEpoch} is not within weak subjectivity period of ${wsPeriod} from the current epoch ${clockEpoch}. Please verify your checkpoint source`
184
+ );
185
+ }
186
+ }