Skip to content

Commit 5ccae1c

Browse files
authored
feat: add finalized metadata field to HTTP API responses (#6645)
* feat: add finalized metadata field to HTTP API responses * Clean up getState type casts * Fix finalized when getting block root * Add comment for block from hot db * Fix case where slot equals finalized block slot * Calculate epoch from unmodded slot
1 parent 4773dd2 commit 5ccae1c

File tree

25 files changed

+326
-165
lines changed

25 files changed

+326
-165
lines changed

packages/api/src/beacon/routes/beacon/block.ts

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
ContainerDataExecutionOptimistic,
1717
WithExecutionOptimistic,
1818
ContainerData,
19+
WithFinalized,
1920
} from "../../../utils/index.js";
2021
import {HttpStatusCode} from "../../../utils/client/httpStatusCode.js";
2122
import {parseAcceptHeader, writeAcceptHeader} from "../../../utils/acceptHeader.js";
@@ -32,6 +33,11 @@ export type BlockId = RootHex | Slot | "head" | "genesis" | "finalized";
3233
*/
3334
export type ExecutionOptimistic = boolean;
3435

36+
/**
37+
* True if the response references the finalized history of the chain, as determined by fork choice.
38+
*/
39+
export type Finalized = boolean;
40+
3541
export type BlockHeaderResponse = {
3642
root: Root;
3743
canonical: boolean;
@@ -66,6 +72,7 @@ export type BlockV2Response<T extends ResponseFormat = "json"> = T extends "ssz"
6672
[HttpStatusCode.OK]: {
6773
data: allForks.SignedBeaconBlock;
6874
executionOptimistic: ExecutionOptimistic;
75+
finalized: Finalized;
6976
version: ForkName;
7077
};
7178
},
@@ -103,6 +110,7 @@ export type Api = {
103110
[HttpStatusCode.OK]: {
104111
data: phase0.Attestation[];
105112
executionOptimistic: ExecutionOptimistic;
113+
finalized: Finalized;
106114
};
107115
},
108116
HttpStatusCode.BAD_REQUEST | HttpStatusCode.NOT_FOUND
@@ -121,6 +129,7 @@ export type Api = {
121129
[HttpStatusCode.OK]: {
122130
data: BlockHeaderResponse;
123131
executionOptimistic: ExecutionOptimistic;
132+
finalized: Finalized;
124133
};
125134
},
126135
HttpStatusCode.BAD_REQUEST | HttpStatusCode.NOT_FOUND
@@ -139,6 +148,7 @@ export type Api = {
139148
[HttpStatusCode.OK]: {
140149
data: BlockHeaderResponse[];
141150
executionOptimistic: ExecutionOptimistic;
151+
finalized: Finalized;
142152
};
143153
},
144154
HttpStatusCode.BAD_REQUEST
@@ -157,6 +167,7 @@ export type Api = {
157167
[HttpStatusCode.OK]: {
158168
data: {root: Root};
159169
executionOptimistic: ExecutionOptimistic;
170+
finalized: Finalized;
160171
};
161172
},
162173
HttpStatusCode.BAD_REQUEST | HttpStatusCode.NOT_FOUND
@@ -236,7 +247,11 @@ export type Api = {
236247
indices?: number[]
237248
): Promise<
238249
ApiClientResponse<{
239-
[HttpStatusCode.OK]: {executionOptimistic: ExecutionOptimistic; data: deneb.BlobSidecars};
250+
[HttpStatusCode.OK]: {
251+
data: deneb.BlobSidecars;
252+
executionOptimistic: ExecutionOptimistic;
253+
finalized: Finalized;
254+
};
240255
}>
241256
>;
242257
};
@@ -395,11 +410,11 @@ export function getReturnTypes(): ReturnTypes<Api> {
395410

396411
return {
397412
getBlock: ContainerData(ssz.phase0.SignedBeaconBlock),
398-
getBlockV2: WithExecutionOptimistic(WithVersion((fork) => ssz[fork].SignedBeaconBlock)),
399-
getBlockAttestations: ContainerDataExecutionOptimistic(ArrayOf(ssz.phase0.Attestation)),
400-
getBlockHeader: ContainerDataExecutionOptimistic(BeaconHeaderResType),
401-
getBlockHeaders: ContainerDataExecutionOptimistic(ArrayOf(BeaconHeaderResType)),
402-
getBlockRoot: ContainerDataExecutionOptimistic(RootContainer),
403-
getBlobSidecars: ContainerDataExecutionOptimistic(ssz.deneb.BlobSidecars),
413+
getBlockV2: WithFinalized(WithExecutionOptimistic(WithVersion((fork) => ssz[fork].SignedBeaconBlock))),
414+
getBlockAttestations: WithFinalized(ContainerDataExecutionOptimistic(ArrayOf(ssz.phase0.Attestation))),
415+
getBlockHeader: WithFinalized(ContainerDataExecutionOptimistic(BeaconHeaderResType)),
416+
getBlockHeaders: WithFinalized(ContainerDataExecutionOptimistic(ArrayOf(BeaconHeaderResType))),
417+
getBlockRoot: WithFinalized(ContainerDataExecutionOptimistic(RootContainer)),
418+
getBlobSidecars: WithFinalized(ContainerDataExecutionOptimistic(ssz.deneb.BlobSidecars)),
404419
};
405420
}

