@lodestar/beacon-node 1.48.0-dev.f22c5ce63e → 1.48.0-rc.0

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 (296) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +4 -11
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  5. package/lib/api/impl/beacon/state/utils.js +14 -0
  6. package/lib/api/impl/beacon/state/utils.js.map +1 -1
  7. package/lib/api/impl/config/index.d.ts.map +1 -1
  8. package/lib/api/impl/config/index.js +4 -1
  9. package/lib/api/impl/config/index.js.map +1 -1
  10. package/lib/api/impl/validator/index.d.ts.map +1 -1
  11. package/lib/api/impl/validator/index.js +39 -39
  12. package/lib/api/impl/validator/index.js.map +1 -1
  13. package/lib/chain/archiveStore/archiveStore.d.ts +1 -0
  14. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  15. package/lib/chain/archiveStore/archiveStore.js +5 -1
  16. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  17. package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts.map +1 -1
  18. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -0
  19. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
  20. package/lib/chain/archiveStore/historicalState/metrics.d.ts.map +1 -1
  21. package/lib/chain/archiveStore/historicalState/metrics.js +12 -1
  22. package/lib/chain/archiveStore/historicalState/metrics.js.map +1 -1
  23. package/lib/chain/archiveStore/historicalState/types.d.ts +2 -0
  24. package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
  25. package/lib/chain/archiveStore/historicalState/types.js.map +1 -1
  26. package/lib/chain/archiveStore/historicalState/worker.js +4 -1
  27. package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
  28. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +9 -1
  29. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
  30. package/lib/chain/archiveStore/utils/archiveBlocks.js +68 -38
  31. package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
  32. package/lib/chain/blocks/importBlock.d.ts +5 -1
  33. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  34. package/lib/chain/blocks/importBlock.js +12 -18
  35. package/lib/chain/blocks/importBlock.js.map +1 -1
  36. package/lib/chain/blocks/index.d.ts +8 -4
  37. package/lib/chain/blocks/index.d.ts.map +1 -1
  38. package/lib/chain/blocks/index.js +83 -17
  39. package/lib/chain/blocks/index.js.map +1 -1
  40. package/lib/chain/blocks/types.d.ts +8 -0
  41. package/lib/chain/blocks/types.d.ts.map +1 -1
  42. package/lib/chain/blocks/types.js.map +1 -1
  43. package/lib/chain/blocks/utils/chainSegment.d.ts +1 -1
  44. package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
  45. package/lib/chain/blocks/utils/chainSegment.js +26 -11
  46. package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
  47. package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
  48. package/lib/chain/blocks/writeBlockInputToDb.js +9 -16
  49. package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
  50. package/lib/chain/chain.d.ts +11 -5
  51. package/lib/chain/chain.d.ts.map +1 -1
  52. package/lib/chain/chain.js +129 -75
  53. package/lib/chain/chain.js.map +1 -1
  54. package/lib/chain/emitter.d.ts +1 -1
  55. package/lib/chain/emitter.js +1 -1
  56. package/lib/chain/errors/blockError.d.ts +19 -7
  57. package/lib/chain/errors/blockError.d.ts.map +1 -1
  58. package/lib/chain/errors/blockError.js +2 -2
  59. package/lib/chain/errors/blockError.js.map +1 -1
  60. package/lib/chain/errors/dataColumnSidecarError.d.ts +15 -2
  61. package/lib/chain/errors/dataColumnSidecarError.d.ts.map +1 -1
  62. package/lib/chain/errors/dataColumnSidecarError.js.map +1 -1
  63. package/lib/chain/errors/executionPayloadBid.d.ts +4 -0
  64. package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
  65. package/lib/chain/errors/executionPayloadBid.js +1 -0
  66. package/lib/chain/errors/executionPayloadBid.js.map +1 -1
  67. package/lib/chain/errors/executionPayloadEnvelope.d.ts +10 -11
  68. package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
  69. package/lib/chain/errors/executionPayloadEnvelope.js +0 -2
  70. package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
  71. package/lib/chain/errors/gossipValidation.d.ts +2 -1
  72. package/lib/chain/errors/gossipValidation.d.ts.map +1 -1
  73. package/lib/chain/errors/gossipValidation.js +1 -0
  74. package/lib/chain/errors/gossipValidation.js.map +1 -1
  75. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  76. package/lib/chain/forkChoice/index.js +2 -0
  77. package/lib/chain/forkChoice/index.js.map +1 -1
  78. package/lib/chain/interface.d.ts +4 -4
  79. package/lib/chain/interface.d.ts.map +1 -1
  80. package/lib/chain/lightClient/index.d.ts +3 -3
  81. package/lib/chain/lightClient/index.d.ts.map +1 -1
  82. package/lib/chain/lightClient/index.js +21 -23
  83. package/lib/chain/lightClient/index.js.map +1 -1
  84. package/lib/chain/lightClient/proofs.d.ts +2 -1
  85. package/lib/chain/lightClient/proofs.d.ts.map +1 -1
  86. package/lib/chain/lightClient/proofs.js +5 -1
  87. package/lib/chain/lightClient/proofs.js.map +1 -1
  88. package/lib/chain/opPools/aggregatedAttestationPool.js +1 -1
  89. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  90. package/lib/chain/prepareNextSlot.js +13 -13
  91. package/lib/chain/prepareNextSlot.js.map +1 -1
  92. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  93. package/lib/chain/produceBlock/produceBlockBody.js +46 -64
  94. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  95. package/lib/chain/validation/block.d.ts.map +1 -1
  96. package/lib/chain/validation/block.js +35 -54
  97. package/lib/chain/validation/block.js.map +1 -1
  98. package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
  99. package/lib/chain/validation/dataColumnSidecar.js +38 -13
  100. package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
  101. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  102. package/lib/chain/validation/executionPayloadBid.js +56 -40
  103. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  104. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  105. package/lib/chain/validation/executionPayloadEnvelope.js +10 -29
  106. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  107. package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
  108. package/lib/chain/validation/payloadAttestationMessage.js +5 -6
  109. package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
  110. package/lib/chain/validatorMonitor.d.ts +7 -1
  111. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  112. package/lib/chain/validatorMonitor.js +22 -5
  113. package/lib/chain/validatorMonitor.js.map +1 -1
  114. package/lib/db/beacon.d.ts +14 -5
  115. package/lib/db/beacon.d.ts.map +1 -1
  116. package/lib/db/beacon.js +17 -3
  117. package/lib/db/beacon.js.map +1 -1
  118. package/lib/db/dataColumnStore.d.ts +39 -0
  119. package/lib/db/dataColumnStore.d.ts.map +1 -0
  120. package/lib/db/dataColumnStore.js +81 -0
  121. package/lib/db/dataColumnStore.js.map +1 -0
  122. package/lib/db/flatFileStore/atomicWrite.d.ts +8 -0
  123. package/lib/db/flatFileStore/atomicWrite.d.ts.map +1 -0
  124. package/lib/db/flatFileStore/atomicWrite.js +61 -0
  125. package/lib/db/flatFileStore/atomicWrite.js.map +1 -0
  126. package/lib/db/flatFileStore/dcolFormat.d.ts +90 -0
  127. package/lib/db/flatFileStore/dcolFormat.d.ts.map +1 -0
  128. package/lib/db/flatFileStore/dcolFormat.js +286 -0
  129. package/lib/db/flatFileStore/dcolFormat.js.map +1 -0
  130. package/lib/db/flatFileStore/errors.d.ts +82 -0
  131. package/lib/db/flatFileStore/errors.d.ts.map +1 -0
  132. package/lib/db/flatFileStore/errors.js +32 -0
  133. package/lib/db/flatFileStore/errors.js.map +1 -0
  134. package/lib/db/flatFileStore/flatFileStore.d.ts +41 -0
  135. package/lib/db/flatFileStore/flatFileStore.d.ts.map +1 -0
  136. package/lib/db/flatFileStore/flatFileStore.js +251 -0
  137. package/lib/db/flatFileStore/flatFileStore.js.map +1 -0
  138. package/lib/db/flatFileStore/index.d.ts +4 -0
  139. package/lib/db/flatFileStore/index.d.ts.map +1 -0
  140. package/lib/db/flatFileStore/index.js +2 -0
  141. package/lib/db/flatFileStore/index.js.map +1 -0
  142. package/lib/db/flatFileStore/interface.d.ts +25 -0
  143. package/lib/db/flatFileStore/interface.d.ts.map +1 -0
  144. package/lib/db/flatFileStore/interface.js +2 -0
  145. package/lib/db/flatFileStore/interface.js.map +1 -0
  146. package/lib/db/flatFileStore/metrics.d.ts +24 -0
  147. package/lib/db/flatFileStore/metrics.d.ts.map +1 -0
  148. package/lib/db/flatFileStore/metrics.js +25 -0
  149. package/lib/db/flatFileStore/metrics.js.map +1 -0
  150. package/lib/db/flatFileStore/path.d.ts +9 -0
  151. package/lib/db/flatFileStore/path.d.ts.map +1 -0
  152. package/lib/db/flatFileStore/path.js +21 -0
  153. package/lib/db/flatFileStore/path.js.map +1 -0
  154. package/lib/db/flatFileStore/slotIndex.d.ts +14 -0
  155. package/lib/db/flatFileStore/slotIndex.d.ts.map +1 -0
  156. package/lib/db/flatFileStore/slotIndex.js +46 -0
  157. package/lib/db/flatFileStore/slotIndex.js.map +1 -0
  158. package/lib/db/flatFileStore/snappy.d.ts +3 -0
  159. package/lib/db/flatFileStore/snappy.d.ts.map +1 -0
  160. package/lib/db/flatFileStore/snappy.js +12 -0
  161. package/lib/db/flatFileStore/snappy.js.map +1 -0
  162. package/lib/db/index.d.ts +1 -0
  163. package/lib/db/index.d.ts.map +1 -1
  164. package/lib/db/interface.d.ts +8 -1
  165. package/lib/db/interface.d.ts.map +1 -1
  166. package/lib/db/repositories/blockArchive.d.ts +8 -1
  167. package/lib/db/repositories/blockArchive.d.ts.map +1 -1
  168. package/lib/db/repositories/blockArchive.js +65 -28
  169. package/lib/db/repositories/blockArchive.js.map +1 -1
  170. package/lib/db/repositories/blockArchiveIndex.d.ts +1 -2
  171. package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
  172. package/lib/db/repositories/blockArchiveIndex.js +3 -7
  173. package/lib/db/repositories/blockArchiveIndex.js.map +1 -1
  174. package/lib/execution/builder/validateBid.d.ts.map +1 -1
  175. package/lib/execution/builder/validateBid.js +8 -5
  176. package/lib/execution/builder/validateBid.js.map +1 -1
  177. package/lib/execution/engine/mock.d.ts.map +1 -1
  178. package/lib/execution/engine/mock.js +4 -1
  179. package/lib/execution/engine/mock.js.map +1 -1
  180. package/lib/metrics/metrics/lodestar.d.ts +22 -3
  181. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  182. package/lib/metrics/metrics/lodestar.js +60 -6
  183. package/lib/metrics/metrics/lodestar.js.map +1 -1
  184. package/lib/monitoring/clientStats.js +1 -1
  185. package/lib/monitoring/clientStats.js.map +1 -1
  186. package/lib/network/gossip/encoding.d.ts.map +1 -1
  187. package/lib/network/gossip/encoding.js +0 -7
  188. package/lib/network/gossip/encoding.js.map +1 -1
  189. package/lib/network/gossip/topic.d.ts +2 -1
  190. package/lib/network/gossip/topic.d.ts.map +1 -1
  191. package/lib/network/gossip/topic.js +4 -20
  192. package/lib/network/gossip/topic.js.map +1 -1
  193. package/lib/network/network.js +2 -2
  194. package/lib/network/network.js.map +1 -1
  195. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  196. package/lib/network/processor/gossipHandlers.js +388 -285
  197. package/lib/network/processor/gossipHandlers.js.map +1 -1
  198. package/lib/network/processor/index.d.ts +49 -3
  199. package/lib/network/processor/index.d.ts.map +1 -1
  200. package/lib/network/processor/index.js +254 -114
  201. package/lib/network/processor/index.js.map +1 -1
  202. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
  203. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +112 -91
  204. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
  205. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.d.ts.map +1 -1
  206. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +2 -0
  207. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js.map +1 -1
  208. package/lib/network/reqresp/protocols.d.ts.map +1 -1
  209. package/lib/network/reqresp/protocols.js +6 -22
  210. package/lib/network/reqresp/protocols.js.map +1 -1
  211. package/lib/network/reqresp/rateLimit.js +2 -1
  212. package/lib/network/reqresp/rateLimit.js.map +1 -1
  213. package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts +2 -1
  214. package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts.map +1 -1
  215. package/lib/network/reqresp/utils/dataColumnResponseValidation.js +14 -9
  216. package/lib/network/reqresp/utils/dataColumnResponseValidation.js.map +1 -1
  217. package/lib/node/nodejs.d.ts +2 -1
  218. package/lib/node/nodejs.d.ts.map +1 -1
  219. package/lib/node/nodejs.js +4 -2
  220. package/lib/node/nodejs.js.map +1 -1
  221. package/lib/sync/range/range.d.ts.map +1 -1
  222. package/lib/sync/range/range.js +24 -1
  223. package/lib/sync/range/range.js.map +1 -1
  224. package/lib/util/sszBytes.d.ts +6 -0
  225. package/lib/util/sszBytes.d.ts.map +1 -1
  226. package/lib/util/sszBytes.js +1 -1
  227. package/lib/util/sszBytes.js.map +1 -1
  228. package/package.json +18 -19
  229. package/src/api/impl/beacon/blocks/index.ts +8 -14
  230. package/src/api/impl/beacon/state/utils.ts +15 -0
  231. package/src/api/impl/config/index.ts +4 -1
  232. package/src/api/impl/validator/index.ts +44 -43
  233. package/src/chain/archiveStore/archiveStore.ts +12 -1
  234. package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +1 -0
  235. package/src/chain/archiveStore/historicalState/metrics.ts +14 -1
  236. package/src/chain/archiveStore/historicalState/types.ts +2 -0
  237. package/src/chain/archiveStore/historicalState/worker.ts +4 -1
  238. package/src/chain/archiveStore/utils/archiveBlocks.ts +73 -42
  239. package/src/chain/blocks/importBlock.ts +25 -20
  240. package/src/chain/blocks/index.ts +120 -23
  241. package/src/chain/blocks/types.ts +9 -0
  242. package/src/chain/blocks/utils/chainSegment.ts +26 -12
  243. package/src/chain/blocks/writeBlockInputToDb.ts +10 -17
  244. package/src/chain/chain.ts +153 -84
  245. package/src/chain/emitter.ts +1 -1
  246. package/src/chain/errors/blockError.ts +22 -10
  247. package/src/chain/errors/dataColumnSidecarError.ts +24 -8
  248. package/src/chain/errors/executionPayloadBid.ts +2 -0
  249. package/src/chain/errors/executionPayloadEnvelope.ts +14 -11
  250. package/src/chain/errors/gossipValidation.ts +1 -0
  251. package/src/chain/forkChoice/index.ts +2 -0
  252. package/src/chain/interface.ts +4 -4
  253. package/src/chain/lightClient/index.ts +32 -36
  254. package/src/chain/lightClient/proofs.ts +10 -0
  255. package/src/chain/opPools/aggregatedAttestationPool.ts +1 -1
  256. package/src/chain/prepareNextSlot.ts +16 -16
  257. package/src/chain/produceBlock/produceBlockBody.ts +50 -71
  258. package/src/chain/validation/block.ts +35 -70
  259. package/src/chain/validation/dataColumnSidecar.ts +47 -14
  260. package/src/chain/validation/executionPayloadBid.ts +62 -44
  261. package/src/chain/validation/executionPayloadEnvelope.ts +10 -37
  262. package/src/chain/validation/payloadAttestationMessage.ts +8 -9
  263. package/src/chain/validatorMonitor.ts +24 -7
  264. package/src/db/beacon.ts +33 -6
  265. package/src/db/dataColumnStore.ts +113 -0
  266. package/src/db/flatFileStore/atomicWrite.ts +65 -0
  267. package/src/db/flatFileStore/dcolFormat.ts +389 -0
  268. package/src/db/flatFileStore/errors.ts +53 -0
  269. package/src/db/flatFileStore/flatFileStore.ts +310 -0
  270. package/src/db/flatFileStore/index.ts +3 -0
  271. package/src/db/flatFileStore/interface.ts +21 -0
  272. package/src/db/flatFileStore/metrics.ts +48 -0
  273. package/src/db/flatFileStore/path.ts +32 -0
  274. package/src/db/flatFileStore/slotIndex.ts +56 -0
  275. package/src/db/flatFileStore/snappy.ts +14 -0
  276. package/src/db/index.ts +1 -0
  277. package/src/db/interface.ts +9 -1
  278. package/src/db/repositories/blockArchive.ts +89 -30
  279. package/src/db/repositories/blockArchiveIndex.ts +4 -9
  280. package/src/execution/builder/validateBid.ts +10 -6
  281. package/src/execution/engine/mock.ts +4 -1
  282. package/src/metrics/metrics/lodestar.ts +63 -6
  283. package/src/monitoring/clientStats.ts +1 -1
  284. package/src/network/gossip/encoding.ts +0 -7
  285. package/src/network/gossip/topic.ts +3 -25
  286. package/src/network/network.ts +2 -2
  287. package/src/network/processor/gossipHandlers.ts +500 -355
  288. package/src/network/processor/index.ts +287 -165
  289. package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +139 -105
  290. package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +2 -0
  291. package/src/network/reqresp/protocols.ts +7 -24
  292. package/src/network/reqresp/rateLimit.ts +2 -1
  293. package/src/network/reqresp/utils/dataColumnResponseValidation.ts +15 -7
  294. package/src/node/nodejs.ts +6 -1
  295. package/src/sync/range/range.ts +23 -1
  296. package/src/util/sszBytes.ts +1 -1
