1
1
/* eslint-disable @typescript-eslint/naming-convention */
2
2
import { ValueOf } from "@chainsafe/ssz" ;
3
3
import { ChainForkConfig } from "@lodestar/config" ;
4
- import { phase0 , capella , CommitteeIndex , Slot , ssz } from "@lodestar/types" ;
4
+ import { isForkPostElectra } from "@lodestar/params" ;
5
+ import { phase0 , capella , CommitteeIndex , Slot , ssz , electra , AttesterSlashing } from "@lodestar/types" ;
5
6
import { Schema , Endpoint , RouteDefinitions } from "../../../utils/index.js" ;
6
7
import {
7
8
ArrayOf ,
@@ -12,19 +13,31 @@ import {
12
13
EmptyRequest ,
13
14
EmptyResponseCodec ,
14
15
EmptyResponseData ,
16
+ WithVersion ,
15
17
} from "../../../utils/codecs.js" ;
18
+ import { MetaHeader , VersionCodec , VersionMeta } from "../../../utils/metadata.js" ;
19
+ import { toForkName } from "../../../utils/fork.js" ;
20
+ import { fromHeaders } from "../../../utils/headers.js" ;
16
21
17
22
// See /packages/api/src/routes/index.ts for reasoning and instructions to add new routes
18
23
19
- const AttestationListType = ArrayOf ( ssz . phase0 . Attestation ) ;
20
- const AttesterSlashingListType = ArrayOf ( ssz . phase0 . AttesterSlashing ) ;
24
+ const AttestationListTypePhase0 = ArrayOf ( ssz . phase0 . Attestation ) ;
25
+ const AttestationListTypeElectra = ArrayOf ( ssz . electra . Attestation ) ;
26
+ const AttesterSlashingListTypePhase0 = ArrayOf ( ssz . phase0 . AttesterSlashing ) ;
27
+ const AttesterSlashingListTypeElectra = ArrayOf ( ssz . electra . AttesterSlashing ) ;
21
28
const ProposerSlashingListType = ArrayOf ( ssz . phase0 . ProposerSlashing ) ;
22
29
const SignedVoluntaryExitListType = ArrayOf ( ssz . phase0 . SignedVoluntaryExit ) ;
23
30
const SignedBLSToExecutionChangeListType = ArrayOf ( ssz . capella . SignedBLSToExecutionChange ) ;
24
31
const SyncCommitteeMessageListType = ArrayOf ( ssz . altair . SyncCommitteeMessage ) ;
25
32
26
- type AttestationList = ValueOf < typeof AttestationListType > ;
27
- type AttesterSlashingList = ValueOf < typeof AttesterSlashingListType > ;
33
+ type AttestationListPhase0 = ValueOf < typeof AttestationListTypePhase0 > ;
34
+ type AttestationListElectra = ValueOf < typeof AttestationListTypeElectra > ;
35
+ type AttestationList = AttestationListPhase0 | AttestationListElectra ;
36
+
37
+ type AttesterSlashingListPhase0 = ValueOf < typeof AttesterSlashingListTypePhase0 > ;
38
+ type AttesterSlashingListElectra = ValueOf < typeof AttesterSlashingListTypeElectra > ;
39
+ type AttesterSlashingList = AttesterSlashingListPhase0 | AttesterSlashingListElectra ;
40
+
28
41
type ProposerSlashingList = ValueOf < typeof ProposerSlashingListType > ;
29
42
type SignedVoluntaryExitList = ValueOf < typeof SignedVoluntaryExitListType > ;
30
43
type SignedBLSToExecutionChangeList = ValueOf < typeof SignedBLSToExecutionChangeListType > ;
@@ -39,10 +52,22 @@ export type Endpoints = {
39
52
"GET" ,
40
53
{ slot ?: Slot ; committeeIndex ?: CommitteeIndex } ,
41
54
{ query : { slot ?: number ; committee_index ?: number } } ,
42
- AttestationList ,
55
+ AttestationListPhase0 ,
43
56
EmptyMeta
44
57
> ;
45
58
59
+ /**
60
+ * Get Attestations from operations pool
61
+ * Retrieves attestations known by the node but not necessarily incorporated into any block
62
+ */
63
+ getPoolAttestationsV2 : Endpoint <
64
+ "GET" ,
65
+ { slot ?: Slot ; committeeIndex ?: CommitteeIndex } ,
66
+ { query : { slot ?: number ; committee_index ?: number } } ,
67
+ AttestationList ,
68
+ VersionMeta
69
+ > ;
70
+
46
71
/**
47
72
* Get AttesterSlashings from operations pool
48
73
* Retrieves attester slashings known by the node but not necessarily incorporated into any block
@@ -52,10 +77,23 @@ export type Endpoints = {
52
77
"GET" ,
53
78
EmptyArgs ,
54
79
EmptyRequest ,
55
- AttesterSlashingList ,
80
+ AttesterSlashingListPhase0 ,
56
81
EmptyMeta
57
82
> ;
58
83
84
+ /**
85
+ * Get AttesterSlashings from operations pool
86
+ * Retrieves attester slashings known by the node but not necessarily incorporated into any block
87
+ */
88
+ getPoolAttesterSlashingsV2 : Endpoint <
89
+ // ⏎
90
+ "GET" ,
91
+ EmptyArgs ,
92
+ EmptyRequest ,
93
+ AttesterSlashingList ,
94
+ VersionMeta
95
+ > ;
96
+
59
97
/**
60
98
* Get ProposerSlashings from operations pool
61
99
* Retrieves proposer slashings known by the node but not necessarily incorporated into any block
@@ -105,12 +143,28 @@ export type Endpoints = {
105
143
*/
106
144
submitPoolAttestations : Endpoint <
107
145
"POST" ,
108
- { signedAttestations : AttestationList } ,
146
+ { signedAttestations : AttestationListPhase0 } ,
109
147
{ body : unknown } ,
110
148
EmptyResponseData ,
111
149
EmptyMeta
112
150
> ;
113
151
152
+ /**
153
+ * Submit Attestation objects to node
154
+ * Submits Attestation objects to the node. Each attestation in the request body is processed individually.
155
+ *
156
+ * If an attestation is validated successfully the node MUST publish that attestation on the appropriate subnet.
157
+ *
158
+ * If one or more attestations fail validation the node MUST return a 400 error with details of which attestations have failed, and why.
159
+ */
160
+ submitPoolAttestationsV2 : Endpoint <
161
+ "POST" ,
162
+ { signedAttestations : AttestationList } ,
163
+ { body : unknown ; headers : { [ MetaHeader . Version ] : string } } ,
164
+ EmptyResponseData ,
165
+ EmptyMeta
166
+ > ;
167
+
114
168
/**
115
169
* Submit AttesterSlashing object to node's pool
116
170
* Submits AttesterSlashing object to node's pool and if passes validation node MUST broadcast it to network.
@@ -123,6 +177,18 @@ export type Endpoints = {
123
177
EmptyMeta
124
178
> ;
125
179
180
+ /**
181
+ * Submit AttesterSlashing object to node's pool
182
+ * Submits AttesterSlashing object to node's pool and if passes validation node MUST broadcast it to network.
183
+ */
184
+ submitPoolAttesterSlashingsV2 : Endpoint <
185
+ "POST" ,
186
+ { attesterSlashing : AttesterSlashing } ,
187
+ { body : unknown ; headers : { [ MetaHeader . Version ] : string } } ,
188
+ EmptyResponseData ,
189
+ EmptyMeta
190
+ > ;
191
+
126
192
/**
127
193
* Submit ProposerSlashing object to node's pool
128
194
* Submits ProposerSlashing object to node's pool and if passes validation node MUST broadcast it to network.
@@ -172,7 +238,7 @@ export type Endpoints = {
172
238
> ;
173
239
} ;
174
240
175
- export function getDefinitions ( _config : ChainForkConfig ) : RouteDefinitions < Endpoints > {
241
+ export function getDefinitions ( config : ChainForkConfig ) : RouteDefinitions < Endpoints > {
176
242
return {
177
243
getPoolAttestations : {
178
244
url : "/eth/v1/beacon/pool/attestations" ,
@@ -183,19 +249,43 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions<Endpo
183
249
schema : { query : { slot : Schema . Uint , committee_index : Schema . Uint } } ,
184
250
} ,
185
251
resp : {
186
- data : AttestationListType ,
252
+ data : AttestationListTypePhase0 ,
187
253
meta : EmptyMetaCodec ,
188
254
} ,
189
255
} ,
256
+ getPoolAttestationsV2 : {
257
+ url : "/eth/v2/beacon/pool/attestations" ,
258
+ method : "GET" ,
259
+ req : {
260
+ writeReq : ( { slot, committeeIndex} ) => ( { query : { slot, committee_index : committeeIndex } } ) ,
261
+ parseReq : ( { query} ) => ( { slot : query . slot , committeeIndex : query . committee_index } ) ,
262
+ schema : { query : { slot : Schema . Uint , committee_index : Schema . Uint } } ,
263
+ } ,
264
+ resp : {
265
+ data : WithVersion ( ( fork ) => ( isForkPostElectra ( fork ) ? AttestationListTypeElectra : AttestationListTypePhase0 ) ) ,
266
+ meta : VersionCodec ,
267
+ } ,
268
+ } ,
190
269
getPoolAttesterSlashings : {
191
270
url : "/eth/v1/beacon/pool/attester_slashings" ,
192
271
method : "GET" ,
193
272
req : EmptyRequestCodec ,
194
273
resp : {
195
- data : AttesterSlashingListType ,
274
+ data : AttesterSlashingListTypePhase0 ,
196
275
meta : EmptyMetaCodec ,
197
276
} ,
198
277
} ,
278
+ getPoolAttesterSlashingsV2 : {
279
+ url : "/eth/v2/beacon/pool/attester_slashings" ,
280
+ method : "GET" ,
281
+ req : EmptyRequestCodec ,
282
+ resp : {
283
+ data : WithVersion ( ( fork ) =>
284
+ isForkPostElectra ( fork ) ? AttesterSlashingListTypeElectra : AttesterSlashingListTypePhase0
285
+ ) ,
286
+ meta : VersionCodec ,
287
+ } ,
288
+ } ,
199
289
getPoolProposerSlashings : {
200
290
url : "/eth/v1/beacon/pool/proposer_slashings" ,
201
291
method : "GET" ,
@@ -227,16 +317,61 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions<Endpo
227
317
url : "/eth/v1/beacon/pool/attestations" ,
228
318
method : "POST" ,
229
319
req : {
230
- writeReqJson : ( { signedAttestations} ) => ( { body : AttestationListType . toJson ( signedAttestations ) } ) ,
231
- parseReqJson : ( { body} ) => ( { signedAttestations : AttestationListType . fromJson ( body ) } ) ,
232
- writeReqSsz : ( { signedAttestations} ) => ( { body : AttestationListType . serialize ( signedAttestations ) } ) ,
233
- parseReqSsz : ( { body} ) => ( { signedAttestations : AttestationListType . deserialize ( body ) } ) ,
320
+ writeReqJson : ( { signedAttestations} ) => ( { body : AttestationListTypePhase0 . toJson ( signedAttestations ) } ) ,
321
+ parseReqJson : ( { body} ) => ( { signedAttestations : AttestationListTypePhase0 . fromJson ( body ) } ) ,
322
+ writeReqSsz : ( { signedAttestations} ) => ( { body : AttestationListTypePhase0 . serialize ( signedAttestations ) } ) ,
323
+ parseReqSsz : ( { body} ) => ( { signedAttestations : AttestationListTypePhase0 . deserialize ( body ) } ) ,
234
324
schema : {
235
325
body : Schema . ObjectArray ,
236
326
} ,
237
327
} ,
238
328
resp : EmptyResponseCodec ,
239
329
} ,
330
+ submitPoolAttestationsV2 : {
331
+ url : "/eth/v2/beacon/pool/attestations" ,
332
+ method : "POST" ,
333
+ req : {
334
+ writeReqJson : ( { signedAttestations} ) => {
335
+ const fork = config . getForkName ( signedAttestations [ 0 ] ?. data . slot ?? 0 ) ;
336
+ return {
337
+ body : isForkPostElectra ( fork )
338
+ ? AttestationListTypeElectra . toJson ( signedAttestations as AttestationListElectra )
339
+ : AttestationListTypePhase0 . toJson ( signedAttestations as AttestationListPhase0 ) ,
340
+ headers : { [ MetaHeader . Version ] : fork } ,
341
+ } ;
342
+ } ,
343
+ parseReqJson : ( { body, headers} ) => {
344
+ const fork = toForkName ( fromHeaders ( headers , MetaHeader . Version ) ) ;
345
+ return {
346
+ signedAttestations : isForkPostElectra ( fork )
347
+ ? AttestationListTypeElectra . fromJson ( body )
348
+ : AttestationListTypePhase0 . fromJson ( body ) ,
349
+ } ;
350
+ } ,
351
+ writeReqSsz : ( { signedAttestations} ) => {
352
+ const fork = config . getForkName ( signedAttestations [ 0 ] ?. data . slot ?? 0 ) ;
353
+ return {
354
+ body : isForkPostElectra ( fork )
355
+ ? AttestationListTypeElectra . serialize ( signedAttestations as AttestationListElectra )
356
+ : AttestationListTypePhase0 . serialize ( signedAttestations as AttestationListPhase0 ) ,
357
+ headers : { [ MetaHeader . Version ] : fork } ,
358
+ } ;
359
+ } ,
360
+ parseReqSsz : ( { body, headers} ) => {
361
+ const fork = toForkName ( fromHeaders ( headers , MetaHeader . Version ) ) ;
362
+ return {
363
+ signedAttestations : isForkPostElectra ( fork )
364
+ ? AttestationListTypeElectra . deserialize ( body )
365
+ : AttestationListTypePhase0 . deserialize ( body ) ,
366
+ } ;
367
+ } ,
368
+ schema : {
369
+ body : Schema . ObjectArray ,
370
+ headers : { [ MetaHeader . Version ] : Schema . String } ,
371
+ } ,
372
+ } ,
373
+ resp : EmptyResponseCodec ,
374
+ } ,
240
375
submitPoolAttesterSlashings : {
241
376
url : "/eth/v1/beacon/pool/attester_slashings" ,
242
377
method : "POST" ,
@@ -251,6 +386,51 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions<Endpo
251
386
} ,
252
387
resp : EmptyResponseCodec ,
253
388
} ,
389
+ submitPoolAttesterSlashingsV2 : {
390
+ url : "/eth/v2/beacon/pool/attester_slashings" ,
391
+ method : "POST" ,
392
+ req : {
393
+ writeReqJson : ( { attesterSlashing} ) => {
394
+ const fork = config . getForkName ( Number ( attesterSlashing . attestation1 . data . slot ) ) ;
395
+ return {
396
+ body : isForkPostElectra ( fork )
397
+ ? ssz . electra . AttesterSlashing . toJson ( attesterSlashing )
398
+ : ssz . phase0 . AttesterSlashing . toJson ( attesterSlashing ) ,
399
+ headers : { [ MetaHeader . Version ] : fork } ,
400
+ } ;
401
+ } ,
402
+ parseReqJson : ( { body, headers} ) => {
403
+ const fork = toForkName ( fromHeaders ( headers , MetaHeader . Version ) ) ;
404
+ return {
405
+ attesterSlashing : isForkPostElectra ( fork )
406
+ ? ssz . electra . AttesterSlashing . fromJson ( body )
407
+ : ssz . phase0 . AttesterSlashing . fromJson ( body ) ,
408
+ } ;
409
+ } ,
410
+ writeReqSsz : ( { attesterSlashing} ) => {
411
+ const fork = config . getForkName ( Number ( attesterSlashing . attestation1 . data . slot ) ) ;
412
+ return {
413
+ body : isForkPostElectra ( fork )
414
+ ? ssz . electra . AttesterSlashing . serialize ( attesterSlashing as electra . AttesterSlashing )
415
+ : ssz . phase0 . AttesterSlashing . serialize ( attesterSlashing as phase0 . AttesterSlashing ) ,
416
+ headers : { [ MetaHeader . Version ] : fork } ,
417
+ } ;
418
+ } ,
419
+ parseReqSsz : ( { body, headers} ) => {
420
+ const fork = toForkName ( fromHeaders ( headers , MetaHeader . Version ) ) ;
421
+ return {
422
+ attesterSlashing : isForkPostElectra ( fork )
423
+ ? ssz . electra . AttesterSlashing . deserialize ( body )
424
+ : ssz . phase0 . AttesterSlashing . deserialize ( body ) ,
425
+ } ;
426
+ } ,
427
+ schema : {
428
+ body : Schema . Object ,
429
+ headers : { [ MetaHeader . Version ] : Schema . String } ,
430
+ } ,
431
+ } ,
432
+ resp : EmptyResponseCodec ,
433
+ } ,
254
434
submitPoolProposerSlashings : {
255
435
url : "/eth/v1/beacon/pool/proposer_slashings" ,
256
436
method : "POST" ,
0 commit comments