@lodestar/state-transition 1.35.0-dev.c85be4e26c → 1.35.0-dev.c9deb9b59f

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 (292) 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/processExecutionPayload.js +3 -3
  34. package/lib/block/processExecutionPayload.js.map +1 -1
  35. package/lib/block/processOperations.d.ts.map +1 -0
  36. package/lib/block/processOperations.js.map +1 -1
  37. package/lib/block/processProposerSlashing.d.ts.map +1 -0
  38. package/lib/block/processRandao.d.ts.map +1 -0
  39. package/lib/block/processSyncCommittee.d.ts.map +1 -0
  40. package/lib/block/processSyncCommittee.js +1 -2
  41. package/lib/block/processSyncCommittee.js.map +1 -1
  42. package/lib/block/processVoluntaryExit.d.ts.map +1 -0
  43. package/lib/block/processWithdrawalRequest.d.ts.map +1 -0
  44. package/lib/block/processWithdrawalRequest.js.map +1 -1
  45. package/lib/block/processWithdrawals.d.ts.map +1 -0
  46. package/lib/block/processWithdrawals.js.map +1 -1
  47. package/lib/block/slashValidator.d.ts.map +1 -0
  48. package/lib/block/slashValidator.js.map +1 -1
  49. package/lib/block/types.d.ts.map +1 -0
  50. package/lib/cache/effectiveBalanceIncrements.d.ts.map +1 -0
  51. package/lib/cache/epochCache.d.ts.map +1 -0
  52. package/lib/cache/epochCache.js +130 -0
  53. package/lib/cache/epochCache.js.map +1 -1
  54. package/lib/cache/epochTransitionCache.d.ts.map +1 -0
  55. package/lib/cache/epochTransitionCache.js.map +1 -1
  56. package/lib/cache/pubkeyCache.d.ts.map +1 -0
  57. package/lib/cache/rewardCache.d.ts.map +1 -0
  58. package/lib/cache/stateCache.d.ts.map +1 -0
  59. package/lib/cache/syncCommitteeCache.d.ts.map +1 -0
  60. package/lib/cache/types.d.ts +2 -2
  61. package/lib/cache/types.d.ts.map +1 -0
  62. package/lib/constants/constants.d.ts.map +1 -0
  63. package/lib/constants/index.d.ts.map +1 -0
  64. package/lib/epoch/computeUnrealizedCheckpoints.d.ts.map +1 -0
  65. package/lib/epoch/getAttestationDeltas.d.ts.map +1 -0
  66. package/lib/epoch/getRewardsAndPenalties.d.ts.map +1 -0
  67. package/lib/epoch/index.d.ts.map +1 -0
  68. package/lib/epoch/index.js.map +1 -1
  69. package/lib/epoch/processEffectiveBalanceUpdates.d.ts.map +1 -0
  70. package/lib/epoch/processEth1DataReset.d.ts.map +1 -0
  71. package/lib/epoch/processHistoricalRootsUpdate.d.ts.map +1 -0
  72. package/lib/epoch/processHistoricalSummariesUpdate.d.ts.map +1 -0
  73. package/lib/epoch/processInactivityUpdates.d.ts.map +1 -0
  74. package/lib/epoch/processJustificationAndFinalization.d.ts.map +1 -0
  75. package/lib/epoch/processParticipationFlagUpdates.d.ts.map +1 -0
  76. package/lib/epoch/processParticipationRecordUpdates.d.ts.map +1 -0
  77. package/lib/epoch/processPendingAttestations.d.ts.map +1 -0
  78. package/lib/epoch/processPendingConsolidations.d.ts.map +1 -0
  79. package/lib/epoch/processPendingDeposits.d.ts.map +1 -0
  80. package/lib/epoch/processProposerLookahead.d.ts.map +1 -0
  81. package/lib/epoch/processRandaoMixesReset.d.ts.map +1 -0
  82. package/lib/epoch/processRegistryUpdates.d.ts.map +1 -0
  83. package/lib/epoch/processRewardsAndPenalties.d.ts.map +1 -0
  84. package/lib/epoch/processSlashings.d.ts.map +1 -0
  85. package/lib/epoch/processSlashings.js.map +1 -1
  86. package/lib/epoch/processSlashingsReset.d.ts.map +1 -0
  87. package/lib/epoch/processSyncCommitteeUpdates.d.ts.map +1 -0
  88. package/lib/index.d.ts +17 -17
  89. package/lib/index.d.ts.map +1 -0
  90. package/lib/index.js +16 -16
  91. package/lib/index.js.map +1 -1
  92. package/lib/metrics.d.ts.map +1 -0
  93. package/lib/signatureSets/attesterSlashings.d.ts.map +1 -0
  94. package/lib/signatureSets/blsToExecutionChange.d.ts.map +1 -0
  95. package/lib/signatureSets/blsToExecutionChange.js.map +1 -1
  96. package/lib/signatureSets/index.d.ts +1 -1
  97. package/lib/signatureSets/index.d.ts.map +1 -0
  98. package/lib/signatureSets/index.js +1 -1
  99. package/lib/signatureSets/index.js.map +1 -1
  100. package/lib/signatureSets/indexedAttestation.d.ts.map +1 -0
  101. package/lib/signatureSets/proposer.d.ts.map +1 -0
  102. package/lib/signatureSets/proposerSlashings.d.ts.map +1 -0
  103. package/lib/signatureSets/randao.d.ts.map +1 -0
  104. package/lib/signatureSets/voluntaryExits.d.ts.map +1 -0
  105. package/lib/slot/index.d.ts.map +1 -0
  106. package/lib/slot/upgradeStateToAltair.d.ts.map +1 -0
  107. package/lib/slot/upgradeStateToBellatrix.d.ts.map +1 -0
  108. package/lib/slot/upgradeStateToCapella.d.ts.map +1 -0
  109. package/lib/slot/upgradeStateToDeneb.d.ts +1 -2
  110. package/lib/slot/upgradeStateToDeneb.d.ts.map +1 -0
  111. package/lib/slot/upgradeStateToDeneb.js.map +1 -1
  112. package/lib/slot/upgradeStateToElectra.d.ts.map +1 -0
  113. package/lib/slot/upgradeStateToFulu.d.ts.map +1 -0
  114. package/lib/slot/upgradeStateToGloas.d.ts.map +1 -0
  115. package/lib/slot/upgradeStateToGloas.js +2 -2
  116. package/lib/slot/upgradeStateToGloas.js.map +1 -1
  117. package/lib/stateTransition.d.ts.map +1 -0
  118. package/lib/types.d.ts +2 -2
  119. package/lib/types.d.ts.map +1 -0
  120. package/lib/util/aggregator.d.ts.map +1 -0
  121. package/lib/util/altair.d.ts.map +1 -0
  122. package/lib/util/array.d.ts.map +1 -0
  123. package/lib/util/attestation.d.ts.map +1 -0
  124. package/lib/util/attesterStatus.d.ts.map +1 -0
  125. package/lib/util/balance.d.ts.map +1 -0
  126. package/lib/util/blindedBlock.d.ts +3 -3
  127. package/lib/util/blindedBlock.d.ts.map +1 -0
  128. package/lib/util/blindedBlock.js.map +1 -1
  129. package/lib/util/blockRoot.d.ts.map +1 -0
  130. package/lib/util/calculateCommitteeAssignments.d.ts.map +1 -0
  131. package/lib/util/capella.d.ts.map +1 -0
  132. package/lib/util/computeAnchorCheckpoint.d.ts.map +1 -0
  133. package/lib/util/deposit.d.ts.map +1 -0
  134. package/lib/util/domain.d.ts.map +1 -0
  135. package/lib/util/electra.d.ts.map +1 -0
  136. package/lib/util/epoch.d.ts.map +1 -0
  137. package/lib/util/epochShuffling.d.ts.map +1 -0
  138. package/lib/util/execution.d.ts +2 -2
  139. package/lib/util/execution.d.ts.map +1 -0
  140. package/lib/util/execution.js.map +1 -1
  141. package/lib/util/finality.d.ts.map +1 -0
  142. package/lib/util/fulu.d.ts.map +1 -0
  143. package/lib/util/genesis.d.ts.map +1 -0
  144. package/lib/util/genesis.js +3 -6
  145. package/lib/util/genesis.js.map +1 -1
  146. package/lib/util/index.d.ts +5 -5
  147. package/lib/util/index.d.ts.map +1 -0
  148. package/lib/util/index.js +5 -5
  149. package/lib/util/index.js.map +1 -1
  150. package/lib/util/interop.d.ts.map +1 -0
  151. package/lib/util/interop.js +1 -1
  152. package/lib/util/interop.js.map +1 -1
  153. package/lib/util/loadState/findModifiedInactivityScores.d.ts.map +1 -0
  154. package/lib/util/loadState/findModifiedValidators.d.ts.map +1 -0
  155. package/lib/util/loadState/index.d.ts.map +1 -0
  156. package/lib/util/loadState/loadState.d.ts.map +1 -0
  157. package/lib/util/loadState/loadValidator.d.ts.map +1 -0
  158. package/lib/util/rootCache.d.ts.map +1 -0
  159. package/lib/util/rootCache.js +5 -2
  160. package/lib/util/rootCache.js.map +1 -1
  161. package/lib/util/seed.d.ts.map +1 -0
  162. package/lib/util/seed.js +1 -2
  163. package/lib/util/seed.js.map +1 -1
  164. package/lib/util/shufflingDecisionRoot.d.ts.map +1 -0
  165. package/lib/util/signatureSets.d.ts.map +1 -0
  166. package/lib/util/signingRoot.d.ts.map +1 -0
  167. package/lib/util/slot.d.ts +0 -1
  168. package/lib/util/slot.d.ts.map +1 -0
  169. package/lib/util/slot.js +3 -7
  170. package/lib/util/slot.js.map +1 -1
  171. package/lib/util/sszBytes.d.ts.map +1 -0
  172. package/lib/util/syncCommittee.d.ts.map +1 -0
  173. package/lib/util/targetUnslashedBalance.d.ts.map +1 -0
  174. package/lib/util/validator.d.ts.map +1 -0
  175. package/lib/util/weakSubjectivity.d.ts.map +1 -0
  176. package/lib/util/weakSubjectivity.js.map +1 -1
  177. package/package.json +13 -11
  178. package/src/block/externalData.ts +26 -0
  179. package/src/block/index.ts +81 -0
  180. package/src/block/initiateValidatorExit.ts +62 -0
  181. package/src/block/isValidIndexedAttestation.ts +70 -0
  182. package/src/block/processAttestationPhase0.ts +158 -0
  183. package/src/block/processAttestations.ts +25 -0
  184. package/src/block/processAttestationsAltair.ts +184 -0
  185. package/src/block/processAttesterSlashing.ts +59 -0
  186. package/src/block/processBlobKzgCommitments.ts +21 -0
  187. package/src/block/processBlockHeader.ts +54 -0
  188. package/src/block/processBlsToExecutionChange.ts +78 -0
  189. package/src/block/processConsolidationRequest.ts +147 -0
  190. package/src/block/processDeposit.ts +166 -0
  191. package/src/block/processDepositRequest.ts +19 -0
  192. package/src/block/processEth1Data.ts +86 -0
  193. package/src/block/processExecutionPayload.ts +84 -0
  194. package/src/block/processOperations.ts +83 -0
  195. package/src/block/processProposerSlashing.ts +66 -0
  196. package/src/block/processRandao.ts +27 -0
  197. package/src/block/processSyncCommittee.ts +117 -0
  198. package/src/block/processVoluntaryExit.ts +55 -0
  199. package/src/block/processWithdrawalRequest.ts +98 -0
  200. package/src/block/processWithdrawals.ts +207 -0
  201. package/src/block/slashValidator.ts +98 -0
  202. package/src/block/types.ts +9 -0
  203. package/src/cache/effectiveBalanceIncrements.ts +39 -0
  204. package/src/cache/epochCache.ts +1213 -0
  205. package/src/cache/epochTransitionCache.ts +542 -0
  206. package/src/cache/pubkeyCache.ts +33 -0
  207. package/src/cache/rewardCache.ts +19 -0
  208. package/src/cache/stateCache.ts +268 -0
  209. package/src/cache/syncCommitteeCache.ts +96 -0
  210. package/src/cache/types.ts +18 -0
  211. package/src/constants/constants.ts +12 -0
  212. package/src/constants/index.ts +1 -0
  213. package/src/epoch/computeUnrealizedCheckpoints.ts +55 -0
  214. package/src/epoch/getAttestationDeltas.ts +169 -0
  215. package/src/epoch/getRewardsAndPenalties.ts +137 -0
  216. package/src/epoch/index.ts +202 -0
  217. package/src/epoch/processEffectiveBalanceUpdates.ts +111 -0
  218. package/src/epoch/processEth1DataReset.ts +17 -0
  219. package/src/epoch/processHistoricalRootsUpdate.ts +25 -0
  220. package/src/epoch/processHistoricalSummariesUpdate.ts +23 -0
  221. package/src/epoch/processInactivityUpdates.ts +60 -0
  222. package/src/epoch/processJustificationAndFinalization.ts +90 -0
  223. package/src/epoch/processParticipationFlagUpdates.ts +27 -0
  224. package/src/epoch/processParticipationRecordUpdates.ts +14 -0
  225. package/src/epoch/processPendingAttestations.ts +75 -0
  226. package/src/epoch/processPendingConsolidations.ts +59 -0
  227. package/src/epoch/processPendingDeposits.ts +136 -0
  228. package/src/epoch/processProposerLookahead.ts +39 -0
  229. package/src/epoch/processRandaoMixesReset.ts +18 -0
  230. package/src/epoch/processRegistryUpdates.ts +65 -0
  231. package/src/epoch/processRewardsAndPenalties.ts +58 -0
  232. package/src/epoch/processSlashings.ts +97 -0
  233. package/src/epoch/processSlashingsReset.ts +20 -0
  234. package/src/epoch/processSyncCommitteeUpdates.ts +44 -0
  235. package/src/index.ts +67 -0
  236. package/src/metrics.ts +169 -0
  237. package/src/signatureSets/attesterSlashings.ts +39 -0
  238. package/src/signatureSets/blsToExecutionChange.ts +43 -0
  239. package/src/signatureSets/index.ts +73 -0
  240. package/src/signatureSets/indexedAttestation.ts +51 -0
  241. package/src/signatureSets/proposer.ts +47 -0
  242. package/src/signatureSets/proposerSlashings.ts +41 -0
  243. package/src/signatureSets/randao.ts +31 -0
  244. package/src/signatureSets/voluntaryExits.ts +44 -0
  245. package/src/slot/index.ts +32 -0
  246. package/src/slot/upgradeStateToAltair.ts +149 -0
  247. package/src/slot/upgradeStateToBellatrix.ts +63 -0
  248. package/src/slot/upgradeStateToCapella.ts +71 -0
  249. package/src/slot/upgradeStateToDeneb.ts +40 -0
  250. package/src/slot/upgradeStateToElectra.ts +126 -0
  251. package/src/slot/upgradeStateToFulu.ts +31 -0
  252. package/src/slot/upgradeStateToGloas.ts +29 -0
  253. package/src/stateTransition.ts +305 -0
  254. package/src/types.ts +26 -0
  255. package/src/util/aggregator.ts +33 -0
  256. package/src/util/altair.ts +13 -0
  257. package/src/util/array.ts +53 -0
  258. package/src/util/attestation.ts +36 -0
  259. package/src/util/attesterStatus.ts +83 -0
  260. package/src/util/balance.ts +83 -0
  261. package/src/util/blindedBlock.ts +145 -0
  262. package/src/util/blockRoot.ts +72 -0
  263. package/src/util/calculateCommitteeAssignments.ts +43 -0
  264. package/src/util/capella.ts +8 -0
  265. package/src/util/computeAnchorCheckpoint.ts +38 -0
  266. package/src/util/deposit.ts +22 -0
  267. package/src/util/domain.ts +31 -0
  268. package/src/util/electra.ts +68 -0
  269. package/src/util/epoch.ts +135 -0
  270. package/src/util/epochShuffling.ts +185 -0
  271. package/src/util/execution.ts +179 -0
  272. package/src/util/finality.ts +17 -0
  273. package/src/util/fulu.ts +43 -0
  274. package/src/util/genesis.ts +340 -0
  275. package/src/util/index.ts +29 -0
  276. package/src/util/interop.ts +22 -0
  277. package/src/util/loadState/findModifiedInactivityScores.ts +47 -0
  278. package/src/util/loadState/findModifiedValidators.ts +46 -0
  279. package/src/util/loadState/index.ts +2 -0
  280. package/src/util/loadState/loadState.ts +225 -0
  281. package/src/util/loadState/loadValidator.ts +77 -0
  282. package/src/util/rootCache.ts +37 -0
  283. package/src/util/seed.ts +381 -0
  284. package/src/util/shufflingDecisionRoot.ts +78 -0
  285. package/src/util/signatureSets.ts +65 -0
  286. package/src/util/signingRoot.ts +13 -0
  287. package/src/util/slot.ts +22 -0
  288. package/src/util/sszBytes.ts +52 -0
  289. package/src/util/syncCommittee.ts +69 -0
  290. package/src/util/targetUnslashedBalance.ts +30 -0
  291. package/src/util/validator.ts +105 -0
  292. package/src/util/weakSubjectivity.ts +186 -0
