@lodestar/beacon-node 1.39.0-dev.882891d89c → 1.39.0-dev.90334173dc

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 (226) hide show
  1. package/README.md +1 -1
  2. package/lib/api/impl/beacon/state/utils.d.ts +2 -7
  3. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  4. package/lib/api/impl/beacon/state/utils.js +0 -12
  5. package/lib/api/impl/beacon/state/utils.js.map +1 -1
  6. package/lib/api/impl/lodestar/index.js +1 -1
  7. package/lib/api/impl/lodestar/index.js.map +1 -1
  8. package/lib/api/impl/proof/index.d.ts.map +1 -1
  9. package/lib/api/impl/proof/index.js +1 -2
  10. package/lib/api/impl/proof/index.js.map +1 -1
  11. package/lib/api/impl/validator/index.d.ts.map +1 -1
  12. package/lib/api/impl/validator/index.js +1 -3
  13. package/lib/api/impl/validator/index.js.map +1 -1
  14. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
  15. package/lib/chain/archiveStore/historicalState/getHistoricalState.js +5 -3
  16. package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
  17. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
  18. package/lib/chain/archiveStore/utils/archiveBlocks.js +19 -14
  19. package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
  20. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  21. package/lib/chain/blocks/importBlock.js +12 -3
  22. package/lib/chain/blocks/importBlock.js.map +1 -1
  23. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  24. package/lib/chain/blocks/verifyBlock.js +8 -1
  25. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  26. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  27. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +4 -2
  28. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  29. package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
  30. package/lib/chain/blocks/verifyBlocksSignatures.js +2 -1
  31. package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
  32. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts.map +1 -1
  33. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js +1 -0
  34. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js.map +1 -1
  35. package/lib/chain/chain.d.ts +11 -11
  36. package/lib/chain/chain.d.ts.map +1 -1
  37. package/lib/chain/chain.js +32 -38
  38. package/lib/chain/chain.js.map +1 -1
  39. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  40. package/lib/chain/forkChoice/index.js +3 -3
  41. package/lib/chain/forkChoice/index.js.map +1 -1
  42. package/lib/chain/initState.d.ts +1 -1
  43. package/lib/chain/initState.d.ts.map +1 -1
  44. package/lib/chain/initState.js +5 -3
  45. package/lib/chain/initState.js.map +1 -1
  46. package/lib/chain/interface.d.ts +6 -9
  47. package/lib/chain/interface.d.ts.map +1 -1
  48. package/lib/chain/interface.js.map +1 -1
  49. package/lib/chain/lightClient/proofs.d.ts.map +1 -1
  50. package/lib/chain/lightClient/proofs.js +0 -2
  51. package/lib/chain/lightClient/proofs.js.map +1 -1
  52. package/lib/chain/opPools/aggregatedAttestationPool.d.ts +5 -9
  53. package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
  54. package/lib/chain/opPools/aggregatedAttestationPool.js +12 -141
  55. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  56. package/lib/chain/opPools/opPool.js +5 -8
  57. package/lib/chain/opPools/opPool.js.map +1 -1
  58. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  59. package/lib/chain/prepareNextSlot.js +4 -7
  60. package/lib/chain/prepareNextSlot.js.map +1 -1
  61. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  62. package/lib/chain/produceBlock/produceBlockBody.js +2 -2
  63. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  64. package/lib/chain/regen/interface.d.ts +1 -5
  65. package/lib/chain/regen/interface.d.ts.map +1 -1
  66. package/lib/chain/regen/queued.d.ts +4 -7
  67. package/lib/chain/regen/queued.d.ts.map +1 -1
  68. package/lib/chain/regen/queued.js +15 -25
  69. package/lib/chain/regen/queued.js.map +1 -1
  70. package/lib/chain/regen/regen.d.ts +1 -1
  71. package/lib/chain/regen/regen.d.ts.map +1 -1
  72. package/lib/chain/regen/regen.js +13 -17
  73. package/lib/chain/regen/regen.js.map +1 -1
  74. package/lib/chain/shufflingCache.d.ts +16 -11
  75. package/lib/chain/shufflingCache.d.ts.map +1 -1
  76. package/lib/chain/shufflingCache.js +47 -41
  77. package/lib/chain/shufflingCache.js.map +1 -1
  78. package/lib/chain/stateCache/blockStateCacheImpl.d.ts +1 -2
  79. package/lib/chain/stateCache/blockStateCacheImpl.d.ts.map +1 -1
  80. package/lib/chain/stateCache/blockStateCacheImpl.js +2 -2
  81. package/lib/chain/stateCache/blockStateCacheImpl.js.map +1 -1
  82. package/lib/chain/stateCache/fifoBlockStateCache.d.ts +1 -2
  83. package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
  84. package/lib/chain/stateCache/fifoBlockStateCache.js +4 -4
  85. package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
  86. package/lib/chain/stateCache/inMemoryCheckpointsCache.d.ts +4 -5
  87. package/lib/chain/stateCache/inMemoryCheckpointsCache.d.ts.map +1 -1
  88. package/lib/chain/stateCache/inMemoryCheckpointsCache.js +9 -10
  89. package/lib/chain/stateCache/inMemoryCheckpointsCache.js.map +1 -1
  90. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +5 -6
  91. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  92. package/lib/chain/stateCache/persistentCheckpointsCache.js +17 -17
  93. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  94. package/lib/chain/stateCache/types.d.ts +5 -6
  95. package/lib/chain/stateCache/types.d.ts.map +1 -1
  96. package/lib/chain/stateCache/types.js.map +1 -1
  97. package/lib/chain/validation/aggregateAndProof.js +9 -0
  98. package/lib/chain/validation/aggregateAndProof.js.map +1 -1
  99. package/lib/chain/validation/attestation.d.ts.map +1 -1
  100. package/lib/chain/validation/attestation.js +2 -2
  101. package/lib/chain/validation/attestation.js.map +1 -1
  102. package/lib/chain/validation/attesterSlashing.d.ts.map +1 -1
  103. package/lib/chain/validation/attesterSlashing.js +2 -2
  104. package/lib/chain/validation/attesterSlashing.js.map +1 -1
  105. package/lib/chain/validation/blobSidecar.d.ts.map +1 -1
  106. package/lib/chain/validation/blobSidecar.js +2 -3
  107. package/lib/chain/validation/blobSidecar.js.map +1 -1
  108. package/lib/chain/validation/block.d.ts.map +1 -1
  109. package/lib/chain/validation/block.js +5 -3
  110. package/lib/chain/validation/block.js.map +1 -1
  111. package/lib/chain/validation/blsToExecutionChange.d.ts.map +1 -1
  112. package/lib/chain/validation/blsToExecutionChange.js +9 -2
  113. package/lib/chain/validation/blsToExecutionChange.js.map +1 -1
  114. package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
  115. package/lib/chain/validation/dataColumnSidecar.js +2 -3
  116. package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
  117. package/lib/chain/validation/proposerSlashing.js +3 -2
  118. package/lib/chain/validation/proposerSlashing.js.map +1 -1
  119. package/lib/chain/validation/voluntaryExit.js +1 -1
  120. package/lib/chain/validation/voluntaryExit.js.map +1 -1
  121. package/lib/db/repositories/checkpointState.d.ts +2 -6
  122. package/lib/db/repositories/checkpointState.d.ts.map +1 -1
  123. package/lib/db/repositories/checkpointState.js +3 -15
  124. package/lib/db/repositories/checkpointState.js.map +1 -1
  125. package/lib/db/repositories/stateArchive.d.ts +9 -9
  126. package/lib/db/repositories/stateArchive.d.ts.map +1 -1
  127. package/lib/db/repositories/stateArchive.js +6 -21
  128. package/lib/db/repositories/stateArchive.js.map +1 -1
  129. package/lib/execution/engine/mock.d.ts +9 -6
  130. package/lib/execution/engine/mock.d.ts.map +1 -1
  131. package/lib/execution/engine/mock.js +34 -7
  132. package/lib/execution/engine/mock.js.map +1 -1
  133. package/lib/index.d.ts +1 -1
  134. package/lib/index.d.ts.map +1 -1
  135. package/lib/index.js +1 -1
  136. package/lib/index.js.map +1 -1
  137. package/lib/metrics/metrics/lodestar.d.ts +1 -6
  138. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  139. package/lib/metrics/metrics/lodestar.js +3 -17
  140. package/lib/metrics/metrics/lodestar.js.map +1 -1
  141. package/lib/network/peers/discover.d.ts.map +1 -1
  142. package/lib/network/peers/discover.js.map +1 -1
  143. package/lib/network/reqresp/utils/dataColumnResponseValidation.js +1 -1
  144. package/lib/network/reqresp/utils/dataColumnResponseValidation.js.map +1 -1
  145. package/lib/node/nodejs.d.ts +6 -3
  146. package/lib/node/nodejs.d.ts.map +1 -1
  147. package/lib/node/nodejs.js +20 -3
  148. package/lib/node/nodejs.js.map +1 -1
  149. package/lib/node/notifier.d.ts.map +1 -1
  150. package/lib/node/notifier.js +9 -6
  151. package/lib/node/notifier.js.map +1 -1
  152. package/lib/sync/backfill/backfill.d.ts.map +1 -1
  153. package/lib/sync/backfill/backfill.js +2 -2
  154. package/lib/sync/backfill/backfill.js.map +1 -1
  155. package/lib/sync/backfill/verify.d.ts +2 -2
  156. package/lib/sync/backfill/verify.d.ts.map +1 -1
  157. package/lib/sync/backfill/verify.js +3 -3
  158. package/lib/sync/backfill/verify.js.map +1 -1
  159. package/lib/util/sszBytes.js +1 -1
  160. package/lib/util/sszBytes.js.map +1 -1
  161. package/package.json +28 -20
  162. package/src/api/impl/beacon/state/utils.ts +2 -22
  163. package/src/api/impl/lodestar/index.ts +1 -1
  164. package/src/api/impl/proof/index.ts +1 -2
  165. package/src/api/impl/validator/index.ts +1 -3
  166. package/src/chain/archiveStore/historicalState/getHistoricalState.ts +5 -3
  167. package/src/chain/archiveStore/utils/archiveBlocks.ts +21 -14
  168. package/src/chain/blocks/importBlock.ts +13 -3
  169. package/src/chain/blocks/verifyBlock.ts +9 -3
  170. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +9 -2
  171. package/src/chain/blocks/verifyBlocksSignatures.ts +11 -3
  172. package/src/chain/blocks/verifyBlocksStateTransitionOnly.ts +1 -0
  173. package/src/chain/chain.ts +46 -46
  174. package/src/chain/forkChoice/index.ts +3 -2
  175. package/src/chain/initState.ts +5 -3
  176. package/src/chain/interface.ts +6 -8
  177. package/src/chain/lightClient/proofs.ts +0 -2
  178. package/src/chain/opPools/aggregatedAttestationPool.ts +19 -191
  179. package/src/chain/opPools/opPool.ts +5 -7
  180. package/src/chain/prepareNextSlot.ts +2 -6
  181. package/src/chain/produceBlock/produceBlockBody.ts +7 -2
  182. package/src/chain/regen/interface.ts +1 -5
  183. package/src/chain/regen/queued.ts +15 -34
  184. package/src/chain/regen/regen.ts +12 -18
  185. package/src/chain/shufflingCache.ts +67 -50
  186. package/src/chain/stateCache/blockStateCacheImpl.ts +2 -3
  187. package/src/chain/stateCache/fifoBlockStateCache.ts +4 -5
  188. package/src/chain/stateCache/inMemoryCheckpointsCache.ts +9 -15
  189. package/src/chain/stateCache/persistentCheckpointsCache.ts +17 -25
  190. package/src/chain/stateCache/types.ts +5 -10
  191. package/src/chain/validation/aggregateAndProof.ts +12 -0
  192. package/src/chain/validation/attestation.ts +3 -3
  193. package/src/chain/validation/attesterSlashing.ts +14 -2
  194. package/src/chain/validation/blobSidecar.ts +3 -3
  195. package/src/chain/validation/block.ts +6 -2
  196. package/src/chain/validation/blsToExecutionChange.ts +9 -7
  197. package/src/chain/validation/dataColumnSidecar.ts +3 -3
  198. package/src/chain/validation/proposerSlashing.ts +8 -2
  199. package/src/chain/validation/voluntaryExit.ts +1 -1
  200. package/src/db/repositories/checkpointState.ts +3 -19
  201. package/src/db/repositories/stateArchive.ts +13 -27
  202. package/src/execution/engine/mock.ts +40 -13
  203. package/src/index.ts +1 -1
  204. package/src/metrics/metrics/lodestar.ts +3 -17
  205. package/src/network/peers/discover.ts +3 -3
  206. package/src/network/reqresp/utils/dataColumnResponseValidation.ts +1 -1
  207. package/src/node/nodejs.ts +26 -4
  208. package/src/node/notifier.ts +13 -7
  209. package/src/sync/backfill/backfill.ts +2 -14
  210. package/src/sync/backfill/verify.ts +2 -9
  211. package/src/util/sszBytes.ts +1 -1
  212. package/lib/chain/rewards/attestationsRewards.d.ts +0 -8
  213. package/lib/chain/rewards/attestationsRewards.d.ts.map +0 -1
  214. package/lib/chain/rewards/attestationsRewards.js +0 -112
  215. package/lib/chain/rewards/attestationsRewards.js.map +0 -1
  216. package/lib/chain/rewards/blockRewards.d.ts +0 -15
  217. package/lib/chain/rewards/blockRewards.d.ts.map +0 -1
  218. package/lib/chain/rewards/blockRewards.js +0 -94
  219. package/lib/chain/rewards/blockRewards.js.map +0 -1
  220. package/lib/chain/rewards/syncCommitteeRewards.d.ts +0 -7
  221. package/lib/chain/rewards/syncCommitteeRewards.d.ts.map +0 -1
  222. package/lib/chain/rewards/syncCommitteeRewards.js +0 -36
  223. package/lib/chain/rewards/syncCommitteeRewards.js.map +0 -1
  224. package/src/chain/rewards/attestationsRewards.ts +0 -206
  225. package/src/chain/rewards/blockRewards.ts +0 -153
  226. package/src/chain/rewards/syncCommitteeRewards.ts +0 -60
