@lodestar/beacon-node 1.45.0-dev.7acc183c2b → 1.45.0-dev.88c017b12c

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 (67) hide show
  1. package/lib/api/rest/base.d.ts.map +1 -1
  2. package/lib/api/rest/base.js +6 -3
  3. package/lib/api/rest/base.js.map +1 -1
  4. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  5. package/lib/chain/blocks/importBlock.js +2 -17
  6. package/lib/chain/blocks/importBlock.js.map +1 -1
  7. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +1 -1
  8. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  9. package/lib/chain/chain.d.ts.map +1 -1
  10. package/lib/chain/chain.js +23 -2
  11. package/lib/chain/chain.js.map +1 -1
  12. package/lib/chain/errors/blockError.d.ts +19 -1
  13. package/lib/chain/errors/blockError.d.ts.map +1 -1
  14. package/lib/chain/errors/blockError.js +6 -0
  15. package/lib/chain/errors/blockError.js.map +1 -1
  16. package/lib/chain/opPools/proposerPreferencesPool.d.ts +1 -1
  17. package/lib/chain/opPools/proposerPreferencesPool.d.ts.map +1 -1
  18. package/lib/chain/opPools/proposerPreferencesPool.js +1 -1
  19. package/lib/chain/opPools/proposerPreferencesPool.js.map +1 -1
  20. package/lib/chain/validation/aggregateAndProof.js +10 -6
  21. package/lib/chain/validation/aggregateAndProof.js.map +1 -1
  22. package/lib/chain/validation/attestation.d.ts.map +1 -1
  23. package/lib/chain/validation/attestation.js +10 -6
  24. package/lib/chain/validation/attestation.js.map +1 -1
  25. package/lib/chain/validation/block.d.ts.map +1 -1
  26. package/lib/chain/validation/block.js +1 -3
  27. package/lib/chain/validation/block.js.map +1 -1
  28. package/lib/chain/validation/executionPayloadBid.js +2 -2
  29. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  30. package/lib/chain/validation/executionPayloadEnvelope.js +1 -2
  31. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  32. package/lib/network/gossip/topic.d.ts.map +1 -1
  33. package/lib/network/gossip/topic.js +2 -2
  34. package/lib/network/gossip/topic.js.map +1 -1
  35. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  36. package/lib/network/processor/gossipHandlers.js +6 -1
  37. package/lib/network/processor/gossipHandlers.js.map +1 -1
  38. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -1
  39. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +4 -2
  40. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
  41. package/lib/network/reqresp/handlers/index.d.ts.map +1 -1
  42. package/lib/network/reqresp/handlers/index.js +20 -11
  43. package/lib/network/reqresp/handlers/index.js.map +1 -1
  44. package/lib/sync/sync.d.ts.map +1 -1
  45. package/lib/sync/sync.js +7 -0
  46. package/lib/sync/sync.js.map +1 -1
  47. package/lib/sync/unknownBlock.d.ts.map +1 -1
  48. package/lib/sync/unknownBlock.js +6 -1
  49. package/lib/sync/unknownBlock.js.map +1 -1
  50. package/package.json +18 -16
  51. package/src/api/rest/base.ts +8 -3
  52. package/src/chain/blocks/importBlock.ts +0 -17
  53. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +1 -1
  54. package/src/chain/chain.ts +31 -2
  55. package/src/chain/errors/blockError.ts +21 -1
  56. package/src/chain/opPools/proposerPreferencesPool.ts +1 -1
  57. package/src/chain/validation/aggregateAndProof.ts +12 -6
  58. package/src/chain/validation/attestation.ts +12 -6
  59. package/src/chain/validation/block.ts +0 -3
  60. package/src/chain/validation/executionPayloadBid.ts +2 -2
  61. package/src/chain/validation/executionPayloadEnvelope.ts +0 -2
  62. package/src/network/gossip/topic.ts +1 -2
  63. package/src/network/processor/gossipHandlers.ts +6 -1
  64. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +4 -2
  65. package/src/network/reqresp/handlers/index.ts +21 -12
  66. package/src/sync/sync.ts +10 -0
  67. package/src/sync/unknownBlock.ts +7 -1
