@lodestar/state-transition 1.46.0-dev.9b97bb94f2 → 1.46.0-dev.a03686d0dc
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.
- package/lib/block/externalData.js +2 -4
- package/lib/block/externalData.js.map +1 -1
- package/lib/block/index.d.ts.map +1 -1
- package/lib/block/index.js +3 -2
- package/lib/block/index.js.map +1 -1
- package/lib/block/initiateValidatorExit.js.map +1 -1
- package/lib/block/isValidIndexedAttestation.js.map +1 -1
- package/lib/block/isValidIndexedPayloadAttestation.js.map +1 -1
- package/lib/block/processAttestationPhase0.js.map +1 -1
- package/lib/block/processAttestations.d.ts +2 -2
- package/lib/block/processAttestations.d.ts.map +1 -1
- package/lib/block/processAttestations.js +2 -2
- package/lib/block/processAttestations.js.map +1 -1
- package/lib/block/processAttestationsAltair.d.ts +3 -3
- package/lib/block/processAttestationsAltair.d.ts.map +1 -1
- package/lib/block/processAttestationsAltair.js +7 -4
- package/lib/block/processAttestationsAltair.js.map +1 -1
- package/lib/block/processAttesterSlashing.js.map +1 -1
- package/lib/block/processBlobKzgCommitments.js.map +1 -1
- package/lib/block/processBlockHeader.js.map +1 -1
- package/lib/block/processBlsToExecutionChange.js.map +1 -1
- package/lib/block/processBuilderDepositRequest.js.map +1 -1
- package/lib/block/processBuilderExitRequest.js.map +1 -1
- package/lib/block/processConsolidationRequest.js.map +1 -1
- package/lib/block/processDeposit.d.ts +15 -0
- package/lib/block/processDeposit.d.ts.map +1 -1
- package/lib/block/processDeposit.js +73 -1
- package/lib/block/processDeposit.js.map +1 -1
- package/lib/block/processDepositRequest.js.map +1 -1
- package/lib/block/processEth1Data.js.map +1 -1
- package/lib/block/processExecutionPayload.js.map +1 -1
- package/lib/block/processExecutionPayloadBid.d.ts +3 -3
- package/lib/block/processExecutionPayloadBid.d.ts.map +1 -1
- package/lib/block/processExecutionPayloadBid.js +10 -3
- package/lib/block/processExecutionPayloadBid.js.map +1 -1
- package/lib/block/processOperations.d.ts +2 -2
- package/lib/block/processOperations.d.ts.map +1 -1
- package/lib/block/processOperations.js +2 -2
- package/lib/block/processOperations.js.map +1 -1
- package/lib/block/processParentExecutionPayload.js.map +1 -1
- package/lib/block/processPayloadAttestation.js.map +1 -1
- package/lib/block/processProposerSlashing.js.map +1 -1
- package/lib/block/processRandao.js.map +1 -1
- package/lib/block/processSyncCommittee.js.map +1 -1
- package/lib/block/processVoluntaryExit.js +1 -2
- package/lib/block/processVoluntaryExit.js.map +1 -1
- package/lib/block/processWithdrawalRequest.d.ts.map +1 -1
- package/lib/block/processWithdrawalRequest.js +2 -2
- package/lib/block/processWithdrawalRequest.js.map +1 -1
- package/lib/block/processWithdrawals.js.map +1 -1
- package/lib/block/slashValidator.js.map +1 -1
- package/lib/block/types.js +1 -2
- package/lib/block/types.js.map +1 -1
- package/lib/cache/builderDepositSignatureCache.d.ts +48 -0
- package/lib/cache/builderDepositSignatureCache.d.ts.map +1 -0
- package/lib/cache/builderDepositSignatureCache.js +70 -0
- package/lib/cache/builderDepositSignatureCache.js.map +1 -0
- package/lib/cache/effectiveBalanceIncrements.js.map +1 -1
- package/lib/cache/epochCache.d.ts +9 -0
- package/lib/cache/epochCache.d.ts.map +1 -1
- package/lib/cache/epochCache.js +14 -2
- package/lib/cache/epochCache.js.map +1 -1
- package/lib/cache/epochTransitionCache.js.map +1 -1
- package/lib/cache/pubkeyCache.js.map +1 -1
- package/lib/cache/rewardCache.js.map +1 -1
- package/lib/cache/stateCache.d.ts +2 -1
- package/lib/cache/stateCache.d.ts.map +1 -1
- package/lib/cache/stateCache.js +3 -2
- package/lib/cache/stateCache.js.map +1 -1
- package/lib/cache/syncCommitteeCache.js.map +1 -1
- package/lib/cache/types.d.ts +1 -0
- package/lib/cache/types.d.ts.map +1 -1
- package/lib/epoch/computeUnrealizedCheckpoints.js.map +1 -1
- package/lib/epoch/getAttestationDeltas.js.map +1 -1
- package/lib/epoch/getRewardsAndPenalties.js.map +1 -1
- package/lib/epoch/index.js +1 -2
- package/lib/epoch/index.js.map +1 -1
- package/lib/epoch/processBuilderPendingPayments.js.map +1 -1
- package/lib/epoch/processEffectiveBalanceUpdates.js.map +1 -1
- package/lib/epoch/processEth1DataReset.js.map +1 -1
- package/lib/epoch/processHistoricalRootsUpdate.js.map +1 -1
- package/lib/epoch/processHistoricalSummariesUpdate.js.map +1 -1
- package/lib/epoch/processInactivityUpdates.js.map +1 -1
- package/lib/epoch/processJustificationAndFinalization.js.map +1 -1
- package/lib/epoch/processParticipationFlagUpdates.js.map +1 -1
- package/lib/epoch/processParticipationRecordUpdates.js.map +1 -1
- package/lib/epoch/processPendingAttestations.js.map +1 -1
- package/lib/epoch/processPendingConsolidations.js.map +1 -1
- package/lib/epoch/processPendingDeposits.js.map +1 -1
- package/lib/epoch/processProposerLookahead.js.map +1 -1
- package/lib/epoch/processPtcWindow.js.map +1 -1
- package/lib/epoch/processRandaoMixesReset.js.map +1 -1
- package/lib/epoch/processRegistryUpdates.js.map +1 -1
- package/lib/epoch/processRewardsAndPenalties.js.map +1 -1
- package/lib/epoch/processSlashings.js.map +1 -1
- package/lib/epoch/processSlashingsReset.js.map +1 -1
- package/lib/epoch/processSyncCommitteeUpdates.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/lightClient/proofs.js.map +1 -1
- package/lib/lightClient/spec/index.js.map +1 -1
- package/lib/lightClient/spec/isBetterUpdate.js.map +1 -1
- package/lib/lightClient/spec/processLightClientUpdate.js.map +1 -1
- package/lib/lightClient/spec/store.js.map +1 -1
- package/lib/lightClient/spec/utils.d.ts +0 -2
- package/lib/lightClient/spec/utils.d.ts.map +1 -1
- package/lib/lightClient/spec/utils.js +8 -2
- package/lib/lightClient/spec/utils.js.map +1 -1
- package/lib/lightClient/spec/validateLightClientBootstrap.js.map +1 -1
- package/lib/lightClient/spec/validateLightClientUpdate.js.map +1 -1
- package/lib/metrics.d.ts.map +1 -1
- package/lib/metrics.js +3 -2
- package/lib/metrics.js.map +1 -1
- package/lib/rewards/attestationsRewards.js.map +1 -1
- package/lib/rewards/blockRewards.d.ts.map +1 -1
- package/lib/rewards/blockRewards.js +7 -4
- package/lib/rewards/blockRewards.js.map +1 -1
- package/lib/rewards/syncCommitteeRewards.js.map +1 -1
- package/lib/signatureSets/attesterSlashings.js.map +1 -1
- package/lib/signatureSets/blsToExecutionChange.js.map +1 -1
- package/lib/signatureSets/executionPayloadBid.d.ts +2 -2
- package/lib/signatureSets/executionPayloadBid.d.ts.map +1 -1
- package/lib/signatureSets/executionPayloadBid.js +7 -5
- package/lib/signatureSets/executionPayloadBid.js.map +1 -1
- package/lib/signatureSets/executionPayloadEnvelope.js.map +1 -1
- package/lib/signatureSets/index.js.map +1 -1
- package/lib/signatureSets/indexedAttestation.js.map +1 -1
- package/lib/signatureSets/indexedPayloadAttestation.js.map +1 -1
- package/lib/signatureSets/proposer.js.map +1 -1
- package/lib/signatureSets/proposerPreferences.js.map +1 -1
- package/lib/signatureSets/proposerSlashings.js.map +1 -1
- package/lib/signatureSets/randao.js.map +1 -1
- package/lib/signatureSets/voluntaryExits.js.map +1 -1
- package/lib/slot/index.d.ts +1 -0
- package/lib/slot/index.d.ts.map +1 -1
- package/lib/slot/index.js +1 -0
- package/lib/slot/index.js.map +1 -1
- package/lib/slot/upgradeStateToAltair.js +1 -1
- package/lib/slot/upgradeStateToAltair.js.map +1 -1
- package/lib/slot/upgradeStateToBellatrix.js.map +1 -1
- package/lib/slot/upgradeStateToCapella.js.map +1 -1
- package/lib/slot/upgradeStateToDeneb.js.map +1 -1
- package/lib/slot/upgradeStateToElectra.js.map +1 -1
- package/lib/slot/upgradeStateToFulu.js.map +1 -1
- package/lib/slot/upgradeStateToGloas.js +14 -8
- package/lib/slot/upgradeStateToGloas.js.map +1 -1
- package/lib/slot/upgradeStateToHeze.d.ts +7 -0
- package/lib/slot/upgradeStateToHeze.d.ts.map +1 -0
- package/lib/slot/upgradeStateToHeze.js +83 -0
- package/lib/slot/upgradeStateToHeze.js.map +1 -0
- package/lib/stateTransition.d.ts.map +1 -1
- package/lib/stateTransition.js +6 -5
- package/lib/stateTransition.js.map +1 -1
- package/lib/stateView/beaconStateView.d.ts +3 -0
- package/lib/stateView/beaconStateView.d.ts.map +1 -1
- package/lib/stateView/beaconStateView.js +7 -0
- package/lib/stateView/beaconStateView.js.map +1 -1
- package/lib/stateView/interface.d.ts +16 -3
- package/lib/stateView/interface.d.ts.map +1 -1
- package/lib/stateView/interface.js +4 -1
- package/lib/stateView/interface.js.map +1 -1
- package/lib/stateView/nativeBeaconStateView.d.ts +3 -0
- package/lib/stateView/nativeBeaconStateView.d.ts.map +1 -1
- package/lib/stateView/nativeBeaconStateView.js +6 -0
- package/lib/stateView/nativeBeaconStateView.js.map +1 -1
- package/lib/stateView/stateViewFactory.js.map +1 -1
- package/lib/testUtils/infura.js.map +1 -1
- package/lib/testUtils/interop.js.map +1 -1
- package/lib/testUtils/params.d.ts.map +1 -1
- package/lib/testUtils/state.js +1 -1
- package/lib/testUtils/state.js.map +1 -1
- package/lib/testUtils/testFileCache.js.map +1 -1
- package/lib/testUtils/util.d.ts +17 -2
- package/lib/testUtils/util.d.ts.map +1 -1
- package/lib/testUtils/util.js +57 -4
- package/lib/testUtils/util.js.map +1 -1
- package/lib/types.d.ts +2 -2
- package/lib/types.d.ts.map +1 -1
- package/lib/util/aggregator.js.map +1 -1
- package/lib/util/altair.js.map +1 -1
- package/lib/util/array.js.map +1 -1
- package/lib/util/attestation.js.map +1 -1
- package/lib/util/attesterStatus.js.map +1 -1
- package/lib/util/balance.js.map +1 -1
- package/lib/util/blindedBlock.js.map +1 -1
- package/lib/util/blockRoot.js.map +1 -1
- package/lib/util/capella.js.map +1 -1
- package/lib/util/clock.d.ts +6 -0
- package/lib/util/clock.d.ts.map +1 -1
- package/lib/util/clock.js +1 -2
- package/lib/util/clock.js.map +1 -1
- package/lib/util/computeAnchorCheckpoint.js.map +1 -1
- package/lib/util/deposit.d.ts.map +1 -1
- package/lib/util/deposit.js +10 -8
- package/lib/util/deposit.js.map +1 -1
- package/lib/util/domain.js.map +1 -1
- package/lib/util/electra.js.map +1 -1
- package/lib/util/epoch.js.map +1 -1
- package/lib/util/epochShuffling.js.map +1 -1
- package/lib/util/execution.js.map +1 -1
- package/lib/util/finality.js.map +1 -1
- package/lib/util/fulu.js.map +1 -1
- package/lib/util/genesis.d.ts.map +1 -1
- package/lib/util/genesis.js +7 -2
- package/lib/util/genesis.js.map +1 -1
- package/lib/util/gloas.d.ts +2 -1
- package/lib/util/gloas.d.ts.map +1 -1
- package/lib/util/gloas.js +7 -4
- package/lib/util/gloas.js.map +1 -1
- package/lib/util/index.d.ts +1 -0
- package/lib/util/index.d.ts.map +1 -1
- package/lib/util/index.js +1 -0
- package/lib/util/index.js.map +1 -1
- package/lib/util/interop.js.map +1 -1
- package/lib/util/loadState/findModifiedInactivityScores.js.map +1 -1
- package/lib/util/loadState/findModifiedValidators.js.map +1 -1
- package/lib/util/loadState/loadState.d.ts.map +1 -1
- package/lib/util/loadState/loadState.js +36 -5
- package/lib/util/loadState/loadState.js.map +1 -1
- package/lib/util/loadState/loadValidator.js.map +1 -1
- package/lib/util/pendingDepositsLookup.d.ts +7 -10
- package/lib/util/pendingDepositsLookup.d.ts.map +1 -1
- package/lib/util/pendingDepositsLookup.js +10 -19
- package/lib/util/pendingDepositsLookup.js.map +1 -1
- package/lib/util/preVerifyBuilderDeposits.d.ts +52 -0
- package/lib/util/preVerifyBuilderDeposits.d.ts.map +1 -0
- package/lib/util/preVerifyBuilderDeposits.js +124 -0
- package/lib/util/preVerifyBuilderDeposits.js.map +1 -0
- package/lib/util/rootCache.js.map +1 -1
- package/lib/util/seed.js.map +1 -1
- package/lib/util/shuffling.js +1 -2
- package/lib/util/shuffling.js.map +1 -1
- package/lib/util/signatureSets.js +1 -2
- package/lib/util/signatureSets.js.map +1 -1
- package/lib/util/signingRoot.js.map +1 -1
- package/lib/util/slot.js.map +1 -1
- package/lib/util/ssz.d.ts +5 -0
- package/lib/util/ssz.d.ts.map +1 -1
- package/lib/util/ssz.js +8 -1
- package/lib/util/ssz.js.map +1 -1
- package/lib/util/sszBytes.js.map +1 -1
- package/lib/util/syncCommittee.js.map +1 -1
- package/lib/util/targetUnslashedBalance.js.map +1 -1
- package/lib/util/validator.d.ts +5 -0
- package/lib/util/validator.d.ts.map +1 -1
- package/lib/util/validator.js +9 -0
- package/lib/util/validator.js.map +1 -1
- package/lib/util/weakSubjectivity.d.ts +1 -0
- package/lib/util/weakSubjectivity.d.ts.map +1 -1
- package/lib/util/weakSubjectivity.js +20 -8
- package/lib/util/weakSubjectivity.js.map +1 -1
- package/package.json +9 -9
- package/src/block/index.ts +4 -3
- package/src/block/processAttestations.ts +10 -2
- package/src/block/processAttestationsAltair.ts +10 -4
- package/src/block/processDeposit.ts +75 -1
- package/src/block/processExecutionPayloadBid.ts +22 -9
- package/src/block/processOperations.ts +3 -2
- package/src/block/processWithdrawalRequest.ts +6 -2
- package/src/cache/builderDepositSignatureCache.ts +81 -0
- package/src/cache/epochCache.ts +14 -0
- package/src/cache/stateCache.ts +5 -2
- package/src/cache/types.ts +1 -0
- package/src/index.ts +4 -0
- package/src/lightClient/spec/utils.ts +9 -2
- package/src/metrics.ts +3 -2
- package/src/rewards/blockRewards.ts +20 -5
- package/src/signatureSets/executionPayloadBid.ts +7 -9
- package/src/slot/index.ts +1 -0
- package/src/slot/upgradeStateToAltair.ts +1 -0
- package/src/slot/upgradeStateToGloas.ts +18 -11
- package/src/slot/upgradeStateToHeze.ts +91 -0
- package/src/stateTransition.ts +5 -0
- package/src/stateView/beaconStateView.ts +13 -0
- package/src/stateView/interface.ts +21 -2
- package/src/stateView/nativeBeaconStateView.ts +9 -0
- package/src/testUtils/state.ts +1 -1
- package/src/testUtils/util.ts +75 -5
- package/src/types.ts +2 -0
- package/src/util/deposit.ts +11 -9
- package/src/util/genesis.ts +8 -2
- package/src/util/gloas.ts +9 -5
- package/src/util/index.ts +1 -0
- package/src/util/loadState/loadState.ts +50 -11
- package/src/util/pendingDepositsLookup.ts +13 -24
- package/src/util/preVerifyBuilderDeposits.ts +153 -0
- package/src/util/ssz.ts +9 -1
- package/src/util/validator.ts +17 -0
- package/src/util/weakSubjectivity.ts +61 -22
|
@@ -25,10 +25,29 @@ export function loadState(
|
|
|
25
25
|
): MigrateStateOutput {
|
|
26
26
|
// casting only to make typescript happy
|
|
27
27
|
const stateType = getStateTypeFromBytes(config, stateBytes) as typeof ssz.capella.BeaconState;
|
|
28
|
+
const fork = getForkFromStateBytes(config, stateBytes);
|
|
29
|
+
const seedFork = config.getForkSeq(seedState.slot);
|
|
30
|
+
|
|
28
31
|
const dataView = new DataView(stateBytes.buffer, stateBytes.byteOffset, stateBytes.byteLength);
|
|
29
32
|
const fieldRanges = stateType.getFieldRanges(dataView, 0, stateBytes.length);
|
|
30
33
|
const allFields = Object.keys(stateType.fields);
|
|
31
34
|
const validatorsFieldIndex = allFields.indexOf("validators");
|
|
35
|
+
const validatorsRange = fieldRanges[validatorsFieldIndex];
|
|
36
|
+
const newValidatorsBytes = stateBytes.subarray(validatorsRange.start, validatorsRange.end);
|
|
37
|
+
|
|
38
|
+
// EIP-7688 replaces List with ProgressiveList for validators and inactivityScores at gloas,
|
|
39
|
+
// changing the merkle tree shape. Seed nodes cannot be reused when one state is pre-gloas
|
|
40
|
+
// and the other post-gloas.
|
|
41
|
+
const crossesGloasFork =
|
|
42
|
+
(fork >= ForkSeq.gloas && seedFork < ForkSeq.gloas) || (fork < ForkSeq.gloas && seedFork >= ForkSeq.gloas);
|
|
43
|
+
if (crossesGloasFork) {
|
|
44
|
+
const migratedState = stateType.deserializeToViewDU(stateBytes) as BeaconStateAllForks;
|
|
45
|
+
// modified validators must still be reported so that the pubkey cache is refreshed for
|
|
46
|
+
// any index that differs from the seed state, which may not be an ancestor of this state
|
|
47
|
+
const modifiedValidators = findModifiedAndAppendedValidators(seedState, newValidatorsBytes, seedValidatorsBytes);
|
|
48
|
+
return {state: migratedState, modifiedValidators};
|
|
49
|
+
}
|
|
50
|
+
|
|
32
51
|
// start with default view has the same performance to start with seed state
|
|
33
52
|
// and it is not fork dependent
|
|
34
53
|
const migratedState = deserializeContainerIgnoreFields(
|
|
@@ -39,19 +58,10 @@ export function loadState(
|
|
|
39
58
|
) as BeaconStateAllForks;
|
|
40
59
|
|
|
41
60
|
// validators are rarely changed
|
|
42
|
-
const
|
|
43
|
-
const modifiedValidators = loadValidators(
|
|
44
|
-
migratedState,
|
|
45
|
-
seedState,
|
|
46
|
-
stateBytes.subarray(validatorsRange.start, validatorsRange.end),
|
|
47
|
-
seedValidatorsBytes
|
|
48
|
-
);
|
|
61
|
+
const modifiedValidators = loadValidators(migratedState, seedState, newValidatorsBytes, seedValidatorsBytes);
|
|
49
62
|
|
|
50
63
|
// inactivityScores are rarely changed
|
|
51
64
|
// this saves ~500ms of hashTreeRoot() time of state
|
|
52
|
-
const fork = getForkFromStateBytes(config, stateBytes);
|
|
53
|
-
const seedFork = config.getForkSeq(seedState.slot);
|
|
54
|
-
|
|
55
65
|
if (fork >= ForkSeq.altair && seedFork >= ForkSeq.altair) {
|
|
56
66
|
const inactivityScoresIndex = allFields.indexOf("inactivityScores");
|
|
57
67
|
const inactivityScoresRange = fieldRanges[inactivityScoresIndex];
|
|
@@ -141,7 +151,9 @@ function loadInactivityScores(
|
|
|
141
151
|
}
|
|
142
152
|
} else {
|
|
143
153
|
if (newValidator - 1 < 0) {
|
|
144
|
-
|
|
154
|
+
// use the state's own field type, the list shape differs between altair (List) and gloas (ProgressiveList)
|
|
155
|
+
const inactivityScoresType = (migratedState.type as typeof ssz.altair.BeaconState).fields.inactivityScores;
|
|
156
|
+
migratedState.inactivityScores = inactivityScoresType.defaultViewDU();
|
|
145
157
|
} else {
|
|
146
158
|
migratedState.inactivityScores = migratedState.inactivityScores.sliceTo(newValidator - 1);
|
|
147
159
|
}
|
|
@@ -177,6 +189,33 @@ function loadInactivityScores(
|
|
|
177
189
|
* @param migratedState state to be migrated, the validators are loaded to this state
|
|
178
190
|
* @returns modified validator indices
|
|
179
191
|
*/
|
|
192
|
+
/**
|
|
193
|
+
* Find indices of validators whose serialized bytes differ from the seed state, plus indices
|
|
194
|
+
* appended past the seed state's validator count. Unlike loadValidators() this only diffs
|
|
195
|
+
* bytes and does not share the seed state's tree.
|
|
196
|
+
*/
|
|
197
|
+
function findModifiedAndAppendedValidators(
|
|
198
|
+
seedState: BeaconStateAllForks,
|
|
199
|
+
newValidatorsBytes: Uint8Array,
|
|
200
|
+
seedStateValidatorsBytes?: Uint8Array
|
|
201
|
+
): number[] {
|
|
202
|
+
const seedValidatorCount = seedState.validators.length;
|
|
203
|
+
const newValidatorCount = Math.floor(newValidatorsBytes.length / VALIDATOR_BYTES_SIZE);
|
|
204
|
+
const minValidatorCount = Math.min(seedValidatorCount, newValidatorCount);
|
|
205
|
+
const seedValidatorsBytes = seedStateValidatorsBytes ?? seedState.validators.serialize();
|
|
206
|
+
const modifiedValidators: number[] = [];
|
|
207
|
+
findModifiedValidators(
|
|
208
|
+
seedValidatorsBytes.subarray(0, minValidatorCount * VALIDATOR_BYTES_SIZE),
|
|
209
|
+
newValidatorsBytes.subarray(0, minValidatorCount * VALIDATOR_BYTES_SIZE),
|
|
210
|
+
modifiedValidators
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
for (let validatorIndex = seedValidatorCount; validatorIndex < newValidatorCount; validatorIndex++) {
|
|
214
|
+
modifiedValidators.push(validatorIndex);
|
|
215
|
+
}
|
|
216
|
+
return modifiedValidators;
|
|
217
|
+
}
|
|
218
|
+
|
|
180
219
|
function loadValidators(
|
|
181
220
|
migratedState: BeaconStateAllForks,
|
|
182
221
|
seedState: BeaconStateAllForks,
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import {BeaconConfig} from "@lodestar/config";
|
|
2
2
|
import {PubkeyHex, electra} from "@lodestar/types";
|
|
3
|
-
import {toPubkeyHex} from "@lodestar/utils";
|
|
4
3
|
import {isValidDepositSignature} from "../block/processDeposit.js";
|
|
5
|
-
import {
|
|
4
|
+
import {BuilderDepositSignatureCache} from "../cache/builderDepositSignatureCache.js";
|
|
6
5
|
|
|
7
6
|
type PendingDepositsValidation = {
|
|
8
7
|
hasValidSignature: boolean;
|
|
@@ -34,28 +33,14 @@ export class PendingDepositsLookup {
|
|
|
34
33
|
}
|
|
35
34
|
|
|
36
35
|
/**
|
|
37
|
-
*
|
|
38
|
-
* No BLS work is done here; signature verification happens lazily in `hasPendingValidator`.
|
|
36
|
+
* Append a pending deposit to the represented sequence, keyed by its (precomputed) `pubkeyHex`.
|
|
39
37
|
*/
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
for (const pendingDeposit of state.pendingDeposits.getAllReadonly()) {
|
|
43
|
-
lookup.add(pendingDeposit);
|
|
44
|
-
}
|
|
45
|
-
return lookup;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Append a pending deposit to the represented sequence.
|
|
50
|
-
* Pass `pubkeyHex` if the caller has already computed it.
|
|
51
|
-
*/
|
|
52
|
-
add(pendingDeposit: electra.PendingDeposit, pubkeyHex?: PubkeyHex): void {
|
|
53
|
-
const key = pubkeyHex ?? toPubkeyHex(pendingDeposit.pubkey);
|
|
54
|
-
const existing = this.depositsByPubkey.get(key);
|
|
38
|
+
add(pendingDeposit: electra.PendingDeposit, pubkeyHex: PubkeyHex): void {
|
|
39
|
+
const existing = this.depositsByPubkey.get(pubkeyHex);
|
|
55
40
|
if (existing) {
|
|
56
41
|
existing.push(pendingDeposit);
|
|
57
42
|
} else {
|
|
58
|
-
this.depositsByPubkey.set(
|
|
43
|
+
this.depositsByPubkey.set(pubkeyHex, [pendingDeposit]);
|
|
59
44
|
}
|
|
60
45
|
}
|
|
61
46
|
|
|
@@ -63,8 +48,11 @@ export class PendingDepositsLookup {
|
|
|
63
48
|
* Returns true if any pending deposit for `pubkeyHex` has a valid BLS deposit signature.
|
|
64
49
|
* Memoizes the result in `validationCache` so repeated checks for the same pubkey
|
|
65
50
|
* within a block only verify deposits that have not already been checked.
|
|
51
|
+
*
|
|
52
|
+
* Most of the time it should hit the BuilderDepositSignatureCache so we don't have to validate
|
|
53
|
+
* signatures here.
|
|
66
54
|
*/
|
|
67
|
-
hasPendingValidator(config: BeaconConfig, pubkeyHex: PubkeyHex): boolean {
|
|
55
|
+
hasPendingValidator(config: BeaconConfig, pubkeyHex: PubkeyHex, cache: BuilderDepositSignatureCache): boolean {
|
|
68
56
|
const validation = this.validationCache.get(pubkeyHex);
|
|
69
57
|
if (validation?.hasValidSignature === true) {
|
|
70
58
|
return true;
|
|
@@ -85,15 +73,16 @@ export class PendingDepositsLookup {
|
|
|
85
73
|
|
|
86
74
|
for (let i = startIndex; i < deposits.length; i++) {
|
|
87
75
|
const deposit = deposits[i];
|
|
88
|
-
|
|
76
|
+
const isValid =
|
|
77
|
+
cache.getSignatureValidity(deposit) ??
|
|
89
78
|
isValidDepositSignature(
|
|
90
79
|
config,
|
|
91
80
|
deposit.pubkey,
|
|
92
81
|
deposit.withdrawalCredentials,
|
|
93
82
|
deposit.amount,
|
|
94
83
|
deposit.signature
|
|
95
|
-
)
|
|
96
|
-
) {
|
|
84
|
+
);
|
|
85
|
+
if (isValid) {
|
|
97
86
|
this.validationCache.set(pubkeyHex, {hasValidSignature: true, validatedCount: i + 1});
|
|
98
87
|
return true;
|
|
99
88
|
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import {electra} from "@lodestar/types";
|
|
2
|
+
import {toPubkeyHex} from "@lodestar/utils";
|
|
3
|
+
import {verifyDepositSignatures} from "../block/processDeposit.js";
|
|
4
|
+
import {CachedBeaconStateFulu} from "../types.js";
|
|
5
|
+
import {isBuilderWithdrawalCredential} from "./gloas.js";
|
|
6
|
+
|
|
7
|
+
/** Verify queued deposit signatures in batches of this size. Also the time-box granularity: the
|
|
8
|
+
* deadline is checked once per batch, so overrun is bounded to a single batch. Exported for tests. */
|
|
9
|
+
export const BUILDER_DEPOSIT_BATCH_SIZE = 32;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Per-tick cap on builder deposits the prepareForNextSlot scanner will verify.
|
|
13
|
+
* ~2.7s for 10_000 BLS verifications on a typical server — fits within the slot budget while the
|
|
14
|
+
* pre-window (see GLOAS_PREVERIFY_WINDOW_EPOCHS) covers up to ~620k deposits over its duration.
|
|
15
|
+
*/
|
|
16
|
+
export const MAX_BUILDER_DEPOSITS_PER_SLOT = 10_000;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Number of epochs before GLOAS_FORK_EPOCH during which the prepareForNextSlot scanner pre-verifies
|
|
20
|
+
* builder-deposit signatures. Two: deposits arriving this late cannot collude with validator
|
|
21
|
+
* deposits — validator-vs-builder routing is decided at the fork boundary from what is already in
|
|
22
|
+
* pendingDeposits, so anything submitted inside this window is unambiguous.
|
|
23
|
+
*/
|
|
24
|
+
export const GLOAS_PREVERIFY_WINDOW_EPOCHS = 2;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Summary of a single `preVerifyBuilderDepositsPreGloas` call.
|
|
28
|
+
*/
|
|
29
|
+
export type PreVerifyBuilderDepositsResult = {
|
|
30
|
+
/** Builder-prefix deposit signatures verified valid in this call (cached true). */
|
|
31
|
+
validBuilderSignaturesCount: number;
|
|
32
|
+
/** Builder-prefix deposit signatures verified invalid in this call (cached false, dropped at fork). */
|
|
33
|
+
invalidBuilderSignaturesCount: number;
|
|
34
|
+
/** Validator (builder-pubkey) deposit signatures verified valid in this call. */
|
|
35
|
+
validValidatorSignaturesCount: number;
|
|
36
|
+
/** Validator (builder-pubkey) deposit signatures verified invalid in this call (abuse signal). */
|
|
37
|
+
invalidValidatorSignaturesCount: number;
|
|
38
|
+
/** Pending deposits examined this call (all creds; < pendingDepositsCount ⇒ per-tick cap hit). */
|
|
39
|
+
scannedPendingDeposits: number;
|
|
40
|
+
/** Cumulative deposits verified & cached so far this window (cache size, pass + fail). */
|
|
41
|
+
totalCachedDeposits: number;
|
|
42
|
+
/** Distinct builder pubkeys tracked so far this window. */
|
|
43
|
+
totalBuilderPubkeys: number;
|
|
44
|
+
/** Current `state.pendingDeposits.length` — the full backlog. */
|
|
45
|
+
pendingDepositsCount: number;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Scanner driven by `prepareForNextSlot` over the `GLOAS_PREVERIFY_WINDOW_EPOCHS` epochs before
|
|
50
|
+
* GLOAS_FORK_EPOCH. Walks `state.pendingDeposits` (as struct values via getAllReadonlyValues) and
|
|
51
|
+
* queues, for signature verification, the deposits the fork transition will check on its hot path:
|
|
52
|
+
* - builder-prefix deposits (for onboarding); records each builder pubkey on the cache, and
|
|
53
|
+
* - validator deposits sharing a builder pubkey (the set `hasPendingValidator` walks at the fork),
|
|
54
|
+
* but only until one is found valid — `hasPendingValidator` stops at the first valid signature, so
|
|
55
|
+
* the cache marks the pubkey and the scanner skips that pubkey's remaining validator deposits.
|
|
56
|
+
*
|
|
57
|
+
* Bounded by two knobs: at most `maxBuilderDeposits` new deposits are queued per call, and the chunk
|
|
58
|
+
* verification is **time-boxed** to `maxDurationMs`.
|
|
59
|
+
*/
|
|
60
|
+
export function preVerifyBuilderDepositsPreGloas(
|
|
61
|
+
state: CachedBeaconStateFulu,
|
|
62
|
+
maxBuilderDeposits: number,
|
|
63
|
+
maxDurationMs: number
|
|
64
|
+
): PreVerifyBuilderDepositsResult {
|
|
65
|
+
const cache = state.epochCtx.builderDepositSignatureCache;
|
|
66
|
+
|
|
67
|
+
// Collect uncached deposits to verify as struct values. Full rescan each tick: iteration is
|
|
68
|
+
// O(pendingDeposits) but runs in prepareNextSlot spare time, and isVerified() is an O(1) skip for
|
|
69
|
+
// already-cached deposits. For a ContainerNodeStructType, getAllReadonlyValues() returns each
|
|
70
|
+
// node.value by reference — the stable cache key.
|
|
71
|
+
const queue: electra.PendingDeposit[] = [];
|
|
72
|
+
let scannedPendingDeposits = 0;
|
|
73
|
+
for (const deposit of state.pendingDeposits.getAllReadonlyValues()) {
|
|
74
|
+
if (queue.length >= maxBuilderDeposits) break; // per-tick cap; next tick resumes via isVerified()
|
|
75
|
+
scannedPendingDeposits++;
|
|
76
|
+
if (cache.isVerified(deposit)) continue; // already verified in an earlier tick
|
|
77
|
+
|
|
78
|
+
if (isBuilderWithdrawalCredential(deposit.withdrawalCredentials)) {
|
|
79
|
+
// Record the builder pubkey so validator deposits sharing it get pre-verified — this or a
|
|
80
|
+
// later tick, since those validator deposits precede the builder deposit in the queue. A cached
|
|
81
|
+
// builder deposit already added its pubkey, so it's safe to skip via the `continue` above.
|
|
82
|
+
cache.addBuilderPubkey(toPubkeyHex(deposit.pubkey));
|
|
83
|
+
queue.push(deposit);
|
|
84
|
+
} else {
|
|
85
|
+
// Validator deposit — pre-verify only if it shares a builder pubkey (the set hasPendingValidator
|
|
86
|
+
// walks at the fork) AND we haven't already cached a valid validator deposit for that pubkey.
|
|
87
|
+
// this is the same logic to hasPendingValidator.
|
|
88
|
+
const pubkeyHex = toPubkeyHex(deposit.pubkey);
|
|
89
|
+
if (cache.isBuilderPubkey(pubkeyHex) && !cache.hasValidValidatorDeposit(pubkeyHex)) {
|
|
90
|
+
queue.push(deposit);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const pendingDepositsCount = state.pendingDeposits.length;
|
|
96
|
+
if (queue.length === 0) {
|
|
97
|
+
return {
|
|
98
|
+
validBuilderSignaturesCount: 0,
|
|
99
|
+
invalidBuilderSignaturesCount: 0,
|
|
100
|
+
validValidatorSignaturesCount: 0,
|
|
101
|
+
invalidValidatorSignaturesCount: 0,
|
|
102
|
+
scannedPendingDeposits,
|
|
103
|
+
totalCachedDeposits: cache.cachedDepositCount,
|
|
104
|
+
totalBuilderPubkeys: cache.builderPubkeyCount,
|
|
105
|
+
pendingDepositsCount,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Verify in chunks; chunking caps the fallback blast radius so one bad signature only forces 32
|
|
110
|
+
// individual re-verifications. Key each result by the deposit value object. Counts are tracked
|
|
111
|
+
// incrementally (not queue.length - verified) so they stay correct when we time-box out early.
|
|
112
|
+
const deadline = Date.now() + maxDurationMs;
|
|
113
|
+
let validBuilderSignaturesCount = 0;
|
|
114
|
+
let invalidBuilderSignaturesCount = 0;
|
|
115
|
+
let validValidatorSignaturesCount = 0;
|
|
116
|
+
let invalidValidatorSignaturesCount = 0;
|
|
117
|
+
for (let chunkStart = 0; chunkStart < queue.length; chunkStart += BUILDER_DEPOSIT_BATCH_SIZE) {
|
|
118
|
+
const end = Math.min(chunkStart + BUILDER_DEPOSIT_BATCH_SIZE, queue.length);
|
|
119
|
+
const chunk = queue.slice(chunkStart, end);
|
|
120
|
+
const chunkResults = verifyDepositSignatures(state.epochCtx.config, chunk);
|
|
121
|
+
for (let j = 0; j < chunk.length; j++) {
|
|
122
|
+
cache.setSignatureValidity(chunk[j], chunkResults[j]);
|
|
123
|
+
const isBuilder = isBuilderWithdrawalCredential(chunk[j].withdrawalCredentials);
|
|
124
|
+
if (chunkResults[j]) {
|
|
125
|
+
if (isBuilder) {
|
|
126
|
+
validBuilderSignaturesCount++;
|
|
127
|
+
} else {
|
|
128
|
+
validValidatorSignaturesCount++;
|
|
129
|
+
// A valid validator deposit satisfies hasPendingValidator() for this pubkey; stop
|
|
130
|
+
// pre-verifying its remaining validator deposits on later ticks.
|
|
131
|
+
cache.setValidValidatorDeposit(toPubkeyHex(chunk[j].pubkey));
|
|
132
|
+
}
|
|
133
|
+
} else if (isBuilder) {
|
|
134
|
+
invalidBuilderSignaturesCount++;
|
|
135
|
+
} else {
|
|
136
|
+
invalidValidatorSignaturesCount++;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Time-box: keep everything verified so far (already cached) and stop
|
|
140
|
+
if (Date.now() >= deadline) break;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
validBuilderSignaturesCount,
|
|
145
|
+
invalidBuilderSignaturesCount,
|
|
146
|
+
validValidatorSignaturesCount,
|
|
147
|
+
invalidValidatorSignaturesCount,
|
|
148
|
+
scannedPendingDeposits,
|
|
149
|
+
totalCachedDeposits: cache.cachedDepositCount,
|
|
150
|
+
totalBuilderPubkeys: cache.builderPubkeyCount,
|
|
151
|
+
pendingDepositsCount,
|
|
152
|
+
};
|
|
153
|
+
}
|
package/src/util/ssz.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {BranchNode, LeafNode, Node, zeroNode} from "@chainsafe/persistent-merkle-tree";
|
|
2
2
|
import {progressiveSubtreeFillToContents} from "@chainsafe/ssz";
|
|
3
3
|
|
|
4
|
-
// TODO: move these utils to @chainsafe/ssz
|
|
4
|
+
// TODO: move these utils to @chainsafe/ssz, see https://github.com/ChainSafe/ssz/issues/542
|
|
5
5
|
|
|
6
6
|
/** Root node (chunks + length mix-in) of a zero-filled ProgressiveListBasicType of `length` items */
|
|
7
7
|
export function zeroProgressiveListBasicRootNode(itemsPerChunk: number, length: number): Node {
|
|
@@ -15,6 +15,14 @@ export function zeroProgressiveListBasicRootNode(itemsPerChunk: number, length:
|
|
|
15
15
|
return new BranchNode(zeroProgressiveNode(numSubtrees), LeafNode.fromUint32(length));
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Check if an array-type ViewDU (ListBasic, ListComposite or their progressive equivalents) has its
|
|
20
|
+
* internal nodes cache populated. The flag is a private attribute maintained by all of these classes.
|
|
21
|
+
*/
|
|
22
|
+
export function isViewDUNodesPopulated(view: unknown): boolean {
|
|
23
|
+
return (view as {nodesPopulated?: boolean}).nodesPopulated === true;
|
|
24
|
+
}
|
|
25
|
+
|
|
18
26
|
/**
|
|
19
27
|
* Root node of a progressive list from its chunk/element nodes + length mix-in.
|
|
20
28
|
* `nodes` are packed 32-byte chunk leaves for basic lists, or element root nodes for composite lists.
|
package/src/util/validator.ts
CHANGED
|
@@ -128,6 +128,23 @@ export function getConsolidationChurnLimit(fork: ForkSeq, epochCtx: EpochCache):
|
|
|
128
128
|
return getBalanceChurnLimitFromCache(epochCtx) - getActivationExitChurnLimit(epochCtx);
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
// NOTE: duplicates the quotient/min choices in get{Exit,Activation,Consolidation}ChurnLimit.
|
|
132
|
+
export function getGloasChurnLimits(
|
|
133
|
+
config: ChainForkConfig,
|
|
134
|
+
totalActiveBalanceIncrements: number
|
|
135
|
+
): {exit: number; activation: number; consolidation: number} {
|
|
136
|
+
const exit = getBalanceChurnLimit(
|
|
137
|
+
totalActiveBalanceIncrements,
|
|
138
|
+
config.CHURN_LIMIT_QUOTIENT_GLOAS,
|
|
139
|
+
config.MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA
|
|
140
|
+
);
|
|
141
|
+
return {
|
|
142
|
+
exit,
|
|
143
|
+
activation: Math.min(config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT_GLOAS, exit),
|
|
144
|
+
consolidation: getBalanceChurnLimit(totalActiveBalanceIncrements, config.CONSOLIDATION_CHURN_LIMIT_QUOTIENT, 0),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
131
148
|
export function getMaxEffectiveBalance(withdrawalCredentials: Uint8Array): number {
|
|
132
149
|
// Compounding withdrawal credential only available since Electra
|
|
133
150
|
if (hasCompoundingWithdrawalCredential(withdrawalCredentials)) {
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import {BeaconConfig, ChainForkConfig} from "@lodestar/config";
|
|
2
2
|
import {
|
|
3
3
|
EFFECTIVE_BALANCE_INCREMENT,
|
|
4
|
+
ForkSeq,
|
|
4
5
|
MAX_DEPOSITS,
|
|
5
6
|
MAX_EFFECTIVE_BALANCE,
|
|
6
7
|
SLOTS_PER_EPOCH,
|
|
7
8
|
isForkPostElectra,
|
|
9
|
+
isForkPostGloas,
|
|
8
10
|
} from "@lodestar/params";
|
|
9
11
|
import {Epoch, Root, ssz} from "@lodestar/types";
|
|
10
12
|
import {Checkpoint} from "@lodestar/types/phase0";
|
|
@@ -14,10 +16,14 @@ import {BeaconStateAllForks, CachedBeaconStateAllForks} from "../types.js";
|
|
|
14
16
|
import {computeCheckpointEpochAtStateSlot, computeEpochAtSlot, getCurrentEpoch} from "./epoch.js";
|
|
15
17
|
import {getCurrentSlot} from "./slot.js";
|
|
16
18
|
import {
|
|
19
|
+
getActivationChurnLimit,
|
|
17
20
|
getActiveValidatorIndices,
|
|
18
21
|
getBalanceChurnLimit,
|
|
19
22
|
getBalanceChurnLimitFromCache,
|
|
20
23
|
getChurnLimit,
|
|
24
|
+
getConsolidationChurnLimit,
|
|
25
|
+
getExitChurnLimit,
|
|
26
|
+
getGloasChurnLimits,
|
|
21
27
|
} from "./validator.js";
|
|
22
28
|
|
|
23
29
|
export const ETH_TO_GWEI = 10 ** 9;
|
|
@@ -49,18 +55,26 @@ export function computeWeakSubjectivityPeriodCachedState(
|
|
|
49
55
|
const activeValidatorCount = state.epochCtx.currentShuffling.activeIndices.length;
|
|
50
56
|
const fork = config.getForkName(state.slot);
|
|
51
57
|
|
|
52
|
-
return
|
|
53
|
-
?
|
|
58
|
+
return isForkPostGloas(fork)
|
|
59
|
+
? computeWeakSubjectivityPeriodFromConstituentsGloas(
|
|
54
60
|
state.epochCtx.totalActiveBalanceIncrements,
|
|
55
|
-
|
|
61
|
+
getExitChurnLimit(state.epochCtx),
|
|
62
|
+
getActivationChurnLimit(state.epochCtx),
|
|
63
|
+
getConsolidationChurnLimit(ForkSeq.gloas, state.epochCtx),
|
|
56
64
|
config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY
|
|
57
65
|
)
|
|
58
|
-
:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
: isForkPostElectra(fork)
|
|
67
|
+
? computeWeakSubjectivityPeriodFromConstituentsElectra(
|
|
68
|
+
state.epochCtx.totalActiveBalanceIncrements,
|
|
69
|
+
getBalanceChurnLimitFromCache(state.epochCtx),
|
|
70
|
+
config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY
|
|
71
|
+
)
|
|
72
|
+
: computeWeakSubjectivityPeriodFromConstituentsPhase0(
|
|
73
|
+
activeValidatorCount,
|
|
74
|
+
state.epochCtx.totalActiveBalanceIncrements,
|
|
75
|
+
getChurnLimit(config, activeValidatorCount),
|
|
76
|
+
config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY
|
|
77
|
+
);
|
|
64
78
|
}
|
|
65
79
|
|
|
66
80
|
/**
|
|
@@ -80,22 +94,32 @@ export function computeWeakSubjectivityPeriod(config: ChainForkConfig, state: Be
|
|
|
80
94
|
totalActiveBalanceIncrements = 1;
|
|
81
95
|
}
|
|
82
96
|
|
|
83
|
-
|
|
84
|
-
|
|
97
|
+
const churnLimitsGloas = getGloasChurnLimits(config, totalActiveBalanceIncrements);
|
|
98
|
+
|
|
99
|
+
return isForkPostGloas(fork)
|
|
100
|
+
? computeWeakSubjectivityPeriodFromConstituentsGloas(
|
|
85
101
|
totalActiveBalanceIncrements,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
config.MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA
|
|
90
|
-
),
|
|
102
|
+
churnLimitsGloas.exit,
|
|
103
|
+
churnLimitsGloas.activation,
|
|
104
|
+
churnLimitsGloas.consolidation,
|
|
91
105
|
config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY
|
|
92
106
|
)
|
|
93
|
-
:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
107
|
+
: isForkPostElectra(fork)
|
|
108
|
+
? computeWeakSubjectivityPeriodFromConstituentsElectra(
|
|
109
|
+
totalActiveBalanceIncrements,
|
|
110
|
+
getBalanceChurnLimit(
|
|
111
|
+
totalActiveBalanceIncrements,
|
|
112
|
+
config.CHURN_LIMIT_QUOTIENT,
|
|
113
|
+
config.MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA
|
|
114
|
+
),
|
|
115
|
+
config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY
|
|
116
|
+
)
|
|
117
|
+
: computeWeakSubjectivityPeriodFromConstituentsPhase0(
|
|
118
|
+
activeIndices.length,
|
|
119
|
+
totalActiveBalanceIncrements,
|
|
120
|
+
getChurnLimit(config, activeIndices.length),
|
|
121
|
+
config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY
|
|
122
|
+
);
|
|
99
123
|
}
|
|
100
124
|
|
|
101
125
|
export function computeWeakSubjectivityPeriodFromConstituentsPhase0(
|
|
@@ -142,6 +166,21 @@ export function computeWeakSubjectivityPeriodFromConstituentsElectra(
|
|
|
142
166
|
return minWithdrawabilityDelay + epochsForValidatorSetChurn;
|
|
143
167
|
}
|
|
144
168
|
|
|
169
|
+
export function computeWeakSubjectivityPeriodFromConstituentsGloas(
|
|
170
|
+
totalBalanceByIncrement: number,
|
|
171
|
+
exitChurnLimit: number,
|
|
172
|
+
activationChurnLimit: number,
|
|
173
|
+
consolidationChurnLimit: number,
|
|
174
|
+
minWithdrawabilityDelay: number
|
|
175
|
+
): number {
|
|
176
|
+
// Keep t as increment for now. Multiply final result by EFFECTIVE_BALANCE_INCREMENT
|
|
177
|
+
const t = totalBalanceByIncrement;
|
|
178
|
+
const delta = Math.floor((2 * exitChurnLimit) / 3) + Math.floor(activationChurnLimit / 3) + consolidationChurnLimit;
|
|
179
|
+
const epochsForValidatorSetChurn = Math.floor(((SAFETY_DECAY * t) / (2 * delta * 100)) * EFFECTIVE_BALANCE_INCREMENT);
|
|
180
|
+
|
|
181
|
+
return minWithdrawabilityDelay + epochsForValidatorSetChurn;
|
|
182
|
+
}
|
|
183
|
+
|
|
145
184
|
export function getLatestBlockRoot(state: BeaconStateAllForks): Root {
|
|
146
185
|
const header = ssz.phase0.BeaconBlockHeader.clone(state.latestBlockHeader);
|
|
147
186
|
if (ssz.Root.equals(header.stateRoot, ZERO_HASH)) {
|