@lodestar/state-transition 1.37.0-rc.0 → 1.38.0-dev.1ddbe5d870

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 (182) hide show
  1. package/lib/block/index.d.ts +4 -1
  2. package/lib/block/index.d.ts.map +1 -1
  3. package/lib/block/index.js +19 -8
  4. package/lib/block/index.js.map +1 -1
  5. package/lib/block/isValidIndexedAttestation.d.ts +3 -2
  6. package/lib/block/isValidIndexedAttestation.d.ts.map +1 -1
  7. package/lib/block/isValidIndexedAttestation.js +4 -4
  8. package/lib/block/isValidIndexedAttestation.js.map +1 -1
  9. package/lib/block/isValidIndexedPayloadAttestation.d.ts +4 -0
  10. package/lib/block/isValidIndexedPayloadAttestation.d.ts.map +1 -0
  11. package/lib/block/isValidIndexedPayloadAttestation.js +14 -0
  12. package/lib/block/isValidIndexedPayloadAttestation.js.map +1 -0
  13. package/lib/block/processAttestationPhase0.d.ts.map +1 -1
  14. package/lib/block/processAttestationPhase0.js +7 -2
  15. package/lib/block/processAttestationPhase0.js.map +1 -1
  16. package/lib/block/processAttestationsAltair.d.ts +3 -3
  17. package/lib/block/processAttestationsAltair.d.ts.map +1 -1
  18. package/lib/block/processAttestationsAltair.js +47 -5
  19. package/lib/block/processAttestationsAltair.js.map +1 -1
  20. package/lib/block/processAttesterSlashing.d.ts +2 -1
  21. package/lib/block/processAttesterSlashing.d.ts.map +1 -1
  22. package/lib/block/processAttesterSlashing.js +5 -4
  23. package/lib/block/processAttesterSlashing.js.map +1 -1
  24. package/lib/block/processConsolidationRequest.d.ts +3 -2
  25. package/lib/block/processConsolidationRequest.d.ts.map +1 -1
  26. package/lib/block/processConsolidationRequest.js +2 -2
  27. package/lib/block/processConsolidationRequest.js.map +1 -1
  28. package/lib/block/processDepositRequest.d.ts +2 -2
  29. package/lib/block/processDepositRequest.d.ts.map +1 -1
  30. package/lib/block/processDepositRequest.js.map +1 -1
  31. package/lib/block/processExecutionPayloadBid.d.ts +5 -0
  32. package/lib/block/processExecutionPayloadBid.d.ts.map +1 -0
  33. package/lib/block/processExecutionPayloadBid.js +89 -0
  34. package/lib/block/processExecutionPayloadBid.js.map +1 -0
  35. package/lib/block/processExecutionPayloadEnvelope.d.ts +4 -0
  36. package/lib/block/processExecutionPayloadEnvelope.d.ts.map +1 -0
  37. package/lib/block/processExecutionPayloadEnvelope.js +118 -0
  38. package/lib/block/processExecutionPayloadEnvelope.js.map +1 -0
  39. package/lib/block/processOperations.d.ts.map +1 -1
  40. package/lib/block/processOperations.js +8 -2
  41. package/lib/block/processOperations.js.map +1 -1
  42. package/lib/block/processPayloadAttestation.d.ts +4 -0
  43. package/lib/block/processPayloadAttestation.d.ts.map +1 -0
  44. package/lib/block/processPayloadAttestation.js +16 -0
  45. package/lib/block/processPayloadAttestation.js.map +1 -0
  46. package/lib/block/processProposerSlashing.d.ts.map +1 -1
  47. package/lib/block/processProposerSlashing.js +17 -2
  48. package/lib/block/processProposerSlashing.js.map +1 -1
  49. package/lib/block/processRandao.js +1 -1
  50. package/lib/block/processRandao.js.map +1 -1
  51. package/lib/block/processSyncCommittee.d.ts +2 -1
  52. package/lib/block/processSyncCommittee.d.ts.map +1 -1
  53. package/lib/block/processSyncCommittee.js +3 -4
  54. package/lib/block/processSyncCommittee.js.map +1 -1
  55. package/lib/block/processVoluntaryExit.js +2 -2
  56. package/lib/block/processVoluntaryExit.js.map +1 -1
  57. package/lib/block/processWithdrawalRequest.d.ts +2 -2
  58. package/lib/block/processWithdrawalRequest.d.ts.map +1 -1
  59. package/lib/block/processWithdrawalRequest.js +1 -1
  60. package/lib/block/processWithdrawalRequest.js.map +1 -1
  61. package/lib/block/processWithdrawals.d.ts +4 -3
  62. package/lib/block/processWithdrawals.d.ts.map +1 -1
  63. package/lib/block/processWithdrawals.js +89 -19
  64. package/lib/block/processWithdrawals.js.map +1 -1
  65. package/lib/cache/epochCache.d.ts +5 -1
  66. package/lib/cache/epochCache.d.ts.map +1 -1
  67. package/lib/cache/epochCache.js +34 -1
  68. package/lib/cache/epochCache.js.map +1 -1
  69. package/lib/epoch/index.d.ts +4 -2
  70. package/lib/epoch/index.d.ts.map +1 -1
  71. package/lib/epoch/index.js +10 -1
  72. package/lib/epoch/index.js.map +1 -1
  73. package/lib/epoch/processBuilderPendingPayments.d.ts +6 -0
  74. package/lib/epoch/processBuilderPendingPayments.d.ts.map +1 -0
  75. package/lib/epoch/processBuilderPendingPayments.js +28 -0
  76. package/lib/epoch/processBuilderPendingPayments.js.map +1 -0
  77. package/lib/index.d.ts +1 -1
  78. package/lib/index.d.ts.map +1 -1
  79. package/lib/index.js.map +1 -1
  80. package/lib/signatureSets/attesterSlashings.d.ts +4 -3
  81. package/lib/signatureSets/attesterSlashings.d.ts.map +1 -1
  82. package/lib/signatureSets/attesterSlashings.js +6 -6
  83. package/lib/signatureSets/attesterSlashings.js.map +1 -1
  84. package/lib/signatureSets/index.d.ts +4 -2
  85. package/lib/signatureSets/index.d.ts.map +1 -1
  86. package/lib/signatureSets/index.js +9 -8
  87. package/lib/signatureSets/index.js.map +1 -1
  88. package/lib/signatureSets/indexedAttestation.d.ts +4 -3
  89. package/lib/signatureSets/indexedAttestation.d.ts.map +1 -1
  90. package/lib/signatureSets/indexedAttestation.js +9 -7
  91. package/lib/signatureSets/indexedAttestation.js.map +1 -1
  92. package/lib/signatureSets/indexedPayloadAttestation.d.ts +6 -0
  93. package/lib/signatureSets/indexedPayloadAttestation.d.ts.map +1 -0
  94. package/lib/signatureSets/indexedPayloadAttestation.js +11 -0
  95. package/lib/signatureSets/indexedPayloadAttestation.js.map +1 -0
  96. package/lib/signatureSets/proposer.d.ts +5 -4
  97. package/lib/signatureSets/proposer.d.ts.map +1 -1
  98. package/lib/signatureSets/proposer.js +12 -12
  99. package/lib/signatureSets/proposer.js.map +1 -1
  100. package/lib/signatureSets/proposerSlashings.d.ts +3 -2
  101. package/lib/signatureSets/proposerSlashings.d.ts.map +1 -1
  102. package/lib/signatureSets/proposerSlashings.js +4 -5
  103. package/lib/signatureSets/proposerSlashings.js.map +1 -1
  104. package/lib/signatureSets/randao.d.ts +3 -2
  105. package/lib/signatureSets/randao.d.ts.map +1 -1
  106. package/lib/signatureSets/randao.js +4 -5
  107. package/lib/signatureSets/randao.js.map +1 -1
  108. package/lib/signatureSets/voluntaryExits.d.ts +4 -3
  109. package/lib/signatureSets/voluntaryExits.d.ts.map +1 -1
  110. package/lib/signatureSets/voluntaryExits.js +6 -7
  111. package/lib/signatureSets/voluntaryExits.js.map +1 -1
  112. package/lib/slot/index.d.ts +2 -1
  113. package/lib/slot/index.d.ts.map +1 -1
  114. package/lib/slot/index.js +6 -2
  115. package/lib/slot/index.js.map +1 -1
  116. package/lib/slot/upgradeStateToAltair.js +1 -1
  117. package/lib/slot/upgradeStateToAltair.js.map +1 -1
  118. package/lib/slot/upgradeStateToGloas.d.ts +0 -1
  119. package/lib/slot/upgradeStateToGloas.d.ts.map +1 -1
  120. package/lib/slot/upgradeStateToGloas.js +47 -5
  121. package/lib/slot/upgradeStateToGloas.js.map +1 -1
  122. package/lib/stateTransition.js +5 -4
  123. package/lib/stateTransition.js.map +1 -1
  124. package/lib/util/electra.d.ts +5 -5
  125. package/lib/util/electra.d.ts.map +1 -1
  126. package/lib/util/electra.js +2 -1
  127. package/lib/util/electra.js.map +1 -1
  128. package/lib/util/epoch.d.ts +3 -3
  129. package/lib/util/epoch.d.ts.map +1 -1
  130. package/lib/util/epoch.js.map +1 -1
  131. package/lib/util/gloas.d.ts +11 -0
  132. package/lib/util/gloas.d.ts.map +1 -0
  133. package/lib/util/gloas.js +35 -0
  134. package/lib/util/gloas.js.map +1 -0
  135. package/lib/util/seed.d.ts +5 -1
  136. package/lib/util/seed.d.ts.map +1 -1
  137. package/lib/util/seed.js +33 -1
  138. package/lib/util/seed.js.map +1 -1
  139. package/lib/util/validator.d.ts +2 -2
  140. package/lib/util/validator.d.ts.map +1 -1
  141. package/lib/util/validator.js +14 -1
  142. package/lib/util/validator.js.map +1 -1
  143. package/package.json +6 -6
  144. package/src/block/index.ts +35 -14
  145. package/src/block/isValidIndexedAttestation.ts +5 -2
  146. package/src/block/isValidIndexedPayloadAttestation.ts +23 -0
  147. package/src/block/processAttestationPhase0.ts +13 -2
  148. package/src/block/processAttestationsAltair.ts +63 -6
  149. package/src/block/processAttesterSlashing.ts +6 -3
  150. package/src/block/processConsolidationRequest.ts +6 -5
  151. package/src/block/processDepositRequest.ts +5 -2
  152. package/src/block/processExecutionPayloadBid.ts +120 -0
  153. package/src/block/processExecutionPayloadEnvelope.ts +181 -0
  154. package/src/block/processOperations.ts +16 -4
  155. package/src/block/processPayloadAttestation.ts +25 -0
  156. package/src/block/processProposerSlashing.ts +25 -4
  157. package/src/block/processRandao.ts +1 -1
  158. package/src/block/processSyncCommittee.ts +4 -3
  159. package/src/block/processVoluntaryExit.ts +2 -2
  160. package/src/block/processWithdrawalRequest.ts +4 -4
  161. package/src/block/processWithdrawals.ts +118 -27
  162. package/src/cache/epochCache.ts +58 -1
  163. package/src/epoch/index.ts +12 -0
  164. package/src/epoch/processBuilderPendingPayments.ts +31 -0
  165. package/src/index.ts +2 -0
  166. package/src/signatureSets/attesterSlashings.ts +7 -3
  167. package/src/signatureSets/index.ts +12 -7
  168. package/src/signatureSets/indexedAttestation.ts +20 -9
  169. package/src/signatureSets/indexedPayloadAttestation.ts +24 -0
  170. package/src/signatureSets/proposer.ts +13 -7
  171. package/src/signatureSets/proposerSlashings.ts +5 -3
  172. package/src/signatureSets/randao.ts +13 -5
  173. package/src/signatureSets/voluntaryExits.ts +7 -4
  174. package/src/slot/index.ts +11 -3
  175. package/src/slot/upgradeStateToAltair.ts +2 -1
  176. package/src/slot/upgradeStateToGloas.ts +49 -5
  177. package/src/stateTransition.ts +5 -5
  178. package/src/util/electra.ts +15 -6
  179. package/src/util/epoch.ts +6 -3
  180. package/src/util/gloas.ts +58 -0
  181. package/src/util/seed.ts +57 -1
  182. package/src/util/validator.ts +21 -2
