@lodestar/beacon-node 1.50.0-dev.0837ebd402 → 1.50.0-dev.09bef4706f

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.
Files changed (188) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +7 -2
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/validator/index.d.ts.map +1 -1
  5. package/lib/api/impl/validator/index.js +57 -17
  6. package/lib/api/impl/validator/index.js.map +1 -1
  7. package/lib/chain/ColumnReconstructionTracker.d.ts +0 -2
  8. package/lib/chain/ColumnReconstructionTracker.d.ts.map +1 -1
  9. package/lib/chain/ColumnReconstructionTracker.js +4 -5
  10. package/lib/chain/ColumnReconstructionTracker.js.map +1 -1
  11. package/lib/chain/beaconProposerCache.d.ts +6 -0
  12. package/lib/chain/beaconProposerCache.d.ts.map +1 -1
  13. package/lib/chain/beaconProposerCache.js +16 -0
  14. package/lib/chain/beaconProposerCache.js.map +1 -1
  15. package/lib/chain/blocks/blockInput/blockInput.d.ts +1 -1
  16. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  17. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  18. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  19. package/lib/chain/blocks/importBlock.js +8 -6
  20. package/lib/chain/blocks/importBlock.js.map +1 -1
  21. package/lib/chain/chain.d.ts +1 -0
  22. package/lib/chain/chain.d.ts.map +1 -1
  23. package/lib/chain/chain.js +16 -2
  24. package/lib/chain/chain.js.map +1 -1
  25. package/lib/chain/interface.d.ts +3 -1
  26. package/lib/chain/interface.d.ts.map +1 -1
  27. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  28. package/lib/chain/prepareNextSlot.js +15 -6
  29. package/lib/chain/prepareNextSlot.js.map +1 -1
  30. package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
  31. package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
  32. package/lib/chain/produceBlock/produceBlockBody.d.ts +8 -0
  33. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  34. package/lib/chain/produceBlock/produceBlockBody.js +48 -34
  35. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  36. package/lib/chain/reprocess.d.ts +2 -1
  37. package/lib/chain/reprocess.d.ts.map +1 -1
  38. package/lib/chain/reprocess.js +2 -1
  39. package/lib/chain/reprocess.js.map +1 -1
  40. package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
  41. package/lib/chain/seenCache/seenGossipBlockInput.js +1 -1
  42. package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
  43. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  44. package/lib/chain/stateCache/persistentCheckpointsCache.js +1 -1
  45. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  46. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  47. package/lib/chain/validatorMonitor.js +6 -4
  48. package/lib/chain/validatorMonitor.js.map +1 -1
  49. package/lib/constants/constants.d.ts +1 -0
  50. package/lib/constants/constants.d.ts.map +1 -1
  51. package/lib/constants/constants.js +1 -0
  52. package/lib/constants/constants.js.map +1 -1
  53. package/lib/db/repositories/blockArchive.js +2 -2
  54. package/lib/db/repositories/blockArchive.js.map +1 -1
  55. package/lib/db/repositories/blockArchiveIndex.d.ts +1 -1
  56. package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
  57. package/lib/db/repositories/blockArchiveIndex.js +1 -2
  58. package/lib/db/repositories/blockArchiveIndex.js.map +1 -1
  59. package/lib/execution/engine/blobVersionedHashes.d.ts +9 -0
  60. package/lib/execution/engine/blobVersionedHashes.d.ts.map +1 -0
  61. package/lib/execution/engine/blobVersionedHashes.js +74 -0
  62. package/lib/execution/engine/blobVersionedHashes.js.map +1 -0
  63. package/lib/execution/engine/http.d.ts +45 -13
  64. package/lib/execution/engine/http.d.ts.map +1 -1
  65. package/lib/execution/engine/http.js +236 -198
  66. package/lib/execution/engine/http.js.map +1 -1
  67. package/lib/execution/engine/index.d.ts +3 -2
  68. package/lib/execution/engine/index.d.ts.map +1 -1
  69. package/lib/execution/engine/index.js +33 -8
  70. package/lib/execution/engine/index.js.map +1 -1
  71. package/lib/execution/engine/interface.d.ts +1 -1
  72. package/lib/execution/engine/interface.d.ts.map +1 -1
  73. package/lib/execution/engine/jsonRpcHttpClient.d.ts.map +1 -1
  74. package/lib/execution/engine/jsonRpcHttpClient.js +14 -4
  75. package/lib/execution/engine/jsonRpcHttpClient.js.map +1 -1
  76. package/lib/execution/engine/jsonRpcTransport.d.ts +25 -0
  77. package/lib/execution/engine/jsonRpcTransport.d.ts.map +1 -0
  78. package/lib/execution/engine/jsonRpcTransport.js +158 -0
  79. package/lib/execution/engine/jsonRpcTransport.js.map +1 -0
  80. package/lib/execution/engine/restHttpClient.d.ts +71 -0
  81. package/lib/execution/engine/restHttpClient.d.ts.map +1 -0
  82. package/lib/execution/engine/restHttpClient.js +201 -0
  83. package/lib/execution/engine/restHttpClient.js.map +1 -0
  84. package/lib/execution/engine/restTransport.d.ts +48 -0
  85. package/lib/execution/engine/restTransport.d.ts.map +1 -0
  86. package/lib/execution/engine/restTransport.js +411 -0
  87. package/lib/execution/engine/restTransport.js.map +1 -0
  88. package/lib/execution/engine/sszTypes.d.ts +1261 -0
  89. package/lib/execution/engine/sszTypes.d.ts.map +1 -0
  90. package/lib/execution/engine/sszTypes.js +216 -0
  91. package/lib/execution/engine/sszTypes.js.map +1 -0
  92. package/lib/execution/engine/transport.d.ts +39 -0
  93. package/lib/execution/engine/transport.d.ts.map +1 -0
  94. package/lib/execution/engine/transport.js +2 -0
  95. package/lib/execution/engine/transport.js.map +1 -0
  96. package/lib/execution/engine/transportMetrics.d.ts +5 -1
  97. package/lib/execution/engine/transportMetrics.d.ts.map +1 -1
  98. package/lib/execution/engine/types.d.ts +2 -0
  99. package/lib/execution/engine/types.d.ts.map +1 -1
  100. package/lib/execution/engine/types.js +31 -63
  101. package/lib/execution/engine/types.js.map +1 -1
  102. package/lib/execution/engine/utils.d.ts.map +1 -1
  103. package/lib/execution/engine/utils.js +9 -2
  104. package/lib/execution/engine/utils.js.map +1 -1
  105. package/lib/metrics/metrics/lodestar.d.ts +7 -0
  106. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  107. package/lib/metrics/metrics/lodestar.js +12 -1
  108. package/lib/metrics/metrics/lodestar.js.map +1 -1
  109. package/lib/network/core/events.d.ts +5 -1
  110. package/lib/network/core/events.d.ts.map +1 -1
  111. package/lib/network/core/events.js +8 -0
  112. package/lib/network/core/events.js.map +1 -1
  113. package/lib/network/gossip/topic.d.ts +0 -14
  114. package/lib/network/gossip/topic.d.ts.map +1 -1
  115. package/lib/network/processor/gossipHandlers.js +1 -1
  116. package/lib/network/processor/gossipHandlers.js.map +1 -1
  117. package/lib/network/processor/index.js +3 -3
  118. package/lib/network/processor/index.js.map +1 -1
  119. package/lib/network/reqresp/rateLimit.js +2 -2
  120. package/lib/network/reqresp/rateLimit.js.map +1 -1
  121. package/lib/network/subnets/attnetsService.d.ts.map +1 -1
  122. package/lib/network/subnets/attnetsService.js +3 -1
  123. package/lib/network/subnets/attnetsService.js.map +1 -1
  124. package/lib/node/notifier.d.ts.map +1 -1
  125. package/lib/node/notifier.js +12 -13
  126. package/lib/node/notifier.js.map +1 -1
  127. package/lib/node/options.d.ts +3 -2
  128. package/lib/node/options.d.ts.map +1 -1
  129. package/lib/node/options.js +2 -2
  130. package/lib/node/options.js.map +1 -1
  131. package/lib/sync/unknownBlock.d.ts.map +1 -1
  132. package/lib/sync/unknownBlock.js +3 -2
  133. package/lib/sync/unknownBlock.js.map +1 -1
  134. package/lib/util/asyncIterableToEvents.d.ts +10 -2
  135. package/lib/util/asyncIterableToEvents.d.ts.map +1 -1
  136. package/lib/util/asyncIterableToEvents.js +29 -3
  137. package/lib/util/asyncIterableToEvents.js.map +1 -1
  138. package/lib/util/clock.d.ts.map +1 -1
  139. package/lib/util/clock.js +3 -4
  140. package/lib/util/clock.js.map +1 -1
  141. package/lib/util/sszBytes.d.ts +2 -2
  142. package/lib/util/sszBytes.d.ts.map +1 -1
  143. package/lib/util/sszBytes.js +22 -14
  144. package/lib/util/sszBytes.js.map +1 -1
  145. package/package.json +16 -15
  146. package/src/api/impl/beacon/blocks/index.ts +10 -3
  147. package/src/api/impl/validator/index.ts +78 -19
  148. package/src/chain/ColumnReconstructionTracker.ts +4 -6
  149. package/src/chain/beaconProposerCache.ts +19 -1
  150. package/src/chain/blocks/blockInput/blockInput.ts +1 -1
  151. package/src/chain/blocks/importBlock.ts +9 -6
  152. package/src/chain/chain.ts +18 -2
  153. package/src/chain/interface.ts +4 -1
  154. package/src/chain/prepareNextSlot.ts +22 -6
  155. package/src/chain/produceBlock/computeNewStateRoot.ts +9 -2
  156. package/src/chain/produceBlock/produceBlockBody.ts +78 -39
  157. package/src/chain/reprocess.ts +2 -1
  158. package/src/chain/seenCache/seenGossipBlockInput.ts +2 -1
  159. package/src/chain/stateCache/persistentCheckpointsCache.ts +4 -1
  160. package/src/chain/validatorMonitor.ts +7 -4
  161. package/src/constants/constants.ts +1 -0
  162. package/src/db/repositories/blockArchive.ts +2 -2
  163. package/src/db/repositories/blockArchiveIndex.ts +2 -3
  164. package/src/execution/engine/blobVersionedHashes.ts +72 -0
  165. package/src/execution/engine/http.ts +304 -271
  166. package/src/execution/engine/index.ts +42 -7
  167. package/src/execution/engine/interface.ts +1 -1
  168. package/src/execution/engine/jsonRpcHttpClient.ts +12 -5
  169. package/src/execution/engine/jsonRpcTransport.ts +247 -0
  170. package/src/execution/engine/restHttpClient.ts +269 -0
  171. package/src/execution/engine/restTransport.ts +575 -0
  172. package/src/execution/engine/sszTypes.ts +354 -0
  173. package/src/execution/engine/transport.ts +61 -0
  174. package/src/execution/engine/transportMetrics.ts +2 -1
  175. package/src/execution/engine/types.ts +42 -80
  176. package/src/execution/engine/utils.ts +12 -2
  177. package/src/metrics/metrics/lodestar.ts +12 -1
  178. package/src/network/core/events.ts +16 -1
  179. package/src/network/processor/gossipHandlers.ts +1 -1
  180. package/src/network/processor/index.ts +3 -3
  181. package/src/network/reqresp/rateLimit.ts +2 -2
  182. package/src/network/subnets/attnetsService.ts +8 -3
  183. package/src/node/notifier.ts +14 -13
  184. package/src/node/options.ts +10 -1
  185. package/src/sync/unknownBlock.ts +3 -2
  186. package/src/util/asyncIterableToEvents.ts +44 -5
  187. package/src/util/clock.ts +3 -4
  188. package/src/util/sszBytes.ts +25 -12