packages/api/src/beacon/routes/beacon/rewards.ts

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
ReqSerializers,
99
ContainerDataExecutionOptimistic,
1010
ArrayOf,
11+
WithFinalized,
1112
} from "../../../utils/index.js";
1213
import {HttpStatusCode} from "../../../utils/client/httpStatusCode.js";
1314
import {ApiClientResponse} from "../../../interfaces.js";
@@ -22,6 +23,11 @@ import {ValidatorId} from "./state.js";
2223
*/
2324
export type ExecutionOptimistic = boolean;
2425

26+
/**
27+
* True if the response references the finalized history of the chain, as determined by fork choice.
28+
*/
29+
export type Finalized = boolean;
30+
2531
/**
2632
* Rewards info for a single block. Every reward value is in Gwei.
2733
*/
@@ -88,11 +94,15 @@ export type Api = {
8894
* @param blockId Block identifier.
8995
* Can be one of: "head" (canonical head in node's view), "genesis", "finalized", \<slot\>, \<hex encoded blockRoot with 0x prefix\>.
9096
*/
91-
getBlockRewards(
92-
blockId: BlockId
93-
): Promise<
97+
getBlockRewards(blockId: BlockId): Promise<
9498
ApiClientResponse<
95-
{[HttpStatusCode.OK]: {data: BlockRewards; executionOptimistic: ExecutionOptimistic}},
99+
{
100+
[HttpStatusCode.OK]: {
101+
data: BlockRewards;
102+
executionOptimistic: ExecutionOptimistic;
103+
finalized: Finalized;
104+
};
105+
},
96106
HttpStatusCode.BAD_REQUEST | HttpStatusCode.NOT_FOUND
97107
>
98108
>;
@@ -108,7 +118,13 @@ export type Api = {
108118
validatorIds?: ValidatorId[]
109119
): Promise<
110120
ApiClientResponse<
111-
{[HttpStatusCode.OK]: {data: AttestationsRewards; executionOptimistic: ExecutionOptimistic}},
121+
{
122+
[HttpStatusCode.OK]: {
123+
data: AttestationsRewards;
124+
executionOptimistic: ExecutionOptimistic;
125+
finalized: Finalized;
126+
};
127+
},
112128
HttpStatusCode.BAD_REQUEST | HttpStatusCode.NOT_FOUND
113129
>
114130
>;
@@ -126,7 +142,13 @@ export type Api = {
126142
validatorIds?: ValidatorId[]
127143
): Promise<
128144
ApiClientResponse<
129-
{[HttpStatusCode.OK]: {data: SyncCommitteeRewards; executionOptimistic: ExecutionOptimistic}},
145+
{
146+
[HttpStatusCode.OK]: {
147+
data: SyncCommitteeRewards;
148+
executionOptimistic: ExecutionOptimistic;
149+
finalized: Finalized;
150+
};
151+
},
130152
HttpStatusCode.BAD_REQUEST | HttpStatusCode.NOT_FOUND
131153
>
132154
>;
@@ -228,8 +250,8 @@ export function getReturnTypes(): ReturnTypes<Api> {
228250
);
229251

230252
return {
231-
getBlockRewards: ContainerDataExecutionOptimistic(BlockRewardsResponse),
232-
getAttestationsRewards: ContainerDataExecutionOptimistic(AttestationsRewardsResponse),
233-
getSyncCommitteeRewards: ContainerDataExecutionOptimistic(ArrayOf(SyncCommitteeRewardsResponse)),
253+
getBlockRewards: WithFinalized(ContainerDataExecutionOptimistic(BlockRewardsResponse)),
254+
getAttestationsRewards: WithFinalized(ContainerDataExecutionOptimistic(AttestationsRewardsResponse)),
255+
getSyncCommitteeRewards: WithFinalized(ContainerDataExecutionOptimistic(ArrayOf(SyncCommitteeRewardsResponse))),
234256
};
235257
}

packages/api/src/beacon/routes/beacon/state.ts

Lines changed: 81 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
Schema,
1111
ReqSerializers,
1212
ReqSerializer,
13+
WithFinalized,
1314
} from "../../../utils/index.js";
1415