@@ -1,3 +1,5 @@
1
+ import {PayloadStatus} from "@lodestar/fork-choice";
2
+ import {computeEpochAtSlot} from "@lodestar/state-transition";
1
3
  import {SignedBeaconBlock, Slot} from "@lodestar/types";
2
4
  import {isErrorAborted, toRootHex} from "@lodestar/utils";
3
5
  import {Metrics} from "../../metrics/metrics.js";
@@ -5,15 +7,17 @@ import {nextEventLoop} from "../../util/eventLoop.js";
5
7
  import {JobItemQueue, isQueueErrorAborted} from "../../util/queue/index.js";
6
8
  import type {BeaconChain} from "../chain.js";
7
9
  import {BlockError, BlockErrorCode, isBlockErrorAborted} from "../errors/index.js";
10
+ import {ForkchoiceCaller} from "../forkChoice/index.js";
8
11
  import {BlockProcessOpts} from "../options.js";
9
12
  import {IBlockInput} from "./blockInput/types.js";
10
- import {importBlock} from "./importBlock.js";
13
+ import {importBlock, importsBlockAttestations} from "./importBlock.js";
11
14
  import {PayloadError, importExecutionPayload} from "./importExecutionPayload.js";
12
15
  import {PayloadEnvelopeInput} from "./payloadEnvelopeInput/payloadEnvelopeInput.js";
