@lodestar/state-transition 1.42.0-dev.f6213da56d → 1.42.0-dev.fb8f8a700e
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/isValidIndexedAttestation.d.ts.map +1 -1
- package/lib/block/isValidIndexedAttestation.js +2 -3
- package/lib/block/isValidIndexedAttestation.js.map +1 -1
- package/lib/block/processAttestationsAltair.d.ts +2 -1
- package/lib/block/processAttestationsAltair.d.ts.map +1 -1
- package/lib/block/processAttestationsAltair.js +5 -3
- package/lib/block/processAttestationsAltair.js.map +1 -1
- package/lib/index.d.ts +4 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -1
- package/lib/index.js.map +1 -1
- package/lib/signatureSets/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/signatureSets/executionPayloadEnvelope.js +4 -0
- package/lib/signatureSets/executionPayloadEnvelope.js.map +1 -1
- package/lib/signatureSets/index.d.ts +2 -2
- package/lib/signatureSets/index.d.ts.map +1 -1
- package/lib/signatureSets/index.js +1 -2
- package/lib/signatureSets/index.js.map +1 -1
- package/lib/signatureSets/voluntaryExits.d.ts +2 -2
- package/lib/signatureSets/voluntaryExits.d.ts.map +1 -1
- package/lib/signatureSets/voluntaryExits.js +4 -0
- package/lib/signatureSets/voluntaryExits.js.map +1 -1
- package/lib/slot/upgradeStateToAltair.d.ts.map +1 -1
- package/lib/slot/upgradeStateToAltair.js +2 -1
- package/lib/slot/upgradeStateToAltair.js.map +1 -1
- package/lib/stateView/beaconStateView.d.ts +10 -11
- package/lib/stateView/beaconStateView.d.ts.map +1 -1
- package/lib/stateView/beaconStateView.js +11 -32
- package/lib/stateView/beaconStateView.js.map +1 -1
- package/lib/stateView/index.d.ts +1 -0
- package/lib/stateView/index.d.ts.map +1 -1
- package/lib/stateView/index.js +1 -0
- package/lib/stateView/index.js.map +1 -1
- package/lib/stateView/interface.d.ts +104 -54
- package/lib/stateView/interface.d.ts.map +1 -1
- package/lib/stateView/interface.js +22 -1
- package/lib/stateView/interface.js.map +1 -1
- package/lib/stateView/stateViewFactory.d.ts +40 -0
- package/lib/stateView/stateViewFactory.d.ts.map +1 -0
- package/lib/stateView/stateViewFactory.js +46 -0
- package/lib/stateView/stateViewFactory.js.map +1 -0
- package/lib/testUtils/cache.d.ts.map +1 -1
- package/lib/testUtils/cache.js +1 -1
- package/lib/testUtils/cache.js.map +1 -1
- package/lib/testUtils/util.d.ts +13 -1
- package/lib/testUtils/util.d.ts.map +1 -1
- package/lib/testUtils/util.js +119 -19
- package/lib/testUtils/util.js.map +1 -1
- package/lib/util/rootCache.d.ts +2 -2
- package/lib/util/rootCache.d.ts.map +1 -1
- package/lib/util/rootCache.js +2 -3
- package/lib/util/rootCache.js.map +1 -1
- package/lib/util/shuffling.d.ts +2 -1
- package/lib/util/shuffling.d.ts.map +1 -1
- package/lib/util/shuffling.js +2 -2
- package/lib/util/shuffling.js.map +1 -1
- package/package.json +7 -7
- package/src/block/isValidIndexedAttestation.ts +2 -3
- package/src/block/processAttestationsAltair.ts +7 -4
- package/src/index.ts +20 -2
- package/src/signatureSets/executionPayloadEnvelope.ts +5 -1
- package/src/signatureSets/index.ts +3 -4
- package/src/signatureSets/voluntaryExits.ts +5 -2
- package/src/slot/upgradeStateToAltair.ts +2 -1
- package/src/stateView/beaconStateView.ts +23 -51
- package/src/stateView/index.ts +1 -0
- package/src/stateView/interface.ts +147 -73
- package/src/stateView/stateViewFactory.ts +78 -0
- package/src/testUtils/cache.ts +1 -1
- package/src/testUtils/util.ts +136 -22
- package/src/util/rootCache.ts +4 -5
- package/src/util/shuffling.ts +5 -4
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {CompactMultiProof, ProofType, Tree, createProof} from "@chainsafe/persistent-merkle-tree";
|
|
2
|
-
import {ByteViews} from "@chainsafe/ssz";
|
|
2
|
+
import {BitArray, ByteViews} from "@chainsafe/ssz";
|
|
3
3
|
import {BeaconConfig} from "@lodestar/config";
|
|
4
|
-
import {ForkSeq, SLOTS_PER_HISTORICAL_ROOT, isForkPostGloas} from "@lodestar/params";
|
|
4
|
+
import {ForkName, ForkSeq, SLOTS_PER_HISTORICAL_ROOT, isForkPostGloas} from "@lodestar/params";
|
|
5
5
|
import {
|
|
6
6
|
BeaconBlock,
|
|
7
|
+
BeaconState,
|
|
7
8
|
BlindedBeaconBlock,
|
|
8
9
|
BuilderIndex,
|
|
9
10
|
Bytes32,
|
|
@@ -33,7 +34,6 @@ import {VoluntaryExitValidity, getVoluntaryExitValidity} from "../block/processV
|
|
|
33
34
|
import {getExpectedWithdrawals} from "../block/processWithdrawals.js";
|
|
34
35
|
import {EffectiveBalanceIncrements} from "../cache/effectiveBalanceIncrements.js";
|
|
35
36
|
import {EpochTransitionCacheOpts} from "../cache/epochTransitionCache.js";
|
|
36
|
-
import {PubkeyCache, createPubkeyCache} from "../cache/pubkeyCache.js";
|
|
37
37
|
import {RewardCache} from "../cache/rewardCache.js";
|
|
38
38
|
import {
|
|
39
39
|
CachedBeaconStateAllForks,
|
|
@@ -47,7 +47,6 @@ import {
|
|
|
47
47
|
isStateValidatorsNodesPopulated,
|
|
48
48
|
} from "../cache/stateCache.js";
|
|
49
49
|
import {SyncCommitteeCache} from "../cache/syncCommitteeCache.js";
|
|
50
|
-
import {BeaconStateAllForks} from "../cache/types.js";
|
|
51
50
|
import {computeUnrealizedCheckpoints} from "../epoch/computeUnrealizedCheckpoints.js";
|
|
52
51
|
import {getFinalizedRootProof, getSyncCommitteesWitness} from "../lightClient/proofs.js";
|
|
53
52
|
import {SyncCommitteeWitness} from "../lightClient/types.js";
|
|
@@ -64,11 +63,10 @@ import {isExecutionEnabled, isExecutionStateType, isMergeTransitionComplete} fro
|
|
|
64
63
|
import {canBuilderCoverBid} from "../util/gloas.js";
|
|
65
64
|
import {loadState} from "../util/loadState/loadState.js";
|
|
66
65
|
import {getRandaoMix} from "../util/seed.js";
|
|
67
|
-
import {getStateTypeFromBytes} from "../util/sszBytes.js";
|
|
68
66
|
import {getLatestWeakSubjectivityCheckpointEpoch} from "../util/weakSubjectivity.js";
|
|
69
|
-
import {IBeaconStateView} from "./interface.js";
|
|
67
|
+
import {IBeaconStateView, IBeaconStateViewLatestFork} from "./interface.js";
|
|
70
68
|
|
|
71
|
-
export class BeaconStateView implements
|
|
69
|
+
export class BeaconStateView implements IBeaconStateViewLatestFork {
|
|
72
70
|
private readonly config: BeaconConfig;
|
|
73
71
|
// Cached values extracted from the tree
|
|
74
72
|
// phase0
|
|
@@ -92,7 +90,7 @@ export class BeaconStateView implements IBeaconStateView {
|
|
|
92
90
|
// fulu
|
|
93
91
|
private _proposerLookahead: fulu.ProposerLookahead | null = null;
|
|
94
92
|
// gloas
|
|
95
|
-
private _executionPayloadAvailability:
|
|
93
|
+
private _executionPayloadAvailability: BitArray | null = null;
|
|
96
94
|
private _latestExecutionPayloadBid: ExecutionPayloadBid | null = null;
|
|
97
95
|
|
|
98
96
|
constructor(readonly cachedState: CachedBeaconStateAllForks) {
|
|
@@ -101,6 +99,10 @@ export class BeaconStateView implements IBeaconStateView {
|
|
|
101
99
|
|
|
102
100
|
// phase0
|
|
103
101
|
|
|
102
|
+
get forkName(): ForkName {
|
|
103
|
+
return this.config.getForkName(this.cachedState.slot);
|
|
104
|
+
}
|
|
105
|
+
|
|
104
106
|
get slot(): number {
|
|
105
107
|
return this.cachedState.slot;
|
|
106
108
|
}
|
|
@@ -357,15 +359,15 @@ export class BeaconStateView implements IBeaconStateView {
|
|
|
357
359
|
|
|
358
360
|
// gloas
|
|
359
361
|
|
|
360
|
-
get executionPayloadAvailability():
|
|
362
|
+
get executionPayloadAvailability(): BitArray {
|
|
361
363
|
if (this.config.getForkSeq(this.cachedState.slot) < ForkSeq.gloas) {
|
|
362
364
|
throw new Error("executionPayloadAvailability is not available before GLOAS");
|
|
363
365
|
}
|
|
364
366
|
|
|
365
367
|
if (this._executionPayloadAvailability === null) {
|
|
366
|
-
this._executionPayloadAvailability = (
|
|
367
|
-
.
|
|
368
|
-
|
|
368
|
+
this._executionPayloadAvailability = (
|
|
369
|
+
this.cachedState as CachedBeaconStateGloas
|
|
370
|
+
).executionPayloadAvailability.toValue();
|
|
369
371
|
}
|
|
370
372
|
|
|
371
373
|
return this._executionPayloadAvailability;
|
|
@@ -404,7 +406,7 @@ export class BeaconStateView implements IBeaconStateView {
|
|
|
404
406
|
* Return the index of the validator in the PTC committee for the given slot.
|
|
405
407
|
* return -1 if validator is not in the PTC committee for the given slot.
|
|
406
408
|
*/
|
|
407
|
-
|
|
409
|
+
getIndexInPayloadTimelinessCommittee(validatorIndex: ValidatorIndex, slot: Slot): number {
|
|
408
410
|
if (this.config.getForkSeq(this.cachedState.slot) < ForkSeq.gloas) {
|
|
409
411
|
throw new Error("PTC committees are not supported before GLOAS");
|
|
410
412
|
}
|
|
@@ -503,6 +505,10 @@ export class BeaconStateView implements IBeaconStateView {
|
|
|
503
505
|
return this.cachedState.epochCtx.syncProposerReward;
|
|
504
506
|
}
|
|
505
507
|
|
|
508
|
+
getIndexedSyncCommittee(slot: Slot): SyncCommitteeCache {
|
|
509
|
+
return this.cachedState.epochCtx.getIndexedSyncCommittee(slot);
|
|
510
|
+
}
|
|
511
|
+
|
|
506
512
|
getIndexedSyncCommitteeAtEpoch(epoch: Epoch): SyncCommitteeCache {
|
|
507
513
|
return this.cachedState.epochCtx.getIndexedSyncCommitteeAtEpoch(epoch);
|
|
508
514
|
}
|
|
@@ -713,6 +719,10 @@ export class BeaconStateView implements IBeaconStateView {
|
|
|
713
719
|
return new BeaconStateView(cachedState);
|
|
714
720
|
}
|
|
715
721
|
|
|
722
|
+
toValue(): BeaconState {
|
|
723
|
+
return this.cachedState.toValue();
|
|
724
|
+
}
|
|
725
|
+
|
|
716
726
|
serialize(): Uint8Array {
|
|
717
727
|
return this.cachedState.serialize();
|
|
718
728
|
}
|
|
@@ -778,41 +788,3 @@ export class BeaconStateView implements IBeaconStateView {
|
|
|
778
788
|
return new BeaconStateView(postPayloadState);
|
|
779
789
|
}
|
|
780
790
|
}
|
|
781
|
-
|
|
782
|
-
/**
|
|
783
|
-
* Create BeaconStateView for historical state regen, no need to sync pubkey cache there.
|
|
784
|
-
*/
|
|
785
|
-
export function createBeaconStateViewForHistoricalRegen(
|
|
786
|
-
config: BeaconConfig,
|
|
787
|
-
stateBytes: Uint8Array
|
|
788
|
-
): IBeaconStateView {
|
|
789
|
-
const state = getStateTypeFromBytes(config, stateBytes).deserializeToViewDU(stateBytes);
|
|
790
|
-
|
|
791
|
-
const pubkeyCache = createPubkeyCache();
|
|
792
|
-
syncPubkeyCache(state, pubkeyCache);
|
|
793
|
-
const cachedState = createCachedBeaconState(
|
|
794
|
-
state,
|
|
795
|
-
{
|
|
796
|
-
config,
|
|
797
|
-
pubkeyCache,
|
|
798
|
-
},
|
|
799
|
-
{
|
|
800
|
-
skipSyncPubkeys: true,
|
|
801
|
-
}
|
|
802
|
-
);
|
|
803
|
-
|
|
804
|
-
return new BeaconStateView(cachedState);
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
/**
|
|
808
|
-
* Populate a PubkeyIndexMap with any new entries based on a BeaconState
|
|
809
|
-
*/
|
|
810
|
-
function syncPubkeyCache(state: BeaconStateAllForks, pubkeyCache: PubkeyCache): void {
|
|
811
|
-
// Get the validators sub tree once for all the loop
|
|
812
|
-
|
|
813
|
-
const newCount = state.validators.length;
|
|
814
|
-
for (let i = pubkeyCache.size; i < newCount; i++) {
|
|
815
|
-
const pubkey = state.validators.getReadonly(i).pubkey;
|
|
816
|
-
pubkeyCache.set(i, pubkey);
|
|
817
|
-
}
|
|
818
|
-
}
|
package/src/stateView/index.ts
CHANGED
|
@@ -1,7 +1,25 @@
|
|
|
1
1
|
import {CompactMultiProof} from "@chainsafe/persistent-merkle-tree";
|
|
2
|
-
import {ByteViews} from "@chainsafe/ssz";
|
|
2
|
+
import {BitArray, ByteViews} from "@chainsafe/ssz";
|
|
3
|
+
import {
|
|
4
|
+
ForkName,
|
|
5
|
+
ForkPostAltair,
|
|
6
|
+
ForkPostBellatrix,
|
|
7
|
+
ForkPostCapella,
|
|
8
|
+
ForkPostDeneb,
|
|
9
|
+
ForkPostElectra,
|
|
10
|
+
ForkPostFulu,
|
|
11
|
+
ForkPostGloas,
|
|
12
|
+
isForkPostAltair,
|
|
13
|
+
isForkPostBellatrix,
|
|
14
|
+
isForkPostCapella,
|
|
15
|
+
isForkPostDeneb,
|
|
16
|
+
isForkPostElectra,
|
|
17
|
+
isForkPostFulu,
|
|
18
|
+
isForkPostGloas,
|
|
19
|
+
} from "@lodestar/params";
|
|
3
20
|
import {
|
|
4
21
|
BeaconBlock,
|
|
22
|
+
BeaconState,
|
|
5
23
|
BlindedBeaconBlock,
|
|
6
24
|
BuilderIndex,
|
|
7
25
|
Bytes32,
|
|
@@ -40,6 +58,7 @@ export interface IBeaconStateView {
|
|
|
40
58
|
// State access
|
|
41
59
|
|
|
42
60
|
// phase0
|
|
61
|
+
forkName: ForkName;
|
|
43
62
|
slot: Slot;
|
|
44
63
|
fork: Fork;
|
|
45
64
|
epoch: Epoch;
|
|
@@ -55,50 +74,6 @@ export interface IBeaconStateView {
|
|
|
55
74
|
getStateRootAtSlot(slot: Slot): Root;
|
|
56
75
|
getRandaoMix(epoch: Epoch): Bytes32;
|
|
57
76
|
|
|
58
|
-
// altair
|
|
59
|
-
previousEpochParticipation: Uint8Array;
|
|
60
|
-
currentEpochParticipation: Uint8Array;
|
|
61
|
-
getPreviousEpochParticipation(validatorIndex: ValidatorIndex): number;
|
|
62
|
-
getCurrentEpochParticipation(validatorIndex: ValidatorIndex): number;
|
|
63
|
-
|
|
64
|
-
// bellatrix
|
|
65
|
-
latestExecutionPayloadHeader: ExecutionPayloadHeader;
|
|
66
|
-
/**
|
|
67
|
-
* Cross-fork accessor for the execution block hash of the most recently included payload.
|
|
68
|
-
* Pre-gloas: returns latestExecutionPayloadHeader.blockHash (bellatrix–fulu).
|
|
69
|
-
* Gloas+: returns the dedicated latestBlockHash state field (EIP-7732).
|
|
70
|
-
* Throws before bellatrix.
|
|
71
|
-
*/
|
|
72
|
-
latestBlockHash: Bytes32;
|
|
73
|
-
/**
|
|
74
|
-
* The execution block number of the most recently included payload.
|
|
75
|
-
* Named payloadBlockNumber (not latestBlockNumber) to mirror ExecutionPayloadHeader.blockNumber pre-gloas.
|
|
76
|
-
* Only available from bellatrix through fulu — not tracked on BeaconState in gloas+ (EIP-7732).
|
|
77
|
-
* Throws before bellatrix and from gloas onwards.
|
|
78
|
-
*/
|
|
79
|
-
payloadBlockNumber: number;
|
|
80
|
-
|
|
81
|
-
// capella
|
|
82
|
-
historicalSummaries: capella.HistoricalSummaries;
|
|
83
|
-
|
|
84
|
-
// electra
|
|
85
|
-
pendingDeposits: electra.PendingDeposits;
|
|
86
|
-
pendingDepositsCount: number;
|
|
87
|
-
pendingPartialWithdrawals: electra.PendingPartialWithdrawals;
|
|
88
|
-
pendingPartialWithdrawalsCount: number;
|
|
89
|
-
pendingConsolidations: electra.PendingConsolidations;
|
|
90
|
-
pendingConsolidationsCount: number;
|
|
91
|
-
|
|
92
|
-
// fulu
|
|
93
|
-
proposerLookahead: fulu.ProposerLookahead;
|
|
94
|
-
|
|
95
|
-
// gloas
|
|
96
|
-
executionPayloadAvailability: boolean[];
|
|
97
|
-
latestExecutionPayloadBid: ExecutionPayloadBid;
|
|
98
|
-
getBuilder(index: BuilderIndex): gloas.Builder;
|
|
99
|
-
canBuilderCoverBid(builderIndex: BuilderIndex, bidAmount: number): boolean;
|
|
100
|
-
validatorPTCCommitteeIndex(validatorIndex: ValidatorIndex, slot: Slot): number;
|
|
101
|
-
|
|
102
77
|
// Shuffling and committees
|
|
103
78
|
getShufflingAtEpoch(epoch: Epoch): EpochShuffling;
|
|
104
79
|
// Decision roots
|
|
@@ -110,19 +85,11 @@ export interface IBeaconStateView {
|
|
|
110
85
|
getCurrentShuffling(): EpochShuffling;
|
|
111
86
|
getNextShuffling(): EpochShuffling;
|
|
112
87
|
|
|
113
|
-
//
|
|
88
|
+
// Proposer shuffling
|
|
114
89
|
previousProposers: ValidatorIndex[] | null;
|
|
115
90
|
currentProposers: ValidatorIndex[];
|
|
116
91
|
nextProposers: ValidatorIndex[];
|
|
117
92
|
getBeaconProposer(slot: Slot): ValidatorIndex;
|
|
118
|
-
computeAnchorCheckpoint(): {checkpoint: phase0.Checkpoint; blockHeader: phase0.BeaconBlockHeader};
|
|
119
|
-
|
|
120
|
-
// Sync committees
|
|
121
|
-
currentSyncCommittee: altair.SyncCommittee;
|
|
122
|
-
nextSyncCommittee: altair.SyncCommittee;
|
|
123
|
-
currentSyncCommitteeIndexed: SyncCommitteeCache;
|
|
124
|
-
syncProposerReward: number;
|
|
125
|
-
getIndexedSyncCommitteeAtEpoch(epoch: Epoch): SyncCommitteeCache;
|
|
126
93
|
|
|
127
94
|
// Validators and balances
|
|
128
95
|
effectiveBalanceIncrements: EffectiveBalanceIncrements;
|
|
@@ -138,28 +105,10 @@ export interface IBeaconStateView {
|
|
|
138
105
|
getAllValidators(): phase0.Validator[];
|
|
139
106
|
getAllBalances(): number[];
|
|
140
107
|
|
|
141
|
-
// Merge
|
|
142
|
-
isExecutionStateType: boolean;
|
|
143
|
-
isMergeTransitionComplete: boolean;
|
|
144
|
-
// TODO this should go away (or rather only need block)
|
|
145
|
-
isExecutionEnabled(block: BeaconBlock | BlindedBeaconBlock): boolean;
|
|
146
|
-
|
|
147
|
-
// Block production
|
|
148
|
-
getExpectedWithdrawals(): {
|
|
149
|
-
expectedWithdrawals: capella.Withdrawal[];
|
|
150
|
-
processedBuilderWithdrawalsCount: number;
|
|
151
|
-
processedPartialWithdrawalsCount: number;
|
|
152
|
-
processedValidatorSweepCount: number;
|
|
153
|
-
};
|
|
154
|
-
|
|
155
108
|
// API
|
|
156
109
|
proposerRewards: RewardCache;
|
|
157
110
|
computeBlockRewards(block: BeaconBlock, proposerRewards?: RewardCache): Promise<rewards.BlockRewards>;
|
|
158
111
|
computeAttestationsRewards(validatorIds?: (ValidatorIndex | string)[]): Promise<rewards.AttestationsRewards>;
|
|
159
|
-
computeSyncCommitteeRewards(
|
|
160
|
-
block: BeaconBlock,
|
|
161
|
-
validatorIds: (ValidatorIndex | string)[]
|
|
162
|
-
): Promise<rewards.SyncCommitteeRewards>;
|
|
163
112
|
getLatestWeakSubjectivityCheckpointEpoch(): Epoch;
|
|
164
113
|
|
|
165
114
|
// Validation
|
|
@@ -171,7 +120,6 @@ export interface IBeaconStateView {
|
|
|
171
120
|
|
|
172
121
|
// Proofs
|
|
173
122
|
getFinalizedRootProof(): Uint8Array[];
|
|
174
|
-
getSyncCommitteesWitness(): SyncCommitteeWitness;
|
|
175
123
|
getSingleProof(gindex: bigint): Uint8Array[];
|
|
176
124
|
createMultiProof(descriptor: Uint8Array): CompactMultiProof;
|
|
177
125
|
|
|
@@ -180,6 +128,7 @@ export interface IBeaconStateView {
|
|
|
180
128
|
justifiedCheckpoint: phase0.Checkpoint;
|
|
181
129
|
finalizedCheckpoint: phase0.Checkpoint;
|
|
182
130
|
};
|
|
131
|
+
computeAnchorCheckpoint(): {checkpoint: phase0.Checkpoint; blockHeader: phase0.BeaconBlockHeader};
|
|
183
132
|
|
|
184
133
|
// this is for backward compatible
|
|
185
134
|
clonedCount: number;
|
|
@@ -190,6 +139,7 @@ export interface IBeaconStateView {
|
|
|
190
139
|
|
|
191
140
|
// Serialization
|
|
192
141
|
loadOtherState(stateBytes: Uint8Array, seedValidatorsBytes?: Uint8Array): IBeaconStateView;
|
|
142
|
+
toValue(): BeaconState;
|
|
193
143
|
serialize(): Uint8Array;
|
|
194
144
|
serializedSize(): number;
|
|
195
145
|
serializeToBytes(output: ByteViews, offset: number): number;
|
|
@@ -210,8 +160,132 @@ export interface IBeaconStateView {
|
|
|
210
160
|
epochTransitionCacheOpts?: EpochTransitionCacheOpts & {dontTransferCache?: boolean},
|
|
211
161
|
modules?: StateTransitionModules
|
|
212
162
|
): IBeaconStateView;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** Altair+ state fields — use isStatePostAltair() guard */
|
|
166
|
+
export interface IBeaconStateViewAltair extends IBeaconStateView {
|
|
167
|
+
forkName: ForkPostAltair;
|
|
168
|
+
previousEpochParticipation: Uint8Array;
|
|
169
|
+
currentEpochParticipation: Uint8Array;
|
|
170
|
+
getPreviousEpochParticipation(validatorIndex: ValidatorIndex): number;
|
|
171
|
+
getCurrentEpochParticipation(validatorIndex: ValidatorIndex): number;
|
|
172
|
+
currentSyncCommittee: altair.SyncCommittee;
|
|
173
|
+
nextSyncCommittee: altair.SyncCommittee;
|
|
174
|
+
currentSyncCommitteeIndexed: SyncCommitteeCache;
|
|
175
|
+
syncProposerReward: number;
|
|
176
|
+
getIndexedSyncCommitteeAtEpoch(epoch: Epoch): SyncCommitteeCache;
|
|
177
|
+
/** Get indexed sync committee with slot+1 offset for duty lookups */
|
|
178
|
+
getIndexedSyncCommittee(slot: Slot): SyncCommitteeCache;
|
|
179
|
+
computeSyncCommitteeRewards(
|
|
180
|
+
block: BeaconBlock,
|
|
181
|
+
validatorIds: (ValidatorIndex | string)[]
|
|
182
|
+
): Promise<rewards.SyncCommitteeRewards>;
|
|
183
|
+
getSyncCommitteesWitness(): SyncCommitteeWitness;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Bellatrix+ state fields — use isStatePostBellatrix() guard */
|
|
187
|
+
export interface IBeaconStateViewBellatrix extends IBeaconStateViewAltair {
|
|
188
|
+
forkName: ForkPostBellatrix;
|
|
189
|
+
latestExecutionPayloadHeader: ExecutionPayloadHeader;
|
|
190
|
+
/**
|
|
191
|
+
* Cross-fork accessor for the execution block hash of the most recently included payload.
|
|
192
|
+
* Pre-gloas: returns latestExecutionPayloadHeader.blockHash (bellatrix–fulu).
|
|
193
|
+
* Gloas+: returns the dedicated latestBlockHash state field (EIP-7732).
|
|
194
|
+
* Throws before bellatrix.
|
|
195
|
+
*/
|
|
196
|
+
latestBlockHash: Bytes32;
|
|
197
|
+
/**
|
|
198
|
+
* The execution block number of the most recently included payload.
|
|
199
|
+
* Named payloadBlockNumber (not latestBlockNumber) to mirror ExecutionPayloadHeader.blockNumber pre-gloas.
|
|
200
|
+
* Only available from bellatrix through fulu — not tracked on BeaconState in gloas+ (EIP-7732).
|
|
201
|
+
* Throws before bellatrix and from gloas onwards.
|
|
202
|
+
*/
|
|
203
|
+
payloadBlockNumber: number;
|
|
204
|
+
isExecutionStateType: boolean;
|
|
205
|
+
isMergeTransitionComplete: boolean;
|
|
206
|
+
isExecutionEnabled(block: BeaconBlock | BlindedBeaconBlock): boolean;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/** Capella+ state fields — use isStatePostCapella() guard */
|
|
210
|
+
export interface IBeaconStateViewCapella extends IBeaconStateViewBellatrix {
|
|
211
|
+
forkName: ForkPostCapella;
|
|
212
|
+
historicalSummaries: capella.HistoricalSummaries;
|
|
213
|
+
getExpectedWithdrawals(): {
|
|
214
|
+
expectedWithdrawals: capella.Withdrawal[];
|
|
215
|
+
processedBuilderWithdrawalsCount: number;
|
|
216
|
+
processedPartialWithdrawalsCount: number;
|
|
217
|
+
processedBuildersSweepCount: number;
|
|
218
|
+
processedValidatorSweepCount: number;
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** Deneb+ state — no new state-view fields; placeholder for fork completeness and isStatePostDeneb() narrowing */
|
|
223
|
+
export interface IBeaconStateViewDeneb extends IBeaconStateViewCapella {
|
|
224
|
+
forkName: ForkPostDeneb;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** Electra+ state fields — use isStatePostElectra() guard */
|
|
228
|
+
export interface IBeaconStateViewElectra extends IBeaconStateViewDeneb {
|
|
229
|
+
forkName: ForkPostElectra;
|
|
230
|
+
pendingDeposits: electra.PendingDeposits;
|
|
231
|
+
pendingDepositsCount: number;
|
|
232
|
+
pendingPartialWithdrawals: electra.PendingPartialWithdrawals;
|
|
233
|
+
pendingPartialWithdrawalsCount: number;
|
|
234
|
+
pendingConsolidations: electra.PendingConsolidations;
|
|
235
|
+
pendingConsolidationsCount: number;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** Fulu+ state fields — use isStatePostFulu() guard */
|
|
239
|
+
export interface IBeaconStateViewFulu extends IBeaconStateViewElectra {
|
|
240
|
+
forkName: ForkPostFulu;
|
|
241
|
+
proposerLookahead: fulu.ProposerLookahead;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/** Gloas+ state fields — use isStatePostGloas() guard */
|
|
245
|
+
export interface IBeaconStateViewGloas extends IBeaconStateViewFulu {
|
|
246
|
+
forkName: ForkPostGloas;
|
|
247
|
+
executionPayloadAvailability: BitArray;
|
|
248
|
+
latestExecutionPayloadBid: ExecutionPayloadBid;
|
|
249
|
+
getBuilder(index: BuilderIndex): gloas.Builder;
|
|
250
|
+
canBuilderCoverBid(builderIndex: BuilderIndex, bidAmount: number): boolean;
|
|
251
|
+
getIndexInPayloadTimelinessCommittee(validatorIndex: ValidatorIndex, slot: Slot): number;
|
|
213
252
|
processExecutionPayloadEnvelope(
|
|
214
253
|
signedEnvelope: gloas.SignedExecutionPayloadEnvelope,
|
|
215
254
|
opts?: ProcessExecutionPayloadEnvelopeOpts
|
|
216
255
|
): IBeaconStateView;
|
|
217
256
|
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Type constraint for the concrete BeaconStateView class.
|
|
260
|
+
* Requires all fields from the latest fork interface (IBeaconStateViewGloas) but keeps
|
|
261
|
+
* forkName as ForkName since the class wraps any fork's state.
|
|
262
|
+
* Sub-interfaces retain their narrowed forkName discriminants for caller-side type guards.
|
|
263
|
+
*/
|
|
264
|
+
export type IBeaconStateViewLatestFork = Omit<IBeaconStateViewGloas, "forkName"> & {forkName: ForkName};
|
|
265
|
+
export function isStatePostAltair(state: IBeaconStateView): state is IBeaconStateViewAltair {
|
|
266
|
+
return isForkPostAltair(state.forkName);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export function isStatePostBellatrix(state: IBeaconStateView): state is IBeaconStateViewBellatrix {
|
|
270
|
+
return isForkPostBellatrix(state.forkName);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export function isStatePostCapella(state: IBeaconStateView): state is IBeaconStateViewCapella {
|
|
274
|
+
return isForkPostCapella(state.forkName);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export function isStatePostDeneb(state: IBeaconStateView): state is IBeaconStateViewDeneb {
|
|
278
|
+
return isForkPostDeneb(state.forkName);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export function isStatePostElectra(state: IBeaconStateView): state is IBeaconStateViewElectra {
|
|
282
|
+
return isForkPostElectra(state.forkName);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export function isStatePostFulu(state: IBeaconStateView): state is IBeaconStateViewFulu {
|
|
286
|
+
return isForkPostFulu(state.forkName);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export function isStatePostGloas(state: IBeaconStateView): state is IBeaconStateViewGloas {
|
|
290
|
+
return isForkPostGloas(state.forkName);
|
|
291
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import {BeaconConfig} from "@lodestar/config";
|
|
2
|
+
import {PubkeyCache, createPubkeyCache} from "../cache/pubkeyCache.js";
|
|
3
|
+
import {createCachedBeaconState} from "../cache/stateCache.js";
|
|
4
|
+
import {BeaconStateAllForks} from "../cache/types.js";
|
|
5
|
+
import {getStateTypeFromBytes} from "../util/sszBytes.js";
|
|
6
|
+
import {BeaconStateView} from "./beaconStateView.js";
|
|
7
|
+
import {IBeaconStateView} from "./interface.js";
|
|
8
|
+
|
|
9
|
+
// ---- createBeaconStateView (startup path) ----
|
|
10
|
+
|
|
11
|
+
type NodeJSOpts = {
|
|
12
|
+
useNative: false;
|
|
13
|
+
anchorState: BeaconStateAllForks;
|
|
14
|
+
config: BeaconConfig;
|
|
15
|
+
pubkeyCache: PubkeyCache;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
type NativeOpts = {
|
|
19
|
+
useNative: true;
|
|
20
|
+
stateBytes: Uint8Array;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Create a BeaconStateView from a pre-deserialized state. Used at node startup.
|
|
25
|
+
*
|
|
26
|
+
* The caller is responsible for creating and populating `pubkeyCache` (it is also
|
|
27
|
+
* passed separately to BeaconNode.init, so it must live outside this factory).
|
|
28
|
+
*
|
|
29
|
+
* Set `useNative: true` to use the native (Zig) implementation once available.
|
|
30
|
+
*/
|
|
31
|
+
export function createBeaconStateView(opts: NodeJSOpts | NativeOpts): IBeaconStateView {
|
|
32
|
+
if (opts.useNative) {
|
|
33
|
+
throw new Error("Native (Zig) BeaconStateView not yet implemented");
|
|
34
|
+
}
|
|
35
|
+
const {anchorState, config, pubkeyCache} = opts;
|
|
36
|
+
const cachedState = createCachedBeaconState(anchorState, {config, pubkeyCache}, {skipSyncPubkeys: true});
|
|
37
|
+
return new BeaconStateView(cachedState);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ---- createBeaconStateViewForHistoricalRegen (regen path) ----
|
|
41
|
+
|
|
42
|
+
// Reused across all historical state regen calls in the worker thread
|
|
43
|
+
const pubkeyCacheRegen = createPubkeyCache();
|
|
44
|
+
|
|
45
|
+
function syncPubkeyCache(state: BeaconStateAllForks, pubkeyCache: PubkeyCache): void {
|
|
46
|
+
const newCount = state.validators.length;
|
|
47
|
+
for (let i = pubkeyCache.size; i < newCount; i++) {
|
|
48
|
+
const pubkey = state.validators.getReadonly(i).pubkey;
|
|
49
|
+
pubkeyCache.set(i, pubkey);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
type RegenNodeJSOpts = {
|
|
54
|
+
useNative: false;
|
|
55
|
+
config: BeaconConfig;
|
|
56
|
+
stateBytes: Uint8Array;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
type RegenNativeOpts = {
|
|
60
|
+
useNative: true;
|
|
61
|
+
stateBytes: Uint8Array;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Create a BeaconStateView from raw SSZ bytes. Used in the historical state regen worker thread.
|
|
66
|
+
*
|
|
67
|
+
* Set `useNative: true` to use the native (Zig) implementation once available.
|
|
68
|
+
*/
|
|
69
|
+
export function createBeaconStateViewForHistoricalRegen(opts: RegenNodeJSOpts | RegenNativeOpts): IBeaconStateView {
|
|
70
|
+
if (opts.useNative) {
|
|
71
|
+
throw new Error("Native (Zig) BeaconStateView not yet implemented");
|
|
72
|
+
}
|
|
73
|
+
const {config, stateBytes} = opts;
|
|
74
|
+
const state = getStateTypeFromBytes(config, stateBytes).deserializeToViewDU(stateBytes);
|
|
75
|
+
syncPubkeyCache(state, pubkeyCacheRegen);
|
|
76
|
+
const cachedState = createCachedBeaconState(state, {config, pubkeyCache: pubkeyCacheRegen}, {skipSyncPubkeys: true});
|
|
77
|
+
return new BeaconStateView(cachedState);
|
|
78
|
+
}
|
package/src/testUtils/cache.ts
CHANGED
|
@@ -5,4 +5,4 @@ import {fileURLToPath} from "node:url";
|
|
|
5
5
|
// Solutions: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules
|
|
6
6
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
7
|
|
|
8
|
-
export const testCachePath = path.join(__dirname, "../../test
|
|
8
|
+
export const testCachePath = path.join(__dirname, "../../test-cache");
|