@lodestar/beacon-node 1.42.0-dev.b10dfaca8d → 1.42.0-dev.bc0be71fb0

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 (203) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +24 -12
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/debug/index.js.map +1 -1
  5. package/lib/chain/ColumnReconstructionTracker.d.ts +2 -1
  6. package/lib/chain/ColumnReconstructionTracker.d.ts.map +1 -1
  7. package/lib/chain/ColumnReconstructionTracker.js +5 -5
  8. package/lib/chain/ColumnReconstructionTracker.js.map +1 -1
  9. package/lib/chain/GetBlobsTracker.d.ts +2 -1
  10. package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
  11. package/lib/chain/GetBlobsTracker.js +14 -12
  12. package/lib/chain/GetBlobsTracker.js.map +1 -1
  13. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  14. package/lib/chain/archiveStore/archiveStore.js +1 -0
  15. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  16. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts +3 -3
  17. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
  18. package/lib/chain/archiveStore/historicalState/getHistoricalState.js +6 -4
  19. package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
  20. package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts +2 -2
  21. package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts.map +1 -1
  22. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -0
  23. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
  24. package/lib/chain/archiveStore/historicalState/types.d.ts +2 -0
  25. package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
  26. package/lib/chain/archiveStore/historicalState/types.js.map +1 -1
  27. package/lib/chain/archiveStore/historicalState/worker.js +1 -4
  28. package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
  29. package/lib/chain/archiveStore/interface.d.ts +1 -0
  30. package/lib/chain/archiveStore/interface.d.ts.map +1 -1
  31. package/lib/chain/blocks/blockInput/blockInput.d.ts +5 -5
  32. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  33. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  34. package/lib/chain/blocks/blockInput/types.d.ts +4 -4
  35. package/lib/chain/blocks/blockInput/types.d.ts.map +1 -1
  36. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  37. package/lib/chain/blocks/importBlock.js +30 -18
  38. package/lib/chain/blocks/importBlock.js.map +1 -1
  39. package/lib/chain/blocks/importExecutionPayload.d.ts +10 -8
  40. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  41. package/lib/chain/blocks/importExecutionPayload.js +76 -48
  42. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  43. package/lib/chain/blocks/index.d.ts.map +1 -1
  44. package/lib/chain/blocks/index.js +2 -1
  45. package/lib/chain/blocks/index.js.map +1 -1
  46. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +14 -6
  47. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
  48. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +33 -2
  49. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
  50. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +2 -1
  51. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
  52. package/lib/chain/blocks/types.d.ts +20 -14
  53. package/lib/chain/blocks/types.d.ts.map +1 -1
  54. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +2 -2
  55. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  56. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +1 -1
  57. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  58. package/lib/chain/chain.d.ts +3 -2
  59. package/lib/chain/chain.d.ts.map +1 -1
  60. package/lib/chain/chain.js +55 -20
  61. package/lib/chain/chain.js.map +1 -1
  62. package/lib/chain/emitter.d.ts +29 -7
  63. package/lib/chain/emitter.d.ts.map +1 -1
  64. package/lib/chain/emitter.js +12 -3
  65. package/lib/chain/emitter.js.map +1 -1
  66. package/lib/chain/errors/dataColumnSidecarError.d.ts +31 -1
  67. package/lib/chain/errors/dataColumnSidecarError.d.ts.map +1 -1
  68. package/lib/chain/errors/dataColumnSidecarError.js +7 -0
  69. package/lib/chain/errors/dataColumnSidecarError.js.map +1 -1
  70. package/lib/chain/interface.d.ts +4 -2
  71. package/lib/chain/interface.d.ts.map +1 -1
  72. package/lib/chain/options.d.ts +1 -0
  73. package/lib/chain/options.d.ts.map +1 -1
  74. package/lib/chain/options.js +1 -0
  75. package/lib/chain/options.js.map +1 -1
  76. package/lib/chain/seenCache/seenGossipBlockInput.d.ts +1 -1
  77. package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
  78. package/lib/chain/seenCache/seenGossipBlockInput.js +2 -2
  79. package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
  80. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +1 -1
  81. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
  82. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +2 -2
  83. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
  84. package/lib/chain/validation/dataColumnSidecar.d.ts +11 -4
  85. package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
  86. package/lib/chain/validation/dataColumnSidecar.js +184 -5
  87. package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
  88. package/lib/db/buckets.d.ts +2 -2
  89. package/lib/db/buckets.d.ts.map +1 -1
  90. package/lib/db/buckets.js +2 -2
  91. package/lib/db/buckets.js.map +1 -1
  92. package/lib/db/repositories/blockArchiveIndex.d.ts +2 -2
  93. package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
  94. package/lib/db/repositories/dataColumnSidecar.d.ts.map +1 -1
  95. package/lib/db/repositories/dataColumnSidecar.js +4 -2
  96. package/lib/db/repositories/dataColumnSidecar.js.map +1 -1
  97. package/lib/db/repositories/dataColumnSidecarArchive.d.ts.map +1 -1
  98. package/lib/db/repositories/dataColumnSidecarArchive.js +4 -2
  99. package/lib/db/repositories/dataColumnSidecarArchive.js.map +1 -1
  100. package/lib/metrics/metrics/lodestar.d.ts +20 -0
  101. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  102. package/lib/metrics/metrics/lodestar.js +33 -0
  103. package/lib/metrics/metrics/lodestar.js.map +1 -1
  104. package/lib/network/interface.d.ts +3 -2
  105. package/lib/network/interface.d.ts.map +1 -1
  106. package/lib/network/libp2p/index.d.ts.map +1 -1
  107. package/lib/network/libp2p/index.js +22 -11
  108. package/lib/network/libp2p/index.js.map +1 -1
  109. package/lib/network/network.d.ts +3 -2
  110. package/lib/network/network.d.ts.map +1 -1
  111. package/lib/network/network.js +3 -0
  112. package/lib/network/network.js.map +1 -1
  113. package/lib/network/options.d.ts.map +1 -1
  114. package/lib/network/options.js +7 -2
  115. package/lib/network/options.js.map +1 -1
  116. package/lib/network/processor/extractSlotRootFns.d.ts +1 -1
  117. package/lib/network/processor/extractSlotRootFns.d.ts.map +1 -1
  118. package/lib/network/processor/extractSlotRootFns.js +25 -5
  119. package/lib/network/processor/extractSlotRootFns.js.map +1 -1
  120. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  121. package/lib/network/processor/gossipHandlers.js +256 -73
  122. package/lib/network/processor/gossipHandlers.js.map +1 -1
  123. package/lib/network/processor/index.d.ts +11 -1
  124. package/lib/network/processor/index.d.ts.map +1 -1
  125. package/lib/network/processor/index.js +234 -22
  126. package/lib/network/processor/index.js.map +1 -1
  127. package/lib/network/reqresp/types.d.ts +3 -3
  128. package/lib/network/reqresp/types.d.ts.map +1 -1
  129. package/lib/network/reqresp/types.js +9 -3
  130. package/lib/network/reqresp/types.js.map +1 -1
  131. package/lib/sync/unknownBlock.js +2 -2
  132. package/lib/sync/unknownBlock.js.map +1 -1
  133. package/lib/sync/utils/downloadByRange.d.ts +3 -3
  134. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  135. package/lib/sync/utils/downloadByRange.js +4 -2
  136. package/lib/sync/utils/downloadByRange.js.map +1 -1
  137. package/lib/sync/utils/downloadByRoot.d.ts +3 -3
  138. package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
  139. package/lib/sync/utils/downloadByRoot.js +10 -5
  140. package/lib/sync/utils/downloadByRoot.js.map +1 -1
  141. package/lib/util/blobs.d.ts +3 -3
  142. package/lib/util/blobs.d.ts.map +1 -1
  143. package/lib/util/blobs.js +21 -10
  144. package/lib/util/blobs.js.map +1 -1
  145. package/lib/util/dataColumns.d.ts +18 -11
  146. package/lib/util/dataColumns.d.ts.map +1 -1
  147. package/lib/util/dataColumns.js +51 -17
  148. package/lib/util/dataColumns.js.map +1 -1
  149. package/lib/util/execution.d.ts +6 -2
  150. package/lib/util/execution.d.ts.map +1 -1
  151. package/lib/util/execution.js +49 -25
  152. package/lib/util/execution.js.map +1 -1
  153. package/lib/util/sszBytes.d.ts +25 -1
  154. package/lib/util/sszBytes.d.ts.map +1 -1
  155. package/lib/util/sszBytes.js +189 -2
  156. package/lib/util/sszBytes.js.map +1 -1
  157. package/package.json +16 -16
  158. package/src/api/impl/beacon/blocks/index.ts +32 -15
  159. package/src/api/impl/debug/index.ts +2 -2
  160. package/src/chain/ColumnReconstructionTracker.ts +6 -5
  161. package/src/chain/GetBlobsTracker.ts +14 -12
  162. package/src/chain/archiveStore/archiveStore.ts +1 -0
  163. package/src/chain/archiveStore/historicalState/getHistoricalState.ts +6 -5
  164. package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +2 -1
  165. package/src/chain/archiveStore/historicalState/types.ts +2 -0
  166. package/src/chain/archiveStore/historicalState/worker.ts +1 -5
  167. package/src/chain/archiveStore/interface.ts +1 -0
  168. package/src/chain/blocks/blockInput/blockInput.ts +8 -8
  169. package/src/chain/blocks/blockInput/types.ts +4 -4
  170. package/src/chain/blocks/importBlock.ts +36 -18
  171. package/src/chain/blocks/importExecutionPayload.ts +84 -53
  172. package/src/chain/blocks/index.ts +2 -1
  173. package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +53 -12
  174. package/src/chain/blocks/payloadEnvelopeInput/types.ts +2 -1
  175. package/src/chain/blocks/types.ts +25 -14
  176. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +4 -4
  177. package/src/chain/chain.ts +63 -24
  178. package/src/chain/emitter.ts +25 -7
  179. package/src/chain/errors/dataColumnSidecarError.ts +32 -1
  180. package/src/chain/interface.ts +4 -2
  181. package/src/chain/options.ts +2 -0
  182. package/src/chain/seenCache/seenGossipBlockInput.ts +2 -2
  183. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +2 -2
  184. package/src/chain/validation/dataColumnSidecar.ts +230 -7
  185. package/src/db/buckets.ts +2 -2
  186. package/src/db/repositories/dataColumnSidecar.ts +4 -2
  187. package/src/db/repositories/dataColumnSidecarArchive.ts +4 -2
  188. package/src/metrics/metrics/lodestar.ts +34 -0
  189. package/src/network/interface.ts +3 -2
  190. package/src/network/libp2p/index.ts +24 -13
  191. package/src/network/network.ts +7 -4
  192. package/src/network/options.ts +7 -2
  193. package/src/network/processor/extractSlotRootFns.ts +32 -6
  194. package/src/network/processor/gossipHandlers.ts +320 -86
  195. package/src/network/processor/index.ts +304 -22
  196. package/src/network/reqresp/types.ts +13 -5
  197. package/src/sync/unknownBlock.ts +3 -3
  198. package/src/sync/utils/downloadByRange.ts +9 -7
  199. package/src/sync/utils/downloadByRoot.ts +16 -12
  200. package/src/util/blobs.ts +35 -15
  201. package/src/util/dataColumns.ts +69 -25
  202. package/src/util/execution.ts +49 -30
  203. package/src/util/sszBytes.ts +245 -3
