@lodestar/api 1.42.0-rc.0 → 1.43.0-dev.07452fe3b7
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/beacon/routes/beacon/block.d.ts +9 -0
- package/lib/beacon/routes/beacon/block.d.ts.map +1 -1
- package/lib/beacon/routes/beacon/block.js +11 -2
- package/lib/beacon/routes/beacon/block.js.map +1 -1
- package/lib/beacon/routes/beacon/pool.d.ts +45 -0
- package/lib/beacon/routes/beacon/pool.d.ts.map +1 -1
- package/lib/beacon/routes/beacon/pool.js +43 -1
- package/lib/beacon/routes/beacon/pool.js.map +1 -1
- package/lib/beacon/routes/events.d.ts +48 -8
- package/lib/beacon/routes/events.d.ts.map +1 -1
- package/lib/beacon/routes/events.js +7 -5
- package/lib/beacon/routes/events.js.map +1 -1
- package/lib/beacon/routes/lodestar.d.ts +12 -3
- package/lib/beacon/routes/lodestar.d.ts.map +1 -1
- package/lib/beacon/routes/lodestar.js +57 -3
- package/lib/beacon/routes/lodestar.js.map +1 -1
- package/lib/beacon/routes/validator.d.ts +45 -0
- package/lib/beacon/routes/validator.d.ts.map +1 -1
- package/lib/beacon/routes/validator.js +44 -1
- package/lib/beacon/routes/validator.js.map +1 -1
- package/lib/utils/types.d.ts +1 -1
- package/lib/utils/types.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/beacon/routes/beacon/block.ts +23 -2
- package/src/beacon/routes/beacon/pool.ts +76 -1
- package/src/beacon/routes/events.ts +9 -7
- package/src/beacon/routes/lodestar.ts +76 -2
- package/src/beacon/routes/validator.ts +82 -1
- package/src/utils/types.ts +4 -1
|
@@ -226,6 +226,18 @@ export type Endpoints = {
|
|
|
226
226
|
EmptyMeta
|
|
227
227
|
>;
|
|
228
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Get signed execution payload envelope.
|
|
231
|
+
* Retrieves signed execution payload envelope for a given block id.
|
|
232
|
+
*/
|
|
233
|
+
getSignedExecutionPayloadEnvelope: Endpoint<
|
|
234
|
+
"GET",
|
|
235
|
+
BlockArgs,
|
|
236
|
+
{params: {block_id: string}},
|
|
237
|
+
gloas.SignedExecutionPayloadEnvelope,
|
|
238
|
+
ExecutionOptimisticFinalizedAndVersionMeta
|
|
239
|
+
>;
|
|
240
|
+
|
|
229
241
|
/**
|
|
230
242
|
* Get block BlobSidecar
|
|
231
243
|
* Retrieves BlobSidecar included in requested block.
|
|
@@ -594,7 +606,7 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoi
|
|
|
594
606
|
method: "POST",
|
|
595
607
|
req: {
|
|
596
608
|
writeReqJson: ({signedExecutionPayloadEnvelope}) => {
|
|
597
|
-
const fork = config.getForkName(signedExecutionPayloadEnvelope.message.
|
|
609
|
+
const fork = config.getForkName(signedExecutionPayloadEnvelope.message.payload.slotNumber);
|
|
598
610
|
return {
|
|
599
611
|
body: getPostGloasForkTypes(fork).SignedExecutionPayloadEnvelope.toJson(signedExecutionPayloadEnvelope),
|
|
600
612
|
headers: {
|
|
@@ -609,7 +621,7 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoi
|
|
|
609
621
|
};
|
|
610
622
|
},
|
|
611
623
|
writeReqSsz: ({signedExecutionPayloadEnvelope}) => {
|
|
612
|
-
const fork = config.getForkName(signedExecutionPayloadEnvelope.message.
|
|
624
|
+
const fork = config.getForkName(signedExecutionPayloadEnvelope.message.payload.slotNumber);
|
|
613
625
|
return {
|
|
614
626
|
body: getPostGloasForkTypes(fork).SignedExecutionPayloadEnvelope.serialize(signedExecutionPayloadEnvelope),
|
|
615
627
|
headers: {
|
|
@@ -634,6 +646,15 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoi
|
|
|
634
646
|
requestWireFormat: WireFormat.ssz,
|
|
635
647
|
},
|
|
636
648
|
},
|
|
649
|
+
getSignedExecutionPayloadEnvelope: {
|
|
650
|
+
url: "/eth/v1/beacon/execution_payload_envelope/{block_id}",
|
|
651
|
+
method: "GET",
|
|
652
|
+
req: blockIdOnlyReq,
|
|
653
|
+
resp: {
|
|
654
|
+
data: WithVersion((fork) => getPostGloasForkTypes(fork).SignedExecutionPayloadEnvelope),
|
|
655
|
+
meta: ExecutionOptimisticFinalizedAndVersionCodec,
|
|
656
|
+
},
|
|
657
|
+
},
|
|
637
658
|
getBlobSidecars: {
|
|
638
659
|
url: "/eth/v1/beacon/blob_sidecars/{block_id}",
|
|
639
660
|
method: "GET",
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import {ValueOf} from "@chainsafe/ssz";
|
|
2
2
|
import {ChainForkConfig} from "@lodestar/config";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
ForkName,
|
|
5
|
+
ForkPostElectra,
|
|
6
|
+
ForkPreElectra,
|
|
7
|
+
MAX_PAYLOAD_ATTESTATIONS,
|
|
8
|
+
PTC_SIZE,
|
|
9
|
+
isForkPostElectra,
|
|
10
|
+
} from "@lodestar/params";
|
|
4
11
|
import {
|
|
5
12
|
ArrayOf,
|
|
6
13
|
AttesterSlashing,
|
|
@@ -37,6 +44,8 @@ const ProposerSlashingListType = ArrayOf(ssz.phase0.ProposerSlashing);
|
|
|
37
44
|
const SignedVoluntaryExitListType = ArrayOf(ssz.phase0.SignedVoluntaryExit);
|
|
38
45
|
const SignedBLSToExecutionChangeListType = ArrayOf(ssz.capella.SignedBLSToExecutionChange);
|
|
39
46
|
const SyncCommitteeMessageListType = ArrayOf(ssz.altair.SyncCommitteeMessage);
|
|
47
|
+
const PayloadAttestationListType = ArrayOf(ssz.gloas.PayloadAttestation, MAX_PAYLOAD_ATTESTATIONS);
|
|
48
|
+
const PayloadAttestationMessageListType = ArrayOf(ssz.gloas.PayloadAttestationMessage, PTC_SIZE);
|
|
40
49
|
|
|
41
50
|
type AttestationListPhase0 = ValueOf<typeof AttestationListTypePhase0>;
|
|
42
51
|
type AttestationListElectra = ValueOf<typeof AttestationListTypeElectra>;
|
|
@@ -50,6 +59,8 @@ type ProposerSlashingList = ValueOf<typeof ProposerSlashingListType>;
|
|
|
50
59
|
type SignedVoluntaryExitList = ValueOf<typeof SignedVoluntaryExitListType>;
|
|
51
60
|
type SignedBLSToExecutionChangeList = ValueOf<typeof SignedBLSToExecutionChangeListType>;
|
|
52
61
|
type SyncCommitteeMessageList = ValueOf<typeof SyncCommitteeMessageListType>;
|
|
62
|
+
type PayloadAttestationList = ValueOf<typeof PayloadAttestationListType>;
|
|
63
|
+
type PayloadAttestationMessageList = ValueOf<typeof PayloadAttestationMessageListType>;
|
|
53
64
|
|
|
54
65
|
export type Endpoints = {
|
|
55
66
|
/**
|
|
@@ -76,6 +87,18 @@ export type Endpoints = {
|
|
|
76
87
|
VersionMeta
|
|
77
88
|
>;
|
|
78
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Get payload attestations from operations pool
|
|
92
|
+
* Retrieves payload attestations known by the node but not necessarily incorporated into any block.
|
|
93
|
+
*/
|
|
94
|
+
getPoolPayloadAttestations: Endpoint<
|
|
95
|
+
"GET",
|
|
96
|
+
{slot?: Slot},
|
|
97
|
+
{query: {slot?: number}},
|
|
98
|
+
PayloadAttestationList,
|
|
99
|
+
VersionMeta
|
|
100
|
+
>;
|
|
101
|
+
|
|
79
102
|
/**
|
|
80
103
|
* Get AttesterSlashings from operations pool
|
|
81
104
|
* Retrieves attester slashings known by the node but not necessarily incorporated into any block
|
|
@@ -244,6 +267,18 @@ export type Endpoints = {
|
|
|
244
267
|
EmptyResponseData,
|
|
245
268
|
EmptyMeta
|
|
246
269
|
>;
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Submit payload attestation messages
|
|
273
|
+
* Submits payload attestation messages to the beacon node.
|
|
274
|
+
*/
|
|
275
|
+
submitPayloadAttestationMessages: Endpoint<
|
|
276
|
+
"POST",
|
|
277
|
+
{payloadAttestationMessages: PayloadAttestationMessageList},
|
|
278
|
+
{body: unknown; headers: {[MetaHeader.Version]: string}},
|
|
279
|
+
EmptyResponseData,
|
|
280
|
+
EmptyMeta
|
|
281
|
+
>;
|
|
247
282
|
};
|
|
248
283
|
|
|
249
284
|
export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoints> {
|
|
@@ -274,6 +309,19 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoi
|
|
|
274
309
|
meta: VersionCodec,
|
|
275
310
|
},
|
|
276
311
|
},
|
|
312
|
+
getPoolPayloadAttestations: {
|
|
313
|
+
url: "/eth/v1/beacon/pool/payload_attestations",
|
|
314
|
+
method: "GET",
|
|
315
|
+
req: {
|
|
316
|
+
writeReq: ({slot}) => ({query: {slot}}),
|
|
317
|
+
parseReq: ({query}) => ({slot: query.slot}),
|
|
318
|
+
schema: {query: {slot: Schema.Uint}},
|
|
319
|
+
},
|
|
320
|
+
resp: {
|
|
321
|
+
data: PayloadAttestationListType,
|
|
322
|
+
meta: VersionCodec,
|
|
323
|
+
},
|
|
324
|
+
},
|
|
277
325
|
getPoolAttesterSlashings: {
|
|
278
326
|
url: "/eth/v1/beacon/pool/attester_slashings",
|
|
279
327
|
method: "GET",
|
|
@@ -499,5 +547,32 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoi
|
|
|
499
547
|
},
|
|
500
548
|
resp: EmptyResponseCodec,
|
|
501
549
|
},
|
|
550
|
+
submitPayloadAttestationMessages: {
|
|
551
|
+
url: "/eth/v1/beacon/pool/payload_attestations",
|
|
552
|
+
method: "POST",
|
|
553
|
+
req: {
|
|
554
|
+
writeReqJson: ({payloadAttestationMessages}) => ({
|
|
555
|
+
body: PayloadAttestationMessageListType.toJson(payloadAttestationMessages),
|
|
556
|
+
headers: {[MetaHeader.Version]: ForkName.gloas},
|
|
557
|
+
}),
|
|
558
|
+
parseReqJson: ({body, headers}) => {
|
|
559
|
+
toForkName(fromHeaders(headers, MetaHeader.Version));
|
|
560
|
+
return {payloadAttestationMessages: PayloadAttestationMessageListType.fromJson(body)};
|
|
561
|
+
},
|
|
562
|
+
writeReqSsz: ({payloadAttestationMessages}) => ({
|
|
563
|
+
body: PayloadAttestationMessageListType.serialize(payloadAttestationMessages),
|
|
564
|
+
headers: {[MetaHeader.Version]: ForkName.gloas},
|
|
565
|
+
}),
|
|
566
|
+
parseReqSsz: ({body, headers}) => {
|
|
567
|
+
toForkName(fromHeaders(headers, MetaHeader.Version));
|
|
568
|
+
return {payloadAttestationMessages: PayloadAttestationMessageListType.deserialize(body)};
|
|
569
|
+
},
|
|
570
|
+
schema: {
|
|
571
|
+
body: Schema.ObjectArray,
|
|
572
|
+
headers: {[MetaHeader.Version]: Schema.String},
|
|
573
|
+
},
|
|
574
|
+
},
|
|
575
|
+
resp: EmptyResponseCodec,
|
|
576
|
+
},
|
|
502
577
|
};
|
|
503
578
|
}
|
|
@@ -16,12 +16,13 @@ import {
|
|
|
16
16
|
altair,
|
|
17
17
|
capella,
|
|
18
18
|
electra,
|
|
19
|
+
gloas,
|
|
19
20
|
phase0,
|
|
20
21
|
ssz,
|
|
21
22
|
sszTypesFor,
|
|
22
23
|
} from "@lodestar/types";
|
|
23
24
|
import {EmptyMeta, EmptyResponseCodec, EmptyResponseData} from "../../utils/codecs.js";
|
|
24
|
-
import {getPostAltairForkTypes, getPostBellatrixForkTypes} from "../../utils/fork.js";
|
|
25
|
+
import {getPostAltairForkTypes, getPostBellatrixForkTypes, getPostGloasForkTypes} from "../../utils/fork.js";
|
|
25
26
|
import {Endpoint, RouteDefinitions, Schema} from "../../utils/index.js";
|
|
26
27
|
import {VersionType} from "../../utils/metadata.js";
|
|
27
28
|
|
|
@@ -99,12 +100,14 @@ export enum EventType {
|
|
|
99
100
|
blobSidecar = "blob_sidecar",
|
|
100
101
|
/** The node has received a valid DataColumnSidecar (from P2P or API) */
|
|
101
102
|
dataColumnSidecar = "data_column_sidecar",
|
|
102
|
-
/** The node has received
|
|
103
|
+
/** The node has received a `SignedExecutionPayloadEnvelope` (from P2P or API) that is successfully imported on the fork-choice `on_execution_payload` handler */
|
|
103
104
|
executionPayload = "execution_payload",
|
|
104
|
-
/** The node has received
|
|
105
|
+
/** The node has received a `SignedExecutionPayloadEnvelope` (from P2P or API) that passes validation rules of the `execution_payload` topic */
|
|
105
106
|
executionPayloadGossip = "execution_payload_gossip",
|
|
106
107
|
/** The node has verified that the execution payload and blobs for a block are available and ready for payload attestation */
|
|
107
108
|
executionPayloadAvailable = "execution_payload_available",
|
|
109
|
+
/** The node has received a `SignedExecutionPayloadBid` (from P2P or API) that passes gossip validation on the `execution_payload_bid` topic */
|
|
110
|
+
executionPayloadBid = "execution_payload_bid",
|
|
108
111
|
}
|
|
109
112
|
|
|
110
113
|
export const eventTypes: {[K in EventType]: K} = {
|
|
@@ -128,6 +131,7 @@ export const eventTypes: {[K in EventType]: K} = {
|
|
|
128
131
|
[EventType.executionPayload]: EventType.executionPayload,
|
|
129
132
|
[EventType.executionPayloadGossip]: EventType.executionPayloadGossip,
|
|
130
133
|
[EventType.executionPayloadAvailable]: EventType.executionPayloadAvailable,
|
|
134
|
+
[EventType.executionPayloadBid]: EventType.executionPayloadBid,
|
|
131
135
|
};
|
|
132
136
|
|
|
133
137
|
export type EventData = {
|
|
@@ -182,7 +186,6 @@ export type EventData = {
|
|
|
182
186
|
builderIndex: BuilderIndex;
|
|
183
187
|
blockHash: RootHex;
|
|
184
188
|
blockRoot: RootHex;
|
|
185
|
-
stateRoot: RootHex;
|
|
186
189
|
executionOptimistic: boolean;
|
|
187
190
|
};
|
|
188
191
|
[EventType.executionPayloadGossip]: {
|
|
@@ -190,12 +193,12 @@ export type EventData = {
|
|
|
190
193
|
builderIndex: BuilderIndex;
|
|
191
194
|
blockHash: RootHex;
|
|
192
195
|
blockRoot: RootHex;
|
|
193
|
-
stateRoot: RootHex;
|
|
194
196
|
};
|
|
195
197
|
[EventType.executionPayloadAvailable]: {
|
|
196
198
|
slot: Slot;
|
|
197
199
|
blockRoot: RootHex;
|
|
198
200
|
};
|
|
201
|
+
[EventType.executionPayloadBid]: {version: ForkName; data: gloas.SignedExecutionPayloadBid};
|
|
199
202
|
};
|
|
200
203
|
|
|
201
204
|
export type BeaconEvent = {[K in EventType]: {type: K; message: EventData[K]}}[EventType];
|
|
@@ -371,7 +374,6 @@ export function getTypeByEvent(config: ChainForkConfig): {[K in EventType]: Type
|
|
|
371
374
|
builderIndex: ssz.BuilderIndex,
|
|
372
375
|
blockHash: stringType,
|
|
373
376
|
blockRoot: stringType,
|
|
374
|
-
stateRoot: stringType,
|
|
375
377
|
executionOptimistic: ssz.Boolean,
|
|
376
378
|
},
|
|
377
379
|
{jsonCase: "eth2"}
|
|
@@ -382,7 +384,6 @@ export function getTypeByEvent(config: ChainForkConfig): {[K in EventType]: Type
|
|
|
382
384
|
builderIndex: ssz.BuilderIndex,
|
|
383
385
|
blockHash: stringType,
|
|
384
386
|
blockRoot: stringType,
|
|
385
|
-
stateRoot: stringType,
|
|
386
387
|
},
|
|
387
388
|
{jsonCase: "eth2"}
|
|
388
389
|
),
|
|
@@ -393,6 +394,7 @@ export function getTypeByEvent(config: ChainForkConfig): {[K in EventType]: Type
|
|
|
393
394
|
},
|
|
394
395
|
{jsonCase: "eth2"}
|
|
395
396
|
),
|
|
397
|
+
[EventType.executionPayloadBid]: WithVersion((fork) => getPostGloasForkTypes(fork).SignedExecutionPayloadBid),
|
|
396
398
|
|
|
397
399
|
[EventType.lightClientOptimisticUpdate]: WithVersion(
|
|
398
400
|
(fork) => getPostAltairForkTypes(fork).LightClientOptimisticUpdate
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import {ContainerType, Type, ValueOf} from "@chainsafe/ssz";
|
|
2
2
|
import {ChainForkConfig} from "@lodestar/config";
|
|
3
|
-
import {
|
|
3
|
+
import {ForkName} from "@lodestar/params";
|
|
4
|
+
import {
|
|
5
|
+
ArrayOf,
|
|
6
|
+
AttesterSlashing,
|
|
7
|
+
BeaconState,
|
|
8
|
+
Epoch,
|
|
9
|
+
RootHex,
|
|
10
|
+
SignedBeaconBlock,
|
|
11
|
+
Slot,
|
|
12
|
+
ValidatorIndex,
|
|
13
|
+
ssz,
|
|
14
|
+
} from "@lodestar/types";
|
|
4
15
|
import {
|
|
5
16
|
EmptyArgs,
|
|
6
17
|
EmptyMeta,
|
|
@@ -11,10 +22,13 @@ import {
|
|
|
11
22
|
JsonOnlyResponseCodec,
|
|
12
23
|
WithVersion,
|
|
13
24
|
} from "../../utils/codecs.js";
|
|
25
|
+
import {toForkName} from "../../utils/fork.js";
|
|
26
|
+
import {fromHeaders} from "../../utils/headers.js";
|
|
14
27
|
import {Endpoint, RouteDefinitions, Schema} from "../../utils/index.js";
|
|
15
28
|
import {
|
|
16
29
|
ExecutionOptimisticFinalizedAndVersionCodec,
|
|
17
30
|
ExecutionOptimisticFinalizedAndVersionMeta,
|
|
31
|
+
MetaHeader,
|
|
18
32
|
VersionCodec,
|
|
19
33
|
VersionMeta,
|
|
20
34
|
} from "../../utils/metadata.js";
|
|
@@ -382,9 +396,27 @@ export type Endpoints = {
|
|
|
382
396
|
CustodyInfo,
|
|
383
397
|
EmptyMeta
|
|
384
398
|
>;
|
|
399
|
+
|
|
400
|
+
/** Craft attester slashings from the attestations in the provided blocks */
|
|
401
|
+
getAttesterSlashingsFromBlocks: Endpoint<
|
|
402
|
+
"POST",
|
|
403
|
+
{signedBlocks: SignedBeaconBlock[]},
|
|
404
|
+
{body: unknown; headers: {[MetaHeader.Version]: string}},
|
|
405
|
+
AttesterSlashing[],
|
|
406
|
+
VersionMeta
|
|
407
|
+
>;
|
|
385
408
|
};
|
|
386
409
|
|
|
387
|
-
export function getDefinitions(
|
|
410
|
+
export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoints> {
|
|
411
|
+
function assertBlocksMatchFork(signedBlocks: SignedBeaconBlock[], expectedFork: ForkName): void {
|
|
412
|
+
for (const block of signedBlocks) {
|
|
413
|
+
const blockFork = config.getForkName(block.message.slot);
|
|
414
|
+
if (blockFork !== expectedFork) {
|
|
415
|
+
throw new Error(`Block at slot ${block.message.slot} is from fork ${blockFork}, expected ${expectedFork}`);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
388
420
|
return {
|
|
389
421
|
writeHeapdump: {
|
|
390
422
|
url: "/eth/v1/lodestar/write_heapdump",
|
|
@@ -602,5 +634,47 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions<Endpo
|
|
|
602
634
|
req: EmptyRequestCodec,
|
|
603
635
|
resp: JsonOnlyResponseCodec,
|
|
604
636
|
},
|
|
637
|
+
getAttesterSlashingsFromBlocks: {
|
|
638
|
+
url: "/eth/v1/lodestar/blocks/attester_slashings",
|
|
639
|
+
method: "POST",
|
|
640
|
+
req: {
|
|
641
|
+
writeReqJson: ({signedBlocks}) => {
|
|
642
|
+
if (signedBlocks.length === 0) throw new Error("No blocks provided.");
|
|
643
|
+
const fork = config.getForkName(signedBlocks[0].message.slot);
|
|
644
|
+
return {
|
|
645
|
+
body: ArrayOf(ssz[fork].SignedBeaconBlock).toJson(signedBlocks as SignedBeaconBlock<typeof fork>[]),
|
|
646
|
+
headers: {[MetaHeader.Version]: fork},
|
|
647
|
+
};
|
|
648
|
+
},
|
|
649
|
+
parseReqJson: ({body, headers}) => {
|
|
650
|
+
const fork = toForkName(fromHeaders(headers, MetaHeader.Version));
|
|
651
|
+
const signedBlocks = ArrayOf(ssz[fork].SignedBeaconBlock).fromJson(body) as SignedBeaconBlock[];
|
|
652
|
+
assertBlocksMatchFork(signedBlocks, fork);
|
|
653
|
+
return {signedBlocks};
|
|
654
|
+
},
|
|
655
|
+
writeReqSsz: ({signedBlocks}) => {
|
|
656
|
+
if (signedBlocks.length === 0) throw new Error("No blocks provided.");
|
|
657
|
+
const fork = config.getForkName(signedBlocks[0].message.slot);
|
|
658
|
+
return {
|
|
659
|
+
body: ArrayOf(ssz[fork].SignedBeaconBlock).serialize(signedBlocks as SignedBeaconBlock<typeof fork>[]),
|
|
660
|
+
headers: {[MetaHeader.Version]: fork},
|
|
661
|
+
};
|
|
662
|
+
},
|
|
663
|
+
parseReqSsz: ({body, headers}) => {
|
|
664
|
+
const fork = toForkName(fromHeaders(headers, MetaHeader.Version));
|
|
665
|
+
const signedBlocks = ArrayOf(ssz[fork].SignedBeaconBlock).deserialize(body) as SignedBeaconBlock[];
|
|
666
|
+
assertBlocksMatchFork(signedBlocks, fork);
|
|
667
|
+
return {signedBlocks};
|
|
668
|
+
},
|
|
669
|
+
schema: {
|
|
670
|
+
body: Schema.ObjectArray,
|
|
671
|
+
headers: {[MetaHeader.Version]: Schema.String},
|
|
672
|
+
},
|
|
673
|
+
},
|
|
674
|
+
resp: {
|
|
675
|
+
data: WithVersion((fork) => ArrayOf(ssz[fork].AttesterSlashing)),
|
|
676
|
+
meta: VersionCodec,
|
|
677
|
+
},
|
|
678
|
+
},
|
|
605
679
|
};
|
|
606
680
|
}
|
|
@@ -131,6 +131,18 @@ export const ProposerDutyType = new ContainerType(
|
|
|
131
131
|
{jsonCase: "eth2"}
|
|
132
132
|
);
|
|
133
133
|
|
|
134
|
+
export const PtcDutyType = new ContainerType(
|
|
135
|
+
{
|
|
136
|
+
/** Public key of the validator in the registry */
|
|
137
|
+
pubkey: ssz.BLSPubkey,
|
|
138
|
+
/** Index of validator in the registry. */
|
|
139
|
+
validatorIndex: ssz.ValidatorIndex,
|
|
140
|
+
/** The slot at which the validator must perform PTC duties. */
|
|
141
|
+
slot: ssz.Slot,
|
|
142
|
+
},
|
|
143
|
+
{jsonCase: "eth2"}
|
|
144
|
+
);
|
|
145
|
+
|
|
134
146
|
/**
|
|
135
147
|
* From https://github.com/ethereum/beacon-APIs/pull/134
|
|
136
148
|
*/
|
|
@@ -219,6 +231,7 @@ export const LivenessResponseDataType = new ContainerType(
|
|
|
219
231
|
export const ValidatorIndicesType = ArrayOf(ssz.ValidatorIndex);
|
|
220
232
|
export const AttesterDutyListType = ArrayOf(AttesterDutyType);
|
|
221
233
|
export const ProposerDutyListType = ArrayOf(ProposerDutyType);
|
|
234
|
+
export const PtcDutyListType = ArrayOf(PtcDutyType);
|
|
222
235
|
export const SyncDutyListType = ArrayOf(SyncDutyType);
|
|
223
236
|
export const SignedAggregateAndProofListPhase0Type = ArrayOf(ssz.phase0.SignedAggregateAndProof);
|
|
224
237
|
export const SignedAggregateAndProofListElectraType = ArrayOf(ssz.electra.SignedAggregateAndProof);
|
|
@@ -239,6 +252,8 @@ export type AttesterDuty = ValueOf<typeof AttesterDutyType>;
|
|
|
239
252
|
export type AttesterDutyList = ValueOf<typeof AttesterDutyListType>;
|
|
240
253
|
export type ProposerDuty = ValueOf<typeof ProposerDutyType>;
|
|
241
254
|
export type ProposerDutyList = ValueOf<typeof ProposerDutyListType>;
|
|
255
|
+
export type PtcDuty = ValueOf<typeof PtcDutyType>;
|
|
256
|
+
export type PtcDutyList = ValueOf<typeof PtcDutyListType>;
|
|
242
257
|
export type SyncDuty = ValueOf<typeof SyncDutyType>;
|
|
243
258
|
export type SyncDutyList = ValueOf<typeof SyncDutyListType>;
|
|
244
259
|
export type SignedAggregateAndProofListPhase0 = ValueOf<typeof SignedAggregateAndProofListPhase0Type>;
|
|
@@ -336,6 +351,23 @@ export type Endpoints = {
|
|
|
336
351
|
ExecutionOptimisticMeta
|
|
337
352
|
>;
|
|
338
353
|
|
|
354
|
+
/**
|
|
355
|
+
* Get PTC duties
|
|
356
|
+
* Requests the beacon node to provide a set of Payload Timeliness Committee duties for a particular epoch.
|
|
357
|
+
*/
|
|
358
|
+
getPtcDuties: Endpoint<
|
|
359
|
+
"POST",
|
|
360
|
+
{
|
|
361
|
+
/** Must not be greater than the next epoch */
|
|
362
|
+
epoch: Epoch;
|
|
363
|
+
/** An array of the validator indices for which to obtain the duties */
|
|
364
|
+
indices: ValidatorIndices;
|
|
365
|
+
},
|
|
366
|
+
{params: {epoch: Epoch}; body: unknown},
|
|
367
|
+
PtcDutyList,
|
|
368
|
+
ExecutionOptimisticAndDependentRootMeta
|
|
369
|
+
>;
|
|
370
|
+
|
|
339
371
|
/**
|
|
340
372
|
* Requests a beacon node to produce a valid block, which can then be signed by a validator.
|
|
341
373
|
* Metadata in the response indicates the type of block produced, and the supported types of block
|
|
@@ -440,6 +472,21 @@ export type Endpoints = {
|
|
|
440
472
|
EmptyMeta
|
|
441
473
|
>;
|
|
442
474
|
|
|
475
|
+
/**
|
|
476
|
+
* Produce payload attestation data
|
|
477
|
+
* Requests that the beacon node produce a PayloadAttestationData.
|
|
478
|
+
*/
|
|
479
|
+
producePayloadAttestationData: Endpoint<
|
|
480
|
+
"GET",
|
|
481
|
+
{
|
|
482
|
+
/** The slot for which payload attestation data should be created */
|
|
483
|
+
slot: Slot;
|
|
484
|
+
},
|
|
485
|
+
{params: {slot: Slot}},
|
|
486
|
+
gloas.PayloadAttestationData,
|
|
487
|
+
VersionMeta
|
|
488
|
+
>;
|
|
489
|
+
|
|
443
490
|
produceSyncCommitteeContribution: Endpoint<
|
|
444
491
|
"GET",
|
|
445
492
|
{
|
|
@@ -698,6 +745,24 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoi
|
|
|
698
745
|
meta: ExecutionOptimisticCodec,
|
|
699
746
|
},
|
|
700
747
|
},
|
|
748
|
+
getPtcDuties: {
|
|
749
|
+
url: "/eth/v1/validator/duties/ptc/{epoch}",
|
|
750
|
+
method: "POST",
|
|
751
|
+
req: {
|
|
752
|
+
writeReqJson: ({epoch, indices}) => ({params: {epoch}, body: ValidatorIndicesType.toJson(indices)}),
|
|
753
|
+
parseReqJson: ({params, body}) => ({epoch: params.epoch, indices: ValidatorIndicesType.fromJson(body)}),
|
|
754
|
+
writeReqSsz: ({epoch, indices}) => ({params: {epoch}, body: ValidatorIndicesType.serialize(indices)}),
|
|
755
|
+
parseReqSsz: ({params, body}) => ({epoch: params.epoch, indices: ValidatorIndicesType.deserialize(body)}),
|
|
756
|
+
schema: {
|
|
757
|
+
params: {epoch: Schema.UintRequired},
|
|
758
|
+
body: Schema.StringArray,
|
|
759
|
+
},
|
|
760
|
+
},
|
|
761
|
+
resp: {
|
|
762
|
+
data: PtcDutyListType,
|
|
763
|
+
meta: ExecutionOptimisticAndDependentRootCodec,
|
|
764
|
+
},
|
|
765
|
+
},
|
|
701
766
|
produceBlockV3: {
|
|
702
767
|
url: "/eth/v3/validator/blocks/{slot}",
|
|
703
768
|
method: "GET",
|
|
@@ -780,7 +845,8 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoi
|
|
|
780
845
|
(data as BlockContents).block as BeaconBlock<ForkPreDeneb> // <- tranformation
|
|
781
846
|
);
|
|
782
847
|
},
|
|
783
|
-
deserialize(data,
|
|
848
|
+
deserialize(data, meta) {
|
|
849
|
+
const {executionPayloadBlinded, version} = meta as ProduceBlockV3Meta;
|
|
784
850
|
return executionPayloadBlinded
|
|
785
851
|
? getPostBellatrixForkTypes(version).BlindedBeaconBlock.deserialize(data)
|
|
786
852
|
: isForkPostDeneb(version)
|
|
@@ -934,6 +1000,21 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoi
|
|
|
934
1000
|
meta: EmptyMetaCodec,
|
|
935
1001
|
},
|
|
936
1002
|
},
|
|
1003
|
+
producePayloadAttestationData: {
|
|
1004
|
+
url: "/eth/v1/validator/payload_attestation_data/{slot}",
|
|
1005
|
+
method: "GET",
|
|
1006
|
+
req: {
|
|
1007
|
+
writeReq: ({slot}) => ({params: {slot}}),
|
|
1008
|
+
parseReq: ({params}) => ({slot: params.slot}),
|
|
1009
|
+
schema: {
|
|
1010
|
+
params: {slot: Schema.UintRequired},
|
|
1011
|
+
},
|
|
1012
|
+
},
|
|
1013
|
+
resp: {
|
|
1014
|
+
data: ssz.gloas.PayloadAttestationData,
|
|
1015
|
+
meta: VersionCodec,
|
|
1016
|
+
},
|
|
1017
|
+
},
|
|
937
1018
|
produceSyncCommitteeContribution: {
|
|
938
1019
|
url: "/eth/v1/validator/sync_committee_contribution",
|
|
939
1020
|
method: "GET",
|
package/src/utils/types.ts
CHANGED
|
@@ -118,7 +118,10 @@ export type ResponseDataCodec<T, M> = {
|
|
|
118
118
|
toJson: (data: T, meta: M) => unknown; // server
|
|
119
119
|
fromJson: (data: unknown, meta: M) => T; // client
|
|
120
120
|
serialize: (data: T, meta: M) => Uint8Array; // server
|
|
121
|
-
deserialize
|
|
121
|
+
// `meta` is typed as `any` so SSZ `Type<T>.deserialize(data, opts?)` satisfies the shape.
|
|
122
|
+
// Route-specific deserializers (e.g. `WithVersion`) cast to their expected meta internally.
|
|
123
|
+
// biome-ignore lint/suspicious/noExplicitAny: contravariant workaround for ssz Type.deserialize(opts?)
|
|
124
|
+
deserialize: (data: Uint8Array, meta: any) => T; // client
|
|
122
125
|
};
|
|
123
126
|
|
|
124
127
|
export type ResponseMetadataCodec<T> = {
|