@lodestar/state-transition 1.35.0-dev.f80d2d52da → 1.35.0-dev.fd1dac853d
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/README.md +1 -1
- package/lib/block/externalData.d.ts.map +1 -0
- package/lib/block/index.d.ts +2 -2
- package/lib/block/index.d.ts.map +1 -0
- package/lib/block/index.js +2 -2
- package/lib/block/index.js.map +1 -1
- package/lib/block/initiateValidatorExit.d.ts.map +1 -0
- package/lib/block/isValidIndexedAttestation.d.ts.map +1 -0
- package/lib/block/processAttestationPhase0.d.ts.map +1 -0
- package/lib/block/processAttestationPhase0.js +1 -2
- package/lib/block/processAttestationPhase0.js.map +1 -1
- package/lib/block/processAttestations.d.ts.map +1 -0
- package/lib/block/processAttestationsAltair.d.ts +1 -1
- package/lib/block/processAttestationsAltair.d.ts.map +1 -0
- package/lib/block/processAttestationsAltair.js +1 -1
- package/lib/block/processAttestationsAltair.js.map +1 -1
- package/lib/block/processAttesterSlashing.d.ts.map +1 -0
- package/lib/block/processAttesterSlashing.js.map +1 -1
- package/lib/block/processBlobKzgCommitments.d.ts.map +1 -0
- package/lib/block/processBlockHeader.d.ts.map +1 -0
- package/lib/block/processBlsToExecutionChange.d.ts.map +1 -0
- package/lib/block/processBlsToExecutionChange.js.map +1 -1
- package/lib/block/processConsolidationRequest.d.ts.map +1 -0
- package/lib/block/processConsolidationRequest.js.map +1 -1
- package/lib/block/processDeposit.d.ts +2 -2
- package/lib/block/processDeposit.d.ts.map +1 -0
- package/lib/block/processDeposit.js +1 -1
- package/lib/block/processDeposit.js.map +1 -1
- package/lib/block/processDepositRequest.d.ts.map +1 -0
- package/lib/block/processDepositRequest.js.map +1 -1
- package/lib/block/processEth1Data.d.ts.map +1 -0
- package/lib/block/processExecutionPayload.d.ts.map +1 -0
- package/lib/block/processExecutionPayload.js +3 -3
- package/lib/block/processExecutionPayload.js.map +1 -1
- package/lib/block/processOperations.d.ts.map +1 -0
- package/lib/block/processOperations.js.map +1 -1
- package/lib/block/processProposerSlashing.d.ts.map +1 -0
- package/lib/block/processRandao.d.ts.map +1 -0
- package/lib/block/processSyncCommittee.d.ts.map +1 -0
- package/lib/block/processSyncCommittee.js +1 -2
- package/lib/block/processSyncCommittee.js.map +1 -1
- package/lib/block/processVoluntaryExit.d.ts.map +1 -0
- package/lib/block/processWithdrawalRequest.d.ts.map +1 -0
- package/lib/block/processWithdrawalRequest.js.map +1 -1
- package/lib/block/processWithdrawals.d.ts.map +1 -0
- package/lib/block/processWithdrawals.js.map +1 -1
- package/lib/block/slashValidator.d.ts.map +1 -0
- package/lib/block/slashValidator.js.map +1 -1
- package/lib/block/types.d.ts.map +1 -0
- package/lib/cache/effectiveBalanceIncrements.d.ts.map +1 -0
- package/lib/cache/epochCache.d.ts.map +1 -0
- package/lib/cache/epochCache.js +130 -0
- package/lib/cache/epochCache.js.map +1 -1
- package/lib/cache/epochTransitionCache.d.ts.map +1 -0
- package/lib/cache/epochTransitionCache.js.map +1 -1
- package/lib/cache/pubkeyCache.d.ts.map +1 -0
- package/lib/cache/rewardCache.d.ts.map +1 -0
- package/lib/cache/stateCache.d.ts.map +1 -0
- package/lib/cache/syncCommitteeCache.d.ts.map +1 -0
- package/lib/cache/types.d.ts +2 -2
- package/lib/cache/types.d.ts.map +1 -0
- package/lib/constants/constants.d.ts.map +1 -0
- package/lib/constants/index.d.ts.map +1 -0
- package/lib/epoch/computeUnrealizedCheckpoints.d.ts.map +1 -0
- package/lib/epoch/getAttestationDeltas.d.ts.map +1 -0
- package/lib/epoch/getRewardsAndPenalties.d.ts.map +1 -0
- package/lib/epoch/index.d.ts.map +1 -0
- package/lib/epoch/index.js.map +1 -1
- package/lib/epoch/processEffectiveBalanceUpdates.d.ts.map +1 -0
- package/lib/epoch/processEth1DataReset.d.ts.map +1 -0
- package/lib/epoch/processHistoricalRootsUpdate.d.ts.map +1 -0
- package/lib/epoch/processHistoricalSummariesUpdate.d.ts.map +1 -0
- package/lib/epoch/processInactivityUpdates.d.ts.map +1 -0
- package/lib/epoch/processJustificationAndFinalization.d.ts.map +1 -0
- package/lib/epoch/processParticipationFlagUpdates.d.ts.map +1 -0
- package/lib/epoch/processParticipationRecordUpdates.d.ts.map +1 -0
- package/lib/epoch/processPendingAttestations.d.ts.map +1 -0
- package/lib/epoch/processPendingConsolidations.d.ts.map +1 -0
- package/lib/epoch/processPendingDeposits.d.ts.map +1 -0
- package/lib/epoch/processProposerLookahead.d.ts.map +1 -0
- package/lib/epoch/processRandaoMixesReset.d.ts.map +1 -0
- package/lib/epoch/processRegistryUpdates.d.ts.map +1 -0
- package/lib/epoch/processRewardsAndPenalties.d.ts.map +1 -0
- package/lib/epoch/processSlashings.d.ts.map +1 -0
- package/lib/epoch/processSlashings.js.map +1 -1
- package/lib/epoch/processSlashingsReset.d.ts.map +1 -0
- package/lib/epoch/processSyncCommitteeUpdates.d.ts.map +1 -0
- package/lib/index.d.ts +17 -17
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +16 -16
- package/lib/index.js.map +1 -1
- package/lib/metrics.d.ts.map +1 -0
- package/lib/signatureSets/attesterSlashings.d.ts.map +1 -0
- package/lib/signatureSets/blsToExecutionChange.d.ts.map +1 -0
- package/lib/signatureSets/blsToExecutionChange.js.map +1 -1
- package/lib/signatureSets/index.d.ts +1 -1
- package/lib/signatureSets/index.d.ts.map +1 -0
- package/lib/signatureSets/index.js +1 -1
- package/lib/signatureSets/index.js.map +1 -1
- package/lib/signatureSets/indexedAttestation.d.ts.map +1 -0
- package/lib/signatureSets/proposer.d.ts.map +1 -0
- package/lib/signatureSets/proposerSlashings.d.ts.map +1 -0
- package/lib/signatureSets/randao.d.ts.map +1 -0
- package/lib/signatureSets/voluntaryExits.d.ts.map +1 -0
- package/lib/slot/index.d.ts.map +1 -0
- package/lib/slot/upgradeStateToAltair.d.ts.map +1 -0
- package/lib/slot/upgradeStateToBellatrix.d.ts.map +1 -0
- package/lib/slot/upgradeStateToCapella.d.ts.map +1 -0
- package/lib/slot/upgradeStateToDeneb.d.ts +1 -2
- package/lib/slot/upgradeStateToDeneb.d.ts.map +1 -0
- package/lib/slot/upgradeStateToDeneb.js.map +1 -1
- package/lib/slot/upgradeStateToElectra.d.ts.map +1 -0
- package/lib/slot/upgradeStateToFulu.d.ts.map +1 -0
- package/lib/slot/upgradeStateToGloas.d.ts.map +1 -0
- package/lib/slot/upgradeStateToGloas.js +2 -2
- package/lib/slot/upgradeStateToGloas.js.map +1 -1
- package/lib/stateTransition.d.ts.map +1 -0
- package/lib/types.d.ts +2 -2
- package/lib/types.d.ts.map +1 -0
- package/lib/util/aggregator.d.ts.map +1 -0
- package/lib/util/altair.d.ts.map +1 -0
- package/lib/util/array.d.ts.map +1 -0
- package/lib/util/attestation.d.ts.map +1 -0
- package/lib/util/attesterStatus.d.ts.map +1 -0
- package/lib/util/balance.d.ts.map +1 -0
- package/lib/util/blindedBlock.d.ts.map +1 -0
- package/lib/util/blindedBlock.js.map +1 -1
- package/lib/util/blockRoot.d.ts.map +1 -0
- package/lib/util/calculateCommitteeAssignments.d.ts.map +1 -0
- package/lib/util/capella.d.ts.map +1 -0
- package/lib/util/computeAnchorCheckpoint.d.ts.map +1 -0
- package/lib/util/deposit.d.ts.map +1 -0
- package/lib/util/domain.d.ts.map +1 -0
- package/lib/util/electra.d.ts.map +1 -0
- package/lib/util/epoch.d.ts.map +1 -0
- package/lib/util/epochShuffling.d.ts.map +1 -0
- package/lib/util/execution.d.ts.map +1 -0
- package/lib/util/execution.js.map +1 -1
- package/lib/util/finality.d.ts.map +1 -0
- package/lib/util/fulu.d.ts.map +1 -0
- package/lib/util/genesis.d.ts.map +1 -0
- package/lib/util/genesis.js +3 -6
- package/lib/util/genesis.js.map +1 -1
- package/lib/util/index.d.ts +5 -5
- package/lib/util/index.d.ts.map +1 -0
- package/lib/util/index.js +5 -5
- package/lib/util/index.js.map +1 -1
- package/lib/util/interop.d.ts.map +1 -0
- package/lib/util/interop.js +1 -1
- package/lib/util/interop.js.map +1 -1
- package/lib/util/loadState/findModifiedInactivityScores.d.ts.map +1 -0
- package/lib/util/loadState/findModifiedValidators.d.ts.map +1 -0
- package/lib/util/loadState/index.d.ts.map +1 -0
- package/lib/util/loadState/loadState.d.ts.map +1 -0
- package/lib/util/loadState/loadValidator.d.ts.map +1 -0
- package/lib/util/rootCache.d.ts.map +1 -0
- package/lib/util/rootCache.js +5 -2
- package/lib/util/rootCache.js.map +1 -1
- package/lib/util/seed.d.ts.map +1 -0
- package/lib/util/seed.js +1 -2
- package/lib/util/seed.js.map +1 -1
- package/lib/util/shufflingDecisionRoot.d.ts.map +1 -0
- package/lib/util/signatureSets.d.ts.map +1 -0
- package/lib/util/signingRoot.d.ts.map +1 -0
- package/lib/util/slot.d.ts +0 -1
- package/lib/util/slot.d.ts.map +1 -0
- package/lib/util/slot.js +3 -7
- package/lib/util/slot.js.map +1 -1
- package/lib/util/sszBytes.d.ts.map +1 -0
- package/lib/util/syncCommittee.d.ts.map +1 -0
- package/lib/util/targetUnslashedBalance.d.ts.map +1 -0
- package/lib/util/validator.d.ts.map +1 -0
- package/lib/util/weakSubjectivity.d.ts.map +1 -0
- package/lib/util/weakSubjectivity.js.map +1 -1
- package/package.json +13 -11
- package/src/block/externalData.ts +26 -0
- package/src/block/index.ts +81 -0
- package/src/block/initiateValidatorExit.ts +62 -0
- package/src/block/isValidIndexedAttestation.ts +70 -0
- package/src/block/processAttestationPhase0.ts +158 -0
- package/src/block/processAttestations.ts +25 -0
- package/src/block/processAttestationsAltair.ts +184 -0
- package/src/block/processAttesterSlashing.ts +59 -0
- package/src/block/processBlobKzgCommitments.ts +21 -0
- package/src/block/processBlockHeader.ts +54 -0
- package/src/block/processBlsToExecutionChange.ts +78 -0
- package/src/block/processConsolidationRequest.ts +147 -0
- package/src/block/processDeposit.ts +166 -0
- package/src/block/processDepositRequest.ts +19 -0
- package/src/block/processEth1Data.ts +86 -0
- package/src/block/processExecutionPayload.ts +84 -0
- package/src/block/processOperations.ts +83 -0
- package/src/block/processProposerSlashing.ts +66 -0
- package/src/block/processRandao.ts +27 -0
- package/src/block/processSyncCommittee.ts +117 -0
- package/src/block/processVoluntaryExit.ts +55 -0
- package/src/block/processWithdrawalRequest.ts +98 -0
- package/src/block/processWithdrawals.ts +207 -0
- package/src/block/slashValidator.ts +98 -0
- package/src/block/types.ts +9 -0
- package/src/cache/effectiveBalanceIncrements.ts +39 -0
- package/src/cache/epochCache.ts +1213 -0
- package/src/cache/epochTransitionCache.ts +542 -0
- package/src/cache/pubkeyCache.ts +33 -0
- package/src/cache/rewardCache.ts +19 -0
- package/src/cache/stateCache.ts +268 -0
- package/src/cache/syncCommitteeCache.ts +96 -0
- package/src/cache/types.ts +18 -0
- package/src/constants/constants.ts +12 -0
- package/src/constants/index.ts +1 -0
- package/src/epoch/computeUnrealizedCheckpoints.ts +55 -0
- package/src/epoch/getAttestationDeltas.ts +169 -0
- package/src/epoch/getRewardsAndPenalties.ts +137 -0
- package/src/epoch/index.ts +202 -0
- package/src/epoch/processEffectiveBalanceUpdates.ts +111 -0
- package/src/epoch/processEth1DataReset.ts +17 -0
- package/src/epoch/processHistoricalRootsUpdate.ts +25 -0
- package/src/epoch/processHistoricalSummariesUpdate.ts +23 -0
- package/src/epoch/processInactivityUpdates.ts +60 -0
- package/src/epoch/processJustificationAndFinalization.ts +90 -0
- package/src/epoch/processParticipationFlagUpdates.ts +27 -0
- package/src/epoch/processParticipationRecordUpdates.ts +14 -0
- package/src/epoch/processPendingAttestations.ts +75 -0
- package/src/epoch/processPendingConsolidations.ts +59 -0
- package/src/epoch/processPendingDeposits.ts +136 -0
- package/src/epoch/processProposerLookahead.ts +39 -0
- package/src/epoch/processRandaoMixesReset.ts +18 -0
- package/src/epoch/processRegistryUpdates.ts +65 -0
- package/src/epoch/processRewardsAndPenalties.ts +58 -0
- package/src/epoch/processSlashings.ts +97 -0
- package/src/epoch/processSlashingsReset.ts +20 -0
- package/src/epoch/processSyncCommitteeUpdates.ts +44 -0
- package/src/index.ts +67 -0
- package/src/metrics.ts +169 -0
- package/src/signatureSets/attesterSlashings.ts +39 -0
- package/src/signatureSets/blsToExecutionChange.ts +43 -0
- package/src/signatureSets/index.ts +73 -0
- package/src/signatureSets/indexedAttestation.ts +51 -0
- package/src/signatureSets/proposer.ts +47 -0
- package/src/signatureSets/proposerSlashings.ts +41 -0
- package/src/signatureSets/randao.ts +31 -0
- package/src/signatureSets/voluntaryExits.ts +44 -0
- package/src/slot/index.ts +32 -0
- package/src/slot/upgradeStateToAltair.ts +149 -0
- package/src/slot/upgradeStateToBellatrix.ts +63 -0
- package/src/slot/upgradeStateToCapella.ts +71 -0
- package/src/slot/upgradeStateToDeneb.ts +40 -0
- package/src/slot/upgradeStateToElectra.ts +126 -0
- package/src/slot/upgradeStateToFulu.ts +31 -0
- package/src/slot/upgradeStateToGloas.ts +29 -0
- package/src/stateTransition.ts +305 -0
- package/src/types.ts +26 -0
- package/src/util/aggregator.ts +33 -0
- package/src/util/altair.ts +13 -0
- package/src/util/array.ts +53 -0
- package/src/util/attestation.ts +36 -0
- package/src/util/attesterStatus.ts +83 -0
- package/src/util/balance.ts +83 -0
- package/src/util/blindedBlock.ts +144 -0
- package/src/util/blockRoot.ts +72 -0
- package/src/util/calculateCommitteeAssignments.ts +43 -0
- package/src/util/capella.ts +8 -0
- package/src/util/computeAnchorCheckpoint.ts +38 -0
- package/src/util/deposit.ts +22 -0
- package/src/util/domain.ts +31 -0
- package/src/util/electra.ts +68 -0
- package/src/util/epoch.ts +135 -0
- package/src/util/epochShuffling.ts +185 -0
- package/src/util/execution.ts +177 -0
- package/src/util/finality.ts +17 -0
- package/src/util/fulu.ts +43 -0
- package/src/util/genesis.ts +340 -0
- package/src/util/index.ts +29 -0
- package/src/util/interop.ts +22 -0
- package/src/util/loadState/findModifiedInactivityScores.ts +47 -0
- package/src/util/loadState/findModifiedValidators.ts +46 -0
- package/src/util/loadState/index.ts +2 -0
- package/src/util/loadState/loadState.ts +225 -0
- package/src/util/loadState/loadValidator.ts +77 -0
- package/src/util/rootCache.ts +37 -0
- package/src/util/seed.ts +381 -0
- package/src/util/shufflingDecisionRoot.ts +78 -0
- package/src/util/signatureSets.ts +65 -0
- package/src/util/signingRoot.ts +13 -0
- package/src/util/slot.ts +22 -0
- package/src/util/sszBytes.ts +52 -0
- package/src/util/syncCommittee.ts +69 -0
- package/src/util/targetUnslashedBalance.ts +30 -0
- package/src/util/validator.ts +105 -0
- package/src/util/weakSubjectivity.ts +186 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export {
|
|
2
|
+
type BlockExternalData,
|
|
3
|
+
DataAvailabilityStatus,
|
|
4
|
+
ExecutionPayloadStatus,
|
|
5
|
+
} from "./block/externalData.js";
|
|
6
|
+
export {getAttestationParticipationStatus, processAttestationsAltair} from "./block/processAttestationsAltair.js";
|
|
7
|
+
export {assertValidAttesterSlashing} from "./block/processAttesterSlashing.js";
|
|
8
|
+
export {isValidBlsToExecutionChange} from "./block/processBlsToExecutionChange.js";
|
|
9
|
+
// BeaconChain, to prepare new blocks
|
|
10
|
+
export {becomesNewEth1Data} from "./block/processEth1Data.js";
|
|
11
|
+
export {assertValidProposerSlashing} from "./block/processProposerSlashing.js";
|
|
12
|
+
// BeaconChain validation
|
|
13
|
+
export {isValidVoluntaryExit} from "./block/processVoluntaryExit.js";
|
|
14
|
+
// Withdrawals for new blocks
|
|
15
|
+
export {getExpectedWithdrawals} from "./block/processWithdrawals.js";
|
|
16
|
+
export {ProposerRewardType} from "./block/types.js";
|
|
17
|
+
export {
|
|
18
|
+
type EffectiveBalanceIncrements,
|
|
19
|
+
getEffectiveBalanceIncrementsWithLen,
|
|
20
|
+
getEffectiveBalanceIncrementsZeroed,
|
|
21
|
+
} from "./cache/effectiveBalanceIncrements.js";
|
|
22
|
+
export {
|
|
23
|
+
EpochCache,
|
|
24
|
+
EpochCacheError,
|
|
25
|
+
EpochCacheErrorCode,
|
|
26
|
+
type EpochCacheImmutableData,
|
|
27
|
+
createEmptyEpochCacheImmutableData,
|
|
28
|
+
} from "./cache/epochCache.js";
|
|
29
|
+
export {type EpochTransitionCache, beforeProcessEpoch} from "./cache/epochTransitionCache.js";
|
|
30
|
+
// Aux data-structures
|
|
31
|
+
export {type Index2PubkeyCache} from "./cache/pubkeyCache.js";
|
|
32
|
+
// Main state caches
|
|
33
|
+
export {
|
|
34
|
+
type BeaconStateCache,
|
|
35
|
+
createCachedBeaconState,
|
|
36
|
+
isCachedBeaconState,
|
|
37
|
+
isStateBalancesNodesPopulated,
|
|
38
|
+
isStateValidatorsNodesPopulated,
|
|
39
|
+
loadCachedBeaconState,
|
|
40
|
+
} from "./cache/stateCache.js";
|
|
41
|
+
export * from "./constants/index.js";
|
|
42
|
+
export type {EpochTransitionStep} from "./epoch/index.js";
|
|
43
|
+
export {type BeaconStateTransitionMetrics, getMetrics} from "./metrics.js";
|
|
44
|
+
export * from "./signatureSets/index.js";
|
|
45
|
+
export * from "./stateTransition.js";
|
|
46
|
+
export type {
|
|
47
|
+
BeaconStateAllForks,
|
|
48
|
+
BeaconStateAltair,
|
|
49
|
+
BeaconStateBellatrix,
|
|
50
|
+
BeaconStateCapella,
|
|
51
|
+
BeaconStateDeneb,
|
|
52
|
+
BeaconStateElectra,
|
|
53
|
+
BeaconStateExecutions,
|
|
54
|
+
BeaconStateFulu,
|
|
55
|
+
// Non-cached states
|
|
56
|
+
BeaconStatePhase0,
|
|
57
|
+
CachedBeaconStateAllForks,
|
|
58
|
+
CachedBeaconStateAltair,
|
|
59
|
+
CachedBeaconStateBellatrix,
|
|
60
|
+
CachedBeaconStateCapella,
|
|
61
|
+
CachedBeaconStateDeneb,
|
|
62
|
+
CachedBeaconStateElectra,
|
|
63
|
+
CachedBeaconStateExecutions,
|
|
64
|
+
CachedBeaconStateFulu,
|
|
65
|
+
CachedBeaconStatePhase0,
|
|
66
|
+
} from "./types.js";
|
|
67
|
+
export * from "./util/index.js";
|
package/src/metrics.ts
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import {MetricsRegister} from "@lodestar/utils";
|
|
2
|
+
import {ProposerRewardType} from "./block/types.js";
|
|
3
|
+
import {EpochTransitionStep} from "./epoch/index.js";
|
|
4
|
+
import {StateCloneSource, StateHashTreeRootSource} from "./stateTransition.js";
|
|
5
|
+
import {CachedBeaconStateAllForks} from "./types.js";
|
|
6
|
+
|
|
7
|
+
export type BeaconStateTransitionMetrics = ReturnType<typeof getMetrics>;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A collection of metrics used throughout the State Transition.
|
|
11
|
+
*/
|
|
12
|
+
export function getMetrics(register: MetricsRegister) {
|
|
13
|
+
// Using function style instead of class to prevent having to re-declare all MetricsPrometheus types.
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
epochTransitionTime: register.histogram({
|
|
17
|
+
name: "lodestar_stfn_epoch_transition_seconds",
|
|
18
|
+
help: "Time to process a single epoch transition in seconds",
|
|
19
|
+
// as of Sep 2025, on mainnet, epoch transition time of lodestar is never less than 0.5s, and it could be up to 3s
|
|
20
|
+
buckets: [0.2, 0.5, 0.75, 1, 1.25, 1.5, 2, 2.5, 3, 10],
|
|
21
|
+
}),
|
|
22
|
+
epochTransitionCommitTime: register.histogram({
|
|
23
|
+
name: "lodestar_stfn_epoch_transition_commit_seconds",
|
|
24
|
+
help: "Time to call commit after process a single epoch transition in seconds",
|
|
25
|
+
buckets: [0.01, 0.05, 0.1, 0.2, 0.5, 0.75, 1],
|
|
26
|
+
}),
|
|
27
|
+
epochTransitionStepTime: register.histogram<{step: EpochTransitionStep}>({
|
|
28
|
+
name: "lodestar_stfn_epoch_transition_step_seconds",
|
|
29
|
+
help: "Time to call each step of epoch transition in seconds",
|
|
30
|
+
labelNames: ["step"],
|
|
31
|
+
buckets: [0.01, 0.05, 0.1, 0.2, 0.5, 0.75, 1],
|
|
32
|
+
}),
|
|
33
|
+
processBlockTime: register.histogram({
|
|
34
|
+
name: "lodestar_stfn_process_block_seconds",
|
|
35
|
+
help: "Time to process a single block in seconds",
|
|
36
|
+
// TODO: Add metrics for each step
|
|
37
|
+
// Block processing can take 5-40ms, 100ms max
|
|
38
|
+
buckets: [0.005, 0.01, 0.02, 0.05, 0.1, 1],
|
|
39
|
+
}),
|
|
40
|
+
processBlockCommitTime: register.histogram({
|
|
41
|
+
name: "lodestar_stfn_process_block_commit_seconds",
|
|
42
|
+
help: "Time to call commit after process a single block in seconds",
|
|
43
|
+
buckets: [0.005, 0.01, 0.02, 0.05, 0.1, 1],
|
|
44
|
+
}),
|
|
45
|
+
stateHashTreeRootTime: register.histogram<{source: StateHashTreeRootSource}>({
|
|
46
|
+
name: "lodestar_stfn_hash_tree_root_seconds",
|
|
47
|
+
help: "Time to compute the hash tree root of a post state in seconds",
|
|
48
|
+
buckets: [0.05, 0.1, 0.2, 0.5, 1, 1.5],
|
|
49
|
+
labelNames: ["source"],
|
|
50
|
+
}),
|
|
51
|
+
numEffectiveBalanceUpdates: register.gauge({
|
|
52
|
+
name: "lodestar_stfn_effective_balance_updates_count",
|
|
53
|
+
help: "Total count of effective balance updates",
|
|
54
|
+
}),
|
|
55
|
+
validatorsInActivationQueue: register.gauge({
|
|
56
|
+
name: "lodestar_stfn_validators_in_activation_queue",
|
|
57
|
+
help: "Current number of validators in the activation queue",
|
|
58
|
+
}),
|
|
59
|
+
validatorsInExitQueue: register.gauge({
|
|
60
|
+
name: "lodestar_stfn_validators_in_exit_queue",
|
|
61
|
+
help: "Current number of validators in the exit queue",
|
|
62
|
+
}),
|
|
63
|
+
preStateBalancesNodesPopulatedMiss: register.gauge<{source: StateCloneSource}>({
|
|
64
|
+
name: "lodestar_stfn_balances_nodes_populated_miss_total",
|
|
65
|
+
help: "Total count state.balances nodesPopulated is false on stfn",
|
|
66
|
+
labelNames: ["source"],
|
|
67
|
+
}),
|
|
68
|
+
preStateBalancesNodesPopulatedHit: register.gauge<{source: StateCloneSource}>({
|
|
69
|
+
name: "lodestar_stfn_balances_nodes_populated_hit_total",
|
|
70
|
+
help: "Total count state.balances nodesPopulated is true on stfn",
|
|
71
|
+
labelNames: ["source"],
|
|
72
|
+
}),
|
|
73
|
+
preStateValidatorsNodesPopulatedMiss: register.gauge<{source: StateCloneSource}>({
|
|
74
|
+
name: "lodestar_stfn_validators_nodes_populated_miss_total",
|
|
75
|
+
help: "Total count state.validators nodesPopulated is false on stfn",
|
|
76
|
+
labelNames: ["source"],
|
|
77
|
+
}),
|
|
78
|
+
preStateValidatorsNodesPopulatedHit: register.gauge<{source: StateCloneSource}>({
|
|
79
|
+
name: "lodestar_stfn_validators_nodes_populated_hit_total",
|
|
80
|
+
help: "Total count state.validators nodesPopulated is true on stfn",
|
|
81
|
+
labelNames: ["source"],
|
|
82
|
+
}),
|
|
83
|
+
preStateClonedCount: register.histogram({
|
|
84
|
+
name: "lodestar_stfn_state_cloned_count",
|
|
85
|
+
help: "Histogram of cloned count per state every time state.clone() is called",
|
|
86
|
+
buckets: [1, 2, 5, 10, 50, 250],
|
|
87
|
+
}),
|
|
88
|
+
postStateBalancesNodesPopulatedHit: register.gauge({
|
|
89
|
+
name: "lodestar_stfn_post_state_balances_nodes_populated_hit_total",
|
|
90
|
+
help: "Total count state.validators nodesPopulated is true on stfn for post state",
|
|
91
|
+
}),
|
|
92
|
+
postStateBalancesNodesPopulatedMiss: register.gauge({
|
|
93
|
+
name: "lodestar_stfn_post_state_balances_nodes_populated_miss_total",
|
|
94
|
+
help: "Total count state.validators nodesPopulated is false on stfn for post state",
|
|
95
|
+
}),
|
|
96
|
+
postStateValidatorsNodesPopulatedHit: register.gauge({
|
|
97
|
+
name: "lodestar_stfn_post_state_validators_nodes_populated_hit_total",
|
|
98
|
+
help: "Total count state.validators nodesPopulated is true on stfn for post state",
|
|
99
|
+
}),
|
|
100
|
+
postStateValidatorsNodesPopulatedMiss: register.gauge({
|
|
101
|
+
name: "lodestar_stfn_post_state_validators_nodes_populated_miss_total",
|
|
102
|
+
help: "Total count state.validators nodesPopulated is false on stfn for post state",
|
|
103
|
+
}),
|
|
104
|
+
newSeenAttestersPerBlock: register.gauge({
|
|
105
|
+
name: "lodestar_stfn_new_seen_attesters_per_block_total",
|
|
106
|
+
help: "Total count of new seen attesters per block",
|
|
107
|
+
}),
|
|
108
|
+
newSeenAttestersEffectiveBalancePerBlock: register.gauge({
|
|
109
|
+
name: "lodestar_stfn_new_seen_attesters_effective_balance_per_block_total",
|
|
110
|
+
help: "Total effective balance increment of new seen attesters per block",
|
|
111
|
+
}),
|
|
112
|
+
attestationsPerBlock: register.gauge({
|
|
113
|
+
name: "lodestar_stfn_attestations_per_block_total",
|
|
114
|
+
help: "Total count of attestations per block",
|
|
115
|
+
}),
|
|
116
|
+
proposerRewards: register.gauge<{type: ProposerRewardType}>({
|
|
117
|
+
name: "lodestar_stfn_proposer_rewards_total",
|
|
118
|
+
help: "Proposer reward by type per block",
|
|
119
|
+
labelNames: ["type"],
|
|
120
|
+
}),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function onStateCloneMetrics(
|
|
125
|
+
state: CachedBeaconStateAllForks,
|
|
126
|
+
metrics: BeaconStateTransitionMetrics,
|
|
127
|
+
source: StateCloneSource
|
|
128
|
+
): void {
|
|
129
|
+
metrics.preStateClonedCount.observe(state.clonedCount);
|
|
130
|
+
|
|
131
|
+
if (isBalancesNodesPopulated(state)) {
|
|
132
|
+
metrics.preStateBalancesNodesPopulatedHit.inc({source});
|
|
133
|
+
} else {
|
|
134
|
+
metrics.preStateBalancesNodesPopulatedMiss.inc({source});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (isValidatorsNodesPopulated(state)) {
|
|
138
|
+
metrics.preStateValidatorsNodesPopulatedHit.inc({source});
|
|
139
|
+
} else {
|
|
140
|
+
metrics.preStateValidatorsNodesPopulatedMiss.inc({source});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function onPostStateMetrics(postState: CachedBeaconStateAllForks, metrics: BeaconStateTransitionMetrics): void {
|
|
145
|
+
if (isBalancesNodesPopulated(postState)) {
|
|
146
|
+
metrics.postStateBalancesNodesPopulatedHit.inc();
|
|
147
|
+
} else {
|
|
148
|
+
metrics.postStateBalancesNodesPopulatedMiss.inc();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (isValidatorsNodesPopulated(postState)) {
|
|
152
|
+
metrics.postStateValidatorsNodesPopulatedHit.inc();
|
|
153
|
+
} else {
|
|
154
|
+
metrics.postStateValidatorsNodesPopulatedMiss.inc();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Given a CachedBeaconState, check if validators array internal cache is populated.
|
|
159
|
+
// This cache is populated during epoch transition, and should be preserved for performance.
|
|
160
|
+
// If the cache is missing too often, means that our clone strategy is not working well.
|
|
161
|
+
function isValidatorsNodesPopulated(state: CachedBeaconStateAllForks): boolean {
|
|
162
|
+
// biome-ignore lint/complexity/useLiteralKeys: It is a private attribute
|
|
163
|
+
return state.validators["nodesPopulated"] === true;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function isBalancesNodesPopulated(state: CachedBeaconStateAllForks): boolean {
|
|
167
|
+
// biome-ignore lint/complexity/useLiteralKeys: It is a private attribute
|
|
168
|
+
return state.balances["nodesPopulated"] === true;
|
|
169
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {DOMAIN_BEACON_ATTESTER} from "@lodestar/params";
|
|
2
|
+
import {AttesterSlashing, IndexedAttestationBigint, SignedBeaconBlock, ssz} from "@lodestar/types";
|
|
3
|
+
import {CachedBeaconStateAllForks} from "../types.js";
|
|
4
|
+
import {ISignatureSet, SignatureSetType, computeSigningRoot, computeStartSlotAtEpoch} from "../util/index.js";
|
|
5
|
+
|
|
6
|
+
/** Get signature sets from all AttesterSlashing objects in a block */
|
|
7
|
+
export function getAttesterSlashingsSignatureSets(
|
|
8
|
+
state: CachedBeaconStateAllForks,
|
|
9
|
+
signedBlock: SignedBeaconBlock
|
|
10
|
+
): ISignatureSet[] {
|
|
11
|
+
return signedBlock.message.body.attesterSlashings.flatMap((attesterSlashing) =>
|
|
12
|
+
getAttesterSlashingSignatureSets(state, attesterSlashing)
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Get signature sets from a single AttesterSlashing object */
|
|
17
|
+
export function getAttesterSlashingSignatureSets(
|
|
18
|
+
state: CachedBeaconStateAllForks,
|
|
19
|
+
attesterSlashing: AttesterSlashing
|
|
20
|
+
): ISignatureSet[] {
|
|
21
|
+
return [attesterSlashing.attestation1, attesterSlashing.attestation2].map((attestation) =>
|
|
22
|
+
getIndexedAttestationBigintSignatureSet(state, attestation)
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function getIndexedAttestationBigintSignatureSet(
|
|
27
|
+
state: CachedBeaconStateAllForks,
|
|
28
|
+
indexedAttestation: IndexedAttestationBigint
|
|
29
|
+
): ISignatureSet {
|
|
30
|
+
const slot = computeStartSlotAtEpoch(Number(indexedAttestation.data.target.epoch as bigint));
|
|
31
|
+
const domain = state.config.getDomain(state.slot, DOMAIN_BEACON_ATTESTER, slot);
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
type: SignatureSetType.aggregate,
|
|
35
|
+
pubkeys: indexedAttestation.attestingIndices.map((i) => state.epochCtx.index2pubkey[i]),
|
|
36
|
+
signingRoot: computeSigningRoot(ssz.phase0.AttestationDataBigint, indexedAttestation.data, domain),
|
|
37
|
+
signature: indexedAttestation.signature,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {PublicKey} from "@chainsafe/blst";
|
|
2
|
+
import {BeaconConfig} from "@lodestar/config";
|
|
3
|
+
import {DOMAIN_BLS_TO_EXECUTION_CHANGE, ForkName} from "@lodestar/params";
|
|
4
|
+
import {capella, ssz} from "@lodestar/types";
|
|
5
|
+
import {CachedBeaconStateAllForks} from "../types.js";
|
|
6
|
+
import {ISignatureSet, SignatureSetType, computeSigningRoot, verifySignatureSet} from "../util/index.js";
|
|
7
|
+
|
|
8
|
+
export function verifyBlsToExecutionChangeSignature(
|
|
9
|
+
state: CachedBeaconStateAllForks,
|
|
10
|
+
signedBLSToExecutionChange: capella.SignedBLSToExecutionChange
|
|
11
|
+
): boolean {
|
|
12
|
+
return verifySignatureSet(getBlsToExecutionChangeSignatureSet(state.config, signedBLSToExecutionChange));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Extract signatures to allow validating all block signatures at once
|
|
17
|
+
*/
|
|
18
|
+
export function getBlsToExecutionChangeSignatureSet(
|
|
19
|
+
config: BeaconConfig,
|
|
20
|
+
signedBLSToExecutionChange: capella.SignedBLSToExecutionChange
|
|
21
|
+
): ISignatureSet {
|
|
22
|
+
// signatureFork for signing domain is fixed
|
|
23
|
+
const signatureFork = ForkName.phase0;
|
|
24
|
+
const domain = config.getDomainAtFork(signatureFork, DOMAIN_BLS_TO_EXECUTION_CHANGE);
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
type: SignatureSetType.single,
|
|
28
|
+
// The withdrawal pubkey is the same as signedBLSToExecutionChange's fromBlsPubkey as it should
|
|
29
|
+
// be validated against the withdrawal credentials digest
|
|
30
|
+
pubkey: PublicKey.fromBytes(signedBLSToExecutionChange.message.fromBlsPubkey, true),
|
|
31
|
+
signingRoot: computeSigningRoot(ssz.capella.BLSToExecutionChange, signedBLSToExecutionChange.message, domain),
|
|
32
|
+
signature: signedBLSToExecutionChange.signature,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function getBlsToExecutionChangeSignatureSets(
|
|
37
|
+
config: BeaconConfig,
|
|
38
|
+
signedBlock: capella.SignedBeaconBlock
|
|
39
|
+
): ISignatureSet[] {
|
|
40
|
+
return signedBlock.message.body.blsToExecutionChanges.map((blsToExecutionChange) =>
|
|
41
|
+
getBlsToExecutionChangeSignatureSet(config, blsToExecutionChange)
|
|
42
|
+
);
|
|
43
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {ForkSeq} from "@lodestar/params";
|
|
2
|
+
import {SignedBeaconBlock, altair, capella} from "@lodestar/types";
|
|
3
|
+
import {getSyncCommitteeSignatureSet} from "../block/processSyncCommittee.js";
|
|
4
|
+
import {CachedBeaconStateAllForks, CachedBeaconStateAltair} from "../types.js";
|
|
5
|
+
import {ISignatureSet} from "../util/index.js";
|
|
6
|
+
import {getAttesterSlashingsSignatureSets} from "./attesterSlashings.js";
|
|
7
|
+
import {getBlsToExecutionChangeSignatureSets} from "./blsToExecutionChange.js";
|
|
8
|
+
import {getAttestationsSignatureSets} from "./indexedAttestation.js";
|
|
9
|
+
import {getBlockProposerSignatureSet} from "./proposer.js";
|
|
10
|
+
import {getProposerSlashingsSignatureSets} from "./proposerSlashings.js";
|
|
11
|
+
import {getRandaoRevealSignatureSet} from "./randao.js";
|
|
12
|
+
import {getVoluntaryExitsSignatureSets} from "./voluntaryExits.js";
|
|
13
|
+
|
|
14
|
+
export * from "./attesterSlashings.js";
|
|
15
|
+
export * from "./blsToExecutionChange.js";
|
|
16
|
+
export * from "./indexedAttestation.js";
|
|
17
|
+
export * from "./proposer.js";
|
|
18
|
+
export * from "./proposerSlashings.js";
|
|
19
|
+
export * from "./randao.js";
|
|
20
|
+
export * from "./voluntaryExits.js";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Includes all signatures on the block (except the deposit signatures) for verification.
|
|
24
|
+
* Deposits are not included because they can legally have invalid signatures.
|
|
25
|
+
*/
|
|
26
|
+
export function getBlockSignatureSets(
|
|
27
|
+
state: CachedBeaconStateAllForks,
|
|
28
|
+
signedBlock: SignedBeaconBlock,
|
|
29
|
+
opts?: {
|
|
30
|
+
/** Useful since block proposer signature is verified beforehand on gossip validation */
|
|
31
|
+
skipProposerSignature?: boolean;
|
|
32
|
+
}
|
|
33
|
+
): ISignatureSet[] {
|
|
34
|
+
// fork based validations
|
|
35
|
+
const fork = state.config.getForkSeq(signedBlock.message.slot);
|
|
36
|
+
|
|
37
|
+
const signatureSets = [
|
|
38
|
+
getRandaoRevealSignatureSet(state, signedBlock.message),
|
|
39
|
+
...getProposerSlashingsSignatureSets(state, signedBlock),
|
|
40
|
+
...getAttesterSlashingsSignatureSets(state, signedBlock),
|
|
41
|
+
...getAttestationsSignatureSets(state, signedBlock),
|
|
42
|
+
...getVoluntaryExitsSignatureSets(state, signedBlock),
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
if (!opts?.skipProposerSignature) {
|
|
46
|
+
signatureSets.push(getBlockProposerSignatureSet(state, signedBlock));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Only after altair fork, validate tSyncCommitteeSignature
|
|
50
|
+
if (fork >= ForkSeq.altair) {
|
|
51
|
+
const syncCommitteeSignatureSet = getSyncCommitteeSignatureSet(
|
|
52
|
+
state as CachedBeaconStateAltair,
|
|
53
|
+
(signedBlock as altair.SignedBeaconBlock).message
|
|
54
|
+
);
|
|
55
|
+
// There may be no participants in this syncCommitteeSignature, so it must not be validated
|
|
56
|
+
if (syncCommitteeSignatureSet) {
|
|
57
|
+
signatureSets.push(syncCommitteeSignatureSet);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// only after capella fork
|
|
62
|
+
if (fork >= ForkSeq.capella) {
|
|
63
|
+
const blsToExecutionChangeSignatureSets = getBlsToExecutionChangeSignatureSets(
|
|
64
|
+
state.config,
|
|
65
|
+
signedBlock as capella.SignedBeaconBlock
|
|
66
|
+
);
|
|
67
|
+
if (blsToExecutionChangeSignatureSets.length > 0) {
|
|
68
|
+
signatureSets.push(...blsToExecutionChangeSignatureSets);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return signatureSets;
|
|
73
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {DOMAIN_BEACON_ATTESTER} from "@lodestar/params";
|
|
2
|
+
import {IndexedAttestation, SignedBeaconBlock, phase0, ssz} from "@lodestar/types";
|
|
3
|
+
import {CachedBeaconStateAllForks} from "../types.js";
|
|
4
|
+
import {
|
|
5
|
+
ISignatureSet,
|
|
6
|
+
computeSigningRoot,
|
|
7
|
+
computeStartSlotAtEpoch,
|
|
8
|
+
createAggregateSignatureSetFromComponents,
|
|
9
|
+
} from "../util/index.js";
|
|
10
|
+
|
|
11
|
+
export function getAttestationDataSigningRoot(
|
|
12
|
+
state: CachedBeaconStateAllForks,
|
|
13
|
+
data: phase0.AttestationData
|
|
14
|
+
): Uint8Array {
|
|
15
|
+
const slot = computeStartSlotAtEpoch(data.target.epoch);
|
|
16
|
+
const domain = state.config.getDomain(state.slot, DOMAIN_BEACON_ATTESTER, slot);
|
|
17
|
+
|
|
18
|
+
return computeSigningRoot(ssz.phase0.AttestationData, data, domain);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function getAttestationWithIndicesSignatureSet(
|
|
22
|
+
state: CachedBeaconStateAllForks,
|
|
23
|
+
attestation: Pick<phase0.Attestation, "data" | "signature">,
|
|
24
|
+
attestingIndices: number[]
|
|
25
|
+
): ISignatureSet {
|
|
26
|
+
return createAggregateSignatureSetFromComponents(
|
|
27
|
+
attestingIndices.map((i) => state.epochCtx.index2pubkey[i]),
|
|
28
|
+
getAttestationDataSigningRoot(state, attestation.data),
|
|
29
|
+
attestation.signature
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function getIndexedAttestationSignatureSet(
|
|
34
|
+
state: CachedBeaconStateAllForks,
|
|
35
|
+
indexedAttestation: IndexedAttestation
|
|
36
|
+
): ISignatureSet {
|
|
37
|
+
return getAttestationWithIndicesSignatureSet(state, indexedAttestation, indexedAttestation.attestingIndices);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function getAttestationsSignatureSets(
|
|
41
|
+
state: CachedBeaconStateAllForks,
|
|
42
|
+
signedBlock: SignedBeaconBlock
|
|
43
|
+
): ISignatureSet[] {
|
|
44
|
+
// TODO: figure how to get attesting indices of an attestation once per block processing
|
|
45
|
+
return signedBlock.message.body.attestations.map((attestation) =>
|
|
46
|
+
getIndexedAttestationSignatureSet(
|
|
47
|
+
state,
|
|
48
|
+
state.epochCtx.getIndexedAttestation(state.config.getForkSeq(signedBlock.message.slot), attestation)
|
|
49
|
+
)
|
|
50
|
+
);
|
|
51
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import {DOMAIN_BEACON_PROPOSER} from "@lodestar/params";
|
|
2
|
+
import {SignedBeaconBlock, SignedBlindedBeaconBlock, isBlindedBeaconBlock, phase0, ssz} from "@lodestar/types";
|
|
3
|
+
import {CachedBeaconStateAllForks} from "../types.js";
|
|
4
|
+
import {computeSigningRoot} from "../util/index.js";
|
|
5
|
+
import {ISignatureSet, SignatureSetType, verifySignatureSet} from "../util/signatureSets.js";
|
|
6
|
+
|
|
7
|
+
export function verifyProposerSignature(
|
|
8
|
+
state: CachedBeaconStateAllForks,
|
|
9
|
+
signedBlock: SignedBeaconBlock | SignedBlindedBeaconBlock
|
|
10
|
+
): boolean {
|
|
11
|
+
const signatureSet = getBlockProposerSignatureSet(state, signedBlock);
|
|
12
|
+
return verifySignatureSet(signatureSet);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function getBlockProposerSignatureSet(
|
|
16
|
+
state: CachedBeaconStateAllForks,
|
|
17
|
+
signedBlock: SignedBeaconBlock | SignedBlindedBeaconBlock
|
|
18
|
+
): ISignatureSet {
|
|
19
|
+
const {config, epochCtx} = state;
|
|
20
|
+
const domain = config.getDomain(state.slot, DOMAIN_BEACON_PROPOSER, signedBlock.message.slot);
|
|
21
|
+
|
|
22
|
+
const blockType = isBlindedBeaconBlock(signedBlock.message)
|
|
23
|
+
? config.getPostBellatrixForkTypes(signedBlock.message.slot).BlindedBeaconBlock
|
|
24
|
+
: config.getForkTypes(signedBlock.message.slot).BeaconBlock;
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
type: SignatureSetType.single,
|
|
28
|
+
pubkey: epochCtx.index2pubkey[signedBlock.message.proposerIndex],
|
|
29
|
+
signingRoot: computeSigningRoot(blockType, signedBlock.message, domain),
|
|
30
|
+
signature: signedBlock.signature,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function getBlockHeaderProposerSignatureSet(
|
|
35
|
+
state: CachedBeaconStateAllForks,
|
|
36
|
+
signedBlockHeader: phase0.SignedBeaconBlockHeader
|
|
37
|
+
): ISignatureSet {
|
|
38
|
+
const {config, epochCtx} = state;
|
|
39
|
+
const domain = config.getDomain(state.slot, DOMAIN_BEACON_PROPOSER, signedBlockHeader.message.slot);
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
type: SignatureSetType.single,
|
|
43
|
+
pubkey: epochCtx.index2pubkey[signedBlockHeader.message.proposerIndex],
|
|
44
|
+
signingRoot: computeSigningRoot(ssz.phase0.BeaconBlockHeader, signedBlockHeader.message, domain),
|
|
45
|
+
signature: signedBlockHeader.signature,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {DOMAIN_BEACON_PROPOSER} from "@lodestar/params";
|
|
2
|
+
import {SignedBeaconBlock, phase0, ssz} from "@lodestar/types";
|
|
3
|
+
import {CachedBeaconStateAllForks} from "../types.js";
|
|
4
|
+
import {ISignatureSet, SignatureSetType, computeSigningRoot} from "../util/index.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Extract signatures to allow validating all block signatures at once
|
|
8
|
+
*/
|
|
9
|
+
export function getProposerSlashingSignatureSets(
|
|
10
|
+
state: CachedBeaconStateAllForks,
|
|
11
|
+
proposerSlashing: phase0.ProposerSlashing
|
|
12
|
+
): ISignatureSet[] {
|
|
13
|
+
const {epochCtx} = state;
|
|
14
|
+
const pubkey = epochCtx.index2pubkey[proposerSlashing.signedHeader1.message.proposerIndex];
|
|
15
|
+
|
|
16
|
+
// In state transition, ProposerSlashing headers are only partially validated. Their slot could be higher than the
|
|
17
|
+
// clock and the slashing would still be valid. Must use bigint variants to hash correctly to all possible values
|
|
18
|
+
return [proposerSlashing.signedHeader1, proposerSlashing.signedHeader2].map((signedHeader): ISignatureSet => {
|
|
19
|
+
const domain = state.config.getDomain(
|
|
20
|
+
state.slot,
|
|
21
|
+
DOMAIN_BEACON_PROPOSER,
|
|
22
|
+
Number(signedHeader.message.slot as bigint)
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
type: SignatureSetType.single,
|
|
27
|
+
pubkey,
|
|
28
|
+
signingRoot: computeSigningRoot(ssz.phase0.BeaconBlockHeaderBigint, signedHeader.message, domain),
|
|
29
|
+
signature: signedHeader.signature,
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function getProposerSlashingsSignatureSets(
|
|
35
|
+
state: CachedBeaconStateAllForks,
|
|
36
|
+
signedBlock: SignedBeaconBlock
|
|
37
|
+
): ISignatureSet[] {
|
|
38
|
+
return signedBlock.message.body.proposerSlashings.flatMap((proposerSlashing) =>
|
|
39
|
+
getProposerSlashingSignatureSets(state, proposerSlashing)
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {DOMAIN_RANDAO} from "@lodestar/params";
|
|
2
|
+
import {BeaconBlock, ssz} from "@lodestar/types";
|
|
3
|
+
import {CachedBeaconStateAllForks} from "../types.js";
|
|
4
|
+
import {
|
|
5
|
+
ISignatureSet,
|
|
6
|
+
SignatureSetType,
|
|
7
|
+
computeEpochAtSlot,
|
|
8
|
+
computeSigningRoot,
|
|
9
|
+
verifySignatureSet,
|
|
10
|
+
} from "../util/index.js";
|
|
11
|
+
|
|
12
|
+
export function verifyRandaoSignature(state: CachedBeaconStateAllForks, block: BeaconBlock): boolean {
|
|
13
|
+
return verifySignatureSet(getRandaoRevealSignatureSet(state, block));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Extract signatures to allow validating all block signatures at once
|
|
18
|
+
*/
|
|
19
|
+
export function getRandaoRevealSignatureSet(state: CachedBeaconStateAllForks, block: BeaconBlock): ISignatureSet {
|
|
20
|
+
const {epochCtx} = state;
|
|
21
|
+
// should not get epoch from epochCtx
|
|
22
|
+
const epoch = computeEpochAtSlot(block.slot);
|
|
23
|
+
const domain = state.config.getDomain(state.slot, DOMAIN_RANDAO, block.slot);
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
type: SignatureSetType.single,
|
|
27
|
+
pubkey: epochCtx.index2pubkey[block.proposerIndex],
|
|
28
|
+
signingRoot: computeSigningRoot(ssz.Epoch, epoch, domain),
|
|
29
|
+
signature: block.body.randaoReveal,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {SignedBeaconBlock, phase0, ssz} from "@lodestar/types";
|
|
2
|
+
import {CachedBeaconStateAllForks} from "../types.js";
|
|
3
|
+
import {
|
|
4
|
+
ISignatureSet,
|
|
5
|
+
SignatureSetType,
|
|
6
|
+
computeSigningRoot,
|
|
7
|
+
computeStartSlotAtEpoch,
|
|
8
|
+
verifySignatureSet,
|
|
9
|
+
} from "../util/index.js";
|
|
10
|
+
|
|
11
|
+
export function verifyVoluntaryExitSignature(
|
|
12
|
+
state: CachedBeaconStateAllForks,
|
|
13
|
+
signedVoluntaryExit: phase0.SignedVoluntaryExit
|
|
14
|
+
): boolean {
|
|
15
|
+
return verifySignatureSet(getVoluntaryExitSignatureSet(state, signedVoluntaryExit));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Extract signatures to allow validating all block signatures at once
|
|
20
|
+
*/
|
|
21
|
+
export function getVoluntaryExitSignatureSet(
|
|
22
|
+
state: CachedBeaconStateAllForks,
|
|
23
|
+
signedVoluntaryExit: phase0.SignedVoluntaryExit
|
|
24
|
+
): ISignatureSet {
|
|
25
|
+
const {epochCtx} = state;
|
|
26
|
+
const slot = computeStartSlotAtEpoch(signedVoluntaryExit.message.epoch);
|
|
27
|
+
const domain = state.config.getDomainForVoluntaryExit(state.slot, slot);
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
type: SignatureSetType.single,
|
|
31
|
+
pubkey: epochCtx.index2pubkey[signedVoluntaryExit.message.validatorIndex],
|
|
32
|
+
signingRoot: computeSigningRoot(ssz.phase0.VoluntaryExit, signedVoluntaryExit.message, domain),
|
|
33
|
+
signature: signedVoluntaryExit.signature,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function getVoluntaryExitsSignatureSets(
|
|
38
|
+
state: CachedBeaconStateAllForks,
|
|
39
|
+
signedBlock: SignedBeaconBlock
|
|
40
|
+
): ISignatureSet[] {
|
|
41
|
+
return signedBlock.message.body.voluntaryExits.map((voluntaryExit) =>
|
|
42
|
+
getVoluntaryExitSignatureSet(state, voluntaryExit)
|
|
43
|
+
);
|
|
44
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {byteArrayEquals} from "@chainsafe/ssz";
|
|
2
|
+
import {SLOTS_PER_HISTORICAL_ROOT} from "@lodestar/params";
|
|
3
|
+
import {ZERO_HASH} from "../constants/index.js";
|
|
4
|
+
import {CachedBeaconStateAllForks} from "../types.js";
|
|
5
|
+
|
|
6
|
+
export {upgradeStateToAltair} from "./upgradeStateToAltair.js";
|
|
7
|
+
export {upgradeStateToBellatrix} from "./upgradeStateToBellatrix.js";
|
|
8
|
+
export {upgradeStateToCapella} from "./upgradeStateToCapella.js";
|
|
9
|
+
export {upgradeStateToDeneb} from "./upgradeStateToDeneb.js";
|
|
10
|
+
export {upgradeStateToElectra} from "./upgradeStateToElectra.js";
|
|
11
|
+
export {upgradeStateToFulu} from "./upgradeStateToFulu.js";
|
|
12
|
+
export {upgradeStateToGloas} from "./upgradeStateToGloas.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Dial state to next slot. Common for all forks
|
|
16
|
+
*/
|
|
17
|
+
export function processSlot(state: CachedBeaconStateAllForks): void {
|
|
18
|
+
// Cache state root
|
|
19
|
+
// Note: .hashTreeRoot() automatically commits() pending changes
|
|
20
|
+
const previousStateRoot = state.hashTreeRoot();
|
|
21
|
+
state.stateRoots.set(state.slot % SLOTS_PER_HISTORICAL_ROOT, previousStateRoot);
|
|
22
|
+
|
|
23
|
+
// Cache latest block header state root
|
|
24
|
+
if (byteArrayEquals(state.latestBlockHeader.stateRoot, ZERO_HASH)) {
|
|
25
|
+
state.latestBlockHeader.stateRoot = previousStateRoot;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Cache block root
|
|
29
|
+
// Note: .hashTreeRoot() automatically commits() pending changes
|
|
30
|
+
const previousBlockRoot = state.latestBlockHeader.hashTreeRoot();
|
|
31
|
+
state.blockRoots.set(state.slot % SLOTS_PER_HISTORICAL_ROOT, previousBlockRoot);
|
|
32
|
+
}
|