@@ -0,0 +1,354 @@
1
+ import {
2
+ BitVectorType,
3
+ ByteListType,
4
+ CompositeType,
5
+ CompositeView,
6
+ CompositeViewDU,
7
+ ContainerType,
8
+ ListCompositeType,
9
+ ValueOf,
10
+ } from "@chainsafe/ssz";
11
+ import {CELLS_PER_EXT_BLOB, ForkName, ForkPostBellatrix, MAX_BYTES_PER_TRANSACTION} from "@lodestar/params";
12
+ import {ssz} from "@lodestar/types";
13
+
14
+ /**
15
+ * SSZ containers of the REST engine API, per execution-apis `src/engine/refactor-ssz.md`
16
+ * at 5bcdc34a477b10af278c079525374e6a4046f291.
17
+ *
18
+ * Execution payloads, withdrawals and blobs bundles are shared with the consensus types since
19
+ * they serialize identically. Everything else is transport-only and therefore defined here.
20
+ */
21
+
22
+ const MAX_EXECUTION_REQUESTS_PER_PAYLOAD = 256;
23
+ const MAX_BYTES_PER_EXECUTION_REQUEST = MAX_BYTES_PER_TRANSACTION;
24
+ const MAX_BAL_BYTES = MAX_BYTES_PER_TRANSACTION;
25
+ const MAX_ERROR_BYTES = 1024;
26
+ export const MAX_BODIES_REQUEST = 32;
27
+ export const MAX_BLOBS_REQUEST = 128;
28
+
29
+ /** `Optional[T]` is `List[T, 1]` on the wire, the ssz library's `OptionalType` is a different encoding */
30
+ function Optional<T extends CompositeType<ValueOf<T>, CompositeView<T>, CompositeViewDU<T>>>(
31
+ type: T
32
+ ): ListCompositeType<T> {
33
+ return new ListCompositeType(type, 1);
34
+ }
35
+
36
+ const {Bytes8, Bytes32, Bytes48, ExecutionAddress, Root, Uint8, UintBn64, UintBn256, UintNum64} = ssz;
37
+
38
+ const ExecutionRequestsList = new ListCompositeType(
39
+ new ByteListType(MAX_BYTES_PER_EXECUTION_REQUEST),
40
+ MAX_EXECUTION_REQUESTS_PER_PAYLOAD
41
+ );
42
+
43
+ export const PayloadStatus = new ContainerType(
44
+ {
45
+ status: Uint8,
46
+ latestValidHash: Optional(Bytes32),
47
+ validationError: Optional(new ByteListType(MAX_ERROR_BYTES)),
48
+ },
49
+ {typeName: "PayloadStatus"}
50
+ );
51
+
52
+ export const ForkchoiceState = new ContainerType(
53
+ {
54
+ headBlockHash: Bytes32,
55
+ safeBlockHash: Bytes32,
56
+ finalizedBlockHash: Bytes32,
57
+ },
58
+ {typeName: "ForkchoiceState"}
59
+ );
60
+
61
+ export const ForkchoiceUpdateResponse = new ContainerType(
62
+ {
63
+ payloadStatus: PayloadStatus,
64
+ payloadId: Optional(Bytes8),
65
+ },
66
+ {typeName: "ForkchoiceUpdateResponse"}
67
+ );
68
+
69
+ export const PayloadAttributesBellatrix = new ContainerType(
70
+ {
71
+ timestamp: UintNum64,
72
+ prevRandao: Bytes32,
73
+ suggestedFeeRecipient: ExecutionAddress,
74
+ },
75
+ {typeName: "PayloadAttributes"}
76
+ );
77
+
78
+ export const PayloadAttributesCapella = new ContainerType(
79
+ {
80
+ ...PayloadAttributesBellatrix.fields,
81
+ withdrawals: ssz.capella.Withdrawals,
82
+ },
83
+ {typeName: "PayloadAttributes"}
84
+ );
85
+
86
+ export const PayloadAttributesDeneb = new ContainerType(
87
+ {
88
+ ...PayloadAttributesCapella.fields,
89
+ parentBeaconBlockRoot: Root,
90
+ },
91
+ {typeName: "PayloadAttributes"}
92
+ );
93
+
94
+ export const PayloadAttributesGloas = new ContainerType(
95
+ {
96
+ ...PayloadAttributesDeneb.fields,
97
+ slotNumber: UintNum64,
98
+ targetGasLimit: UintBn64,
99
+ },
100
+ {typeName: "PayloadAttributes"}
101
+ );
102
+
103
+ const CustodyColumns = new BitVectorType(CELLS_PER_EXT_BLOB);
104
+
105
+ function ForkchoiceUpdateType<T extends CompositeType<ValueOf<T>, CompositeView<T>, CompositeViewDU<T>>>(
106
+ payloadAttributes: T
107
+ ) {
108
+ return new ContainerType(
109
+ {
110
+ forkchoiceState: ForkchoiceState,
111
+ payloadAttributes: Optional(payloadAttributes),
112
+ },
113
+ {typeName: "ForkchoiceUpdate"}
114
+ );
115
+ }
116
+
117
+ export const ForkchoiceUpdateBellatrix = ForkchoiceUpdateType(PayloadAttributesBellatrix);
118
+ export const ForkchoiceUpdateCapella = ForkchoiceUpdateType(PayloadAttributesCapella);
119
+ export const ForkchoiceUpdateDeneb = ForkchoiceUpdateType(PayloadAttributesDeneb);
120
+ export const ForkchoiceUpdateGloas = new ContainerType(
121
+ {
122
+ ...ForkchoiceUpdateType(PayloadAttributesGloas).fields,
123
+ custodyColumns: Optional(CustodyColumns),
124
+ },
125
+ {typeName: "ForkchoiceUpdate"}
126
+ );
127
+
128
+ export const ExecutionPayloadEnvelopeBellatrix = new ContainerType(
129
+ {payload: ssz.bellatrix.ExecutionPayload},
130
+ {typeName: "ExecutionPayloadEnvelope"}
131
+ );
132
+ export const ExecutionPayloadEnvelopeCapella = new ContainerType(
133
+ {payload: ssz.capella.ExecutionPayload},
134
+ {typeName: "ExecutionPayloadEnvelope"}
135
+ );
136
+ export const ExecutionPayloadEnvelopeDeneb = new ContainerType(
137
+ {
138
+ payload: ssz.deneb.ExecutionPayload,
139
+ parentBeaconBlockRoot: Root,
140
+ },
141
+ {typeName: "ExecutionPayloadEnvelope"}
142
+ );
143
+ export const ExecutionPayloadEnvelopeElectra = new ContainerType(
144
+ {
145
+ payload: ssz.electra.ExecutionPayload,
146
+ parentBeaconBlockRoot: Root,
147
+ executionRequests: ExecutionRequestsList,
148
+ },
149
+ {typeName: "ExecutionPayloadEnvelope"}
150
+ );
151
+ export const ExecutionPayloadEnvelopeGloas = new ContainerType(
152
+ {
153
+ payload: ssz.gloas.ExecutionPayload,
154
+ parentBeaconBlockRoot: Root,
155
+ executionRequests: ExecutionRequestsList,
156
+ },
157
+ {typeName: "ExecutionPayloadEnvelope"}
158
+ );
159
+
160
+ export const BuiltPayloadBellatrix = new ContainerType(
161
+ {
162
+ payload: ssz.bellatrix.ExecutionPayload,
163
+ blockValue: UintBn256,
164
+ },
165
+ {typeName: "BuiltPayload"}
166
+ );
167
+ export const BuiltPayloadCapella = new ContainerType(
168
+ {
169
+ payload: ssz.capella.ExecutionPayload,
170
+ blockValue: UintBn256,
171
+ },
172
+ {typeName: "BuiltPayload"}
173
+ );
174
+ export const BuiltPayloadDeneb = new ContainerType(
175
+ {
176
+ payload: ssz.deneb.ExecutionPayload,
177
+ blockValue: UintBn256,
178
+ blobsBundle: ssz.deneb.BlobsBundle,
179
+ shouldOverrideBuilder: ssz.Boolean,
180
+ },
181
+ {typeName: "BuiltPayload"}
182
+ );
183
+ export const BuiltPayloadElectra = new ContainerType(
184
+ {
185
+ payload: ssz.electra.ExecutionPayload,
186
+ blockValue: UintBn256,
187
+ blobsBundle: ssz.deneb.BlobsBundle,
188
+ executionRequests: ExecutionRequestsList,
189
+ shouldOverrideBuilder: ssz.Boolean,
190
+ },
191
+ {typeName: "BuiltPayload"}
192
+ );
193
+ export const BuiltPayloadFulu = new ContainerType(
194
+ {
195
+ payload: ssz.fulu.ExecutionPayload,
196
+ blockValue: UintBn256,
197
+ blobsBundle: ssz.fulu.BlobsBundle,
198
+ executionRequests: ExecutionRequestsList,
199
+ shouldOverrideBuilder: ssz.Boolean,
200
+ },
201
+ {typeName: "BuiltPayload"}
202
+ );
203
+ export const BuiltPayloadGloas = new ContainerType(
204
+ {
205
+ payload: ssz.gloas.ExecutionPayload,
206
+ blockValue: UintBn256,
207
+ blobsBundle: ssz.fulu.BlobsBundle,
208
+ executionRequests: ExecutionRequestsList,
209
+ shouldOverrideBuilder: ssz.Boolean,
210
+ },
211
+ {typeName: "BuiltPayload"}
212
+ );
213
+
214
+ export const ExecutionPayloadBodyBellatrix = new ContainerType(
215
+ {transactions: ssz.bellatrix.Transactions},
216
+ {typeName: "ExecutionPayloadBody"}
217
+ );
218
+ export const ExecutionPayloadBodyCapella = new ContainerType(
219
+ {
220
+ transactions: ssz.bellatrix.Transactions,
221
+ withdrawals: ssz.capella.Withdrawals,
222
+ },
223
+ {typeName: "ExecutionPayloadBody"}
224
+ );
225
+ export const ExecutionPayloadBodyGloas = new ContainerType(
226
+ {
227
+ transactions: ssz.bellatrix.Transactions,
228
+ withdrawals: ssz.capella.Withdrawals,
229
+ blockAccessList: new ByteListType(MAX_BAL_BYTES),
230
+ },
231
+ {typeName: "ExecutionPayloadBody"}
232
+ );
233
+
234
+ function BodiesResponseType<T extends CompositeType<ValueOf<T>, CompositeView<T>, CompositeViewDU<T>>>(body: T) {
235
+ const BodyEntry = new ContainerType({available: ssz.Boolean, body}, {typeName: "BodyEntry"});
236
+ return new ContainerType(
237
+ {entries: new ListCompositeType(BodyEntry, MAX_BODIES_REQUEST)},
238
+ {typeName: "BodiesResponse"}
239
+ );
240
+ }
241
+
242
+ export const BodiesResponseBellatrix = BodiesResponseType(ExecutionPayloadBodyBellatrix);
243
+ export const BodiesResponseCapella = BodiesResponseType(ExecutionPayloadBodyCapella);
244
+ export const BodiesResponseGloas = BodiesResponseType(ExecutionPayloadBodyGloas);
245
+
246
+ export const BodiesByHashRequest = new ContainerType(
247
+ {blockHashes: new ListCompositeType(Bytes32, MAX_BODIES_REQUEST)},
248
+ {typeName: "BodiesByHashRequest"}
249
+ );
250
+
251
+ export const BlobsRequest = new ContainerType(
252
+ {versionedHashes: new ListCompositeType(Bytes32, MAX_BLOBS_REQUEST)},
253
+ {typeName: "BlobsRequest"}
254
+ );
255
+
256
+ const BlobAndProofV1 = new ContainerType(
257
+ {
258
+ blob: ssz.deneb.Blob,
259
+ proof: Bytes48,
260
+ },
261
+ {typeName: "BlobAndProofV1"}
262
+ );
263
+
264
+ const BlobAndProofV2 = new ContainerType(
265
+ {
266
+ blob: ssz.deneb.Blob,
267
+ proofs: new ListCompositeType(Bytes48, CELLS_PER_EXT_BLOB),
268
+ },
269
+ {typeName: "BlobAndProofV2"}
270
+ );
271
+
272
+ function BlobsResponseType<T extends CompositeType<ValueOf<T>, CompositeView<T>, CompositeViewDU<T>>>(contents: T) {
273
+ const BlobEntry = new ContainerType({available: ssz.Boolean, contents}, {typeName: "BlobEntry"});
274
+ return new ContainerType({entries: new ListCompositeType(BlobEntry, MAX_BLOBS_REQUEST)}, {typeName: "BlobsResponse"});
275
+ }
276
+
277
+ export const BlobsV1Response = BlobsResponseType(BlobAndProofV1);
278
+ export const BlobsV2Response = BlobsResponseType(BlobAndProofV2);
279
+
280
+ const bellatrix = {
281
+ PayloadAttributes: PayloadAttributesBellatrix,
282
+ ForkchoiceUpdate: ForkchoiceUpdateBellatrix,
283
+ ExecutionPayloadEnvelope: ExecutionPayloadEnvelopeBellatrix,
284
+ BuiltPayload: BuiltPayloadBellatrix,
285
+ BodiesResponse: BodiesResponseBellatrix,
286
+ };
287
+
288
+ const capella = {
289
+ PayloadAttributes: PayloadAttributesCapella,
290
+ ForkchoiceUpdate: ForkchoiceUpdateCapella,
291
+ ExecutionPayloadEnvelope: ExecutionPayloadEnvelopeCapella,
292
+ BuiltPayload: BuiltPayloadCapella,
293
+ BodiesResponse: BodiesResponseCapella,
294
+ };
295
+
296
+ const deneb = {
297
+ PayloadAttributes: PayloadAttributesDeneb,
298
+ ForkchoiceUpdate: ForkchoiceUpdateDeneb,
299
+ ExecutionPayloadEnvelope: ExecutionPayloadEnvelopeDeneb,
300
+ BuiltPayload: BuiltPayloadDeneb,
301
+ BodiesResponse: BodiesResponseCapella,
302
+ };
303
+
304
+ const electra = {
305
+ ...deneb,
306
+ ExecutionPayloadEnvelope: ExecutionPayloadEnvelopeElectra,
307
+ BuiltPayload: BuiltPayloadElectra,
308
+ };
309
+
310
+ const fulu = {
311
+ ...electra,
312
+ BuiltPayload: BuiltPayloadFulu,
313
+ };
314
+
315
+ const gloas = {
316
+ PayloadAttributes: PayloadAttributesGloas,
317
+ ForkchoiceUpdate: ForkchoiceUpdateGloas,
318
+ ExecutionPayloadEnvelope: ExecutionPayloadEnvelopeGloas,
319
+ BuiltPayload: BuiltPayloadGloas,
320
+ BodiesResponse: BodiesResponseGloas,
321
+ };
322
+
323
+ export const engineSszTypes = {
324
+ [ForkName.bellatrix]: bellatrix,
325
+ [ForkName.capella]: capella,
326
+ [ForkName.deneb]: deneb,
327
+ [ForkName.electra]: electra,
328
+ [ForkName.fulu]: fulu,
329
+ [ForkName.gloas]: gloas,
330
+ [ForkName.heze]: gloas,
331
+ };
332
+
333
+ export type PayloadStatusSsz = ValueOf<typeof PayloadStatus>;
334
+
335
+ /** Fork names accepted in the `Eth-Execution-Version` header */
336
+ export type ExecutionForkName = "paris" | "shanghai" | "cancun" | "prague" | "osaka" | "amsterdam";
337
+
338
+ /** Heze has no execution fork name in the spec yet, auto mode serves it over JSON-RPC and ssz mode fails the call */
339
+ export const executionForkName: Record<ForkPostBellatrix, ExecutionForkName | null> = {
340
+ [ForkName.bellatrix]: "paris",
341
+ [ForkName.capella]: "shanghai",
342
+ [ForkName.deneb]: "cancun",
343
+ [ForkName.electra]: "prague",
344
+ [ForkName.fulu]: "osaka",
345
+ [ForkName.gloas]: "amsterdam",
346
+ [ForkName.heze]: null,
347
+ };
348
+
349
+ export enum PayloadStatusCode {
350
+ VALID = 0,
351
+ INVALID = 1,
352
+ SYNCING = 2,
353
+ ACCEPTED = 3,
354
+ }
@@ -0,0 +1,61 @@
1
+ import {ForkName} from "@lodestar/params";
2
+ import {BlobsBundle, ExecutionPayload, ExecutionRequests, Root, RootHex, Wei} from "@lodestar/types";
3
+ import {BlobAndProof} from "@lodestar/types/deneb";
4
+ import {BlobAndProofV2} from "@lodestar/types/fulu";
5
+ import {ClientVersion, ExecutionPayloadStatus, PayloadAttributes, PayloadId, VersionedHashes} from "./interface.js";
6
+ import {JsonRpcHttpClientEventEmitter} from "./jsonRpcHttpClient.js";
7
+ import {ExecutionPayloadBodyV2} from "./types.js";
8
+
9
+ export type PayloadStatusResult = {
10
+ status: ExecutionPayloadStatus;
11
+ latestValidHash: RootHex | null;
12
+ validationError: string | null;
13
+ };
14
+
15
+ export type ForkchoiceUpdatedResult = {
16
+ payloadStatus: PayloadStatusResult;
17
+ payloadId: PayloadId | null;
18
+ };
19
+
20
+ export type GetPayloadResult = {
21
+ executionPayload: ExecutionPayload;
22
+ executionPayloadValue: Wei;
23
+ blobsBundle?: BlobsBundle;
24
+ executionRequests?: ExecutionRequests;
25
+ shouldOverrideBuilder?: boolean;
26
+ };
27
+
28
+ /**
29
+ * Wire-level access to the engine API of the execution client. Implementations only translate
30
+ * between Lodestar types and the encoding of their transport, `ExecutionEngineHttp` owns request
31
+ * ordering, engine state and result interpretation.
32
+ */
33
+ export interface IEngineTransport {
34
+ readonly emitter: JsonRpcHttpClientEventEmitter;
35
+
36
+ newPayload(
37
+ fork: ForkName,
38
+ executionPayload: ExecutionPayload,
39
+ versionedHashes?: VersionedHashes,
40
+ parentBeaconBlockRoot?: Root,
41
+ executionRequests?: ExecutionRequests
42
+ ): Promise<PayloadStatusResult>;
43
+
44
+ forkchoiceUpdated(
45
+ fork: ForkName,
46
+ headBlockHash: RootHex,
47
+ safeBlockHash: RootHex,
48
+ finalizedBlockHash: RootHex,
49
+ payloadAttributes?: PayloadAttributes
50
+ ): Promise<ForkchoiceUpdatedResult>;
51
+
52
+ getPayload(fork: ForkName, payloadId: PayloadId): Promise<GetPayloadResult>;
53
+
54
+ getPayloadBodiesByHashV2(blockHashes: RootHex[]): Promise<(ExecutionPayloadBodyV2 | null)[]>;
55
+
56
+ getBlobsV1(versionedHashes: VersionedHashes): Promise<(BlobAndProof | null)[]>;
57
+
58
+ getBlobsV2(versionedHashes: VersionedHashes, buffers?: Uint8Array[]): Promise<BlobAndProofV2[] | null>;
59
+
60
+ getClientVersion(clientVersion: ClientVersion): Promise<ClientVersion[]>;
61
+ }
@@ -1,4 +1,4 @@
1
- import {Counter} from "@lodestar/utils";
1
+ import {Counter, Histogram} from "@lodestar/utils";
2
2
 