1516
// See /packages/api/src/routes/index.ts for reasoning and instructions to add new routes
@@ -23,6 +24,11 @@ export type ValidatorId = string | number;
2324
*/
2425
export type ExecutionOptimistic = boolean;
2526

27+
/**
28+
* True if the response references the finalized history of the chain, as determined by fork choice.
29+
*/
30+
export type Finalized = boolean;
31+
2632
export type ValidatorStatus =
2733
| "active"
2834
| "pending_initialized"
@@ -85,11 +91,15 @@ export type Api = {
8591
* @param stateId State identifier.
8692
* Can be one of: "head" (canonical head in node's view), "genesis", "finalized", "justified", \<slot\>, \<hex encoded stateRoot with 0x prefix\>.
8793
*/
88-
getStateRoot(
89-
stateId: StateId
90-
): Promise<
94+
getStateRoot(stateId: StateId): Promise<
9195
ApiClientResponse<
92-
{[HttpStatusCode.OK]: {data: {root: Root}; executionOptimistic: ExecutionOptimistic}},
96+
{
97+
[HttpStatusCode.OK]: {
98+
data: {root: Root};
99+
executionOptimistic: ExecutionOptimistic;
100+
finalized: Finalized;
101+
};
102+
},
93103
HttpStatusCode.BAD_REQUEST | HttpStatusCode.NOT_FOUND
94104
>
95105
>;
@@ -100,11 +110,15 @@ export type Api = {
100110
* @param stateId State identifier.
101111
* Can be one of: "head" (canonical head in node's view), "genesis", "finalized", "justified", \<slot\>, \<hex encoded stateRoot with 0x prefix\>.
102112
*/
103-
getStateFork(
104-
stateId: StateId
105-
): Promise<
113+
getStateFork(stateId: StateId): Promise<
106114
ApiClientResponse<
107-
{[HttpStatusCode.OK]: {data: phase0.Fork; executionOptimistic: ExecutionOptimistic}},
115+
{
116+
[HttpStatusCode.OK]: {
117+
data: phase0.Fork;
118+
executionOptimistic: ExecutionOptimistic;
119+
finalized: Finalized;
120+
};
121+
},
108122
HttpStatusCode.BAD_REQUEST | HttpStatusCode.NOT_FOUND
109123
>
110124
>;
@@ -121,7 +135,13 @@ export type Api = {
121135
epoch?: Epoch
122136
): Promise<
123137
ApiClientResponse<
124-
{[HttpStatusCode.OK]: {data: {randao: Root}; executionOptimistic: ExecutionOptimistic}},
138+
{
139+
[HttpStatusCode.OK]: {
140+
data: {randao: Root};
141+
executionOptimistic: ExecutionOptimistic;
142+
finalized: Finalized;
143+
};
144+
},
125145
HttpStatusCode.BAD_REQUEST | HttpStatusCode.NOT_FOUND
126146
>
127147
>;
@@ -133,11 +153,15 @@ export type Api = {
133153
* @param stateId State identifier.
134154
* Can be one of: "head" (canonical head in node's view), "genesis", "finalized", "justified", \<slot\>, \<hex encoded stateRoot with 0x prefix\>.
135155
*/
136-
getStateFinalityCheckpoints(
137-
stateId: StateId
138-
): Promise<
156+
getStateFinalityCheckpoints(stateId: StateId): Promise<
139157
ApiClientResponse<
140-
{[HttpStatusCode.OK]: {data: FinalityCheckpoints; executionOptimistic: ExecutionOptimistic}},
158+
{
159+
[HttpStatusCode.OK]: {
160+
data: FinalityCheckpoints;
161+
executionOptimistic: ExecutionOptimistic;
162+
finalized: Finalized;
163+
};
164+
},
141165
HttpStatusCode.BAD_REQUEST | HttpStatusCode.NOT_FOUND
142166
>
143167
>;
@@ -155,7 +179,13 @@ export type Api = {
155179
filters?: ValidatorFilters
156180
): Promise<
157181
ApiClientResponse<
158-
{[HttpStatusCode.OK]: {data: ValidatorResponse[]; executionOptimistic: ExecutionOptimistic}},
182+
{
183+
[HttpStatusCode.OK]: {
184+
data: ValidatorResponse[];
185+
executionOptimistic: ExecutionOptimistic;
186+
finalized: Finalized;
187+
};
188+
},
159189
HttpStatusCode.BAD_REQUEST | HttpStatusCode.NOT_FOUND
160190
>
161191
>;
@@ -172,7 +202,13 @@ export type Api = {
172202
validatorId: ValidatorId
173203
): Promise<
174204
ApiClientResponse<
175-
{[HttpStatusCode.OK]: {data: ValidatorResponse; executionOptimistic: ExecutionOptimistic}},
205+
{
206+
[HttpStatusCode.OK]: {
207+
data: ValidatorResponse;
208+
executionOptimistic: ExecutionOptimistic;
209+
finalized: Finalized;
210+
};
211+
},
176212
HttpStatusCode.BAD_REQUEST | HttpStatusCode.NOT_FOUND
177213
>
178214
>;
@@ -189,7 +225,13 @@ export type Api = {
189225
indices?: ValidatorId[]
190226
): Promise<
191227
ApiClientResponse<
192-
{[HttpStatusCode.OK]: {data: ValidatorBalance[]; executionOptimistic: ExecutionOptimistic}},
228+
{
229+
[HttpStatusCode.OK]: {
230+
data: ValidatorBalance[];
231+
executionOptimistic: ExecutionOptimistic;
232+
finalized: Finalized;
233+
};
234+
},
193235
HttpStatusCode.BAD_REQUEST
194236
>
195237
>;
@@ -208,7 +250,13 @@ export type Api = {
208250
filters?: CommitteesFilters
209251
): Promise<
210252
ApiClientResponse<
211-
{[HttpStatusCode.OK]: {data: EpochCommitteeResponse[]; executionOptimistic: ExecutionOptimistic}},
253+
{
254+
[HttpStatusCode.OK]: {
255+
data: EpochCommitteeResponse[];
256+
executionOptimistic: ExecutionOptimistic;
257+
finalized: Finalized;
258+
};
259+
},
212260
HttpStatusCode.BAD_REQUEST | HttpStatusCode.NOT_FOUND
213261
>
214262
>;
@@ -218,7 +266,13 @@ export type Api = {
218266
epoch?: Epoch
219267
): Promise<
220268
ApiClientResponse<
221-
{[HttpStatusCode.OK]: {data: EpochSyncCommitteeResponse; executionOptimistic: ExecutionOptimistic}},
269+
{
270+
[HttpStatusCode.OK]: {
271+
data: EpochSyncCommitteeResponse;
272+
executionOptimistic: ExecutionOptimistic;
273+
finalized: Finalized;
274+
};
275+
},
222276
HttpStatusCode.BAD_REQUEST | HttpStatusCode.NOT_FOUND
223277
>
224278
>;
@@ -376,14 +430,14 @@ export function getReturnTypes(): ReturnTypes<Api> {
376430
);
377431

378432
return {
379-
getStateRoot: ContainerDataExecutionOptimistic(RootContainer),
380-
getStateFork: ContainerDataExecutionOptimistic(ssz.phase0.Fork),
381-
getStateRandao: ContainerDataExecutionOptimistic(RandaoContainer),
382-
getStateFinalityCheckpoints: ContainerDataExecutionOptimistic(FinalityCheckpoints),
383-
getStateValidators: ContainerDataExecutionOptimistic(ArrayOf(ValidatorResponse)),
384-
getStateValidator: ContainerDataExecutionOptimistic(ValidatorResponse),
385-
getStateValidatorBalances: ContainerDataExecutionOptimistic(ArrayOf(ValidatorBalance)),
386-
getEpochCommittees: ContainerDataExecutionOptimistic(ArrayOf(EpochCommitteeResponse)),
387-
getEpochSyncCommittees: ContainerDataExecutionOptimistic(EpochSyncCommitteesResponse),
433+
getStateRoot: WithFinalized(ContainerDataExecutionOptimistic(RootContainer)),
434+
getStateFork: WithFinalized(ContainerDataExecutionOptimistic(ssz.phase0.Fork)),
435+
getStateRandao: WithFinalized(ContainerDataExecutionOptimistic(RandaoContainer)),
436+
getStateFinalityCheckpoints: WithFinalized(ContainerDataExecutionOptimistic(FinalityCheckpoints)),
437+
getStateValidators: WithFinalized(ContainerDataExecutionOptimistic(ArrayOf(ValidatorResponse))),
438+
getStateValidator: WithFinalized(ContainerDataExecutionOptimistic(ValidatorResponse)),
439+
getStateValidatorBalances: WithFinalized(ContainerDataExecutionOptimistic(ArrayOf(ValidatorBalance))),
440+
getEpochCommittees: WithFinalized(ContainerDataExecutionOptimistic(ArrayOf(EpochCommitteeResponse))),
441+
getEpochSyncCommittees: WithFinalized(ContainerDataExecutionOptimistic(EpochSyncCommitteesResponse)),
388442
};
389443
}

0 commit comments

Comments
 (0)