@lodestar/state-transition 1.35.0-dev.98d359db41 → 1.35.0-dev.b42a298a7c
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/package.json +11 -9
- package/lib/block/externalData.d.ts.map +0 -1
- package/lib/block/index.d.ts.map +0 -1
- package/lib/block/initiateValidatorExit.d.ts.map +0 -1
- package/lib/block/isValidIndexedAttestation.d.ts.map +0 -1
- package/lib/block/processAttestationPhase0.d.ts.map +0 -1
- package/lib/block/processAttestations.d.ts.map +0 -1
- package/lib/block/processAttestationsAltair.d.ts.map +0 -1
- package/lib/block/processAttesterSlashing.d.ts.map +0 -1
- package/lib/block/processBlobKzgCommitments.d.ts.map +0 -1
- package/lib/block/processBlockHeader.d.ts.map +0 -1
- package/lib/block/processBlsToExecutionChange.d.ts.map +0 -1
- package/lib/block/processConsolidationRequest.d.ts.map +0 -1
- package/lib/block/processDeposit.d.ts.map +0 -1
- package/lib/block/processDepositRequest.d.ts.map +0 -1
- package/lib/block/processEth1Data.d.ts.map +0 -1
- package/lib/block/processExecutionPayload.d.ts.map +0 -1
- package/lib/block/processOperations.d.ts.map +0 -1
- package/lib/block/processProposerSlashing.d.ts.map +0 -1
- package/lib/block/processRandao.d.ts.map +0 -1
- package/lib/block/processSyncCommittee.d.ts.map +0 -1
- package/lib/block/processVoluntaryExit.d.ts.map +0 -1
- package/lib/block/processWithdrawalRequest.d.ts.map +0 -1
- package/lib/block/processWithdrawals.d.ts.map +0 -1
- package/lib/block/slashValidator.d.ts.map +0 -1
- package/lib/block/types.d.ts.map +0 -1
- package/lib/cache/effectiveBalanceIncrements.d.ts.map +0 -1
- package/lib/cache/epochCache.d.ts.map +0 -1
- package/lib/cache/epochTransitionCache.d.ts.map +0 -1
- package/lib/cache/pubkeyCache.d.ts.map +0 -1
- package/lib/cache/rewardCache.d.ts.map +0 -1
- package/lib/cache/stateCache.d.ts.map +0 -1
- package/lib/cache/syncCommitteeCache.d.ts.map +0 -1
- package/lib/cache/types.d.ts.map +0 -1
- package/lib/constants/constants.d.ts.map +0 -1
- package/lib/constants/index.d.ts.map +0 -1
- package/lib/epoch/computeUnrealizedCheckpoints.d.ts.map +0 -1
- package/lib/epoch/getAttestationDeltas.d.ts.map +0 -1
- package/lib/epoch/getRewardsAndPenalties.d.ts.map +0 -1
- package/lib/epoch/index.d.ts.map +0 -1
- package/lib/epoch/processEffectiveBalanceUpdates.d.ts.map +0 -1
- package/lib/epoch/processEth1DataReset.d.ts.map +0 -1
- package/lib/epoch/processHistoricalRootsUpdate.d.ts.map +0 -1
- package/lib/epoch/processHistoricalSummariesUpdate.d.ts.map +0 -1
- package/lib/epoch/processInactivityUpdates.d.ts.map +0 -1
- package/lib/epoch/processJustificationAndFinalization.d.ts.map +0 -1
- package/lib/epoch/processParticipationFlagUpdates.d.ts.map +0 -1
- package/lib/epoch/processParticipationRecordUpdates.d.ts.map +0 -1
- package/lib/epoch/processPendingAttestations.d.ts.map +0 -1
- package/lib/epoch/processPendingConsolidations.d.ts.map +0 -1
- package/lib/epoch/processPendingDeposits.d.ts.map +0 -1
- package/lib/epoch/processProposerLookahead.d.ts.map +0 -1
- package/lib/epoch/processRandaoMixesReset.d.ts.map +0 -1
- package/lib/epoch/processRegistryUpdates.d.ts.map +0 -1
- package/lib/epoch/processRewardsAndPenalties.d.ts.map +0 -1
- package/lib/epoch/processSlashings.d.ts.map +0 -1
- package/lib/epoch/processSlashingsReset.d.ts.map +0 -1
- package/lib/epoch/processSyncCommitteeUpdates.d.ts.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/metrics.d.ts.map +0 -1
- package/lib/signatureSets/attesterSlashings.d.ts.map +0 -1
- package/lib/signatureSets/blsToExecutionChange.d.ts.map +0 -1
- package/lib/signatureSets/index.d.ts.map +0 -1
- package/lib/signatureSets/indexedAttestation.d.ts.map +0 -1
- package/lib/signatureSets/proposer.d.ts.map +0 -1
- package/lib/signatureSets/proposerSlashings.d.ts.map +0 -1
- package/lib/signatureSets/randao.d.ts.map +0 -1
- package/lib/signatureSets/voluntaryExits.d.ts.map +0 -1
- package/lib/slot/index.d.ts.map +0 -1
- package/lib/slot/upgradeStateToAltair.d.ts.map +0 -1
- package/lib/slot/upgradeStateToBellatrix.d.ts.map +0 -1
- package/lib/slot/upgradeStateToCapella.d.ts.map +0 -1
- package/lib/slot/upgradeStateToDeneb.d.ts.map +0 -1
- package/lib/slot/upgradeStateToElectra.d.ts.map +0 -1
- package/lib/slot/upgradeStateToFulu.d.ts.map +0 -1
- package/lib/slot/upgradeStateToGloas.d.ts.map +0 -1
- package/lib/stateTransition.d.ts.map +0 -1
- package/lib/types.d.ts.map +0 -1
- package/lib/util/aggregator.d.ts.map +0 -1
- package/lib/util/altair.d.ts.map +0 -1
- package/lib/util/array.d.ts.map +0 -1
- package/lib/util/attestation.d.ts.map +0 -1
- package/lib/util/attesterStatus.d.ts.map +0 -1
- package/lib/util/balance.d.ts.map +0 -1
- package/lib/util/blindedBlock.d.ts.map +0 -1
- package/lib/util/blockRoot.d.ts.map +0 -1
- package/lib/util/calculateCommitteeAssignments.d.ts.map +0 -1
- package/lib/util/capella.d.ts.map +0 -1
- package/lib/util/computeAnchorCheckpoint.d.ts.map +0 -1
- package/lib/util/deposit.d.ts.map +0 -1
- package/lib/util/domain.d.ts.map +0 -1
- package/lib/util/electra.d.ts.map +0 -1
- package/lib/util/epoch.d.ts.map +0 -1
- package/lib/util/epochShuffling.d.ts.map +0 -1
- package/lib/util/execution.d.ts.map +0 -1
- package/lib/util/finality.d.ts.map +0 -1
- package/lib/util/fulu.d.ts.map +0 -1
- package/lib/util/genesis.d.ts.map +0 -1
- package/lib/util/index.d.ts.map +0 -1
- package/lib/util/interop.d.ts.map +0 -1
- package/lib/util/loadState/findModifiedInactivityScores.d.ts.map +0 -1
- package/lib/util/loadState/findModifiedValidators.d.ts.map +0 -1
- package/lib/util/loadState/index.d.ts.map +0 -1
- package/lib/util/loadState/loadState.d.ts.map +0 -1
- package/lib/util/loadState/loadValidator.d.ts.map +0 -1
- package/lib/util/rootCache.d.ts.map +0 -1
- package/lib/util/seed.d.ts.map +0 -1
- package/lib/util/shufflingDecisionRoot.d.ts.map +0 -1
- package/lib/util/signatureSets.d.ts.map +0 -1
- package/lib/util/signingRoot.d.ts.map +0 -1
- package/lib/util/slot.d.ts.map +0 -1
- package/lib/util/sszBytes.d.ts.map +0 -1
- package/lib/util/syncCommittee.d.ts.map +0 -1
- package/lib/util/targetUnslashedBalance.d.ts.map +0 -1
- package/lib/util/validator.d.ts.map +0 -1
- package/lib/util/weakSubjectivity.d.ts.map +0 -1
- package/src/block/externalData.ts +0 -26
- package/src/block/index.ts +0 -81
- package/src/block/initiateValidatorExit.ts +0 -62
- package/src/block/isValidIndexedAttestation.ts +0 -70
- package/src/block/processAttestationPhase0.ts +0 -158
- package/src/block/processAttestations.ts +0 -25
- package/src/block/processAttestationsAltair.ts +0 -184
- package/src/block/processAttesterSlashing.ts +0 -59
- package/src/block/processBlobKzgCommitments.ts +0 -21
- package/src/block/processBlockHeader.ts +0 -54
- package/src/block/processBlsToExecutionChange.ts +0 -78
- package/src/block/processConsolidationRequest.ts +0 -147
- package/src/block/processDeposit.ts +0 -166
- package/src/block/processDepositRequest.ts +0 -19
- package/src/block/processEth1Data.ts +0 -86
- package/src/block/processExecutionPayload.ts +0 -84
- package/src/block/processOperations.ts +0 -83
- package/src/block/processProposerSlashing.ts +0 -66
- package/src/block/processRandao.ts +0 -27
- package/src/block/processSyncCommittee.ts +0 -117
- package/src/block/processVoluntaryExit.ts +0 -55
- package/src/block/processWithdrawalRequest.ts +0 -98
- package/src/block/processWithdrawals.ts +0 -207
- package/src/block/slashValidator.ts +0 -98
- package/src/block/types.ts +0 -9
- package/src/cache/effectiveBalanceIncrements.ts +0 -39
- package/src/cache/epochCache.ts +0 -1213
- package/src/cache/epochTransitionCache.ts +0 -542
- package/src/cache/pubkeyCache.ts +0 -33
- package/src/cache/rewardCache.ts +0 -19
- package/src/cache/stateCache.ts +0 -268
- package/src/cache/syncCommitteeCache.ts +0 -96
- package/src/cache/types.ts +0 -18
- package/src/constants/constants.ts +0 -12
- package/src/constants/index.ts +0 -1
- package/src/epoch/computeUnrealizedCheckpoints.ts +0 -55
- package/src/epoch/getAttestationDeltas.ts +0 -169
- package/src/epoch/getRewardsAndPenalties.ts +0 -137
- package/src/epoch/index.ts +0 -202
- package/src/epoch/processEffectiveBalanceUpdates.ts +0 -111
- package/src/epoch/processEth1DataReset.ts +0 -17
- package/src/epoch/processHistoricalRootsUpdate.ts +0 -25
- package/src/epoch/processHistoricalSummariesUpdate.ts +0 -23
- package/src/epoch/processInactivityUpdates.ts +0 -60
- package/src/epoch/processJustificationAndFinalization.ts +0 -90
- package/src/epoch/processParticipationFlagUpdates.ts +0 -27
- package/src/epoch/processParticipationRecordUpdates.ts +0 -14
- package/src/epoch/processPendingAttestations.ts +0 -75
- package/src/epoch/processPendingConsolidations.ts +0 -59
- package/src/epoch/processPendingDeposits.ts +0 -136
- package/src/epoch/processProposerLookahead.ts +0 -39
- package/src/epoch/processRandaoMixesReset.ts +0 -18
- package/src/epoch/processRegistryUpdates.ts +0 -65
- package/src/epoch/processRewardsAndPenalties.ts +0 -58
- package/src/epoch/processSlashings.ts +0 -97
- package/src/epoch/processSlashingsReset.ts +0 -20
- package/src/epoch/processSyncCommitteeUpdates.ts +0 -44
- package/src/index.ts +0 -67
- package/src/metrics.ts +0 -169
- package/src/signatureSets/attesterSlashings.ts +0 -39
- package/src/signatureSets/blsToExecutionChange.ts +0 -43
- package/src/signatureSets/index.ts +0 -73
- package/src/signatureSets/indexedAttestation.ts +0 -51
- package/src/signatureSets/proposer.ts +0 -47
- package/src/signatureSets/proposerSlashings.ts +0 -41
- package/src/signatureSets/randao.ts +0 -31
- package/src/signatureSets/voluntaryExits.ts +0 -44
- package/src/slot/index.ts +0 -32
- package/src/slot/upgradeStateToAltair.ts +0 -149
- package/src/slot/upgradeStateToBellatrix.ts +0 -63
- package/src/slot/upgradeStateToCapella.ts +0 -71
- package/src/slot/upgradeStateToDeneb.ts +0 -40
- package/src/slot/upgradeStateToElectra.ts +0 -126
- package/src/slot/upgradeStateToFulu.ts +0 -31
- package/src/slot/upgradeStateToGloas.ts +0 -29
- package/src/stateTransition.ts +0 -305
- package/src/types.ts +0 -26
- package/src/util/aggregator.ts +0 -33
- package/src/util/altair.ts +0 -13
- package/src/util/array.ts +0 -53
- package/src/util/attestation.ts +0 -36
- package/src/util/attesterStatus.ts +0 -83
- package/src/util/balance.ts +0 -83
- package/src/util/blindedBlock.ts +0 -144
- package/src/util/blockRoot.ts +0 -72
- package/src/util/calculateCommitteeAssignments.ts +0 -43
- package/src/util/capella.ts +0 -8
- package/src/util/computeAnchorCheckpoint.ts +0 -38
- package/src/util/deposit.ts +0 -22
- package/src/util/domain.ts +0 -31
- package/src/util/electra.ts +0 -68
- package/src/util/epoch.ts +0 -135
- package/src/util/epochShuffling.ts +0 -185
- package/src/util/execution.ts +0 -177
- package/src/util/finality.ts +0 -17
- package/src/util/fulu.ts +0 -43
- package/src/util/genesis.ts +0 -343
- package/src/util/index.ts +0 -29
- package/src/util/interop.ts +0 -22
- package/src/util/loadState/findModifiedInactivityScores.ts +0 -47
- package/src/util/loadState/findModifiedValidators.ts +0 -46
- package/src/util/loadState/index.ts +0 -2
- package/src/util/loadState/loadState.ts +0 -225
- package/src/util/loadState/loadValidator.ts +0 -77
- package/src/util/rootCache.ts +0 -37
- package/src/util/seed.ts +0 -381
- package/src/util/shufflingDecisionRoot.ts +0 -78
- package/src/util/signatureSets.ts +0 -65
- package/src/util/signingRoot.ts +0 -13
- package/src/util/slot.ts +0 -27
- package/src/util/sszBytes.ts +0 -52
- package/src/util/syncCommittee.ts +0 -69
- package/src/util/targetUnslashedBalance.ts +0 -30
- package/src/util/validator.ts +0 -105
- package/src/util/weakSubjectivity.ts +0 -186
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import {byteArrayEquals} from "@chainsafe/ssz";
|
|
2
|
-
import {ForkName, ForkSeq, isForkPostDeneb} from "@lodestar/params";
|
|
3
|
-
import {BeaconBlockBody, BlindedBeaconBlockBody, deneb, isExecutionPayload} from "@lodestar/types";
|
|
4
|
-
import {toHex, toRootHex} from "@lodestar/utils";
|
|
5
|
-
import {CachedBeaconStateBellatrix, CachedBeaconStateCapella} from "../types.js";
|
|
6
|
-
import {
|
|
7
|
-
executionPayloadToPayloadHeader,
|
|
8
|
-
getFullOrBlindedPayloadFromBody,
|
|
9
|
-
isMergeTransitionComplete,
|
|
10
|
-
} from "../util/execution.js";
|
|
11
|
-
import {computeEpochAtSlot, getRandaoMix} from "../util/index.js";
|
|
12
|
-
import {BlockExternalData, ExecutionPayloadStatus} from "./externalData.js";
|
|
13
|
-
|
|
14
|
-
export function processExecutionPayload(
|
|
15
|
-
fork: ForkSeq,
|
|
16
|
-
state: CachedBeaconStateBellatrix | CachedBeaconStateCapella,
|
|
17
|
-
body: BeaconBlockBody | BlindedBeaconBlockBody,
|
|
18
|
-
externalData: Omit<BlockExternalData, "dataAvailabilityStatus">
|
|
19
|
-
): void {
|
|
20
|
-
const payload = getFullOrBlindedPayloadFromBody(body);
|
|
21
|
-
const forkName = ForkName[ForkSeq[fork] as ForkName];
|
|
22
|
-
// Verify consistency of the parent hash, block number, base fee per gas and gas limit
|
|
23
|
-
// with respect to the previous execution payload header
|
|
24
|
-
if (isMergeTransitionComplete(state)) {
|
|
25
|
-
const {latestExecutionPayloadHeader} = state;
|
|
26
|
-
if (!byteArrayEquals(payload.parentHash, latestExecutionPayloadHeader.blockHash)) {
|
|
27
|
-
throw Error(
|
|
28
|
-
`Invalid execution payload parentHash ${toRootHex(payload.parentHash)} latest blockHash ${toRootHex(
|
|
29
|
-
latestExecutionPayloadHeader.blockHash
|
|
30
|
-
)}`
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Verify random
|
|
36
|
-
const expectedRandom = getRandaoMix(state, state.epochCtx.epoch);
|
|
37
|
-
if (!byteArrayEquals(payload.prevRandao, expectedRandom)) {
|
|
38
|
-
throw Error(`Invalid execution payload random ${toHex(payload.prevRandao)} expected=${toHex(expectedRandom)}`);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Verify timestamp
|
|
42
|
-
//
|
|
43
|
-
// Note: inlined function in if statement
|
|
44
|
-
// def compute_timestamp_at_slot(state: BeaconState, slot: Slot) -> uint64:
|
|
45
|
-
// slots_since_genesis = slot - GENESIS_SLOT
|
|
46
|
-
// return uint64(state.genesis_time + slots_since_genesis * SECONDS_PER_SLOT)
|
|
47
|
-
if (payload.timestamp !== state.genesisTime + state.slot * state.config.SECONDS_PER_SLOT) {
|
|
48
|
-
throw Error(`Invalid timestamp ${payload.timestamp} genesisTime=${state.genesisTime} slot=${state.slot}`);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (isForkPostDeneb(forkName)) {
|
|
52
|
-
const maxBlobsPerBlock = state.config.getMaxBlobsPerBlock(computeEpochAtSlot(state.slot));
|
|
53
|
-
const blobKzgCommitmentsLen = (body as deneb.BeaconBlockBody).blobKzgCommitments?.length ?? 0;
|
|
54
|
-
if (blobKzgCommitmentsLen > maxBlobsPerBlock) {
|
|
55
|
-
throw Error(`blobKzgCommitmentsLen of ${blobKzgCommitmentsLen} exceeds limit=${maxBlobsPerBlock}`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Verify the execution payload is valid
|
|
60
|
-
//
|
|
61
|
-
// if executionEngine is null, executionEngine.onPayload MUST be called after running processBlock to get the
|
|
62
|
-
// correct randao mix. Since executionEngine will be an async call in most cases it is called afterwards to keep
|
|
63
|
-
// the state transition sync
|
|
64
|
-
//
|
|
65
|
-
// Equivalent to `assert executionEngine.notifyNewPayload(payload)`
|
|
66
|
-
if (isExecutionPayload(payload)) {
|
|
67
|
-
switch (externalData.executionPayloadStatus) {
|
|
68
|
-
case ExecutionPayloadStatus.preMerge:
|
|
69
|
-
throw Error("executionPayloadStatus preMerge");
|
|
70
|
-
case ExecutionPayloadStatus.invalid:
|
|
71
|
-
throw Error("Invalid execution payload");
|
|
72
|
-
case ExecutionPayloadStatus.valid:
|
|
73
|
-
break; // ok
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const payloadHeader = isExecutionPayload(payload) ? executionPayloadToPayloadHeader(fork, payload) : payload;
|
|
78
|
-
|
|
79
|
-
// TODO Deneb: Types are not happy by default. Since it's a generic type going through ViewDU
|
|
80
|
-
// transformation then into all forks compatible probably some weird intersection incompatibility happens
|
|
81
|
-
state.latestExecutionPayloadHeader = state.config
|
|
82
|
-
.getPostBellatrixForkTypes(state.slot)
|
|
83
|
-
.ExecutionPayloadHeader.toViewDU(payloadHeader) as typeof state.latestExecutionPayloadHeader;
|
|
84
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import {ForkSeq} from "@lodestar/params";
|
|
2
|
-
import {BeaconBlockBody, capella, electra} from "@lodestar/types";
|
|
3
|
-
import {BeaconStateTransitionMetrics} from "../metrics.js";
|
|
4
|
-
import {CachedBeaconStateAllForks, CachedBeaconStateCapella, CachedBeaconStateElectra} from "../types.js";
|
|
5
|
-
import {getEth1DepositCount} from "../util/deposit.js";
|
|
6
|
-
import {processAttestations} from "./processAttestations.js";
|
|
7
|
-
import {processAttesterSlashing} from "./processAttesterSlashing.js";
|
|
8
|
-
import {processBlsToExecutionChange} from "./processBlsToExecutionChange.js";
|
|
9
|
-
import {processConsolidationRequest} from "./processConsolidationRequest.js";
|
|
10
|
-
import {processDeposit} from "./processDeposit.js";
|
|
11
|
-
import {processDepositRequest} from "./processDepositRequest.js";
|
|
12
|
-
import {processProposerSlashing} from "./processProposerSlashing.js";
|
|
13
|
-
import {processVoluntaryExit} from "./processVoluntaryExit.js";
|
|
14
|
-
import {processWithdrawalRequest} from "./processWithdrawalRequest.js";
|
|
15
|
-
import {ProcessBlockOpts} from "./types.js";
|
|
16
|
-
|
|
17
|
-
export {
|
|
18
|
-
processProposerSlashing,
|
|
19
|
-
processAttesterSlashing,
|
|
20
|
-
processAttestations,
|
|
21
|
-
processDeposit,
|
|
22
|
-
processVoluntaryExit,
|
|
23
|
-
processWithdrawalRequest,
|
|
24
|
-
processBlsToExecutionChange,
|
|
25
|
-
processDepositRequest,
|
|
26
|
-
processConsolidationRequest,
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
export function processOperations(
|
|
30
|
-
fork: ForkSeq,
|
|
31
|
-
state: CachedBeaconStateAllForks,
|
|
32
|
-
body: BeaconBlockBody,
|
|
33
|
-
opts: ProcessBlockOpts = {verifySignatures: true},
|
|
34
|
-
metrics?: BeaconStateTransitionMetrics | null
|
|
35
|
-
): void {
|
|
36
|
-
// verify that outstanding deposits are processed up to the maximum number of deposits
|
|
37
|
-
const maxDeposits = getEth1DepositCount(state);
|
|
38
|
-
if (body.deposits.length !== maxDeposits) {
|
|
39
|
-
throw new Error(
|
|
40
|
-
`Block contains incorrect number of deposits: depositCount=${body.deposits.length} expected=${maxDeposits}`
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
for (const proposerSlashing of body.proposerSlashings) {
|
|
45
|
-
processProposerSlashing(fork, state, proposerSlashing, opts.verifySignatures);
|
|
46
|
-
}
|
|
47
|
-
for (const attesterSlashing of body.attesterSlashings) {
|
|
48
|
-
processAttesterSlashing(fork, state, attesterSlashing, opts.verifySignatures);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
processAttestations(fork, state, body.attestations, opts.verifySignatures, metrics);
|
|
52
|
-
|
|
53
|
-
for (const deposit of body.deposits) {
|
|
54
|
-
processDeposit(fork, state, deposit);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
for (const voluntaryExit of body.voluntaryExits) {
|
|
58
|
-
processVoluntaryExit(fork, state, voluntaryExit, opts.verifySignatures);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (fork >= ForkSeq.capella) {
|
|
62
|
-
for (const blsToExecutionChange of (body as capella.BeaconBlockBody).blsToExecutionChanges) {
|
|
63
|
-
processBlsToExecutionChange(state as CachedBeaconStateCapella, blsToExecutionChange);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (fork >= ForkSeq.electra) {
|
|
68
|
-
const stateElectra = state as CachedBeaconStateElectra;
|
|
69
|
-
const bodyElectra = body as electra.BeaconBlockBody;
|
|
70
|
-
|
|
71
|
-
for (const depositRequest of bodyElectra.executionRequests.deposits) {
|
|
72
|
-
processDepositRequest(stateElectra, depositRequest);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
for (const elWithdrawalRequest of bodyElectra.executionRequests.withdrawals) {
|
|
76
|
-
processWithdrawalRequest(fork, stateElectra, elWithdrawalRequest);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
for (const elConsolidationRequest of bodyElectra.executionRequests.consolidations) {
|
|
80
|
-
processConsolidationRequest(stateElectra, elConsolidationRequest);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import {ForkSeq} from "@lodestar/params";
|
|
2
|
-
import {phase0, ssz} from "@lodestar/types";
|
|
3
|
-
import {getProposerSlashingSignatureSets} from "../signatureSets/index.js";
|
|
4
|
-
import {CachedBeaconStateAllForks} from "../types.js";
|
|
5
|
-
import {isSlashableValidator} from "../util/index.js";
|
|
6
|
-
import {verifySignatureSet} from "../util/signatureSets.js";
|
|
7
|
-
import {slashValidator} from "./slashValidator.js";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Process a ProposerSlashing operation. Initiates the exit of a validator, decreases the balance of the slashed
|
|
11
|
-
* validator and increases the block proposer balance.
|
|
12
|
-
*
|
|
13
|
-
* PERF: Work depends on number of ProposerSlashing per block. On regular networks the average is 0 / block.
|
|
14
|
-
*/
|
|
15
|
-
export function processProposerSlashing(
|
|
16
|
-
fork: ForkSeq,
|
|
17
|
-
state: CachedBeaconStateAllForks,
|
|
18
|
-
proposerSlashing: phase0.ProposerSlashing,
|
|
19
|
-
verifySignatures = true
|
|
20
|
-
): void {
|
|
21
|
-
assertValidProposerSlashing(state, proposerSlashing, verifySignatures);
|
|
22
|
-
|
|
23
|
-
slashValidator(fork, state, proposerSlashing.signedHeader1.message.proposerIndex);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function assertValidProposerSlashing(
|
|
27
|
-
state: CachedBeaconStateAllForks,
|
|
28
|
-
proposerSlashing: phase0.ProposerSlashing,
|
|
29
|
-
verifySignatures = true
|
|
30
|
-
): void {
|
|
31
|
-
const header1 = proposerSlashing.signedHeader1.message;
|
|
32
|
-
const header2 = proposerSlashing.signedHeader2.message;
|
|
33
|
-
|
|
34
|
-
// verify header slots match
|
|
35
|
-
if (header1.slot !== header2.slot) {
|
|
36
|
-
throw new Error(`ProposerSlashing slots do not match: slot1=${header1.slot} slot2=${header2.slot}`);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// verify header proposer indices match
|
|
40
|
-
if (header1.proposerIndex !== header2.proposerIndex) {
|
|
41
|
-
throw new Error(
|
|
42
|
-
`ProposerSlashing proposer indices do not match: proposerIndex1=${header1.proposerIndex} proposerIndex2=${header2.proposerIndex}`
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// verify headers are different
|
|
47
|
-
if (ssz.phase0.BeaconBlockHeaderBigint.equals(header1, header2)) {
|
|
48
|
-
throw new Error("ProposerSlashing headers are equal");
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// verify the proposer is slashable
|
|
52
|
-
const proposer = state.validators.getReadonly(header1.proposerIndex);
|
|
53
|
-
if (!isSlashableValidator(proposer, state.epochCtx.epoch)) {
|
|
54
|
-
throw new Error("ProposerSlashing proposer is not slashable");
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// verify signatures
|
|
58
|
-
if (verifySignatures) {
|
|
59
|
-
const signatureSets = getProposerSlashingSignatureSets(state, proposerSlashing);
|
|
60
|
-
for (let i = 0; i < signatureSets.length; i++) {
|
|
61
|
-
if (!verifySignatureSet(signatureSets[i])) {
|
|
62
|
-
throw new Error(`ProposerSlashing header${i + 1} signature invalid`);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import {digest} from "@chainsafe/as-sha256";
|
|
2
|
-
import {EPOCHS_PER_HISTORICAL_VECTOR} from "@lodestar/params";
|
|
3
|
-
import {BeaconBlock} from "@lodestar/types";
|
|
4
|
-
import {xor} from "@lodestar/utils";
|
|
5
|
-
import {verifyRandaoSignature} from "../signatureSets/index.js";
|
|
6
|
-
import {CachedBeaconStateAllForks} from "../types.js";
|
|
7
|
-
import {getRandaoMix} from "../util/index.js";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Commit a randao reveal to generate pseudorandomness seeds
|
|
11
|
-
*
|
|
12
|
-
* PERF: Fixed work independent of block contents.
|
|
13
|
-
*/
|
|
14
|
-
export function processRandao(state: CachedBeaconStateAllForks, block: BeaconBlock, verifySignature = true): void {
|
|
15
|
-
const {epochCtx} = state;
|
|
16
|
-
const epoch = epochCtx.epoch;
|
|
17
|
-
const randaoReveal = block.body.randaoReveal;
|
|
18
|
-
|
|
19
|
-
// verify RANDAO reveal
|
|
20
|
-
if (verifySignature && !verifyRandaoSignature(state, block)) {
|
|
21
|
-
throw new Error("RANDAO reveal is an invalid signature");
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// mix in RANDAO reveal
|
|
25
|
-
const randaoMix = xor(getRandaoMix(state, epoch), digest(randaoReveal));
|
|
26
|
-
state.randaoMixes.set(epoch % EPOCHS_PER_HISTORICAL_VECTOR, randaoMix);
|
|
27
|
-
}
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import {byteArrayEquals} from "@chainsafe/ssz";
|
|
2
|
-
import {DOMAIN_SYNC_COMMITTEE, SYNC_COMMITTEE_SIZE} from "@lodestar/params";
|
|
3
|
-
import {altair, ssz} from "@lodestar/types";
|
|
4
|
-
import {G2_POINT_AT_INFINITY} from "../constants/index.js";
|
|
5
|
-
import {CachedBeaconStateAllForks} from "../types.js";
|
|
6
|
-
import {
|
|
7
|
-
ISignatureSet,
|
|
8
|
-
SignatureSetType,
|
|
9
|
-
computeSigningRoot,
|
|
10
|
-
decreaseBalance,
|
|
11
|
-
increaseBalance,
|
|
12
|
-
verifySignatureSet,
|
|
13
|
-
} from "../util/index.js";
|
|
14
|
-
|
|
15
|
-
export function processSyncAggregate(
|
|
16
|
-
state: CachedBeaconStateAllForks,
|
|
17
|
-
block: altair.BeaconBlock,
|
|
18
|
-
verifySignatures = true
|
|
19
|
-
): void {
|
|
20
|
-
const committeeIndices = state.epochCtx.currentSyncCommitteeIndexed.validatorIndices;
|
|
21
|
-
|
|
22
|
-
// different from the spec but not sure how to get through signature verification for default/empty SyncAggregate in the spec test
|
|
23
|
-
if (verifySignatures) {
|
|
24
|
-
// This is to conform to the spec - we want the signature to be verified
|
|
25
|
-
const participantIndices = block.body.syncAggregate.syncCommitteeBits.intersectValues(committeeIndices);
|
|
26
|
-
const signatureSet = getSyncCommitteeSignatureSet(state, block, participantIndices);
|
|
27
|
-
// When there's no participation we consider the signature valid and just ignore i
|
|
28
|
-
if (signatureSet !== null && !verifySignatureSet(signatureSet)) {
|
|
29
|
-
throw Error("Sync committee signature invalid");
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const {syncParticipantReward, syncProposerReward} = state.epochCtx;
|
|
34
|
-
const {syncCommitteeBits} = block.body.syncAggregate;
|
|
35
|
-
const proposerIndex = state.epochCtx.getBeaconProposer(state.slot);
|
|
36
|
-
let proposerBalance = state.balances.get(proposerIndex);
|
|
37
|
-
|
|
38
|
-
for (let i = 0; i < SYNC_COMMITTEE_SIZE; i++) {
|
|
39
|
-
const index = committeeIndices[i];
|
|
40
|
-
|
|
41
|
-
if (syncCommitteeBits.get(i)) {
|
|
42
|
-
// Positive rewards for participants
|
|
43
|
-
if (index === proposerIndex) {
|
|
44
|
-
proposerBalance += syncParticipantReward;
|
|
45
|
-
} else {
|
|
46
|
-
increaseBalance(state, index, syncParticipantReward);
|
|
47
|
-
}
|
|
48
|
-
// Proposer reward
|
|
49
|
-
proposerBalance += syncProposerReward;
|
|
50
|
-
state.proposerRewards.syncAggregate += syncProposerReward;
|
|
51
|
-
} else {
|
|
52
|
-
// Negative rewards for non participants
|
|
53
|
-
if (index === proposerIndex) {
|
|
54
|
-
proposerBalance = Math.max(0, proposerBalance - syncParticipantReward);
|
|
55
|
-
} else {
|
|
56
|
-
decreaseBalance(state, index, syncParticipantReward);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Apply proposer balance
|
|
62
|
-
state.balances.set(proposerIndex, proposerBalance);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function getSyncCommitteeSignatureSet(
|
|
66
|
-
state: CachedBeaconStateAllForks,
|
|
67
|
-
block: altair.BeaconBlock,
|
|
68
|
-
/** Optional parameter to prevent computing it twice */
|
|
69
|
-
participantIndices?: number[]
|
|
70
|
-
): ISignatureSet | null {
|
|
71
|
-
const {epochCtx} = state;
|
|
72
|
-
const {syncAggregate} = block.body;
|
|
73
|
-
const signature = syncAggregate.syncCommitteeSignature;
|
|
74
|
-
|
|
75
|
-
// The spec uses the state to get the previous slot
|
|
76
|
-
// ```python
|
|
77
|
-
// previous_slot = max(state.slot, Slot(1)) - Slot(1)
|
|
78
|
-
// ```
|
|
79
|
-
// However we need to run the function getSyncCommitteeSignatureSet() for all the blocks in a epoch
|
|
80
|
-
// with the same state when verifying blocks in batch on RangeSync. Therefore we use the block.slot.
|
|
81
|
-
const previousSlot = Math.max(block.slot, 1) - 1;
|
|
82
|
-
|
|
83
|
-
// The spec uses the state to get the root at previousSlot
|
|
84
|
-
// ```python
|
|
85
|
-
// get_block_root_at_slot(state, previous_slot)
|
|
86
|
-
// ```
|
|
87
|
-
// However we need to run the function getSyncCommitteeSignatureSet() for all the blocks in a epoch
|
|
88
|
-
// with the same state when verifying blocks in batch on RangeSync.
|
|
89
|
-
//
|
|
90
|
-
// On skipped slots state block roots just copy the latest block, so using the parentRoot here is equivalent.
|
|
91
|
-
// So getSyncCommitteeSignatureSet() can be called with a state in any slot (with the correct shuffling)
|
|
92
|
-
const rootSigned = block.parentRoot;
|
|
93
|
-
|
|
94
|
-
if (!participantIndices) {
|
|
95
|
-
const committeeIndices = state.epochCtx.currentSyncCommitteeIndexed.validatorIndices;
|
|
96
|
-
participantIndices = syncAggregate.syncCommitteeBits.intersectValues(committeeIndices);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// When there's no participation we consider the signature valid and just ignore it
|
|
100
|
-
if (participantIndices.length === 0) {
|
|
101
|
-
// Must set signature as G2_POINT_AT_INFINITY when participating bits are empty
|
|
102
|
-
// https://github.com/ethereum/eth2.0-specs/blob/30f2a076377264677e27324a8c3c78c590ae5e20/specs/altair/bls.md#eth2_fast_aggregate_verify
|
|
103
|
-
if (byteArrayEquals(signature, G2_POINT_AT_INFINITY)) {
|
|
104
|
-
return null;
|
|
105
|
-
}
|
|
106
|
-
throw Error("Empty sync committee signature is not infinity");
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const domain = state.config.getDomain(state.slot, DOMAIN_SYNC_COMMITTEE, previousSlot);
|
|
110
|
-
|
|
111
|
-
return {
|
|
112
|
-
type: SignatureSetType.aggregate,
|
|
113
|
-
pubkeys: participantIndices.map((i) => epochCtx.index2pubkey[i]),
|
|
114
|
-
signingRoot: computeSigningRoot(ssz.Root, rootSigned, domain),
|
|
115
|
-
signature,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import {FAR_FUTURE_EPOCH, ForkSeq} from "@lodestar/params";
|
|
2
|
-
import {phase0} from "@lodestar/types";
|
|
3
|
-
import {verifyVoluntaryExitSignature} from "../signatureSets/index.js";
|
|
4
|
-
import {CachedBeaconStateAllForks, CachedBeaconStateElectra} from "../types.js";
|
|
5
|
-
import {getPendingBalanceToWithdraw, isActiveValidator} from "../util/index.js";
|
|
6
|
-
import {initiateValidatorExit} from "./index.js";
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Process a VoluntaryExit operation. Initiates the exit of a validator.
|
|
10
|
-
*
|
|
11
|
-
* PERF: Work depends on number of VoluntaryExit per block. On regular networks the average is 0 / block.
|
|
12
|
-
*/
|
|
13
|
-
export function processVoluntaryExit(
|
|
14
|
-
fork: ForkSeq,
|
|
15
|
-
state: CachedBeaconStateAllForks,
|
|
16
|
-
signedVoluntaryExit: phase0.SignedVoluntaryExit,
|
|
17
|
-
verifySignature = true
|
|
18
|
-
): void {
|
|
19
|
-
if (!isValidVoluntaryExit(fork, state, signedVoluntaryExit, verifySignature)) {
|
|
20
|
-
throw Error(`Invalid voluntary exit at forkSeq=${fork}`);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const validator = state.validators.get(signedVoluntaryExit.message.validatorIndex);
|
|
24
|
-
initiateValidatorExit(fork, state, validator);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function isValidVoluntaryExit(
|
|
28
|
-
fork: ForkSeq,
|
|
29
|
-
state: CachedBeaconStateAllForks,
|
|
30
|
-
signedVoluntaryExit: phase0.SignedVoluntaryExit,
|
|
31
|
-
verifySignature = true
|
|
32
|
-
): boolean {
|
|
33
|
-
const {config, epochCtx} = state;
|
|
34
|
-
const voluntaryExit = signedVoluntaryExit.message;
|
|
35
|
-
const validator = state.validators.get(voluntaryExit.validatorIndex);
|
|
36
|
-
const currentEpoch = epochCtx.epoch;
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
// verify the validator is active
|
|
40
|
-
isActiveValidator(validator, currentEpoch) &&
|
|
41
|
-
// verify exit has not been initiated
|
|
42
|
-
validator.exitEpoch === FAR_FUTURE_EPOCH &&
|
|
43
|
-
// exits must specify an epoch when they become valid; they are not valid before then
|
|
44
|
-
currentEpoch >= voluntaryExit.epoch &&
|
|
45
|
-
// verify the validator had been active long enough
|
|
46
|
-
currentEpoch >= validator.activationEpoch + config.SHARD_COMMITTEE_PERIOD &&
|
|
47
|
-
(fork >= ForkSeq.electra
|
|
48
|
-
? // only exit validator if it has no pending withdrawals in the queue
|
|
49
|
-
getPendingBalanceToWithdraw(state as CachedBeaconStateElectra, voluntaryExit.validatorIndex) === 0
|
|
50
|
-
: // there are no pending withdrawals in previous forks
|
|
51
|
-
true) &&
|
|
52
|
-
// verify signature
|
|
53
|
-
(!verifySignature || verifyVoluntaryExitSignature(state, signedVoluntaryExit))
|
|
54
|
-
);
|
|
55
|
-
}
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
FAR_FUTURE_EPOCH,
|
|
3
|
-
FULL_EXIT_REQUEST_AMOUNT,
|
|
4
|
-
ForkSeq,
|
|
5
|
-
MIN_ACTIVATION_BALANCE,
|
|
6
|
-
PENDING_PARTIAL_WITHDRAWALS_LIMIT,
|
|
7
|
-
} from "@lodestar/params";
|
|
8
|
-
import {electra, phase0, ssz} from "@lodestar/types";
|
|
9
|
-
import {toHex} from "@lodestar/utils";
|
|
10
|
-
import {CachedBeaconStateElectra} from "../types.js";
|
|
11
|
-
import {hasCompoundingWithdrawalCredential, hasExecutionWithdrawalCredential} from "../util/electra.js";
|
|
12
|
-
import {computeExitEpochAndUpdateChurn} from "../util/epoch.js";
|
|
13
|
-
import {getPendingBalanceToWithdraw, isActiveValidator} from "../util/validator.js";
|
|
14
|
-
import {initiateValidatorExit} from "./initiateValidatorExit.js";
|
|
15
|
-
|
|
16
|
-
export function processWithdrawalRequest(
|
|
17
|
-
fork: ForkSeq,
|
|
18
|
-
state: CachedBeaconStateElectra,
|
|
19
|
-
withdrawalRequest: electra.WithdrawalRequest
|
|
20
|
-
): void {
|
|
21
|
-
const amount = Number(withdrawalRequest.amount);
|
|
22
|
-
const {pendingPartialWithdrawals, validators, epochCtx} = state;
|
|
23
|
-
// no need to use unfinalized pubkey cache from 6110 as validator won't be active anyway
|
|
24
|
-
const {pubkey2index, config} = epochCtx;
|
|
25
|
-
const isFullExitRequest = amount === FULL_EXIT_REQUEST_AMOUNT;
|
|
26
|
-
|
|
27
|
-
// If partial withdrawal queue is full, only full exits are processed
|
|
28
|
-
if (pendingPartialWithdrawals.length >= PENDING_PARTIAL_WITHDRAWALS_LIMIT && !isFullExitRequest) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// bail out if validator is not in beacon state
|
|
33
|
-
// note that we don't need to check for 6110 unfinalized vals as they won't be eligible for withdraw/exit anyway
|
|
34
|
-
const validatorIndex = pubkey2index.get(withdrawalRequest.validatorPubkey);
|
|
35
|
-
if (validatorIndex === null) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const validator = validators.get(validatorIndex);
|
|
40
|
-
if (!isValidatorEligibleForWithdrawOrExit(validator, withdrawalRequest.sourceAddress, state)) {
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// TODO Electra: Consider caching pendingPartialWithdrawals
|
|
45
|
-
const pendingBalanceToWithdraw = getPendingBalanceToWithdraw(state, validatorIndex);
|
|
46
|
-
const validatorBalance = state.balances.get(validatorIndex);
|
|
47
|
-
|
|
48
|
-
if (isFullExitRequest) {
|
|
49
|
-
// only exit validator if it has no pending withdrawals in the queue
|
|
50
|
-
if (pendingBalanceToWithdraw === 0) {
|
|
51
|
-
initiateValidatorExit(fork, state, validator);
|
|
52
|
-
}
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// partial withdrawal request
|
|
57
|
-
const hasSufficientEffectiveBalance = validator.effectiveBalance >= MIN_ACTIVATION_BALANCE;
|
|
58
|
-
const hasExcessBalance = validatorBalance > MIN_ACTIVATION_BALANCE + pendingBalanceToWithdraw;
|
|
59
|
-
|
|
60
|
-
// Only allow partial withdrawals with compounding withdrawal credentials
|
|
61
|
-
if (
|
|
62
|
-
hasCompoundingWithdrawalCredential(validator.withdrawalCredentials) &&
|
|
63
|
-
hasSufficientEffectiveBalance &&
|
|
64
|
-
hasExcessBalance
|
|
65
|
-
) {
|
|
66
|
-
const amountToWithdraw = BigInt(
|
|
67
|
-
Math.min(validatorBalance - MIN_ACTIVATION_BALANCE - pendingBalanceToWithdraw, amount)
|
|
68
|
-
);
|
|
69
|
-
const exitQueueEpoch = computeExitEpochAndUpdateChurn(state, amountToWithdraw);
|
|
70
|
-
const withdrawableEpoch = exitQueueEpoch + config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY;
|
|
71
|
-
|
|
72
|
-
const pendingPartialWithdrawal = ssz.electra.PendingPartialWithdrawal.toViewDU({
|
|
73
|
-
validatorIndex,
|
|
74
|
-
amount: amountToWithdraw,
|
|
75
|
-
withdrawableEpoch,
|
|
76
|
-
});
|
|
77
|
-
state.pendingPartialWithdrawals.push(pendingPartialWithdrawal);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function isValidatorEligibleForWithdrawOrExit(
|
|
82
|
-
validator: phase0.Validator,
|
|
83
|
-
sourceAddress: Uint8Array,
|
|
84
|
-
state: CachedBeaconStateElectra
|
|
85
|
-
): boolean {
|
|
86
|
-
const {withdrawalCredentials} = validator;
|
|
87
|
-
const addressStr = toHex(withdrawalCredentials.subarray(12));
|
|
88
|
-
const sourceAddressStr = toHex(sourceAddress);
|
|
89
|
-
const {epoch: currentEpoch, config} = state.epochCtx;
|
|
90
|
-
|
|
91
|
-
return (
|
|
92
|
-
hasExecutionWithdrawalCredential(withdrawalCredentials) &&
|
|
93
|
-
addressStr === sourceAddressStr &&
|
|
94
|
-
isActiveValidator(validator, currentEpoch) &&
|
|
95
|
-
validator.exitEpoch === FAR_FUTURE_EPOCH &&
|
|
96
|
-
currentEpoch >= validator.activationEpoch + config.SHARD_COMMITTEE_PERIOD
|
|
97
|
-
);
|
|
98
|
-
}
|