@lodestar/beacon-node 1.40.0-dev.737da5eee3 → 1.40.0-dev.787d0f5eee

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 (30) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +2 -8
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/chain/blocks/blockInput/blockInput.d.ts +0 -28
  5. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  6. package/lib/chain/blocks/blockInput/blockInput.js +1 -36
  7. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  8. package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
  9. package/lib/chain/blocks/writeBlockInputToDb.js +0 -8
  10. package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
  11. package/lib/chain/chain.d.ts.map +1 -1
  12. package/lib/chain/chain.js +2 -1
  13. package/lib/chain/chain.js.map +1 -1
  14. package/lib/network/gossip/gossipsub.d.ts +0 -19
  15. package/lib/network/gossip/gossipsub.d.ts.map +1 -1
  16. package/lib/network/gossip/gossipsub.js +0 -71
  17. package/lib/network/gossip/gossipsub.js.map +1 -1
  18. package/lib/network/options.d.ts +0 -6
  19. package/lib/network/options.d.ts.map +1 -1
  20. package/lib/network/options.js.map +1 -1
  21. package/lib/network/processor/gossipHandlers.js +1 -1
  22. package/lib/network/processor/gossipHandlers.js.map +1 -1
  23. package/package.json +15 -15
  24. package/src/api/impl/beacon/blocks/index.ts +12 -22
  25. package/src/chain/blocks/blockInput/blockInput.ts +2 -45
  26. package/src/chain/blocks/writeBlockInputToDb.ts +0 -9
  27. package/src/chain/chain.ts +2 -1
  28. package/src/network/gossip/gossipsub.ts +1 -86
  29. package/src/network/options.ts +0 -6
  30. package/src/network/processor/gossipHandlers.ts +1 -1
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "bugs": {
12
12
  "url": "https://github.com/ChainSafe/lodestar/issues"
13
13
  },
14
- "version": "1.40.0-dev.737da5eee3",
14
+ "version": "1.40.0-dev.787d0f5eee",
15
15
  "type": "module",
16
16
  "exports": {
17
17
  ".": {
@@ -134,18 +134,18 @@
134
134
  "@libp2p/peer-id": "^5.1.0",
135
135
  "@libp2p/prometheus-metrics": "^4.3.15",
136
136
  "@libp2p/tcp": "^10.1.8",
137
- "@lodestar/api": "^1.40.0-dev.737da5eee3",
138
- "@lodestar/config": "^1.40.0-dev.737da5eee3",
139
- "@lodestar/db": "^1.40.0-dev.737da5eee3",
140
- "@lodestar/fork-choice": "^1.40.0-dev.737da5eee3",
141
- "@lodestar/light-client": "^1.40.0-dev.737da5eee3",
142
- "@lodestar/logger": "^1.40.0-dev.737da5eee3",
143
- "@lodestar/params": "^1.40.0-dev.737da5eee3",
144
- "@lodestar/reqresp": "^1.40.0-dev.737da5eee3",
145
- "@lodestar/state-transition": "^1.40.0-dev.737da5eee3",
146
- "@lodestar/types": "^1.40.0-dev.737da5eee3",
147
- "@lodestar/utils": "^1.40.0-dev.737da5eee3",
148
- "@lodestar/validator": "^1.40.0-dev.737da5eee3",
137
+ "@lodestar/api": "^1.40.0-dev.787d0f5eee",
138
+ "@lodestar/config": "^1.40.0-dev.787d0f5eee",
139
+ "@lodestar/db": "^1.40.0-dev.787d0f5eee",
140
+ "@lodestar/fork-choice": "^1.40.0-dev.787d0f5eee",
141
+ "@lodestar/light-client": "^1.40.0-dev.787d0f5eee",
142
+ "@lodestar/logger": "^1.40.0-dev.787d0f5eee",
143
+ "@lodestar/params": "^1.40.0-dev.787d0f5eee",
144
+ "@lodestar/reqresp": "^1.40.0-dev.787d0f5eee",
145
+ "@lodestar/state-transition": "^1.40.0-dev.787d0f5eee",
146
+ "@lodestar/types": "^1.40.0-dev.787d0f5eee",
147
+ "@lodestar/utils": "^1.40.0-dev.787d0f5eee",
148
+ "@lodestar/validator": "^1.40.0-dev.787d0f5eee",
149
149
  "@multiformats/multiaddr": "^12.1.3",
150
150
  "datastore-core": "^10.0.2",
151
151
  "datastore-fs": "^10.0.6",
@@ -169,7 +169,7 @@
169
169
  "@chainsafe/swap-or-not-shuffle": "^1.2.1",
170
170
  "@libp2p/interface-internal": "^2.3.18",
171
171
  "@libp2p/logger": "^5.1.21",
172
- "@lodestar/spec-test-util": "^1.40.0-dev.737da5eee3",
172
+ "@lodestar/spec-test-util": "^1.40.0-dev.787d0f5eee",
173
173
  "@types/js-yaml": "^4.0.5",
174
174
  "@types/qs": "^6.9.7",
175
175
  "@types/tmp": "^0.2.3",
@@ -188,5 +188,5 @@
188
188
  "beacon",
189
189
  "blockchain"
190
190
  ],
191
- "gitHead": "253ac39a389f4da3c98760a1f80876cfaef9ac5b"
191
+ "gitHead": "652021e4737c3fcce4b03f730fef446fb1883061"
192
192
  }