@@ -17,6 +17,8 @@ export type BlockRootHex = RootHex;
17
17
  export type AttDataBase64 = string;
18
18
  // electra, CommitteeBits
19
19
  export type CommitteeBitsBase64 = string;
20
+ /** `attestation.data.index` from gossip-serialized attestations / aggregates */
21
+ export type AttDataIndex = number;
20
22
 
21
23
  // pre-electra
22
24
  // class Attestation(Container):
@@ -57,6 +59,7 @@ const SIGNATURE_SIZE = 96;
57
59
  const SINGLE_ATTESTATION_ATTDATA_OFFSET = 8 + 8;
58
60
  const SINGLE_ATTESTATION_SLOT_OFFSET = SINGLE_ATTESTATION_ATTDATA_OFFSET;
59
61
  const SINGLE_ATTESTATION_COMMITTEE_INDEX_OFFSET = 0;
62
+ const SINGLE_ATTESTATION_DATA_INDEX_OFFSET = SINGLE_ATTESTATION_ATTDATA_OFFSET + 8;
60
63
  const SINGLE_ATTESTATION_ATTESTER_INDEX_OFFSET = 8;
61
64
  const SINGLE_ATTESTATION_BEACON_BLOCK_ROOT_OFFSET = SINGLE_ATTESTATION_ATTDATA_OFFSET + 8 + 8;
