@lodestar/beacon-node 1.44.0-dev.b66425f010 → 1.44.0-dev.be2850b7bb

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 (92) hide show
  1. package/lib/api/impl/config/constants.d.ts +1 -0
  2. package/lib/api/impl/config/constants.d.ts.map +1 -1
  3. package/lib/api/impl/config/constants.js +2 -1
  4. package/lib/api/impl/config/constants.js.map +1 -1
  5. package/lib/api/impl/debug/index.d.ts.map +1 -1
  6. package/lib/api/impl/debug/index.js +69 -12
  7. package/lib/api/impl/debug/index.js.map +1 -1
  8. package/lib/api/impl/validator/index.d.ts.map +1 -1
  9. package/lib/api/impl/validator/index.js +21 -9
  10. package/lib/api/impl/validator/index.js.map +1 -1
  11. package/lib/chain/archiveStore/archiveStore.d.ts +0 -1
  12. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  13. package/lib/chain/archiveStore/archiveStore.js +0 -4
  14. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  15. package/lib/chain/errors/payloadAttestation.d.ts +6 -0
  16. package/lib/chain/errors/payloadAttestation.d.ts.map +1 -1
  17. package/lib/chain/errors/payloadAttestation.js +1 -0
  18. package/lib/chain/errors/payloadAttestation.js.map +1 -1
  19. package/lib/chain/prepareNextSlot.js +1 -1
  20. package/lib/chain/prepareNextSlot.js.map +1 -1
  21. package/lib/chain/produceBlock/produceBlockBody.js +3 -3
  22. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  23. package/lib/chain/regen/interface.d.ts +0 -1
  24. package/lib/chain/regen/interface.d.ts.map +1 -1
  25. package/lib/chain/regen/queued.d.ts +0 -1
  26. package/lib/chain/regen/queued.d.ts.map +1 -1
  27. package/lib/chain/regen/queued.js +0 -4
  28. package/lib/chain/regen/queued.js.map +1 -1
  29. package/lib/chain/stateCache/fifoBlockStateCache.d.ts +0 -5
  30. package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
  31. package/lib/chain/stateCache/fifoBlockStateCache.js +0 -5
  32. package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
  33. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +1 -4
  34. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  35. package/lib/chain/stateCache/persistentCheckpointsCache.js +5 -2
  36. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  37. package/lib/chain/stateCache/types.d.ts +0 -2
  38. package/lib/chain/stateCache/types.d.ts.map +1 -1
  39. package/lib/chain/stateCache/types.js.map +1 -1
  40. package/lib/chain/validation/executionPayloadBid.js +22 -5
  41. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  42. package/lib/chain/validation/payloadAttestationMessage.js +10 -0
  43. package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
  44. package/lib/network/gossip/topic.d.ts +19 -766
  45. package/lib/network/gossip/topic.d.ts.map +1 -1
  46. package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
  47. package/lib/network/reqresp/handlers/beaconBlocksByRange.js +9 -5
  48. package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
  49. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
  50. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +13 -3
  51. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
  52. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +1 -1
  53. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js.map +1 -1
  54. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts +2 -1
  55. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -1
  56. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +16 -6
  57. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
  58. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.d.ts +2 -1
  59. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.d.ts.map +1 -1
  60. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js +15 -1
  61. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js.map +1 -1
  62. package/lib/network/reqresp/handlers/index.js +4 -4
  63. package/lib/network/reqresp/handlers/index.js.map +1 -1
  64. package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts.map +1 -1
  65. package/lib/network/reqresp/utils/dataColumnResponseValidation.js +22 -3
  66. package/lib/network/reqresp/utils/dataColumnResponseValidation.js.map +1 -1
  67. package/lib/util/dataColumns.d.ts.map +1 -1
  68. package/lib/util/dataColumns.js +16 -11
  69. package/lib/util/dataColumns.js.map +1 -1
  70. package/package.json +14 -16
  71. package/src/api/impl/config/constants.ts +2 -0
  72. package/src/api/impl/debug/index.ts +73 -12
  73. package/src/api/impl/validator/index.ts +23 -14
  74. package/src/chain/archiveStore/archiveStore.ts +0 -5
  75. package/src/chain/errors/payloadAttestation.ts +2 -0
  76. package/src/chain/prepareNextSlot.ts +1 -1
  77. package/src/chain/produceBlock/produceBlockBody.ts +3 -3
  78. package/src/chain/regen/interface.ts +0 -1
  79. package/src/chain/regen/queued.ts +0 -5
  80. package/src/chain/stateCache/fifoBlockStateCache.ts +0 -6
  81. package/src/chain/stateCache/persistentCheckpointsCache.ts +6 -2
  82. package/src/chain/stateCache/types.ts +0 -2
  83. package/src/chain/validation/executionPayloadBid.ts +23 -5
  84. package/src/chain/validation/payloadAttestationMessage.ts +11 -0
  85. package/src/network/reqresp/handlers/beaconBlocksByRange.ts +12 -5
  86. package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +17 -3
  87. package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +1 -1
  88. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +22 -6
  89. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRoot.ts +20 -1
  90. package/src/network/reqresp/handlers/index.ts +4 -4
  91. package/src/network/reqresp/utils/dataColumnResponseValidation.ts +21 -3
  92. package/src/util/dataColumns.ts +17 -12
