@lodestar/state-transition 1.35.0-dev.e18102ed8c → 1.35.0-dev.f45a2be721

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 (243) hide show
  1. package/lib/block/externalData.d.ts.map +1 -0
  2. package/lib/block/index.d.ts.map +1 -0
  3. package/lib/block/initiateValidatorExit.d.ts.map +1 -0
  4. package/lib/block/isValidIndexedAttestation.d.ts.map +1 -0
  5. package/lib/block/processAttestationPhase0.d.ts.map +1 -0
  6. package/lib/block/processAttestations.d.ts.map +1 -0
  7. package/lib/block/processAttestationsAltair.d.ts.map +1 -0
  8. package/lib/block/processAttesterSlashing.d.ts.map +1 -0
  9. package/lib/block/processBlobKzgCommitments.d.ts.map +1 -0
  10. package/lib/block/processBlockHeader.d.ts.map +1 -0
  11. package/lib/block/processBlsToExecutionChange.d.ts.map +1 -0
  12. package/lib/block/processConsolidationRequest.d.ts.map +1 -0
  13. package/lib/block/processDeposit.d.ts.map +1 -0
  14. package/lib/block/processDepositRequest.d.ts.map +1 -0
  15. package/lib/block/processEth1Data.d.ts.map +1 -0
  16. package/lib/block/processExecutionPayload.d.ts.map +1 -0
  17. package/lib/block/processExecutionPayload.js +3 -3
  18. package/lib/block/processExecutionPayload.js.map +1 -1
  19. package/lib/block/processOperations.d.ts.map +1 -0
  20. package/lib/block/processProposerSlashing.d.ts.map +1 -0
  21. package/lib/block/processRandao.d.ts.map +1 -0
  22. package/lib/block/processSyncCommittee.d.ts.map +1 -0
  23. package/lib/block/processVoluntaryExit.d.ts.map +1 -0
  24. package/lib/block/processWithdrawalRequest.d.ts.map +1 -0
  25. package/lib/block/processWithdrawals.d.ts.map +1 -0
  26. package/lib/block/slashValidator.d.ts.map +1 -0
  27. package/lib/block/types.d.ts.map +1 -0
  28. package/lib/cache/effectiveBalanceIncrements.d.ts.map +1 -0
  29. package/lib/cache/epochCache.d.ts.map +1 -0
  30. package/lib/cache/epochTransitionCache.d.ts.map +1 -0
  31. package/lib/cache/pubkeyCache.d.ts.map +1 -0
  32. package/lib/cache/rewardCache.d.ts.map +1 -0
  33. package/lib/cache/stateCache.d.ts.map +1 -0
  34. package/lib/cache/syncCommitteeCache.d.ts.map +1 -0
  35. package/lib/cache/types.d.ts +2 -2
  36. package/lib/cache/types.d.ts.map +1 -0
  37. package/lib/constants/constants.d.ts.map +1 -0
  38. package/lib/constants/index.d.ts.map +1 -0
  39. package/lib/epoch/computeUnrealizedCheckpoints.d.ts.map +1 -0
  40. package/lib/epoch/getAttestationDeltas.d.ts.map +1 -0
  41. package/lib/epoch/getRewardsAndPenalties.d.ts.map +1 -0
  42. package/lib/epoch/index.d.ts.map +1 -0
  43. package/lib/epoch/processEffectiveBalanceUpdates.d.ts.map +1 -0
  44. package/lib/epoch/processEth1DataReset.d.ts.map +1 -0
  45. package/lib/epoch/processHistoricalRootsUpdate.d.ts.map +1 -0
  46. package/lib/epoch/processHistoricalSummariesUpdate.d.ts.map +1 -0
  47. package/lib/epoch/processInactivityUpdates.d.ts.map +1 -0
  48. package/lib/epoch/processJustificationAndFinalization.d.ts.map +1 -0
  49. package/lib/epoch/processParticipationFlagUpdates.d.ts.map +1 -0
  50. package/lib/epoch/processParticipationRecordUpdates.d.ts.map +1 -0
  51. package/lib/epoch/processPendingAttestations.d.ts.map +1 -0
  52. package/lib/epoch/processPendingConsolidations.d.ts.map +1 -0
  53. package/lib/epoch/processPendingDeposits.d.ts.map +1 -0
  54. package/lib/epoch/processProposerLookahead.d.ts.map +1 -0
  55. package/lib/epoch/processRandaoMixesReset.d.ts.map +1 -0
  56. package/lib/epoch/processRegistryUpdates.d.ts.map +1 -0
  57. package/lib/epoch/processRewardsAndPenalties.d.ts.map +1 -0
  58. package/lib/epoch/processSlashings.d.ts.map +1 -0
  59. package/lib/epoch/processSlashingsReset.d.ts.map +1 -0
  60. package/lib/epoch/processSyncCommitteeUpdates.d.ts.map +1 -0
  61. package/lib/index.d.ts.map +1 -0
  62. package/lib/metrics.d.ts.map +1 -0
  63. package/lib/signatureSets/attesterSlashings.d.ts.map +1 -0
  64. package/lib/signatureSets/blsToExecutionChange.d.ts.map +1 -0
  65. package/lib/signatureSets/index.d.ts.map +1 -0
  66. package/lib/signatureSets/indexedAttestation.d.ts.map +1 -0
  67. package/lib/signatureSets/proposer.d.ts.map +1 -0
  68. package/lib/signatureSets/proposerSlashings.d.ts.map +1 -0
  69. package/lib/signatureSets/randao.d.ts.map +1 -0
  70. package/lib/signatureSets/voluntaryExits.d.ts.map +1 -0
  71. package/lib/slot/index.d.ts.map +1 -0
  72. package/lib/slot/upgradeStateToAltair.d.ts.map +1 -0
  73. package/lib/slot/upgradeStateToBellatrix.d.ts.map +1 -0
  74. package/lib/slot/upgradeStateToCapella.d.ts.map +1 -0
  75. package/lib/slot/upgradeStateToDeneb.d.ts.map +1 -0
  76. package/lib/slot/upgradeStateToElectra.d.ts.map +1 -0
  77. package/lib/slot/upgradeStateToFulu.d.ts.map +1 -0
  78. package/lib/slot/upgradeStateToGloas.d.ts.map +1 -0
  79. package/lib/stateTransition.d.ts.map +1 -0
  80. package/lib/types.d.ts.map +1 -0
  81. package/lib/util/aggregator.d.ts.map +1 -0
  82. package/lib/util/altair.d.ts.map +1 -0
  83. package/lib/util/array.d.ts.map +1 -0
  84. package/lib/util/attestation.d.ts.map +1 -0
  85. package/lib/util/attesterStatus.d.ts.map +1 -0
  86. package/lib/util/balance.d.ts.map +1 -0
  87. package/lib/util/blindedBlock.d.ts +3 -3
  88. package/lib/util/blindedBlock.d.ts.map +1 -0
  89. package/lib/util/blindedBlock.js.map +1 -1
  90. package/lib/util/blockRoot.d.ts.map +1 -0
  91. package/lib/util/calculateCommitteeAssignments.d.ts.map +1 -0
  92. package/lib/util/capella.d.ts.map +1 -0
  93. package/lib/util/computeAnchorCheckpoint.d.ts.map +1 -0
  94. package/lib/util/deposit.d.ts.map +1 -0
  95. package/lib/util/domain.d.ts.map +1 -0
  96. package/lib/util/electra.d.ts.map +1 -0
  97. package/lib/util/epoch.d.ts.map +1 -0
  98. package/lib/util/epochShuffling.d.ts.map +1 -0
  99. package/lib/util/execution.d.ts +2 -2
  100. package/lib/util/execution.d.ts.map +1 -0
  101. package/lib/util/execution.js.map +1 -1
  102. package/lib/util/finality.d.ts.map +1 -0
  103. package/lib/util/fulu.d.ts.map +1 -0
  104. package/lib/util/genesis.d.ts.map +1 -0
  105. package/lib/util/genesis.js +0 -3
  106. package/lib/util/genesis.js.map +1 -1
  107. package/lib/util/index.d.ts.map +1 -0
  108. package/lib/util/interop.d.ts.map +1 -0
  109. package/lib/util/loadState/findModifiedInactivityScores.d.ts.map +1 -0
  110. package/lib/util/loadState/findModifiedValidators.d.ts.map +1 -0
  111. package/lib/util/loadState/index.d.ts.map +1 -0
  112. package/lib/util/loadState/loadState.d.ts.map +1 -0
  113. package/lib/util/loadState/loadValidator.d.ts.map +1 -0
  114. package/lib/util/rootCache.d.ts.map +1 -0
  115. package/lib/util/seed.d.ts.map +1 -0
  116. package/lib/util/shufflingDecisionRoot.d.ts.map +1 -0
  117. package/lib/util/signatureSets.d.ts.map +1 -0
  118. package/lib/util/signingRoot.d.ts.map +1 -0
  119. package/lib/util/slot.d.ts +0 -1
  120. package/lib/util/slot.d.ts.map +1 -0
  121. package/lib/util/slot.js +3 -7
  122. package/lib/util/slot.js.map +1 -1
  123. package/lib/util/sszBytes.d.ts.map +1 -0
  124. package/lib/util/syncCommittee.d.ts.map +1 -0
  125. package/lib/util/targetUnslashedBalance.d.ts.map +1 -0
  126. package/lib/util/validator.d.ts.map +1 -0
  127. package/lib/util/weakSubjectivity.d.ts.map +1 -0
  128. package/package.json +13 -11
  129. package/src/block/externalData.ts +26 -0
  130. package/src/block/index.ts +81 -0
  131. package/src/block/initiateValidatorExit.ts +62 -0
  132. package/src/block/isValidIndexedAttestation.ts +70 -0
  133. package/src/block/processAttestationPhase0.ts +158 -0
  134. package/src/block/processAttestations.ts +25 -0
  135. package/src/block/processAttestationsAltair.ts +184 -0
  136. package/src/block/processAttesterSlashing.ts +59 -0
  137. package/src/block/processBlobKzgCommitments.ts +21 -0
  138. package/src/block/processBlockHeader.ts +54 -0
  139. package/src/block/processBlsToExecutionChange.ts +78 -0
  140. package/src/block/processConsolidationRequest.ts +147 -0
  141. package/src/block/processDeposit.ts +166 -0
  142. package/src/block/processDepositRequest.ts +19 -0
  143. package/src/block/processEth1Data.ts +86 -0
  144. package/src/block/processExecutionPayload.ts +84 -0
  145. package/src/block/processOperations.ts +83 -0
  146. package/src/block/processProposerSlashing.ts +66 -0
  147. package/src/block/processRandao.ts +27 -0
  148. package/src/block/processSyncCommittee.ts +117 -0
  149. package/src/block/processVoluntaryExit.ts +55 -0
  150. package/src/block/processWithdrawalRequest.ts +98 -0
  151. package/src/block/processWithdrawals.ts +207 -0
  152. package/src/block/slashValidator.ts +98 -0
  153. package/src/block/types.ts +9 -0
  154. package/src/cache/effectiveBalanceIncrements.ts +39 -0
  155. package/src/cache/epochCache.ts +1213 -0
  156. package/src/cache/epochTransitionCache.ts +542 -0
  157. package/src/cache/pubkeyCache.ts +33 -0
  158. package/src/cache/rewardCache.ts +19 -0
  159. package/src/cache/stateCache.ts +268 -0
  160. package/src/cache/syncCommitteeCache.ts +96 -0
  161. package/src/cache/types.ts +18 -0
  162. package/src/constants/constants.ts +12 -0
  163. package/src/constants/index.ts +1 -0
  164. package/src/epoch/computeUnrealizedCheckpoints.ts +55 -0
  165. package/src/epoch/getAttestationDeltas.ts +169 -0
  166. package/src/epoch/getRewardsAndPenalties.ts +137 -0
  167. package/src/epoch/index.ts +202 -0
  168. package/src/epoch/processEffectiveBalanceUpdates.ts +111 -0
  169. package/src/epoch/processEth1DataReset.ts +17 -0
  170. package/src/epoch/processHistoricalRootsUpdate.ts +25 -0
  171. package/src/epoch/processHistoricalSummariesUpdate.ts +23 -0
  172. package/src/epoch/processInactivityUpdates.ts +60 -0
  173. package/src/epoch/processJustificationAndFinalization.ts +90 -0
  174. package/src/epoch/processParticipationFlagUpdates.ts +27 -0
  175. package/src/epoch/processParticipationRecordUpdates.ts +14 -0
  176. package/src/epoch/processPendingAttestations.ts +75 -0
  177. package/src/epoch/processPendingConsolidations.ts +59 -0
  178. package/src/epoch/processPendingDeposits.ts +136 -0
  179. package/src/epoch/processProposerLookahead.ts +39 -0
  180. package/src/epoch/processRandaoMixesReset.ts +18 -0
  181. package/src/epoch/processRegistryUpdates.ts +65 -0
  182. package/src/epoch/processRewardsAndPenalties.ts +58 -0
  183. package/src/epoch/processSlashings.ts +97 -0
  184. package/src/epoch/processSlashingsReset.ts +20 -0
  185. package/src/epoch/processSyncCommitteeUpdates.ts +44 -0
  186. package/src/index.ts +67 -0
  187. package/src/metrics.ts +169 -0
  188. package/src/signatureSets/attesterSlashings.ts +39 -0
  189. package/src/signatureSets/blsToExecutionChange.ts +43 -0
  190. package/src/signatureSets/index.ts +73 -0
  191. package/src/signatureSets/indexedAttestation.ts +51 -0
  192. package/src/signatureSets/proposer.ts +47 -0
  193. package/src/signatureSets/proposerSlashings.ts +41 -0
  194. package/src/signatureSets/randao.ts +31 -0
  195. package/src/signatureSets/voluntaryExits.ts +44 -0
  196. package/src/slot/index.ts +32 -0
  197. package/src/slot/upgradeStateToAltair.ts +149 -0
  198. package/src/slot/upgradeStateToBellatrix.ts +63 -0
  199. package/src/slot/upgradeStateToCapella.ts +71 -0
  200. package/src/slot/upgradeStateToDeneb.ts +40 -0
  201. package/src/slot/upgradeStateToElectra.ts +126 -0
  202. package/src/slot/upgradeStateToFulu.ts +31 -0
  203. package/src/slot/upgradeStateToGloas.ts +29 -0
  204. package/src/stateTransition.ts +305 -0
  205. package/src/types.ts +26 -0
  206. package/src/util/aggregator.ts +33 -0
  207. package/src/util/altair.ts +13 -0
  208. package/src/util/array.ts +53 -0
  209. package/src/util/attestation.ts +36 -0
  210. package/src/util/attesterStatus.ts +83 -0
  211. package/src/util/balance.ts +83 -0
  212. package/src/util/blindedBlock.ts +145 -0
  213. package/src/util/blockRoot.ts +72 -0
  214. package/src/util/calculateCommitteeAssignments.ts +43 -0
  215. package/src/util/capella.ts +8 -0
  216. package/src/util/computeAnchorCheckpoint.ts +38 -0
  217. package/src/util/deposit.ts +22 -0
  218. package/src/util/domain.ts +31 -0
  219. package/src/util/electra.ts +68 -0
  220. package/src/util/epoch.ts +135 -0
  221. package/src/util/epochShuffling.ts +185 -0
  222. package/src/util/execution.ts +179 -0
  223. package/src/util/finality.ts +17 -0
  224. package/src/util/fulu.ts +43 -0
  225. package/src/util/genesis.ts +340 -0
  226. package/src/util/index.ts +29 -0
  227. package/src/util/interop.ts +22 -0
  228. package/src/util/loadState/findModifiedInactivityScores.ts +47 -0
  229. package/src/util/loadState/findModifiedValidators.ts +46 -0
  230. package/src/util/loadState/index.ts +2 -0
  231. package/src/util/loadState/loadState.ts +225 -0
  232. package/src/util/loadState/loadValidator.ts +77 -0
  233. package/src/util/rootCache.ts +37 -0
  234. package/src/util/seed.ts +381 -0
  235. package/src/util/shufflingDecisionRoot.ts +78 -0
  236. package/src/util/signatureSets.ts +65 -0
  237. package/src/util/signingRoot.ts +13 -0
  238. package/src/util/slot.ts +22 -0
  239. package/src/util/sszBytes.ts +52 -0
  240. package/src/util/syncCommittee.ts +69 -0
  241. package/src/util/targetUnslashedBalance.ts +30 -0
  242. package/src/util/validator.ts +105 -0
  243. package/src/util/weakSubjectivity.ts +186 -0