62
65
  const SINGLE_ATTESTATION_SIGNATURE_OFFSET = SINGLE_ATTESTATION_ATTDATA_OFFSET + ATTESTATION_DATA_SIZE;
@@ -180,7 +183,7 @@ export function getSlotFromSingleAttestationSerialized(data: Uint8Array): Slot |
180
183
 
181
184
  /**
182
185
  * Extract committee index from SingleAttestation serialized bytes.
183
- * Return null if data is not long enough to extract slot.
186
+ * Return null if data is not long enough to extract the committee index.
184
187
  */
185
188
  export function getCommitteeIndexFromSingleAttestationSerialized(
186
189
  fork: ForkName,
@@ -201,6 +204,29 @@ export function getCommitteeIndexFromSingleAttestationSerialized(
201
204
  return getIndexFromOffset(data, VARIABLE_FIELD_OFFSET + SLOT_SIZE);
202
205
  }
203
206
 
207
+ /**
208
+ * Extract data index from SingleAttestation serialized bytes.
209
+ * Post-gloas, `data.index` field is repurposed:
210
+ * - 0 - payload was not available (or attestation is same-slot, where availability is not yet known)
211
+ * - 1 - payload was available
212
+ * Return null if data is not long enough to extract the index.
213
+ */
214
+ export function getDataIndexFromSingleAttestationSerialized(fork: ForkName, data: Uint8Array): AttDataIndex | null {
215
+ if (isForkPostElectra(fork)) {
216
+ if (data.length !== SINGLE_ATTESTATION_SIZE) {
217
+ return null;
218
+ }
219
+
220
+ return getIndexFromOffset(data, SINGLE_ATTESTATION_DATA_INDEX_OFFSET);
221
+ }
222
+
223
+ if (data.length < VARIABLE_FIELD_OFFSET + SLOT_SIZE + COMMITTEE_INDEX_SIZE) {
224
+ return null;
225
+ }
226
+
227
+ return getIndexFromOffset(data, VARIABLE_FIELD_OFFSET + SLOT_SIZE);
228
+ }
229
+
204
230
  /**
205
231
  * Extract attester index from SingleAttestation serialized bytes.
206
232
  * Return null if data is not long enough to extract index.
@@ -269,6 +295,7 @@ export function getSignatureFromSingleAttestationSerialized(data: Uint8Array): B
269
295
  const AGGREGATE_AND_PROOF_OFFSET = 4 + 96;
270
296
  const AGGREGATE_OFFSET = AGGREGATE_AND_PROOF_OFFSET + 8 + 4 + 96;
271
297
  const SIGNED_AGGREGATE_AND_PROOF_SLOT_OFFSET = AGGREGATE_OFFSET + VARIABLE_FIELD_OFFSET;
298
+ const SIGNED_AGGREGATE_AND_PROOF_ATTESTATION_DATA_INDEX_OFFSET = SIGNED_AGGREGATE_AND_PROOF_SLOT_OFFSET + SLOT_SIZE;
272
299
  const SIGNED_AGGREGATE_AND_PROOF_BLOCK_ROOT_OFFSET = SIGNED_AGGREGATE_AND_PROOF_SLOT_OFFSET + 8 + 8;
273
300
 
274
301
  /**
@@ -303,6 +330,19 @@ export function getBlockRootFromSignedAggregateAndProofSerialized(data: Uint8Arr
303
330
  return "0x" + blockRootBuf.toString("hex");
304
331
  }
305
332
 
333
+ /**
334
+ * Extract data index from signed aggregate and proof serialized bytes.
335
+ * Return null if data is not long enough to extract the index.
336
+ * This works for both phase0 + electra (index is in attestation data at the same offset).
337
+ */
338
+ export function getDataIndexFromSignedAggregateAndProofSerialized(data: Uint8Array): AttDataIndex | null {
339
+ if (data.length < SIGNED_AGGREGATE_AND_PROOF_ATTESTATION_DATA_INDEX_OFFSET + COMMITTEE_INDEX_SIZE) {
340
+ return null;
341
+ }
342
+
343
+ return getIndexFromOffset(data, SIGNED_AGGREGATE_AND_PROOF_ATTESTATION_DATA_INDEX_OFFSET);
344
+ }
345
+
306
346
  /**
307
347
  * Extract AttestationData base64 from SignedAggregateAndProof for electra
308
348
  * Return null if data is not long enough
@@ -369,6 +409,8 @@ export function getAttDataFromSignedAggregateAndProofPhase0(data: Uint8Array): A
369
409
  * ```
370
410
  */
371
411
  const SLOT_BYTES_POSITION_IN_SIGNED_BEACON_BLOCK = VARIABLE_FIELD_OFFSET + SIGNATURE_SIZE;
412
+ // proposer_index is ValidatorIndex = uint64 = 8 bytes
413
+ const PARENT_ROOT_BYTES_POSITION_IN_SIGNED_BEACON_BLOCK = VARIABLE_FIELD_OFFSET + SIGNATURE_SIZE + SLOT_SIZE + 8;
372
414
 
373
415
  export function getSlotFromSignedBeaconBlockSerialized(data: Uint8Array): Slot | null {
374
416
  if (data.length < SLOT_BYTES_POSITION_IN_SIGNED_BEACON_BLOCK + SLOT_SIZE) {
@@ -378,6 +420,68 @@ export function getSlotFromSignedBeaconBlockSerialized(data: Uint8Array): Slot |
378
420
  return getSlotFromOffset(data, SLOT_BYTES_POSITION_IN_SIGNED_BEACON_BLOCK);
379
421
  }
380
422
 
423
+ export function getParentRootFromSignedBeaconBlockSerialized(data: Uint8Array): RootHex | null {
424
+ if (data.length < PARENT_ROOT_BYTES_POSITION_IN_SIGNED_BEACON_BLOCK + ROOT_SIZE) {
425
+ return null;
426
+ }
427
+ blockRootBuf.set(
428
+ data.subarray(
429
+ PARENT_ROOT_BYTES_POSITION_IN_SIGNED_BEACON_BLOCK,
430
+ PARENT_ROOT_BYTES_POSITION_IN_SIGNED_BEACON_BLOCK + ROOT_SIZE
431
+ )
432
+ );
433
+ return `0x${blockRootBuf.toString("hex")}`;
434
+ }
435
+
436
+ /**
437
+ * Extract parentBlockHash from a GLOAS SignedBeaconBlock by navigating the SSZ offset pointer
438
+ * to the embedded SignedExecutionPayloadBid.
439
+ *
440
+ * Layout (bytes from start of SignedBeaconBlock):
441
+ * [0..4) message offset
442
+ * [4..100) signature (96 B)
443
+ * [100..184) BeaconBlock fixed section: slot(8)+proposer_index(8)+parent_root(32)+state_root(32)+body_offset(4)
444
+ * [184..) BeaconBlockBody
445
+ *
446
+ * BeaconBlockBody (GLOAS) fixed section before signedExecutionPayloadBid offset pointer:
447
+ * randaoReveal(96) + eth1Data(72) + graffiti(32)
448
+ * + proposerSlashings(4) + attesterSlashings(4) + attestations(4) + deposits(4) + voluntaryExits(4)
449
+ * + syncAggregate(160) + blsToExecutionChanges(4) = 384 bytes
450
+ *
451
+ * The 4-byte pointer at byte 568 (= 184+384) gives the offset of SignedExecutionPayloadBid
452
+ * within BeaconBlockBody. parentBlockHash is at that bid's byte 100 (after offset+sig).
453
+ */
454
+ // BeaconBlock body starts after: msg_offset(4) + sig(96) + slot(8) + proposer_index(8) + parent_root(32) + state_root(32) + body_offset_ptr(4)
455
+ const GLOAS_BODY_START_IN_SIGNED_BEACON_BLOCK =
456
+ VARIABLE_FIELD_OFFSET + SIGNATURE_SIZE + SLOT_SIZE + 8 + ROOT_SIZE + ROOT_SIZE + VARIABLE_FIELD_OFFSET; // = 184
457
+ const GLOAS_SIGNED_BID_OFFSET_POINTER_IN_BODY = 96 + 72 + 32 + 4 + 4 + 4 + 4 + 4 + 160 + 4; // = 384
458
+ const GLOAS_SIGNED_BID_OFFSET_POINTER_IN_SIGNED_BEACON_BLOCK =
459
+ GLOAS_BODY_START_IN_SIGNED_BEACON_BLOCK + GLOAS_SIGNED_BID_OFFSET_POINTER_IN_BODY; // = 568
460
+ // Within SignedExecutionPayloadBid, parentBlockHash is at byte 100 (msg_offset:4 + sig:96)
461
+ const PARENT_BLOCK_HASH_OFFSET_IN_SIGNED_BID = VARIABLE_FIELD_OFFSET + SIGNATURE_SIZE; // = 100
462
+
463
+ // CAUTION: update offsets if BeaconBlockBody fixed fields change after Gloas
464
+ export function getParentBlockHashFromGloasSignedBeaconBlockSerialized(data: Uint8Array): RootHex | null {
465
+ if (data.length < GLOAS_SIGNED_BID_OFFSET_POINTER_IN_SIGNED_BEACON_BLOCK + VARIABLE_FIELD_OFFSET) {
466
+ return null;
467
+ }
468
+ const bidOffset =
469
+ data[GLOAS_SIGNED_BID_OFFSET_POINTER_IN_SIGNED_BEACON_BLOCK] |
470
+ (data[GLOAS_SIGNED_BID_OFFSET_POINTER_IN_SIGNED_BEACON_BLOCK + 1] << 8) |
471
+ (data[GLOAS_SIGNED_BID_OFFSET_POINTER_IN_SIGNED_BEACON_BLOCK + 2] << 16) |
472
+ (data[GLOAS_SIGNED_BID_OFFSET_POINTER_IN_SIGNED_BEACON_BLOCK + 3] << 24);
473
+
474
+ const parentBlockHashStart =
475
+ GLOAS_BODY_START_IN_SIGNED_BEACON_BLOCK + bidOffset + PARENT_BLOCK_HASH_OFFSET_IN_SIGNED_BID;
476
+
477
+ if (data.length < parentBlockHashStart + ROOT_SIZE) {
478
+ return null;
479
+ }
480
+
481
+ blockRootBuf.set(data.subarray(parentBlockHashStart, parentBlockHashStart + ROOT_SIZE));
482
+ return `0x${blockRootBuf.toString("hex")}`;
483
+ }
484
+
381
485
  /**
382
486
  * class BlobSidecar(Container):
383
487
  * index: BlobIndex [fixed - 8 bytes ],
@@ -527,6 +631,104 @@ export function getSlotFromBeaconStateSerialized(data: Uint8Array): Slot | null
527
631
  return getSlotFromOffset(data, SLOT_BYTES_POSITION_IN_BEACON_STATE);
528
632
  }
529
633
 
634
+ /**
635
+ * PayloadAttestationMessage: {
636
+ * validatorIndex: ValidatorIndex (8 bytes)
637
+ * data: PayloadAttestationData {
638
+ * beaconBlockRoot: Root (32 bytes) ← offset 8
639
+ * slot: Slot (8 bytes) ← offset 40
640
+ * payloadPresent: Boolean (1 byte)
641
+ * blobDataAvailable: Boolean (1 byte)
642
+ * }
643
+ * signature: BLSSignature (96 bytes)
644
+ * }
645
+ * Fully fixed-size container, no offset table.
646
+ */
647
+ const PAYLOAD_ATTESTATION_MESSAGE_BEACON_BLOCK_ROOT_OFFSET = 8;
648
+ const PAYLOAD_ATTESTATION_MESSAGE_SLOT_OFFSET = 8 + ROOT_SIZE; // 40
649
+ const PAYLOAD_ATTESTATION_MESSAGE_PAYLOAD_PRESENT_OFFSET = PAYLOAD_ATTESTATION_MESSAGE_SLOT_OFFSET + SLOT_SIZE; // 48
650
+
651
+ export function getSlotFromPayloadAttestationMessageSerialized(data: Uint8Array): Slot | null {
652
+ if (data.length < PAYLOAD_ATTESTATION_MESSAGE_SLOT_OFFSET + SLOT_SIZE) {
653
+ return null;
654
+ }
655
+ return getSlotFromOffset(data, PAYLOAD_ATTESTATION_MESSAGE_SLOT_OFFSET);
656
+ }
657
+
658
+ export function getPayloadPresentFromPayloadAttestationMessageSerialized(data: Uint8Array): boolean | null {
659
+ if (data.length < PAYLOAD_ATTESTATION_MESSAGE_PAYLOAD_PRESENT_OFFSET + 1) {
660
+ return null;
661
+ }
662
+ return data[PAYLOAD_ATTESTATION_MESSAGE_PAYLOAD_PRESENT_OFFSET] !== 0;
663
+ }
664
+
665
+ export function getBlockRootFromPayloadAttestationMessageSerialized(data: Uint8Array): RootHex | null {
666
+ if (data.length < PAYLOAD_ATTESTATION_MESSAGE_BEACON_BLOCK_ROOT_OFFSET + ROOT_SIZE) {
667
+ return null;
668
+ }
669
+ blockRootBuf.set(
670
+ data.subarray(
671
+ PAYLOAD_ATTESTATION_MESSAGE_BEACON_BLOCK_ROOT_OFFSET,
672
+ PAYLOAD_ATTESTATION_MESSAGE_BEACON_BLOCK_ROOT_OFFSET + ROOT_SIZE
673
+ )
674
+ );
675
+ return `0x${blockRootBuf.toString("hex")}`;
676
+ }
677
+
678
+ /**
679
+ * SignedExecutionPayloadBid: {message: ExecutionPayloadBid (variable), signature: BLSSignature (96 bytes)}
680
+ * Fixed part: 4-byte offset + 96-byte signature = 100 bytes
681
+ * message data starts at byte 100
682
+ *
683
+ * ExecutionPayloadBid fixed fields (in order):
684
+ * parentBlockHash: Bytes32 (32 bytes)
685
+ * parentBlockRoot: Root (32 bytes)
686
+ * blockHash: Bytes32 (32 bytes)
687
+ * prevRandao: Bytes32 (32 bytes)
688
+ * feeRecipient: ExecutionAddress(20 bytes)
689
+ * gasLimit: UintBn64 (8 bytes)
690
+ * builderIndex: BuilderIndex (8 bytes)
691
+ * slot: Slot (8 bytes) ← absolute offset 264
692
+ */
693
+ const SIGNED_EXECUTION_PAYLOAD_BID_PARENT_BLOCK_HASH_OFFSET = VARIABLE_FIELD_OFFSET + SIGNATURE_SIZE; // 100
694
+ const SIGNED_EXECUTION_PAYLOAD_BID_PARENT_BLOCK_ROOT_OFFSET =
695
+ SIGNED_EXECUTION_PAYLOAD_BID_PARENT_BLOCK_HASH_OFFSET + ROOT_SIZE; // 132
696
+ const SIGNED_EXECUTION_PAYLOAD_BID_SLOT_OFFSET =
697
+ VARIABLE_FIELD_OFFSET + SIGNATURE_SIZE + 32 + 32 + 32 + 32 + 20 + 8 + 8; // 264
698
+
699
+ export function getSlotFromSignedExecutionPayloadBidSerialized(data: Uint8Array): Slot | null {
700
+ if (data.length < SIGNED_EXECUTION_PAYLOAD_BID_SLOT_OFFSET + SLOT_SIZE) {
701
+ return null;
702
+ }
703
+ return getSlotFromOffset(data, SIGNED_EXECUTION_PAYLOAD_BID_SLOT_OFFSET);
704
+ }
705
+
706
+ export function getParentBlockHashFromSignedExecutionPayloadBidSerialized(data: Uint8Array): RootHex | null {
707
+ if (data.length < SIGNED_EXECUTION_PAYLOAD_BID_PARENT_BLOCK_HASH_OFFSET + ROOT_SIZE) {
708
+ return null;
709
+ }
710
+ blockRootBuf.set(
711
+ data.subarray(
712
+ SIGNED_EXECUTION_PAYLOAD_BID_PARENT_BLOCK_HASH_OFFSET,
713
+ SIGNED_EXECUTION_PAYLOAD_BID_PARENT_BLOCK_HASH_OFFSET + ROOT_SIZE
714
+ )
715
+ );
716
+ return `0x${blockRootBuf.toString("hex")}`;
717
+ }
718
+
719
+ export function getParentBlockRootFromSignedExecutionPayloadBidSerialized(data: Uint8Array): RootHex | null {
720
+ if (data.length < SIGNED_EXECUTION_PAYLOAD_BID_PARENT_BLOCK_ROOT_OFFSET + ROOT_SIZE) {
721
+ return null;
722
+ }
723
+ blockRootBuf.set(
724
+ data.subarray(
725
+ SIGNED_EXECUTION_PAYLOAD_BID_PARENT_BLOCK_ROOT_OFFSET,
726
+ SIGNED_EXECUTION_PAYLOAD_BID_PARENT_BLOCK_ROOT_OFFSET + ROOT_SIZE
727
+ )
728
+ );
729
+ return `0x${blockRootBuf.toString("hex")}`;
730
+ }
731
+
530
732
  /**
531
733
  * Read only the first 4 bytes of Slot, max value is 4,294,967,295 will be reached 1634 years after genesis
532
734
  *
@@ -562,9 +764,49 @@ export function getBlobKzgCommitmentsCountFromSignedBeaconBlockSerialized(
562
764
  if (slot === null) throw new Error("Can not parse the slot from block bytes");
563
765
 
564
766
  if (config.getForkSeq(slot) < ForkSeq.deneb) return 0;
767
+ const forkName = config.getForkName(slot);
768
+
769
+ if (isForkPostGloas(forkName)) {
770
+ // Gloas stores commitments under signedExecutionPayloadBid.message.blobKzgCommitments.
771
+ // Navigate the offset chain: SignedBeaconBlock → message → body → signedExecutionPayloadBid → message → blobKzgCommitments
772
+ const {SignedBeaconBlock: GloasSignedBlock, BeaconBlock: GloasBlock, BeaconBlockBody: GloasBody} = ssz[forkName];
773
+ const {SignedExecutionPayloadBid, ExecutionPayloadBid} = ssz[forkName];
774
+ const commitmentSize = ssz.deneb.KZGCommitment.fixedSize;
775
+
776
+ const view = new DataView(blockBytes.buffer, blockBytes.byteOffset, blockBytes.byteLength);
777
+
778
+ const signedBlockRanges = GloasSignedBlock.getFieldRanges(view, 0, blockBytes.length);
779
+ const messageIdx = Object.keys(GloasSignedBlock.fields).indexOf("message");
780
+ const messageRange = signedBlockRanges[messageIdx];
781
+
782
+ const blockRanges = GloasBlock.getFieldRanges(view, messageRange.start, messageRange.end);
783
+ const bodyIdx = Object.keys(GloasBlock.fields).indexOf("body");
784
+ const bodyRange = blockRanges[bodyIdx];
785
+ const bodyStart = messageRange.start + bodyRange.start;
786
+ const bodyEnd = messageRange.start + bodyRange.end;
787
+
788
+ const bodyRanges = GloasBody.getFieldRanges(view, bodyStart, bodyEnd);
789
+ const bidIdx = Object.keys(GloasBody.fields).indexOf("signedExecutionPayloadBid");
790
+ const bidRange = bodyRanges[bidIdx];
791
+ const bidStart = bodyStart + bidRange.start;
792
+ const bidEnd = bodyStart + bidRange.end;
793
+
794
+ const bidRanges = SignedExecutionPayloadBid.getFieldRanges(view, bidStart, bidEnd);
795
+ const bidMsgIdx = Object.keys(SignedExecutionPayloadBid.fields).indexOf("message");
796
+ const bidMsgRange = bidRanges[bidMsgIdx];
797
+ const bidMsgStart = bidStart + bidMsgRange.start;
798
+ const bidMsgEnd = bidStart + bidMsgRange.end;
799
+
800
+ const execBidRanges = ExecutionPayloadBid.getFieldRanges(view, bidMsgStart, bidMsgEnd);
801
+ const commitmentsIdx = Object.keys(ExecutionPayloadBid.fields).indexOf("blobKzgCommitments");
802
+ const commitmentsRange = execBidRanges[commitmentsIdx];
803
+
804
+ const start = bidMsgStart + commitmentsRange.start;
805
+ const end = bidMsgStart + commitmentsRange.end;
806
+ return Math.round(((end > blockBytes.byteLength ? blockBytes.byteLength : end) - start) / commitmentSize);
807
+ }
565
808
 
566
- const {SignedBeaconBlock, BeaconBlock, BeaconBlockBody, KZGCommitment} =
567
- ssz[config.getForkName(slot) as ForkPostDeneb];
809
+ const {SignedBeaconBlock, BeaconBlock, BeaconBlockBody, KZGCommitment} = ssz[forkName as ForkPostDeneb];
568
810
 
569
811
  const view = new DataView(blockBytes.buffer, blockBytes.byteOffset, blockBytes.byteLength);
570
812
  const singedBlockFieldRanges = SignedBeaconBlock.getFieldRanges(view, 0, blockBytes.length);