@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
@@ -1 +1 @@
1
- {"version":3,"file":"extractSlotRootFns.d.ts","sourceRoot":"","sources":["../../../src/network/processor/extractSlotRootFns.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,kBAAkB,EAAC,MAAM,YAAY,CAAC;AAE9C;;;GAGG;AACH,wBAAgB,6BAA6B,IAAI,kBAAkB,CAuDlE"}
1
+ {"version":3,"file":"extractSlotRootFns.d.ts","sourceRoot":"","sources":["../../../src/network/processor/extractSlotRootFns.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAC,kBAAkB,EAAC,MAAM,YAAY,CAAC;AAE9C;;;GAGG;AACH,wBAAgB,6BAA6B,IAAI,kBAAkB,CA+ElE"}
@@ -1,9 +1,9 @@
1
- import { isForkPostGloas } from "@lodestar/params";
2
- import { getBeaconBlockRootFromDataColumnSidecarSerialized, getBeaconBlockRootFromExecutionPayloadEnvelopeSerialized, getBlockRootFromBeaconAttestationSerialized, getBlockRootFromSignedAggregateAndProofSerialized, getSlotFromBeaconAttestationSerialized, getSlotFromBlobSidecarSerialized, getSlotFromDataColumnSidecarSerialized, getSlotFromExecutionPayloadEnvelopeSerialized, getSlotFromSignedAggregateAndProofSerialized, getSlotFromSignedBeaconBlockSerialized, } from "../../util/sszBytes.js";
1
+ import { ForkSeq } from "@lodestar/params";
2
+ import { getBeaconBlockRootFromDataColumnSidecarSerialized, getBlockRootFromBeaconAttestationSerialized, getBlockRootFromPayloadAttestationMessageSerialized, getBlockRootFromSignedAggregateAndProofSerialized, getSlotFromBeaconAttestationSerialized, getSlotFromBlobSidecarSerialized, getSlotFromDataColumnSidecarSerialized, getSlotFromExecutionPayloadEnvelopeSerialized, getSlotFromPayloadAttestationMessageSerialized, getSlotFromSignedAggregateAndProofSerialized, getSlotFromSignedBeaconBlockSerialized, getSlotFromSignedExecutionPayloadBidSerialized, } from "../../util/sszBytes.js";
3
3
  import { GossipType } from "../gossip/index.js";
4
4
  /**
5
5
  * Extract the slot and block root of a gossip message form serialized data.
6
- * Not applicable for all topics.
6
+ * Only do it for messages that have a slot and block root, and we want to await the block if the block root is not known.
7
7
  */
8
8
  export function createExtractBlockSlotRootFns() {
9
9
  return {
@@ -42,17 +42,37 @@ export function createExtractBlockSlotRootFns() {
42
42
  if (slot === null) {
43
43
  return null;
44
44
  }
45
- const root = isForkPostGloas(fork) ? getBeaconBlockRootFromDataColumnSidecarSerialized(data) : null;
45
+ if (ForkSeq[fork] < ForkSeq.gloas) {
46
+ return { slot };
47
+ }
48
+ const root = getBeaconBlockRootFromDataColumnSidecarSerialized(data);
49
+ // null root means the message is invalid here and will be ignored in gossip handler later
50
+ // returning the slot here helps check the earliest permissable slot in the network processor
46
51
  return root !== null ? { slot, root } : { slot };
47
52
  },
48
53
  [GossipType.execution_payload]: (data) => {
49
54
  const slot = getSlotFromExecutionPayloadEnvelopeSerialized(data);
50
- const root = getBeaconBlockRootFromExecutionPayloadEnvelopeSerialized(data);
55
+ // Do not extract the root here; the network processor will extract it in the 2nd round to trigger block search without awaiting.
56
+ if (slot === null) {
57
+ return null;
58
+ }
59
+ return { slot };
60
+ },
61
+ [GossipType.payload_attestation_message]: (data) => {
62
+ const slot = getSlotFromPayloadAttestationMessageSerialized(data);
63
+ const root = getBlockRootFromPayloadAttestationMessageSerialized(data);
51
64
  if (slot === null || root === null) {
52
65
  return null;
53
66
  }
54
67
  return { slot, root };
55
68
  },
69
+ [GossipType.execution_payload_bid]: (data) => {
70
+ const slot = getSlotFromSignedExecutionPayloadBidSerialized(data);
71
+ if (slot === null) {
72
+ return null;
73
+ }
74
+ return { slot };
75
+ },
56
76
  };
57
77
  }
58
78
  //# sourceMappingURL=extractSlotRootFns.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"extractSlotRootFns.js","sourceRoot":"","sources":["../../../src/network/processor/extractSlotRootFns.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAE3D,OAAO,EACL,iDAAiD,EACjD,wDAAwD,EACxD,2CAA2C,EAC3C,iDAAiD,EACjD,sCAAsC,EACtC,gCAAgC,EAChC,sCAAsC,EACtC,6CAA6C,EAC7C,4CAA4C,EAC5C,sCAAsC,GACvC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAC,UAAU,EAAC,MAAM,oBAAoB,CAAC;AAG9C;;;GAGG;AACH,MAAM,UAAU,6BAA6B,GAAuB;IAClE,OAAO;QACL,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC,IAAgB,EAAE,IAAc,EAAsB,EAAE,CAAC;YACzF,MAAM,IAAI,GAAG,sCAAsC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAChE,MAAM,IAAI,GAAG,2CAA2C,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAErE,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBACnC,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC;QAAA,CACrB;QACD,CAAC,UAAU,CAAC,0BAA0B,CAAC,EAAE,CAAC,IAAgB,EAAsB,EAAE,CAAC;YACjF,MAAM,IAAI,GAAG,4CAA4C,CAAC,IAAI,CAAC,CAAC;YAChE,MAAM,IAAI,GAAG,iDAAiD,CAAC,IAAI,CAAC,CAAC;YAErE,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBACnC,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC;QAAA,CACrB;QACD,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC,IAAgB,EAA2B,EAAE,CAAC;YACxE,MAAM,IAAI,GAAG,sCAAsC,CAAC,IAAI,CAAC,CAAC;YAE1D,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAClB,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,EAAC,IAAI,EAAC,CAAC;QAAA,CACf;QACD,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC,IAAgB,EAA2B,EAAE,CAAC;YACxE,MAAM,IAAI,GAAG,gCAAgC,CAAC,IAAI,CAAC,CAAC;YAEpD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAClB,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,EAAC,IAAI,EAAC,CAAC;QAAA,CACf;QACD,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC,IAAgB,EAAE,IAAc,EAA2B,EAAE,CAAC;YAC/F,MAAM,IAAI,GAAG,sCAAsC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAChE,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAClB,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,iDAAiD,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YACpG,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC,CAAC,EAAC,IAAI,EAAC,CAAC;QAAA,CAC9C;QACD,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC,IAAgB,EAAsB,EAAE,CAAC;YACxE,MAAM,IAAI,GAAG,6CAA6C,CAAC,IAAI,CAAC,CAAC;YACjE,MAAM,IAAI,GAAG,wDAAwD,CAAC,IAAI,CAAC,CAAC;YAE5E,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBACnC,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC;QAAA,CACrB;KACF,CAAC;AAAA,CACH"}
1
+ {"version":3,"file":"extractSlotRootFns.js","sourceRoot":"","sources":["../../../src/network/processor/extractSlotRootFns.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"gossipHandlers.d.ts","sourceRoot":"","sources":["../../../src/network/processor/gossipHandlers.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,YAAY,EAAkB,MAAM,kBAAkB,CAAC;AAW/D,OAAO,EACL,IAAI,EAGJ,IAAI,EAOL,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAW,MAAM,EAAgC,MAAM,iBAAiB,CAAC;AA2BhF,OAAO,EAAC,YAAY,EAAC,MAAM,0BAA0B,CAAC;AAuBtD,OAAO,EAAC,OAAO,EAAC,MAAM,wBAAwB,CAAC;AAG/C,OAAO,EAAC,YAAY,EAAC,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAC,eAAe,EAAC,MAAM,cAAc,CAAC;AAC7C,OAAO,EAGL,cAAc,EAGf,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAC,QAAQ,EAAC,MAAM,iBAAiB,CAAC;AAEzC,OAAO,EAAC,iBAAiB,EAAC,MAAM,wBAAwB,CAAC;AAEzD;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,wDAAwD;IACxD,sCAAsC,CAAC,EAAE,OAAO,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,eAAe,CAAC;IACxB,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,IAAI,EAAE,YAAY,CAAC;CACpB,CAAC;AAKF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,iBAAiB,GAAG,cAAc,CAE1G;AAg4BD;;GAEG;AACH,wBAAsB,gCAAgC,CAAC,CAAC,EACtD,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,IAAI,GACd,OAAO,CAAC,CAAC,CAAC,CA6BZ"}
1
+ {"version":3,"file":"gossipHandlers.d.ts","sourceRoot":"","sources":["../../../src/network/processor/gossipHandlers.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,YAAY,EAAkB,MAAM,kBAAkB,CAAC;AAc/D,OAAO,EACL,IAAI,EAGJ,IAAI,EASL,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAW,MAAM,EAAgC,MAAM,iBAAiB,CAAC;AA2BhF,OAAO,EAAC,YAAY,EAAC,MAAM,0BAA0B,CAAC;AA0BtD,OAAO,EAAC,OAAO,EAAC,MAAM,wBAAwB,CAAC;AAG/C,OAAO,EAAC,YAAY,EAAC,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAC,eAAe,EAAC,MAAM,cAAc,CAAC;AAC7C,OAAO,EAGL,cAAc,EAGf,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAC,QAAQ,EAAC,MAAM,iBAAiB,CAAC;AAEzC,OAAO,EAAC,iBAAiB,EAAC,MAAM,wBAAwB,CAAC;AAEzD;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,wDAAwD;IACxD,sCAAsC,CAAC,EAAE,OAAO,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,eAAe,CAAC;IACxB,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,IAAI,EAAE,YAAY,CAAC;CACpB,CAAC;AAKF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,iBAAiB,GAAG,cAAc,CAE1G;AAkmCD;;GAEG;AACH,wBAAsB,gCAAgC,CAAC,CAAC,EACtD,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,IAAI,GACd,OAAO,CAAC,CAAC,CAAC,CA6BZ"}
@@ -1,7 +1,8 @@
1
1
  import { routes } from "@lodestar/api";
2
- import { ForkSeq, NUMBER_OF_COLUMNS, isForkPostElectra, } from "@lodestar/params";
2
+ import { PayloadStatus } from "@lodestar/fork-choice";
3
+ import { ForkSeq, NUMBER_OF_COLUMNS, isForkPostElectra, isForkPostGloas, } from "@lodestar/params";
3
4
  import { computeTimeAtSlot } from "@lodestar/state-transition";
4
- import { ssz, sszTypesFor, } from "@lodestar/types";
5
+ import { isGloasDataColumnSidecar, ssz, sszTypesFor, } from "@lodestar/types";
5
6
  import { LogLevel, prettyBytes, toHex, toRootHex } from "@lodestar/utils";
6
7
  import { BlockInputSource, isBlockInputColumns, } from "../../chain/blocks/blockInput/index.js";
7
8
  import { PayloadEnvelopeInputSource } from "../../chain/blocks/payloadEnvelopeInput/index.js";
@@ -9,7 +10,7 @@ import { BlobSidecarValidation } from "../../chain/blocks/types.js";
9
10
  import { ChainEvent } from "../../chain/emitter.js";
10
11
  import { AttestationError, AttestationErrorCode, BlobSidecarErrorCode, BlobSidecarGossipError, BlockError, BlockErrorCode, BlockGossipError, DataColumnSidecarErrorCode, DataColumnSidecarGossipError, ExecutionPayloadEnvelopeError, ExecutionPayloadEnvelopeErrorCode, GossipAction, GossipActionError, SyncCommitteeError, } from "../../chain/errors/index.js";
11
12
  import { validateGossipBlobSidecar } from "../../chain/validation/blobSidecar.js";
12
- import { validateGossipDataColumnSidecar } from "../../chain/validation/dataColumnSidecar.js";
13
+ import { validateGossipFuluDataColumnSidecar, validateGossipGloasDataColumnSidecar, } from "../../chain/validation/dataColumnSidecar.js";
13
14
  import { validateGossipExecutionPayloadBid } from "../../chain/validation/executionPayloadBid.js";
14
15
  import { validateGossipExecutionPayloadEnvelope } from "../../chain/validation/executionPayloadEnvelope.js";
15
16
  import { toElectraSingleAttestation, validateGossipAggregateAndProof, validateGossipAttestationsSameAttData, validateGossipAttesterSlashing, validateGossipBlock, validateGossipBlsToExecutionChange, validateGossipProposerSlashing, validateGossipSyncCommittee, validateGossipVoluntaryExit, validateSyncCommitteeGossipContributionAndProof, } from "../../chain/validation/index.js";
@@ -18,7 +19,7 @@ import { validateLightClientOptimisticUpdate } from "../../chain/validation/ligh
18
19
  import { validateGossipPayloadAttestationMessage } from "../../chain/validation/payloadAttestationMessage.js";
19
20
  import { OpSource } from "../../chain/validatorMonitor.js";
20
21
  import { kzgCommitmentToVersionedHash } from "../../util/blobs.js";
21
- import { getBlobKzgCommitments } from "../../util/dataColumns.js";
22
+ import { getBlobKzgCommitments, getDataColumnSidecarSlot } from "../../util/dataColumns.js";
22
23
  import { GossipType, } from "../gossip/interface.js";
23
24
  import { sszDeserialize } from "../gossip/topic.js";
24
25
  import { PeerAction } from "../peers/index.js";
@@ -64,16 +65,19 @@ function getSequentialHandlers(modules, options) {
64
65
  recvToValLatency,
65
66
  };
66
67
  logger.debug("Received gossip block", { ...logCtx });
67
- let blockInput;
68
+ // optimistically add gossip block to the seen cache
69
+ // if validation fails, we will NOT forward this gossip block to peers
70
+ // - if PARENT_UNKNOWN error, blockInput will then be queued inside BlockInputSync. If the gossip block is really invalid, it will be pruned there
71
+ // - if other validator errors, blockInput will stay in the seen cache and will be pruned on finalization
72
+ const blockInput = chain.seenBlockInputCache.getByBlock({
73
+ block: signedBlock,
74
+ blockRootHex,
75
+ source: BlockInputSource.gossip,
76
+ seenTimestampSec,
77
+ peerIdStr,
78
+ });
68
79
  try {
69
80
  await validateGossipBlock(config, chain, signedBlock, fork);
70
- blockInput = chain.seenBlockInputCache.getByBlock({
71
- block: signedBlock,
72
- blockRootHex,
73
- source: BlockInputSource.gossip,
74
- seenTimestampSec,
75
- peerIdStr,
76
- });
77
81
  const blockInputMeta = blockInput.getLogMeta();
78
82
  const recvToValidation = Date.now() / 1000 - seenTimestampSec;
79
83
  const validationTime = recvToValidation - recvToValLatency;
@@ -85,9 +89,9 @@ function getSequentialHandlers(modules, options) {
85
89
  }
86
90
  catch (e) {
87
91
  if (e instanceof BlockGossipError) {
92
+ logger.debug("Gossip block has error", { slot, root: blockShortHex, code: e.type.code });
88
93
  if (e.type.code === BlockErrorCode.PARENT_UNKNOWN && blockInput) {
89
- logger.debug("Gossip block has error", { slot, root: blockShortHex, code: e.type.code });
90
- chain.emitter.emit(ChainEvent.unknownParent, {
94
+ chain.emitter.emit(ChainEvent.blockUnknownParent, {
91
95
  blockInput,
92
96
  peer: peerIdStr,
93
97
  source: BlockInputSource.gossip,
@@ -196,7 +200,7 @@ function getSequentialHandlers(modules, options) {
196
200
  const blockInput = chain.seenBlockInputCache.get(blockRootHex);
197
201
  if (blockInput && isBlockInputColumns(blockInput) && blockInput.hasColumn(dataColumnSidecar.index)) {
198
202
  metrics?.peerDas.dataColumnSidecarProcessingSkip.inc();
199
- logger.debug("Already have column sidecar, skipping processing", {
203
+ logger.debug("Already have column sidecar in BlockInput, skipping processing", {
200
204
  ...blockInput.getLogMeta(),
201
205
  index: dataColumnSidecar.index,
202
206
  });
@@ -209,9 +213,10 @@ function getSequentialHandlers(modules, options) {
209
213
  }
210
214
  const verificationTimer = metrics?.peerDas.dataColumnSidecarGossipVerificationTime.startTimer();
211
215
  const delaySec = chain.clock.secFromSlot(slot, seenTimestampSec);
216
+ const secFromSlot = chain.clock.secFromSlot(slot);
212
217
  const recvToValLatency = Date.now() / 1000 - seenTimestampSec;
213
218
  try {
214
- await validateGossipDataColumnSidecar(chain, dataColumnSidecar, gossipSubnet, metrics);
219
+ await validateGossipFuluDataColumnSidecar(chain, dataColumnSidecar, gossipSubnet, metrics);
215
220
  const blockInput = chain.seenBlockInputCache.getByColumn({
216
221
  blockRootHex,
217
222
  columnSidecar: dataColumnSidecar,
@@ -237,6 +242,7 @@ function getSequentialHandlers(modules, options) {
237
242
  currentSlot: chain.clock.currentSlot,
238
243
  peerId: peerIdStr,
239
244
  delaySec,
245
+ secFromSlot,
240
246
  gossipSubnet,
241
247
  columnIndex: dataColumnSidecar.index,
242
248
  recvToValLatency,
@@ -261,6 +267,108 @@ function getSequentialHandlers(modules, options) {
261
267
  verificationTimer?.();
262
268
  }
263
269
  }
270
+ async function validatePayloadDataColumn(dataColumnSidecar, gossipSubnet, peerIdStr, seenTimestampSec) {
271
+ metrics?.peerDas.dataColumnSidecarProcessingRequests.inc();
272
+ const slot = dataColumnSidecar.slot;
273
+ const blockRootHex = toRootHex(dataColumnSidecar.beaconBlockRoot);
274
+ // check to see if payload has already been processed and PayloadEnvelopeInput has been deleted (column received via reqresp or other means)
275
+ if (chain.forkChoice.getBlockHex(blockRootHex, PayloadStatus.FULL) !== null) {
276
+ metrics?.peerDas.dataColumnSidecarProcessingSkip.inc();
277
+ logger.debug("Already processed payload for column sidecar, skipping processing", {
278
+ slot,
279
+ blockRoot: blockRootHex,
280
+ index: dataColumnSidecar.index,
281
+ });
282
+ throw new DataColumnSidecarGossipError(GossipAction.IGNORE, {
283
+ code: DataColumnSidecarErrorCode.ALREADY_KNOWN,
284
+ columnIndex: dataColumnSidecar.index,
285
+ slot,
286
+ });
287
+ }
288
+ const payloadInput = chain.seenPayloadEnvelopeInputCache.get(blockRootHex);
289
+ if (!payloadInput) {
290
+ // This should not happen for gossip because the network processor queues `data_column_sidecar`
291
+ // until block import creates the corresponding PayloadEnvelopeInput.
292
+ throw new DataColumnSidecarGossipError(GossipAction.IGNORE, {
293
+ code: DataColumnSidecarErrorCode.PAYLOAD_ENVELOPE_INPUT_MISSING,
294
+ slot,
295
+ blockRoot: blockRootHex,
296
+ });
297
+ }
298
+ // [IGNORE] The sidecar is the first sidecar for the tuple
299
+ // (sidecar.beacon_block_root, sidecar.index) with valid kzg proof.
300
+ if (payloadInput.hasColumn(dataColumnSidecar.index)) {
301
+ metrics?.peerDas.dataColumnSidecarProcessingSkip.inc();
302
+ logger.debug("Already have column sidecar in PayloadEnvelopeInput, skipping processing", {
303
+ ...payloadInput.getLogMeta(),
304
+ index: dataColumnSidecar.index,
305
+ });
306
+ throw new DataColumnSidecarGossipError(GossipAction.IGNORE, {
307
+ code: DataColumnSidecarErrorCode.ALREADY_KNOWN,
308
+ columnIndex: dataColumnSidecar.index,
309
+ slot,
310
+ });
311
+ }
312
+ const verificationTimer = metrics?.peerDas.dataColumnSidecarGossipVerificationTime.startTimer();
313
+ const delaySec = chain.clock.secFromSlot(slot, seenTimestampSec);
314
+ const secFromSlot = chain.clock.secFromSlot(slot);
315
+ const recvToValLatency = Date.now() / 1000 - seenTimestampSec;
316
+ try {
317
+ await validateGossipGloasDataColumnSidecar(chain, payloadInput, dataColumnSidecar, gossipSubnet, metrics);
318
+ const addedColumn = payloadInput.addColumn({
319
+ columnSidecar: dataColumnSidecar,
320
+ source: PayloadEnvelopeInputSource.gossip,
321
+ seenTimestampSec,
322
+ peerIdStr,
323
+ });
324
+ if (!addedColumn) {
325
+ metrics?.peerDas.dataColumnSidecarProcessingSkip.inc();
326
+ logger.debug("Already have column sidecar in PayloadEnvelopeInput, skipping processing", {
327
+ ...payloadInput.getLogMeta(),
328
+ index: dataColumnSidecar.index,
329
+ });
330
+ throw new DataColumnSidecarGossipError(GossipAction.IGNORE, {
331
+ code: DataColumnSidecarErrorCode.ALREADY_KNOWN,
332
+ columnIndex: dataColumnSidecar.index,
333
+ slot,
334
+ });
335
+ }
336
+ const recvToValidation = Date.now() / 1000 - seenTimestampSec;
337
+ const validationTime = recvToValidation - recvToValLatency;
338
+ metrics?.peerDas.dataColumnSidecarProcessingSuccesses.inc();
339
+ metrics?.gossipBlob.recvToValidation.observe(recvToValidation);
340
+ metrics?.gossipBlob.validationTime.observe(validationTime);
341
+ if (chain.emitter.listenerCount(routes.events.EventType.dataColumnSidecar)) {
342
+ chain.emitter.emit(routes.events.EventType.dataColumnSidecar, {
343
+ blockRoot: blockRootHex,
344
+ slot,
345
+ index: dataColumnSidecar.index,
346
+ });
347
+ }
348
+ logger.debug("Received gossip dataColumn", {
349
+ ...payloadInput.getLogMeta(),
350
+ currentSlot: chain.clock.currentSlot,
351
+ peerId: peerIdStr,
352
+ delaySec,
353
+ secFromSlot,
354
+ gossipSubnet,
355
+ columnIndex: dataColumnSidecar.index,
356
+ recvToValLatency,
357
+ recvToValidation,
358
+ validationTime,
359
+ });
360
+ return payloadInput;
361
+ }
362
+ catch (e) {
363
+ if (e instanceof DataColumnSidecarGossipError && e.action === GossipAction.REJECT) {
364
+ chain.persistInvalidSszValue(sszTypesFor(payloadInput.forkName).DataColumnSidecar, dataColumnSidecar, `gossip_reject_slot_${slot}_index_${dataColumnSidecar.index}`);
365
+ }
366
+ throw e;
367
+ }
368
+ finally {
369
+ verificationTimer?.();
370
+ }
371
+ }
264
372
  function handleValidBeaconBlock(blockInput, peerIdStr, seenTimestampSec) {
265
373
  const signedBlock = blockInput.getBlock();
266
374
  const slot = signedBlock.message.slot;
@@ -382,65 +490,110 @@ function getSequentialHandlers(modules, options) {
382
490
  }
383
491
  },
384
492
  [GossipType.data_column_sidecar]: async ({ gossipData, topic, peerIdStr, seenTimestampSec, }) => {
493
+ const { fork } = topic.boundary;
385
494
  const { serializedData } = gossipData;
386
- // TODO GLOAS: handle gloas.DataColumnSidecar
387
495
  const dataColumnSidecar = sszDeserialize(topic, serializedData);
388
- const dataColumnSlot = dataColumnSidecar.signedBlockHeader.message.slot;
496
+ const dataColumnSlot = getDataColumnSidecarSlot(dataColumnSidecar);
389
497
  const index = dataColumnSidecar.index;
390
- if (config.getForkSeq(dataColumnSlot) < ForkSeq.fulu) {
391
- throw new GossipActionError(GossipAction.REJECT, { code: "PRE_FULU_BLOCK" });
392
- }
393
498
  const delaySec = chain.clock.secFromSlot(dataColumnSlot, seenTimestampSec);
394
- const blockInput = await validateBeaconDataColumn(dataColumnSidecar, serializedData, topic.subnet, peerIdStr, seenTimestampSec);
395
- chain.serializedCache.set(dataColumnSidecar, serializedData);
396
- const blockInputMeta = blockInput.getLogMeta();
397
- const { receivedColumns } = blockInputMeta;
398
- // it's not helpful to track every single column received
399
- // instead of that, track 1st, 8th, 16th 32th, 64th, and 128th column
400
- switch (receivedColumns) {
401
- case 1:
402
- case config.SAMPLES_PER_SLOT:
403
- case 2 * config.SAMPLES_PER_SLOT:
404
- case NUMBER_OF_COLUMNS / 4:
405
- case NUMBER_OF_COLUMNS / 2:
406
- case NUMBER_OF_COLUMNS:
407
- metrics?.dataColumns.elapsedTimeTillReceived.observe({ receivedOrder: receivedColumns }, delaySec);
408
- break;
409
- }
410
- if (!blockInput.hasComputedAllData()) {
411
- // immediately attempt fetch of data columns from execution engine
412
- chain.getBlobsTracker.triggerGetBlobs(blockInput);
413
- // if we've received at least half of the columns, trigger reconstruction of the rest
414
- if (blockInput.columnCount >= NUMBER_OF_COLUMNS / 2) {
415
- chain.columnReconstructionTracker.triggerColumnReconstruction(blockInput);
499
+ if (isForkPostGloas(fork)) {
500
+ if (!isGloasDataColumnSidecar(dataColumnSidecar)) {
501
+ throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
502
+ code: DataColumnSidecarErrorCode.INCORRECT_TYPE,
503
+ slot: dataColumnSlot,
504
+ columnIndex: index,
505
+ fork,
506
+ });
416
507
  }
417
- }
418
- if (!blockInput.hasBlockAndAllData()) {
419
- const cutoffTimeMs = getCutoffTimeMs(chain, dataColumnSlot, BLOCK_AVAILABILITY_CUTOFF_MS);
420
- chain.logger.debug("Received gossip data column, waiting for full data availability", {
421
- msToWait: cutoffTimeMs,
422
- dataColumnIndex: index,
423
- ...blockInputMeta,
508
+ // After gloas, data columns are tracked in PayloadEnvelopeInput
509
+ const payloadInput = await validatePayloadDataColumn(dataColumnSidecar, topic.subnet, peerIdStr, seenTimestampSec);
510
+ chain.serializedCache.set(dataColumnSidecar, serializedData);
511
+ const payloadInputMeta = payloadInput.getLogMeta();
512
+ const { receivedColumns } = payloadInputMeta;
513
+ // it's not helpful to track every single column received
514
+ // instead of that, track 1st, 8th, 16th 32th, 64th, and 128th column
515
+ switch (receivedColumns) {
516
+ case 1:
517
+ case config.SAMPLES_PER_SLOT:
518
+ case 2 * config.SAMPLES_PER_SLOT:
519
+ case NUMBER_OF_COLUMNS / 4:
520
+ case NUMBER_OF_COLUMNS / 2:
521
+ case NUMBER_OF_COLUMNS:
522
+ metrics?.dataColumns.elapsedTimeTillReceived.observe({ receivedOrder: receivedColumns }, delaySec);
523
+ break;
524
+ }
525
+ if (!payloadInput.hasComputedAllData()) {
526
+ // if we've received at least half of the columns, trigger reconstruction of the rest
527
+ if (receivedColumns >= NUMBER_OF_COLUMNS / 2) {
528
+ chain.columnReconstructionTracker.triggerColumnReconstruction(payloadInput);
529
+ }
530
+ chain.logger.debug("Received gossip data column, payload envelope input not yet complete", {
531
+ dataColumnIndex: index,
532
+ ...payloadInputMeta,
533
+ });
534
+ }
535
+ chain.processExecutionPayload(payloadInput, { validSignature: true }).catch((e) => {
536
+ chain.logger.debug("Error processing execution payload from gossip data column", { slot: dataColumnSlot, root: payloadInput.blockRootHex }, e);
424
537
  });
425
- // do not await here to not delay gossip validation
426
- blockInput.waitForBlockAndAllData(cutoffTimeMs).catch((_e) => {
427
- chain.logger.debug("Waited for data after receiving gossip column. Cut-off reached so attempting to fetch remainder of BlockInput", {
538
+ }
539
+ else {
540
+ if (config.getForkSeq(dataColumnSlot) < ForkSeq.fulu) {
541
+ throw new GossipActionError(GossipAction.REJECT, { code: "PRE_FULU_BLOCK" });
542
+ }
543
+ if (isGloasDataColumnSidecar(dataColumnSidecar)) {
544
+ throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
545
+ code: DataColumnSidecarErrorCode.INCORRECT_TYPE,
546
+ slot: dataColumnSlot,
547
+ columnIndex: index,
548
+ fork,
549
+ });
550
+ }
551
+ // Before gloas, data columns are tracked in BlockInput
552
+ const blockInput = await validateBeaconDataColumn(dataColumnSidecar, serializedData, topic.subnet, peerIdStr, seenTimestampSec);
553
+ chain.serializedCache.set(dataColumnSidecar, serializedData);
554
+ const blockInputMeta = blockInput.getLogMeta();
555
+ const { receivedColumns } = blockInputMeta;
556
+ // it's not helpful to track every single column received
557
+ // instead of that, track 1st, 8th, 16th 32th, 64th, and 128th column
558
+ switch (receivedColumns) {
559
+ case 1:
560
+ case config.SAMPLES_PER_SLOT:
561
+ case 2 * config.SAMPLES_PER_SLOT:
562
+ case NUMBER_OF_COLUMNS / 4:
563
+ case NUMBER_OF_COLUMNS / 2:
564
+ case NUMBER_OF_COLUMNS:
565
+ metrics?.dataColumns.elapsedTimeTillReceived.observe({ receivedOrder: receivedColumns }, delaySec);
566
+ break;
567
+ }
568
+ if (!blockInput.hasComputedAllData()) {
569
+ // immediately attempt fetch of data columns from execution engine
570
+ chain.getBlobsTracker.triggerGetBlobs(blockInput);
571
+ // if we've received at least half of the columns, trigger reconstruction of the rest
572
+ if (blockInput.columnCount >= NUMBER_OF_COLUMNS / 2) {
573
+ chain.columnReconstructionTracker.triggerColumnReconstruction(blockInput);
574
+ }
575
+ }
576
+ if (!blockInput.hasBlockAndAllData()) {
577
+ const cutoffTimeMs = getCutoffTimeMs(chain, dataColumnSlot, BLOCK_AVAILABILITY_CUTOFF_MS);
578
+ chain.logger.debug("Received gossip data column, waiting for full data availability", {
579
+ msToWait: cutoffTimeMs,
428
580
  dataColumnIndex: index,
429
581
  ...blockInputMeta,
430
582
  });
431
- chain.emitter.emit(ChainEvent.incompleteBlockInput, {
432
- blockInput,
433
- peer: peerIdStr,
434
- source: BlockInputSource.gossip,
583
+ // do not await here to not delay gossip validation
584
+ blockInput.waitForBlockAndAllData(cutoffTimeMs).catch((_e) => {
585
+ chain.logger.debug("Waited for data after receiving gossip column. Cut-off reached so attempting to fetch remainder of BlockInput", {
586
+ dataColumnIndex: index,
587
+ ...blockInputMeta,
588
+ });
589
+ chain.emitter.emit(ChainEvent.incompleteBlockInput, {
590
+ blockInput,
591
+ peer: peerIdStr,
592
+ source: BlockInputSource.gossip,
593
+ });
435
594
  });
436
- });
595
+ }
437
596
  }
438
- // TODO GLOAS: In Gloas, also add column to PayloadEnvelopeInput and notify the payload processor:
439
- // const payloadInput = chain.seenPayloadEnvelopeInput.get(blockRootHex);
440
- // if (payloadInput) {
441
- // payloadInput.addColumn({columnSidecar, source: BlockInputSource.gossip, seenTimestampSec, peerIdStr});
442
- // chain.processExecutionPayload(payloadInput, {validSignature: true});
443
- // }
444
597
  },
445
598
  [GossipType.beacon_aggregate_and_proof]: async ({ gossipData, topic, seenTimestampSec, }) => {
446
599
  const { serializedData } = gossipData;
@@ -584,14 +737,38 @@ function getSequentialHandlers(modules, options) {
584
737
  },
585
738
  [GossipType.execution_payload]: async ({ gossipData, topic, peerIdStr, seenTimestampSec, }) => {
586
739
  const { serializedData } = gossipData;
587
- const executionPayloadEnvelope = sszDeserialize(topic, serializedData);
588
- // TODO GLOAS: handle BLOCK_ROOT_UNKNOWN error to trigger sync
589
- await validateGossipExecutionPayloadEnvelope(chain, executionPayloadEnvelope);
590
- const slot = executionPayloadEnvelope.message.slot;
740
+ const signedEnvelope = sszDeserialize(topic, serializedData);
741
+ const envelope = signedEnvelope.message;
742
+ // TODO GLOAS: consider optimistically create PayloadEnvelopeInput here similar to how we do that for beacon_block
743
+ // so that UnknownBlockSync can handle backward sync
744
+ // the problem now is we cannot create a PayloadEnvelopeInput without the beacon block being known, we need at least the proposer index
745
+ // we can achieve that by looking into the EpochCache
746
+ try {
747
+ await validateGossipExecutionPayloadEnvelope(chain, signedEnvelope);
748
+ }
749
+ catch (e) {
750
+ if (e instanceof ExecutionPayloadEnvelopeError) {
751
+ const { slot, beaconBlockRoot } = signedEnvelope.message;
752
+ logger.debug("Gossip envelope has error", { slot, root: toRootHex(beaconBlockRoot), code: e.type.code });
753
+ if (e.type.code === ExecutionPayloadEnvelopeErrorCode.BLOCK_ROOT_UNKNOWN) {
754
+ // TODO GLOAS: UnknownBlockSync to handle this
755
+ chain.emitter.emit(ChainEvent.envelopeUnknownBlock, {
756
+ envelope: signedEnvelope,
757
+ peer: peerIdStr,
758
+ source: BlockInputSource.gossip,
759
+ });
760
+ }
761
+ if (e.action === GossipAction.REJECT) {
762
+ chain.persistInvalidSszValue(ssz.gloas.SignedExecutionPayloadEnvelope, signedEnvelope, `gossip_reject_slot_${slot}`);
763
+ }
764
+ }
765
+ throw e;
766
+ }
767
+ const slot = envelope.slot;
591
768
  const delaySec = seenTimestampSec - computeTimeAtSlot(config, slot, chain.genesisTime);
592
769
  metrics?.gossipExecutionPayloadEnvelope.elapsedTimeTillReceived.observe({ source: OpSource.gossip }, delaySec);
593
- chain.validatorMonitor?.registerExecutionPayloadEnvelope(OpSource.gossip, delaySec, executionPayloadEnvelope);
594
- const blockRootHex = toRootHex(executionPayloadEnvelope.message.beaconBlockRoot);
770
+ chain.validatorMonitor?.registerExecutionPayloadEnvelope(OpSource.gossip, delaySec, signedEnvelope);
771
+ const blockRootHex = toRootHex(envelope.beaconBlockRoot);
595
772
  const payloadInput = chain.seenPayloadEnvelopeInputCache.get(blockRootHex);
596
773
  if (!payloadInput) {
597
774
  // This shouldn't happen because beacon block should have been imported and thus payload input should have been created.
@@ -600,14 +777,20 @@ function getSequentialHandlers(modules, options) {
600
777
  blockRoot: blockRootHex,
601
778
  });
602
779
  }
603
- chain.serializedCache.set(executionPayloadEnvelope, serializedData);
780
+ chain.serializedCache.set(signedEnvelope, serializedData);
604
781
  payloadInput.addPayloadEnvelope({
605
- envelope: executionPayloadEnvelope,
782
+ envelope: signedEnvelope,
606
783
  source: PayloadEnvelopeInputSource.gossip,
607
784
  seenTimestampSec,
608
785
  peerIdStr,
609
786
  });
610
- // TODO GLOAS: Emit execution_payload_gossip event for gossip receipt.
787
+ chain.emitter.emit(routes.events.EventType.executionPayloadGossip, {
788
+ slot,
789
+ builderIndex: envelope.builderIndex,
790
+ blockHash: toRootHex(envelope.payload.blockHash),
791
+ blockRoot: blockRootHex,
792
+ stateRoot: toRootHex(envelope.stateRoot),
793
+ });
611
794
  chain.processExecutionPayload(payloadInput, { validSignature: true }).catch((e) => {
612
795
  chain.logger.debug("Error processing execution payload from gossip", { slot, root: blockRootHex }, e);
613
796
  });