@lodestar/beacon-node 1.51.0-dev.d422f387ac → 1.51.0-dev.dc21d14c20

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 (443) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +19 -61
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
  5. package/lib/api/impl/beacon/pool/index.js +17 -0
  6. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  7. package/lib/api/impl/validator/index.d.ts +6 -0
  8. package/lib/api/impl/validator/index.d.ts.map +1 -1
  9. package/lib/api/impl/validator/index.js +38 -25
  10. package/lib/api/impl/validator/index.js.map +1 -1
  11. package/lib/chain/GetBlobsTracker.d.ts +2 -2
  12. package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
  13. package/lib/chain/GetBlobsTracker.js +7 -31
  14. package/lib/chain/GetBlobsTracker.js.map +1 -1
  15. package/lib/chain/blocks/blockInput/blockInput.d.ts +11 -56
  16. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  17. package/lib/chain/blocks/blockInput/blockInput.js +5 -241
  18. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  19. package/lib/chain/blocks/blockInput/errors.d.ts +2 -4
  20. package/lib/chain/blocks/blockInput/errors.d.ts.map +1 -1
  21. package/lib/chain/blocks/blockInput/errors.js.map +1 -1
  22. package/lib/chain/blocks/blockInput/types.d.ts +2 -18
  23. package/lib/chain/blocks/blockInput/types.d.ts.map +1 -1
  24. package/lib/chain/blocks/blockInput/types.js +0 -1
  25. package/lib/chain/blocks/blockInput/types.js.map +1 -1
  26. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  27. package/lib/chain/blocks/importBlock.js +36 -53
  28. package/lib/chain/blocks/importBlock.js.map +1 -1
  29. package/lib/chain/blocks/importExecutionPayload.d.ts +4 -0
  30. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  31. package/lib/chain/blocks/importExecutionPayload.js +24 -3
  32. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  33. package/lib/chain/blocks/index.d.ts.map +1 -1
  34. package/lib/chain/blocks/index.js +2 -2
  35. package/lib/chain/blocks/index.js.map +1 -1
  36. package/lib/chain/blocks/types.d.ts +4 -20
  37. package/lib/chain/blocks/types.d.ts.map +1 -1
  38. package/lib/chain/blocks/types.js +0 -24
  39. package/lib/chain/blocks/types.js.map +1 -1
  40. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  41. package/lib/chain/blocks/verifyBlock.js +17 -6
  42. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  43. package/lib/chain/blocks/verifyBlocksDataAvailability.d.ts.map +1 -1
  44. package/lib/chain/blocks/verifyBlocksDataAvailability.js +6 -1
  45. package/lib/chain/blocks/verifyBlocksDataAvailability.js.map +1 -1
  46. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +1 -1
  47. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  48. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +7 -3
  49. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  50. package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
  51. package/lib/chain/blocks/verifyBlocksSanityChecks.js +4 -0
  52. package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
  53. package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
  54. package/lib/chain/blocks/verifyBlocksSignatures.js +10 -5
  55. package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
  56. package/lib/chain/blocks/writeBlockInputToDb.d.ts +0 -2
  57. package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
  58. package/lib/chain/blocks/writeBlockInputToDb.js +6 -24
  59. package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
  60. package/lib/chain/bls/interface.d.ts +2 -0
  61. package/lib/chain/bls/interface.d.ts.map +1 -1
  62. package/lib/chain/bls/multithread/index.d.ts +1 -1
  63. package/lib/chain/bls/multithread/index.d.ts.map +1 -1
  64. package/lib/chain/bls/multithread/index.js +45 -17
  65. package/lib/chain/bls/multithread/index.js.map +1 -1
  66. package/lib/chain/chain.d.ts +24 -3
  67. package/lib/chain/chain.d.ts.map +1 -1
  68. package/lib/chain/chain.js +120 -39
  69. package/lib/chain/chain.js.map +1 -1
  70. package/lib/chain/emitter.d.ts +7 -7
  71. package/lib/chain/emitter.d.ts.map +1 -1
  72. package/lib/chain/emitter.js +5 -5
  73. package/lib/chain/emitter.js.map +1 -1
  74. package/lib/chain/errors/executionPayloadEnvelope.d.ts +7 -0
  75. package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
  76. package/lib/chain/errors/executionPayloadEnvelope.js +1 -0
  77. package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
  78. package/lib/chain/errors/index.d.ts +0 -1
  79. package/lib/chain/errors/index.d.ts.map +1 -1
  80. package/lib/chain/errors/index.js +0 -1
  81. package/lib/chain/errors/index.js.map +1 -1
  82. package/lib/chain/forkChoice/index.d.ts +11 -1
  83. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  84. package/lib/chain/forkChoice/index.js +11 -0
  85. package/lib/chain/forkChoice/index.js.map +1 -1
  86. package/lib/chain/forkChoiceExecutionEngine.d.ts +51 -0
  87. package/lib/chain/forkChoiceExecutionEngine.d.ts.map +1 -0
  88. package/lib/chain/forkChoiceExecutionEngine.js +117 -0
  89. package/lib/chain/forkChoiceExecutionEngine.js.map +1 -0
  90. package/lib/chain/interface.d.ts +7 -4
  91. package/lib/chain/interface.d.ts.map +1 -1
  92. package/lib/chain/interface.js.map +1 -1
  93. package/lib/chain/opPools/aggregatedAttestationPool.d.ts +17 -4
  94. package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
  95. package/lib/chain/opPools/aggregatedAttestationPool.js +177 -37
  96. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  97. package/lib/chain/opPools/index.d.ts +1 -0
  98. package/lib/chain/opPools/index.d.ts.map +1 -1
  99. package/lib/chain/opPools/index.js +1 -0
  100. package/lib/chain/opPools/index.js.map +1 -1
  101. package/lib/chain/opPools/singleAttestationPool.d.ts +77 -0
  102. package/lib/chain/opPools/singleAttestationPool.d.ts.map +1 -0
  103. package/lib/chain/opPools/singleAttestationPool.js +209 -0
  104. package/lib/chain/opPools/singleAttestationPool.js.map +1 -0
  105. package/lib/chain/options.d.ts +5 -2
  106. package/lib/chain/options.d.ts.map +1 -1
  107. package/lib/chain/options.js.map +1 -1
  108. package/lib/chain/produceBlock/produceBlockBody.d.ts +3 -2
  109. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  110. package/lib/chain/produceBlock/produceBlockBody.js +3 -2
  111. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  112. package/lib/chain/proposerTracker.d.ts +31 -0
  113. package/lib/chain/proposerTracker.d.ts.map +1 -0
  114. package/lib/chain/proposerTracker.js +75 -0
  115. package/lib/chain/proposerTracker.js.map +1 -0
  116. package/lib/chain/regen/interface.d.ts +1 -1
  117. package/lib/chain/regen/interface.d.ts.map +1 -1
  118. package/lib/chain/regen/queued.d.ts +1 -1
  119. package/lib/chain/regen/queued.d.ts.map +1 -1
  120. package/lib/chain/regen/queued.js +5 -3
  121. package/lib/chain/regen/queued.js.map +1 -1
  122. package/lib/chain/seenCache/seenGossipBlockInput.d.ts +7 -14
  123. package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
  124. package/lib/chain/seenCache/seenGossipBlockInput.js +6 -65
  125. package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
  126. package/lib/chain/validation/executionPayloadEnvelope.d.ts +6 -0
  127. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  128. package/lib/chain/validation/executionPayloadEnvelope.js +53 -0
  129. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  130. package/lib/chain/validation/syncCommittee.d.ts.map +1 -1
  131. package/lib/chain/validation/syncCommittee.js +16 -10
  132. package/lib/chain/validation/syncCommittee.js.map +1 -1
  133. package/lib/chain/validation/syncCommitteeContributionAndProof.d.ts.map +1 -1
  134. package/lib/chain/validation/syncCommitteeContributionAndProof.js +11 -0
  135. package/lib/chain/validation/syncCommitteeContributionAndProof.js.map +1 -1
  136. package/lib/chain/validatorMonitor.d.ts +1 -2
  137. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  138. package/lib/chain/validatorMonitor.js +0 -3
  139. package/lib/chain/validatorMonitor.js.map +1 -1
  140. package/lib/db/repositories/blobSidecars.d.ts +0 -1
  141. package/lib/db/repositories/blobSidecars.d.ts.map +1 -1
  142. package/lib/db/repositories/blobSidecars.js +0 -1
  143. package/lib/db/repositories/blobSidecars.js.map +1 -1
  144. package/lib/execution/builder/apiClient.d.ts +14 -8
  145. package/lib/execution/builder/apiClient.d.ts.map +1 -1
  146. package/lib/execution/builder/apiClient.js +12 -10
  147. package/lib/execution/builder/apiClient.js.map +1 -1
  148. package/lib/execution/builder/http.d.ts +2 -0
  149. package/lib/execution/builder/http.d.ts.map +1 -1
  150. package/lib/execution/builder/http.js +2 -0
  151. package/lib/execution/builder/http.js.map +1 -1
  152. package/lib/execution/engine/http.d.ts +4 -6
  153. package/lib/execution/engine/http.d.ts.map +1 -1
  154. package/lib/execution/engine/http.js +8 -10
  155. package/lib/execution/engine/http.js.map +1 -1
  156. package/lib/execution/engine/interface.d.ts +17 -5
  157. package/lib/execution/engine/interface.d.ts.map +1 -1
  158. package/lib/execution/engine/interface.js.map +1 -1
  159. package/lib/execution/engine/jsonRpcTransport.d.ts +2 -4
  160. package/lib/execution/engine/jsonRpcTransport.d.ts.map +1 -1
  161. package/lib/execution/engine/jsonRpcTransport.js +2 -12
  162. package/lib/execution/engine/jsonRpcTransport.js.map +1 -1
  163. package/lib/execution/engine/mock.d.ts +0 -1
  164. package/lib/execution/engine/mock.d.ts.map +1 -1
  165. package/lib/execution/engine/mock.js +0 -4
  166. package/lib/execution/engine/mock.js.map +1 -1
  167. package/lib/execution/engine/restTransport.d.ts +2 -4
  168. package/lib/execution/engine/restTransport.d.ts.map +1 -1
  169. package/lib/execution/engine/restTransport.js +1 -15
  170. package/lib/execution/engine/restTransport.js.map +1 -1
  171. package/lib/execution/engine/sszTypes.d.ts +0 -9
  172. package/lib/execution/engine/sszTypes.d.ts.map +1 -1
  173. package/lib/execution/engine/sszTypes.js +0 -5
  174. package/lib/execution/engine/sszTypes.js.map +1 -1
  175. package/lib/execution/engine/transport.d.ts +1 -14
  176. package/lib/execution/engine/transport.d.ts.map +1 -1
  177. package/lib/execution/engine/types.d.ts +0 -8
  178. package/lib/execution/engine/types.d.ts.map +1 -1
  179. package/lib/execution/engine/types.js +0 -8
  180. package/lib/execution/engine/types.js.map +1 -1
  181. package/lib/execution/engine/utils.d.ts.map +1 -1
  182. package/lib/execution/engine/utils.js +3 -2
  183. package/lib/execution/engine/utils.js.map +1 -1
  184. package/lib/index.d.ts +1 -1
  185. package/lib/index.d.ts.map +1 -1
  186. package/lib/index.js +1 -1
  187. package/lib/index.js.map +1 -1
  188. package/lib/metrics/metrics/beacon.d.ts +0 -9
  189. package/lib/metrics/metrics/beacon.d.ts.map +1 -1
  190. package/lib/metrics/metrics/beacon.js +0 -30
  191. package/lib/metrics/metrics/beacon.js.map +1 -1
  192. package/lib/metrics/metrics/lodestar.d.ts +27 -8
  193. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  194. package/lib/metrics/metrics/lodestar.js +74 -18
  195. package/lib/metrics/metrics/lodestar.js.map +1 -1
  196. package/lib/metrics/server/http.js +5 -5
  197. package/lib/metrics/server/http.js.map +1 -1
  198. package/lib/network/core/networkCore.d.ts +2 -1
  199. package/lib/network/core/networkCore.d.ts.map +1 -1
  200. package/lib/network/core/networkCore.js +4 -0
  201. package/lib/network/core/networkCore.js.map +1 -1
  202. package/lib/network/core/networkCoreWorker.js +1 -0
  203. package/lib/network/core/networkCoreWorker.js.map +1 -1
  204. package/lib/network/core/networkCoreWorkerHandler.d.ts +2 -1
  205. package/lib/network/core/networkCoreWorkerHandler.d.ts.map +1 -1
  206. package/lib/network/core/networkCoreWorkerHandler.js +3 -0
  207. package/lib/network/core/networkCoreWorkerHandler.js.map +1 -1
  208. package/lib/network/core/types.d.ts +4 -1
  209. package/lib/network/core/types.d.ts.map +1 -1
  210. package/lib/network/gossip/gossipsub.d.ts +1 -0
  211. package/lib/network/gossip/gossipsub.d.ts.map +1 -1
  212. package/lib/network/gossip/gossipsub.js +10 -0
  213. package/lib/network/gossip/gossipsub.js.map +1 -1
  214. package/lib/network/gossip/interface.d.ts +1 -8
  215. package/lib/network/gossip/interface.d.ts.map +1 -1
  216. package/lib/network/gossip/interface.js +0 -1
  217. package/lib/network/gossip/interface.js.map +1 -1
  218. package/lib/network/gossip/topic.d.ts +0 -16
  219. package/lib/network/gossip/topic.d.ts.map +1 -1
  220. package/lib/network/gossip/topic.js +0 -23
  221. package/lib/network/gossip/topic.js.map +1 -1
  222. package/lib/network/interface.d.ts +2 -5
  223. package/lib/network/interface.d.ts.map +1 -1
  224. package/lib/network/network.d.ts +6 -7
  225. package/lib/network/network.d.ts.map +1 -1
  226. package/lib/network/network.js +50 -37
  227. package/lib/network/network.js.map +1 -1
  228. package/lib/network/options.d.ts.map +1 -1
  229. package/lib/network/options.js +2 -0
  230. package/lib/network/options.js.map +1 -1
  231. package/lib/network/peers/peerManager.d.ts.map +1 -1
  232. package/lib/network/peers/peerManager.js +28 -1
  233. package/lib/network/peers/peerManager.js.map +1 -1
  234. package/lib/network/peers/utils/prioritizePeers.d.ts +4 -1
  235. package/lib/network/peers/utils/prioritizePeers.d.ts.map +1 -1
  236. package/lib/network/peers/utils/prioritizePeers.js +8 -16
  237. package/lib/network/peers/utils/prioritizePeers.js.map +1 -1
  238. package/lib/network/peers/utils/subnetMap.d.ts +5 -2
  239. package/lib/network/peers/utils/subnetMap.d.ts.map +1 -1
  240. package/lib/network/peers/utils/subnetMap.js +6 -3
  241. package/lib/network/peers/utils/subnetMap.js.map +1 -1
  242. package/lib/network/processor/extractSlotRootFns.d.ts.map +1 -1
  243. package/lib/network/processor/extractSlotRootFns.js +1 -8
  244. package/lib/network/processor/extractSlotRootFns.js.map +1 -1
  245. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  246. package/lib/network/processor/gossipHandlers.js +43 -123
  247. package/lib/network/processor/gossipHandlers.js.map +1 -1
  248. package/lib/network/processor/gossipQueues/index.d.ts.map +1 -1
  249. package/lib/network/processor/gossipQueues/index.js +0 -6
  250. package/lib/network/processor/gossipQueues/index.js.map +1 -1
  251. package/lib/network/processor/gossipValidatorFn.d.ts.map +1 -1
  252. package/lib/network/processor/gossipValidatorFn.js +1 -5
  253. package/lib/network/processor/gossipValidatorFn.js.map +1 -1
  254. package/lib/network/processor/index.d.ts +6 -0
  255. package/lib/network/processor/index.d.ts.map +1 -1
  256. package/lib/network/processor/index.js +29 -4
  257. package/lib/network/processor/index.js.map +1 -1
  258. package/lib/network/reqresp/ReqRespBeaconNode.d.ts.map +1 -1
  259. package/lib/network/reqresp/ReqRespBeaconNode.js +0 -3
  260. package/lib/network/reqresp/ReqRespBeaconNode.js.map +1 -1
  261. package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts +2 -2
  262. package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
  263. package/lib/network/reqresp/handlers/index.d.ts.map +1 -1
  264. package/lib/network/reqresp/handlers/index.js +1 -12
  265. package/lib/network/reqresp/handlers/index.js.map +1 -1
  266. package/lib/network/reqresp/protocols.d.ts +0 -2
  267. package/lib/network/reqresp/protocols.d.ts.map +1 -1
  268. package/lib/network/reqresp/protocols.js +0 -10
  269. package/lib/network/reqresp/protocols.js.map +1 -1
  270. package/lib/network/reqresp/rateLimit.d.ts.map +1 -1
  271. package/lib/network/reqresp/rateLimit.js +1 -17
  272. package/lib/network/reqresp/rateLimit.js.map +1 -1
  273. package/lib/network/reqresp/types.d.ts +2 -8
  274. package/lib/network/reqresp/types.d.ts.map +1 -1
  275. package/lib/network/reqresp/types.js +1 -7
  276. package/lib/network/reqresp/types.js.map +1 -1
  277. package/lib/network/subnets/attnetsService.d.ts +35 -5
  278. package/lib/network/subnets/attnetsService.d.ts.map +1 -1
  279. package/lib/network/subnets/attnetsService.js +84 -6
  280. package/lib/network/subnets/attnetsService.js.map +1 -1
  281. package/lib/network/subnets/interface.d.ts +7 -0
  282. package/lib/network/subnets/interface.d.ts.map +1 -1
  283. package/lib/network/subnets/interface.js.map +1 -1
  284. package/lib/node/nodejs.d.ts +2 -0
  285. package/lib/node/nodejs.d.ts.map +1 -1
  286. package/lib/node/nodejs.js +37 -19
  287. package/lib/node/nodejs.js.map +1 -1
  288. package/lib/node/options.d.ts +3 -1
  289. package/lib/node/options.d.ts.map +1 -1
  290. package/lib/node/options.js +4 -2
  291. package/lib/node/options.js.map +1 -1
  292. package/lib/sync/range/batch.d.ts +2 -3
  293. package/lib/sync/range/batch.d.ts.map +1 -1
  294. package/lib/sync/range/batch.js +9 -22
  295. package/lib/sync/range/batch.js.map +1 -1
  296. package/lib/sync/range/chain.d.ts.map +1 -1
  297. package/lib/sync/range/chain.js +2 -15
  298. package/lib/sync/range/chain.js.map +1 -1
  299. package/lib/sync/sync.d.ts +8 -0
  300. package/lib/sync/sync.d.ts.map +1 -1
  301. package/lib/sync/sync.js +42 -22
  302. package/lib/sync/sync.js.map +1 -1
  303. package/lib/sync/unknownBlock.d.ts.map +1 -1
  304. package/lib/sync/unknownBlock.js +1 -7
  305. package/lib/sync/unknownBlock.js.map +1 -1
  306. package/lib/sync/utils/downloadByRange.d.ts +6 -34
  307. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  308. package/lib/sync/utils/downloadByRange.js +24 -128
  309. package/lib/sync/utils/downloadByRange.js.map +1 -1
  310. package/lib/sync/utils/downloadByRoot.d.ts +2 -18
  311. package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
  312. package/lib/sync/utils/downloadByRoot.js +14 -99
  313. package/lib/sync/utils/downloadByRoot.js.map +1 -1
  314. package/lib/util/blobs.d.ts +1 -7
  315. package/lib/util/blobs.d.ts.map +1 -1
  316. package/lib/util/blobs.js +0 -19
  317. package/lib/util/blobs.js.map +1 -1
  318. package/lib/util/execution.d.ts +3 -4
  319. package/lib/util/execution.d.ts.map +1 -1
  320. package/lib/util/execution.js +1 -73
  321. package/lib/util/execution.js.map +1 -1
  322. package/lib/util/sszBytes.d.ts +5 -1
  323. package/lib/util/sszBytes.d.ts.map +1 -1
  324. package/lib/util/sszBytes.js +34 -17
  325. package/lib/util/sszBytes.js.map +1 -1
  326. package/lib/util/types.d.ts +0 -5
  327. package/lib/util/types.d.ts.map +1 -1
  328. package/lib/util/types.js +1 -2
  329. package/lib/util/types.js.map +1 -1
  330. package/package.json +16 -16
  331. package/src/api/impl/beacon/blocks/index.ts +24 -64
  332. package/src/api/impl/beacon/pool/index.ts +26 -0
  333. package/src/api/impl/validator/index.ts +43 -29
  334. package/src/chain/GetBlobsTracker.ts +10 -39
  335. package/src/chain/blocks/blockInput/blockInput.ts +11 -343
  336. package/src/chain/blocks/blockInput/errors.ts +1 -2
  337. package/src/chain/blocks/blockInput/types.ts +2 -20
  338. package/src/chain/blocks/importBlock.ts +56 -72
  339. package/src/chain/blocks/importExecutionPayload.ts +42 -13
  340. package/src/chain/blocks/index.ts +5 -2
  341. package/src/chain/blocks/types.ts +5 -31
  342. package/src/chain/blocks/verifyBlock.ts +30 -16
  343. package/src/chain/blocks/verifyBlocksDataAvailability.ts +6 -1
  344. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +9 -6
  345. package/src/chain/blocks/verifyBlocksSanityChecks.ts +4 -1
  346. package/src/chain/blocks/verifyBlocksSignatures.ts +10 -5
  347. package/src/chain/blocks/writeBlockInputToDb.ts +6 -29
  348. package/src/chain/bls/interface.ts +2 -0
  349. package/src/chain/bls/multithread/index.ts +43 -19
  350. package/src/chain/chain.ts +135 -37
  351. package/src/chain/emitter.ts +8 -8
  352. package/src/chain/errors/executionPayloadEnvelope.ts +8 -0
  353. package/src/chain/errors/index.ts +0 -1
  354. package/src/chain/forkChoice/index.ts +11 -0
  355. package/src/chain/forkChoiceExecutionEngine.ts +183 -0
  356. package/src/chain/interface.ts +7 -3
  357. package/src/chain/opPools/aggregatedAttestationPool.ts +222 -35
  358. package/src/chain/opPools/index.ts +1 -0
  359. package/src/chain/opPools/singleAttestationPool.ts +287 -0
  360. package/src/chain/options.ts +5 -2
  361. package/src/chain/produceBlock/produceBlockBody.ts +7 -3
  362. package/src/chain/proposerTracker.ts +94 -0
  363. package/src/chain/regen/interface.ts +1 -1
  364. package/src/chain/regen/queued.ts +6 -4
  365. package/src/chain/seenCache/seenGossipBlockInput.ts +9 -93
  366. package/src/chain/validation/executionPayloadEnvelope.ts +68 -1
  367. package/src/chain/validation/syncCommittee.ts +31 -15
  368. package/src/chain/validation/syncCommitteeContributionAndProof.ts +13 -0
  369. package/src/chain/validatorMonitor.ts +0 -6
  370. package/src/db/repositories/blobSidecars.ts +0 -1
  371. package/src/execution/builder/apiClient.ts +16 -13
  372. package/src/execution/builder/http.ts +4 -0
  373. package/src/execution/engine/http.ts +19 -42
  374. package/src/execution/engine/interface.ts +18 -9
  375. package/src/execution/engine/jsonRpcTransport.ts +10 -22
  376. package/src/execution/engine/mock.ts +0 -7
  377. package/src/execution/engine/restTransport.ts +3 -22
  378. package/src/execution/engine/sszTypes.ts +0 -9
  379. package/src/execution/engine/transport.ts +8 -17
  380. package/src/execution/engine/types.ts +0 -17
  381. package/src/execution/engine/utils.ts +4 -2
  382. package/src/index.ts +1 -1
  383. package/src/metrics/metrics/beacon.ts +0 -30
  384. package/src/metrics/metrics/lodestar.ts +75 -18
  385. package/src/metrics/server/http.ts +5 -5
  386. package/src/network/core/networkCore.ts +6 -1
  387. package/src/network/core/networkCoreWorker.ts +1 -0
  388. package/src/network/core/networkCoreWorkerHandler.ts +4 -1
  389. package/src/network/core/types.ts +4 -1
  390. package/src/network/gossip/gossipsub.ts +11 -0
  391. package/src/network/gossip/interface.ts +0 -5
  392. package/src/network/gossip/topic.ts +0 -25
  393. package/src/network/interface.ts +0 -5
  394. package/src/network/network.ts +50 -60
  395. package/src/network/options.ts +2 -0
  396. package/src/network/peers/peerManager.ts +27 -2
  397. package/src/network/peers/utils/prioritizePeers.ts +14 -22
  398. package/src/network/peers/utils/subnetMap.ts +6 -3
  399. package/src/network/processor/extractSlotRootFns.ts +0 -9
  400. package/src/network/processor/gossipHandlers.ts +56 -156
  401. package/src/network/processor/gossipQueues/index.ts +0 -6
  402. package/src/network/processor/gossipValidatorFn.ts +0 -5
  403. package/src/network/processor/index.ts +25 -4
  404. package/src/network/reqresp/ReqRespBeaconNode.ts +0 -7
  405. package/src/network/reqresp/handlers/beaconBlocksByRange.ts +2 -2
  406. package/src/network/reqresp/handlers/index.ts +0 -17
  407. package/src/network/reqresp/protocols.ts +0 -12
  408. package/src/network/reqresp/rateLimit.ts +1 -17
  409. package/src/network/reqresp/types.ts +0 -13
  410. package/src/network/subnets/attnetsService.ts +94 -6
  411. package/src/network/subnets/interface.ts +7 -0
  412. package/src/node/nodejs.ts +34 -15
  413. package/src/node/options.ts +5 -1
  414. package/src/sync/range/batch.ts +9 -21
  415. package/src/sync/range/chain.ts +2 -14
  416. package/src/sync/sync.ts +43 -22
  417. package/src/sync/unknownBlock.ts +1 -8
  418. package/src/sync/utils/downloadByRange.ts +31 -230
  419. package/src/sync/utils/downloadByRoot.ts +15 -142
  420. package/src/util/blobs.ts +0 -34
  421. package/src/util/execution.ts +8 -102
  422. package/src/util/sszBytes.ts +40 -22
  423. package/src/util/types.ts +1 -8
  424. package/lib/chain/errors/blobSidecarError.d.ts +0 -108
  425. package/lib/chain/errors/blobSidecarError.d.ts.map +0 -1
  426. package/lib/chain/errors/blobSidecarError.js +0 -38
  427. package/lib/chain/errors/blobSidecarError.js.map +0 -1
  428. package/lib/chain/validation/blobSidecar.d.ts +0 -16
  429. package/lib/chain/validation/blobSidecar.d.ts.map +0 -1
  430. package/lib/chain/validation/blobSidecar.js +0 -276
  431. package/lib/chain/validation/blobSidecar.js.map +0 -1
  432. package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts +0 -9
  433. package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts.map +0 -1
  434. package/lib/network/reqresp/handlers/blobSidecarsByRange.js +0 -91
  435. package/lib/network/reqresp/handlers/blobSidecarsByRange.js.map +0 -1
  436. package/lib/network/reqresp/handlers/blobSidecarsByRoot.d.ts +0 -5
  437. package/lib/network/reqresp/handlers/blobSidecarsByRoot.d.ts.map +0 -1
  438. package/lib/network/reqresp/handlers/blobSidecarsByRoot.js +0 -46
  439. package/lib/network/reqresp/handlers/blobSidecarsByRoot.js.map +0 -1
  440. package/src/chain/errors/blobSidecarError.ts +0 -70
  441. package/src/chain/validation/blobSidecar.ts +0 -357
  442. package/src/network/reqresp/handlers/blobSidecarsByRange.ts +0 -133
  443. package/src/network/reqresp/handlers/blobSidecarsByRoot.ts +0 -69
