@lodestar/state-transition 1.43.0-dev.6b7eebbf6d → 1.43.0-dev.6f485b1b61

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 (59) hide show
  1. package/lib/block/processConsolidationRequest.d.ts.map +1 -1
  2. package/lib/block/processConsolidationRequest.js +2 -1
  3. package/lib/block/processConsolidationRequest.js.map +1 -1
  4. package/lib/block/processParentExecutionPayload.d.ts +2 -2
  5. package/lib/block/processParentExecutionPayload.js +3 -3
  6. package/lib/block/processWithdrawals.d.ts.map +1 -1
  7. package/lib/block/processWithdrawals.js +4 -6
  8. package/lib/block/processWithdrawals.js.map +1 -1
  9. package/lib/cache/epochCache.js +3 -3
  10. package/lib/cache/epochCache.js.map +1 -1
  11. package/lib/epoch/processPendingDeposits.d.ts.map +1 -1
  12. package/lib/epoch/processPendingDeposits.js +4 -2
  13. package/lib/epoch/processPendingDeposits.js.map +1 -1
  14. package/lib/signatureSets/index.d.ts +1 -0
  15. package/lib/signatureSets/index.d.ts.map +1 -1
  16. package/lib/signatureSets/index.js +1 -0
  17. package/lib/signatureSets/index.js.map +1 -1
  18. package/lib/signatureSets/proposerPreferences.d.ts +4 -0
  19. package/lib/signatureSets/proposerPreferences.d.ts.map +1 -0
  20. package/lib/signatureSets/proposerPreferences.js +8 -0
  21. package/lib/signatureSets/proposerPreferences.js.map +1 -0
  22. package/lib/slot/upgradeStateToElectra.d.ts.map +1 -1
  23. package/lib/slot/upgradeStateToElectra.js +2 -2
  24. package/lib/slot/upgradeStateToElectra.js.map +1 -1
  25. package/lib/stateView/beaconStateView.d.ts +6 -2
  26. package/lib/stateView/beaconStateView.d.ts.map +1 -1
  27. package/lib/stateView/beaconStateView.js +26 -8
  28. package/lib/stateView/beaconStateView.js.map +1 -1
  29. package/lib/stateView/interface.d.ts +6 -4
  30. package/lib/stateView/interface.d.ts.map +1 -1
  31. package/lib/stateView/interface.js.map +1 -1
  32. package/lib/util/epoch.d.ts.map +1 -1
  33. package/lib/util/epoch.js +6 -4
  34. package/lib/util/epoch.js.map +1 -1
  35. package/lib/util/gloas.d.ts +0 -1
  36. package/lib/util/gloas.d.ts.map +1 -1
  37. package/lib/util/gloas.js +0 -4
  38. package/lib/util/gloas.js.map +1 -1
  39. package/lib/util/loadState/loadState.js +4 -4
  40. package/lib/util/loadState/loadState.js.map +1 -1
  41. package/lib/util/validator.d.ts +14 -2
  42. package/lib/util/validator.d.ts.map +1 -1
  43. package/lib/util/validator.js +24 -2
  44. package/lib/util/validator.js.map +1 -1
  45. package/package.json +7 -7
  46. package/src/block/processConsolidationRequest.ts +2 -1
  47. package/src/block/processParentExecutionPayload.ts +3 -3
  48. package/src/block/processWithdrawals.ts +6 -6
  49. package/src/cache/epochCache.ts +3 -3
  50. package/src/epoch/processPendingDeposits.ts +5 -2
  51. package/src/signatureSets/index.ts +1 -0
  52. package/src/signatureSets/proposerPreferences.ts +12 -0
  53. package/src/slot/upgradeStateToElectra.ts +4 -2
  54. package/src/stateView/beaconStateView.ts +29 -9
  55. package/src/stateView/interface.ts +6 -4
  56. package/src/util/epoch.ts +13 -4
  57. package/src/util/gloas.ts +0 -5
  58. package/src/util/loadState/loadState.ts +4 -4
  59. package/src/util/validator.ts +42 -2