@@ -24,6 +24,7 @@ import {
24
24
  SyncPeriod,
25
25
  ValidatorIndex,
26
26
  electra,
27
+ gloas,
27
28
  phase0,
28
29
  } from "@lodestar/types";
29
30
  import {LodestarError} from "@lodestar/utils";
@@ -46,6 +47,7 @@ import {
46
47
  getSeed,
47
48
  isActiveValidator,
48
49
  isAggregatorFromCommitteeLength,
50
+ naiveGetPayloadTimlinessCommitteeIndices,
49
51
  } from "../util/index.js";
50
52
  import {computeBaseRewardPerIncrement, computeSyncParticipantReward} from "../util/syncCommittee.js";
51
53
  import {sumTargetUnslashedBalanceIncrements} from "../util/targetUnslashedBalance.js";
@@ -59,7 +61,7 @@ import {
59
61
  computeSyncCommitteeCache,
60
62
  getSyncCommitteeCache,
61
63
  } from "./syncCommitteeCache.js";
62
- import {BeaconStateAllForks, BeaconStateAltair} from "./types.js";
64
+ import {BeaconStateAllForks, BeaconStateAltair, BeaconStateGloas} from "./types.js";
63
65
 
64
66
  /** `= PROPOSER_WEIGHT / (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT)` */