@@ -133,31 +133,21 @@ export function getBeaconBlockApi({
133
133
 
134
134
  if (isBlockInputColumns(blockForImport)) {
135
135
  for (const dataColumnSidecar of dataColumnSidecars) {
136
- blockForImport.addColumn(
137
- {
138
- blockRootHex: blockRoot,
139
- columnSidecar: dataColumnSidecar,
140
- source: BlockInputSource.api,
141
- seenTimestampSec,
142
- },
143
- // In multi-BN setups (DVT, fallback), the same block may be published to multiple nodes.
144
- // Data columns may arrive via gossip from another node before the API publish completes,
145
- // so we allow duplicates here instead of throwing an error.
146
- {throwOnDuplicateAdd: false}
147
- );
136
+ blockForImport.addColumn({
137
+ blockRootHex: blockRoot,
138
+ columnSidecar: dataColumnSidecar,
139
+ source: BlockInputSource.api,
140
+ seenTimestampSec,
141
+ });
148
142
  }
149
143
  } else if (isBlockInputBlobs(blockForImport)) {
150
144
  for (const blobSidecar of blobSidecars) {
151
- blockForImport.addBlob(
152
- {
153
- blockRootHex: blockRoot,
154
- blobSidecar,
155
- source: BlockInputSource.api,
156
- seenTimestampSec,
157
- },
158
- // Same as above for columns
159
- {throwOnDuplicateAdd: false}
160
- );
145
+ blockForImport.addBlob({
146
+ blockRootHex: blockRoot,
147
+ blobSidecar,
148
+ source: BlockInputSource.api,
149
+ seenTimestampSec,
150
+ });
161
151
  }
162
152
  }
163
153
 
@@ -1,4 +1,4 @@
1
- import {ForkName, ForkPostFulu, ForkPreDeneb, ForkPreGloas, NUMBER_OF_COLUMNS} from "@lodestar/params";
1
+ import {ForkName, ForkPostFulu, ForkPreDeneb, ForkPreGloas} from "@lodestar/params";
2
2
  import {BeaconBlockBody, BlobIndex, ColumnIndex, SignedBeaconBlock, Slot, deneb, fulu} from "@lodestar/types";
3
3
  import {fromHex, prettyBytes, toRootHex, withTimeout} from "@lodestar/utils";
4
4
  import {VersionedHashes} from "../../../execution/index.js";
@@ -561,7 +561,6 @@ type BlockInputColumnsState =
561
561
  | {
562
562
  hasBlock: true;
563
563
  hasAllData: true;
564
- hasComputedAllData: boolean;
565
564
  versionedHashes: VersionedHashes;
566
565
  block: SignedBeaconBlock<ForkColumnsDA>;
567
566
  source: SourceMeta;
@@ -570,7 +569,6 @@ type BlockInputColumnsState =
570
569
  | {
571
570
  hasBlock: true;
572
571
  hasAllData: false;
573
- hasComputedAllData: false;
574
572
  versionedHashes: VersionedHashes;
575
573
  block: SignedBeaconBlock<ForkColumnsDA>;
576
574
  source: SourceMeta;
@@ -578,13 +576,11 @@ type BlockInputColumnsState =
578
576
  | {
579
577
  hasBlock: false;
580
578
  hasAllData: true;
581
- hasComputedAllData: boolean;
582
579
  versionedHashes: VersionedHashes;
583
580
  }
584
581
  | {
585
582
  hasBlock: false;
586
583
  hasAllData: false;
587
- hasComputedAllData: false;
588
584
  versionedHashes: VersionedHashes;
589
585
  };
590
586
  /**
@@ -602,12 +598,6 @@ export class BlockInputColumns extends AbstractBlockInput<ForkColumnsDA, fulu.Da
602
598
  private columnsCache = new Map<ColumnIndex, ColumnWithSource>();
603
599
  private readonly sampledColumns: ColumnIndex[];
604
600
  private readonly custodyColumns: ColumnIndex[];
605
- /**
606
- * This promise resolves when all sampled columns are available
607
- *
608
- * This is different from `dataPromise` which resolves when all data is available or could become available (e.g. through reconstruction)
609
- */
610
- protected computedDataPromise = createPromise<fulu.DataColumnSidecars>();
611
601
 
612
602
  private constructor(
613
603
  init: BlockInputInit,
@@ -636,7 +626,6 @@ export class BlockInputColumns extends AbstractBlockInput<ForkColumnsDA, fulu.Da
636
626
  const state = {
637
627
  hasBlock: true,
638
628
  hasAllData,
639
- hasComputedAllData: hasAllData,
640
629
  versionedHashes: props.block.message.body.blobKzgCommitments.map(kzgCommitmentToVersionedHash),
641
630
  block: props.block,
642
631
  source: {
@@ -660,7 +649,6 @@ export class BlockInputColumns extends AbstractBlockInput<ForkColumnsDA, fulu.Da
660
649
  blockInput.blockPromise.resolve(props.block);
661
650
  if (hasAllData) {
662
651
  blockInput.dataPromise.resolve([]);
663
- blockInput.computedDataPromise.resolve([]);
664
652
  }
665
653
  return blockInput;
666
654
  }
@@ -673,7 +661,6 @@ export class BlockInputColumns extends AbstractBlockInput<ForkColumnsDA, fulu.Da
673
661
  const state: BlockInputColumnsState = {
674
662
  hasBlock: false,
675
663
  hasAllData,
676
- hasComputedAllData: hasAllData as false,
677
664
  versionedHashes: props.columnSidecar.kzgCommitments.map(kzgCommitmentToVersionedHash),
678
665
  };
679
666
  const init: BlockInputInit = {
@@ -687,7 +674,6 @@ export class BlockInputColumns extends AbstractBlockInput<ForkColumnsDA, fulu.Da
687
674
  const blockInput = new BlockInputColumns(init, state, props.sampledColumns, props.custodyColumns);
688
675
  if (hasAllData) {
689
676
  blockInput.dataPromise.resolve([]);
690
- blockInput.computedDataPromise.resolve([]);
691
677
  }
692
678
  return blockInput;
693
679
  }
@@ -736,14 +722,11 @@ export class BlockInputColumns extends AbstractBlockInput<ForkColumnsDA, fulu.Da
736
722
  const hasAllData =
737
723
  (props.block.message.body as BeaconBlockBody<ForkPostFulu & ForkPreGloas>).blobKzgCommitments.length === 0 ||
738
724
  this.state.hasAllData;
739
- const hasComputedAllData =
740
- props.block.message.body.blobKzgCommitments.length === 0 || this.state.hasComputedAllData;
741
725
 
742
726
  this.state = {
743
727
  ...this.state,
744
728
  hasBlock: true,
745
729
  hasAllData,
746
- hasComputedAllData,
747
730
  block: props.block,
748
731
  source: {
749
732
  source: props.source,
@@ -791,32 +774,17 @@ export class BlockInputColumns extends AbstractBlockInput<ForkColumnsDA, fulu.Da
791
774
  this.columnsCache.set(columnSidecar.index, {columnSidecar, source, seenTimestampSec, peerIdStr});
792
775
 
793
776
  const sampledColumns = this.getSampledColumns();
794
- const hasAllData =
795
- // already hasAllData
796
- this.state.hasAllData ||
797
- // has all sampled columns
798
- sampledColumns.length === this.sampledColumns.length ||
799
- // has enough columns to reconstruct the rest
800
- this.columnsCache.size >= NUMBER_OF_COLUMNS / 2;
801
-
802
- const hasComputedAllData =
803
- // has all sampled columns
804
- sampledColumns.length === this.sampledColumns.length;
777
+ const hasAllData = this.state.hasAllData || sampledColumns.length === this.sampledColumns.length;
805
778
 
806
779
  this.state = {
807
780
  ...this.state,
808
781
  hasAllData: hasAllData || this.state.hasAllData,
809
- hasComputedAllData: hasComputedAllData || this.state.hasComputedAllData,
810
782
  timeCompleteSec: hasAllData ? seenTimestampSec : undefined,
811
783
  } as BlockInputColumnsState;
812
784
 
813
785
  if (hasAllData && sampledColumns !== null) {
814
786
  this.dataPromise.resolve(sampledColumns);
815
787
  }
816
-
817
- if (hasComputedAllData && sampledColumns !== null) {
818
- this.computedDataPromise.resolve(sampledColumns);
819
- }
820
788
  }
821
789
 
822
790
  hasColumn(columnIndex: number): boolean {
@@ -891,15 +859,4 @@ export class BlockInputColumns extends AbstractBlockInput<ForkColumnsDA, fulu.Da
891
859
  versionedHashes: this.state.versionedHashes,
892
860
  };
893
861
  }
894
-
895
- hasComputedAllData(): boolean {
896
- return this.state.hasComputedAllData;
897
- }
898
-
899
- waitForComputedAllData(timeout: number, signal?: AbortSignal): Promise<fulu.DataColumnSidecars> {
900
- if (!this.state.hasComputedAllData) {
901
- return withTimeout(() => this.computedDataPromise.promise, timeout, signal);
902
- }
903
- return Promise.resolve(this.getSampledColumns());
904
- }
905
862
  }
@@ -44,15 +44,6 @@ export async function writeBlockInputToDb(this: BeaconChain, blocksInputs: IBloc
44
44
 
45
45
  // NOTE: Old data is pruned on archive
46
46
  if (isBlockInputColumns(blockInput)) {
47
- if (!blockInput.hasComputedAllData()) {
48
- // Supernodes may only have a subset of the data columns by the time the block begins to be imported
49
- // because full data availability can be assumed after NUMBER_OF_COLUMNS / 2 columns are available.
50
- // Here, however, all data columns must be fully available/reconstructed before persisting to the DB.
51
- await blockInput.waitForComputedAllData(BLOB_AVAILABILITY_TIMEOUT).catch(() => {
52
- this.logger.debug("Failed to wait for computed all data", {slot, blockRoot: blockRootHex});
53
- });
54
- }
55
-
56
47
  const {custodyColumns} = this.custodyConfig;
57
48
  const blobsLen = (block.message as fulu.BeaconBlock).body.blobKzgCommitments.length;
58
49
  let dataColumnsLen: number;
@@ -340,8 +340,9 @@ export class BeaconChain implements IBeaconChain {
340
340
  const blockStateCache = new FIFOBlockStateCache(this.opts, {metrics});
341
341
  this.bufferPool = new BufferPool(anchorState.type.tree_serializedSize(anchorState.node), metrics);
342
342
 
343
+ let checkpointStateCache: CheckpointStateCache;
343
344
  this.cpStateDatastore = fileDataStore ? new FileCPStateDatastore(dataDir) : new DbCPStateDatastore(this.db);
344
- const checkpointStateCache: CheckpointStateCache = new PersistentCheckpointStateCache(
345
+ checkpointStateCache = new PersistentCheckpointStateCache(
345
346
  {
346
347
  config,
347
348
  metrics,
@@ -1,10 +1,7 @@
1
- import {peerIdFromString} from "@libp2p/peer-id";
2
- import {multiaddr} from "@multiformats/multiaddr";
3
- import {ENR} from "@chainsafe/enr";
4
1
  import {GossipSub, GossipsubEvents} from "@chainsafe/libp2p-gossipsub";
5
2
  import {MetricsRegister, TopicLabel, TopicStrToLabel} from "@chainsafe/libp2p-gossipsub/metrics";
6
3
  import {PeerScoreParams} from "@chainsafe/libp2p-gossipsub/score";
7
- import {AddrInfo, SignaturePolicy, TopicStr} from "@chainsafe/libp2p-gossipsub/types";
4
+ import {SignaturePolicy, TopicStr} from "@chainsafe/libp2p-gossipsub/types";
8
5
  import {BeaconConfig, ForkBoundary} from "@lodestar/config";
9
6
  import {ATTESTATION_SUBNET_COUNT, SLOTS_PER_EPOCH, SYNC_COMMITTEE_SUBNET_COUNT} from "@lodestar/params";
10
7
  import {SubnetID} from "@lodestar/types";
@@ -58,12 +55,6 @@ export type Eth2GossipsubOpts = {
58
55
  disableFloodPublish?: boolean;
59
56
  skipParamsLog?: boolean;
60
57
  disableLightClientServer?: boolean;
61
- /**
62
- * Direct peers for GossipSub - these peers maintain permanent mesh connections without GRAFT/PRUNE.
63
- * Supports multiaddr strings with peer ID (e.g., "/ip4/192.168.1.1/tcp/9000/p2p/16Uiu2HAmKLhW7...")
64
- * or ENR strings (e.g., "enr:-IS4QHCYrYZbAKWCBRlAy5zzaDZXJBGkcnh4MHcBFZntXNFrdvJjX04jRzjzCBOo...")
65
- */
66
- directPeers?: string[];
67
58
  };
68
59
 
69
60
  export type ForkBoundaryLabel = string;
@@ -106,9 +97,6 @@ export class Eth2Gossipsub extends GossipSub {
106
97
  );
107
98
  }
108
99
 
109
- // Parse direct peers from multiaddr strings to AddrInfo objects
110
- const directPeers = parseDirectPeers(opts.directPeers ?? [], logger);
111
-
112
100
  // Gossipsub parameters defined here:
113
101
  // https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/phase0/p2p-interface.md#the-gossip-domain-gossipsub
114
102
  super(modules.libp2p.services.components, {
@@ -118,7 +106,6 @@ export class Eth2Gossipsub extends GossipSub {
118
106
  Dlo: gossipsubDLow ?? GOSSIP_D_LOW,
119
107
  Dhi: gossipsubDHigh ?? GOSSIP_D_HIGH,
120
108
  Dlazy: 6,
121
- directPeers,
122
109
  heartbeatInterval: GOSSIPSUB_HEARTBEAT_INTERVAL,
123
110
  fanoutTTL: 60 * 1000,
124
111
  mcacheLength: 6,
@@ -394,75 +381,3 @@ function getForkBoundaryLabel(boundary: ForkBoundary): ForkBoundaryLabel {
394
381
 
395
382
  return label;
396
383
  }
397
-
398
- /**
399
- * Parse direct peer strings into AddrInfo objects for GossipSub.
400
- * Direct peers maintain permanent mesh connections without GRAFT/PRUNE negotiation.
401
- *
402
- * Supported formats:
403
- * - Multiaddr with peer ID: `/ip4/192.168.1.1/tcp/9000/p2p/16Uiu2HAmKLhW7...`
404
- * - ENR: `enr:-IS4QHCYrYZbAKWCBRlAy5zzaDZXJBGkcnh4MHcBFZntXNFrdvJjX04jRzjzCBOo...`
405
- *
406
- * For multiaddrs, the string must contain a /p2p/ component with the peer ID.
407
- * For ENRs, the TCP multiaddr and peer ID are extracted from the encoded record.
408
- */
409
- export function parseDirectPeers(directPeerStrs: string[], logger: Logger): AddrInfo[] {
410
- const directPeers: AddrInfo[] = [];
411
-
412
- for (const peerStr of directPeerStrs) {
413
- // Check if this is an ENR (starts with "enr:")
414
- if (peerStr.startsWith("enr:")) {
415
- try {
416
- const enr = ENR.decodeTxt(peerStr);
417
- const peerId = enr.peerId;
418
-
419
- // Get TCP multiaddr from ENR
420
- const multiaddrTCP = enr.getLocationMultiaddr("tcp");
421
- if (!multiaddrTCP) {
422
- logger.warn("ENR does not contain TCP multiaddr", {enr: peerStr});
423
- continue;
424
- }
425
-
426
- directPeers.push({
427
- id: peerId,
428
- addrs: [multiaddrTCP],
429
- });
430
-
431
- logger.info("Added direct peer from ENR", {peerId: peerId.toString(), addr: multiaddrTCP.toString()});
432
- } catch (e) {
433
- logger.warn("Failed to parse direct peer ENR", {enr: peerStr}, e as Error);
434
- }
435
- } else {
436
- // Parse as multiaddr
437
- try {
438
- const ma = multiaddr(peerStr);
439
-
440
- const peerIdStr = ma.getPeerId();
441
- if (!peerIdStr) {
442
- logger.warn("Direct peer multiaddr must contain /p2p/ component with peer ID", {multiaddr: peerStr});
443
- continue;
444
- }
445
-
446
- try {
447
- const peerId = peerIdFromString(peerIdStr);
448
-
449
- // Get the address without the /p2p/ component
450
- const addr = ma.decapsulate("/p2p/" + peerIdStr);
451
-
452
- directPeers.push({
453
- id: peerId,
454
- addrs: [addr],
455
- });
456
-
457
- logger.info("Added direct peer", {peerId: peerIdStr, addr: addr.toString()});
458
- } catch (e) {
459
- logger.warn("Invalid peer ID in direct peer multiaddr", {multiaddr: peerStr, peerId: peerIdStr}, e as Error);
460
- }
461
- } catch (e) {
462
- logger.warn("Failed to parse direct peer multiaddr", {multiaddr: peerStr}, e as Error);
463
- }
464
- }
465
- }
466
-
467
- return directPeers;
468
- }
@@ -15,12 +15,6 @@ export interface NetworkOptions
15
15
  Omit<Eth2GossipsubOpts, "disableLightClientServer"> {
16
16
  localMultiaddrs: string[];
17
17
  bootMultiaddrs?: string[];
18
- /**
19
- * Direct peers for GossipSub - these peers maintain permanent mesh connections without GRAFT/PRUNE.
20
- * Format: multiaddr strings with peer ID, e.g., "/ip4/192.168.1.1/tcp/9000/p2p/16Uiu2HAmKLhW7..."
21
- * Both peers must configure each other as direct peers for the feature to work properly.
22
- */
23
- directPeers?: string[];
24
18
  subscribeAllSubnets?: boolean;
25
19
  mdns?: boolean;
26
20
  connectToDiscv5Bootnodes?: boolean;
@@ -579,7 +579,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
579
579
  break;
580
580
  }
581
581
 
582
- if (!blockInput.hasComputedAllData()) {
582
+ if (!blockInput.hasAllData()) {
583
583
  // immediately attempt fetch of data columns from execution engine
584
584
  chain.getBlobsTracker.triggerGetBlobs(blockInput);
585
585
  // if we've received at least half of the columns, trigger reconstruction of the rest