3
3
  /**
4
4
  * Common metrics type for both json rpc and ssz transport.
@@ -6,4 +6,5 @@ import {Counter} from "@lodestar/utils";
6
6
  export type EngineTransportMetrics = {
7
7
  requestBytes: Counter<{routeId: string}>;
8
8
  responseBytes: Counter<{routeId: string}>;
9
+ responseParseTime: Histogram<{routeId: string; encoding: "json" | "ssz"}>;
9
10
  };
@@ -1,3 +1,4 @@
1
+ import {Type} from "@chainsafe/ssz";
1
2
  import {
2
3
  BUILDER_DEPOSIT_REQUEST_TYPE,
3
4
  BUILDER_EXIT_REQUEST_TYPE,
@@ -20,7 +21,6 @@ import {
20
21
  bellatrix,
21
22
  capella,
22
23
  deneb,
23
- electra,
24
24
  gloas,
25
25
  ssz,
26
26
  } from "@lodestar/types";
@@ -501,63 +501,15 @@ export function deserializeWithdrawal(serialized: WithdrawalRpc): capella.Withdr
501
501
  }
502
502
 
503
503
  /**
504
- * Prepend a single-byte requestType to requestsBytes
504
+ * Serialize requests prefixed with a single-byte requestType in one allocation
505
505
  */