13
- import {FullyVerifiedBlock, ImportBlockOpts} from "./types.js";
14
- import {assertLinearChainSegment} from "./utils/chainSegment.js";
16
+ import {FullyVerifiedBlock, ImportBlockOpts, ProcessBlocksResult} from "./types.js";
17
+ import {OrphanedPayloadEnvelope, assertLinearChainSegment} from "./utils/chainSegment.js";
15
18
  import {verifyBlocksInEpoch} from "./verifyBlock.js";
16
19
  import {verifyBlocksSanityChecks} from "./verifyBlocksSanityChecks.js";
20
+ import {verifyPayloadsDataAvailability} from "./verifyPayloadsDataAvailability.js";
17
21
 
18
22
  export {AttestationImportOpt, type ImportBlockOpts} from "./types.js";
19
23
 
@@ -23,10 +27,16 @@ const QUEUE_MAX_LENGTH = 256;
23
27
  * BlockProcessor processes block jobs in a queued fashion, one after the other.
24
28
  */
25
29
  export class BlockProcessor {
26
- readonly jobQueue: JobItemQueue<[IBlockInput[], Map<Slot, PayloadEnvelopeInput> | null, ImportBlockOpts], void>;
30
+ readonly jobQueue: JobItemQueue<
31
+ [IBlockInput[], Map<Slot, PayloadEnvelopeInput> | null, ImportBlockOpts],
32
+ ProcessBlocksResult
33
+ >;
27
34
 
28
35
  constructor(chain: BeaconChain, metrics: Metrics | null, opts: BlockProcessOpts, signal: AbortSignal) {
29
- this.jobQueue = new JobItemQueue<[IBlockInput[], Map<Slot, PayloadEnvelopeInput> | null, ImportBlockOpts], void>(
36
+ this.jobQueue = new JobItemQueue<
37
+ [IBlockInput[], Map<Slot, PayloadEnvelopeInput> | null, ImportBlockOpts],
38
+ ProcessBlocksResult
39
+ >(
30
40
  (job, payloadEnvelopes, importOpts) => {
31
41
  return processBlocks.call(chain, job, payloadEnvelopes, {...opts, ...importOpts});
32
42
  },
@@ -39,8 +49,8 @@ export class BlockProcessor {
39
49
  job: IBlockInput[],
40
50
  payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
41
51
  opts: ImportBlockOpts = {}
42
- ): Promise<void> {
43
- await this.jobQueue.push(job, payloadEnvelopes, opts);
52
+ ): Promise<ProcessBlocksResult> {
53
+ return this.jobQueue.push(job, payloadEnvelopes, opts);
44
54
  }
45
55
  }
46
56
 
@@ -59,9 +69,10 @@ export async function processBlocks(
59
69
  blocks: IBlockInput[],
60
70
  payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
61
71
  opts: BlockProcessOpts & ImportBlockOpts
62
- ): Promise<void> {
72
+ ): Promise<ProcessBlocksResult> {
73
+ const emptyResult: ProcessBlocksResult = {orphaned: [], skipped: false};
63
74
  if (blocks.length === 0) {
64
- return; // TODO: or throw?
75
+ return emptyResult; // TODO: or throw?
65
76
  }
66
77
 
67
78
  try {
@@ -70,7 +81,7 @@ export async function processBlocks(
70
81
  // No relevant blocks, skip verifyBlocksInEpoch()
71
82
  if (relevantBlocks.length === 0 || parentBlock === null) {
72
83
  // parentBlock can only be null if relevantBlocks are empty
73
- return;
84
+ return await importPayloadEnvelopesOfKnownBlocks.call(this, payloadEnvelopes, opts);
74
85
  }
75
86
 
76
87
  const {warnings: orphanedPayloads} = assertLinearChainSegment(
@@ -79,12 +90,21 @@ export async function processBlocks(
79
90
  payloadEnvelopes,
80
91
  parentBlock
81
92
  );
82
- if (orphanedPayloads != null) {
83
- for (const orphaned of orphanedPayloads) {
84
- this.logger.debug("Orphaned payload envelope in chain segment", {
85
- slot: orphaned.slot,
86
- blockRoot: orphaned.payloadEnvelopeInput.blockRootHex,
87
- });
93
+ // Orphaned payloads of recent blocks are still imported, a reorg of the child could make the payload canonical
94
+ // again and later blocks build on it. Older ones are skipped: without the block attestations the orphaned FULL
95
+ // variant has no descendants and ties at zero weight with the EMPTY variant carrying the chain, the payload
96
+ // status tiebreaker then picks FULL and parks the head there.
97
+ const blockEpoch = computeEpochAtSlot(relevantBlocks[0].getBlock().message.slot);
98
+ const importsAttestations = importsBlockAttestations(opts, blockEpoch, this.clock.currentEpoch);
99
+ const skipped = orphanedPayloads != null && payloadEnvelopes !== null && !importsAttestations;
100
+ let payloadEnvelopesToImport = payloadEnvelopes;
101
+ if (skipped) {
102
+ payloadEnvelopesToImport = new Map(payloadEnvelopes);
103
+ for (const orphaned of orphanedPayloads ?? []) {
104
+ payloadEnvelopesToImport.delete(orphaned.slot);
105
+ // never validated, drop it from the shared cache so it is not served to peers, by-root sync reloads the
106
+ // entry from db if the payload is ever needed
107
+ this.seenPayloadEnvelopeInputCache.prune(orphaned.payloadEnvelopeInput.blockRootHex);
88
108
  }
89
109
  }
90
110
 
@@ -97,7 +117,7 @@ export async function processBlocks(
97
117
  proposerBalanceDeltas,
98
118
  segmentExecStatus,
99
119
  indexedAttestationsByBlock,
100
- } = await verifyBlocksInEpoch.call(this, parentBlock, relevantBlocks, payloadEnvelopes, opts);
120
+ } = await verifyBlocksInEpoch.call(this, parentBlock, relevantBlocks, payloadEnvelopesToImport, opts);
101
121
 
102
122
  // If segmentExecStatus has lvhForkchoice then, the entire segment should be invalid
103
123
  // and we need to further propagate
@@ -132,8 +152,8 @@ export async function processBlocks(
132
152
  }
133
153
 
134
154
  const slotSet = new Set<Slot>(blocks.map((b) => b.getBlock().message.slot));
135
- if (payloadEnvelopes) {
136
- for (const slot of payloadEnvelopes.keys()) slotSet.add(slot);
155
+ if (payloadEnvelopesToImport) {
156
+ for (const slot of payloadEnvelopesToImport.keys()) slotSet.add(slot);
137
157
  }
138
158
  const slots = Array.from(slotSet).sort((a, b) => a - b);
139
159
  for (const slot of slots) {
@@ -146,7 +166,7 @@ export async function processBlocks(
146
166
  // PayloadEnvelopeInput is shared and may receive an envelope after the DA snapshot was taken.
147
167
  const payloadDA = payloadDAStatuses.get(slot);
148
168
  if (payloadDA !== undefined) {
149
- const payloadInput = payloadEnvelopes?.get(slot);
169
+ const payloadInput = payloadEnvelopesToImport?.get(slot);
150
170
  if (payloadInput === undefined) {
151
171
  throw new Error(`Missing payload input for slot ${slot} after DA verification`);
152
172
  }
@@ -159,9 +179,11 @@ export async function processBlocks(
159
179
 
160
180
  await nextEventLoop();
161
181
  }
182
+
183
+ return {orphaned: orphanedPayloads ?? [], skipped};
162
184
  } catch (e) {
163
185
  if (isErrorAborted(e) || isQueueErrorAborted(e) || isBlockErrorAborted(e)) {
164
- return; // Ignore
186
+ return emptyResult; // Ignore
165
187
  }
166
188
 
167
189
  // above functions should only throw BlockError, or PayloadError from the gloas payload import
@@ -187,8 +209,19 @@ export async function processBlocks(
187
209
  const blockSlot = signedBlock.message.slot;
188
210
  const {state} = err.type;
189
211
  const forkTypes = this.config.getForkTypes(blockSlot);
190
- this.persistInvalidSszValue(forkTypes.SignedBeaconBlock, signedBlock, `${blockSlot}_invalid_signature`);
191
- this.persistInvalidSszBytes("BeaconState", state.serialize(), `${state.slot}_invalid_signature`);
212
+ const blockRootHex = toRootHex(forkTypes.BeaconBlock.hashTreeRoot(signedBlock.message));
213
+ this.persistInvalidSszValue(
214
+ forkTypes.SignedBeaconBlock,
215
+ signedBlock,
216
+ `${blockSlot}_invalid_signature`,
217
+ blockRootHex
218
+ );
219
+ this.persistInvalidSszBytes(
220
+ "BeaconState",
221
+ state.serialize(),
222
+ toRootHex(state.hashTreeRoot()),
223
+ `${state.slot}_invalid_signature`
224
+ );
192
225
  } else if (err.type.code === BlockErrorCode.INVALID_STATE_ROOT) {
193
226
  const {signedBlock} = err;
194
227
  const blockSlot = signedBlock.message.slot;
@@ -209,6 +242,70 @@ export async function processBlocks(
209
242
  }
210
243
  }
211
244
 
245
+ /**
246
+ * A peer can serve a block without its envelope, the block is then imported with a PENDING payload. Later batches
247
+ * carry the envelope but all their blocks are known, without importing it here every child building on the FULL
248
+ * variant fails with PARENT_PAYLOAD_UNKNOWN and range sync never progresses. If our head already descends from the
249
+ * block's EMPTY variant the chain did not build on the payload, importing it would only add a dead FULL leaf. As for
250
+ * orphaned payloads in a segment this only applies while the block attestations are not imported, a recent payload
251
+ * is imported anyway so a reorg building on it does not have to fetch it through unknown block sync.
252
+ */
253
+ async function importPayloadEnvelopesOfKnownBlocks(
254
+ this: BeaconChain,
255
+ payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
256
+ opts: ImportBlockOpts
257
+ ): Promise<ProcessBlocksResult> {
258
+ if (payloadEnvelopes === null) {
259
+ return {orphaned: [], skipped: false};
260
+ }
261
+
262
+ const head = this.forkChoice.getHead();
263
+ const currentEpoch = this.clock.currentEpoch;
264
+ const payloadInputs: PayloadEnvelopeInput[] = [];
265
+ const orphaned: OrphanedPayloadEnvelope[] = [];
266
+ for (const payloadInput of payloadEnvelopes.values()) {
267
+ const {blockRootHex, slot} = payloadInput;
268
+ if (
269
+ !payloadInput.hasPayloadEnvelope() ||
270
+ !this.forkChoice.hasBlockHex(blockRootHex) ||
271
+ this.forkChoice.getBlockHexAndBlockHash(blockRootHex, payloadInput.getBlockHashHex()) !== null
272
+ ) {
273
+ continue;
274
+ }
275
+ if (
276
+ head.blockRoot !== blockRootHex &&
277
+ !importsBlockAttestations(opts, computeEpochAtSlot(slot), currentEpoch) &&
278
+ this.forkChoice.isDescendant(blockRootHex, PayloadStatus.EMPTY, head.blockRoot, head.payloadStatus)
279
+ ) {
280
+ // never validated, see processBlocks()
281
+ this.seenPayloadEnvelopeInputCache.prune(blockRootHex);
282
+ orphaned.push({slot, payloadEnvelopeInput: payloadInput});
283
+ continue;
284
+ }
285
+ payloadInputs.push(payloadInput);
286
+ }
287
+
288
+ // orphaned envelopes on this path are always skipped, range sync logs them with peer/client context
289
+ const result: ProcessBlocksResult = {orphaned, skipped: orphaned.length > 0};
290
+
291
+ if (payloadInputs.length === 0) {
292
+ return result;
293
+ }
294
+
295
+ const {dataAvailabilityStatuses} = await verifyPayloadsDataAvailability(payloadInputs, new AbortController().signal);
296
+ for (let i = 0; i < payloadInputs.length; i++) {
297
+ this.logger.debug("Importing payload envelope of known block", {
298
+ slot: payloadInputs[i].slot,
299
+ blockRoot: payloadInputs[i].blockRootHex,
300
+ });
301
+ await importExecutionPayload.call(this, payloadInputs[i], dataAvailabilityStatuses[i], {validSignature: false});
302
+ }
303
+ // the new FULL variants are not seen by the head cached from the last block import
304
+ this.recomputeForkChoiceHead(ForkchoiceCaller.importBlock);
305
+
306
+ return result;
307
+ }
308
+
212
309
  function getBlockOrPayloadError(e: unknown, block: SignedBeaconBlock): BlockError | PayloadError {
213
310
  if (e instanceof BlockError) {
214
311
  return e;
@@ -4,6 +4,7 @@ import {ForkSeq} from "@lodestar/params";
4
4
  import {DataAvailabilityStatus, IBeaconStateView, computeEpochAtSlot} from "@lodestar/state-transition";
5
5
  import type {IndexedAttestation, Slot, fulu} from "@lodestar/types";
6
6
  import {IBlockInput} from "./blockInput/types.js";
7
+ import {OrphanedPayloadEnvelope} from "./utils/chainSegment.js";
7
8
 
8
9
  export enum GossipedInputType {
9
10
  block = "block",
@@ -110,3 +111,11 @@ export type FullyVerifiedBlock = {
110
111
  /** If the execution payload couldn't be verified because of EL syncing status, used in optimistic sync */
111
112
  executionStatus: BlockExecutionStatus | PayloadExecutionStatus;
112
113
  };
114
+
115
+ /**
116
+ * Result of processing a chain segment.
117
+ */
118
+ export type ProcessBlocksResult = {
119
+ orphaned: OrphanedPayloadEnvelope[];
120
+ skipped: boolean;
121
+ };
@@ -22,7 +22,7 @@ export type ChainSegmentResult = {warnings: OrphanedPayloadEnvelope[] | null};
22
22
  * - Verifies parent root + slot linearity
23
23
  * - For gloas: verifies bid.parentBlockHash matches the tracked execution hash; if not, the
24
24
  * previous FULL envelope is treated as orphaned (segment continues as if previous slot was EMPTY)
25
- * - If an envelope exists for this slot: verifies it references this block's root
25
+ * - If an envelope exists for this slot (or the parent's slot): verifies it references this block's root
26
26
  * - Advances the tracked execution hash (FULL if envelope present, EMPTY if not)
27
27
  */
28
28
  export function assertLinearChainSegment(
@@ -37,17 +37,6 @@ export function assertLinearChainSegment(
37
37
 
38
38
  const warnings: OrphanedPayloadEnvelope[] = [];
39
39
 
40
- let parentExecHash: string | null = parentBlock?.executionPayloadBlockHash ?? null;
41
- if (parentBlock !== null) {
42
- const parentPayloadInput = payloadEnvelopes?.get(parentBlock.slot);
43
- if (parentPayloadInput?.hasPayloadEnvelope()) {
44
- // Checkpoint-sync first batch: the anchor is stored PENDING with the inherited (grandparent)
45
- // hash, not its own payload. Its payload envelope is in this batch, so use that blockHash as
46
- // the real parent EL head.
47
- parentExecHash = parentPayloadInput.getBlockHashHex();
48
- }
49
- }
50
-
51
40
  // Track the expected execution payload block hash through the segment, seeded from the FIRST
52
41
  // block's own bid
53
42
  const firstBlockMessage = blocks[0].getBlock().message;
@@ -55,6 +44,31 @@ export function assertLinearChainSegment(
55
44
  ? toRootHex(firstBlockMessage.body.signedExecutionPayloadBid.message.parentBlockHash)
56
45
  : null;
57
46
 
47
+ let parentExecHash: string | null = parentBlock?.executionPayloadBlockHash ?? null;
48
+ if (parentBlock !== null) {
49
+ const parentPayloadInput = payloadEnvelopes?.get(parentBlock.slot);
50
+ if (parentPayloadInput?.hasPayloadEnvelope()) {
51
+ // Envelopes are served by slot, the one at the parent's slot must reference the parent block. Without this
52
+ // check an envelope of a sibling block is taken as orphaned and only fails downstream in the payload import
53
+ if (parentPayloadInput.blockRootHex !== parentBlock.blockRoot) {
54
+ throw new BlockError(blocks[0].getBlock(), {
55
+ code: BlockErrorCode.ENVELOPE_BLOCK_ROOT_MISMATCH,
56
+ envelopeBlockRoot: parentPayloadInput.blockRootHex,
57
+ blockRoot: parentBlock.blockRoot,
58
+ });
59
+ }
60
+ const parentPayloadBlockHash = parentPayloadInput.getBlockHashHex();
61
+ if (currentExecHash === parentPayloadBlockHash) {
62
+ // Checkpoint-sync first batch: the anchor is stored PENDING with the inherited (grandparent)
63
+ // hash, its own payload is in this batch and is the real parent EL head
64
+ parentExecHash = parentPayloadBlockHash;
65
+ } else {
66
+ // First block builds on the parent's EMPTY variant, the parent's payload in this batch is orphaned
67
+ warnings.push({slot: parentBlock.slot, payloadEnvelopeInput: parentPayloadInput});
68
+ }
69
+ }
70
+ }
71
+
58
72
  // First block must build on the parent's EL head. PARENT_PAYLOAD_UNKNOWN (vs the in-segment
59
73
  // NON_LINEAR_PAYLOAD_ROOTS below) tells range sync this is a parent-link problem, not an in-batch one.
60
74
  if (parentExecHash !== null && currentExecHash !== null && currentExecHash !== parentExecHash) {
@@ -1,6 +1,6 @@
1
- import {ForkPostDeneb, isForkPostDeneb} from "@lodestar/params";
1
+ import {ForkPostDeneb, ForkPostFulu, isForkPostDeneb} from "@lodestar/params";
2
2
  import {SignedBeaconBlock} from "@lodestar/types";
3
- import {fromHex, toRootHex} from "@lodestar/utils";
3
+ import {toRootHex} from "@lodestar/utils";
4
4
  import {getBlobKzgCommitments} from "../../util/dataColumns.js";
5
5
  import {BeaconChain} from "../chain.js";
6
6
  import {IBlockInput, IDataColumnsInput, isBlockInputBlobs, isBlockInputColumns} from "./blockInput/index.js";
@@ -76,7 +76,6 @@ async function writeBlockAndBlobsToDb(this: BeaconChain, blockInput: IBlockInput
76
76
  */
77
77
  export async function writeDataColumnsToDb(this: BeaconChain, blockInput: IDataColumnsInput): Promise<void> {
78
78
  const {slot, blockRootHex} = blockInput;
79
- const blockRoot = fromHex(blockRootHex);
80
79
 
81
80
  if (!blockInput.hasComputedAllData()) {
82
81
  // Supernodes may only have a subset of the data columns by the time the block begins to be imported
@@ -89,25 +88,19 @@ export async function writeDataColumnsToDb(this: BeaconChain, blockInput: IDataC
89
88
 
90
89
  const {custodyColumns} = this.custodyConfig;
91
90
  const dataColumnSidecars = blockInput.getCustodyColumns();
91
+ const dataColumnSidecarType = this.config.getForkTypes<ForkPostFulu>(slot).DataColumnSidecar;
92
92
 
93
- const binaryPuts: {key: number; value: Uint8Array}[] = [];
94
- const nonbinaryPuts = [];
93
+ const binaryColumns: {index: number; data: Uint8Array}[] = [];
95
94
  for (const dataColumnSidecar of dataColumnSidecars) {
96
- // skip reserializing column if we already have it
97
95
  const serialized = this.serializedCache.get(dataColumnSidecar);
98
- if (serialized) {
99
- binaryPuts.push({key: dataColumnSidecar.index, value: serialized});
100
- } else {
101
- nonbinaryPuts.push(dataColumnSidecar);
102
- }
96
+ binaryColumns.push({
97
+ index: dataColumnSidecar.index,
98
+ data: serialized ?? dataColumnSidecarType.serialize(dataColumnSidecar),
99
+ });
103
100
  }
101
+ await this.db.dataColumns.putManyBinary({slot, blockRoot: blockRootHex}, binaryColumns);
104
102
 
105
- await Promise.all([
106
- this.db.dataColumnSidecar.putManyBinary(blockRoot, binaryPuts),
107
- this.db.dataColumnSidecar.putMany(blockRoot, nonbinaryPuts),
108
- ]);
109
-
110
- this.logger.debug("Persisted dataColumnSidecars to hot DB", {
103
+ this.logger.debug("Persisted dataColumnSidecars", {
111
104
  slot,
112
105
  root: blockRootHex,
113
106
  dataColumnSidecars: dataColumnSidecars.length,