@@ -0,0 +1,305 @@
1
+ import {SLOTS_PER_EPOCH} from "@lodestar/params";
2
+ import {Epoch, SignedBeaconBlock, SignedBlindedBeaconBlock, Slot, ssz} from "@lodestar/types";
3
+ import {toRootHex} from "@lodestar/utils";
4
+ import {BlockExternalData, DataAvailabilityStatus, ExecutionPayloadStatus} from "./block/externalData.js";
5
+ import {processBlock} from "./block/index.js";
6
+ import {ProcessBlockOpts} from "./block/types.js";
7
+ import {EpochTransitionCache, EpochTransitionCacheOpts, beforeProcessEpoch} from "./cache/epochTransitionCache.js";
8
+ import {EpochTransitionStep, processEpoch} from "./epoch/index.js";
9
+ import {BeaconStateTransitionMetrics, onPostStateMetrics, onStateCloneMetrics} from "./metrics.js";
10
+ import {verifyProposerSignature} from "./signatureSets/index.js";
11
+ import {
12
+ processSlot,
13
+ upgradeStateToAltair,
14
+ upgradeStateToBellatrix,
15
+ upgradeStateToCapella,
16
+ upgradeStateToDeneb,
17
+ upgradeStateToElectra,
18
+ upgradeStateToGloas,
19
+ } from "./slot/index.js";
20
+ import {upgradeStateToFulu} from "./slot/upgradeStateToFulu.js";
21
+ import {
22
+ CachedBeaconStateAllForks,
23
+ CachedBeaconStateAltair,
24
+ CachedBeaconStateBellatrix,
25
+ CachedBeaconStateCapella,
26
+ CachedBeaconStateDeneb,
27
+ CachedBeaconStateElectra,
28
+ CachedBeaconStateFulu,
29
+ CachedBeaconStatePhase0,
30
+ } from "./types.js";
31
+ import {computeEpochAtSlot} from "./util/index.js";
32
+
33
+ // Multifork capable state transition
34
+
35
+ // NOTE DENEB: Mandatory BlockExternalData to decide if block is available or not
36
+ export type StateTransitionOpts = BlockExternalData &
37
+ EpochTransitionCacheOpts &
38
+ ProcessBlockOpts & {
39
+ verifyStateRoot?: boolean;
40
+ verifyProposer?: boolean;
41
+ verifySignatures?: boolean;
42
+ dontTransferCache?: boolean;
43
+ };
44
+
45
+ export type StateTransitionModules = {
46
+ metrics?: BeaconStateTransitionMetrics | null;
47
+ validatorMonitor?: ValidatorMonitor | null;
48
+ };
49
+
50
+ interface ValidatorMonitor {
51
+ registerValidatorStatuses(
52
+ currentEpoch: Epoch,
53
+ inclusionDelays: number[],
54
+ flags: number[],
55
+ isActiveCurrEpoch: boolean[],
56
+ isActivePrevEpoch: boolean[],
57
+ balances?: number[]
58
+ ): void;
59
+ }
60
+
61
+ /**
62
+ * `state.clone()` invocation source tracked in metrics
63
+ */
64
+ export enum StateCloneSource {
65
+ stateTransition = "stateTransition",
66
+ processSlots = "processSlots",
67
+ }
68
+
69
+ /**
70
+ * `state.hashTreeRoot()` invocation source tracked in metrics
71
+ */
72
+ export enum StateHashTreeRootSource {
73
+ stateTransition = "state_transition",
74
+ blockTransition = "block_transition",
75
+ prepareNextSlot = "prepare_next_slot",
76
+ prepareNextEpoch = "prepare_next_epoch",
77
+ regenState = "regen_state",
78
+ computeNewStateRoot = "compute_new_state_root",
79
+ }
80
+
81
+ /**
82
+ * Implementation Note: follows the optimizations in protolambda's eth2fastspec (https://github.com/protolambda/eth2fastspec)
83
+ */
84
+ export function stateTransition(
85
+ state: CachedBeaconStateAllForks,
86
+ signedBlock: SignedBeaconBlock | SignedBlindedBeaconBlock,
87
+ options: StateTransitionOpts = {
88
+ // Assume default to be valid and available
89
+ executionPayloadStatus: ExecutionPayloadStatus.valid,
90
+ dataAvailabilityStatus: DataAvailabilityStatus.Available,
91
+ },
92
+ {metrics, validatorMonitor}: StateTransitionModules = {}
93
+ ): CachedBeaconStateAllForks {
94
+ const {verifyStateRoot = true, verifyProposer = true} = options;
95
+
96
+ const block = signedBlock.message;
97
+ const blockSlot = block.slot;
98
+
99
+ // .clone() before mutating state in state transition
100
+ let postState = state.clone(options.dontTransferCache);
101
+
102
+ if (metrics) {
103
+ onStateCloneMetrics(postState, metrics, StateCloneSource.stateTransition);
104
+ }
105
+
106
+ // State is already a ViewDU, which won't commit changes. Equivalent to .setStateCachesAsTransient()
107
+ // postState.setStateCachesAsTransient();
108
+
109
+ // Process slots (including those with no blocks) since block.
110
+ // Includes state upgrades
111
+ postState = processSlotsWithTransientCache(postState, blockSlot, options, {metrics, validatorMonitor});
112
+
113
+ // Verify proposer signature only
114
+ if (verifyProposer && !verifyProposerSignature(postState, signedBlock)) {
115
+ throw new Error("Invalid block signature");
116
+ }
117
+
118
+ // Process block
119
+ const fork = state.config.getForkSeq(block.slot);
120
+
121
+ // Note: time only on success
122
+ const processBlockTimer = metrics?.processBlockTime.startTimer();
123
+
124
+ processBlock(fork, postState, block, options, options, metrics);
125
+
126
+ const processBlockCommitTimer = metrics?.processBlockCommitTime.startTimer();
127
+ postState.commit();
128
+ processBlockCommitTimer?.();
129
+
130
+ // Note: time only on success. Include processBlock and commit
131
+ processBlockTimer?.();
132
+
133
+ if (metrics) {
134
+ onPostStateMetrics(postState, metrics);
135
+ }
136
+
137
+ // Verify state root
138
+ if (verifyStateRoot) {
139
+ const hashTreeRootTimer = metrics?.stateHashTreeRootTime.startTimer({
140
+ source: StateHashTreeRootSource.stateTransition,
141
+ });
142
+ const stateRoot = postState.hashTreeRoot();
143
+ hashTreeRootTimer?.();
144
+
145
+ if (!ssz.Root.equals(block.stateRoot, stateRoot)) {
146
+ throw new Error(
147
+ `Invalid state root at slot ${block.slot}, expected=${toRootHex(block.stateRoot)}, actual=${toRootHex(
148
+ stateRoot
149
+ )}`
150
+ );
151
+ }
152
+ }
153
+
154
+ return postState;
155
+ }
156
+
157
+ /**
158
+ * Like `processSlots` from the spec but additionally handles fork upgrades
159
+ *
160
+ * Implementation Note: follows the optimizations in protolambda's eth2fastspec (https://github.com/protolambda/eth2fastspec)
161
+ */
162
+ export function processSlots(
163
+ state: CachedBeaconStateAllForks,
164
+ slot: Slot,
165
+ epochTransitionCacheOpts?: EpochTransitionCacheOpts & {dontTransferCache?: boolean},
166
+ {metrics, validatorMonitor}: StateTransitionModules = {}
167
+ ): CachedBeaconStateAllForks {
168
+ // .clone() before mutating state in state transition
169
+ let postState = state.clone(epochTransitionCacheOpts?.dontTransferCache);
170
+
171
+ if (metrics) {
172
+ onStateCloneMetrics(postState, metrics, StateCloneSource.processSlots);
173
+ }
174
+
175
+ // State is already a ViewDU, which won't commit changes. Equivalent to .setStateCachesAsTransient()
176
+ // postState.setStateCachesAsTransient();
177
+
178
+ postState = processSlotsWithTransientCache(postState, slot, epochTransitionCacheOpts, {metrics, validatorMonitor});
179
+
180
+ // Apply changes to state, must do before hashing
181
+ postState.commit();
182
+
183
+ return postState;
184
+ }
185
+
186
+ /**
187
+ * All processSlot() logic but separate so stateTransition() can recycle the caches
188
+ *
189
+ * Epoch transition will be processed at the last slot of an epoch. Note that compute_shuffling() is going
190
+ * to be executed in parallel (either by napi-rs or worker thread) with processEpoch() like below:
191
+ *
192
+ * state-transition
193
+ * ╔══════════════════════════════════════════════════════════════════════════════════╗
194
+ * ║ beforeProcessEpoch processEpoch afterPRocessEpoch ║
195
+ * ║ |-------------------------|--------------------|-------------------------------|║
196
+ * ║ | | | ║
197
+ * ╚═══════════════════════|═══════════════════════════════|══════════════════════════╝
198
+ * | |
199
+ * build() get()
200
+ * | |
201
+ * ╔═══════════════════════V═══════════════════════════════V═══════════════════════════╗
202
+ * ║ | | ║
203
+ * ║ |-------------------------------| ║
204
+ * ║ compute_shuffling() ║
205
+ * ╚═══════════════════════════════════════════════════════════════════════════════════╝
206
+ * beacon-node ShufflingCache
207
+ */
208
+ function processSlotsWithTransientCache(
209
+ postState: CachedBeaconStateAllForks,
210
+ slot: Slot,
211
+ epochTransitionCacheOpts?: EpochTransitionCacheOpts,
212
+ {metrics, validatorMonitor}: StateTransitionModules = {}
213
+ ): CachedBeaconStateAllForks {
214
+ const {config} = postState;
215
+ if (postState.slot > slot) {
216
+ throw Error(`Too old slot ${slot}, current=${postState.slot}`);
217
+ }
218
+
219
+ while (postState.slot < slot) {
220
+ processSlot(postState);
221
+
222
+ // Process epoch on the first slot of the next epoch
223
+ if ((postState.slot + 1) % SLOTS_PER_EPOCH === 0) {
224
+ // At fork boundary we don't want to process "next fork" epoch before upgrading state
225
+ const fork = postState.config.getForkSeq(postState.slot);
226
+
227
+ const epochTransitionTimer = metrics?.epochTransitionTime.startTimer();
228
+
229
+ let epochTransitionCache: EpochTransitionCache;
230
+ {
231
+ const timer = metrics?.epochTransitionStepTime.startTimer({step: EpochTransitionStep.beforeProcessEpoch});
232
+ epochTransitionCache = beforeProcessEpoch(postState, epochTransitionCacheOpts);
233
+ timer?.();
234
+ }
235
+
236
+ processEpoch(fork, postState, epochTransitionCache, metrics);
237
+
238
+ const {currentEpoch, inclusionDelays, flags, isActiveCurrEpoch, isActivePrevEpoch, balances} =
239
+ epochTransitionCache;
240
+ validatorMonitor?.registerValidatorStatuses(
241
+ currentEpoch,
242
+ inclusionDelays,
243
+ flags,
244
+ isActiveCurrEpoch,
245
+ isActivePrevEpoch,
246
+ balances
247
+ );
248
+
249
+ postState.slot++;
250
+
251
+ {
252
+ const timer = metrics?.epochTransitionStepTime.startTimer({step: EpochTransitionStep.afterProcessEpoch});
253
+ // this should be called before `upgradeState*()` below to prepare data for it
254
+ postState.epochCtx.afterProcessEpoch(postState, epochTransitionCache);
255
+ timer?.();
256
+ }
257
+
258
+ // Upgrade state if exactly at epoch boundary
259
+ const stateEpoch = computeEpochAtSlot(postState.slot);
260
+ if (stateEpoch === config.ALTAIR_FORK_EPOCH) {
261
+ postState = upgradeStateToAltair(postState as CachedBeaconStatePhase0) as CachedBeaconStateAllForks;
262
+ }
263
+ if (stateEpoch === config.BELLATRIX_FORK_EPOCH) {
264
+ postState = upgradeStateToBellatrix(postState as CachedBeaconStateAltair) as CachedBeaconStateAllForks;
265
+ }
266
+ if (stateEpoch === config.CAPELLA_FORK_EPOCH) {
267
+ postState = upgradeStateToCapella(postState as CachedBeaconStateBellatrix) as CachedBeaconStateAllForks;
268
+ }
269
+ if (stateEpoch === config.DENEB_FORK_EPOCH) {
270
+ postState = upgradeStateToDeneb(postState as CachedBeaconStateCapella) as CachedBeaconStateAllForks;
271
+ }
272
+ if (stateEpoch === config.ELECTRA_FORK_EPOCH) {
273
+ postState = upgradeStateToElectra(postState as CachedBeaconStateDeneb) as CachedBeaconStateAllForks;
274
+ }
275
+ if (stateEpoch === config.FULU_FORK_EPOCH) {
276
+ postState = upgradeStateToFulu(postState as CachedBeaconStateElectra) as CachedBeaconStateAllForks;
277
+ }
278
+ if (stateEpoch === config.GLOAS_FORK_EPOCH) {
279
+ postState = upgradeStateToGloas(postState as CachedBeaconStateFulu) as CachedBeaconStateAllForks;
280
+ }
281
+
282
+ {
283
+ const timer = metrics?.epochTransitionStepTime.startTimer({step: EpochTransitionStep.finalProcessEpoch});
284
+ // last step to prepare epoch data that depends on the upgraded state, for example proposerLookahead of BeaconStateFulu
285
+ postState.epochCtx.finalProcessEpoch(postState);
286
+ timer?.();
287
+ }
288
+
289
+ // Running commit here is not strictly necessary. The cost of running commit twice (here + after process block)
290
+ // Should be negligible but gives better metrics to differentiate the cost of it for block and epoch proc.
291
+ {
292
+ const timer = metrics?.epochTransitionCommitTime.startTimer();
293
+ postState.commit();
294
+ timer?.();
295
+ }
296
+
297
+ // Note: time only on success. Include beforeProcessEpoch, processEpoch, afterProcessEpoch, upgradeState*, finalProcessEpoch, commit
298
+ epochTransitionTimer?.();
299
+ } else {
300
+ postState.slot++;
301
+ }
302
+ }
303
+
304
+ return postState;
305
+ }
package/src/types.ts ADDED
@@ -0,0 +1,26 @@
1
+ export {EpochCache} from "./cache/epochCache.js";
2
+ export type {EpochTransitionCache} from "./cache/epochTransitionCache.js";
3
+ export type {
4
+ CachedBeaconStateAllForks,
5
+ CachedBeaconStateAltair,
6
+ CachedBeaconStateBellatrix,
7
+ CachedBeaconStateCapella,
8
+ CachedBeaconStateDeneb,
9
+ CachedBeaconStateElectra,
10
+ CachedBeaconStateExecutions,
11
+ CachedBeaconStateFulu,
12
+ CachedBeaconStateGloas,
13
+ CachedBeaconStatePhase0,
14
+ } from "./cache/stateCache.js";
15
+ export type {
16
+ BeaconStateAllForks,
17
+ BeaconStateAltair,
18
+ BeaconStateBellatrix,
19
+ BeaconStateCapella,
20
+ BeaconStateDeneb,
21
+ BeaconStateElectra,
22
+ BeaconStateExecutions,
23
+ BeaconStateFulu,
24
+ BeaconStateGloas,
25
+ BeaconStatePhase0,
26
+ } from "./cache/types.js";
@@ -0,0 +1,33 @@
1
+ import {digest} from "@chainsafe/as-sha256";
2
+ import {
3
+ SYNC_COMMITTEE_SIZE,
4
+ SYNC_COMMITTEE_SUBNET_COUNT,
5
+ TARGET_AGGREGATORS_PER_COMMITTEE,
6
+ TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE,
7
+ } from "@lodestar/params";
8
+ import {BLSSignature} from "@lodestar/types";
9
+ import {bytesToBigInt, intDiv} from "@lodestar/utils";
10
+
11
+ const ZERO_BIGINT = BigInt(0);
12
+
13
+ export function isSyncCommitteeAggregator(selectionProof: BLSSignature): boolean {
14
+ const modulo = Math.max(
15
+ 1,
16
+ intDiv(intDiv(SYNC_COMMITTEE_SIZE, SYNC_COMMITTEE_SUBNET_COUNT), TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE)
17
+ );
18
+ return isSelectionProofValid(selectionProof, modulo);
19
+ }
20
+
21
+ export function isAggregatorFromCommitteeLength(committeeLength: number, slotSignature: BLSSignature): boolean {
22
+ const modulo = Math.max(1, intDiv(committeeLength, TARGET_AGGREGATORS_PER_COMMITTEE));
23
+ return isSelectionProofValid(slotSignature, modulo);
24
+ }
25
+
26
+ /**
27
+ * Note: **must** use bytesToBigInt() otherwise a JS number is not able to represent the latest digits of
28
+ * the remainder, resulting in `14333559117764833000` for example, where the last three digits are always zero.
29
+ * Using bytesToInt() may cause isSelectionProofValid() to always return false.
30
+ */
31
+ export function isSelectionProofValid(sig: BLSSignature, modulo: number): boolean {
32
+ return bytesToBigInt(digest(sig).slice(0, 8)) % BigInt(modulo) === ZERO_BIGINT;
33
+ }
@@ -0,0 +1,13 @@
1
+ import {BASE_REWARD_FACTOR, EFFECTIVE_BALANCE_INCREMENT} from "@lodestar/params";
2
+ import {bigIntSqrt, bnToNum} from "@lodestar/utils";
3
+
4
+ /**
5
+ * Before we manage bigIntSqrt(totalActiveStake) as BigInt and return BigInt.
6
+ * bigIntSqrt(totalActiveStake) should fit a number (2 ** 53 -1 max)
7
+ **/
8
+ export function computeBaseRewardPerIncrement(totalActiveStakeByIncrement: number): number {
9
+ return Math.floor(
10
+ (EFFECTIVE_BALANCE_INCREMENT * BASE_REWARD_FACTOR) /
11
+ bnToNum(bigIntSqrt(BigInt(totalActiveStakeByIncrement) * BigInt(EFFECTIVE_BALANCE_INCREMENT)))
12
+ );
13
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Returns an array of size `n` filled with 0
3
+ * 20 times faster than
4
+ * ```
5
+ * Array.from({length: n}, () => 0)
6
+ * ```
7
+ * - Array.from: 40ms / 200_000 elements
8
+ * - This fn: 2.2ms / 200_000 elements
9
+ */
10
+ export function newZeroedArray(n: number): number[] {
11
+ const arr = new Array<number>(n);
12
+ for (let i = 0; i < n; ++i) {
13
+ arr[i] = 0;
14
+ }
15
+ return arr;
16
+ }
17
+
18
+ export function newZeroedBigIntArray(n: number): bigint[] {
19
+ const arr = new Array<bigint>(n);
20
+ for (let i = 0; i < n; ++i) {
21
+ arr[i] = BigInt(0);
22
+ }
23
+ return arr;
24
+ }
25
+
26
+ export function newFilledArray<T>(n: number, val: T): T[] {
27
+ const arr = new Array<T>(n);
28
+ for (let i = 0; i < n; ++i) {
29
+ arr[i] = val;
30
+ }
31
+ return arr;
32
+ }
33
+
34
+ /**
35
+ * Returns an array with all values not in the participants array.
36
+ * - All elements in values must be unique
37
+ * - Does NOT require sorting
38
+ */
39
+ export function getUnparticipantValues<T>(participants: T[], values: T[]): T[] {
40
+ const unparticipants: T[] = [];
41
+
42
+ let j = 0;
43
+ for (let i = 0; i < values.length; i++) {
44
+ if (values[i] === participants[j]) {
45
+ // Included
46
+ j++;
47
+ } else {
48
+ unparticipants.push(values[i]);
49
+ }
50
+ }
51
+
52
+ return unparticipants;
53
+ }
@@ -0,0 +1,36 @@
1
+ import {MIN_ATTESTATION_INCLUSION_DELAY, SLOTS_PER_EPOCH} from "@lodestar/params";
2
+ import {AttesterSlashing, Slot, ValidatorIndex, phase0, ssz} from "@lodestar/types";
3
+
4
+ /**
5
+ * Check if [[data1]] and [[data2]] are slashable according to Casper FFG rules.
6
+ */
7
+ export function isSlashableAttestationData(
8
+ data1: phase0.AttestationDataBigint,
9
+ data2: phase0.AttestationDataBigint
10
+ ): boolean {
11
+ return (
12
+ // Double vote
13
+ (!ssz.phase0.AttestationDataBigint.equals(data1, data2) && data1.target.epoch === data2.target.epoch) ||
14
+ // Surround vote
15
+ (data1.source.epoch < data2.source.epoch && data2.target.epoch < data1.target.epoch)
16
+ );
17
+ }
18
+
19
+ export function isValidAttestationSlot(attestationSlot: Slot, currentSlot: Slot): boolean {
20
+ return (
21
+ attestationSlot + MIN_ATTESTATION_INCLUSION_DELAY <= currentSlot && currentSlot <= attestationSlot + SLOTS_PER_EPOCH
22
+ );
23
+ }
24
+
25
+ export function getAttesterSlashableIndices(attesterSlashing: AttesterSlashing): ValidatorIndex[] {
26
+ const indices: ValidatorIndex[] = [];
27
+ const attSet1 = new Set(attesterSlashing.attestation1.attestingIndices);
28
+ const attArr2 = attesterSlashing.attestation2.attestingIndices;
29
+ for (let i = 0, len = attArr2.length; i < len; i++) {
30
+ const index = attArr2[i];
31
+ if (attSet1.has(index)) {
32
+ indices.push(index);
33
+ }
34
+ }
35
+ return indices;
36
+ }
@@ -0,0 +1,83 @@
1
+ import {TIMELY_HEAD_FLAG_INDEX, TIMELY_SOURCE_FLAG_INDEX, TIMELY_TARGET_FLAG_INDEX} from "@lodestar/params";
2
+
3
+ // We pack both previous and current epoch attester flags
4
+ // as well as slashed and eligibility flags into a single number
5
+ // to save space in our epoch transition cache.
6
+ // Note: the order of the flags is important for efficiently translating
7
+ // from the BeaconState flags to our flags.
8
+ // [prevSource, prevTarget, prevHead, currSource, currTarget, currHead, unslashed, eligible]
9
+ export const FLAG_PREV_SOURCE_ATTESTER = 1 << TIMELY_SOURCE_FLAG_INDEX;
10
+ export const FLAG_PREV_TARGET_ATTESTER = 1 << TIMELY_TARGET_FLAG_INDEX;
11
+ export const FLAG_PREV_HEAD_ATTESTER = 1 << TIMELY_HEAD_FLAG_INDEX;
12
+
13
+ export const FLAG_CURR_SOURCE_ATTESTER = 1 << (3 + TIMELY_SOURCE_FLAG_INDEX);
14
+ export const FLAG_CURR_TARGET_ATTESTER = 1 << (3 + TIMELY_TARGET_FLAG_INDEX);
15
+ export const FLAG_CURR_HEAD_ATTESTER = 1 << (3 + TIMELY_HEAD_FLAG_INDEX);
16
+
17
+ export const FLAG_UNSLASHED = 1 << 6;
18
+ export const FLAG_ELIGIBLE_ATTESTER = 1 << 7;
19
+
20
+ // Precompute OR flags used in epoch processing
21
+ export const FLAG_PREV_SOURCE_ATTESTER_UNSLASHED = FLAG_PREV_SOURCE_ATTESTER | FLAG_UNSLASHED;
22
+ export const FLAG_PREV_TARGET_ATTESTER_UNSLASHED = FLAG_PREV_TARGET_ATTESTER | FLAG_UNSLASHED;
23
+ export const FLAG_PREV_HEAD_ATTESTER_UNSLASHED = FLAG_PREV_HEAD_ATTESTER | FLAG_UNSLASHED;
24
+
25
+ export function hasMarkers(flags: number, markers: number): boolean {
26
+ return (flags & markers) === markers;
27
+ }
28
+
29
+ export type AttesterFlags = {
30
+ prevSourceAttester: boolean;
31
+ prevTargetAttester: boolean;
32
+ prevHeadAttester: boolean;
33
+ currSourceAttester: boolean;
34
+ currTargetAttester: boolean;
35
+ currHeadAttester: boolean;
36
+ unslashed: boolean;
37
+ eligibleAttester: boolean;
38
+ };
39
+
40
+ export function parseAttesterFlags(flags: number): AttesterFlags {
41
+ return {
42
+ prevSourceAttester: hasMarkers(flags, FLAG_PREV_SOURCE_ATTESTER),
43
+ prevTargetAttester: hasMarkers(flags, FLAG_PREV_TARGET_ATTESTER),
44
+ prevHeadAttester: hasMarkers(flags, FLAG_PREV_HEAD_ATTESTER),
45
+ currSourceAttester: hasMarkers(flags, FLAG_CURR_SOURCE_ATTESTER),
46
+ currTargetAttester: hasMarkers(flags, FLAG_CURR_TARGET_ATTESTER),
47
+ currHeadAttester: hasMarkers(flags, FLAG_CURR_HEAD_ATTESTER),
48
+ unslashed: hasMarkers(flags, FLAG_UNSLASHED),
49
+ eligibleAttester: hasMarkers(flags, FLAG_ELIGIBLE_ATTESTER),
50
+ };
51
+ }
52
+
53
+ export function toAttesterFlags(flagsObj: AttesterFlags): number {
54
+ let flag = 0;
55
+ if (flagsObj.prevSourceAttester) flag |= FLAG_PREV_SOURCE_ATTESTER;
56
+ if (flagsObj.prevTargetAttester) flag |= FLAG_PREV_TARGET_ATTESTER;
57
+ if (flagsObj.prevHeadAttester) flag |= FLAG_PREV_HEAD_ATTESTER;
58
+ if (flagsObj.currSourceAttester) flag |= FLAG_CURR_SOURCE_ATTESTER;
59
+ if (flagsObj.currTargetAttester) flag |= FLAG_CURR_TARGET_ATTESTER;
60
+ if (flagsObj.currHeadAttester) flag |= FLAG_CURR_HEAD_ATTESTER;
61
+ if (flagsObj.unslashed) flag |= FLAG_UNSLASHED;
62
+ if (flagsObj.eligibleAttester) flag |= FLAG_ELIGIBLE_ATTESTER;
63
+ return flag;
64
+ }
65
+
66
+ /** Same to https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.5/specs/altair/beacon-chain.md#has_flag */
67
+ const TIMELY_SOURCE = 1 << TIMELY_SOURCE_FLAG_INDEX;
68
+ const TIMELY_TARGET = 1 << TIMELY_TARGET_FLAG_INDEX;
69
+ const TIMELY_HEAD = 1 << TIMELY_HEAD_FLAG_INDEX;
70
+
71
+ export type ParticipationFlags = {
72
+ timelySource: boolean;
73
+ timelyTarget: boolean;
74
+ timelyHead: boolean;
75
+ };
76
+
77
+ export function parseParticipationFlags(flags: number): ParticipationFlags {
78
+ return {
79
+ timelySource: hasMarkers(flags, TIMELY_SOURCE),
80
+ timelyTarget: hasMarkers(flags, TIMELY_TARGET),
81
+ timelyHead: hasMarkers(flags, TIMELY_HEAD),
82
+ };
83
+ }
@@ -0,0 +1,83 @@
1
+ import {EFFECTIVE_BALANCE_INCREMENT} from "@lodestar/params";
2
+ import {Gwei, ValidatorIndex} from "@lodestar/types";
3
+ import {bigIntMax} from "@lodestar/utils";
4
+ import {EffectiveBalanceIncrements} from "../cache/effectiveBalanceIncrements.js";
5
+ import {BeaconStateAllForks} from "../index.js";
6
+ import {CachedBeaconStateAllForks} from "../types.js";
7
+
8
+ /**
9
+ * Return the combined effective balance of the [[indices]].
10
+ * `EFFECTIVE_BALANCE_INCREMENT` Gwei minimum to avoid divisions by zero.
11
+ *
12
+ * SLOW CODE - 🐢
13
+ */
14
+ export function getTotalBalance(state: BeaconStateAllForks, indices: ValidatorIndex[]): Gwei {
15
+ let total = BigInt(0);
16
+
17
+ // TODO: Use a fast cache to get the effective balance 🐢
18
+ const validatorsArr = state.validators.getAllReadonlyValues();
19
+ for (let i = 0; i < indices.length; i++) {
20
+ total += BigInt(validatorsArr[indices[i]].effectiveBalance);
21
+ }
22
+
23
+ return bigIntMax(BigInt(EFFECTIVE_BALANCE_INCREMENT), total);
24
+ }
25
+
26
+ /**
27
+ * Increase the balance for a validator with the given ``index`` by ``delta``.
28
+ */
29
+ export function increaseBalance(state: BeaconStateAllForks, index: ValidatorIndex, delta: number): void {
30
+ // TODO: Inline this
31
+ state.balances.set(index, state.balances.get(index) + delta);
32
+ }
33
+
34
+ /**
35
+ * Decrease the balance for a validator with the given ``index`` by ``delta``.
36
+ *
37
+ * Set to ``0`` when underflow.
38
+ */
39
+ export function decreaseBalance(state: BeaconStateAllForks, index: ValidatorIndex, delta: number): void {
40
+ const currentBalance = state.balances.get(index);
41
+ const newBalance = currentBalance > delta ? state.balances.get(index) - delta : 0;
42
+ // TODO: Is it necessary to protect against underflow here? Add unit test
43
+ state.balances.set(index, Math.max(0, newBalance));
44
+ }
45
+
46
+ /**
47
+ * This method is used to get justified balances from a justified state.
48
+ * This is consumed by forkchoice which based on delta so we return "by increment" (in ether) value,
49
+ * ie [30, 31, 32] instead of [30e9, 31e9, 32e9]
50
+ */
51
+ export function getEffectiveBalanceIncrementsZeroInactive(
52
+ justifiedState: CachedBeaconStateAllForks
53
+ ): EffectiveBalanceIncrements {
54
+ const {activeIndices} = justifiedState.epochCtx.currentShuffling;
55
+ // 5x faster than reading from state.validators, with validator Nodes as values
56
+ const validatorCount = justifiedState.validators.length;
57
+ const {effectiveBalanceIncrements} = justifiedState.epochCtx;
58
+ // Slice up to `validatorCount` since it won't be mutated, nor accessed beyond `validatorCount`
59
+ // NOTE: Force to use Uint16Array.slice (copy) instead of Buffer.call (not copy)
60
+ const effectiveBalanceIncrementsZeroInactive = Uint16Array.prototype.slice.call(
61
+ effectiveBalanceIncrements,
62
+ 0,
63
+ validatorCount
64
+ );
65
+
66
+ let j = 0;
67
+ justifiedState.validators.forEachValue((validator, i) => {
68
+ const {slashed} = validator;
69
+ if (i === activeIndices[j]) {
70
+ // active validator
71
+ j++;
72
+ if (slashed) {
73
+ // slashed validator
74
+ effectiveBalanceIncrementsZeroInactive[i] = 0;
75
+ }
76
+ } else {
77
+ // inactive validator
78
+ effectiveBalanceIncrementsZeroInactive[i] = 0;
79
+ }
80
+ });
81
+
82
+ return effectiveBalanceIncrementsZeroInactive;
83
+ }