506
- function prefixRequests(requestsBytes: Uint8Array, requestType: ExecutionRequestType): Uint8Array {
507
- const prefixedRequests = new Uint8Array(1 + requestsBytes.length);
508
- prefixedRequests[0] = requestType;
509
- prefixedRequests.set(requestsBytes, 1);
506
+ function serializePrefixedRequests<T>(type: Type<T>, requests: T, requestType: ExecutionRequestType): Uint8Array {
507
+ const uint8Array = new Uint8Array(1 + type.value_serializedSize(requests));
508
+ const dataView = new DataView(uint8Array.buffer, uint8Array.byteOffset, uint8Array.byteLength);
509
+ uint8Array[0] = requestType;
510
+ type.value_serializeToBytes({uint8Array, dataView}, 1, requests);
510
511
 
511
- return prefixedRequests;
512
- }
513
-
514
- function serializeDepositRequests(depositRequests: electra.DepositRequests): DepositRequestsRpc {
515
- const requestsBytes = ssz.electra.DepositRequests.serialize(depositRequests);
516
- return bytesToData(prefixRequests(requestsBytes, DEPOSIT_REQUEST_TYPE));
517
- }
518
-
519
- function deserializeDepositRequests(serialized: DepositRequestsRpc): electra.DepositRequests {
520
- return ssz.electra.DepositRequests.deserialize(dataToBytes(serialized, null));
521
- }
522
-
523
- function serializeWithdrawalRequests(withdrawalRequests: electra.WithdrawalRequests): WithdrawalRequestsRpc {
524
- const requestsBytes = ssz.electra.WithdrawalRequests.serialize(withdrawalRequests);
525
- return bytesToData(prefixRequests(requestsBytes, WITHDRAWAL_REQUEST_TYPE));
526
- }
527
-
528
- function deserializeWithdrawalRequests(serialized: WithdrawalRequestsRpc): electra.WithdrawalRequests {
529
- return ssz.electra.WithdrawalRequests.deserialize(dataToBytes(serialized, null));
530
- }
531
-
532
- function serializeConsolidationRequests(
533
- consolidationRequests: electra.ConsolidationRequests
534
- ): ConsolidationRequestsRpc {
535
- const requestsBytes = ssz.electra.ConsolidationRequests.serialize(consolidationRequests);
536
- return bytesToData(prefixRequests(requestsBytes, CONSOLIDATION_REQUEST_TYPE));
537
- }
538
-
539
- function deserializeConsolidationRequests(serialized: ConsolidationRequestsRpc): electra.ConsolidationRequests {
540
- return ssz.electra.ConsolidationRequests.deserialize(dataToBytes(serialized, null));
541
- }
542
-
543
- function serializeBuilderDepositRequests(
544
- builderDepositRequests: gloas.BuilderDepositRequests
545
- ): BuilderDepositRequestsRpc {
546
- const requestsBytes = ssz.gloas.BuilderDepositRequests.serialize(builderDepositRequests);
547
- return bytesToData(prefixRequests(requestsBytes, BUILDER_DEPOSIT_REQUEST_TYPE));
548
- }
549
-
550
- function deserializeBuilderDepositRequests(serialized: BuilderDepositRequestsRpc): gloas.BuilderDepositRequests {
551
- return ssz.gloas.BuilderDepositRequests.deserialize(dataToBytes(serialized, null));
552
- }
553
-
554
- function serializeBuilderExitRequests(builderExitRequests: gloas.BuilderExitRequests): BuilderExitRequestsRpc {
555
- const requestsBytes = ssz.gloas.BuilderExitRequests.serialize(builderExitRequests);
556
- return bytesToData(prefixRequests(requestsBytes, BUILDER_EXIT_REQUEST_TYPE));
557
- }
558
-
559
- function deserializeBuilderExitRequests(serialized: BuilderExitRequestsRpc): gloas.BuilderExitRequests {
560
- return ssz.gloas.BuilderExitRequests.deserialize(dataToBytes(serialized, null));
512
+ return uint8Array;
561
513
  }
562
514
 
563
515
  /**
@@ -567,62 +519,65 @@ function deserializeBuilderExitRequests(serialized: BuilderExitRequestsRpc): glo
567
519
  * Gloas extends the list with builder deposits (0x03) and builder exits (0x04) per
568
520
  * https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.11/specs/gloas/beacon-chain.md#modified-get_execution_requests_list
569
521
  */
570
- export function serializeExecutionRequests(fork: ForkName, executionRequests: ExecutionRequests): ExecutionRequestsRpc {
522
+ export function serializeExecutionRequestsToBytes(fork: ForkName, executionRequests: ExecutionRequests): Uint8Array[] {
571
523
  const {deposits, withdrawals, consolidations} = executionRequests;
572
- const result: ExecutionRequestsRpc = [];
524
+ const result: Uint8Array[] = [];
573
525
 
574
526
  if (deposits.length !== 0) {
575
- result.push(serializeDepositRequests(deposits));
527
+ result.push(serializePrefixedRequests(ssz.electra.DepositRequests, deposits, DEPOSIT_REQUEST_TYPE));
576
528
  }
577
529
 
578
530
  if (withdrawals.length !== 0) {
579
- result.push(serializeWithdrawalRequests(withdrawals));
531
+ result.push(serializePrefixedRequests(ssz.electra.WithdrawalRequests, withdrawals, WITHDRAWAL_REQUEST_TYPE));
580
532
  }
581
533
 
582
534
  if (consolidations.length !== 0) {
583
- result.push(serializeConsolidationRequests(consolidations));
535
+ result.push(
536
+ serializePrefixedRequests(ssz.electra.ConsolidationRequests, consolidations, CONSOLIDATION_REQUEST_TYPE)
537
+ );
584
538
  }
585
539
 
586
540
  if (ForkSeq[fork] >= ForkSeq.gloas) {
587
541
  const {builderDeposits, builderExits} = executionRequests as gloas.ExecutionRequests;
588
542
 
589
543
  if (builderDeposits.length !== 0) {
590
- result.push(serializeBuilderDepositRequests(builderDeposits));
544
+ result.push(
545
+ serializePrefixedRequests(ssz.gloas.BuilderDepositRequests, builderDeposits, BUILDER_DEPOSIT_REQUEST_TYPE)
546
+ );
591
547
  }
592
548
 
593
549
  if (builderExits.length !== 0) {
594
- result.push(serializeBuilderExitRequests(builderExits));
550
+ result.push(serializePrefixedRequests(ssz.gloas.BuilderExitRequests, builderExits, BUILDER_EXIT_REQUEST_TYPE));
595
551
  }
596
552
  }
597
553
 
598
554
  return result;
599
555
  }
600
556
 
601
- export function deserializeExecutionRequests(fork: ForkName, serialized: ExecutionRequestsRpc): ExecutionRequests {
557
+ export function serializeExecutionRequests(fork: ForkName, executionRequests: ExecutionRequests): ExecutionRequestsRpc {
558
+ return serializeExecutionRequestsToBytes(fork, executionRequests).map(bytesToData);
559
+ }
560
+
561
+ export function deserializeExecutionRequestsFromBytes(fork: ForkName, serialized: Uint8Array[]): ExecutionRequests {
602
562
  const result: ExecutionRequests =
603
563
  ForkSeq[fork] >= ForkSeq.gloas
604
564
  ? {deposits: [], withdrawals: [], consolidations: [], builderDeposits: [], builderExits: []}
605
565
  : {deposits: [], withdrawals: [], consolidations: []};
606
566
 
607
- if (serialized.length === 0) {
608
- return result;
609
- }
610
-
611
567
  let prevRequestType: ExecutionRequestType | undefined;
612
568
 
613
- for (let prefixedRequests of serialized) {
614
- // Slice out 0x so it is easier to extract request type
615
- if (prefixedRequests.startsWith("0x")) {
616
- prefixedRequests = prefixedRequests.slice(2);
569
+ for (const prefixedRequests of serialized) {
570
+ if (prefixedRequests.length === 0) {
571
+ throw Error("Invalid request type, request must be prefixed with its type");
617
572
  }
618
573
 
619
- const currentRequestType = parseInt(prefixedRequests.substring(0, 2), 16);
574
+ const currentRequestType = prefixedRequests[0];
620
575
 
621
576
  if (!isExecutionRequestType(currentRequestType)) {
622
- throw Error(`Invalid request type currentRequestType=${prefixedRequests.substring(0, 2)}`);
577
+ throw Error(`Invalid request type currentRequestType=${currentRequestType}`);
623
578
  }
624
579
 
625
- const requests = prefixedRequests.slice(2);
580
+ const requests = prefixedRequests.subarray(1);
626
581
 
627
582
  if (requests.length === 0) {
628
583
  throw Error(
@@ -638,29 +593,29 @@ export function deserializeExecutionRequests(fork: ForkName, serialized: Executi
638
593
 
639
594
  switch (currentRequestType) {
640
595
  case DEPOSIT_REQUEST_TYPE: {
641
- result.deposits = deserializeDepositRequests(requests);
596
+ result.deposits = ssz.electra.DepositRequests.deserialize(requests);
642
597
  break;
643
598
  }
644
599
  case WITHDRAWAL_REQUEST_TYPE: {
645
- result.withdrawals = deserializeWithdrawalRequests(requests);
600
+ result.withdrawals = ssz.electra.WithdrawalRequests.deserialize(requests);
646
601
  break;
647
602
  }
648
603
  case CONSOLIDATION_REQUEST_TYPE: {
649
- result.consolidations = deserializeConsolidationRequests(requests);
604
+ result.consolidations = ssz.electra.ConsolidationRequests.deserialize(requests);
650
605
  break;
651
606
  }
652
607
  case BUILDER_DEPOSIT_REQUEST_TYPE: {
653
608
  if (ForkSeq[fork] < ForkSeq.gloas) {
654
609
  throw Error(`Builder deposit request is not supported pre-gloas fork=${fork}`);
655
610
  }
656
- (result as gloas.ExecutionRequests).builderDeposits = deserializeBuilderDepositRequests(requests);
611
+ (result as gloas.ExecutionRequests).builderDeposits = ssz.gloas.BuilderDepositRequests.deserialize(requests);
657
612
  break;
658
613
  }
659
614
  case BUILDER_EXIT_REQUEST_TYPE: {
660
615
  if (ForkSeq[fork] < ForkSeq.gloas) {
661
616
  throw Error(`Builder exit request is not supported pre-gloas fork=${fork}`);
662
617
  }
663
- (result as gloas.ExecutionRequests).builderExits = deserializeBuilderExitRequests(requests);
618
+ (result as gloas.ExecutionRequests).builderExits = ssz.gloas.BuilderExitRequests.deserialize(requests);
664
619
  break;
665
620
  }
666
621
  }
@@ -670,6 +625,13 @@ export function deserializeExecutionRequests(fork: ForkName, serialized: Executi
670
625
  return result;
671
626
  }
672
627
 
628
+ export function deserializeExecutionRequests(fork: ForkName, serialized: ExecutionRequestsRpc): ExecutionRequests {
629
+ return deserializeExecutionRequestsFromBytes(
630
+ fork,
631
+ serialized.map((data) => dataToBytes(data, null))
632
+ );
633
+ }
634
+
673
635
  export function deserializeExecutionPayloadBody(data: ExecutionPayloadBodyRpc | null): ExecutionPayloadBody | null {
674
636
  return data
675
637
  ? {
@@ -8,6 +8,7 @@ import {
8
8
  JsonRpcHttpClientEvent,
9
9
  JsonRpcHttpClientEventEmitter,
10
10
  } from "./jsonRpcHttpClient.js";
11
+ import {EngineRestError, EngineRestResponseError} from "./restHttpClient.js";
11
12
 
12
13
  /** QUANTITY as defined in ethereum execution layer JSON RPC https://eth.wiki/json-rpc/API */
13
14
  export type QUANTITY = string;
@@ -191,12 +192,21 @@ function getExecutionEngineStateForPayloadError(
191
192
  return oldState;
192
193
  }
193
194
 
195
+ if (payloadError instanceof EngineRestError && (payloadError.status === 401 || payloadError.status === 403)) {
196
+ return ExecutionEngineState.AUTH_FAILED;
197
+ }
198
+
194
199
  // Originally this case was handled with {status: ExecutePayloadStatus.ELERROR}
195
- if (payloadError instanceof HttpRpcError || payloadError instanceof ErrorJsonRpcResponse) {
200
+ if (
201
+ payloadError instanceof HttpRpcError ||
202
+ payloadError instanceof ErrorJsonRpcResponse ||
203
+ payloadError instanceof EngineRestError ||
204
+ payloadError instanceof EngineRestResponseError
205
+ ) {
196
206
  return ExecutionEngineState.SYNCING;
197
207
  }
198
208
 
199
- if (payloadError && isFetchError(payloadError) && HTTP_FATAL_ERROR_CODES.includes(payloadError.code)) {
209
+ if (isFetchError(payloadError) && HTTP_FATAL_ERROR_CODES.includes(payloadError.code)) {
200
210
  return ExecutionEngineState.OFFLINE;
201
211
  }
202
212