@lodestar/state-transition 1.41.0-dev.eb7efb2b90 → 1.41.0-dev.f225223000

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 (128) hide show
  1. package/lib/block/isValidIndexedAttestation.d.ts +3 -3
  2. package/lib/block/isValidIndexedAttestation.d.ts.map +1 -1
  3. package/lib/block/isValidIndexedAttestation.js +4 -4
  4. package/lib/block/isValidIndexedAttestation.js.map +1 -1
  5. package/lib/block/isValidIndexedPayloadAttestation.js +1 -1
  6. package/lib/block/isValidIndexedPayloadAttestation.js.map +1 -1
  7. package/lib/block/processAttestationPhase0.js +1 -1
  8. package/lib/block/processAttestationPhase0.js.map +1 -1
  9. package/lib/block/processAttestationsAltair.js +1 -1
  10. package/lib/block/processAttestationsAltair.js.map +1 -1
  11. package/lib/block/processAttesterSlashing.d.ts +2 -2
  12. package/lib/block/processAttesterSlashing.d.ts.map +1 -1
  13. package/lib/block/processAttesterSlashing.js +3 -3
  14. package/lib/block/processAttesterSlashing.js.map +1 -1
  15. package/lib/block/processExecutionPayloadEnvelope.js +5 -1
  16. package/lib/block/processExecutionPayloadEnvelope.js.map +1 -1
  17. package/lib/block/processProposerSlashing.d.ts +2 -2
  18. package/lib/block/processProposerSlashing.d.ts.map +1 -1
  19. package/lib/block/processProposerSlashing.js +3 -3
  20. package/lib/block/processProposerSlashing.js.map +1 -1
  21. package/lib/block/processRandao.js +1 -1
  22. package/lib/block/processRandao.js.map +1 -1
  23. package/lib/block/processSyncCommittee.js +1 -1
  24. package/lib/block/processSyncCommittee.js.map +1 -1
  25. package/lib/block/processVoluntaryExit.js +1 -1
  26. package/lib/block/processVoluntaryExit.js.map +1 -1
  27. package/lib/block/processWithdrawalRequest.js +2 -2
  28. package/lib/block/processWithdrawalRequest.js.map +1 -1
  29. package/lib/cache/epochCache.d.ts +6 -15
  30. package/lib/cache/epochCache.d.ts.map +1 -1
  31. package/lib/cache/epochCache.js +15 -28
  32. package/lib/cache/epochCache.js.map +1 -1
  33. package/lib/cache/pubkeyCache.d.ts +21 -6
  34. package/lib/cache/pubkeyCache.d.ts.map +1 -1
  35. package/lib/cache/pubkeyCache.js +39 -14
  36. package/lib/cache/pubkeyCache.js.map +1 -1
  37. package/lib/cache/stateCache.d.ts +1 -1
  38. package/lib/cache/stateCache.d.ts.map +1 -1
  39. package/lib/cache/stateCache.js +3 -7
  40. package/lib/cache/stateCache.js.map +1 -1
  41. package/lib/cache/syncCommitteeCache.d.ts +3 -2
  42. package/lib/cache/syncCommitteeCache.d.ts.map +1 -1
  43. package/lib/cache/syncCommitteeCache.js +4 -4
  44. package/lib/cache/syncCommitteeCache.js.map +1 -1
  45. package/lib/index.d.ts +3 -1
  46. package/lib/index.d.ts.map +1 -1
  47. package/lib/index.js +2 -1
  48. package/lib/index.js.map +1 -1
  49. package/lib/lightClient/proofs.d.ts +10 -0
  50. package/lib/lightClient/proofs.d.ts.map +1 -0
  51. package/lib/lightClient/proofs.js +63 -0
  52. package/lib/lightClient/proofs.js.map +1 -0
  53. package/lib/lightClient/types.d.ts +34 -0
  54. package/lib/lightClient/types.d.ts.map +1 -0
  55. package/lib/lightClient/types.js +2 -0
  56. package/lib/lightClient/types.js.map +1 -0
  57. package/lib/rewards/attestationsRewards.d.ts +2 -2
  58. package/lib/rewards/attestationsRewards.d.ts.map +1 -1
  59. package/lib/rewards/attestationsRewards.js +4 -4
  60. package/lib/rewards/attestationsRewards.js.map +1 -1
  61. package/lib/rewards/syncCommitteeRewards.d.ts +2 -2
  62. package/lib/rewards/syncCommitteeRewards.d.ts.map +1 -1
  63. package/lib/rewards/syncCommitteeRewards.js +5 -2
  64. package/lib/rewards/syncCommitteeRewards.js.map +1 -1
  65. package/lib/signatureSets/proposer.d.ts +2 -2
  66. package/lib/signatureSets/proposer.d.ts.map +1 -1
  67. package/lib/signatureSets/proposer.js +2 -2
  68. package/lib/signatureSets/proposer.js.map +1 -1
  69. package/lib/signatureSets/randao.d.ts +2 -2
  70. package/lib/signatureSets/randao.d.ts.map +1 -1
  71. package/lib/signatureSets/randao.js +2 -2
  72. package/lib/signatureSets/randao.js.map +1 -1
  73. package/lib/signatureSets/voluntaryExits.d.ts +2 -2
  74. package/lib/signatureSets/voluntaryExits.d.ts.map +1 -1
  75. package/lib/signatureSets/voluntaryExits.js +2 -2
  76. package/lib/signatureSets/voluntaryExits.js.map +1 -1
  77. package/lib/stateTransition.d.ts +2 -1
  78. package/lib/stateTransition.d.ts.map +1 -1
  79. package/lib/stateTransition.js +2 -1
  80. package/lib/stateTransition.js.map +1 -1
  81. package/lib/stateView/beaconStateView.d.ts +144 -0
  82. package/lib/stateView/beaconStateView.d.ts.map +1 -0
  83. package/lib/stateView/beaconStateView.js +496 -0
  84. package/lib/stateView/beaconStateView.js.map +1 -0
  85. package/lib/stateView/index.d.ts +3 -0
  86. package/lib/stateView/index.d.ts.map +1 -0
  87. package/lib/stateView/index.js +3 -0
  88. package/lib/stateView/index.js.map +1 -0
  89. package/lib/stateView/interface.d.ts +118 -0
  90. package/lib/stateView/interface.d.ts.map +1 -0
  91. package/lib/stateView/interface.js +2 -0
  92. package/lib/stateView/interface.js.map +1 -0
  93. package/lib/util/signatureSets.d.ts +7 -7
  94. package/lib/util/signatureSets.d.ts.map +1 -1
  95. package/lib/util/signatureSets.js +18 -12
  96. package/lib/util/signatureSets.js.map +1 -1
  97. package/lib/util/weakSubjectivity.js +1 -1
  98. package/lib/util/weakSubjectivity.js.map +1 -1
  99. package/package.json +7 -7
  100. package/src/block/isValidIndexedAttestation.ts +5 -5
  101. package/src/block/isValidIndexedPayloadAttestation.ts +1 -1
  102. package/src/block/processAttestationPhase0.ts +1 -1
  103. package/src/block/processAttestationsAltair.ts +1 -1
  104. package/src/block/processAttesterSlashing.ts +4 -4
  105. package/src/block/processExecutionPayloadEnvelope.ts +5 -1
  106. package/src/block/processProposerSlashing.ts +4 -4
  107. package/src/block/processRandao.ts +1 -1
  108. package/src/block/processSyncCommittee.ts +1 -1
  109. package/src/block/processVoluntaryExit.ts +1 -1
  110. package/src/block/processWithdrawalRequest.ts +2 -2
  111. package/src/cache/epochCache.ts +17 -31
  112. package/src/cache/pubkeyCache.ts +62 -21
  113. package/src/cache/stateCache.ts +4 -8
  114. package/src/cache/syncCommitteeCache.ts +4 -5
  115. package/src/index.ts +3 -1
  116. package/src/lightClient/proofs.ts +83 -0
  117. package/src/lightClient/types.ts +33 -0
  118. package/src/rewards/attestationsRewards.ts +5 -5
  119. package/src/rewards/syncCommitteeRewards.ts +6 -5
  120. package/src/signatureSets/proposer.ts +3 -3
  121. package/src/signatureSets/randao.ts +3 -7
  122. package/src/signatureSets/voluntaryExits.ts +3 -3
  123. package/src/stateTransition.ts +2 -1
  124. package/src/stateView/beaconStateView.ts +744 -0
  125. package/src/stateView/index.ts +2 -0
  126. package/src/stateView/interface.ts +196 -0
  127. package/src/util/signatureSets.ts +23 -17
  128. package/src/util/weakSubjectivity.ts +1 -1
