@lodestar/beacon-node 1.51.0-dev.ab56d90f0c → 1.51.0-dev.ab8f3f6381

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 (414) hide show
  1. package/lib/api/impl/api.js +1 -1
  2. package/lib/api/impl/api.js.map +1 -1
  3. package/lib/api/impl/beacon/blocks/index.d.ts +2 -1
  4. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  5. package/lib/api/impl/beacon/blocks/index.js +29 -34
  6. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  7. package/lib/api/impl/beacon/index.d.ts +2 -1
  8. package/lib/api/impl/beacon/index.d.ts.map +1 -1
  9. package/lib/api/impl/beacon/index.js +2 -2
  10. package/lib/api/impl/beacon/index.js.map +1 -1
  11. package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
  12. package/lib/api/impl/beacon/pool/index.js +22 -2
  13. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  14. package/lib/api/impl/beacon/state/utils.d.ts +1 -1
  15. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  16. package/lib/api/impl/validator/index.d.ts +6 -0
  17. package/lib/api/impl/validator/index.d.ts.map +1 -1
  18. package/lib/api/impl/validator/index.js +42 -26
  19. package/lib/api/impl/validator/index.js.map +1 -1
  20. package/lib/api/options.d.ts +2 -0
  21. package/lib/api/options.d.ts.map +1 -1
  22. package/lib/api/options.js +1 -0
  23. package/lib/api/options.js.map +1 -1
  24. package/lib/chain/GetBlobsTracker.d.ts +13 -2
  25. package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
  26. package/lib/chain/GetBlobsTracker.js +85 -27
  27. package/lib/chain/GetBlobsTracker.js.map +1 -1
  28. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  29. package/lib/chain/archiveStore/archiveStore.js +1 -0
  30. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  31. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +4 -0
  32. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
  33. package/lib/chain/archiveStore/utils/archiveBlocks.js +61 -97
  34. package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
  35. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  36. package/lib/chain/blocks/importBlock.js +39 -50
  37. package/lib/chain/blocks/importBlock.js.map +1 -1
  38. package/lib/chain/blocks/importExecutionPayload.d.ts +10 -11
  39. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  40. package/lib/chain/blocks/importExecutionPayload.js +32 -18
  41. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  42. package/lib/chain/blocks/index.d.ts.map +1 -1
  43. package/lib/chain/blocks/index.js +4 -4
  44. package/lib/chain/blocks/index.js.map +1 -1
  45. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +12 -9
  46. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -1
  47. package/lib/chain/blocks/payloadEnvelopeProcessor.js +24 -19
  48. package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
  49. package/lib/chain/blocks/types.d.ts +4 -1
  50. package/lib/chain/blocks/types.d.ts.map +1 -1
  51. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  52. package/lib/chain/blocks/verifyBlock.js +18 -7
  53. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  54. package/lib/chain/blocks/verifyBlocksDataAvailability.d.ts.map +1 -1
  55. package/lib/chain/blocks/verifyBlocksDataAvailability.js +8 -1
  56. package/lib/chain/blocks/verifyBlocksDataAvailability.js.map +1 -1
  57. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +1 -1
  58. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  59. package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
  60. package/lib/chain/blocks/verifyBlocksSanityChecks.js +4 -0
  61. package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
  62. package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
  63. package/lib/chain/blocks/verifyBlocksSignatures.js +7 -5
  64. package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
  65. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts +3 -3
  66. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -1
  67. package/lib/chain/blocks/verifyPayloadsDataAvailability.js +11 -6
  68. package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -1
  69. package/lib/chain/bls/interface.d.ts +2 -0
  70. package/lib/chain/bls/interface.d.ts.map +1 -1
  71. package/lib/chain/bls/multithread/index.d.ts.map +1 -1
  72. package/lib/chain/bls/multithread/index.js +13 -11
  73. package/lib/chain/bls/multithread/index.js.map +1 -1
  74. package/lib/chain/bls/multithread/types.d.ts +1 -1
  75. package/lib/chain/bls/multithread/types.d.ts.map +1 -1
  76. package/lib/chain/bls/multithread/worker.js +1 -1
  77. package/lib/chain/bls/multithread/worker.js.map +1 -1
  78. package/lib/chain/bls/singleThread.js +1 -1
  79. package/lib/chain/bls/singleThread.js.map +1 -1
  80. package/lib/chain/bls/utils.js +1 -1
  81. package/lib/chain/bls/utils.js.map +1 -1
  82. package/lib/chain/chain.d.ts +25 -3
  83. package/lib/chain/chain.d.ts.map +1 -1
  84. package/lib/chain/chain.js +123 -10
  85. package/lib/chain/chain.js.map +1 -1
  86. package/lib/chain/emitter.d.ts +6 -0
  87. package/lib/chain/emitter.d.ts.map +1 -1
  88. package/lib/chain/emitter.js +5 -0
  89. package/lib/chain/emitter.js.map +1 -1
  90. package/lib/chain/errors/blockError.d.ts +1 -1
  91. package/lib/chain/errors/blockError.d.ts.map +1 -1
  92. package/lib/chain/errors/blockError.js +1 -1
  93. package/lib/chain/errors/blockError.js.map +1 -1
  94. package/lib/chain/errors/executionPayloadEnvelope.d.ts +7 -0
  95. package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
  96. package/lib/chain/errors/executionPayloadEnvelope.js +1 -0
  97. package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
  98. package/lib/chain/forkChoice/index.d.ts +11 -1
  99. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  100. package/lib/chain/forkChoice/index.js +11 -0
  101. package/lib/chain/forkChoice/index.js.map +1 -1
  102. package/lib/chain/forkChoiceExecutionEngine.d.ts +53 -0
  103. package/lib/chain/forkChoiceExecutionEngine.d.ts.map +1 -0
  104. package/lib/chain/forkChoiceExecutionEngine.js +121 -0
  105. package/lib/chain/forkChoiceExecutionEngine.js.map +1 -0
  106. package/lib/chain/interface.d.ts +9 -6
  107. package/lib/chain/interface.d.ts.map +1 -1
  108. package/lib/chain/interface.js.map +1 -1
  109. package/lib/chain/opPools/aggregatedAttestationPool.d.ts +17 -4
  110. package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
  111. package/lib/chain/opPools/aggregatedAttestationPool.js +199 -46
  112. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  113. package/lib/chain/opPools/attestationPool.d.ts +1 -1
  114. package/lib/chain/opPools/attestationPool.d.ts.map +1 -1
  115. package/lib/chain/opPools/attestationPool.js +15 -4
  116. package/lib/chain/opPools/attestationPool.js.map +1 -1
  117. package/lib/chain/opPools/index.d.ts +1 -0
  118. package/lib/chain/opPools/index.d.ts.map +1 -1
  119. package/lib/chain/opPools/index.js +1 -0
  120. package/lib/chain/opPools/index.js.map +1 -1
  121. package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -1
  122. package/lib/chain/opPools/payloadAttestationPool.js +17 -7
  123. package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
  124. package/lib/chain/opPools/singleAttestationPool.d.ts +77 -0
  125. package/lib/chain/opPools/singleAttestationPool.d.ts.map +1 -0
  126. package/lib/chain/opPools/singleAttestationPool.js +209 -0
  127. package/lib/chain/opPools/singleAttestationPool.js.map +1 -0
  128. package/lib/chain/opPools/syncCommitteeMessagePool.d.ts.map +1 -1
  129. package/lib/chain/opPools/syncCommitteeMessagePool.js +9 -3
  130. package/lib/chain/opPools/syncCommitteeMessagePool.js.map +1 -1
  131. package/lib/chain/opPools/syncContributionAndProofPool.d.ts.map +1 -1
  132. package/lib/chain/opPools/syncContributionAndProofPool.js +11 -3
  133. package/lib/chain/opPools/syncContributionAndProofPool.js.map +1 -1
  134. package/lib/chain/opPools/utils.d.ts +1 -1
  135. package/lib/chain/opPools/utils.d.ts.map +1 -1
  136. package/lib/chain/opPools/utils.js +1 -1
  137. package/lib/chain/opPools/utils.js.map +1 -1
  138. package/lib/chain/options.d.ts +5 -1
  139. package/lib/chain/options.d.ts.map +1 -1
  140. package/lib/chain/options.js +0 -1
  141. package/lib/chain/options.js.map +1 -1
  142. package/lib/chain/produceBlock/produceBlockBody.d.ts +3 -2
  143. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  144. package/lib/chain/produceBlock/produceBlockBody.js +3 -2
  145. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  146. package/lib/chain/proposerTracker.d.ts +31 -0
  147. package/lib/chain/proposerTracker.d.ts.map +1 -0
  148. package/lib/chain/proposerTracker.js +75 -0
  149. package/lib/chain/proposerTracker.js.map +1 -0
  150. package/lib/chain/regen/interface.d.ts +1 -2
  151. package/lib/chain/regen/interface.d.ts.map +1 -1
  152. package/lib/chain/regen/interface.js +0 -1
  153. package/lib/chain/regen/interface.js.map +1 -1
  154. package/lib/chain/regen/queued.d.ts +1 -1
  155. package/lib/chain/regen/queued.d.ts.map +1 -1
  156. package/lib/chain/regen/queued.js +5 -3
  157. package/lib/chain/regen/queued.js.map +1 -1
  158. package/lib/chain/validation/executionPayloadBid.d.ts +0 -15
  159. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  160. package/lib/chain/validation/executionPayloadBid.js +13 -166
  161. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  162. package/lib/chain/validation/executionPayloadEnvelope.d.ts +6 -0
  163. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  164. package/lib/chain/validation/executionPayloadEnvelope.js +53 -0
  165. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  166. package/lib/db/beacon.d.ts +7 -0
  167. package/lib/db/beacon.d.ts.map +1 -1
  168. package/lib/db/beacon.js +34 -0
  169. package/lib/db/beacon.js.map +1 -1
  170. package/lib/db/dataColumnStore.d.ts +1 -1
  171. package/lib/db/dataColumnStore.d.ts.map +1 -1
  172. package/lib/db/dataColumnStore.js +1 -4
  173. package/lib/db/dataColumnStore.js.map +1 -1
  174. package/lib/db/flatFileStore/flatFileStore.js +5 -5
  175. package/lib/db/flatFileStore/flatFileStore.js.map +1 -1
  176. package/lib/db/flatFileStore/slotIndex.d.ts.map +1 -1
  177. package/lib/db/flatFileStore/slotIndex.js +2 -2
  178. package/lib/db/flatFileStore/slotIndex.js.map +1 -1
  179. package/lib/db/interface.d.ts +1 -0
  180. package/lib/db/interface.d.ts.map +1 -1
  181. package/lib/db/repositories/dataColumnSidecarArchive.d.ts +6 -0
  182. package/lib/db/repositories/dataColumnSidecarArchive.d.ts.map +1 -1
  183. package/lib/db/repositories/dataColumnSidecarArchive.js +19 -0
  184. package/lib/db/repositories/dataColumnSidecarArchive.js.map +1 -1
  185. package/lib/execution/builder/apiClient.d.ts +14 -8
  186. package/lib/execution/builder/apiClient.d.ts.map +1 -1
  187. package/lib/execution/builder/apiClient.js +12 -10
  188. package/lib/execution/builder/apiClient.js.map +1 -1
  189. package/lib/execution/builder/http.d.ts +2 -0
  190. package/lib/execution/builder/http.d.ts.map +1 -1
  191. package/lib/execution/builder/http.js +2 -0
  192. package/lib/execution/builder/http.js.map +1 -1
  193. package/lib/execution/engine/http.d.ts +2 -2
  194. package/lib/execution/engine/http.d.ts.map +1 -1
  195. package/lib/execution/engine/http.js +5 -4
  196. package/lib/execution/engine/http.js.map +1 -1
  197. package/lib/execution/engine/index.d.ts +1 -1
  198. package/lib/execution/engine/index.d.ts.map +1 -1
  199. package/lib/execution/engine/index.js +1 -1
  200. package/lib/execution/engine/index.js.map +1 -1
  201. package/lib/execution/engine/interface.d.ts +17 -3
  202. package/lib/execution/engine/interface.d.ts.map +1 -1
  203. package/lib/execution/engine/interface.js.map +1 -1
  204. package/lib/execution/engine/jsonRpcTransport.d.ts +2 -2
  205. package/lib/execution/engine/jsonRpcTransport.d.ts.map +1 -1
  206. package/lib/execution/engine/jsonRpcTransport.js +1 -1
  207. package/lib/execution/engine/jsonRpcTransport.js.map +1 -1
  208. package/lib/execution/engine/restTransport.d.ts +2 -2
  209. package/lib/execution/engine/restTransport.d.ts.map +1 -1
  210. package/lib/execution/engine/restTransport.js.map +1 -1
  211. package/lib/execution/engine/transport.d.ts +1 -12
  212. package/lib/execution/engine/transport.d.ts.map +1 -1
  213. package/lib/execution/engine/types.d.ts.map +1 -1
  214. package/lib/execution/engine/types.js +2 -2
  215. package/lib/execution/engine/types.js.map +1 -1
  216. package/lib/execution/engine/utils.d.ts.map +1 -1
  217. package/lib/execution/engine/utils.js +3 -2
  218. package/lib/execution/engine/utils.js.map +1 -1
  219. package/lib/index.d.ts +1 -0
  220. package/lib/index.d.ts.map +1 -1
  221. package/lib/index.js +2 -0
  222. package/lib/index.js.map +1 -1
  223. package/lib/metrics/metrics/lodestar.d.ts +33 -0
  224. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  225. package/lib/metrics/metrics/lodestar.js +84 -0
  226. package/lib/metrics/metrics/lodestar.js.map +1 -1
  227. package/lib/metrics/server/http.js +5 -5
  228. package/lib/metrics/server/http.js.map +1 -1
  229. package/lib/monitoring/service.js +1 -1
  230. package/lib/monitoring/service.js.map +1 -1
  231. package/lib/network/core/networkCore.d.ts +4 -1
  232. package/lib/network/core/networkCore.d.ts.map +1 -1
  233. package/lib/network/core/networkCore.js +7 -0
  234. package/lib/network/core/networkCore.js.map +1 -1
  235. package/lib/network/core/networkCoreWorker.js +2 -0
  236. package/lib/network/core/networkCoreWorker.js.map +1 -1
  237. package/lib/network/core/networkCoreWorkerHandler.d.ts +4 -1
  238. package/lib/network/core/networkCoreWorkerHandler.d.ts.map +1 -1
  239. package/lib/network/core/networkCoreWorkerHandler.js +6 -0
  240. package/lib/network/core/networkCoreWorkerHandler.js.map +1 -1
  241. package/lib/network/core/types.d.ts +6 -1
  242. package/lib/network/core/types.d.ts.map +1 -1
  243. package/lib/network/gossip/gossipsub.d.ts +1 -0
  244. package/lib/network/gossip/gossipsub.d.ts.map +1 -1
  245. package/lib/network/gossip/gossipsub.js +10 -0
  246. package/lib/network/gossip/gossipsub.js.map +1 -1
  247. package/lib/network/interface.d.ts +2 -0
  248. package/lib/network/interface.d.ts.map +1 -1
  249. package/lib/network/libp2p/index.d.ts.map +1 -1
  250. package/lib/network/libp2p/index.js +5 -1
  251. package/lib/network/libp2p/index.js.map +1 -1
  252. package/lib/network/network.d.ts +6 -1
  253. package/lib/network/network.d.ts.map +1 -1
  254. package/lib/network/network.js +53 -15
  255. package/lib/network/network.js.map +1 -1
  256. package/lib/network/options.d.ts +2 -0
  257. package/lib/network/options.d.ts.map +1 -1
  258. package/lib/network/options.js +2 -0
  259. package/lib/network/options.js.map +1 -1
  260. package/lib/network/peers/peerManager.d.ts +2 -1
  261. package/lib/network/peers/peerManager.d.ts.map +1 -1
  262. package/lib/network/peers/peerManager.js +28 -1
  263. package/lib/network/peers/peerManager.js.map +1 -1
  264. package/lib/network/peers/utils/assertPeerRelevance.d.ts +9 -1
  265. package/lib/network/peers/utils/assertPeerRelevance.d.ts.map +1 -1
  266. package/lib/network/peers/utils/assertPeerRelevance.js +32 -21
  267. package/lib/network/peers/utils/assertPeerRelevance.js.map +1 -1
  268. package/lib/network/peers/utils/prioritizePeers.d.ts +4 -1
  269. package/lib/network/peers/utils/prioritizePeers.d.ts.map +1 -1
  270. package/lib/network/peers/utils/prioritizePeers.js +8 -16
  271. package/lib/network/peers/utils/prioritizePeers.js.map +1 -1
  272. package/lib/network/peers/utils/subnetMap.d.ts +5 -2
  273. package/lib/network/peers/utils/subnetMap.d.ts.map +1 -1
  274. package/lib/network/peers/utils/subnetMap.js +6 -3
  275. package/lib/network/peers/utils/subnetMap.js.map +1 -1
  276. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  277. package/lib/network/processor/gossipHandlers.js +77 -37
  278. package/lib/network/processor/gossipHandlers.js.map +1 -1
  279. package/lib/network/processor/index.d.ts +6 -0
  280. package/lib/network/processor/index.d.ts.map +1 -1
  281. package/lib/network/processor/index.js +29 -3
  282. package/lib/network/processor/index.js.map +1 -1
  283. package/lib/network/subnets/attnetsService.d.ts +35 -5
  284. package/lib/network/subnets/attnetsService.d.ts.map +1 -1
  285. package/lib/network/subnets/attnetsService.js +84 -6
  286. package/lib/network/subnets/attnetsService.js.map +1 -1
  287. package/lib/network/subnets/interface.d.ts +7 -0
  288. package/lib/network/subnets/interface.d.ts.map +1 -1
  289. package/lib/network/subnets/interface.js.map +1 -1
  290. package/lib/node/nodejs.d.ts +3 -1
  291. package/lib/node/nodejs.d.ts.map +1 -1
  292. package/lib/node/nodejs.js +47 -21
  293. package/lib/node/nodejs.js.map +1 -1
  294. package/lib/node/options.d.ts +3 -1
  295. package/lib/node/options.d.ts.map +1 -1
  296. package/lib/node/options.js +4 -2
  297. package/lib/node/options.js.map +1 -1
  298. package/lib/sync/interface.d.ts.map +1 -1
  299. package/lib/sync/interface.js.map +1 -1
  300. package/lib/sync/sync.d.ts +7 -0
  301. package/lib/sync/sync.d.ts.map +1 -1
  302. package/lib/sync/sync.js +61 -3
  303. package/lib/sync/sync.js.map +1 -1
  304. package/lib/sync/unknownBlock.d.ts.map +1 -1
  305. package/lib/sync/unknownBlock.js +42 -18
  306. package/lib/sync/unknownBlock.js.map +1 -1
  307. package/lib/util/execution.d.ts +4 -4
  308. package/lib/util/execution.d.ts.map +1 -1
  309. package/lib/util/execution.js.map +1 -1
  310. package/lib/util/file.d.ts.map +1 -1
  311. package/lib/util/file.js +8 -9
  312. package/lib/util/file.js.map +1 -1
  313. package/lib/util/queue/itemQueue.js +1 -1
  314. package/lib/util/queue/itemQueue.js.map +1 -1
  315. package/lib/util/sszBytes.d.ts +5 -0
  316. package/lib/util/sszBytes.d.ts.map +1 -1
  317. package/lib/util/sszBytes.js +35 -2
  318. package/lib/util/sszBytes.js.map +1 -1
  319. package/package.json +16 -17
  320. package/src/api/impl/api.ts +1 -1
  321. package/src/api/impl/beacon/blocks/index.ts +57 -62
  322. package/src/api/impl/beacon/index.ts +3 -1
  323. package/src/api/impl/beacon/pool/index.ts +31 -1
  324. package/src/api/impl/beacon/state/utils.ts +1 -1
  325. package/src/api/impl/validator/index.ts +47 -30
  326. package/src/api/options.ts +3 -0
  327. package/src/chain/GetBlobsTracker.ts +99 -40
  328. package/src/chain/archiveStore/archiveStore.ts +1 -0
  329. package/src/chain/archiveStore/utils/archiveBlocks.ts +76 -130
  330. package/src/chain/blocks/importBlock.ts +60 -71
  331. package/src/chain/blocks/importExecutionPayload.ts +55 -34
  332. package/src/chain/blocks/index.ts +11 -4
  333. package/src/chain/blocks/payloadEnvelopeProcessor.ts +35 -24
  334. package/src/chain/blocks/types.ts +4 -1
  335. package/src/chain/blocks/verifyBlock.ts +31 -16
  336. package/src/chain/blocks/verifyBlocksDataAvailability.ts +10 -1
  337. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +1 -1
  338. package/src/chain/blocks/verifyBlocksSanityChecks.ts +4 -1
  339. package/src/chain/blocks/verifyBlocksSignatures.ts +7 -5
  340. package/src/chain/blocks/verifyPayloadsDataAvailability.ts +14 -6
  341. package/src/chain/bls/interface.ts +2 -0
  342. package/src/chain/bls/multithread/index.ts +14 -10
  343. package/src/chain/bls/multithread/types.ts +1 -1
  344. package/src/chain/bls/multithread/worker.ts +1 -5
  345. package/src/chain/bls/singleThread.ts +1 -1
  346. package/src/chain/bls/utils.ts +1 -1
  347. package/src/chain/chain.ts +139 -8
  348. package/src/chain/emitter.ts +7 -0
  349. package/src/chain/errors/blockError.ts +1 -1
  350. package/src/chain/errors/executionPayloadEnvelope.ts +8 -0
  351. package/src/chain/forkChoice/index.ts +11 -0
  352. package/src/chain/forkChoiceExecutionEngine.ts +197 -0
  353. package/src/chain/interface.ts +9 -5
  354. package/src/chain/opPools/aggregatedAttestationPool.ts +246 -43
  355. package/src/chain/opPools/attestationPool.ts +16 -4
  356. package/src/chain/opPools/index.ts +1 -0
  357. package/src/chain/opPools/payloadAttestationPool.ts +18 -7
  358. package/src/chain/opPools/singleAttestationPool.ts +287 -0
  359. package/src/chain/opPools/syncCommitteeMessagePool.ts +10 -3
  360. package/src/chain/opPools/syncContributionAndProofPool.ts +13 -3
  361. package/src/chain/opPools/utils.ts +1 -1
  362. package/src/chain/options.ts +5 -2
  363. package/src/chain/produceBlock/produceBlockBody.ts +7 -3
  364. package/src/chain/proposerTracker.ts +94 -0
  365. package/src/chain/regen/interface.ts +1 -2
  366. package/src/chain/regen/queued.ts +6 -4
  367. package/src/chain/validation/executionPayloadBid.ts +14 -193
  368. package/src/chain/validation/executionPayloadEnvelope.ts +68 -1
  369. package/src/db/beacon.ts +44 -0
  370. package/src/db/dataColumnStore.ts +2 -4
  371. package/src/db/flatFileStore/flatFileStore.ts +7 -7
  372. package/src/db/flatFileStore/slotIndex.ts +4 -3
  373. package/src/db/interface.ts +2 -0
  374. package/src/db/repositories/dataColumnSidecarArchive.ts +20 -0
  375. package/src/execution/builder/apiClient.ts +16 -13
  376. package/src/execution/builder/http.ts +4 -0
  377. package/src/execution/engine/http.ts +12 -13
  378. package/src/execution/engine/index.ts +1 -1
  379. package/src/execution/engine/interface.ts +19 -3
  380. package/src/execution/engine/jsonRpcTransport.ts +10 -2
  381. package/src/execution/engine/restTransport.ts +3 -1
  382. package/src/execution/engine/transport.ts +8 -14
  383. package/src/execution/engine/types.ts +3 -1
  384. package/src/execution/engine/utils.ts +4 -2
  385. package/src/index.ts +2 -0
  386. package/src/metrics/metrics/lodestar.ts +85 -0
  387. package/src/metrics/server/http.ts +5 -5
  388. package/src/monitoring/service.ts +1 -1
  389. package/src/network/core/networkCore.ts +11 -1
  390. package/src/network/core/networkCoreWorker.ts +2 -0
  391. package/src/network/core/networkCoreWorkerHandler.ts +8 -1
  392. package/src/network/core/types.ts +6 -1
  393. package/src/network/gossip/gossipsub.ts +11 -0
  394. package/src/network/interface.ts +2 -0
  395. package/src/network/libp2p/index.ts +5 -1
  396. package/src/network/network.ts +55 -19
  397. package/src/network/options.ts +4 -0
  398. package/src/network/peers/peerManager.ts +28 -3
  399. package/src/network/peers/utils/assertPeerRelevance.ts +39 -23
  400. package/src/network/peers/utils/prioritizePeers.ts +14 -22
  401. package/src/network/peers/utils/subnetMap.ts +6 -3
  402. package/src/network/processor/gossipHandlers.ts +98 -40
  403. package/src/network/processor/index.ts +25 -3
  404. package/src/network/subnets/attnetsService.ts +94 -6
  405. package/src/network/subnets/interface.ts +7 -0
  406. package/src/node/nodejs.ts +58 -22
  407. package/src/node/options.ts +9 -6
  408. package/src/sync/interface.ts +1 -0
  409. package/src/sync/sync.ts +65 -4
  410. package/src/sync/unknownBlock.ts +47 -28
  411. package/src/util/execution.ts +6 -6
  412. package/src/util/file.ts +8 -9
  413. package/src/util/queue/itemQueue.ts +1 -1
  414. package/src/util/sszBytes.ts +42 -2