65
67
  export const PROPOSER_WEIGHT_FACTOR = PROPOSER_WEIGHT / (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT);
@@ -238,6 +240,10 @@ export class EpochCache {
238
240
  /** TODO: Indexed SyncCommitteeCache */
239
241
  nextSyncCommitteeIndexed: SyncCommitteeCache;
240
242
 
243
+ // TODO GLOAS: See if we need to cached PTC for prev/next epoch
244
+ // PTC for current epoch
245
+ payloadTimelinessCommittee: ValidatorIndex[][];
246
+
241
247
  // TODO: Helper stats
242
248
  syncPeriod: SyncPeriod;
243
249
 
@@ -276,6 +282,7 @@ export class EpochCache {
276
282
  previousTargetUnslashedBalanceIncrements: number;
277
283
  currentSyncCommitteeIndexed: SyncCommitteeCache;
278
284
  nextSyncCommitteeIndexed: SyncCommitteeCache;
285
+ payloadTimelinessCommittee: ValidatorIndex[][];
279
286
  epoch: Epoch;
280
287
  syncPeriod: SyncPeriod;
281
288
  }) {
@@ -307,6 +314,7 @@ export class EpochCache {
307
314
  this.previousTargetUnslashedBalanceIncrements = data.previousTargetUnslashedBalanceIncrements;
308
315
  this.currentSyncCommitteeIndexed = data.currentSyncCommitteeIndexed;
309
316
  this.nextSyncCommitteeIndexed = data.nextSyncCommitteeIndexed;
317
+ this.payloadTimelinessCommittee = data.payloadTimelinessCommittee;
310
318
  this.epoch = data.epoch;
311
319
  this.syncPeriod = data.syncPeriod;
312
320
  }
@@ -485,6 +493,17 @@ export class EpochCache {
485
493
  nextSyncCommitteeIndexed = new SyncCommitteeCacheEmpty();
486
494
  }
487
495
 
496
+ // Compute PTC for this epoch
497
+ let payloadTimelinessCommittee: ValidatorIndex[][] = [];
498
+ if (currentEpoch >= config.GLOAS_FORK_EPOCH) {
499
+ payloadTimelinessCommittee = naiveGetPayloadTimlinessCommitteeIndices(
500
+ state as BeaconStateGloas,
501
+ currentShuffling,
502
+ effectiveBalanceIncrements,
503
+ currentEpoch
504
+ );
505
+ }
506
+
488
507
  // Precompute churnLimit for efficient initiateValidatorExit() during block proposing MUST be recompute everytime the
489
508
  // active validator indices set changes in size. Validators change active status only when:
490
509
  // - validator.activation_epoch is set. Only changes in process_registry_updates() if validator can be activated. If
@@ -559,6 +578,7 @@ export class EpochCache {
559
578
  currentTargetUnslashedBalanceIncrements,
560
579
  currentSyncCommitteeIndexed,
561
580
  nextSyncCommitteeIndexed,
581
+ payloadTimelinessCommittee: payloadTimelinessCommittee,
562
582
  epoch: currentEpoch,
563
583
  syncPeriod: computeSyncPeriodAtEpoch(currentEpoch),
564
584
  });
@@ -605,6 +625,7 @@ export class EpochCache {
605
625
  currentTargetUnslashedBalanceIncrements: this.currentTargetUnslashedBalanceIncrements,
606
626
  currentSyncCommitteeIndexed: this.currentSyncCommitteeIndexed,
607
627
  nextSyncCommitteeIndexed: this.nextSyncCommitteeIndexed,
628
+ payloadTimelinessCommittee: this.payloadTimelinessCommittee,
608
629
  epoch: this.epoch,
609
630
  syncPeriod: this.syncPeriod,
610
631
  });