@@ -0,0 +1,12 @@
1
+ import {BeaconConfig} from "@lodestar/config";
2
+ import {DOMAIN_PROPOSER_PREFERENCES} from "@lodestar/params";
3
+ import {gloas, ssz} from "@lodestar/types";
4
+ import {computeSigningRoot} from "../util/index.js";
5
+
6
+ export function getProposerPreferencesSigningRoot(
7
+ config: BeaconConfig,
8
+ preferences: gloas.ProposerPreferences
9
+ ): Uint8Array {
10
+ const domain = config.getDomain(preferences.proposalSlot, DOMAIN_PROPOSER_PREFERENCES);
11
+ return computeSigningRoot(ssz.gloas.ProposerPreferences, preferences, domain);
12
+ }
@@ -1,4 +1,4 @@
1
- import {FAR_FUTURE_EPOCH, GENESIS_SLOT, UNSET_DEPOSIT_REQUESTS_START_INDEX} from "@lodestar/params";
1
+ import {FAR_FUTURE_EPOCH, ForkSeq, GENESIS_SLOT, UNSET_DEPOSIT_REQUESTS_START_INDEX} from "@lodestar/params";
2
2
  import {ValidatorIndex, ssz} from "@lodestar/types";
3
3
  import {CachedBeaconStateElectra, getCachedBeaconState} from "../cache/stateCache.js";
4
4
  import {G2_POINT_AT_INFINITY} from "../constants/constants.js";
@@ -78,7 +78,9 @@ export function upgradeStateToElectra(stateDeneb: CachedBeaconStateDeneb): Cache
78
78
  stateElectraView.commit();
79
79
  const tmpElectraState = getCachedBeaconState(stateElectraView, stateDeneb);
80
80
  stateElectraView.exitBalanceToConsume = BigInt(getActivationExitChurnLimit(tmpElectraState.epochCtx));
81
- stateElectraView.consolidationBalanceToConsume = BigInt(getConsolidationChurnLimit(tmpElectraState.epochCtx));
81
+ stateElectraView.consolidationBalanceToConsume = BigInt(
82
+ getConsolidationChurnLimit(ForkSeq.electra, tmpElectraState.epochCtx)
83
+ );
82
84
 