@@ -36,6 +36,7 @@ import {Metrics} from "../../metrics/metrics.js";
36
36
  import {IntersectResult, intersectUint8Arrays} from "../../util/bitArray.js";
37
37
  import {getShufflingDependentRoot} from "../../util/dependentRoot.js";
38
38
  import {ShufflingCache} from "../shufflingCache.js";
39
+ import {SingleAttestationPool, SinglesForCommittee} from "./singleAttestationPool.js";
39
40
  import {InsertOutcome} from "./types.js";
40
41
  import {pruneBySlot, signatureFromBytesNoCheck} from "./utils.js";
41
42
 
@@ -49,12 +50,23 @@ type CommitteeIndex = number;
49
50
  */
50
51
  export type AttestationsConsolidation = {
51
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>;
52
58
  attData: phase0.AttestationData;
53
59
  totalNewSeenEffectiveBalance: number;
54
60
  newSeenAttesters: number;
55
61
  notSeenAttesters: number;
56
62
  /** total number of attesters across all committees in this consolidation */
57
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;
58
70
  };
59
71
 
60
72
  /**
@@ -110,6 +122,14 @@ const MAX_ATTESTATIONS_PER_GROUP_ELECTRA = Math.min(
110
122
  MAX_ATTESTATIONS_ELECTRA
111
123
  );
112
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
+
113
133
  /** Same to https://github.com/ethereum/consensus-specs/blob/v1.5.0/specs/altair/beacon-chain.md#has_flag */