@@ -750,6 +771,14 @@ export class EpochCache {
750
771
  const epochAfterUpcoming = upcomingEpoch + 1;
751
772
 
752
773
  this.proposersPrevEpoch = this.proposers;
774
+ if (upcomingEpoch >= this.config.GLOAS_FORK_EPOCH) {
775
+ this.payloadTimelinessCommittee = naiveGetPayloadTimlinessCommitteeIndices(
776
+ state as BeaconStateGloas,
777
+ this.currentShuffling,
778
+ this.effectiveBalanceIncrements,
779
+ upcomingEpoch
780
+ );
781
+ }
753
782
  if (upcomingEpoch >= this.config.FULU_FORK_EPOCH) {
754
783
  // Populate proposer cache with lookahead from state
755
784
  const proposerLookahead = (state as CachedBeaconStateFulu).proposerLookahead.getAll();
@@ -1151,6 +1180,34 @@ export class EpochCache {
1151
1180
  isPostElectra(): boolean {
1152
1181
  return this.epoch >= this.config.ELECTRA_FORK_EPOCH;
1153
1182
  }
1183
+
1184
+ getPayloadTimelinessCommittee(slot: Slot): ValidatorIndex[] {
1185
+ const epoch = computeEpochAtSlot(slot);
1186
+
1187
+ if (epoch < this.config.GLOAS_FORK_EPOCH) {
1188
+ throw new Error("Payload Timeliness Committee is not available before gloas fork");
1189
+ }
1190
+
1191
+ if (epoch === this.epoch) {
1192
+ return this.payloadTimelinessCommittee[slot % SLOTS_PER_EPOCH];
1193
+ }
1194
+
1195
+ throw new Error(`Payload Timeliness Committee is not available for slot=${slot}`);
1196
+ }
1197
+
1198
+ getIndexedPayloadAttestation(
1199
+ slot: Slot,
1200
+ payloadAttestation: gloas.PayloadAttestation
1201
+ ): gloas.IndexedPayloadAttestation {
1202
+ const payloadTimelinessCommittee = this.getPayloadTimelinessCommittee(slot);
1203
+ const attestingIndices = payloadAttestation.aggregationBits.intersectValues(payloadTimelinessCommittee);
1204
+
1205
+ return {
1206
+ attestingIndices: attestingIndices.sort((a, b) => a - b),
1207
+ data: payloadAttestation.data,
1208
+ signature: payloadAttestation.signature,
1209
+ };
1210
+ }
1154
1211
  }
1155
1212
 
1156
1213
  function getEffectiveBalanceIncrementsByteLen(validatorCount: number): number {
@@ -12,9 +12,11 @@ import {
12
12
  CachedBeaconStateCapella,
13
13
  CachedBeaconStateElectra,
14
14
  CachedBeaconStateFulu,
15
+ CachedBeaconStateGloas,
15
16
  CachedBeaconStatePhase0,
16
17
  EpochTransitionCache,
17
18
  } from "../types.js";
19
+ import {processBuilderPendingPayments} from "./processBuilderPendingPayments.ts";
18
20
  import {processEffectiveBalanceUpdates} from "./processEffectiveBalanceUpdates.js";
19
21
  import {processEth1DataReset} from "./processEth1DataReset.js";
20
22
  import {processHistoricalRootsUpdate} from "./processHistoricalRootsUpdate.js";
@@ -53,6 +55,7 @@ export {
53
55
  processPendingDeposits,
54
56
  processPendingConsolidations,
55
57
  processProposerLookahead,
58
+ processBuilderPendingPayments,
56
59
  };
57
60
 
58
61
  export {computeUnrealizedCheckpoints} from "./computeUnrealizedCheckpoints.js";
@@ -78,6 +81,7 @@ export enum EpochTransitionStep {
78
81
  processPendingDeposits = "processPendingDeposits",
79
82
  processPendingConsolidations = "processPendingConsolidations",
80
83
  processProposerLookahead = "processProposerLookahead",
84
+ processBuilderPendingPayments = "processBuilderPendingPayments",
81
85
  }
82
86
 
83
87
  export function processEpoch(
@@ -154,6 +158,14 @@ export function processEpoch(
154
158
  }
155
159
  }
156
160
 
161
+ if (fork >= ForkSeq.gloas) {
162
+ const timer = metrics?.epochTransitionStepTime.startTimer({
163
+ step: EpochTransitionStep.processBuilderPendingPayments,
164
+ });
165
+ processBuilderPendingPayments(state as CachedBeaconStateGloas);
166
+ timer?.();
167
+ }
168
+
157
169
  {
158
170
  const timer = metrics?.epochTransitionStepTime.startTimer({
159
171
  step: EpochTransitionStep.processEffectiveBalanceUpdates,
@@ -0,0 +1,31 @@
1
+ import {SLOTS_PER_EPOCH} from "@lodestar/params";
2
+ import {ssz} from "@lodestar/types";
3
+ import {CachedBeaconStateGloas} from "../types.ts";
4
+ import {computeExitEpochAndUpdateChurn} from "../util/epoch.ts";
5
+ import {getBuilderPaymentQuorumThreshold} from "../util/gloas.ts";
6
+
7
+ /**
8
+ * Processes the builder pending payments from the previous epoch.
9
+ */
10
+ export function processBuilderPendingPayments(state: CachedBeaconStateGloas): void {
11
+ const quorum = getBuilderPaymentQuorumThreshold(state);
12
+
13
+ for (let i = 0; i < SLOTS_PER_EPOCH; i++) {
14
+ const payment = state.builderPendingPayments.get(i);
15
+ if (payment.weight > quorum) {
16
+ const exitQueueEpoch = computeExitEpochAndUpdateChurn(state, BigInt(payment.withdrawal.amount));
17
+ payment.withdrawal.withdrawableEpoch = exitQueueEpoch + state.config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY;
18
+
19
+ state.builderPendingWithdrawals.push(payment.withdrawal);
20
+ }
21
+ }
22
+
23
+ // TODO GLOAS: Optimize this
24
+ for (let i = 0; i < state.builderPendingPayments.length; i++) {
25
+ if (i < SLOTS_PER_EPOCH) {
26
+ state.builderPendingPayments.set(i, state.builderPendingPayments.get(i + SLOTS_PER_EPOCH).clone());
27
+ } else {
28
+ state.builderPendingPayments.set(i, ssz.gloas.BuilderPendingPayment.defaultViewDU());
29
+ }
30
+ }
31
+ }
package/src/index.ts CHANGED
@@ -52,6 +52,7 @@ export type {
52
52
  BeaconStateElectra,
53
53
  BeaconStateExecutions,
54
54
  BeaconStateFulu,
55
+ BeaconStateGloas,
55
56
  // Non-cached states
56
57
  BeaconStatePhase0,
57
58
  CachedBeaconStateAllForks,
@@ -62,6 +63,7 @@ export type {
62
63
  CachedBeaconStateElectra,
63
64
  CachedBeaconStateExecutions,
64
65
  CachedBeaconStateFulu,
66
+ CachedBeaconStateGloas,
65
67
  CachedBeaconStatePhase0,
66
68
  } from "./types.js";
67
69
  export * from "./util/index.js";
@@ -1,29 +1,33 @@
1
1
  import {DOMAIN_BEACON_ATTESTER} from "@lodestar/params";
2
2
  import {AttesterSlashing, IndexedAttestationBigint, SignedBeaconBlock, ssz} from "@lodestar/types";
3
+ import {Index2PubkeyCache} from "../cache/pubkeyCache.js";
3
4
  import {CachedBeaconStateAllForks} from "../types.js";
4
5
  import {ISignatureSet, SignatureSetType, computeSigningRoot, computeStartSlotAtEpoch} from "../util/index.js";
5
6
 
6
7
  /** Get signature sets from all AttesterSlashing objects in a block */
7
8
  export function getAttesterSlashingsSignatureSets(
9
+ index2pubkey: Index2PubkeyCache,
8
10
  state: CachedBeaconStateAllForks,
9
11
  signedBlock: SignedBeaconBlock
10
12
  ): ISignatureSet[] {
11
13
  return signedBlock.message.body.attesterSlashings.flatMap((attesterSlashing) =>
12
- getAttesterSlashingSignatureSets(state, attesterSlashing)
14
+ getAttesterSlashingSignatureSets(index2pubkey, state, attesterSlashing)
13
15
  );
14
16
  }
15
17
 
16
18
  /** Get signature sets from a single AttesterSlashing object */
17
19
  export function getAttesterSlashingSignatureSets(
20
+ index2pubkey: Index2PubkeyCache,
18
21
  state: CachedBeaconStateAllForks,
19
22
  attesterSlashing: AttesterSlashing
20
23
  ): ISignatureSet[] {
21
24
  return [attesterSlashing.attestation1, attesterSlashing.attestation2].map((attestation) =>
22
- getIndexedAttestationBigintSignatureSet(state, attestation)
25
+ getIndexedAttestationBigintSignatureSet(index2pubkey, state, attestation)
23
26
  );
24
27
  }
25
28
 
26
29
  export function getIndexedAttestationBigintSignatureSet(
30
+ index2pubkey: Index2PubkeyCache,
27
31
  state: CachedBeaconStateAllForks,
28
32
  indexedAttestation: IndexedAttestationBigint
29
33
  ): ISignatureSet {
@@ -32,7 +36,7 @@ export function getIndexedAttestationBigintSignatureSet(
32
36
 
33
37
  return {
34
38
  type: SignatureSetType.aggregate,
35
- pubkeys: indexedAttestation.attestingIndices.map((i) => state.epochCtx.index2pubkey[i]),
39
+ pubkeys: indexedAttestation.attestingIndices.map((i) => index2pubkey[i]),
36
40
  signingRoot: computeSigningRoot(ssz.phase0.AttestationDataBigint, indexedAttestation.data, domain),
37
41
  signature: indexedAttestation.signature,
38
42
  };
@@ -1,6 +1,7 @@
1
1
  import {ForkSeq} from "@lodestar/params";
2
- import {SignedBeaconBlock, altair, capella} from "@lodestar/types";
2
+ import {IndexedAttestation, SignedBeaconBlock, altair, capella} from "@lodestar/types";
3
3
  import {getSyncCommitteeSignatureSet} from "../block/processSyncCommittee.js";
4
+ import {Index2PubkeyCache} from "../cache/pubkeyCache.js";
4
5
  import {CachedBeaconStateAllForks, CachedBeaconStateAltair} from "../types.js";
5
6
  import {ISignatureSet} from "../util/index.js";
6
7
  import {getAttesterSlashingsSignatureSets} from "./attesterSlashings.js";
@@ -14,6 +15,7 @@ import {getVoluntaryExitsSignatureSets} from "./voluntaryExits.js";
14
15
  export * from "./attesterSlashings.js";
15
16
  export * from "./blsToExecutionChange.js";
16
17
  export * from "./indexedAttestation.js";
18
+ export * from "./indexedPayloadAttestation.js";
17
19
  export * from "./proposer.js";
18
20
  export * from "./proposerSlashings.js";
19
21
  export * from "./randao.js";
@@ -24,8 +26,10 @@ export * from "./voluntaryExits.js";
24
26
  * Deposits are not included because they can legally have invalid signatures.
25
27
  */
26
28
  export function getBlockSignatureSets(
29
+ index2pubkey: Index2PubkeyCache,
27
30
  state: CachedBeaconStateAllForks,
28
31
  signedBlock: SignedBeaconBlock,
32
+ indexedAttestations: IndexedAttestation[],
29
33
  opts?: {
30
34
  /** Useful since block proposer signature is verified beforehand on gossip validation */
31
35
  skipProposerSignature?: boolean;
@@ -35,20 +39,21 @@ export function getBlockSignatureSets(
35
39
  const fork = state.config.getForkSeq(signedBlock.message.slot);
36
40
 
37
41
  const signatureSets = [
38
- getRandaoRevealSignatureSet(state, signedBlock.message),
39
- ...getProposerSlashingsSignatureSets(state, signedBlock),
40
- ...getAttesterSlashingsSignatureSets(state, signedBlock),
41
- ...getAttestationsSignatureSets(state, signedBlock),
42
- ...getVoluntaryExitsSignatureSets(state, signedBlock),
42
+ getRandaoRevealSignatureSet(index2pubkey, state, signedBlock.message),
43
+ ...getProposerSlashingsSignatureSets(index2pubkey, state, signedBlock),
44
+ ...getAttesterSlashingsSignatureSets(index2pubkey, state, signedBlock),
45
+ ...getAttestationsSignatureSets(index2pubkey, state, signedBlock, indexedAttestations),
46
+ ...getVoluntaryExitsSignatureSets(index2pubkey, state, signedBlock),
43
47
  ];
44
48
 
45
49
  if (!opts?.skipProposerSignature) {
46
- signatureSets.push(getBlockProposerSignatureSet(state, signedBlock));
50
+ signatureSets.push(getBlockProposerSignatureSet(index2pubkey, state, signedBlock));
47
51
  }
48
52
 
49
53
  // Only after altair fork, validate tSyncCommitteeSignature
50
54
  if (fork >= ForkSeq.altair) {
51
55
  const syncCommitteeSignatureSet = getSyncCommitteeSignatureSet(
56
+ index2pubkey,
52
57
  state as CachedBeaconStateAltair,
53
58
  (signedBlock as altair.SignedBeaconBlock).message
54
59
  );
@@ -1,5 +1,6 @@
1
1
  import {DOMAIN_BEACON_ATTESTER} from "@lodestar/params";
2
2
  import {IndexedAttestation, SignedBeaconBlock, phase0, ssz} from "@lodestar/types";
3
+ import {Index2PubkeyCache} from "../cache/pubkeyCache.js";
3
4
  import {CachedBeaconStateAllForks} from "../types.js";
4
5
  import {
5
6
  ISignatureSet,
@@ -19,33 +20,43 @@ export function getAttestationDataSigningRoot(
19
20
  }
20
21
 
21
22
  export function getAttestationWithIndicesSignatureSet(
23
+ index2pubkey: Index2PubkeyCache,
22
24
  state: CachedBeaconStateAllForks,
23
25
  attestation: Pick<phase0.Attestation, "data" | "signature">,
24
26
  attestingIndices: number[]
25
27
  ): ISignatureSet {
26
28
  return createAggregateSignatureSetFromComponents(
27
- attestingIndices.map((i) => state.epochCtx.index2pubkey[i]),
29
+ attestingIndices.map((i) => index2pubkey[i]),
28
30
  getAttestationDataSigningRoot(state, attestation.data),
29
31
  attestation.signature
30
32
  );
31
33
  }
32
34
 
33
35
  export function getIndexedAttestationSignatureSet(
36
+ index2pubkey: Index2PubkeyCache,
34
37
  state: CachedBeaconStateAllForks,
35
38
  indexedAttestation: IndexedAttestation
36
39
  ): ISignatureSet {
37
- return getAttestationWithIndicesSignatureSet(state, indexedAttestation, indexedAttestation.attestingIndices);
40
+ return getAttestationWithIndicesSignatureSet(
41
+ index2pubkey,
42
+ state,
43
+ indexedAttestation,
44
+ indexedAttestation.attestingIndices
45
+ );
38
46
  }
39
47
 
40
48
  export function getAttestationsSignatureSets(
49
+ index2pubkey: Index2PubkeyCache,
41
50
  state: CachedBeaconStateAllForks,
42
- signedBlock: SignedBeaconBlock
51
+ signedBlock: SignedBeaconBlock,
52
+ indexedAttestations: IndexedAttestation[]
43
53
  ): ISignatureSet[] {
44
- // TODO: figure how to get attesting indices of an attestation once per block processing
45
- return signedBlock.message.body.attestations.map((attestation) =>
46
- getIndexedAttestationSignatureSet(
47
- state,
48
- state.epochCtx.getIndexedAttestation(state.config.getForkSeq(signedBlock.message.slot), attestation)
49
- )
54
+ if (indexedAttestations.length !== signedBlock.message.body.attestations.length) {
55
+ throw Error(
56
+ `Indexed attestations length mismatch: got ${indexedAttestations.length}, expected ${signedBlock.message.body.attestations.length}`
57
+ );
58
+ }
59
+ return indexedAttestations.map((indexedAttestation) =>
60
+ getIndexedAttestationSignatureSet(index2pubkey, state, indexedAttestation)
50
61
  );
51
62
  }
@@ -0,0 +1,24 @@
1
+ import {DOMAIN_PTC_ATTESTER} from "@lodestar/params";
2
+ import {gloas, ssz} from "@lodestar/types";
3
+ import {CachedBeaconStateGloas} from "../types.ts";
4
+ import {ISignatureSet, computeSigningRoot, createAggregateSignatureSetFromComponents} from "../util/index.ts";
5
+
6
+ export function getIndexedPayloadAttestationSignatureSet(
7
+ state: CachedBeaconStateGloas,
8
+ indexedPayloadAttestation: gloas.IndexedPayloadAttestation
9
+ ): ISignatureSet {
10
+ return createAggregateSignatureSetFromComponents(
11
+ indexedPayloadAttestation.attestingIndices.map((i) => state.epochCtx.index2pubkey[i]),
12
+ getPayloadAttestationDataSigningRoot(state, indexedPayloadAttestation.data),
13
+ indexedPayloadAttestation.signature
14
+ );
15
+ }
16
+
17
+ export function getPayloadAttestationDataSigningRoot(
18
+ state: CachedBeaconStateGloas,
19
+ data: gloas.PayloadAttestationData
20
+ ): Uint8Array {
21
+ const domain = state.config.getDomain(state.slot, DOMAIN_PTC_ATTESTER);
22
+
23
+ return computeSigningRoot(ssz.gloas.PayloadAttestationData, data, domain);
24
+ }
@@ -1,22 +1,25 @@
1
1
  import {DOMAIN_BEACON_PROPOSER} from "@lodestar/params";
2
2
  import {SignedBeaconBlock, SignedBlindedBeaconBlock, Slot, isBlindedBeaconBlock, phase0, ssz} from "@lodestar/types";
3
+ import {Index2PubkeyCache} from "../cache/pubkeyCache.js";
3
4
  import {CachedBeaconStateAllForks} from "../types.js";
4
5
  import {computeSigningRoot} from "../util/index.js";
5
6
  import {ISignatureSet, SignatureSetType, verifySignatureSet} from "../util/signatureSets.js";
6
7
 
7
8
  export function verifyProposerSignature(
9
+ index2pubkey: Index2PubkeyCache,
8
10
  state: CachedBeaconStateAllForks,
9
11
  signedBlock: SignedBeaconBlock | SignedBlindedBeaconBlock
10
12
  ): boolean {
11
- const signatureSet = getBlockProposerSignatureSet(state, signedBlock);
13
+ const signatureSet = getBlockProposerSignatureSet(index2pubkey, state, signedBlock);
12
14
  return verifySignatureSet(signatureSet);
13
15
  }
14
16
 
15
17
  export function getBlockProposerSignatureSet(
18
+ index2pubkey: Index2PubkeyCache,
16
19
  state: CachedBeaconStateAllForks,
17
20
  signedBlock: SignedBeaconBlock | SignedBlindedBeaconBlock
18
21
  ): ISignatureSet {
19
- const {config, epochCtx} = state;
22
+ const {config} = state;
20
23
  const domain = config.getDomain(state.slot, DOMAIN_BEACON_PROPOSER, signedBlock.message.slot);
21
24
 
22
25
  const blockType = isBlindedBeaconBlock(signedBlock.message)
@@ -25,37 +28,40 @@ export function getBlockProposerSignatureSet(
25
28
 
26
29
  return {
27
30
  type: SignatureSetType.single,
28
- pubkey: epochCtx.index2pubkey[signedBlock.message.proposerIndex],
31
+ pubkey: index2pubkey[signedBlock.message.proposerIndex],
29
32
  signingRoot: computeSigningRoot(blockType, signedBlock.message, domain),
30
33
  signature: signedBlock.signature,
31
34
  };
32
35
  }
33
36
 
34
37
  export function getBlockHeaderProposerSignatureSetByParentStateSlot(
38
+ index2pubkey: Index2PubkeyCache,
35
39
  parentState: CachedBeaconStateAllForks,
36
40
  signedBlockHeader: phase0.SignedBeaconBlockHeader
37
41
  ) {
38
- return getBlockHeaderProposerSignatureSet(parentState, signedBlockHeader, parentState.slot);
42
+ return getBlockHeaderProposerSignatureSet(index2pubkey, parentState, signedBlockHeader, parentState.slot);
39
43
  }
40
44
 
41
45
  export function getBlockHeaderProposerSignatureSetByHeaderSlot(
46
+ index2pubkey: Index2PubkeyCache,
42
47
  headState: CachedBeaconStateAllForks,
43
48
  signedBlockHeader: phase0.SignedBeaconBlockHeader
44
49
  ) {
45
- return getBlockHeaderProposerSignatureSet(headState, signedBlockHeader, signedBlockHeader.message.slot);
50
+ return getBlockHeaderProposerSignatureSet(index2pubkey, headState, signedBlockHeader, signedBlockHeader.message.slot);
46
51
  }
47
52
 
48
53
  function getBlockHeaderProposerSignatureSet(
54
+ index2pubkey: Index2PubkeyCache,
49
55
  state: CachedBeaconStateAllForks,
50
56
  signedBlockHeader: phase0.SignedBeaconBlockHeader,
51
57
  domainSlot: Slot
52
58
  ): ISignatureSet {
53
- const {config, epochCtx} = state;
59
+ const {config} = state;
54
60
  const domain = config.getDomain(domainSlot, DOMAIN_BEACON_PROPOSER, signedBlockHeader.message.slot);
55
61
 
56
62
  return {
57
63
  type: SignatureSetType.single,
58
- pubkey: epochCtx.index2pubkey[signedBlockHeader.message.proposerIndex],
64
+ pubkey: index2pubkey[signedBlockHeader.message.proposerIndex],
59
65
  signingRoot: computeSigningRoot(ssz.phase0.BeaconBlockHeader, signedBlockHeader.message, domain),
60
66
  signature: signedBlockHeader.signature,
61
67
  };
@@ -1,5 +1,6 @@
1
1
  import {DOMAIN_BEACON_PROPOSER} from "@lodestar/params";
2
2
  import {SignedBeaconBlock, phase0, ssz} from "@lodestar/types";
3
+ import {Index2PubkeyCache} from "../cache/pubkeyCache.js";
3
4
  import {CachedBeaconStateAllForks} from "../types.js";
4
5
  import {ISignatureSet, SignatureSetType, computeSigningRoot} from "../util/index.js";
5
6
 
@@ -7,11 +8,11 @@ import {ISignatureSet, SignatureSetType, computeSigningRoot} from "../util/index
7
8
  * Extract signatures to allow validating all block signatures at once
8
9
  */
9
10
  export function getProposerSlashingSignatureSets(
11
+ index2pubkey: Index2PubkeyCache,
10
12
  state: CachedBeaconStateAllForks,
11
13
  proposerSlashing: phase0.ProposerSlashing
12
14
  ): ISignatureSet[] {
13
- const {epochCtx} = state;
14
- const pubkey = epochCtx.index2pubkey[proposerSlashing.signedHeader1.message.proposerIndex];
15
+ const pubkey = index2pubkey[proposerSlashing.signedHeader1.message.proposerIndex];
15
16
 
16
17
  // In state transition, ProposerSlashing headers are only partially validated. Their slot could be higher than the
17
18
  // clock and the slashing would still be valid. Must use bigint variants to hash correctly to all possible values
@@ -32,10 +33,11 @@ export function getProposerSlashingSignatureSets(
32
33
  }
33
34
 
34
35
  export function getProposerSlashingsSignatureSets(
36
+ index2pubkey: Index2PubkeyCache,
35
37
  state: CachedBeaconStateAllForks,
36
38
  signedBlock: SignedBeaconBlock
37
39
  ): ISignatureSet[] {
38
40
  return signedBlock.message.body.proposerSlashings.flatMap((proposerSlashing) =>
39
- getProposerSlashingSignatureSets(state, proposerSlashing)
41
+ getProposerSlashingSignatureSets(index2pubkey, state, proposerSlashing)
40
42
  );
41
43
  }
@@ -1,5 +1,6 @@
1
1
  import {DOMAIN_RANDAO} from "@lodestar/params";
2
2
  import {BeaconBlock, ssz} from "@lodestar/types";
3
+ import {Index2PubkeyCache} from "../cache/pubkeyCache.js";
3
4
  import {CachedBeaconStateAllForks} from "../types.js";
4
5
  import {
5
6
  ISignatureSet,
@@ -9,22 +10,29 @@ import {
9
10
  verifySignatureSet,
10
11
  } from "../util/index.js";
11
12
 
12
- export function verifyRandaoSignature(state: CachedBeaconStateAllForks, block: BeaconBlock): boolean {
13
- return verifySignatureSet(getRandaoRevealSignatureSet(state, block));
13
+ export function verifyRandaoSignature(
14
+ index2pubkey: Index2PubkeyCache,
15
+ state: CachedBeaconStateAllForks,
16
+ block: BeaconBlock
17
+ ): boolean {
18
+ return verifySignatureSet(getRandaoRevealSignatureSet(index2pubkey, state, block));
14
19
  }
15
20
 
16
21
  /**
17
22
  * Extract signatures to allow validating all block signatures at once
18
23
  */
19
- export function getRandaoRevealSignatureSet(state: CachedBeaconStateAllForks, block: BeaconBlock): ISignatureSet {
20
- const {epochCtx} = state;
24
+ export function getRandaoRevealSignatureSet(
25
+ index2pubkey: Index2PubkeyCache,
26
+ state: CachedBeaconStateAllForks,
27
+ block: BeaconBlock
28
+ ): ISignatureSet {
21
29
  // should not get epoch from epochCtx
22
30
  const epoch = computeEpochAtSlot(block.slot);
23
31
  const domain = state.config.getDomain(state.slot, DOMAIN_RANDAO, block.slot);
24
32
 
25
33
  return {
26
34
  type: SignatureSetType.single,
27
- pubkey: epochCtx.index2pubkey[block.proposerIndex],
35
+ pubkey: index2pubkey[block.proposerIndex],
28
36
  signingRoot: computeSigningRoot(ssz.Epoch, epoch, domain),
29
37
  signature: block.body.randaoReveal,
30
38
  };
@@ -1,4 +1,5 @@
1
1
  import {SignedBeaconBlock, phase0, ssz} from "@lodestar/types";
2
+ import {Index2PubkeyCache} from "../cache/pubkeyCache.js";
2
3
  import {CachedBeaconStateAllForks} from "../types.js";
3
4
  import {
4
5
  ISignatureSet,
@@ -9,36 +10,38 @@ import {
9
10
  } from "../util/index.js";
10
11
 
11
12
  export function verifyVoluntaryExitSignature(
13
+ index2pubkey: Index2PubkeyCache,
12
14
  state: CachedBeaconStateAllForks,
13
15
  signedVoluntaryExit: phase0.SignedVoluntaryExit
14
16
  ): boolean {
15
- return verifySignatureSet(getVoluntaryExitSignatureSet(state, signedVoluntaryExit));
17
+ return verifySignatureSet(getVoluntaryExitSignatureSet(index2pubkey, state, signedVoluntaryExit));
16
18
  }
17
19
 
18
20
  /**
19
21
  * Extract signatures to allow validating all block signatures at once
20
22
  */
21
23
  export function getVoluntaryExitSignatureSet(
24
+ index2pubkey: Index2PubkeyCache,
22
25
  state: CachedBeaconStateAllForks,
23
26
  signedVoluntaryExit: phase0.SignedVoluntaryExit
24
27
  ): ISignatureSet {
25
- const {epochCtx} = state;
26
28
  const slot = computeStartSlotAtEpoch(signedVoluntaryExit.message.epoch);
27
29
  const domain = state.config.getDomainForVoluntaryExit(state.slot, slot);
28
30
 
29
31
  return {
30
32
  type: SignatureSetType.single,
31
- pubkey: epochCtx.index2pubkey[signedVoluntaryExit.message.validatorIndex],
33
+ pubkey: index2pubkey[signedVoluntaryExit.message.validatorIndex],
32
34
  signingRoot: computeSigningRoot(ssz.phase0.VoluntaryExit, signedVoluntaryExit.message, domain),
33
35
  signature: signedVoluntaryExit.signature,
34
36
  };
35
37
  }
36
38
 
37
39
  export function getVoluntaryExitsSignatureSets(
40
+ index2pubkey: Index2PubkeyCache,
38
41
  state: CachedBeaconStateAllForks,
39
42
  signedBlock: SignedBeaconBlock
40
43
  ): ISignatureSet[] {
41
44
  return signedBlock.message.body.voluntaryExits.map((voluntaryExit) =>
42
- getVoluntaryExitSignatureSet(state, voluntaryExit)
45
+ getVoluntaryExitSignatureSet(index2pubkey, state, voluntaryExit)
43
46
  );
44
47
  }
package/src/slot/index.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import {byteArrayEquals} from "@chainsafe/ssz";
2
- import {SLOTS_PER_HISTORICAL_ROOT} from "@lodestar/params";
2
+ import {ForkSeq, SLOTS_PER_HISTORICAL_ROOT} from "@lodestar/params";
3
3
  import {ZERO_HASH} from "../constants/index.js";
4
- import {CachedBeaconStateAllForks} from "../types.js";
4
+ import {CachedBeaconStateAllForks, CachedBeaconStateGloas} from "../types.js";
5
5
 
6
6
  export {upgradeStateToAltair} from "./upgradeStateToAltair.js";
7
7
  export {upgradeStateToBellatrix} from "./upgradeStateToBellatrix.js";
@@ -14,7 +14,7 @@ export {upgradeStateToGloas} from "./upgradeStateToGloas.js";
14
14
  /**
15
15
  * Dial state to next slot. Common for all forks
16
16
  */
17
- export function processSlot(state: CachedBeaconStateAllForks): void {
17
+ export function processSlot(fork: ForkSeq, state: CachedBeaconStateAllForks): void {
18
18
  // Cache state root
19
19
  // Note: .hashTreeRoot() automatically commits() pending changes
20
20
  const previousStateRoot = state.hashTreeRoot();
@@ -29,4 +29,12 @@ export function processSlot(state: CachedBeaconStateAllForks): void {
29
29
  // Note: .hashTreeRoot() automatically commits() pending changes
30
30
  const previousBlockRoot = state.latestBlockHeader.hashTreeRoot();
31
31
  state.blockRoots.set(state.slot % SLOTS_PER_HISTORICAL_ROOT, previousBlockRoot);
32
+
33
+ if (fork >= ForkSeq.gloas) {
34
+ // Unset the next payload availability
35
+ (state as CachedBeaconStateGloas).executionPayloadAvailability.set(
36
+ (state.slot + 1) % SLOTS_PER_HISTORICAL_ROOT,
37
+ false
38
+ );
39
+ }
32
40
  }
@@ -135,7 +135,8 @@ function translateParticipation(
135
135
  data,
136
136
  attestation.inclusionDelay,
137
137
  epochCtx.epoch,
138
- rootCache
138
+ rootCache,
139
+ null
139
140
  );
140
141
 
141
142
  const committeeIndices = epochCtx.getBeaconCommittee(data.slot, data.index);