83
85
  preActivation.sort((i0, i1) => {
84
86
  const res = validatorsArr[i0].activationEligibilityEpoch - validatorsArr[i1].activationEligibilityEpoch;
@@ -68,7 +68,7 @@ import {canBuilderCoverBid} from "../util/gloas.js";
68
68
  import {loadState} from "../util/loadState/loadState.js";
69
69
  import {getRandaoMix} from "../util/seed.js";
70
70
  import {getLatestWeakSubjectivityCheckpointEpoch} from "../util/weakSubjectivity.js";
71
- import {IBeaconStateView, IBeaconStateViewLatestFork} from "./interface.js";
71
+ import {IBeaconStateView, IBeaconStateViewGloas, IBeaconStateViewLatestFork, isStatePostGloas} from "./interface.js";
72
72
 
73
73
  export class BeaconStateView implements IBeaconStateViewLatestFork {
74
74
  private readonly config: BeaconConfig;
@@ -405,6 +405,23 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
405
405
  return canBuilderCoverBid(this.cachedState as CachedBeaconStateGloas, builderIndex, bidAmount);
406
406
  }
407
407
 
408
+ /**
409
+ * Return the PTCs for an epoch
410
+ */
411
+ getEpochPTCs(epoch: Epoch): Uint32Array[] {
412
+ if (this.config.getForkSeq(this.cachedState.slot) < ForkSeq.gloas) {
413
+ throw new Error("PTC committees are not supported before Gloas");
414
+ }
415
+
416
+ const epochCtx = (this.cachedState as CachedBeaconStateGloas).epochCtx;
417
+ if (epoch === epochCtx.epoch) {
418
+ return epochCtx.payloadTimelinessCommittees;
419
+ }
420
+ if (epoch === epochCtx.nextEpoch) {
421
+ return epochCtx.nextPayloadTimelinessCommittees;
422
+ }
423
+ throw new Error(`PTC committees are not available for epoch=${epoch}`);
424
+ }
408
425
  /**
409
426
  * Return the index of the validator in the PTC committee for the given slot.
410
427
  * return -1 if validator is not in the PTC committee for the given slot.
@@ -786,16 +803,19 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
786
803
  /**
787
804
  * Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.5/specs/gloas/validator.md#executionpayload
788
805
  */
789
- getExpectedWithdrawalsForFullParent(envelope: gloas.SignedExecutionPayloadEnvelope): capella.Withdrawal[] {
790
- const fork = this.config.getForkSeq(this.cachedState.slot);
791
- if (fork < ForkSeq.gloas) {
792
- throw new Error("getExpectedWithdrawalsForFullParent is not available before Gloas");
806
+ withParentPayloadApplied(executionRequests: electra.ExecutionRequests): IBeaconStateViewGloas {
807
+ if (this.config.getForkSeq(this.cachedState.slot) < ForkSeq.gloas) {
808
+ throw new Error("withParentPayloadApplied is not available before Gloas");
793
809
  }
794
- // Make a copy of the state to avoid mutability issues
795
810
  const stateCopy = this.cachedState.clone(true) as CachedBeaconStateGloas;
796
- // Apply parent payload before computing withdrawals
797
- applyParentExecutionPayload(stateCopy, envelope.message.executionRequests);
798
811
 
799
- return getExpectedWithdrawals(fork, stateCopy).expectedWithdrawals;
812
+ applyParentExecutionPayload(stateCopy, executionRequests);
813
+
814
+ const stateView = new BeaconStateView(stateCopy);
815
+ if (!isStatePostGloas(stateView)) {
816
+ throw new Error("Expected gloas state after clone");
817
+ }
818
+
819
+ return stateView;
800
820
  }
801
821
  }
@@ -252,13 +252,15 @@ export interface IBeaconStateViewGloas extends IBeaconStateViewFulu {
252
252
  payloadExpectedWithdrawals: capella.Withdrawal[];
253
253
  getBuilder(index: BuilderIndex): gloas.Builder;
254
254
  canBuilderCoverBid(builderIndex: BuilderIndex, bidAmount: number): boolean;
255
+ getEpochPTCs(epoch: Epoch): Uint32Array[];
255
256
  getIndexInPayloadTimelinessCommittee(validatorIndex: ValidatorIndex, slot: Slot): number;
256
257
  /**
257
- * Compute expected withdrawals as if the parent was FULL.
258
- * Clones the state, applies parent payload effects, then computes withdrawals.
259
- * Used by prepare_execution_payload when building on FULL parent.
258
+ * Clone the state and apply parent execution payload effects.
259
+ * Used during block production and prepareNextSlot so that withdrawals and
260
+ * operation selection (e.g. voluntary exits) see the same post-apply state that the block
261
+ * processor will see at import.
260
262
  */
261
- getExpectedWithdrawalsForFullParent(envelope: gloas.SignedExecutionPayloadEnvelope): capella.Withdrawal[];
263
+ withParentPayloadApplied(executionRequests: electra.ExecutionRequests): IBeaconStateViewGloas;
262
264
  }
263
265
 
264
266
  /**
package/src/util/epoch.ts CHANGED
@@ -1,7 +1,13 @@
1
- import {EPOCHS_PER_SYNC_COMMITTEE_PERIOD, GENESIS_EPOCH, MAX_SEED_LOOKAHEAD, SLOTS_PER_EPOCH} from "@lodestar/params";
1
+ import {
2
+ EPOCHS_PER_SYNC_COMMITTEE_PERIOD,
3
+ ForkSeq,
4
+ GENESIS_EPOCH,
5
+ MAX_SEED_LOOKAHEAD,
6
+ SLOTS_PER_EPOCH,
7
+ } from "@lodestar/params";
2
8
  import {BeaconState, Epoch, Gwei, Slot, SyncPeriod} from "@lodestar/types";
3
9
  import {CachedBeaconStateElectra, CachedBeaconStateGloas} from "../types.js";
4
- import {getActivationExitChurnLimit, getConsolidationChurnLimit} from "./validator.js";
10
+ import {getActivationExitChurnLimit, getConsolidationChurnLimit, getExitChurnLimit} from "./validator.js";
5
11
 
6
12
  /**
7
13
  * Return the epoch number at the given slot.
@@ -45,8 +51,10 @@ export function computeExitEpochAndUpdateChurn(
45
51
  state: CachedBeaconStateElectra | CachedBeaconStateGloas,
46
52
  exitBalance: Gwei
47
53
  ): number {
54
+ const fork = state.config.getForkSeq(state.slot);
48
55
  let earliestExitEpoch = Math.max(state.earliestExitEpoch, computeActivationExitEpoch(state.epochCtx.epoch));
49
- const perEpochChurn = getActivationExitChurnLimit(state.epochCtx);
56
+ const perEpochChurn =
57
+ fork >= ForkSeq.gloas ? getExitChurnLimit(state.epochCtx) : getActivationExitChurnLimit(state.epochCtx);
50
58
 
51
59
  // New epoch for exits.
52
60
  let exitBalanceToConsume =
@@ -71,11 +79,12 @@ export function computeConsolidationEpochAndUpdateChurn(
71
79
  state: CachedBeaconStateElectra | CachedBeaconStateGloas,
72
80
  consolidationBalance: Gwei
73
81
  ): number {
82
+ const fork = state.config.getForkSeq(state.slot);
74
83
  let earliestConsolidationEpoch = Math.max(
75
84
  state.earliestConsolidationEpoch,
76
85
  computeActivationExitEpoch(state.epochCtx.epoch)
77
86
  );
78
- const perEpochConsolidationChurn = getConsolidationChurnLimit(state.epochCtx);
87
+ const perEpochConsolidationChurn = getConsolidationChurnLimit(fork, state.epochCtx);
79
88
 
80
89
  // New epoch for consolidations
81
90
  let consolidationBalanceToConsume =
package/src/util/gloas.ts CHANGED
@@ -172,11 +172,6 @@ export function isAttestationSameSlotRootCache(rootCache: RootCache, data: Attes
172
172
  return isMatchingBlockRoot && isCurrentBlockRoot;
173
173
  }
174
174
 
175
- // TODO GLOAS: This function no longer exists in v1.7.0-alpha.5 specs. Remove it when appropriate to do so
176
- export function isParentBlockFull(state: CachedBeaconStateGloas): boolean {
177
- return byteArrayEquals(state.latestExecutionPayloadBid.blockHash, state.latestBlockHash);
178
- }
179
-
180
175
  export function initializePtcWindow(state: CachedBeaconStateFulu): Uint32Array[] {
181
176
  const ptcWindow: Uint32Array[] = Array.from({length: SLOTS_PER_EPOCH}, () => new Uint32Array(PTC_SIZE));
182
177
  const currentEpoch = state.epochCtx.epoch;
@@ -110,8 +110,8 @@ function loadInactivityScores(
110
110
  seedState: BeaconStateAltair,
111
111
  inactivityScoresBytes: Uint8Array
112
112
  ): void {
113
- // migratedState starts with the same inactivityScores to seed state
114
- migratedState.inactivityScores = seedState.inactivityScores.clone();
113
+ // true = do not transfer cache
114
+ migratedState.inactivityScores = seedState.inactivityScores.clone(true);
115
115
  const oldValidator = migratedState.inactivityScores.length;
116
116
  // UintNum64 = 8 bytes
117
117
  const newValidator = inactivityScoresBytes.length / 8;
@@ -187,8 +187,8 @@ function loadValidators(
187
187
  const newValidatorCount = Math.floor(newValidatorsBytes.length / VALIDATOR_BYTES_SIZE);
188
188
  const isMoreValidator = newValidatorCount >= seedValidatorCount;
189
189
  const minValidatorCount = Math.min(seedValidatorCount, newValidatorCount);
190
- // migrated state starts with the same validators to seed state
191
- migratedState.validators = seedState.validators.clone();
190
+ // true = do not transfer cache
191
+ migratedState.validators = seedState.validators.clone(true);
192
192
  // 80% of validators serialization time comes from memory allocation
193
193
  // seedStateValidatorsBytes is an optimization at beacon-node side to avoid memory allocation here
194
194
  const seedValidatorsBytes = seedStateValidatorsBytes ?? seedState.validators.serialize();
@@ -44,7 +44,12 @@ export function getActiveValidatorIndices(state: BeaconStateAllForks, epoch: Epo
44
44
  return new Uint32Array(indices);
45
45
  }
46
46
 
47
- export function getActivationChurnLimit(config: ChainForkConfig, fork: ForkSeq, activeValidatorCount: number): number {
47
+ // Deneb fork upgrade only
48
+ export function getValidatorActivationChurnLimit(
49
+ config: ChainForkConfig,
50
+ fork: ForkSeq,
51
+ activeValidatorCount: number
52
+ ): number {
48
53
  if (fork >= ForkSeq.deneb) {
49
54
  return Math.min(config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT, getChurnLimit(config, activeValidatorCount));
50
55
  }
@@ -84,7 +89,42 @@ export function getActivationExitChurnLimit(epochCtx: EpochCache): number {
84
89
  return Math.min(epochCtx.config.MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT, getBalanceChurnLimitFromCache(epochCtx));
85
90
  }
86
91
 
87
- export function getConsolidationChurnLimit(epochCtx: EpochCache): number {
92
+ /**
93
+ * https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/beacon-chain.md#new-get_activation_churn_limit
94
+ */
95
+ export function getActivationChurnLimit(epochCtx: EpochCache): number {
96
+ const churn = getBalanceChurnLimit(
97
+ epochCtx.totalActiveBalanceIncrements,
98
+ epochCtx.config.CHURN_LIMIT_QUOTIENT_GLOAS,
99
+ epochCtx.config.MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA
100
+ );
101
+ return Math.min(epochCtx.config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT_GLOAS, churn);
102
+ }
103
+
104
+ /**
105
+ * https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/beacon-chain.md#new-get_exit_churn_limit
106
+ */
107
+ export function getExitChurnLimit(epochCtx: EpochCache): number {
108
+ return getBalanceChurnLimit(
109
+ epochCtx.totalActiveBalanceIncrements,
110
+ epochCtx.config.CHURN_LIMIT_QUOTIENT_GLOAS,
111
+ epochCtx.config.MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA
112
+ );
113
+ }
114
+
115
+ /**
116
+ * Spec (electra): get_consolidation_churn_limit (uses combined balance churn minus activation+exit churn)
117
+ * Spec (gloas): get_consolidation_churn_limit (independent quotient, no MIN floor)
118
+ */
119
+ export function getConsolidationChurnLimit(fork: ForkSeq, epochCtx: EpochCache): number {
120
+ if (fork >= ForkSeq.gloas) {
121
+ // No MIN floor — pass 0 so getBalanceChurnLimit's max(churn, min) is a no-op.
122
+ return getBalanceChurnLimit(
123
+ epochCtx.totalActiveBalanceIncrements,
124
+ epochCtx.config.CONSOLIDATION_CHURN_LIMIT_QUOTIENT,
125
+ 0
126
+ );
127
+ }
88
128
  return getBalanceChurnLimitFromCache(epochCtx) - getActivationExitChurnLimit(epochCtx);
89
129
  }
90
130