@@ -0,0 +1,145 @@
1
+ import {ChainForkConfig} from "@lodestar/config";
2
+ import {
3
+ ForkName,
4
+ ForkPostBellatrix,
5
+ ForkPostDeneb,
6
+ ForkPreGloas,
7
+ ForkSeq,
8
+ isForkPostBellatrix,
9
+ isForkPostDeneb,
10
+ } from "@lodestar/params";
11
+ import {
12
+ BeaconBlock,
13
+ BeaconBlockHeader,
14
+ BlindedBeaconBlock,
15
+ BlobsBundle,
16
+ ExecutionPayload,
17
+ ExecutionPayloadAndBlobsBundle,
18
+ ExecutionPayloadHeader,
19
+ Root,
20
+ SignedBeaconBlock,
21
+ SignedBlindedBeaconBlock,
22
+ SignedBlockContents,
23
+ isBlindedBeaconBlock,
24
+ isExecutionPayloadAndBlobsBundle,
25
+ } from "@lodestar/types";
26
+ import {executionPayloadToPayloadHeader} from "./execution.js";
27
+
28
+ export function blindedOrFullBlockHashTreeRoot(
29
+ config: ChainForkConfig,
30
+ blindedOrFull: BeaconBlock | BlindedBeaconBlock
31
+ ): Root {
32
+ return isBlindedBeaconBlock(blindedOrFull)
33
+ ? // Blinded
34
+ config
35
+ .getPostBellatrixForkTypes(blindedOrFull.slot)
36
+ .BlindedBeaconBlock.hashTreeRoot(blindedOrFull)
37
+ : // Full
38
+ config
39
+ .getForkTypes(blindedOrFull.slot)
40
+ .BeaconBlock.hashTreeRoot(blindedOrFull);
41
+ }
42
+
43
+ export function blindedOrFullBlockToHeader(
44
+ config: ChainForkConfig,
45
+ blindedOrFull: BeaconBlock | BlindedBeaconBlock
46
+ ): BeaconBlockHeader {
47
+ const bodyRoot = isBlindedBeaconBlock(blindedOrFull)
48
+ ? // Blinded
49
+ config
50
+ .getPostBellatrixForkTypes(blindedOrFull.slot)
51
+ .BlindedBeaconBlockBody.hashTreeRoot(blindedOrFull.body)
52
+ : // Full
53
+ config
54
+ .getForkTypes(blindedOrFull.slot)
55
+ .BeaconBlockBody.hashTreeRoot(blindedOrFull.body);
56
+
57
+ return {
58
+ slot: blindedOrFull.slot,
59
+ proposerIndex: blindedOrFull.proposerIndex,
60
+ parentRoot: blindedOrFull.parentRoot,
61
+ stateRoot: blindedOrFull.stateRoot,
62
+ bodyRoot,
63
+ };
64
+ }
65
+
66
+ export function beaconBlockToBlinded(
67
+ config: ChainForkConfig,
68
+ block: BeaconBlock<ForkPostBellatrix & ForkPreGloas>
69
+ ): BlindedBeaconBlock {
70
+ const fork = config.getForkName(block.slot);
71
+ const executionPayloadHeader = executionPayloadToPayloadHeader(ForkSeq[fork], block.body.executionPayload);
72
+ const blindedBlock: BlindedBeaconBlock = {...block, body: {...block.body, executionPayloadHeader}};
73
+ return blindedBlock;
74
+ }
75
+
76
+ export function signedBeaconBlockToBlinded(
77
+ config: ChainForkConfig,
78
+ signedBlock: SignedBeaconBlock<ForkPostBellatrix & ForkPreGloas>
79
+ ): SignedBlindedBeaconBlock {
80
+ return {
81
+ message: beaconBlockToBlinded(config, signedBlock.message),
82
+ signature: signedBlock.signature,
83
+ };
84
+ }
85
+
86
+ export function signedBlindedBlockToFull(
87
+ fork: ForkName,
88
+ signedBlindedBlock: SignedBlindedBeaconBlock,
89
+ executionPayload: ExecutionPayload | null
90
+ ): SignedBeaconBlock {
91
+ if (isForkPostBellatrix(fork) && executionPayload === null) {
92
+ throw Error("Missing executionPayload to reconstruct post-bellatrix full block");
93
+ }
94
+
95
+ const signedBlock = {
96
+ ...signedBlindedBlock,
97
+ message: {
98
+ ...signedBlindedBlock.message,
99
+ body: {
100
+ ...signedBlindedBlock.message.body,
101
+ // state transition doesn't handle null value for executionPayload in pre-bellatrix blocks
102
+ executionPayload: executionPayload ?? undefined,
103
+ },
104
+ },
105
+ } as SignedBeaconBlock;
106
+
107
+ // state transition can't seem to handle executionPayloadHeader presense in merge block
108
+ // so just delete the extra field we don't require
109
+ delete (signedBlock.message.body as {executionPayloadHeader?: ExecutionPayloadHeader}).executionPayloadHeader;
110
+ return signedBlock;
111
+ }
112
+
113
+ export function parseExecutionPayloadAndBlobsBundle(data: ExecutionPayload | ExecutionPayloadAndBlobsBundle): {
114
+ executionPayload: ExecutionPayload;
115
+ blobsBundle: BlobsBundle | null;
116
+ } {
117
+ if (isExecutionPayloadAndBlobsBundle(data)) {
118
+ return data;
119
+ }
120
+ return {
121
+ executionPayload: data,
122
+ blobsBundle: null,
123
+ };
124
+ }
125
+
126
+ export function reconstructSignedBlockContents(
127
+ fork: ForkName,
128
+ signedBlindedBlock: SignedBlindedBeaconBlock,
129
+ executionPayload: ExecutionPayload | null,
130
+ blobsBundle: BlobsBundle | null
131
+ ): SignedBlockContents {
132
+ const signedBlock = signedBlindedBlockToFull(fork, signedBlindedBlock, executionPayload);
133
+
134
+ if (isForkPostDeneb(fork)) {
135
+ if (blobsBundle === null) {
136
+ throw Error("Missing blobs bundle to reconstruct post-deneb block contents");
137
+ }
138
+ return {
139
+ signedBlock: signedBlock as SignedBeaconBlock<ForkPostDeneb>,
140
+ kzgProofs: blobsBundle.proofs,
141
+ blobs: blobsBundle.blobs,
142
+ };
143
+ }
144
+ return {signedBlock};
145
+ }
@@ -0,0 +1,72 @@
1
+ import {ChainForkConfig} from "@lodestar/config";
2
+ import {SLOTS_PER_HISTORICAL_ROOT} from "@lodestar/params";
3
+ import {
4
+ BeaconBlock,
5
+ BeaconBlockHeader,
6
+ Epoch,
7
+ Root,
8
+ SignedBeaconBlock,
9
+ SignedBeaconBlockHeader,
10
+ Slot,
11
+ } from "@lodestar/types";
12
+ import {ZERO_HASH} from "../constants/index.js";
13
+ import {BeaconStateAllForks} from "../types.js";
14
+ import {computeStartSlotAtEpoch} from "./epoch.js";
15
+
16
+ /**
17
+ * Return the block root at a recent [[slot]].
18
+ */
19
+ export function getBlockRootAtSlot(state: BeaconStateAllForks, slot: Slot): Root {
20
+ if (slot >= state.slot) {
21
+ throw Error(`Can only get block root in the past currentSlot=${state.slot} slot=${slot}`);
22
+ }
23
+ if (slot < state.slot - SLOTS_PER_HISTORICAL_ROOT) {
24
+ throw Error(`Cannot get block root more than ${SLOTS_PER_HISTORICAL_ROOT} in the past`);
25
+ }
26
+ return state.blockRoots.get(slot % SLOTS_PER_HISTORICAL_ROOT);
27
+ }
28
+
29
+ /**
30
+ * Return the block root at the start of a recent [[epoch]].
31
+ */
32
+ export function getBlockRoot(state: BeaconStateAllForks, epoch: Epoch): Root {
33
+ return getBlockRootAtSlot(state, computeStartSlotAtEpoch(epoch));
34
+ }
35
+ /**
36
+ * Return the block header corresponding to a block with ``state_root`` set to ``ZERO_HASH``.
37
+ */
38
+ export function getTemporaryBlockHeader(config: ChainForkConfig, block: BeaconBlock): BeaconBlockHeader {
39
+ return {
40
+ slot: block.slot,
41
+ proposerIndex: block.proposerIndex,
42
+ parentRoot: block.parentRoot,
43
+ // `state_root` is zeroed and overwritten in the next `process_slot` call
44
+ stateRoot: ZERO_HASH,
45
+ bodyRoot: config.getForkTypes(block.slot).BeaconBlockBody.hashTreeRoot(block.body),
46
+ };
47
+ }
48
+
49
+ /**
50
+ * Receives a BeaconBlock, and produces the corresponding BeaconBlockHeader.
51
+ */
52
+ export function blockToHeader(config: ChainForkConfig, block: BeaconBlock): BeaconBlockHeader {
53
+ return {
54
+ stateRoot: block.stateRoot,
55
+ proposerIndex: block.proposerIndex,
56
+ slot: block.slot,
57
+ parentRoot: block.parentRoot,
58
+ bodyRoot: config.getForkTypes(block.slot).BeaconBlockBody.hashTreeRoot(block.body),
59
+ };
60
+ }
61
+
62
+ export function signedBlockToSignedHeader(
63
+ config: ChainForkConfig,
64
+ signedBlock: SignedBeaconBlock
65
+ ): SignedBeaconBlockHeader {
66
+ const message = blockToHeader(config, signedBlock.message);
67
+ const signature = signedBlock.signature;
68
+ return {
69
+ message,
70
+ signature,
71
+ };
72
+ }
@@ -0,0 +1,43 @@
1
+ import {SLOTS_PER_EPOCH} from "@lodestar/params";
2
+ import {CommitteeIndex, Slot, ValidatorIndex} from "@lodestar/types";
3
+ import {EpochShuffling} from "./epochShuffling.js";
4
+
5
+ // Copied from lodestar-api package to avoid depending on the package
6
+ export interface AttesterDuty {
7
+ validatorIndex: ValidatorIndex;
8
+ committeeIndex: CommitteeIndex;
9
+ committeeLength: number;
10
+ committeesAtSlot: number;
11
+ validatorCommitteeIndex: number;
12
+ slot: Slot;
13
+ }
14
+
15
+ export function calculateCommitteeAssignments(
16
+ epochShuffling: EpochShuffling,
17
+ requestedValidatorIndices: ValidatorIndex[]
18
+ ): Map<ValidatorIndex, AttesterDuty> {
19
+ const requestedValidatorIndicesSet = new Set(requestedValidatorIndices);
20
+ const duties = new Map<ValidatorIndex, AttesterDuty>();
21
+
22
+ const epochCommittees = epochShuffling.committees;
23
+ for (let epochSlot = 0; epochSlot < SLOTS_PER_EPOCH; epochSlot++) {
24
+ const slotCommittees = epochCommittees[epochSlot];
25
+ for (let i = 0, committeesAtSlot = slotCommittees.length; i < committeesAtSlot; i++) {
26
+ for (let j = 0, committeeLength = slotCommittees[i].length; j < committeeLength; j++) {
27
+ const validatorIndex = slotCommittees[i][j];
28
+ if (requestedValidatorIndicesSet.has(validatorIndex)) {
29
+ duties.set(validatorIndex, {
30
+ validatorIndex,
31
+ committeeLength,
32
+ committeesAtSlot,
33
+ validatorCommitteeIndex: j,
34
+ committeeIndex: i,
35
+ slot: epochShuffling.epoch * SLOTS_PER_EPOCH + epochSlot,
36
+ });
37
+ }
38
+ }
39
+ }
40
+ }
41
+
42
+ return duties;
43
+ }
@@ -0,0 +1,8 @@
1
+ import {ETH1_ADDRESS_WITHDRAWAL_PREFIX} from "@lodestar/params";
2
+
3
+ /**
4
+ * https://github.com/ethereum/consensus-specs/blob/3d235740e5f1e641d3b160c8688f26e7dc5a1894/specs/capella/beacon-chain.md#has_eth1_withdrawal_credential
5
+ */
6
+ export function hasEth1WithdrawalCredential(withdrawalCredentials: Uint8Array): boolean {
7
+ return withdrawalCredentials[0] === ETH1_ADDRESS_WITHDRAWAL_PREFIX;
8
+ }
@@ -0,0 +1,38 @@
1
+ import {ChainForkConfig} from "@lodestar/config";
2
+ import {GENESIS_SLOT, ZERO_HASH} from "@lodestar/params";
3
+ import {phase0, ssz} from "@lodestar/types";
4
+ import {BeaconStateAllForks} from "../types.js";
5
+ import {blockToHeader} from "./blockRoot.js";
6
+ import {computeCheckpointEpochAtStateSlot} from "./epoch.js";
7
+
8
+ export function computeAnchorCheckpoint(
9
+ config: ChainForkConfig,
10
+ anchorState: BeaconStateAllForks
11
+ ): {checkpoint: phase0.Checkpoint; blockHeader: phase0.BeaconBlockHeader} {
12
+ let blockHeader: phase0.BeaconBlockHeader;
13
+ let root: Uint8Array;
14
+ const blockTypes = config.getForkTypes(anchorState.latestBlockHeader.slot);
15
+
16
+ if (anchorState.latestBlockHeader.slot === GENESIS_SLOT) {
17
+ const block = blockTypes.BeaconBlock.defaultValue();
18
+ block.stateRoot = anchorState.hashTreeRoot();
19
+ blockHeader = blockToHeader(config, block);
20
+ root = ssz.phase0.BeaconBlockHeader.hashTreeRoot(blockHeader);
21
+ } else {
22
+ blockHeader = ssz.phase0.BeaconBlockHeader.clone(anchorState.latestBlockHeader);
23
+ if (ssz.Root.equals(blockHeader.stateRoot, ZERO_HASH)) {
24
+ blockHeader.stateRoot = anchorState.hashTreeRoot();
25
+ }
26
+ root = ssz.phase0.BeaconBlockHeader.hashTreeRoot(blockHeader);
27
+ }
28
+
29
+ return {
30
+ checkpoint: {
31
+ root,
32
+ // the checkpoint epoch = computeEpochAtSlot(anchorState.slot) + 1 if slot is not at epoch boundary
33
+ // this is similar to a process_slots() call
34
+ epoch: computeCheckpointEpochAtStateSlot(anchorState.slot),
35
+ },
36
+ blockHeader,
37
+ };
38
+ }
@@ -0,0 +1,22 @@
1
+ import {ForkSeq, MAX_DEPOSITS} from "@lodestar/params";
2
+ import {UintNum64, phase0} from "@lodestar/types";
3
+ import {CachedBeaconStateAllForks, CachedBeaconStateElectra} from "../types.js";
4
+
5
+ export function getEth1DepositCount(state: CachedBeaconStateAllForks, eth1Data?: phase0.Eth1Data): UintNum64 {
6
+ const eth1DataToUse = eth1Data ?? state.eth1Data;
7
+ if (state.config.getForkSeq(state.slot) >= ForkSeq.electra) {
8
+ 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);
15
+
16
+ if (state.eth1DepositIndex < eth1DataIndexLimit) {
17
+ return Math.min(MAX_DEPOSITS, eth1DataIndexLimit - state.eth1DepositIndex);
18
+ }
19
+ return 0;
20
+ }
21
+ return Math.min(MAX_DEPOSITS, eth1DataToUse.depositCount - state.eth1DepositIndex);
22
+ }
@@ -0,0 +1,31 @@
1
+ import {DomainType, Epoch, Root, Version, phase0, ssz} from "@lodestar/types";
2
+
3
+ // Only used by processDeposit + lightclient
4
+ /**
5
+ * Return the domain for the [[domainType]] and [[forkVersion]].
6
+ */
7
+ export function computeDomain(domainType: DomainType, forkVersion: Version, genesisValidatorRoot: Root): Uint8Array {
8
+ const forkDataRoot = computeForkDataRoot(forkVersion, genesisValidatorRoot);
9
+ const domain = new Uint8Array(32);
10
+ domain.set(domainType, 0);
11
+ domain.set(forkDataRoot.slice(0, 28), 4);
12
+ return domain;
13
+ }
14
+
15
+ /**
16
+ * Return the ForkVersion at an epoch from a Fork type
17
+ */
18
+ export function getForkVersion(fork: phase0.Fork, epoch: Epoch): Version {
19
+ return epoch < fork.epoch ? fork.previousVersion : fork.currentVersion;
20
+ }
21
+
22
+ /**
23
+ * Used primarily in signature domains to avoid collisions across forks/chains.
24
+ */
25
+ export function computeForkDataRoot(currentVersion: Version, genesisValidatorsRoot: Root): Uint8Array {
26
+ const forkData: phase0.ForkData = {
27
+ currentVersion,
28
+ genesisValidatorsRoot,
29
+ };
30
+ return ssz.phase0.ForkData.hashTreeRoot(forkData);
31
+ }
@@ -0,0 +1,68 @@
1
+ import {COMPOUNDING_WITHDRAWAL_PREFIX, GENESIS_SLOT, MIN_ACTIVATION_BALANCE} from "@lodestar/params";
2
+ import {ValidatorIndex, ssz} from "@lodestar/types";
3
+ import {G2_POINT_AT_INFINITY} from "../constants/constants.js";
4
+ import {CachedBeaconStateElectra} from "../types.js";
5
+ import {hasEth1WithdrawalCredential} from "./capella.js";
6
+
7
+ export function hasCompoundingWithdrawalCredential(withdrawalCredentials: Uint8Array): boolean {
8
+ return withdrawalCredentials[0] === COMPOUNDING_WITHDRAWAL_PREFIX;
9
+ }
10
+
11
+ export function hasExecutionWithdrawalCredential(withdrawalCredentials: Uint8Array): boolean {
12
+ return (
13
+ hasCompoundingWithdrawalCredential(withdrawalCredentials) || hasEth1WithdrawalCredential(withdrawalCredentials)
14
+ );
15
+ }
16
+
17
+ export function switchToCompoundingValidator(state: CachedBeaconStateElectra, index: ValidatorIndex): void {
18
+ const validator = state.validators.get(index);
19
+
20
+ // directly modifying the byte leads to ssz missing the modification resulting into
21
+ // wrong root compute, although slicing can be avoided but anyway this is not going
22
+ // to be a hot path so its better to clean slice and avoid side effects
23
+ const newWithdrawalCredentials = Uint8Array.prototype.slice.call(
24
+ validator.withdrawalCredentials,
25
+ 0,
26
+ validator.withdrawalCredentials.length
27
+ );
28
+ newWithdrawalCredentials[0] = COMPOUNDING_WITHDRAWAL_PREFIX;
29
+ validator.withdrawalCredentials = newWithdrawalCredentials;
30
+ queueExcessActiveBalance(state, index);
31
+ }
32
+
33
+ export function queueExcessActiveBalance(state: CachedBeaconStateElectra, index: ValidatorIndex): void {
34
+ const balance = state.balances.get(index);
35
+ if (balance > MIN_ACTIVATION_BALANCE) {
36
+ const validator = state.validators.getReadonly(index);
37
+ const excessBalance = balance - MIN_ACTIVATION_BALANCE;
38
+ state.balances.set(index, MIN_ACTIVATION_BALANCE);
39
+
40
+ const pendingDeposit = ssz.electra.PendingDeposit.toViewDU({
41
+ pubkey: validator.pubkey,
42
+ withdrawalCredentials: validator.withdrawalCredentials,
43
+ amount: excessBalance,
44
+ // Use bls.G2_POINT_AT_INFINITY as a signature field placeholder
45
+ signature: G2_POINT_AT_INFINITY,
46
+ // Use GENESIS_SLOT to distinguish from a pending deposit request
47
+ slot: GENESIS_SLOT,
48
+ });
49
+ state.pendingDeposits.push(pendingDeposit);
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Since we share pubkey2index, pubkey maybe added by other epoch transition but we don't have that validator in this state
55
+ */
56
+ export function isPubkeyKnown(state: CachedBeaconStateElectra, pubkey: Uint8Array): boolean {
57
+ return isValidatorKnown(state, state.epochCtx.getValidatorIndex(pubkey));
58
+ }
59
+
60
+ /**
61
+ * Since we share pubkey2index, validatorIndex maybe not null but we don't have that validator in this state
62
+ */
63
+ export function isValidatorKnown(
64
+ state: CachedBeaconStateElectra,
65
+ index: ValidatorIndex | null
66
+ ): index is ValidatorIndex {
67
+ return index !== null && index < state.validators.length;
68
+ }
@@ -0,0 +1,135 @@
1
+ import {EPOCHS_PER_SYNC_COMMITTEE_PERIOD, GENESIS_EPOCH, MAX_SEED_LOOKAHEAD, SLOTS_PER_EPOCH} from "@lodestar/params";
2
+ import {BeaconState, Epoch, Gwei, Slot, SyncPeriod} from "@lodestar/types";
3
+ import {CachedBeaconStateElectra} from "../types.js";
4
+ import {getActivationExitChurnLimit, getConsolidationChurnLimit} from "./validator.js";
5
+
6
+ /**
7
+ * Return the epoch number at the given slot.
8
+ */
9
+ export function computeEpochAtSlot(slot: Slot): Epoch {
10
+ return Math.floor(slot / SLOTS_PER_EPOCH);
11
+ }
12
+
13
+ /**
14
+ * Return the epoch at the state slot for purposes of checkpoint.
15
+ * Ideally this slot % SLOTS_PER_EPOCH === 0, but just to handle the improbable case of
16
+ * non boundary slot, using ceil so that the state's latestBlockHeader would always
17
+ * lie before this epooch
18
+ */
19
+ export function computeCheckpointEpochAtStateSlot(slot: Slot): Epoch {
20
+ return Math.ceil(slot / SLOTS_PER_EPOCH);
21
+ }
22
+
23
+ /**
24
+ * Return the starting slot of the given epoch.
25
+ */
26
+ export function computeStartSlotAtEpoch(epoch: Epoch): Slot {
27
+ return epoch * SLOTS_PER_EPOCH;
28
+ }
29
+
30
+ /**
31
+ * Return the end slot of the given epoch.
32
+ */
33
+ export function computeEndSlotAtEpoch(epoch: Epoch): Slot {
34
+ return computeStartSlotAtEpoch(epoch + 1) - 1;
35
+ }
36
+
37
+ /**
38
+ * Return the epoch at which an activation or exit triggered in ``epoch`` takes effect.
39
+ */
40
+ export function computeActivationExitEpoch(epoch: Epoch): Epoch {
41
+ return epoch + 1 + MAX_SEED_LOOKAHEAD;
42
+ }
43
+
44
+ export function computeExitEpochAndUpdateChurn(state: CachedBeaconStateElectra, exitBalance: Gwei): number {
45
+ let earliestExitEpoch = Math.max(state.earliestExitEpoch, computeActivationExitEpoch(state.epochCtx.epoch));
46
+ const perEpochChurn = getActivationExitChurnLimit(state.epochCtx);
47
+
48
+ // New epoch for exits.
49
+ let exitBalanceToConsume =
50
+ state.earliestExitEpoch < earliestExitEpoch ? perEpochChurn : Number(state.exitBalanceToConsume);
51
+
52
+ // Exit doesn't fit in the current earliest epoch.
53
+ if (exitBalance > exitBalanceToConsume) {
54
+ const balanceToProcess = Number(exitBalance) - exitBalanceToConsume;
55
+ const additionalEpochs = Math.floor((balanceToProcess - 1) / perEpochChurn) + 1;
56
+ earliestExitEpoch += additionalEpochs;
57
+ exitBalanceToConsume += additionalEpochs * perEpochChurn;
58
+ }
59
+
60
+ // Consume the balance and update state variables.
61
+ state.exitBalanceToConsume = BigInt(exitBalanceToConsume) - exitBalance;
62
+ state.earliestExitEpoch = earliestExitEpoch;
63
+
64
+ return state.earliestExitEpoch;
65
+ }
66
+
67
+ export function computeConsolidationEpochAndUpdateChurn(
68
+ state: CachedBeaconStateElectra,
69
+ consolidationBalance: Gwei
70
+ ): number {
71
+ let earliestConsolidationEpoch = Math.max(
72
+ state.earliestConsolidationEpoch,
73
+ computeActivationExitEpoch(state.epochCtx.epoch)
74
+ );
75
+ const perEpochConsolidationChurn = getConsolidationChurnLimit(state.epochCtx);
76
+
77
+ // New epoch for consolidations
78
+ let consolidationBalanceToConsume =
79
+ state.earliestConsolidationEpoch < earliestConsolidationEpoch
80
+ ? perEpochConsolidationChurn
81
+ : Number(state.consolidationBalanceToConsume);
82
+
83
+ // Consolidation doesn't fit in the current earliest epoch.
84
+ if (consolidationBalance > consolidationBalanceToConsume) {
85
+ const balanceToProcess = Number(consolidationBalance) - consolidationBalanceToConsume;
86
+ const additionalEpochs = Math.floor((balanceToProcess - 1) / perEpochConsolidationChurn) + 1;
87
+ earliestConsolidationEpoch += additionalEpochs;
88
+ consolidationBalanceToConsume += additionalEpochs * perEpochConsolidationChurn;
89
+ }
90
+
91
+ // Consume the balance and update state variables.
92
+ state.consolidationBalanceToConsume = BigInt(consolidationBalanceToConsume) - consolidationBalance;
93
+ state.earliestConsolidationEpoch = earliestConsolidationEpoch;
94
+
95
+ return state.earliestConsolidationEpoch;
96
+ }
97
+
98
+ /**
99
+ * Return the current epoch of the given state.
100
+ */
101
+ export function getCurrentEpoch(state: Pick<BeaconState, "slot">): Epoch {
102
+ return computeEpochAtSlot(state.slot);
103
+ }
104
+
105
+ /**
106
+ * Return the previous epoch of the given state.
107
+ */
108
+ export function getPreviousEpoch(state: Pick<BeaconState, "slot">): Epoch {
109
+ const currentEpoch = getCurrentEpoch(state);
110
+ if (currentEpoch === GENESIS_EPOCH) {
111
+ return GENESIS_EPOCH;
112
+ }
113
+ return currentEpoch - 1;
114
+ }
115
+
116
+ /**
117
+ * Return the sync committee period at slot
118
+ */
119
+ export function computeSyncPeriodAtSlot(slot: Slot): SyncPeriod {
120
+ return computeSyncPeriodAtEpoch(computeEpochAtSlot(slot));
121
+ }
122
+
123
+ /**
124
+ * Return the sync committee period at epoch
125
+ */
126
+ export function computeSyncPeriodAtEpoch(epoch: Epoch): SyncPeriod {
127
+ return Math.floor(epoch / EPOCHS_PER_SYNC_COMMITTEE_PERIOD);
128
+ }
129
+
130
+ /**
131
+ * Determine if the given slot is start slot of an epoch
132
+ */
133
+ export function isStartSlotOfEpoch(slot: Slot): boolean {
134
+ return slot % SLOTS_PER_EPOCH === 0;
135
+ }