@@ -1,7 +1,7 @@
1
- import {Signature, aggregateSignatures} from "@chainsafe/lodestar-z/blst";
2
1
  import {BitArray} from "@chainsafe/ssz";
3
2
  import {BeaconConfig} from "@lodestar/config";
4
3
  import {IForkChoice} from "@lodestar/fork-choice";
4
+ import {Signature, aggregateSignatures} from "@lodestar/native/blst";
5
5
  import {
6
6
  ForkName,
7
7
  ForkSeq,
@@ -20,6 +20,7 @@ import {
20
20
  } from "@lodestar/params";
21
21
  import {
22
22
  EffectiveBalanceIncrements,
23
+ G2_POINT_AT_INFINITY,
23
24
  IBeaconStateView,
24
25
  RootCache,
25
26
  computeEpochAtSlot,
@@ -30,11 +31,12 @@ import {
30
31
  isStatePostGloas,
31
32
  } from "@lodestar/state-transition";
32
33
  import {Attestation, Epoch, RootHex, Slot, electra, isElectraAttestation, phase0, ssz} from "@lodestar/types";
33
- import {Logger, MapDef, assert, toRootHex} from "@lodestar/utils";
34
+ import {Logger, MapDef, assert, byteArrayEquals, toRootHex} from "@lodestar/utils";
34
35
  import {Metrics} from "../../metrics/metrics.js";
35
36
  import {IntersectResult, intersectUint8Arrays} from "../../util/bitArray.js";
36
37
  import {getShufflingDependentRoot} from "../../util/dependentRoot.js";
37
38
  import {ShufflingCache} from "../shufflingCache.js";
39
+ import {SingleAttestationPool, SinglesForCommittee} from "./singleAttestationPool.js";
38
40
  import {InsertOutcome} from "./types.js";
39
41
  import {pruneBySlot, signatureFromBytesNoCheck} from "./utils.js";
40
42
 
@@ -48,12 +50,23 @@ type CommitteeIndex = number;
48
50
  */
49
51
  export type AttestationsConsolidation = {
50
52
  byCommittee: Map<CommitteeIndex, AttestationNonParticipant>;
53
+ /**
54
+ * Single attestations of committee members that no aggregate in `byCommittee` covers, a committee may have both.
55
+ * Disjoint from `byCommittee` by construction so the signatures can be aggregated together
56
+ */
57
+ singlesByCommittee: Map<CommitteeIndex, SinglesForCommittee>;
51
58
  attData: phase0.AttestationData;
52
59
  totalNewSeenEffectiveBalance: number;
53
60
  newSeenAttesters: number;
54
61
  notSeenAttesters: number;
55
62
  /** total number of attesters across all committees in this consolidation */
56
63
  totalAttesters: number;
64
+ /** part of `totalNewSeenEffectiveBalance` contributed by `singlesByCommittee` */
65
+ singlesNewSeenEffectiveBalance: number;
66
+ /** part of `newSeenAttesters` contributed by `singlesByCommittee` */
67
+ singlesNewSeenAttesters: number;
68
+ /** sum of participation flag weights this consolidation earns, set when scoring */
69
+ weight: number;
57
70
  };
58
71
 
59
72
  /**
@@ -109,6 +122,14 @@ const MAX_ATTESTATIONS_PER_GROUP_ELECTRA = Math.min(
109
122
  MAX_ATTESTATIONS_ELECTRA
110
123
  );
111
124
 
125
+ /**
126
+ * Bounds the single attestation signatures decoded and aggregated synchronously in block production. Without
127
+ * aggregates (e.g. during non-finality) the pool can hold far more uncovered singles than a block needs.
128
+ * The budget is spent in scan order, also by candidates that later miss the top MAX_ATTESTATIONS_ELECTRA
129
+ * As tested on Nov 2026, we never this many not-seen attesters on mainnet.
130
+ */
131
+ const MAX_SINGLE_ATTESTATIONS_PER_BLOCK = 1024;
132
+
112
133
  /** Same to https://github.com/ethereum/consensus-specs/blob/v1.5.0/specs/altair/beacon-chain.md#has_flag */
113
134
  const TIMELY_SOURCE = 1 << TIMELY_SOURCE_FLAG_INDEX;
114
135
  const TIMELY_TARGET = 1 << TIMELY_TARGET_FLAG_INDEX;
@@ -212,24 +233,27 @@ export class AggregatedAttestationPool {
212
233
  fork: ForkName,
213
234
  forkChoice: IForkChoice,
214
235
  shufflingCache: ShufflingCache,
215
- state: IBeaconStateView
236
+ state: IBeaconStateView,
237
+ singleAttestationPool: SingleAttestationPool
216
238
  ): Attestation[] {
217
239
  const forkSeq = ForkSeq[fork];
218
240
  if (forkSeq < ForkSeq.electra) {
219
241
  throw new Error("Does not support producing blocks for pre-electra forks anymore");
220
242
  }
221
243
 
222
- return this.getAttestationsForBlockElectra(fork, forkChoice, shufflingCache, state);
244
+ return this.getAttestationsForBlockElectra(fork, forkChoice, shufflingCache, state, singleAttestationPool);
223
245
  }
224
246
 
225
247
  /**
226
- * Get attestations to be included in an electra block. Returns up to $MAX_ATTESTATIONS_ELECTRA items
248
+ * Get attestations to be included in an electra block. Returns up to $MAX_ATTESTATIONS_ELECTRA items.
249
+ * Single attestations fill committee members that no picked aggregate covers, see `addSinglesToConsolidation`
227
250
  */
228
251
  getAttestationsForBlockElectra(
229
252
  fork: ForkName,
230
253
  forkChoice: IForkChoice,
231
254
  shufflingCache: ShufflingCache,
232
- state: IBeaconStateView
255
+ state: IBeaconStateView,
256
+ singleAttestationPool: SingleAttestationPool
233
257
  ): electra.Attestation[] {
234
258
  const stateSlot = state.slot;
235
259
  const stateEpoch = state.epoch;
@@ -240,18 +264,27 @@ export class AggregatedAttestationPool {
240
264
  const notSeenValidatorsFn = getNotSeenValidatorsFn(this.config, shufflingCache, state);
241
265
  const validateAttestationDataFn = getValidateAttestationDataFn(forkChoice, state);
242
266
 
243
- const slots = Array.from(this.attestationGroupByIndexByDataHexBySlot.keys()).sort((a, b) => b - a);
267
+ const slots = Array.from(
268
+ new Set([...this.attestationGroupByIndexByDataHexBySlot.keys(), ...singleAttestationPool.getStoredSlots()])
269
+ ).sort((a, b) => b - a);
244
270
  // Track score of each `AttestationsConsolidation`
245
271
  const consolidations = new Map<AttestationsConsolidation, number>();
272
+ let remainingSingles = MAX_SINGLE_ATTESTATIONS_PER_BLOCK;
246
273
  let scannedSlots = 0;
247
274
  let stopReason: ScannedSlotsTerminationReason | null = null;
248
275
  const missingShufflingCommitteesByEpoch = new Map<Epoch, number>();
276
+ // reset so that inclusion distances not scanned for this block do not keep values of a previous block
277
+ this.metrics?.opPool.aggregatedAttestationPool.packedAttestations.returnedAttestations.reset();
278
+ this.metrics?.opPool.aggregatedAttestationPool.packedAttestations.scannedAttestations.reset();
249
279
  slot: for (const slot of slots) {
250
- const attestationGroupByIndexByDataHash = this.attestationGroupByIndexByDataHexBySlot.get(slot);
251
- // should not happen
252
- if (!attestationGroupByIndexByDataHash) {
253
- throw Error(`No aggregated attestation pool for slot=${slot}`);
254
- }
280
+ // a slot may only have single attestations, e.g. votes for a minority head that nobody aggregated
281
+ const attestationGroupByIndexByDataHash =
282
+ this.attestationGroupByIndexByDataHexBySlot.get(slot) ??
283
+ new Map<DataRootHex, Map<CommitteeIndex, MatchingDataAttestationGroup>>();
284
+ const singlesDataBySlot =
285
+ remainingSingles > 0
286
+ ? singleAttestationPool.getDataRoots(slot)
287
+ : new Map<DataRootHex, phase0.AttestationData>();
255
288
 
256
289
  const epoch = computeEpochAtSlot(slot);
257
290
  if (epoch < statePrevEpoch) {
@@ -278,16 +311,22 @@ export class AggregatedAttestationPool {
278
311
  // Attestations att00 --- att10 --- att20 --- 0 (att 00 10 20)
279
312
  // att01 --- - --- att21 --- 1 (att 01 __ 21)
280
313
  // - --- - --- att22 --- 2 (att __ __ 22)
281
- for (const attestationGroupByIndex of attestationGroupByIndexByDataHash.values()) {
314
+ const dataRootHexes = new Set([...attestationGroupByIndexByDataHash.keys(), ...singlesDataBySlot.keys()]);
315
+ for (const dataRootHex of dataRootHexes) {
316
+ if (remainingSingles === 0 && !attestationGroupByIndexByDataHash.has(dataRootHex)) {
317
+ continue;
318
+ }
319
+ const attestationGroupByIndex =
320
+ attestationGroupByIndexByDataHash.get(dataRootHex) ?? new Map<CommitteeIndex, MatchingDataAttestationGroup>();
282
321
  // sameAttDataCons could be up to MAX_ATTESTATIONS_PER_GROUP_ELECTRA
283
322
  const sameAttDataCons: AttestationsConsolidation[] = [];
284
- const allAttestationGroups = Array.from(attestationGroupByIndex.values());
285
- if (allAttestationGroups.length === 0) {
323
+ const attData = attestationGroupByIndex.values().next().value?.data ?? singlesDataBySlot.get(dataRootHex);
324
+ if (attData === undefined) {
286
325
  this.metrics?.opPool.aggregatedAttestationPool.packedAttestations.emptyAttestationData.inc();
287
326
  continue;
288
327
  }
289
328
 
290
- const invalidAttDataReason = validateAttestationDataFn(allAttestationGroups[0].data);
329
+ const invalidAttDataReason = validateAttestationDataFn(attData);
291
330
  if (invalidAttDataReason !== null) {
292
331
  this.metrics?.opPool.aggregatedAttestationPool.packedAttestations.invalidAttestationData.inc({
293
332
  reason: invalidAttDataReason,
@@ -295,6 +334,8 @@ export class AggregatedAttestationPool {
295
334
  continue;
296
335
  }
297
336
 
337
+ // committee members not on chain and not covered by any picked aggregate, owned by this loop
338
+ const remainingNotSeenByCommittee = new Map<CommitteeIndex, Set<number>>();
298
339
  for (const [committeeIndex, attestationGroup] of attestationGroupByIndex.entries()) {
299
340
  const notSeenCommitteeMembers = notSeenValidatorsFn(epoch, slot, committeeIndex);
300
341
  if (notSeenCommitteeMembers === null) {
@@ -326,18 +367,16 @@ export class AggregatedAttestationPool {
326
367
  const attestationsSameGroup = getAttestationGroupResult.result;
327
368
  returnedAttestationsPerSlot += attestationsSameGroup.length;
328
369
  totalAttestationsPerSlot += getAttestationGroupResult.totalAttestations;
370
+ // notSeenCommitteeMembers of the last pick are the ones no pick covers, it's a new Set (not the cached one)
371
+ remainingNotSeenByCommittee.set(
372
+ committeeIndex,
373
+ attestationsSameGroup.at(-1)?.notSeenCommitteeMembers ?? notSeenCommitteeMembers
374
+ );
329
375
 
330
376
  for (const [i, attestationNonParticipation] of attestationsSameGroup.entries()) {
331
377
  // sameAttDataCons shares the same index for different committees so we use index `i` here
332
378
  if (sameAttDataCons[i] === undefined) {
333
- sameAttDataCons[i] = {
334
- byCommittee: new Map(),
335
- attData: attestationNonParticipation.attestation.data,
336
- totalNewSeenEffectiveBalance: 0,
337
- newSeenAttesters: 0,
338
- notSeenAttesters: 0,
339
- totalAttesters: 0,
340
- };
379
+ sameAttDataCons[i] = newConsolidation(attestationNonParticipation.attestation.data);
341
380
  }
342
381
  const sameAttDataCon = sameAttDataCons[i];
343
382
  // committeeIndex was from a map so it should be unique, but just in case
@@ -351,6 +390,34 @@ export class AggregatedAttestationPool {
351
390
  }
352
391
  } // all committees are processed
353
392
 
393
+ for (const committeeIndex of singleAttestationPool.getCommitteeIndices(slot, dataRootHex)) {
394
+ if (remainingSingles === 0) {
395
+ break;
396
+ }
397
+ // a committee with no aggregate for this data starts from on chain participation (cached set, read only)
398
+ const notSeenCommitteeMembers =
399
+ remainingNotSeenByCommittee.get(committeeIndex) ?? notSeenValidatorsFn(epoch, slot, committeeIndex);
400
+ if (notSeenCommitteeMembers === null || notSeenCommitteeMembers.size === 0) {
401
+ continue;
402
+ }
403
+
404
+ const singles = singleAttestationPool.getUncovered(
405
+ slot,
406
+ dataRootHex,
407
+ committeeIndex,
408
+ notSeenCommitteeMembers,
409
+ state.effectiveBalanceIncrements,
410
+ remainingSingles
411
+ );
412
+ if (singles !== null) {
413
+ // the first consolidation holds the best aggregate of every committee, adding singles to it costs no
414
+ // extra attestation in the block. It's created if this data has no aggregate at all
415
+ sameAttDataCons[0] ??= newConsolidation(attData);
416
+ addSinglesToConsolidation(sameAttDataCons[0], committeeIndex, singles, notSeenCommitteeMembers.size);
417
+ remainingSingles -= singles.newSeenAttesters;
418
+ }
419
+ }
420
+
354
421
  this.metrics?.opPool.aggregatedAttestationPool.packedAttestations.returnedAttestations.set(
355
422
  {inclusionDistance},
356
423
  returnedAttestationsPerSlot
@@ -373,16 +440,16 @@ export class AggregatedAttestationPool {
373
440
  gloasState?.latestBlockHeader.slot ?? null
374
441
  );
375
442
 
376
- const weight =
443
+ consolidation.weight =
377
444
  ((flags & TIMELY_SOURCE) === TIMELY_SOURCE ? TIMELY_SOURCE_WEIGHT : 0) +
378
445
  ((flags & TIMELY_TARGET) === TIMELY_TARGET ? TIMELY_TARGET_WEIGHT : 0) +
379
446
  ((flags & TIMELY_HEAD) === TIMELY_HEAD ? TIMELY_HEAD_WEIGHT : 0);
380
447
 
381
- const score = consolidation.totalNewSeenEffectiveBalance * weight;
448
+ const score = consolidation.totalNewSeenEffectiveBalance * consolidation.weight;
382
449
 
383
450
  consolidations.set(consolidation, score);
384
- // Stop accumulating attestations there are enough that may have good scoring
385
- if (consolidations.size >= MAX_ATTESTATIONS_ELECTRA * 2) {
451
+ // bound the max consolidation candidates, does not likely happen on mainnet through
452
+ if (consolidations.size >= MAX_ATTESTATIONS_ELECTRA * 4) {
386
453
  stopReason = ScannedSlotsTerminationReason.MaxConsolidationReached;
387
454
  break slot;
388
455
  }
@@ -409,27 +476,104 @@ export class AggregatedAttestationPool {
409
476
 
410
477
  const sortedConsolidationsByScore = Array.from(consolidations.entries())
411
478
  .sort((a, b) => b[1] - a[1])
412
- .map(([consolidation, _]) => consolidation)
413
- .slice(0, MAX_ATTESTATIONS_ELECTRA);
479
+ .map(([consolidation, _]) => consolidation);
414
480
 
415
481
  // on chain aggregation is expensive, only do it after all
416
482
  const packedAttestationsMetrics = this.metrics?.opPool.aggregatedAttestationPool.packedAttestations;
417
- const packedAttestations: electra.Attestation[] = new Array(sortedConsolidationsByScore.length);
418
- for (const [i, consolidation] of sortedConsolidationsByScore.entries()) {
419
- packedAttestations[i] = aggregateConsolidation(consolidation);
483
+ const packedAttestations: electra.Attestation[] = [];
484
+ const packedConsolidations: AttestationsConsolidation[] = [];
485
+ // reset so that indexes beyond the packed attestations of this block do not keep values of a previous block
486
+ packedAttestationsMetrics?.committeeCount.reset();
487
+ packedAttestationsMetrics?.totalAttesters.reset();
488
+ packedAttestationsMetrics?.nonParticipation.reset();
489
+ packedAttestationsMetrics?.inclusionDistance.reset();
490
+ packedAttestationsMetrics?.newSeenAttesters.reset();
491
+ packedAttestationsMetrics?.totalEffectiveBalance.reset();
492
+ for (const consolidation of sortedConsolidationsByScore) {
493
+ if (packedAttestations.length >= MAX_ATTESTATIONS_ELECTRA) {
494
+ break;
495
+ }
496
+
497
+ const attestation = aggregateConsolidation(consolidation);
498
+ const committeeCount = attestation.committeeBits.getTrueBitIndexes().length;
499
+ // The point at infinity is not a valid aggregate signature, exclude it from the block
500
+ if (byteArrayEquals(attestation.signature, G2_POINT_AT_INFINITY)) {
501
+ this.logger?.debug("Excluding aggregate with infinity signature", {
502
+ slot: stateSlot,
503
+ attestationSlot: attestation.data.slot,
504
+ committees: committeeCount,
505
+ });
506
+ continue;
507
+ }
508
+
509
+ const i = packedAttestations.push(attestation) - 1;
510
+ packedConsolidations.push(consolidation);
420
511
 
421
512
  // record metrics of packed attestations
422
- packedAttestationsMetrics?.committeeCount.set({index: i}, consolidation.byCommittee.size);
513
+ packedAttestationsMetrics?.committeeCount.set({index: i}, committeeCount);
423
514
  packedAttestationsMetrics?.totalAttesters.set({index: i}, consolidation.totalAttesters);
424
515
  packedAttestationsMetrics?.nonParticipation.set({index: i}, consolidation.notSeenAttesters);
425
- packedAttestationsMetrics?.inclusionDistance.set({index: i}, stateSlot - packedAttestations[i].data.slot);
516
+ packedAttestationsMetrics?.inclusionDistance.set({index: i}, stateSlot - attestation.data.slot);
426
517
  packedAttestationsMetrics?.newSeenAttesters.set({index: i}, consolidation.newSeenAttesters);
427
518
  packedAttestationsMetrics?.totalEffectiveBalance.set({index: i}, consolidation.totalNewSeenEffectiveBalance);
428
519
  }
429
520
 
521
+ // value is proportional to the proposer reward of the attestations, singles are disjoint from aggregates
522
+ // so their part is exactly what they add on top of an aggregates only block
523
+ let totalValue = 0;
524
+ let singlesValue = 0;
525
+ let newSeenAttesters = 0;
526
+ let singlesNewSeenAttesters = 0;
527
+ let singlesNewSeenEffectiveBalance = 0;
528
+ let singlesOnlyConsolidations = 0;
529
+ let singlesCommittees = 0;
530
+ const singlesNewSeenAttestersByInclusionDistance = new Map<number, number>();
531
+ for (const consolidation of packedConsolidations) {
532
+ totalValue += consolidation.totalNewSeenEffectiveBalance * consolidation.weight;
533
+ singlesValue += consolidation.singlesNewSeenEffectiveBalance * consolidation.weight;
534
+ newSeenAttesters += consolidation.newSeenAttesters;
535
+ singlesNewSeenAttesters += consolidation.singlesNewSeenAttesters;
536
+ if (consolidation.singlesNewSeenAttesters > 0) {
537
+ const inclusionDistance = stateSlot - consolidation.attData.slot;
538
+ singlesNewSeenAttestersByInclusionDistance.set(
539
+ inclusionDistance,
540
+ (singlesNewSeenAttestersByInclusionDistance.get(inclusionDistance) ?? 0) +
541
+ consolidation.singlesNewSeenAttesters
542
+ );
543
+ }
544
+ singlesNewSeenEffectiveBalance += consolidation.singlesNewSeenEffectiveBalance;
545
+ singlesCommittees += consolidation.singlesByCommittee.size;
546
+ if (consolidation.byCommittee.size === 0) {
547
+ singlesOnlyConsolidations++;
548
+ }
549
+ }
550
+ packedAttestationsMetrics?.attestationValue.inc({source: "aggregate"}, totalValue - singlesValue);
551
+ packedAttestationsMetrics?.attestationValue.inc({source: "single"}, singlesValue);
552
+ packedAttestationsMetrics?.blockNewSeenAttesters.set(newSeenAttesters);
553
+ packedAttestationsMetrics?.singlesValueRatio.observe(totalValue > 0 ? singlesValue / totalValue : 0);
554
+ packedAttestationsMetrics?.singlesNewSeenAttesters.observe(singlesNewSeenAttesters);
555
+ // reset so that distances of a previous block do not keep stale values, the gauge then sums to the last block
556
+ packedAttestationsMetrics?.singlesNewSeenAttestersByInclusionDistance.reset();
557
+ for (const [inclusionDistance, count] of singlesNewSeenAttestersByInclusionDistance) {
558
+ packedAttestationsMetrics?.singlesNewSeenAttestersByInclusionDistance.set({inclusionDistance}, count);
559
+ }
560
+ packedAttestationsMetrics?.singlesNewSeenEffectiveBalance.observe(singlesNewSeenEffectiveBalance);
561
+ packedAttestationsMetrics?.singlesOnlyConsolidations.observe(singlesOnlyConsolidations);
562
+ packedAttestationsMetrics?.singlesFoldedCommittees.observe(singlesCommittees);
563
+ this.logger?.debug("Packed single attestations into block", {
564
+ slot: stateSlot,
565
+ singlesNewSeenAttesters,
566
+ singlesNewSeenEffectiveBalance,
567
+ singlesCommittees,
568
+ singlesOnlyConsolidations,
569
+ packedAttestations: packedAttestations.length,
570
+ });
571
+
430
572
  if (stopReason === null) {
431
573
  stopReason = ScannedSlotsTerminationReason.ScannedAllSlots;
432
574
  }
575
+ // only one reason per block, reset so that other reasons do not keep values of a previous block
576
+ packedAttestationsMetrics?.scannedSlots.reset();
433
577
  packedAttestationsMetrics?.scannedSlots.set({reason: stopReason}, scannedSlots);
434
578
  packedAttestationsMetrics?.poolSlots.set(slots.length);
435
579
 
@@ -462,7 +606,8 @@ export class AggregatedAttestationPool {
462
606
  attestations.push(...attestationGroup.getAttestations());
463
607
  }
464
608
  }
465
- return attestations;
609
+ // The point at infinity is not a valid aggregate signature, do not serve such an aggregate
610
+ return attestations.filter((attestation) => !byteArrayEquals(attestation.signature, G2_POINT_AT_INFINITY));
466
611
  }
467
612
 
468
613
  private onScrapeMetrics(metrics: Metrics): void {
@@ -729,20 +874,38 @@ export function aggregateInto(attestation1: AttestationWithIndex, attestation2:
729
874
  * attestation data from different committee into a single attestation
730
875
  * https://github.com/ethereum/consensus-specs/blob/aba6345776aa876dad368cab27fbbb23fae20455/specs/_features/eip7549/validator.md?plain=1#L39
731
876
  */
732
- export function aggregateConsolidation({byCommittee, attData}: AttestationsConsolidation): electra.Attestation {
877
+ export function aggregateConsolidation({
878
+ byCommittee,
879
+ singlesByCommittee,
880
+ attData,
881
+ }: AttestationsConsolidation): electra.Attestation {
733
882
  const committeeBits = BitArray.fromBitLen(MAX_COMMITTEES_PER_SLOT);
734
883
  // TODO: can we improve this?
735
884
  let aggregationBits: boolean[] = [];
736
885
  const signatures: Signature[] = [];
737
- const sortedCommittees = Array.from(byCommittee.keys()).sort((a, b) => a - b);
886
+ const sortedCommittees = Array.from(new Set([...byCommittee.keys(), ...singlesByCommittee.keys()])).sort(
887
+ (a, b) => a - b
888
+ );
738
889
  for (const committeeIndex of sortedCommittees) {
739
- const attestationNonParticipation = byCommittee.get(committeeIndex);
740
- if (attestationNonParticipation !== undefined) {
741
- const {attestation} = attestationNonParticipation;
742
- committeeBits.set(committeeIndex, true);
743
- aggregationBits = [...aggregationBits, ...attestation.aggregationBits.toBoolArray()];
890
+ const attestation = byCommittee.get(committeeIndex)?.attestation;
891
+ const singles = singlesByCommittee.get(committeeIndex);
892
+ let committeeAggregationBits: boolean[];
893
+ if (attestation !== undefined) {
894
+ committeeAggregationBits = attestation.aggregationBits.toBoolArray();
744
895
  signatures.push(signatureFromBytesNoCheck(attestation.signature));
896
+ } else if (singles !== undefined) {
897
+ committeeAggregationBits = new Array<boolean>(singles.committeeSize).fill(false);
898
+ } else {
899
+ continue;
745
900
  }
901
+
902
+ // singles are disjoint from the aggregate of the same committee, see addSinglesToConsolidation
903
+ for (const {validatorCommitteeIndex, single} of singles?.singles ?? []) {
904
+ committeeAggregationBits[validatorCommitteeIndex] = true;
905
+ signatures.push(signatureFromBytesNoCheck(single.signature));
906
+ }
907
+ committeeBits.set(committeeIndex, true);
908
+ aggregationBits = [...aggregationBits, ...committeeAggregationBits];
746
909
  }
747
910
  return {
748
911
  aggregationBits: BitArray.fromBoolArray(aggregationBits),
@@ -752,6 +915,46 @@ export function aggregateConsolidation({byCommittee, attData}: AttestationsConso
752
915
  };
753
916
  }
754
917
 
918
+ function newConsolidation(attData: phase0.AttestationData): AttestationsConsolidation {
919
+ return {
920
+ byCommittee: new Map(),
921
+ singlesByCommittee: new Map(),
922
+ attData,
923
+ totalNewSeenEffectiveBalance: 0,
924
+ newSeenAttesters: 0,
925
+ notSeenAttesters: 0,
926
+ totalAttesters: 0,
927
+ singlesNewSeenEffectiveBalance: 0,
928
+ singlesNewSeenAttesters: 0,
929
+ weight: 0,
930
+ };
931
+ }
932
+
933
+ /**
934
+ * Add single attestations of committee members that no picked aggregate covers. They are disjoint from every picked
935
+ * aggregate of the same committee, so their signatures can be aggregated with the committee's aggregate.
936
+ * @param notSeenCommitteeMembersCount committee members still not seen before adding these singles
937
+ */
938
+ function addSinglesToConsolidation(
939
+ consolidation: AttestationsConsolidation,
940
+ committeeIndex: CommitteeIndex,
941
+ singles: SinglesForCommittee,
942
+ notSeenCommitteeMembersCount: number
943
+ ): void {
944
+ consolidation.singlesByCommittee.set(committeeIndex, singles);
945
+ consolidation.totalNewSeenEffectiveBalance += singles.newSeenEffectiveBalance;
946
+ consolidation.newSeenAttesters += singles.newSeenAttesters;
947
+ consolidation.singlesNewSeenEffectiveBalance += singles.newSeenEffectiveBalance;
948
+ consolidation.singlesNewSeenAttesters += singles.newSeenAttesters;
949
+ if (consolidation.byCommittee.has(committeeIndex)) {
950
+ // these members were counted as not seen by the aggregate of this committee
951
+ consolidation.notSeenAttesters -= singles.newSeenAttesters;
952
+ } else {
953
+ consolidation.totalAttesters += singles.committeeSize;
954
+ consolidation.notSeenAttesters += notSeenCommitteeMembersCount - singles.newSeenAttesters;
955
+ }
956
+ }
957
+
755
958
  /**
756
959
  * Pre-compute participation from a IBeaconStateView, for use to check if an attestation's committee
757
960
  * has already attested or not.
@@ -1,9 +1,10 @@
1
- import {Signature, aggregateSignatures} from "@chainsafe/lodestar-z/blst";
2
1
  import {BitArray} from "@chainsafe/ssz";
3
2
  import {ChainForkConfig} from "@lodestar/config";
3
+ import {Signature, aggregateSignatures} from "@lodestar/native/blst";
4
4
  import {MAX_COMMITTEES_PER_SLOT, isForkPostElectra} from "@lodestar/params";
5
+ import {G2_POINT_AT_INFINITY} from "@lodestar/state-transition";
5
6
  import {Attestation, RootHex, SingleAttestation, Slot, isElectraSingleAttestation} from "@lodestar/types";
6
- import {MapDef, assert} from "@lodestar/utils";
7
+ import {MapDef, assert, byteArrayEquals} from "@lodestar/utils";
7
8
  import {Metrics} from "../../metrics/metrics.js";
8
9
  import {IClock} from "../../util/clock.js";
9
10
  import {InsertOutcome, OpPoolError, OpPoolErrorCode} from "./types.js";
@@ -180,7 +181,13 @@ export class AttestationPool {
180
181
  assert.true(!isElectraAggregate(aggregate), "Aggregate should be type AggregateFastPhase0");
181
182
  }
182
183
 
183
- return fastToAttestation(aggregate);
184
+ const attestation = fastToAttestation(aggregate);
185
+ // The point at infinity is not a valid aggregate signature, do not serve such an aggregate
186
+ if (byteArrayEquals(attestation.signature, G2_POINT_AT_INFINITY)) {
187
+ return null;
188
+ }
189
+
190
+ return attestation;
184
191
  }
185
192
 
186
193
  /**
@@ -209,7 +216,12 @@ export class AttestationPool {
209
216
  if (aggregateByRoot) {
210
217
  for (const aggFastByIndex of aggregateByRoot.values()) {
211
218
  for (const aggFast of aggFastByIndex.values()) {
212
- attestations.push(fastToAttestation(aggFast));
219
+ const attestation = fastToAttestation(aggFast);
220
+ // The point at infinity is not a valid aggregate signature, do not serve such an aggregate
221
+ if (byteArrayEquals(attestation.signature, G2_POINT_AT_INFINITY)) {
222
+ continue;
223
+ }
224
+ attestations.push(attestation);
213
225
  }
214
226
  }
215
227
  }
@@ -6,5 +6,6 @@ export {InclusionListInsertOutcome, InclusionListStore} from "./inclusionListSto
6
6
  export {OpPool} from "./opPool.js";
7
7
  export {PayloadAttestationPool} from "./payloadAttestationPool.js";
8
8
  export {ProposerPreferencesPool} from "./proposerPreferencesPool.js";
9
+ export {SingleAttestationPool} from "./singleAttestationPool.js";
9
10
  export {SyncCommitteeMessagePool} from "./syncCommitteeMessagePool.js";
10
11
  export {SyncContributionAndProofPool} from "./syncContributionAndProofPool.js";
@@ -1,9 +1,10 @@
1
- import {Signature, aggregateSignatures} from "@chainsafe/lodestar-z/blst";
2
1
  import {BitArray} from "@chainsafe/ssz";
3
2
  import {ChainForkConfig} from "@lodestar/config";
3
+ import {Signature, aggregateSignatures} from "@lodestar/native/blst";
4
4
  import {MAX_COMMITTEES_PER_SLOT, MAX_PAYLOAD_ATTESTATIONS, PTC_SIZE} from "@lodestar/params";
5
+ import {G2_POINT_AT_INFINITY} from "@lodestar/state-transition";
5
6
  import {RootHex, Slot, gloas} from "@lodestar/types";
6
- import {MapDef, toRootHex} from "@lodestar/utils";
7
+ import {MapDef, byteArrayEquals, toRootHex} from "@lodestar/utils";
7
8
  import {Metrics} from "../../metrics/metrics.js";
8
9
  import {IClock} from "../../util/clock.js";
9
10
  import {InsertOutcome, OpPoolError, OpPoolErrorCode} from "./types.js";
@@ -112,11 +113,19 @@ export class PayloadAttestationPool {
112
113
  return [];
113
114
  }
114
115
 
115
- return Array.from(aggregateByDataRoot.values())
116
- .slice()
116
+ const payloadAttestations: gloas.PayloadAttestation[] = [];
117
+ for (const aggregate of aggregateByDataRoot.values()) {
118
+ const payloadAttestation = fastToPayloadAttestation(aggregate);
119
+ // The point at infinity is not a valid aggregate signature, exclude it from the block
120
+ if (byteArrayEquals(payloadAttestation.signature, G2_POINT_AT_INFINITY)) {
121
+ continue;
122
+ }
123
+ payloadAttestations.push(payloadAttestation);
124
+ }
125
+
126
+ return payloadAttestations
117
127
  .sort((a, b) => b.aggregationBits.getTrueBitIndexes().length - a.aggregationBits.getTrueBitIndexes().length)
118
- .slice(0, MAX_PAYLOAD_ATTESTATIONS)
119
- .map(fastToPayloadAttestation);
128
+ .slice(0, MAX_PAYLOAD_ATTESTATIONS);
120
129
  }
121
130
 
122
131
  getAll(slot?: Slot): gloas.PayloadAttestation[] {
@@ -139,9 +148,11 @@ export class PayloadAttestationPool {
139
148
  }
140
149
  }
141
150
 
151
+ // The point at infinity is not a valid aggregate signature, do not serve such an aggregate
142
152
  return aggregates
143
153
  .sort((a, b) => b.aggregationBits.getTrueBitIndexes().length - a.aggregationBits.getTrueBitIndexes().length)
144
- .map(fastToPayloadAttestation);
154
+ .map(fastToPayloadAttestation)
155
+ .filter((attestation) => !byteArrayEquals(attestation.signature, G2_POINT_AT_INFINITY));
145
156
  }
146
157
 
147
158
  prune(clockSlot: Slot): void {