@@ -1,33 +1,74 @@
1
1
  import {PublicKey} from "@chainsafe/blst";
2
2
  import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
3
- import {phase0} from "@lodestar/types";
3
+ import {ValidatorIndex, phase0} from "@lodestar/types";
4
4
 
5
- export type Index2PubkeyCache = PublicKey[];
5
+ /**
6
+ * Unified pubkey cache coupling index→pubkey and pubkey→index lookups.
7
+ * Both directions are kept in sync atomically via `set()`.
8
+ */
9
+ export interface PubkeyCache {
10
+ /** Get deserialized PublicKey by validator index */
11
+ get(index: ValidatorIndex): PublicKey | undefined;
12
+ /** Get deserialized PublicKey by validator index or throw if not found */
13
+ getOrThrow(index: ValidatorIndex): PublicKey;
14
+ /** Get validator index by pubkey bytes */
15
+ getIndex(pubkey: Uint8Array): ValidatorIndex | null;
16
+ /** Set both directions atomically. Takes raw pubkey bytes — deserialization is handled internally. */
17
+ set(index: ValidatorIndex, pubkey: Uint8Array): void;
18
+ /** Number of entries */
19
+ readonly size: number;
20
+ }
21
+
22
+ class StandardPubkeyCache implements PubkeyCache {
23
+ private readonly pubkey2index: PubkeyIndexMap;
24
+ private readonly index2pubkey: (PublicKey | undefined)[];
25
+
26
+ constructor(pubkey2index?: PubkeyIndexMap, index2pubkey?: (PublicKey | undefined)[]) {
27
+ this.pubkey2index = pubkey2index ?? new PubkeyIndexMap();
28
+ this.index2pubkey = index2pubkey ?? [];
29
+ }
30
+
31
+ get size(): number {
32
+ return this.pubkey2index.size;
33
+ }
34
+
35
+ get(index: ValidatorIndex): PublicKey | undefined {
36
+ return this.index2pubkey[index];
37
+ }
38
+
39
+ getOrThrow(index: ValidatorIndex): PublicKey {
40
+ const pubkey = this.get(index);
41
+ if (!pubkey) throw Error(`Missing pubkey for validator index ${index}`);
42
+ return pubkey;
43
+ }
44
+
45
+ getIndex(pubkey: Uint8Array): ValidatorIndex | null {
46
+ return this.pubkey2index.get(pubkey);
47
+ }
48
+
49
+ set(index: ValidatorIndex, pubkey: Uint8Array): void {
50
+ this.pubkey2index.set(pubkey, index);
51
+ // Pubkeys must be checked for group + inf. This must be done only once when the validator deposit is processed.
52
+ // Afterwards any public key in the state is considered validated.
53
+ // > Do not do any validation here
54
+ this.index2pubkey[index] = PublicKey.fromBytes(pubkey); // Optimize for aggregation
55
+ }
56
+ }
57
+
58
+ export function createPubkeyCache(): PubkeyCache {
59
+ return new StandardPubkeyCache();
60
+ }
6
61
 