@@ -70,13 +70,13 @@ export function getReqRespHandlers({db, chain}: {db: IBeaconDb; chain: IBeaconCh
70
70
  return onDataColumnSidecarsByRoot(body, chain, db, peerId, peerClient);
71
71
  },
72
72
 
73
- [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: (req) => {
73
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: (req, peerId, peerClient) => {
74
74
  const body = ExecutionPayloadEnvelopesByRootRequestType(chain.config).deserialize(req.data);
75
- return onExecutionPayloadEnvelopesByRoot(body, chain, db);
75
+ return onExecutionPayloadEnvelopesByRoot(body, chain, db, peerId, peerClient);
76
76
  },
77
- [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: (req) => {
77
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: (req, peerId, peerClient) => {
78
78
  const body = ssz.gloas.ExecutionPayloadEnvelopesByRangeRequest.deserialize(req.data);
79
- return onExecutionPayloadEnvelopesByRange(body, chain, db);
79
+ return onExecutionPayloadEnvelopesByRange(body, chain, db, peerId, peerClient);
80
80
  },
81
81
 
82
82
  [ReqRespMethod.LightClientBootstrap]: (req) => {
@@ -1,4 +1,5 @@
1
1
  import {LogData} from "@lodestar/logger";
2
+ import {ForkSeq} from "@lodestar/params";
2
3
  import {RespStatus, ResponseError} from "@lodestar/reqresp";
3
4
  import {ColumnIndex, Slot} from "@lodestar/types";
4
5
  import {prettyBytes, prettyPrintIndices, toRootHex} from "@lodestar/utils";
@@ -38,6 +39,13 @@ export async function handleColumnSidecarUnavailability({
38
39
 
39
40
  chain.logger.debug("dataColumnSidecar requested unavailable", logData);
40
41
 
42
+ // Post-gloas, columns exist only for FULL blocks; a finalized block is FULL if its envelope was
43
+ // archived. Bid blobsCount is unreliable here since an EMPTY block's bid may still commit to blobs
44
+ if (blockRoot === undefined && chain.config.getForkSeq(slot) >= ForkSeq.gloas) {
45
+ const envelopeBytes = await db.executionPayloadEnvelopeArchive.getBinary(slot);
46
+ if (!envelopeBytes) return;
47
+ }
48
+
41
49
  const blockBytes = blockRoot ? await db.block.getBinary(blockRoot) : await db.blockArchive.getBinary(slot);
42
50
  if (!blockBytes) {
43
51
  chain.logger.verbose(
@@ -71,9 +79,19 @@ export function validateRequestedDataColumns(chain: IBeaconChain, requestedColum
71
79
  throw new ResponseError(RespStatus.INVALID_REQUEST, "dataColumnSidecar requested without column indices");
72
80
  }
73
81
 
74
- const custodyColumns = chain.custodyConfig.custodyColumns;
75
- const availableColumns = requestedColumns.filter((c) => custodyColumns.includes(c));
76
- const missingColumns = requestedColumns.filter((c) => !custodyColumns.includes(c));
82
+ const {custodyColumns, custodyColumnsIndex} = chain.custodyConfig;
83
+ const availableColumns: ColumnIndex[] = [];
84
+ const missingColumns: ColumnIndex[] = [];
85
+ for (const c of requestedColumns) {
86
+ // `c` is peer-controlled and SSZ-deserialized as `uint64`, so it may exceed
87
+ // `NUMBER_OF_COLUMNS - 1`; `Uint8Array` returns `undefined` for OOB reads,
88
+ // and `undefined !== 0` would silently classify OOB indices as custodied.
89
+ if ((custodyColumnsIndex[c] ?? 0) !== 0) {
90
+ availableColumns.push(c);
91
+ } else {
92
+ missingColumns.push(c);
93
+ }
94
+ }
77
95
 
78
96
  if (missingColumns.length > 0) {
79
97
  chain.logger.verbose("Requested dataColumnSidecar for non-custody columns", {
@@ -470,15 +470,17 @@ export async function recoverDataColumnSidecars(
470
470
  return DataColumnReconstructionCode.SuccessLate;
471
471
  }
472
472
 
473
- // Once the node obtains a column through reconstruction,
474
- // the node MUST expose the new column as if it had received it over the network.
475
- // If the node is subscribed to the subnet corresponding to the column,
476
- // it MUST send the reconstructed DataColumnSidecar to its topic mesh neighbors.
477
- // If instead the node is not subscribed to the corresponding subnet,
478
- // it SHOULD still expose the availability of the DataColumnSidecar as part of the gossip emission process.
479
- // After exposing the reconstructed DataColumnSidecar to the network,
480
- // the node MAY delete the DataColumnSidecar if it is not part of the node's custody requirement.
481
- const sidecarsToPublish = [];
473
+ // Per consensus-specs PR #4657, only publish reconstructed columns the node is
474
+ // subscribed to (custody + sampling). Eagerly cross-seeding non-subscribed
475
+ // columns floods the network with duplicates because the sender has no
476
+ // visibility into which peers already saw the message via the topic mesh.
477
+ // This matches the getBlobsV2 path in `getDataColumnSidecarsFromExecution` and
478
+ // aligns with Lighthouse/Prysm. Capture missing sampled indices before adding
479
+ // any reconstructed columns so they are not filtered out by the subsequent
480
+ // `addColumn` calls.
481
+ const missingSampledColumns = new Set(input.getMissingSampledColumnMeta().missing);
482
+ const sidecarsReconstructed: DataColumnSidecar[] = [];
483
+ const sidecarsToPublish: DataColumnSidecar[] = [];
482
484
  for (const columnSidecar of fullSidecars) {
483
485
  if (!input.hasColumn(columnSidecar.index)) {
484
486
  if (input instanceof PayloadEnvelopeInput) {
@@ -501,11 +503,14 @@ export async function recoverDataColumnSidecars(
501
503
  source: BlockInputSource.recovery,
502
504
  });
503
505
  }
504
- sidecarsToPublish.push(columnSidecar);
506
+ sidecarsReconstructed.push(columnSidecar);
507
+ if (missingSampledColumns.has(columnSidecar.index)) {
508
+ sidecarsToPublish.push(columnSidecar);
509
+ }
505
510
  }
506
511
  }
507
- metrics?.peerDas.reconstructedColumns.inc(sidecarsToPublish.length);
508
- metrics?.dataColumns.bySource.inc({source: BlockInputSource.recovery}, sidecarsToPublish.length);
512
+ metrics?.peerDas.reconstructedColumns.inc(sidecarsReconstructed.length);
513
+ metrics?.dataColumns.bySource.inc({source: BlockInputSource.recovery}, sidecarsReconstructed.length);
509
514
  emitter.emit(ChainEvent.publishDataColumns, sidecarsToPublish);
510
515
  // TODO: Can we record dataColumns.sentPeersPerSubnet metric somehow
511
516
  return DataColumnReconstructionCode.SuccessResolved;