@@ -7,7 +7,6 @@ import {
7
7
  MAX_ATTESTER_SLASHING_SIZE,
8
8
  MAX_DATA_COLUMN_SIDECAR_SIZE,
9
9
  MAX_SIGNED_AGGREGATE_AND_PROOF_SIZE,
10
- MAX_SIGNED_BEACON_BLOCK_SIZE,
11
10
  MAX_SIGNED_EXECUTION_PAYLOAD_BID_SIZE,
12
11
  SYNC_COMMITTEE_SUBNET_COUNT,
13
12
  isForkPostAltair,
@@ -145,7 +144,7 @@ export function getGossipSSZMaxSize(topic: GossipTopic, maxPayloadSize: number,
145
144
  // Gloas progressive containers have broad theoretical SSZ max sizes; use the preset p2p bounds instead.
146
145
  switch (topic.type) {
147
146
  case GossipType.beacon_block:
148
- return isForkPostGloas(fork) ? MAX_SIGNED_BEACON_BLOCK_SIZE : maxPayloadSize;
147
+ return maxPayloadSize;
149
148
  case GossipType.beacon_aggregate_and_proof:
150
149
  return isForkPostGloas(fork) ? MAX_SIGNED_AGGREGATE_AND_PROOF_SIZE : (sszType ?? getGossipSSZType(topic)).maxSize;
151
150
  case GossipType.attester_slashing:
@@ -667,9 +667,14 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
667
667
  case BlockErrorCode.PARENT_BLOCK_UNKNOWN:
668
668
  case BlockErrorCode.PRESTATE_MISSING:
669
669
  case BlockErrorCode.EXECUTION_ENGINE_ERROR:
670
- // Errors might indicate an issue with our node or the connected EL client
670
+ // Errors might indicate an issue with our node or the connected EL client.
671
671
  logLevel = LogLevel.error;
672
672
  break;
673
+ case BlockErrorCode.EXECUTION_ENGINE_INVALID:
674
+ // the peer served a bad block
675
+ core.reportPeer(peerIdStr, PeerAction.LowToleranceError, "ExecutionEngineInvalid");
676
+ logLevel = LogLevel.warn;
677
+ break;
673
678
  default:
674
679
  // TODO: Should it use PeerId or string?
675
680
  core.reportPeer(peerIdStr, PeerAction.LowToleranceError, "BadGossipBlock");
@@ -107,8 +107,10 @@ export function validateExecutionPayloadEnvelopesByRangeRequest(
107
107
  // The gloas req/resp spec uses MIN_EPOCHS_FOR_BLOCK_REQUESTS to define the minimum range peers MUST serve.
108
108
  // Archival nodes may still serve older retained payloads to allow genesis sync.
109
109
 
110
- if (count > config.MAX_REQUEST_BLOCKS_DENEB) {
111
- count = config.MAX_REQUEST_BLOCKS_DENEB;
110
+ // Spec: EnvelopesByRange response is bounded by MAX_REQUEST_PAYLOADS (consensus-specs #5383),
111
+ // distinct from the MAX_REQUEST_BLOCKS_DENEB cap used for block-by-range.
112
+ if (count > config.MAX_REQUEST_PAYLOADS) {
113
+ count = config.MAX_REQUEST_PAYLOADS;
112
114
  }
113
115
 
114
116
  return {startSlot, count};
@@ -1,4 +1,5 @@
1
- import {ProtocolHandler} from "@lodestar/reqresp";
1
+ import type {Type} from "@chainsafe/ssz";
2
+ import {ProtocolHandler, RespStatus, ResponseError} from "@lodestar/reqresp";
2
3
  import {ssz} from "@lodestar/types";
3
4
  import {IBeaconChain} from "../../../chain/index.js";
4
5
  import {IBeaconDb} from "../../../db/index.js";
@@ -29,6 +30,14 @@ function notImplemented(method: ReqRespMethod): ProtocolHandler {
29
30
  };
30
31
  }
31
32
 
33
+ function deserializeRequestBody<T>(type: Type<T>, data: Uint8Array): T {
34
+ try {
35
+ return type.deserialize(data);
36
+ } catch (e) {
37
+ throw new ResponseError(RespStatus.INVALID_REQUEST, e instanceof Error ? e.message : String(e));
38
+ }
39
+ }
40
+
32
41
  /**
33
42
  * The ReqRespHandler module handles app-level requests / responses from other peers,
34
43
  * fetching state from the chain and database as needed.
@@ -40,51 +49,51 @@ export function getReqRespHandlers({db, chain}: {db: IBeaconDb; chain: IBeaconCh
40
49
  [ReqRespMethod.Ping]: notImplemented(ReqRespMethod.Ping),
41
50
  [ReqRespMethod.Metadata]: notImplemented(ReqRespMethod.Metadata),
42
51
  [ReqRespMethod.BeaconBlocksByRange]: (req, peerId, peerClient) => {
43
- const body = ssz.phase0.BeaconBlocksByRangeRequest.deserialize(req.data);
52
+ const body = deserializeRequestBody(ssz.phase0.BeaconBlocksByRangeRequest, req.data);
44
53
  return onBeaconBlocksByRange(body, chain, db, peerId, peerClient);
45
54
  },
46
55
  [ReqRespMethod.BeaconBlocksByRoot]: (req) => {
47
56
  const fork = chain.config.getForkName(chain.clock.currentSlot);
48
- const body = BeaconBlocksByRootRequestType(fork, chain.config).deserialize(req.data);
57
+ const body = deserializeRequestBody(BeaconBlocksByRootRequestType(fork, chain.config), req.data);
49
58
  return onBeaconBlocksByRoot(body, chain);
50
59
  },
51
60
  [ReqRespMethod.BeaconBlocksByHead]: (req, peerId, peerClient) => {
52
- const body = ssz.fulu.BeaconBlocksByHeadRequest.deserialize(req.data);
61
+ const body = deserializeRequestBody(ssz.fulu.BeaconBlocksByHeadRequest, req.data);
53
62
  return onBeaconBlocksByHead(body, chain, peerId, peerClient);
54
63
  },
55
64
  [ReqRespMethod.BlobSidecarsByRoot]: (req) => {
56
65
  const fork = chain.config.getForkName(chain.clock.currentSlot);
57
- const body = BlobSidecarsByRootRequestType(fork, chain.config).deserialize(req.data);
66
+ const body = deserializeRequestBody(BlobSidecarsByRootRequestType(fork, chain.config), req.data);
58
67
  return onBlobSidecarsByRoot(body, chain);
59
68
  },
60
69
  [ReqRespMethod.BlobSidecarsByRange]: (req) => {
61
- const body = ssz.deneb.BlobSidecarsByRangeRequest.deserialize(req.data);
70
+ const body = deserializeRequestBody(ssz.deneb.BlobSidecarsByRangeRequest, req.data);
62
71
  return onBlobSidecarsByRange(body, chain, db);
63
72
  },
64
73
  [ReqRespMethod.DataColumnSidecarsByRange]: (req, peerId, peerClient) => {
65
- const body = ssz.fulu.DataColumnSidecarsByRangeRequest.deserialize(req.data);
74
+ const body = deserializeRequestBody(ssz.fulu.DataColumnSidecarsByRangeRequest, req.data);
66
75
  return onDataColumnSidecarsByRange(body, chain, db, peerId, peerClient);
67
76
  },
68
77
  [ReqRespMethod.DataColumnSidecarsByRoot]: (req, peerId, peerClient) => {
69
- const body = DataColumnSidecarsByRootRequestType(chain.config).deserialize(req.data);
78
+ const body = deserializeRequestBody(DataColumnSidecarsByRootRequestType(chain.config), req.data);
70
79
  return onDataColumnSidecarsByRoot(body, chain, db, peerId, peerClient);
71
80
  },
72
81
 
73
82
  [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: (req, peerId, peerClient) => {
74
- const body = ExecutionPayloadEnvelopesByRootRequestType(chain.config).deserialize(req.data);
83
+ const body = deserializeRequestBody(ExecutionPayloadEnvelopesByRootRequestType(chain.config), req.data);
75
84
  return onExecutionPayloadEnvelopesByRoot(body, chain, db, peerId, peerClient);
76
85
  },
77
86
  [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: (req, peerId, peerClient) => {
78
- const body = ssz.gloas.ExecutionPayloadEnvelopesByRangeRequest.deserialize(req.data);
87
+ const body = deserializeRequestBody(ssz.gloas.ExecutionPayloadEnvelopesByRangeRequest, req.data);
79
88
  return onExecutionPayloadEnvelopesByRange(body, chain, db, peerId, peerClient);
80
89
  },
81
90
 
82
91
  [ReqRespMethod.LightClientBootstrap]: (req) => {
83
- const body = ssz.Root.deserialize(req.data);
92
+ const body = deserializeRequestBody(ssz.Root, req.data);
84
93
  return onLightClientBootstrap(body, chain);
85
94
  },
86
95
  [ReqRespMethod.LightClientUpdatesByRange]: (req) => {
87
- const body = ssz.altair.LightClientUpdatesByRange.deserialize(req.data);
96
+ const body = deserializeRequestBody(ssz.altair.LightClientUpdatesByRange, req.data);
88
97
  return onLightClientUpdatesByRange(body, chain);
89
98
  },
90
99
  [ReqRespMethod.LightClientFinalityUpdate]: () => onLightClientFinalityUpdate(chain),
package/src/sync/sync.ts CHANGED
@@ -75,6 +75,11 @@ export class BeaconSync implements IBeaconSync {
75
75
  if (metrics) {
76
76
  metrics.syncStatus.addCollect(() => this.scrapeMetrics(metrics));
77
77
  }
78
+
79
+ // A from-scratch or large-gap start boots not synced; updateSyncState resumes once synced
80
+ if (this.state !== SyncState.Synced) {
81
+ this.chain.forkChoice.pauseFastConfirmation();
82
+ }
78
83
  }
79
84
 
80
85
  close(): void {
@@ -228,6 +233,8 @@ export class BeaconSync implements IBeaconSync {
228
233
 
229
234
  // We have become synced, subscribe to all the gossip core topics
230
235
  if (state === SyncState.Synced && this.chain.clock.currentEpoch >= MIN_EPOCH_TO_START_GOSSIP) {
236
+ this.chain.forkChoice.resumeFastConfirmation();
237
+
231
238
  if (!this.network.isSubscribedToGossipCoreTopics()) {
232
239
  this.network
233
240
  .subscribeGossipCoreTopics()
@@ -251,6 +258,9 @@ export class BeaconSync implements IBeaconSync {
251
258
  else if (state !== SyncState.Synced) {
252
259
  const syncDiff = this.chain.clock.currentSlot - this.chain.forkChoice.getHead().slot;
253
260
  if (syncDiff > this.slotImportTolerance * 2) {
261
+ // Same debounce as gossip: transient blips keep the rule running, only a real gap pauses it
262
+ this.chain.forkChoice.pauseFastConfirmation();
263
+
254
264
  if (this.network.isSubscribedToGossipCoreTopics()) {
255
265
  this.logger.warn(`Node sync has fallen behind by ${syncDiff} slots`);
256
266
  this.network
@@ -841,10 +841,16 @@ export class BlockInputSync {
841
841
 
842
842
  case BlockErrorCode.EXECUTION_ENGINE_ERROR:
843
843
  // Removing the block(s) without penalizing the peers, hoping for EL to
844
- // recover on a latter download + verify attempt
844
+ // recover on a latter download + verify attempt.
845
845
  this.removeAllDescendants(pendingBlock);
846
846
  break;
847
847
 
848
+ case BlockErrorCode.EXECUTION_ENGINE_INVALID:
849
+ // the peer served a bad block
850
+ this.logger.debug("Execution engine rejected block from unknown parent sync", errorData, res.err);
851
+ this.removeAndDownScoreAllDescendants(pendingBlock);
852
+ break;
853
+
848
854
  default:
849
855
  // Block is not correct with respect to our chain. Log error loudly
850
856
  this.logger.debug("Error processing block from unknown parent sync", errorData, res.err);