Skip to content

Commit b8a1fd7

Browse files
committed
feat: align BeaconStateView to IBeaconStateView
1 parent 1bcb36f commit b8a1fd7

8 files changed

Lines changed: 597 additions & 124 deletions

File tree

bindings/napi/BeaconStateView.zig

Lines changed: 461 additions & 85 deletions
Large diffs are not rendered by default.

bindings/napi/js_types.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ pub const Validator = js.Object(struct {
5656
});
5757

5858
pub const ProposerRewards = js.Object(struct {
59-
attestations: js.BigInt,
60-
syncAggregate: js.BigInt,
61-
slashing: js.BigInt,
59+
attestations: js.Number,
60+
syncAggregate: js.Number,
61+
slashing: js.Number,
6262
});
6363

6464
pub const MultiProof = js.Object(struct {

bindings/napi/root.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,6 @@ fn register(env: napi.Env, exports: napi.Value) !void {
5252
}
5353

5454
comptime {
55+
@setEvalBranchQuota(1_000_000);
5556
js.exportModule(@This(), .{ .init = init, .cleanup = cleanup, .register = register });
5657
}

bindings/napi/stateTransition.zig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ else
2222
/// - dontTransferCache: bool (negated to set transfer_cache)
2323
///
2424
/// This is the double negative version to conform with production lodestar.
25-
/// TODO(bing): Eventually rename this to `transferCache` to avoid double negation because its confusing naming.
26-
/// TODO(bing): Other fields (executionPayloadStatus, ..).
27-
fn parseOptions(options: ?js.Value) !st.TransitionOpt {
28-
var transition_opts: st.TransitionOpt = .{};
25+
/// TODO(bing): Eventually rename `dontTransferCache` to `transferCache` to avoid double negation because its confusing naming.
26+
fn parseOptions(options: ?js.Value) !st.TransitionOpts {
27+
var transition_opts: st.TransitionOpts = .{};
28+
2929
if (options) |value| {
3030
const raw = value.toValue();
3131
if (try raw.typeof() == .object) {

bindings/src/index.d.ts

Lines changed: 125 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,17 @@ interface Fork {
4343
epoch: number;
4444
}
4545

46+
enum ForkName {
47+
phase0 = "phase0",
48+
altair = "altair",
49+
bellatrix = "bellatrix",
50+
capella = "capella",
51+
deneb = "deneb",
52+
electra = "electra",
53+
fulu = "fulu",
54+
gloas = "gloas",
55+
}
56+
4657
interface SyncCommittee {
4758
pubkeys: Uint8Array;
4859
aggregatePubkey: Uint8Array;
@@ -54,7 +65,8 @@ interface ProcessSlotsOpts {
5465
}
5566

5667
interface CompactMultiProof {
57-
type: "compactMulti";
68+
// biome-ignore lint/suspicious/noExplicitAny: native returns string literal "compactMulti", IBeaconStateView uses @chainsafe/persistent-merkle-tree's ProofType enum nominally
69+
type: any;
5870
leaves: Uint8Array[];
5971
descriptor: Uint8Array;
6072
}
@@ -74,20 +86,27 @@ interface TransitionOpts {
7486
verifySignatures?: boolean;
7587
/** Default: false (cache is transferred). Set to true to opt out of cache transfer. */
7688
dontTransferCache?: boolean;
77-
/** Other fields (executionPayloadStatus, dataAvailabilityStatus, metrics, validatorMonitor, …) */
78-
[extra: string]: unknown;
7989
}
8090

8191
interface ProposerRewards {
82-
attestations: bigint;
83-
syncAggregate: bigint;
84-
slashing: bigint;
92+
attestations: number;
93+
syncAggregate: number;
94+
slashing: number;
8595
}
8696

8797
interface SyncCommitteeCache {
8898
validatorIndices: number[];
8999
}
90100

101+
interface EpochShuffling {
102+
epoch: number;
103+
activeIndices: Uint32Array;
104+
shuffling: Uint32Array;
105+
/** committees[slotInEpoch][committeeIndex] -> validator indices */
106+
committees: Uint32Array[][];
107+
committeesPerSlot: number;
108+
}
109+
91110
interface HistoricalSummary {
92111
blockSummaryRoot: Uint8Array;
93112
stateSummaryRoot: Uint8Array;
@@ -134,6 +153,7 @@ declare class BeaconStateView {
134153

135154
slot: number;
136155
fork: Fork;
156+
forkName: ForkName;
137157
epoch: number;
138158
genesisTime: number;
139159
genesisValidatorsRoot: Uint8Array;
@@ -142,11 +162,17 @@ declare class BeaconStateView {
142162
previousJustifiedCheckpoint: Checkpoint;
143163
currentJustifiedCheckpoint: Checkpoint;
144164
finalizedCheckpoint: Checkpoint;
145-
getBlockRoot(slot: number): Uint8Array;
165+
getBlockRoot(epoch: number): Uint8Array;
166+
getBlockRootAtSlot(slot: number): Uint8Array;
167+
getBlockRootAtEpoch(epoch: number): Uint8Array;
168+
getStateRootAtSlot(slot: number): Uint8Array;
146169
getRandaoMix(epoch: number): Uint8Array;
147-
previousEpochParticipation: number[];
148-
currentEpochParticipation: number[];
170+
previousEpochParticipation: Uint8Array;
171+
currentEpochParticipation: Uint8Array;
172+
getPreviousEpochParticipation(index: number): number;
173+
getCurrentEpochParticipation(index: number): number;
149174
latestExecutionPayloadHeader: ExecutionPayloadHeader;
175+
payloadBlockNumber: number;
150176
historicalSummaries: HistoricalSummary[];
151177
pendingDeposits: Uint8Array;
152178
pendingDepositsCount: number;
@@ -157,12 +183,35 @@ declare class BeaconStateView {
157183
proposerLookahead: Uint32Array;
158184
// executionPayloadAvailability: boolean[];
159185

160-
// getShufflingAtEpoch(epoch: number): EpochShuffling;
161-
previousDecisionRoot: Uint8Array;
162-
currentDecisionRoot: Uint8Array;
163-
nextDecisionRoot: Uint8Array;
164-
// TODO wrong return type
165-
getShufflingDecisionRoot(epoch: number): Uint8Array;
186+
// Gloas-only — throw "not available before Gloas" when called pre-Gloas.
187+
latestBlockHash: Uint8Array;
188+
// TODO(bing): type this once we support gloas
189+
// biome-ignore lint/suspicious/noExplicitAny: gloas stub
190+
executionPayloadAvailability: any;
191+
// TODO(bing): type this once we support gloas
192+
// biome-ignore lint/suspicious/noExplicitAny: gloas stub
193+
latestExecutionPayloadBid: any;
194+
// TODO(bing): type this once we support gloas
195+
// biome-ignore lint/suspicious/noExplicitAny: gloas stub
196+
payloadExpectedWithdrawals: any[];
197+
// TODO(bing): type this once we support gloas
198+
// biome-ignore lint/suspicious/noExplicitAny: gloas stub
199+
getBuilder(index: number): any;
200+
canBuilderCoverBid(builderIndex: number, bidAmount: number): boolean;
201+
getEpochPTCs(epoch: number): Uint32Array[];
202+
getIndexInPayloadTimelinessCommittee(validatorIndex: number, slot: number): number;
203+
// TODO(bing): type this once we support gloas
204+
// biome-ignore lint/suspicious/noExplicitAny: gloas stub
205+
getExpectedWithdrawalsForFullParent(executionRequests: any): any[];
206+
207+
getShufflingAtEpoch(epoch: number): EpochShuffling;
208+
getPreviousShuffling(): EpochShuffling;
209+
getCurrentShuffling(): EpochShuffling;
210+
getNextShuffling(): EpochShuffling;
211+
previousDecisionRoot: string;
212+
currentDecisionRoot: string;
213+
nextDecisionRoot: string;
214+
getShufflingDecisionRoot(epoch: number): string;
166215
previousProposers: number[] | null;
167216
currentProposers: number[];
168217
nextProposers: number[];
@@ -172,58 +221,103 @@ declare class BeaconStateView {
172221
currentSyncCommitteeIndexed: SyncCommitteeCache;
173222
syncProposerReward: number;
174223
getIndexedSyncCommitteeAtEpoch(epoch: number): SyncCommitteeCache;
224+
getIndexedSyncCommittee(slot: number): SyncCommitteeCache;
175225

176226
effectiveBalanceIncrements: Uint16Array;
177227
getEffectiveBalanceIncrementsZeroInactive(): Uint16Array;
178-
getBalance(index: number): bigint;
228+
getBalance(index: number): number;
179229
getValidator(index: number): Validator;
230+
getAllValidators(): Validator[];
231+
getAllBalances(): number[];
232+
getValidatorsByStatus(statuses: Set<string>, currentEpoch: number): Validator[];
180233
// TODO wrong function
181234
getValidatorStatus(index: number): ValidatorStatus;
182235
validatorCount: number;
183236
activeValidatorCount: number;
184237

185238
isExecutionStateType: boolean;
186239
isMergeTransitionComplete: boolean;
187-
// TODO remove
188-
isExecutionEnabled(fork: string, signedBlockBytes: Uint8Array): boolean;
240+
/** True iff state is pre-merge AND the given block carries a non-default execution payload. Bellatrix-only. */
241+
isMergeTransitionBlock(signedBlockBytes: Uint8Array): boolean;
242+
/**
243+
* Spec: `is_execution_enabled(state, body) = is_merge_transition_complete(state) or is_merge_transition_block(state, body)`.
244+
* Fast path for post-merge states (no SSZ work); deserializes only on the rare pre-merge bellatrix path.
245+
*/
246+
isExecutionEnabled(signedBlockBytes: Uint8Array): boolean;
189247

190248
// getExpectedWithdrawals(): ExpectedWithdrawals;
191249

192250
proposerRewards: ProposerRewards;
193-
// computeBlockRewards(block: BeaconBlock, proposerRewards: RewardsCache): BlockRewards;
194-
// computeAttestationRewards(validatorIds?: (number | string)[]): AttestationRewards;
195-
// computeSyncCommitteeRewards(block: BeaconBlock, validatorIds?: (number | string)[]): SyncCommitteeRewards;
196-
// getLatestWeakSubjectivityCheckpointEpoch(): number;
251+
// biome-ignore lint/suspicious/noExplicitAny: stub
252+
// TODO(bing): This is stubbed and untyped until we implement the beacon node rewards endpoints
253+
computeBlockRewards(block: any, proposerRewards?: any): Promise<any>;
254+
// biome-ignore lint/suspicious/noExplicitAny: stub
255+
// TODO(bing): This is stubbed and untyped until we implement the beacon node rewards endpoints
256+
computeAttestationsRewards(validatorIds?: (number | string)[]): Promise<any>;
257+
// TODO(bing): This is stubbed and untyped until we implement the beacon node rewards endpoints
258+
// biome-ignore lint/suspicious/noExplicitAny: stub
259+
computeSyncCommitteeRewards(block: any, validatorIds: (number | string)[]): Promise<any>;
260+
getLatestWeakSubjectivityCheckpointEpoch(): number;
197261

198-
getVoluntaryExitValidity(signedVoluntaryExitBytes: Uint8Array, verifySignature: boolean): VoluntaryExitValidity;
199-
isValidVoluntaryExit(signedVoluntaryExitBytes: Uint8Array, verifySignature: boolean): boolean;
262+
/**
263+
* Native walks the JS `phase0.SignedVoluntaryExit` shape directly.
264+
* Return is the string union `VoluntaryExitValidity` at runtime, but lodestar's
265+
* matching TS enum is nominally typed — `any` to satisfy structural conformance.
266+
*/
267+
// biome-ignore lint/suspicious/noExplicitAny: TS-nominal-enum mismatch (runtime values match exactly)
268+
getVoluntaryExitValidity(
269+
signedVoluntaryExit: {message: {epoch: number; validatorIndex: number}; signature: Uint8Array},
270+
verifySignature: boolean
271+
): any;
272+
isValidVoluntaryExit(
273+
signedVoluntaryExit: {message: {epoch: number; validatorIndex: number}; signature: Uint8Array},
274+
verifySignature: boolean
275+
): boolean;
200276

201277
getFinalizedRootProof(): Uint8Array[];
202-
// getSyncCommitteesWitness(): SyncCommitteeWitness;
203-
getSingleProof(gindex: number): Uint8Array[];
278+
// biome-ignore lint/suspicious/noExplicitAny: stub
279+
getSyncCommitteesWitness(): any;
280+
// biome-ignore lint/suspicious/noExplicitAny: stub
281+
getExpectedWithdrawals(): any;
282+
// biome-ignore lint/suspicious/noExplicitAny: native takes number, IBeaconStateView declares bigint
283+
getSingleProof(gindex: any): Uint8Array[];
204284
// createMultiProof(descriptor: Uint8Array): CompactMultiProof;
205285

206286
computeUnrealizedCheckpoints(): {
207287
justifiedCheckpoint: Checkpoint;
208288
finalizedCheckpoint: Checkpoint;
209289
};
290+
computeAnchorCheckpoint(): {
291+
checkpoint: Checkpoint;
292+
blockHeader: BeaconBlockHeader;
293+
};
210294

211295
clonedCount: number;
212296
clonedCountWithTransferCache: number;
213297
createdWithTransferCache: boolean;
214-
// isStateValidatorsNodesPopulated(): boolean;
298+
isStateValidatorsNodesPopulated(): boolean;
215299

216-
// loadOtherState(stateBytes: Uint8Array, seedValidatorsBytes?: Uint8Array): void;
300+
// biome-ignore lint/suspicious/noExplicitAny: stub
301+
loadOtherState(
302+
stateBytes: Uint8Array,
303+
seedValidatorsBytes?: Uint8Array,
304+
opts?: {preloadValidatorsAndBalances?: boolean}
305+
): any;
306+
// biome-ignore lint/suspicious/noExplicitAny: stub
307+
toValue(): any;
217308
serialize(): Uint8Array;
218309
serializedSize(): number;
219-
serializeToBytes(output: Uint8Array, offset: number): number;
310+
/** Takes a `@chainsafe/ssz` ByteViews `{uint8Array, dataView}`; native uses `uint8Array` only. */
311+
serializeToBytes(output: {uint8Array: Uint8Array; dataView: DataView}, offset: number): number;
220312
serializeValidators(): Uint8Array;
221313
serializedValidatorsSize(): number;
222-
serializeValidatorsToBytes(output: Uint8Array, offset: number): number;
314+
/** Same shape as `serializeToBytes`. */
315+
serializeValidatorsToBytes(output: {uint8Array: Uint8Array; dataView: DataView}, offset: number): number;
223316
hashTreeRoot(): Uint8Array;
224317
createMultiProof(descriptor: Uint8Array): CompactMultiProof;
225318

226-
// stateTransition(signedBlockBytes: Uint8Array): BeaconStateView;
319+
// biome-ignore lint/suspicious/noExplicitAny: signed block bytes are passed as Uint8Array at runtime; signature is loosened so it satisfies `IBeaconStateView.stateTransition(block, opts, modules)` structurally.
320+
stateTransition(signedBlock: any, options?: any, modules?: any): BeaconStateView;
227321
processSlots(slot: number, options?: ProcessSlotsOpts): BeaconStateView;
228322
}
229323

build.zig.zon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@
307307
.config,
308308
.fork_types,
309309
.state_transition,
310+
.hex,
310311
"zapi:zapi",
311312
},
312313
},

src/state_transition/root.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ pub const AnchorCheckpoint = @import("./AnchorCheckpoint.zig");
8787
pub const deinitStateTransition = @import("./state_transition.zig").deinitStateTransition;
8888
pub const isExecutionEnabled = @import("./utils/execution.zig").isExecutionEnabled;
8989
pub const isMergeTransitionComplete = @import("./utils/execution.zig").isMergeTransitionComplete;
90+
pub const isMergeTransitionBlock = @import("./utils/execution.zig").isMergeTransitionBlock;
9091
pub const getRandaoMix = @import("./utils/seed.zig").getRandaoMix;
9192
pub const getEffectiveBalanceIncrementsZeroInactive = @import("./utils/balance.zig").getEffectiveBalanceIncrementsZeroInactive;
9293

src/state_transition/utils/execution.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub fn isMergeTransitionBlock(
2626
comptime fork: ForkSeq,
2727
state: *BeaconState(fork),
2828
comptime block_type: BlockType,
29-
body: *const BeaconBlockBody(fork, block_type),
29+
body: *const BeaconBlockBody(block_type, fork),
3030
) bool {
3131
if (comptime fork != .bellatrix) {
3232
return false;

0 commit comments

Comments
 (0)