@@ -1,12 +1,12 @@
1
+ import {ForkSeq} from "@lodestar/params";
1
2
  import {
2
- BeaconStateAllForks,
3
+ CachedBeaconStateAllForks,
3
4
  EpochShuffling,
4
- IShufflingCache,
5
- ShufflingBuildProps,
6
- computeEpochShuffling,
7
- computeEpochShufflingAsync,
5
+ getAttestingIndices,
6
+ getBeaconCommittees,
7
+ getIndexedAttestation,
8
8
  } from "@lodestar/state-transition";
9
- import {Epoch, RootHex} from "@lodestar/types";
9
+ import {Attestation, CommitteeIndex, Epoch, IndexedAttestation, RootHex, Slot} from "@lodestar/types";
10
10
  import {LodestarError, Logger, MapDef, pruneSetToMax} from "@lodestar/utils";
11
11
  import {Metrics} from "../metrics/metrics.js";
12
12
 
@@ -53,7 +53,7 @@ export type ShufflingCacheOpts = {
53
53
  * - if a shuffling is not available (which does not happen with default chain option of maxSkipSlots = 32), track a promise to make sure we don't compute the same shuffling twice
54
54
  * - skip computing shuffling when loading state bytes from disk
55
55
  */
56
- export class ShufflingCache implements IShufflingCache {
56
+ export class ShufflingCache {
57
57
  /** LRU cache implemented as a map, pruned every time we add an item */
58
58
  private readonly itemsByDecisionRootByEpoch: MapDef<Epoch, Map<RootHex, CacheItem>> = new MapDef(
59
59
  () => new Map<RootHex, CacheItem>()
@@ -136,60 +136,76 @@ export class ShufflingCache implements IShufflingCache {
136
136
  }
137
137
 
138
138
  /**
139
- * Gets a cached shuffling via the epoch and decision root. If the shuffling is not
140
- * available it will build it synchronously and return the shuffling.
141
- *
142
- * NOTE: If a shuffling is already queued and not calculated it will build and resolve
143
- * the promise but the already queued build will happen at some later time
139
+ * Get a shuffling synchronously, return null if not present.
140
+ * The only time we have a promise cache item is when we regen shuffling for attestation, which never happens
141
+ * with default chain option.
144
142
  */
145
- getSync<T extends ShufflingBuildProps | undefined>(
146
- epoch: Epoch,
147
- decisionRoot: RootHex,
148
- buildProps?: T
149
- ): T extends ShufflingBuildProps ? EpochShuffling : EpochShuffling | null {
143
+ getSync(epoch: Epoch, decisionRoot: RootHex): EpochShuffling | null {
150
144
  const cacheItem = this.itemsByDecisionRootByEpoch.getOrDefault(epoch).get(decisionRoot);
151
- if (!cacheItem) {
145
+ if (cacheItem === undefined) {
152
146
  this.metrics?.shufflingCache.miss.inc();
153
- } else if (isShufflingCacheItem(cacheItem)) {
147
+ return null;
148
+ }
149
+
150
+ if (isShufflingCacheItem(cacheItem)) {
154
151
  this.metrics?.shufflingCache.hit.inc();
155
152
  return cacheItem.shuffling;
156
- } else if (buildProps) {
157
- // TODO: (@matthewkeil) This should possible log a warning??
158
- this.metrics?.shufflingCache.shufflingPromiseNotResolvedAndThrownAway.inc();
159
- } else {
160
- this.metrics?.shufflingCache.shufflingPromiseNotResolved.inc();
161
153
  }
162
154
 
163
- let shuffling: EpochShuffling | null = null;
164
- if (buildProps) {
165
- const timer = this.metrics?.shufflingCache.shufflingCalculationTime.startTimer({source: "getSync"});
166
- shuffling = computeEpochShuffling(buildProps.state, buildProps.activeIndices, epoch);
167
- timer?.();
168
- this.set(shuffling, decisionRoot);
169
- }
170
- return shuffling as T extends ShufflingBuildProps ? EpochShuffling : EpochShuffling | null;
155
+ return null;
171
156
  }
172
157
 
173
158
  /**
174
- * Queue asynchronous build for an EpochShuffling, triggered from state-transition
159
+ * Process a state to extract and cache all shufflings (previous, current, next).
160
+ * Uses the stored decision roots from epochCtx.
175
161
  */
176
- build(epoch: number, decisionRoot: string, state: BeaconStateAllForks, activeIndices: Uint32Array): void {
177
- this.insertPromise(epoch, decisionRoot);
178
- /**
179
- * TODO: (@matthewkeil) This will get replaced by a proper build queue and a worker to do calculations
180
- * on a NICE thread
181
- */
182
- const timer = this.metrics?.shufflingCache.shufflingCalculationTime.startTimer({source: "build"});
183
- computeEpochShufflingAsync(state, activeIndices, epoch)
184
- .then((shuffling) => {
185
- this.set(shuffling, decisionRoot);
186
- })
187
- .catch((err) =>
188
- this.logger?.error(`error building shuffling for epoch ${epoch} at decisionRoot ${decisionRoot}`, {}, err)
189
- )
190
- .finally(() => {
191
- timer?.();
162
+ processState(state: CachedBeaconStateAllForks): void {
163
+ const {epochCtx} = state;
164
+
165
+ // Cache previous shuffling
166
+ this.set(epochCtx.previousShuffling, epochCtx.previousDecisionRoot);
167
+
168
+ // Cache current shuffling
169
+ this.set(epochCtx.currentShuffling, epochCtx.currentDecisionRoot);
170
+
171
+ // Cache next shuffling
172
+ this.set(epochCtx.nextShuffling, epochCtx.nextDecisionRoot);
173
+ }
174
+
175
+ getIndexedAttestation(
176
+ epoch: number,
177
+ decisionRoot: string,
178
+ fork: ForkSeq,
179
+ attestation: Attestation
180
+ ): IndexedAttestation {
181
+ const shuffling = this.getShufflingOrThrow(epoch, decisionRoot);
182
+ return getIndexedAttestation(shuffling, fork, attestation);
183
+ }
184
+
185
+ getAttestingIndices(epoch: number, decisionRoot: string, fork: ForkSeq, attestation: Attestation): number[] {
186
+ const shuffling = this.getShufflingOrThrow(epoch, decisionRoot);
187
+ return getAttestingIndices(shuffling, fork, attestation);
188
+ }
189
+
190
+ getBeaconCommittee(epoch: number, decisionRoot: string, slot: Slot, index: CommitteeIndex): Uint32Array {
191
+ return this.getBeaconCommittees(epoch, decisionRoot, slot, [index])[0];
192
+ }
193
+
194
+ getBeaconCommittees(epoch: number, decisionRoot: string, slot: Slot, indices: CommitteeIndex[]): Uint32Array[] {
195
+ const shuffling = this.getShufflingOrThrow(epoch, decisionRoot);
196
+ return getBeaconCommittees(shuffling, slot, indices);
197
+ }
198
+
199
+ private getShufflingOrThrow(epoch: number, decisionRoot: string): EpochShuffling {
200
+ const shuffling = this.getSync(epoch, decisionRoot);
201
+ if (shuffling === null) {
202
+ throw new ShufflingCacheError({
203
+ code: ShufflingCacheErrorCode.NO_SHUFFLING_FOUND,
204
+ epoch,
205
+ decisionRoot,
192
206
  });
207
+ }
208
+ return shuffling;
193
209
  }
194
210
 
195
211
  /**
@@ -207,7 +223,8 @@ export class ShufflingCache implements IShufflingCache {
207
223
  (Date.now() - cacheItem.timeInsertedMs) / 1000
208
224
  );
209
225
  } else {
210
- this.metrics?.shufflingCache.shufflingBuiltMultipleTimes.inc();
226
+ this.metrics?.shufflingCache.shufflingSetMultipleTimes.inc();
227
+ return;
211
228
  }
212
229
  }
213
230
  // set the shuffling
@@ -3,7 +3,6 @@ import {CachedBeaconStateAllForks} from "@lodestar/state-transition";
3
3
  import {Epoch, RootHex} from "@lodestar/types";
4
4
  import {toRootHex} from "@lodestar/utils";
5
5
  import {Metrics} from "../../metrics/index.js";
6
- import {StateRegenerationOpts} from "../regen/interface.js";
7
6
  import {MapTracker} from "./mapMetrics.js";
8
7
  import {BlockStateCache} from "./types.js";
9
8
 
@@ -39,7 +38,7 @@ export class BlockStateCacheImpl implements BlockStateCache {
39
38
  }
40
39
  }
41
40
 
42
- get(rootHex: RootHex, opts?: StateRegenerationOpts): CachedBeaconStateAllForks | null {
41
+ get(rootHex: RootHex): CachedBeaconStateAllForks | null {
43
42
  this.metrics?.lookups.inc();
44
43
  const item = this.head?.stateRoot === rootHex ? this.head.state : this.cache.get(rootHex);
45
44
  if (!item) {
@@ -49,7 +48,7 @@ export class BlockStateCacheImpl implements BlockStateCache {
49
48
  this.metrics?.hits.inc();
50
49
  this.metrics?.stateClonedCount.observe(item.clonedCount);
51
50
 
52
- return item.clone(opts?.dontTransferCache);
51
+ return item;
53
52
  }
54
53
 
55
54
  add(item: CachedBeaconStateAllForks): void {
@@ -4,7 +4,6 @@ import {RootHex} from "@lodestar/types";
4
4
  import {toRootHex} from "@lodestar/utils";
5
5
  import {Metrics} from "../../metrics/index.js";
6
6
  import {LinkedList} from "../../util/array.js";
7
- import {StateRegenerationOpts} from "../regen/interface.js";
8
7
  import {MapTracker} from "./mapMetrics.js";
9
8
  import {BlockStateCache} from "./types.js";
10
9
 
@@ -86,14 +85,14 @@ export class FIFOBlockStateCache implements BlockStateCache {
86
85
  }
87
86
 
88
87
  const firstState = firstValue.value;
89
- // don't transfer cache because consumer only use this cache to reload another state from disc
90
- return firstState.clone(true);
88
+ // consumers should not mutate the returned state
89
+ return firstState;
91
90
  }
92
91
 
93
92
  /**
94
93
  * Get a state from this cache given a state root hex.
95
94
  */
96
- get(rootHex: RootHex, opts?: StateRegenerationOpts): CachedBeaconStateAllForks | null {
95
+ get(rootHex: RootHex): CachedBeaconStateAllForks | null {
97
96
  this.metrics?.lookups.inc();
98
97
  const item = this.cache.get(rootHex);
99
98
  if (!item) {
@@ -103,7 +102,7 @@ export class FIFOBlockStateCache implements BlockStateCache {
103
102
  this.metrics?.hits.inc();
104
103
  this.metrics?.stateClonedCount.observe(item.clonedCount);
105
104
 
106
- return item.clone(opts?.dontTransferCache);
105
+ return item;
107
106
  }
108
107
 
109
108
  /**
@@ -3,7 +3,6 @@ import {CachedBeaconStateAllForks} from "@lodestar/state-transition";
3
3
  import {Epoch, RootHex, phase0} from "@lodestar/types";
4
4
  import {MapDef, toRootHex} from "@lodestar/utils";
5
5
  import {Metrics} from "../../metrics/index.js";
6
- import {StateRegenerationOpts} from "../regen/interface.js";
7
6
  import {MapTracker} from "./mapMetrics.js";
8
7
  import {CacheItemType, CheckpointStateCache} from "./types.js";
9
8
 
@@ -42,21 +41,16 @@ export class InMemoryCheckpointStateCache implements CheckpointStateCache {
42
41
  this.maxEpochs = maxEpochs;
43
42
  }
44
43
 
45
- async getOrReload(cp: CheckpointHex, opts?: StateRegenerationOpts): Promise<CachedBeaconStateAllForks | null> {
46
- return this.get(cp, opts);
44
+ async getOrReload(cp: CheckpointHex): Promise<CachedBeaconStateAllForks | null> {
45
+ return this.get(cp);
47
46
  }
48
47
 
49
48
  async getStateOrBytes(cp: CheckpointHex): Promise<Uint8Array | CachedBeaconStateAllForks | null> {
50
- // no need to transfer cache for this api
51
- return this.get(cp, {dontTransferCache: true});
49
+ return this.get(cp);
52
50
  }
53
51
 
54
- async getOrReloadLatest(
55
- rootHex: string,
56
- maxEpoch: number,
57
- opts?: StateRegenerationOpts
58
- ): Promise<CachedBeaconStateAllForks | null> {
59
- return this.getLatest(rootHex, maxEpoch, opts);
52
+ async getOrReloadLatest(rootHex: string, maxEpoch: number): Promise<CachedBeaconStateAllForks | null> {
53
+ return this.getLatest(rootHex, maxEpoch);
60
54
  }
61
55
 
62
56
  async processState(): Promise<number> {
@@ -64,7 +58,7 @@ export class InMemoryCheckpointStateCache implements CheckpointStateCache {
64
58
  return 0;
65
59
  }
66
60
 
67
- get(cp: CheckpointHex, opts?: StateRegenerationOpts): CachedBeaconStateAllForks | null {
61
+ get(cp: CheckpointHex): CachedBeaconStateAllForks | null {
68
62
  this.metrics?.lookups.inc();
69
63
  const cpKey = toCheckpointKey(cp);
70
64
  const item = this.cache.get(cpKey);
@@ -81,7 +75,7 @@ export class InMemoryCheckpointStateCache implements CheckpointStateCache {
81
75
 
82
76
  this.metrics?.stateClonedCount.observe(item.clonedCount);
83
77
 
84
- return item.clone(opts?.dontTransferCache);
78
+ return item;
85
79
  }
86
80
 
87
81
  add(cp: phase0.Checkpoint, item: CachedBeaconStateAllForks): void {
@@ -98,14 +92,14 @@ export class InMemoryCheckpointStateCache implements CheckpointStateCache {
98
92
  /**
99
93
  * Searches for the latest cached state with a `root`, starting with `epoch` and descending
100
94
  */
101
- getLatest(rootHex: RootHex, maxEpoch: Epoch, opts?: StateRegenerationOpts): CachedBeaconStateAllForks | null {
95
+ getLatest(rootHex: RootHex, maxEpoch: Epoch): CachedBeaconStateAllForks | null {
102
96
  // sort epochs in descending order, only consider epochs lte `epoch`
103
97
  const epochs = Array.from(this.epochIndex.keys())
104
98
  .sort((a, b) => b - a)
105
99
  .filter((e) => e <= maxEpoch);
106
100
  for (const epoch of epochs) {
107
101
  if (this.epochIndex.get(epoch)?.has(rootHex)) {
108
- return this.get({rootHex, epoch}, opts);
102
+ return this.get({rootHex, epoch});
109
103
  }
110
104
  }
111
105
  return null;
@@ -11,7 +11,6 @@ import {Logger, MapDef, fromHex, sleep, toHex, toRootHex} from "@lodestar/utils"
11
11
  import {Metrics} from "../../metrics/index.js";
12
12
  import {AllocSource, BufferPool, BufferWithKey} from "../../util/bufferPool.js";
13
13
  import {IClock} from "../../util/clock.js";
14
- import {StateRegenerationOpts} from "../regen/interface.js";
15
14
  import {serializeState} from "../serializeState.js";
16
15
  import {CPStateDatastore, DatastoreKey} from "./datastore/index.js";
17
16
  import {MapTracker} from "./mapMetrics.js";
@@ -204,10 +203,10 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
204
203
  * - Get block for processing
205
204
  * - Regen head state
206
205
  */
207
- async getOrReload(cp: CheckpointHex, opts?: StateRegenerationOpts): Promise<CachedBeaconStateAllForks | null> {
208
- const stateOrStateBytesData = await this.getStateOrLoadDb(cp, opts);
206
+ async getOrReload(cp: CheckpointHex): Promise<CachedBeaconStateAllForks | null> {
207
+ const stateOrStateBytesData = await this.getStateOrLoadDb(cp);
209
208
  if (stateOrStateBytesData === null || isCachedBeaconState(stateOrStateBytesData)) {
210
- return stateOrStateBytesData?.clone(opts?.dontTransferCache) ?? null;
209
+ return stateOrStateBytesData ?? null;
211
210
  }
212
211
  const {persistedKey, stateBytes} = stateOrStateBytesData;
213
212
  const logMeta = {persistedKey: toHex(persistedKey)};
@@ -233,7 +232,8 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
233
232
  sszTimer?.();
234
233
  const timer = this.metrics?.cpStateCache.stateReloadDuration.startTimer();
235
234
  const newCachedState = loadCachedBeaconState(seedState, stateBytes, {}, validatorsBytes);
236
- newCachedState.commit();
235
+ // hashTreeRoot() calls the commit() inside
236
+ // there is no modification inside the state, it's just that we want to compute and cache all roots
237
237
  const stateRoot = toRootHex(newCachedState.hashTreeRoot());
238
238
  timer?.();
239
239
 
@@ -252,7 +252,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
252
252
  this.cache.set(cpKey, {type: CacheItemType.inMemory, state: newCachedState, persistedKey});
253
253
  this.epochIndex.getOrDefault(cp.epoch).add(cp.rootHex);
254
254
  // don't prune from memory here, call it at the last 1/3 of slot 0 of an epoch
255
- return newCachedState.clone(opts?.dontTransferCache);
255
+ return newCachedState;
256
256
  } catch (e) {
257
257
  this.logger.debug("Reload: error loading cached state", logMeta, e as Error);
258
258
  return null;
@@ -263,8 +263,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
263
263
  * Return either state or state bytes loaded from db.
264
264
  */
265
265
  async getStateOrBytes(cp: CheckpointHex): Promise<CachedBeaconStateAllForks | Uint8Array | null> {
266
- // don't have to transfer cache for this specific api
267
- const stateOrLoadedState = await this.getStateOrLoadDb(cp, {dontTransferCache: true});
266
+ const stateOrLoadedState = await this.getStateOrLoadDb(cp);
268
267
  if (stateOrLoadedState === null || isCachedBeaconState(stateOrLoadedState)) {
269
268
  return stateOrLoadedState;
270
269
  }
@@ -274,12 +273,9 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
274
273
  /**
275
274
  * Return either state or state bytes with persisted key loaded from db.
276
275
  */
277
- async getStateOrLoadDb(
278
- cp: CheckpointHex,
279
- opts?: StateRegenerationOpts
280
- ): Promise<CachedBeaconStateAllForks | LoadedStateBytesData | null> {
276
+ async getStateOrLoadDb(cp: CheckpointHex): Promise<CachedBeaconStateAllForks | LoadedStateBytesData | null> {
281
277
  const cpKey = toCacheKey(cp);
282
- const inMemoryState = this.get(cpKey, opts);
278
+ const inMemoryState = this.get(cpKey);
283
279
  if (inMemoryState) {
284
280
  return inMemoryState;
285
281
  }
@@ -308,7 +304,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
308
304
  /**
309
305
  * Similar to get() api without reloading from disk
310
306
  */
311
- get(cpOrKey: CheckpointHex | string, opts?: StateRegenerationOpts): CachedBeaconStateAllForks | null {
307
+ get(cpOrKey: CheckpointHex | string): CachedBeaconStateAllForks | null {
312
308
  this.metrics?.cpStateCache.lookups.inc();
313
309
  const cpKey = typeof cpOrKey === "string" ? cpOrKey : toCacheKey(cpOrKey);
314
310
  const cacheItem = this.cache.get(cpKey);
@@ -326,7 +322,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
326
322
  if (isInMemoryCacheItem(cacheItem)) {
327
323
  const {state} = cacheItem;
328
324
  this.metrics?.cpStateCache.stateClonedCount.observe(state.clonedCount);
329
- return state.clone(opts?.dontTransferCache);
325
+ return state;
330
326
  }
331
327
 
332
328
  return null;
@@ -360,14 +356,14 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
360
356
  /**
361
357
  * Searches in-memory state for the latest cached state with a `root` without reload, starting with `epoch` and descending
362
358
  */
363
- getLatest(rootHex: RootHex, maxEpoch: Epoch, opts?: StateRegenerationOpts): CachedBeaconStateAllForks | null {
359
+ getLatest(rootHex: RootHex, maxEpoch: Epoch): CachedBeaconStateAllForks | null {
364
360
  // sort epochs in descending order, only consider epochs lte `epoch`
365
361
  const epochs = Array.from(this.epochIndex.keys())
366
362
  .sort((a, b) => b - a)
367
363
  .filter((e) => e <= maxEpoch);
368
364
  for (const epoch of epochs) {
369
365
  if (this.epochIndex.get(epoch)?.has(rootHex)) {
370
- const inMemoryClonedState = this.get({rootHex, epoch}, opts);
366
+ const inMemoryClonedState = this.get({rootHex, epoch});
371
367
  if (inMemoryClonedState) {
372
368
  return inMemoryClonedState;
373
369
  }
@@ -383,11 +379,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
383
379
  * - Get block for processing
384
380
  * - Regen head state
385
381
  */
386
- async getOrReloadLatest(
387
- rootHex: RootHex,
388
- maxEpoch: Epoch,
389
- opts?: StateRegenerationOpts
390
- ): Promise<CachedBeaconStateAllForks | null> {
382
+ async getOrReloadLatest(rootHex: RootHex, maxEpoch: Epoch): Promise<CachedBeaconStateAllForks | null> {
391
383
  // sort epochs in descending order, only consider epochs lte `epoch`
392
384
  const epochs = Array.from(this.epochIndex.keys())
393
385
  .sort((a, b) => b - a)
@@ -395,9 +387,9 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
395
387
  for (const epoch of epochs) {
396
388
  if (this.epochIndex.get(epoch)?.has(rootHex)) {
397
389
  try {
398
- const clonedState = await this.getOrReload({rootHex, epoch}, opts);
399
- if (clonedState) {
400
- return clonedState;
390
+ const state = await this.getOrReload({rootHex, epoch});
391
+ if (state) {
392
+ return state;
401
393
  }
402
394
  } catch (e) {
403
395
  this.logger.debug("Error get or reload state", {epoch, rootHex}, e as Error);
@@ -1,7 +1,6 @@
1
1
  import {routes} from "@lodestar/api";
2
2
  import {CachedBeaconStateAllForks} from "@lodestar/state-transition";
3
3
  import {Epoch, RootHex, phase0} from "@lodestar/types";
4
- import {StateRegenerationOpts} from "../regen/interface.js";
5
4
 
6
5
  export type CheckpointHex = {epoch: Epoch; rootHex: RootHex};
7
6
 
@@ -21,7 +20,7 @@ export type CheckpointHex = {epoch: Epoch; rootHex: RootHex};
21
20
  * The cache key is state root
22
21
  */
23
22
  export interface BlockStateCache {
24
- get(rootHex: RootHex, opts?: StateRegenerationOpts): CachedBeaconStateAllForks | null;
23
+ get(rootHex: RootHex): CachedBeaconStateAllForks | null;
25
24
  add(item: CachedBeaconStateAllForks): void;
26
25
  setHeadState(item: CachedBeaconStateAllForks | null): void;
27
26
  /**
@@ -60,16 +59,12 @@ export interface BlockStateCache {
60
59
  */
61
60
  export interface CheckpointStateCache {
62
61
  init?: () => Promise<void>;
63
- getOrReload(cp: CheckpointHex, opts?: StateRegenerationOpts): Promise<CachedBeaconStateAllForks | null>;
62
+ getOrReload(cp: CheckpointHex): Promise<CachedBeaconStateAllForks | null>;
64
63
  getStateOrBytes(cp: CheckpointHex): Promise<CachedBeaconStateAllForks | Uint8Array | null>;
65
- get(cpOrKey: CheckpointHex | string, opts?: StateRegenerationOpts): CachedBeaconStateAllForks | null;
64
+ get(cpOrKey: CheckpointHex | string): CachedBeaconStateAllForks | null;
66
65
  add(cp: phase0.Checkpoint, state: CachedBeaconStateAllForks): void;
67
- getLatest(rootHex: RootHex, maxEpoch: Epoch, opts?: StateRegenerationOpts): CachedBeaconStateAllForks | null;
68
- getOrReloadLatest(
69
- rootHex: RootHex,
70
- maxEpoch: Epoch,
71
- opts?: StateRegenerationOpts
72
- ): Promise<CachedBeaconStateAllForks | null>;
66
+ getLatest(rootHex: RootHex, maxEpoch: Epoch): CachedBeaconStateAllForks | null;
67
+ getOrReloadLatest(rootHex: RootHex, maxEpoch: Epoch): Promise<CachedBeaconStateAllForks | null>;
73
68
  updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch): number | null;
74
69
  prune(finalizedEpoch: Epoch, justifiedEpoch: Epoch): void;
75
70
  pruneFinalized(finalizedEpoch: Epoch): void;
@@ -245,6 +245,18 @@ async function validateAggregateAndProof(
245
245
  });
246
246
  }
247
247
 
248
+ // Same race-condition check as above for seen aggregators
249
+ if (
250
+ !skipValidationKnownAttesters &&
251
+ chain.seenAggregatedAttestations.isKnown(targetEpoch, attIndex, attDataRootHex, aggregationBits)
252
+ ) {
253
+ throw new AttestationError(GossipAction.IGNORE, {
254
+ code: AttestationErrorCode.ATTESTERS_ALREADY_KNOWN,
255
+ targetEpoch,
256
+ aggregateRoot: attDataRootHex,
257
+ });
258
+ }
259
+
248
260
  chain.seenAggregators.add(targetEpoch, aggregatorIndex);
249
261
  chain.seenAggregatedAttestations.add(
250
262
  targetEpoch,
@@ -12,9 +12,9 @@ import {
12
12
  isForkPostElectra,
13
13
  } from "@lodestar/params";
14
14
  import {
15
- EpochCacheError,
16
- EpochCacheErrorCode,
17
15
  EpochShuffling,
16
+ ShufflingError,
17
+ ShufflingErrorCode,
18
18
  SingleSignatureSet,
19
19
  computeEpochAtSlot,
20
20
  computeSigningRoot,
@@ -224,7 +224,7 @@ export async function validateApiAttestation(
224
224
  code: AttestationErrorCode.INVALID_SIGNATURE,
225
225
  });
226
226
  } catch (err) {
227
- if (err instanceof EpochCacheError && err.type.code === EpochCacheErrorCode.COMMITTEE_INDEX_OUT_OF_RANGE) {
227
+ if (err instanceof ShufflingError && err.type.code === ShufflingErrorCode.COMMITTEE_INDEX_OUT_OF_RANGE) {
228
228
  throw new AttestationError(GossipAction.IGNORE, {
229
229
  code: AttestationErrorCode.BAD_TARGET_EPOCH,
230
230
  });
@@ -43,7 +43,14 @@ export async function validateAttesterSlashing(
43
43
  // [REJECT] All of the conditions within process_attester_slashing pass validation.
44
44
  try {
45
45
  // verifySignature = false, verified in batch below
46
- assertValidAttesterSlashing(chain.index2pubkey, state, attesterSlashing, false);
46
+ assertValidAttesterSlashing(
47
+ chain.config,
48
+ chain.index2pubkey,
49
+ state.slot,
50
+ state.validators.length,
51
+ attesterSlashing,
52
+ false
53
+ );
47
54
  } catch (e) {
48
55
  throw new AttesterSlashingError(GossipAction.REJECT, {
49
56
  code: AttesterSlashingErrorCode.INVALID,
@@ -51,7 +58,12 @@ export async function validateAttesterSlashing(
51
58
  });
52
59
  }
53
60
 
54
- const signatureSets = getAttesterSlashingSignatureSets(chain.config, chain.index2pubkey, state, attesterSlashing);
61
+ const signatureSets = getAttesterSlashingSignatureSets(
62
+ chain.config,
63
+ chain.index2pubkey,
64
+ state.slot,
65
+ attesterSlashing
66
+ );
55
67
  if (!(await chain.bls.verifySignatureSets(signatureSets, {batchable: true, priority: prioritizeBls}))) {
56
68
  throw new AttesterSlashingError(GossipAction.REJECT, {
57
69
  code: AttesterSlashingErrorCode.INVALID,
@@ -138,8 +138,9 @@ export async function validateGossipBlobSidecar(
138
138
  const signature = blobSidecar.signedBlockHeader.signature;
139
139
  if (!chain.seenBlockInputCache.isVerifiedProposerSignature(blobSlot, blockHex, signature)) {
140
140
  const signatureSet = getBlockHeaderProposerSignatureSetByParentStateSlot(
141
+ chain.config,
141
142
  chain.index2pubkey,
142
- blockState,
143
+ blockState.slot,
143
144
  blobSidecar.signedBlockHeader
144
145
  );
145
146
  // Don't batch so verification is not delayed
@@ -243,10 +244,9 @@ export async function validateBlockBlobSidecars(
243
244
  const blockRootHex = toRootHex(blockRoot);
244
245
  const signature = firstSidecarSignedBlockHeader.signature;
245
246
  if (!chain.seenBlockInputCache.isVerifiedProposerSignature(blockSlot, blockRootHex, signature)) {
246
- const headState = await chain.getHeadState();
247
247
  const signatureSet = getBlockHeaderProposerSignatureSetByHeaderSlot(
248
+ chain.config,
248
249
  chain.index2pubkey,
249
- headState,
250
250
  firstSidecarSignedBlockHeader
251
251
  );
252
252
 
@@ -6,6 +6,7 @@ import {
6
6
  computeTimeAtSlot,
7
7
  getBlockProposerSignatureSet,
8
8
  isExecutionBlockBodyType,
9
+ isExecutionEnabled,
9
10
  isExecutionStateType,
10
11
  } from "@lodestar/state-transition";
11
12
  import {SignedBeaconBlock, deneb} from "@lodestar/types";
@@ -133,13 +134,16 @@ export async function validateGossipBlock(
133
134
  throw new BlockGossipError(GossipAction.IGNORE, {code: BlockErrorCode.PARENT_UNKNOWN, parentRoot});
134
135
  });
135
136
 
137
+ // in forky condition, make sure to populate ShufflingCache with regened state
138
+ chain.shufflingCache.processState(blockState);
139
+
136
140
  // Extra conditions for merge fork blocks
137
141
  // [REJECT] The block's execution payload timestamp is correct with respect to the slot
138
142
  // -- i.e. execution_payload.timestamp == compute_timestamp_at_slot(state, block.slot).
139
143
  if (fork === ForkName.bellatrix) {
140
144
  if (!isExecutionBlockBodyType(block.body)) throw Error("Not merge block type");
141
145
  const executionPayload = block.body.executionPayload;
142
- if (isExecutionStateType(blockState)) {
146
+ if (isExecutionStateType(blockState) && isExecutionEnabled(blockState, block)) {
143
147
  const expectedTimestamp = computeTimeAtSlot(config, blockSlot, chain.genesisTime);
144
148
  if (executionPayload.timestamp !== computeTimeAtSlot(config, blockSlot, chain.genesisTime)) {
145
149
  throw new BlockGossipError(GossipAction.REJECT, {
@@ -153,7 +157,7 @@ export async function validateGossipBlock(
153
157
 
154
158
  // [REJECT] The proposer signature, signed_beacon_block.signature, is valid with respect to the proposer_index pubkey.
155
159
  if (!chain.seenBlockInputCache.isVerifiedProposerSignature(blockSlot, blockRoot, signedBlock.signature)) {
156
- const signatureSet = getBlockProposerSignatureSet(chain.config, chain.index2pubkey, blockState, signedBlock);
160
+ const signatureSet = getBlockProposerSignatureSet(chain.config, chain.index2pubkey, signedBlock);
157
161
  // Don't batch so verification is not delayed
158
162
  if (!(await chain.bls.verifySignatureSets([signatureSet], {verifyOnMainThread: true}))) {
159
163
  throw new BlockGossipError(GossipAction.REJECT, {
@@ -1,8 +1,4 @@
1
- import {
2
- CachedBeaconStateCapella,
3
- getBlsToExecutionChangeSignatureSet,
4
- isValidBlsToExecutionChange,
5
- } from "@lodestar/state-transition";
1
+ import {getBlsToExecutionChangeSignatureSet, isValidBlsToExecutionChange} from "@lodestar/state-transition";
6
2
  import {capella} from "@lodestar/types";
7
3
  import {BlsToExecutionChangeError, BlsToExecutionChangeErrorCode, GossipAction} from "../errors/index.js";
8
4
  import {IBeaconChain} from "../index.js";
@@ -42,10 +38,16 @@ async function validateBlsToExecutionChange(
42
38
  // and chanes relevant to `isValidBlsToExecutionChange()` happen only on processBlock(), not processEpoch()
43
39
  const state = chain.getHeadState();
44
40
  const {config} = chain;
45
-
41
+ const addressChange = blsToExecutionChange.message;
42
+ if (addressChange.validatorIndex >= state.validators.length) {
43
+ throw new BlsToExecutionChangeError(GossipAction.REJECT, {
44
+ code: BlsToExecutionChangeErrorCode.INVALID,
45
+ });
46
+ }
47
+ const validator = state.validators.getReadonly(addressChange.validatorIndex);
46
48
  // [REJECT] All of the conditions within process_bls_to_execution_change pass validation.
47
49
  // verifySignature = false, verified in batch below
48
- const {valid} = isValidBlsToExecutionChange(state as CachedBeaconStateCapella, blsToExecutionChange, false);
50
+ const {valid} = isValidBlsToExecutionChange(config, validator, blsToExecutionChange, false);
49
51
  if (!valid) {
50
52
  throw new BlsToExecutionChangeError(GossipAction.REJECT, {
51
53
  code: BlsToExecutionChangeErrorCode.INVALID,
@@ -135,8 +135,9 @@ export async function validateGossipDataColumnSidecar(
135
135
  const signature = dataColumnSidecar.signedBlockHeader.signature;
136
136
  if (!chain.seenBlockInputCache.isVerifiedProposerSignature(blockHeader.slot, blockRootHex, signature)) {
137
137
  const signatureSet = getBlockHeaderProposerSignatureSetByParentStateSlot(
138
+ chain.config,
138
139
  chain.index2pubkey,
139
- blockState,
140
+ blockState.slot,
140
141
  dataColumnSidecar.signedBlockHeader
141
142
  );
142
143
 
@@ -336,10 +337,9 @@ export async function validateBlockDataColumnSidecars(
336
337
  const slot = firstSidecarSignedBlockHeader.message.slot;
337
338
  const signature = firstSidecarSignedBlockHeader.signature;
338
339
  if (!chain.seenBlockInputCache.isVerifiedProposerSignature(slot, rootHex, signature)) {
339
- const headState = await chain.getHeadState();
340
340
  const signatureSet = getBlockHeaderProposerSignatureSetByHeaderSlot(
341
+ chain.config,
341
342
  chain.index2pubkey,
342
- headState,
343
343
  firstSidecarSignedBlockHeader
344
344
  );
345
345
 
@@ -35,8 +35,9 @@ async function validateProposerSlashing(
35
35
 
36
36
  // [REJECT] All of the conditions within process_proposer_slashing pass validation.
37
37
  try {
38
+ const proposer = state.validators.getReadonly(proposerSlashing.signedHeader1.message.proposerIndex);
38
39
  // verifySignature = false, verified in batch below
39
- assertValidProposerSlashing(state, proposerSlashing, false);
40
+ assertValidProposerSlashing(chain.config, chain.index2pubkey, state.slot, proposerSlashing, proposer, false);
40
41
  } catch (e) {
41
42
  throw new ProposerSlashingError(GossipAction.REJECT, {
42
43
  code: ProposerSlashingErrorCode.INVALID,
@@ -44,7 +45,12 @@ async function validateProposerSlashing(
44
45
  });
45
46
  }
46
47
 
47
- const signatureSets = getProposerSlashingSignatureSets(chain.config, chain.index2pubkey, state, proposerSlashing);
48
+ const signatureSets = getProposerSlashingSignatureSets(
49
+ chain.config,
50
+ chain.index2pubkey,
51
+ state.slot,
52
+ proposerSlashing
53
+ );
48
54
  if (!(await chain.bls.verifySignatureSets(signatureSets, {batchable: true, priority: prioritizeBls}))) {
49
55
  throw new ProposerSlashingError(GossipAction.REJECT, {
50
56
  code: ProposerSlashingErrorCode.INVALID,