114
134
  const TIMELY_SOURCE = 1 << TIMELY_SOURCE_FLAG_INDEX;
115
135
  const TIMELY_TARGET = 1 << TIMELY_TARGET_FLAG_INDEX;
@@ -213,24 +233,27 @@ export class AggregatedAttestationPool {
213
233
  fork: ForkName,
214
234
  forkChoice: IForkChoice,
215
235
  shufflingCache: ShufflingCache,
216
- state: IBeaconStateView
236
+ state: IBeaconStateView,
237
+ singleAttestationPool: SingleAttestationPool
217
238
  ): Attestation[] {
218
239
  const forkSeq = ForkSeq[fork];
219
240
  if (forkSeq < ForkSeq.electra) {
220
241
  throw new Error("Does not support producing blocks for pre-electra forks anymore");
221
242
  }
222
243
 
223
- return this.getAttestationsForBlockElectra(fork, forkChoice, shufflingCache, state);
244
+ return this.getAttestationsForBlockElectra(fork, forkChoice, shufflingCache, state, singleAttestationPool);
224
245
  }
225
246
 
226
247
  /**
227
- * 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`
228
250
  */
229
251
  getAttestationsForBlockElectra(
230
252
  fork: ForkName,
231
253
  forkChoice: IForkChoice,
232
254
  shufflingCache: ShufflingCache,
233
- state: IBeaconStateView
255
+ state: IBeaconStateView,
256
+ singleAttestationPool: SingleAttestationPool
234
257
  ): electra.Attestation[] {
235
258
  const stateSlot = state.slot;
236
259
  const stateEpoch = state.epoch;
@@ -241,18 +264,27 @@ export class AggregatedAttestationPool {
241
264
  const notSeenValidatorsFn = getNotSeenValidatorsFn(this.config, shufflingCache, state);
242
265
  const validateAttestationDataFn = getValidateAttestationDataFn(forkChoice, state);
243
266
 
244
- 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);
245
270
  // Track score of each `AttestationsConsolidation`
246
271
  const consolidations = new Map<AttestationsConsolidation, number>();
272
+ let remainingSingles = MAX_SINGLE_ATTESTATIONS_PER_BLOCK;
247
273
  let scannedSlots = 0;
248
274
  let stopReason: ScannedSlotsTerminationReason | null = null;
249
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();
250
279
  slot: for (const slot of slots) {
251
- const attestationGroupByIndexByDataHash = this.attestationGroupByIndexByDataHexBySlot.get(slot);
252
- // should not happen
253
- if (!attestationGroupByIndexByDataHash) {
254
- throw Error(`No aggregated attestation pool for slot=${slot}`);
255
- }
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>();
256
288
 
257
289
  const epoch = computeEpochAtSlot(slot);
258
290
  if (epoch < statePrevEpoch) {
@@ -279,16 +311,22 @@ export class AggregatedAttestationPool {
279
311
  // Attestations att00 --- att10 --- att20 --- 0 (att 00 10 20)
280
312
  // att01 --- - --- att21 --- 1 (att 01 __ 21)
281
313
  // - --- - --- att22 --- 2 (att __ __ 22)
282
- 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>();
283
321
  // sameAttDataCons could be up to MAX_ATTESTATIONS_PER_GROUP_ELECTRA
284
322
  const sameAttDataCons: AttestationsConsolidation[] = [];
285
- const allAttestationGroups = Array.from(attestationGroupByIndex.values());
286
- if (allAttestationGroups.length === 0) {
323
+ const attData = attestationGroupByIndex.values().next().value?.data ?? singlesDataBySlot.get(dataRootHex);
324
+ if (attData === undefined) {
287
325
  this.metrics?.opPool.aggregatedAttestationPool.packedAttestations.emptyAttestationData.inc();
288
326
  continue;
289
327
  }
290
328
 
291
- const invalidAttDataReason = validateAttestationDataFn(allAttestationGroups[0].data);
329
+ const invalidAttDataReason = validateAttestationDataFn(attData);
292
330
  if (invalidAttDataReason !== null) {
293
331
  this.metrics?.opPool.aggregatedAttestationPool.packedAttestations.invalidAttestationData.inc({
294
332
  reason: invalidAttDataReason,
@@ -296,6 +334,8 @@ export class AggregatedAttestationPool {
296
334
  continue;
297
335
  }
298
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>>();
299
339
  for (const [committeeIndex, attestationGroup] of attestationGroupByIndex.entries()) {
300
340
  const notSeenCommitteeMembers = notSeenValidatorsFn(epoch, slot, committeeIndex);
301
341
  if (notSeenCommitteeMembers === null) {
@@ -327,18 +367,16 @@ export class AggregatedAttestationPool {
327
367
  const attestationsSameGroup = getAttestationGroupResult.result;
328
368
  returnedAttestationsPerSlot += attestationsSameGroup.length;
329
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
+ );
330
375
 
331
376
  for (const [i, attestationNonParticipation] of attestationsSameGroup.entries()) {
332
377
  // sameAttDataCons shares the same index for different committees so we use index `i` here
333
378
  if (sameAttDataCons[i] === undefined) {
334
- sameAttDataCons[i] = {
335
- byCommittee: new Map(),
336
- attData: attestationNonParticipation.attestation.data,
337
- totalNewSeenEffectiveBalance: 0,
338
- newSeenAttesters: 0,
339
- notSeenAttesters: 0,
340
- totalAttesters: 0,
341
- };
379
+ sameAttDataCons[i] = newConsolidation(attestationNonParticipation.attestation.data);
342
380
  }
343
381
  const sameAttDataCon = sameAttDataCons[i];
344
382
  // committeeIndex was from a map so it should be unique, but just in case
@@ -352,6 +390,34 @@ export class AggregatedAttestationPool {
352
390
  }
353
391
  } // all committees are processed
354
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
+
355
421
  this.metrics?.opPool.aggregatedAttestationPool.packedAttestations.returnedAttestations.set(
356
422
  {inclusionDistance},
357
423
  returnedAttestationsPerSlot
@@ -374,16 +440,16 @@ export class AggregatedAttestationPool {
374
440
  gloasState?.latestBlockHeader.slot ?? null
375
441
  );
376
442
 
377
- const weight =
443
+ consolidation.weight =
378
444
  ((flags & TIMELY_SOURCE) === TIMELY_SOURCE ? TIMELY_SOURCE_WEIGHT : 0) +
379
445
  ((flags & TIMELY_TARGET) === TIMELY_TARGET ? TIMELY_TARGET_WEIGHT : 0) +
380
446
  ((flags & TIMELY_HEAD) === TIMELY_HEAD ? TIMELY_HEAD_WEIGHT : 0);
381
447
 
382
- const score = consolidation.totalNewSeenEffectiveBalance * weight;
448
+ const score = consolidation.totalNewSeenEffectiveBalance * consolidation.weight;
383
449
 
384
450
  consolidations.set(consolidation, score);
385
- // Stop accumulating attestations there are enough that may have good scoring
386
- 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) {
387
453
  stopReason = ScannedSlotsTerminationReason.MaxConsolidationReached;
388
454
  break slot;
389
455
  }
@@ -415,26 +481,36 @@ export class AggregatedAttestationPool {
415
481
  // on chain aggregation is expensive, only do it after all
416
482
  const packedAttestationsMetrics = this.metrics?.opPool.aggregatedAttestationPool.packedAttestations;
417
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();
418
492
  for (const consolidation of sortedConsolidationsByScore) {
419
493
  if (packedAttestations.length >= MAX_ATTESTATIONS_ELECTRA) {
420
494
  break;
421
495
  }
422
496
 
423
497
  const attestation = aggregateConsolidation(consolidation);
498
+ const committeeCount = attestation.committeeBits.getTrueBitIndexes().length;
424
499
  // The point at infinity is not a valid aggregate signature, exclude it from the block
425
500
  if (byteArrayEquals(attestation.signature, G2_POINT_AT_INFINITY)) {
426
501
  this.logger?.debug("Excluding aggregate with infinity signature", {
427
502
  slot: stateSlot,
428
503
  attestationSlot: attestation.data.slot,
429
- committees: consolidation.byCommittee.size,
504
+ committees: committeeCount,
430
505
  });
431
506
  continue;
432
507
  }
433
508
 
434
509
  const i = packedAttestations.push(attestation) - 1;
510
+ packedConsolidations.push(consolidation);
435
511
 
436
512
  // record metrics of packed attestations
437
- packedAttestationsMetrics?.committeeCount.set({index: i}, consolidation.byCommittee.size);
513
+ packedAttestationsMetrics?.committeeCount.set({index: i}, committeeCount);
438
514
  packedAttestationsMetrics?.totalAttesters.set({index: i}, consolidation.totalAttesters);
439
515
  packedAttestationsMetrics?.nonParticipation.set({index: i}, consolidation.notSeenAttesters);
440
516
  packedAttestationsMetrics?.inclusionDistance.set({index: i}, stateSlot - attestation.data.slot);
@@ -442,9 +518,62 @@ export class AggregatedAttestationPool {
442
518
  packedAttestationsMetrics?.totalEffectiveBalance.set({index: i}, consolidation.totalNewSeenEffectiveBalance);
443
519
  }
444
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
+
445
572
  if (stopReason === null) {
446
573
  stopReason = ScannedSlotsTerminationReason.ScannedAllSlots;
447
574
  }
575
+ // only one reason per block, reset so that other reasons do not keep values of a previous block
576
+ packedAttestationsMetrics?.scannedSlots.reset();
448
577
  packedAttestationsMetrics?.scannedSlots.set({reason: stopReason}, scannedSlots);
449
578
  packedAttestationsMetrics?.poolSlots.set(slots.length);
450
579
 
@@ -745,20 +874,38 @@ export function aggregateInto(attestation1: AttestationWithIndex, attestation2:
745
874
  * attestation data from different committee into a single attestation
746
875
  * https://github.com/ethereum/consensus-specs/blob/aba6345776aa876dad368cab27fbbb23fae20455/specs/_features/eip7549/validator.md?plain=1#L39
747
876
  */
748
- export function aggregateConsolidation({byCommittee, attData}: AttestationsConsolidation): electra.Attestation {
877
+ export function aggregateConsolidation({
878
+ byCommittee,
879
+ singlesByCommittee,
880
+ attData,
881
+ }: AttestationsConsolidation): electra.Attestation {
749
882
  const committeeBits = BitArray.fromBitLen(MAX_COMMITTEES_PER_SLOT);
750
883
  // TODO: can we improve this?
751
884
  let aggregationBits: boolean[] = [];
752
885
  const signatures: Signature[] = [];
753
- 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
+ );
754
889
  for (const committeeIndex of sortedCommittees) {
755
- const attestationNonParticipation = byCommittee.get(committeeIndex);
756
- if (attestationNonParticipation !== undefined) {
757
- const {attestation} = attestationNonParticipation;
758
- committeeBits.set(committeeIndex, true);
759
- 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();
760
895
  signatures.push(signatureFromBytesNoCheck(attestation.signature));
896
+ } else if (singles !== undefined) {
897
+ committeeAggregationBits = new Array<boolean>(singles.committeeSize).fill(false);
898
+ } else {
899
+ continue;
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));
761
906
  }
907
+ committeeBits.set(committeeIndex, true);
908
+ aggregationBits = [...aggregationBits, ...committeeAggregationBits];
762
909
  }
763
910
  return {
764
911
  aggregationBits: BitArray.fromBoolArray(aggregationBits),
@@ -768,6 +915,46 @@ export function aggregateConsolidation({byCommittee, attData}: AttestationsConso
768
915
  };
769
916
  }
770
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
+
771
958
  /**
772
959
  * Pre-compute participation from a IBeaconStateView, for use to check if an attestation's committee
773
960
  * has already attested or not.
@@ -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";