7
62
  /**
8
63
  * Checks the pubkey indices against a state and adds missing pubkeys
9
64
  *
10
- * Mutates `pubkey2index` and `index2pubkey`
65
+ * Mutates `pubkeyCache`
11
66
  *
12
- * If pubkey caches are empty: SLOW CODE - 🐢
67
+ * If pubkey cache is empty: SLOW CODE - 🐢
13
68
  */
14
- export function syncPubkeys(
15
- validators: phase0.Validator[],
16
- pubkey2index: PubkeyIndexMap,
17
- index2pubkey: Index2PubkeyCache
18
- ): void {
19
- if (pubkey2index.size !== index2pubkey.length) {
20
- throw new Error(`Pubkey indices have fallen out of sync: ${pubkey2index.size} != ${index2pubkey.length}`);
21
- }
22
-
69
+ export function syncPubkeys(pubkeyCache: PubkeyCache, validators: phase0.Validator[]): void {
23
70
  const newCount = validators.length;
24
- index2pubkey.length = newCount;
25
- for (let i = pubkey2index.size; i < newCount; i++) {
26
- const pubkey = validators[i].pubkey;
27
- pubkey2index.set(pubkey, i);
28
- // Pubkeys must be checked for group + inf. This must be done only once when the validator deposit is processed.
29
- // Afterwards any public key is the state consider validated.
30
- // > Do not do any validation here
31
- index2pubkey[i] = PublicKey.fromBytes(pubkey); // Optimize for aggregation
71
+ for (let i = pubkeyCache.size; i < newCount; i++) {
72
+ pubkeyCache.set(i, validators[i].pubkey);
32
73
  }
33
74
  }
@@ -1,4 +1,3 @@
1
- import {PublicKey} from "@chainsafe/blst";
2
1
  import {BeaconConfig} from "@lodestar/config";
3
2
  import {loadState} from "../util/loadState/loadState.js";
4
3
  import {EpochCache, EpochCacheImmutableData, EpochCacheOpts} from "./epochCache.js";
@@ -168,7 +167,7 @@ export function createCachedBeaconState<T extends BeaconStateAllForks>(
168
167
  * Check loadState() api for more details
169
168
  * // TODO: rename to loadUnfinalizedCachedBeaconState() due to ELECTRA
170
169
  */
171
- export function loadCachedBeaconState<T extends BeaconStateAllForks & BeaconStateCache>(
170
+ export function loadCachedBeaconState<T extends CachedBeaconStateAllForks>(
172
171
  cachedSeedState: T,
173
172
  stateBytes: Uint8Array,
174
173
  opts?: EpochCacheOpts,
@@ -180,22 +179,19 @@ export function loadCachedBeaconState<T extends BeaconStateAllForks & BeaconStat
180
179
  stateBytes,
181
180
  seedValidatorsBytes
182
181
  );
183
- const {pubkey2index, index2pubkey} = cachedSeedState.epochCtx;
182
+ const {pubkeyCache} = cachedSeedState.epochCtx;
184
183
  // Get the validators sub tree once for all the loop
185
184
  const validators = migratedState.validators;
186
185
  for (const validatorIndex of modifiedValidators) {
187
186
  const validator = validators.getReadonly(validatorIndex);
188
- const pubkey = validator.pubkey;
189
- pubkey2index.set(pubkey, validatorIndex);
190
- index2pubkey[validatorIndex] = PublicKey.fromBytes(pubkey);
187
+ pubkeyCache.set(validatorIndex, validator.pubkey);
191
188
  }
192
189
 
193
190
  return createCachedBeaconState(
194
191
  migratedState,
195
192
  {
196
193
  config: cachedSeedState.config,
197
- pubkey2index,
198
- index2pubkey,
194
+ pubkeyCache,
199
195
  },
200
196
  {...(opts ?? {}), ...{skipSyncPubkeys: true}}
201
197
  ) as T;
@@ -1,4 +1,3 @@
1
- import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
2
1
  import {CompositeViewDU} from "@chainsafe/ssz";
3
2
  import {ValidatorIndex, ssz} from "@lodestar/types";
4
3
  import {toPubkeyHex} from "@lodestar/utils";
@@ -39,9 +38,9 @@ export function getSyncCommitteeCache(validatorIndices: Uint32Array): SyncCommit
39
38
 
40
39
  export function computeSyncCommitteeCache(
41
40
  syncCommittee: CompositeViewDU<typeof ssz.altair.SyncCommittee>,
42
- pubkey2index: PubkeyIndexMap
41
+ pubkeyCache: {getIndex(pubkey: Uint8Array): number | null}
43
42
  ): SyncCommitteeCache {
44
- const validatorIndices = computeSyncCommitteeValidatorIndices(syncCommittee, pubkey2index);
43
+ const validatorIndices = computeSyncCommitteeValidatorIndices(syncCommittee, pubkeyCache);
45
44
  const validatorIndexMap = computeValidatorSyncCommitteeIndexMap(validatorIndices);
46
45
  return {
47
46
  validatorIndices,
@@ -79,12 +78,12 @@ export function computeValidatorSyncCommitteeIndexMap(
79
78
  */
80
79
  function computeSyncCommitteeValidatorIndices(
81
80
  syncCommittee: CompositeViewDU<typeof ssz.altair.SyncCommittee>,
82
- pubkey2index: PubkeyIndexMap
81
+ pubkeyCache: {getIndex(pubkey: Uint8Array): number | null}
83
82
  ): Uint32Array {
84
83
  const pubkeys = syncCommittee.pubkeys.getAllReadonly();
85
84
  const validatorIndices = new Uint32Array(pubkeys.length);
86
85
  for (const [i, pubkey] of pubkeys.entries()) {
87
- const validatorIndex = pubkey2index.get(pubkey);
86
+ const validatorIndex = pubkeyCache.getIndex(pubkey);
88
87
  if (validatorIndex === null) {
89
88
  throw Error(`SyncCommittee pubkey is unknown ${toPubkeyHex(pubkey)}`);
90
89
  }
package/src/index.ts CHANGED
@@ -25,7 +25,7 @@ export {
25
25
  createEmptyEpochCacheImmutableData,
26
26
  } from "./cache/epochCache.js";
27
27
  export {type EpochTransitionCache, beforeProcessEpoch} from "./cache/epochTransitionCache.js";
28
- export {type Index2PubkeyCache, syncPubkeys} from "./cache/pubkeyCache.js";
28
+ export {type PubkeyCache, createPubkeyCache, syncPubkeys} from "./cache/pubkeyCache.js";
29
29
  // Main state caches
30
30
  export {
31
31
  type BeaconStateCache,
@@ -35,12 +35,14 @@ export {
35
35
  isStateValidatorsNodesPopulated,
36
36
  loadCachedBeaconState,
37
37
  } from "./cache/stateCache.js";
38
+ export {type SyncCommitteeCache} from "./cache/syncCommitteeCache.js";
38
39
  export * from "./constants/index.js";
39
40
  export type {EpochTransitionStep} from "./epoch/index.js";
40
41
  export {type BeaconStateTransitionMetrics, getMetrics} from "./metrics.js";
41
42
  export * from "./rewards/index.js";
42
43
  export * from "./signatureSets/index.js";
43
44
  export * from "./stateTransition.js";
45
+ export * from "./stateView/index.js";
44
46
  export type {
45
47
  BeaconStateAllForks,
46
48
  BeaconStateAltair,
@@ -0,0 +1,83 @@
1
+ import {Tree} from "@chainsafe/persistent-merkle-tree";
2
+ import {
3
+ BLOCK_BODY_EXECUTION_PAYLOAD_GINDEX,
4
+ FINALIZED_ROOT_GINDEX,
5
+ FINALIZED_ROOT_GINDEX_ELECTRA,
6
+ ForkName,
7
+ ForkPostBellatrix,
8
+ isForkPostElectra,
9
+ } from "@lodestar/params";
10
+ import {BeaconBlockBody, SSZTypesFor, ssz} from "@lodestar/types";
11
+ import {BeaconStateAllForks, CachedBeaconStateAllForks} from "../types.js";
12
+ import {SyncCommitteeWitness} from "./types.js";
13
+
14
+ export function getSyncCommitteesWitness(fork: ForkName, state: BeaconStateAllForks): SyncCommitteeWitness {
15
+ const n1 = state.node;
16
+ let witness: Uint8Array[];
17
+ let currentSyncCommitteeRoot: Uint8Array;
18
+ let nextSyncCommitteeRoot: Uint8Array;
19
+
20
+ if (isForkPostElectra(fork)) {
21
+ const n2 = n1.left;
22
+ const n5 = n2.right;
23
+ const n10 = n5.left;
24
+ const n21 = n10.right;
25
+ const n43 = n21.right;
26
+
27
+ currentSyncCommitteeRoot = n43.left.root; // n86
28
+ nextSyncCommitteeRoot = n43.right.root; // n87
29
+
30
+ // Witness branch is sorted by descending gindex
31
+ witness = [
32
+ n21.left.root, // 42
33
+ n10.left.root, // 20
34
+ n5.right.root, // 11
35
+ n2.left.root, // 4
36
+ n1.right.root, // 3
37
+ ];
38
+ } else {
39
+ const n3 = n1.right; // [1]0110
40
+ const n6 = n3.left; // 1[0]110
41
+ const n13 = n6.right; // 10[1]10
42
+ const n27 = n13.right; // 101[1]0
43
+ currentSyncCommitteeRoot = n27.left.root; // n54 1011[0]
44
+ nextSyncCommitteeRoot = n27.right.root; // n55 1011[1]
45
+
46
+ // Witness branch is sorted by descending gindex
47
+ witness = [
48
+ n13.left.root, // 26
49
+ n6.left.root, // 12
50
+ n3.right.root, // 7
51
+ n1.left.root, // 2
52
+ ];
53
+ }
54
+
55
+ return {
56
+ witness,
57
+ currentSyncCommitteeRoot,
58
+ nextSyncCommitteeRoot,
59
+ };
60
+ }
61
+
62
+ export function getNextSyncCommitteeBranch(syncCommitteesWitness: SyncCommitteeWitness): Uint8Array[] {
63
+ // Witness branch is sorted by descending gindex
64
+ return [syncCommitteesWitness.currentSyncCommitteeRoot, ...syncCommitteesWitness.witness];
65
+ }
66
+
67
+ export function getCurrentSyncCommitteeBranch(syncCommitteesWitness: SyncCommitteeWitness): Uint8Array[] {
68
+ // Witness branch is sorted by descending gindex
69
+ return [syncCommitteesWitness.nextSyncCommitteeRoot, ...syncCommitteesWitness.witness];
70
+ }
71
+
72
+ export function getFinalizedRootProof(state: CachedBeaconStateAllForks): Uint8Array[] {
73
+ const finalizedRootGindex = state.epochCtx.isPostElectra() ? FINALIZED_ROOT_GINDEX_ELECTRA : FINALIZED_ROOT_GINDEX;
74
+ return new Tree(state.node).getSingleProof(BigInt(finalizedRootGindex));
75
+ }
76
+
77
+ export function getBlockBodyExecutionHeaderProof(
78
+ fork: ForkPostBellatrix,
79
+ body: BeaconBlockBody<ForkPostBellatrix>
80
+ ): Uint8Array[] {
81
+ const bodyView = (ssz[fork].BeaconBlockBody as SSZTypesFor<ForkPostBellatrix, "BeaconBlockBody">).toView(body);
82
+ return new Tree(bodyView.node).getSingleProof(BigInt(BLOCK_BODY_EXECUTION_PAYLOAD_GINDEX));
83
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * We aren't creating the sync committee proofs separately because our ssz library automatically adds leaves to composite types,
3
+ * so they're already included in the state proof, currently with no way to specify otherwise
4
+ *
5
+ * remove two offsets so the # of offsets in the state proof will be the # expected
6
+ * This is a hack, but properly setting the offsets in the state proof would require either removing witnesses needed for the committees
7
+ * or setting the roots of the committees in the state proof
8
+ * this will always be 1, syncProofLeavesLength
9
+ *
10
+ *
11
+ * With empty state (minimal)
12
+ * - `genesisTime = 0xffffffff`
13
+ * - `genesisValidatorsRoot = Buffer.alloc(32, 1)`
14
+ *
15
+ * Proof:
16
+ * ```
17
+ * offsets: [ 5, 4, 3, 2, 1 ]
18
+ * leaves: [
19
+ * '0xffffffff00000000000000000000000000000000000000000000000000000000',
20
+ * '0x0101010101010101010101010101010101010101010101010101010101010101',
21
+ * '0xb11b8bcf59425d6c99019cca1d2c2e47b51a2f74917a67ad132274f43e13ec43',
22
+ * '0x74bd1f2437cdf74b0904ee525d8da070a3fa27570942bf42cbab3dc5939600f0',
23
+ * '0x7f06739e5a42360c56e519a511675901c95402ea9877edc0d9a87471b1374a6a',
24
+ * '0x9f534204ba3c0b69fcb42a11987bfcbc5aea0463e5b0614312ded4b62cf3a380'
25
+ * ]
26
+ * ```
27
+ */
28
+ export type SyncCommitteeWitness = {
29
+ /** Vector[Bytes32, 4] or Vector[Bytes32, 5] depending on the fork */
30
+ witness: Uint8Array[];
31
+ currentSyncCommitteeRoot: Uint8Array;
32
+ nextSyncCommitteeRoot: Uint8Array;
33
+ };
@@ -1,4 +1,3 @@
1
- import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
2
1
  import {BeaconConfig} from "@lodestar/config";
3
2
  import {
4
3
  EFFECTIVE_BALANCE_INCREMENT,
@@ -16,6 +15,7 @@ import {
16
15
  import {ValidatorIndex, rewards} from "@lodestar/types";
17
16
  import {fromHex} from "@lodestar/utils";
18
17
  import {EpochTransitionCache, beforeProcessEpoch} from "../cache/epochTransitionCache.js";
18
+ import {PubkeyCache} from "../cache/pubkeyCache.js";
19
19
  import {CachedBeaconStateAllForks, CachedBeaconStateAltair} from "../types.js";
20
20
  import {
21
21
  FLAG_ELIGIBLE_ATTESTER,
@@ -34,7 +34,7 @@ const defaultAttestationsPenalty = {target: 0, source: 0};
34
34
 
35
35
  export async function computeAttestationsRewards(
36
36
  config: BeaconConfig,
37
- pubkey2index: PubkeyIndexMap,
37
+ pubkeyCache: PubkeyCache,
38
38
  state: CachedBeaconStateAllForks,
39
39
  validatorIds?: (ValidatorIndex | string)[]
40
40
  ): Promise<rewards.AttestationsRewards> {
@@ -53,7 +53,7 @@ export async function computeAttestationsRewards(
53
53
  );
54
54
  const totalRewards = computeTotalAttestationsRewardsAltair(
55
55
  config,
56
- pubkey2index,
56
+ pubkeyCache,
57
57
  stateAltair,
58
58
  transitionCache,
59
59
  idealRewards,
@@ -142,7 +142,7 @@ function computeIdealAttestationsRewardsAndPenaltiesAltair(
142
142
  // Same calculation as `getRewardsAndPenaltiesAltair` but returns the breakdown of rewards instead of aggregated
143
143
  function computeTotalAttestationsRewardsAltair(
144
144
  config: BeaconConfig,
145
- pubkey2index: PubkeyIndexMap,
145
+ pubkeyCache: PubkeyCache,
146
146
  state: CachedBeaconStateAltair,
147
147
  transitionCache: EpochTransitionCache,
148
148
  idealRewards: rewards.IdealAttestationsReward[],
@@ -153,7 +153,7 @@ function computeTotalAttestationsRewardsAltair(
153
153
  const {flags} = transitionCache;
154
154
  const {epochCtx} = state;
155
155
  const validatorIndices = validatorIds
156
- .map((id) => (typeof id === "number" ? id : pubkey2index.get(fromHex(id))))
156
+ .map((id) => (typeof id === "number" ? id : pubkeyCache.getIndex(fromHex(id))))
157
157
  .filter((index) => index !== undefined); // Validator indices to include in the result
158
158
 
159
159
  const inactivityPenaltyDenominator = config.INACTIVITY_SCORE_BIAS * INACTIVITY_PENALTY_QUOTIENT_ALTAIR;
@@ -1,12 +1,12 @@
1
1
  import {BeaconConfig} from "@lodestar/config";
2
2
  import {ForkName, SYNC_COMMITTEE_SIZE} from "@lodestar/params";
3
3
  import {BeaconBlock, ValidatorIndex, altair, rewards} from "@lodestar/types";
4
- import {Index2PubkeyCache} from "../cache/pubkeyCache.js";
4
+ import {PubkeyCache} from "../cache/pubkeyCache.js";
5
5
  import {CachedBeaconStateAllForks, CachedBeaconStateAltair} from "../cache/stateCache.js";
6
6
 
7
7
  export async function computeSyncCommitteeRewards(
8
8
  config: BeaconConfig,
9
- index2pubkey: Index2PubkeyCache,
9
+ pubkeyCache: PubkeyCache,
10
10
  block: BeaconBlock,
11
11
  preState: CachedBeaconStateAllForks,
12
12
  validatorIds: (ValidatorIndex | string)[] = []
@@ -47,9 +47,10 @@ export async function computeSyncCommitteeRewards(
47
47
 
48
48
  if (validatorIds.length) {
49
49
  const filtersSet = new Set(validatorIds);
50
- return rewards.filter(
51
- (reward) => filtersSet.has(reward.validatorIndex) || filtersSet.has(index2pubkey[reward.validatorIndex].toHex())
52
- );
50
+ return rewards.filter((reward) => {
51
+ const pubkeyHex = pubkeyCache.get(reward.validatorIndex)?.toHex();
52
+ return filtersSet.has(reward.validatorIndex) || (pubkeyHex !== undefined && filtersSet.has(pubkeyHex));
53
+ });
53
54
  }
54
55
 
55
56
  return rewards;
@@ -1,17 +1,17 @@
1
1
  import {BeaconConfig} from "@lodestar/config";
2
2
  import {DOMAIN_BEACON_PROPOSER} from "@lodestar/params";
3
3
  import {SignedBeaconBlock, SignedBlindedBeaconBlock, Slot, isBlindedBeaconBlock, phase0, ssz} from "@lodestar/types";
4
- import {Index2PubkeyCache} from "../cache/pubkeyCache.js";
4
+ import {PubkeyCache} from "../cache/pubkeyCache.js";
5
5
  import {computeSigningRoot} from "../util/index.js";
6
6
  import {ISignatureSet, SignatureSetType, verifySignatureSet} from "../util/signatureSets.js";
7
7
 
8
8
  export function verifyProposerSignature(
9
9
  config: BeaconConfig,
10
- index2pubkey: Index2PubkeyCache,
10
+ pubkeyCache: PubkeyCache,
11
11
  signedBlock: SignedBeaconBlock | SignedBlindedBeaconBlock
12
12
  ): boolean {
13
13
  const signatureSet = getBlockProposerSignatureSet(config, signedBlock);
14
- return verifySignatureSet(signatureSet, index2pubkey);
14
+ return verifySignatureSet(signatureSet, pubkeyCache);
15
15
  }
16
16
 
17
17
  export function getBlockProposerSignatureSet(
@@ -1,7 +1,7 @@
1
1
  import {BeaconConfig} from "@lodestar/config";
2
2
  import {DOMAIN_RANDAO} from "@lodestar/params";
3
3
  import {BeaconBlock, ssz} from "@lodestar/types";
4
- import {Index2PubkeyCache} from "../cache/pubkeyCache.js";
4
+ import {PubkeyCache} from "../cache/pubkeyCache.js";
5
5
  import {
6
6
  ISignatureSet,
7
7
  SignatureSetType,
@@ -10,12 +10,8 @@ import {
10
10
  verifySignatureSet,
11
11
  } from "../util/index.js";
12
12
 
13
- export function verifyRandaoSignature(
14
- config: BeaconConfig,
15
- index2pubkey: Index2PubkeyCache,
16
- block: BeaconBlock
17
- ): boolean {
18
- return verifySignatureSet(getRandaoRevealSignatureSet(config, block), index2pubkey);
13
+ export function verifyRandaoSignature(config: BeaconConfig, pubkeyCache: PubkeyCache, block: BeaconBlock): boolean {
14
+ return verifySignatureSet(getRandaoRevealSignatureSet(config, block), pubkeyCache);
19
15
  }
20
16
 
21
17
  /**
@@ -1,6 +1,6 @@
1
1
  import {BeaconConfig} from "@lodestar/config";
2
2
  import {SignedBeaconBlock, Slot, phase0, ssz} from "@lodestar/types";
3
- import {Index2PubkeyCache} from "../cache/pubkeyCache.js";
3
+ import {PubkeyCache} from "../cache/pubkeyCache.js";
4
4
  import {
5
5
  ISignatureSet,
6
6
  SignatureSetType,
@@ -11,11 +11,11 @@ import {
11
11
 
12
12
  export function verifyVoluntaryExitSignature(
13
13
  config: BeaconConfig,
14
- index2pubkey: Index2PubkeyCache,
14
+ pubkeyCache: PubkeyCache,
15
15
  stateSlot: Slot,
16
16
  signedVoluntaryExit: phase0.SignedVoluntaryExit
17
17
  ): boolean {
18
- return verifySignatureSet(getVoluntaryExitSignatureSet(config, stateSlot, signedVoluntaryExit), index2pubkey);
18
+ return verifySignatureSet(getVoluntaryExitSignatureSet(config, stateSlot, signedVoluntaryExit), pubkeyCache);
19
19
  }
20
20
 
21
21
  /**
@@ -76,6 +76,7 @@ export enum StateHashTreeRootSource {
76
76
  prepareNextEpoch = "prepare_next_epoch",
77
77
  regenState = "regen_state",
78
78
  computeNewStateRoot = "compute_new_state_root",
79
+ computeEnvelopeStateRoot = "compute_envelope_state_root",
79
80
  }
80
81
 
81
82
  /**
@@ -111,7 +112,7 @@ export function stateTransition(
111
112
  postState = processSlotsWithTransientCache(postState, blockSlot, options, {metrics, validatorMonitor});
112
113
 
113
114
  // Verify proposer signature only
114
- if (verifyProposer && !verifyProposerSignature(postState.config, postState.epochCtx.index2pubkey, signedBlock)) {
115
+ if (verifyProposer && !verifyProposerSignature(postState.config, postState.epochCtx.pubkeyCache, signedBlock)) {
115
116
  throw new Error("Invalid block signature");
116
117
  }
117
118