@lodestar/beacon-node 1.45.0-dev.51a1c44b27 → 1.45.0-dev.7acc183c2b

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 (237) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +3 -2
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/beacon/index.d.ts +1 -1
  5. package/lib/api/impl/beacon/index.d.ts.map +1 -1
  6. package/lib/api/impl/beacon/index.js.map +1 -1
  7. package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
  8. package/lib/api/impl/beacon/pool/index.js +6 -43
  9. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  10. package/lib/api/impl/beacon/state/index.d.ts +1 -1
  11. package/lib/api/impl/beacon/state/index.d.ts.map +1 -1
  12. package/lib/api/impl/beacon/state/index.js +48 -5
  13. package/lib/api/impl/beacon/state/index.js.map +1 -1
  14. package/lib/api/impl/beacon/state/utils.d.ts +13 -3
  15. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  16. package/lib/api/impl/beacon/state/utils.js +48 -4
  17. package/lib/api/impl/beacon/state/utils.js.map +1 -1
  18. package/lib/api/impl/debug/index.d.ts +1 -1
  19. package/lib/api/impl/debug/index.d.ts.map +1 -1
  20. package/lib/api/impl/debug/index.js +2 -2
  21. package/lib/api/impl/debug/index.js.map +1 -1
  22. package/lib/api/impl/lodestar/index.js +2 -2
  23. package/lib/api/impl/lodestar/index.js.map +1 -1
  24. package/lib/api/impl/proof/index.d.ts +1 -1
  25. package/lib/api/impl/proof/index.d.ts.map +1 -1
  26. package/lib/api/impl/proof/index.js +2 -2
  27. package/lib/api/impl/proof/index.js.map +1 -1
  28. package/lib/api/impl/utils.d.ts +23 -0
  29. package/lib/api/impl/utils.d.ts.map +1 -1
  30. package/lib/api/impl/utils.js +44 -1
  31. package/lib/api/impl/utils.js.map +1 -1
  32. package/lib/api/impl/validator/index.d.ts +0 -14
  33. package/lib/api/impl/validator/index.d.ts.map +1 -1
  34. package/lib/api/impl/validator/index.js +67 -62
  35. package/lib/api/impl/validator/index.js.map +1 -1
  36. package/lib/api/rest/base.d.ts.map +1 -1
  37. package/lib/api/rest/base.js +8 -0
  38. package/lib/api/rest/base.js.map +1 -1
  39. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  40. package/lib/chain/blocks/importBlock.js +2 -5
  41. package/lib/chain/blocks/importBlock.js.map +1 -1
  42. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +5 -2
  43. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -1
  44. package/lib/chain/blocks/payloadEnvelopeProcessor.js +17 -17
  45. package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
  46. package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
  47. package/lib/chain/blocks/utils/chainSegment.js +13 -5
  48. package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
  49. package/lib/chain/blocks/verifyBlocksSanityChecks.js +1 -1
  50. package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
  51. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +2 -2
  52. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -1
  53. package/lib/chain/builderCircuitBreaker.d.ts +31 -0
  54. package/lib/chain/builderCircuitBreaker.d.ts.map +1 -0
  55. package/lib/chain/builderCircuitBreaker.js +59 -0
  56. package/lib/chain/builderCircuitBreaker.js.map +1 -0
  57. package/lib/chain/chain.d.ts +3 -2
  58. package/lib/chain/chain.d.ts.map +1 -1
  59. package/lib/chain/chain.js +4 -3
  60. package/lib/chain/chain.js.map +1 -1
  61. package/lib/chain/errors/blockError.d.ts +29 -5
  62. package/lib/chain/errors/blockError.d.ts.map +1 -1
  63. package/lib/chain/errors/blockError.js +19 -4
  64. package/lib/chain/errors/blockError.js.map +1 -1
  65. package/lib/chain/errors/executionPayloadEnvelope.d.ts +11 -0
  66. package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
  67. package/lib/chain/errors/executionPayloadEnvelope.js +2 -0
  68. package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
  69. package/lib/chain/interface.d.ts +3 -2
  70. package/lib/chain/interface.d.ts.map +1 -1
  71. package/lib/chain/interface.js.map +1 -1
  72. package/lib/chain/lightClient/index.d.ts.map +1 -1
  73. package/lib/chain/lightClient/index.js +11 -6
  74. package/lib/chain/lightClient/index.js.map +1 -1
  75. package/lib/chain/lightClient/proofs.d.ts.map +1 -1
  76. package/lib/chain/lightClient/proofs.js +28 -2
  77. package/lib/chain/lightClient/proofs.js.map +1 -1
  78. package/lib/chain/lightClient/types.d.ts +3 -1
  79. package/lib/chain/lightClient/types.d.ts.map +1 -1
  80. package/lib/chain/opPools/aggregatedAttestationPool.js +1 -1
  81. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  82. package/lib/chain/opPools/proposerPreferencesPool.d.ts +2 -1
  83. package/lib/chain/opPools/proposerPreferencesPool.d.ts.map +1 -1
  84. package/lib/chain/opPools/proposerPreferencesPool.js +3 -0
  85. package/lib/chain/opPools/proposerPreferencesPool.js.map +1 -1
  86. package/lib/chain/options.d.ts +5 -0
  87. package/lib/chain/options.d.ts.map +1 -1
  88. package/lib/chain/options.js +1 -0
  89. package/lib/chain/options.js.map +1 -1
  90. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  91. package/lib/chain/prepareNextSlot.js +12 -7
  92. package/lib/chain/prepareNextSlot.js.map +1 -1
  93. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  94. package/lib/chain/produceBlock/produceBlockBody.js +4 -12
  95. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  96. package/lib/chain/seenCache/index.d.ts +0 -1
  97. package/lib/chain/seenCache/index.d.ts.map +1 -1
  98. package/lib/chain/seenCache/index.js +0 -1
  99. package/lib/chain/seenCache/index.js.map +1 -1
  100. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  101. package/lib/chain/stateCache/persistentCheckpointsCache.js +3 -2
  102. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  103. package/lib/chain/validation/block.d.ts.map +1 -1
  104. package/lib/chain/validation/block.js +55 -4
  105. package/lib/chain/validation/block.js.map +1 -1
  106. package/lib/chain/validation/executionPayloadBid.js +11 -10
  107. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  108. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  109. package/lib/chain/validation/executionPayloadEnvelope.js +30 -0
  110. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  111. package/lib/chain/validation/proposerPreferences.d.ts.map +1 -1
  112. package/lib/chain/validation/proposerPreferences.js +14 -5
  113. package/lib/chain/validation/proposerPreferences.js.map +1 -1
  114. package/lib/chain/validation/signatureSets/aggregateAndProof.d.ts.map +1 -1
  115. package/lib/chain/validation/signatureSets/aggregateAndProof.js +2 -3
  116. package/lib/chain/validation/signatureSets/aggregateAndProof.js.map +1 -1
  117. package/lib/db/repositories/lightclientSyncCommitteeWitness.d.ts.map +1 -1
  118. package/lib/db/repositories/lightclientSyncCommitteeWitness.js +42 -7
  119. package/lib/db/repositories/lightclientSyncCommitteeWitness.js.map +1 -1
  120. package/lib/execution/builder/http.d.ts +18 -0
  121. package/lib/execution/builder/http.d.ts.map +1 -1
  122. package/lib/execution/builder/http.js +20 -11
  123. package/lib/execution/builder/http.js.map +1 -1
  124. package/lib/metrics/metrics/beacon.d.ts +6 -0
  125. package/lib/metrics/metrics/beacon.d.ts.map +1 -1
  126. package/lib/metrics/metrics/beacon.js +18 -0
  127. package/lib/metrics/metrics/beacon.js.map +1 -1
  128. package/lib/network/core/metrics.d.ts +65 -0
  129. package/lib/network/core/metrics.d.ts.map +1 -1
  130. package/lib/network/core/metrics.js +94 -0
  131. package/lib/network/core/metrics.js.map +1 -1
  132. package/lib/network/discv5/utils.d.ts.map +1 -1
  133. package/lib/network/discv5/utils.js +12 -3
  134. package/lib/network/discv5/utils.js.map +1 -1
  135. package/lib/network/gossip/encoding.d.ts +2 -2
  136. package/lib/network/gossip/encoding.d.ts.map +1 -1
  137. package/lib/network/gossip/encoding.js +22 -9
  138. package/lib/network/gossip/encoding.js.map +1 -1
  139. package/lib/network/gossip/gossipsub.d.ts.map +1 -1
  140. package/lib/network/gossip/gossipsub.js +4 -3
  141. package/lib/network/gossip/gossipsub.js.map +1 -1
  142. package/lib/network/gossip/topic.d.ts +831 -226
  143. package/lib/network/gossip/topic.d.ts.map +1 -1
  144. package/lib/network/gossip/topic.js +47 -4
  145. package/lib/network/gossip/topic.js.map +1 -1
  146. package/lib/network/peers/peerManager.d.ts.map +1 -1
  147. package/lib/network/peers/peerManager.js +10 -0
  148. package/lib/network/peers/peerManager.js.map +1 -1
  149. package/lib/network/peers/score/score.d.ts +3 -1
  150. package/lib/network/peers/score/score.d.ts.map +1 -1
  151. package/lib/network/peers/score/score.js +6 -1
  152. package/lib/network/peers/score/score.js.map +1 -1
  153. package/lib/network/peers/score/store.d.ts.map +1 -1
  154. package/lib/network/peers/score/store.js +6 -1
  155. package/lib/network/peers/score/store.js.map +1 -1
  156. package/lib/network/peers/utils/prioritizePeers.d.ts.map +1 -1
  157. package/lib/network/peers/utils/prioritizePeers.js +14 -0
  158. package/lib/network/peers/utils/prioritizePeers.js.map +1 -1
  159. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  160. package/lib/network/processor/gossipHandlers.js +12 -8
  161. package/lib/network/processor/gossipHandlers.js.map +1 -1
  162. package/lib/sync/range/chain.d.ts +4 -1
  163. package/lib/sync/range/chain.d.ts.map +1 -1
  164. package/lib/sync/range/chain.js +3 -3
  165. package/lib/sync/range/chain.js.map +1 -1
  166. package/lib/sync/range/range.d.ts.map +1 -1
  167. package/lib/sync/range/range.js +10 -0
  168. package/lib/sync/range/range.js.map +1 -1
  169. package/lib/sync/unknownBlock.js +1 -1
  170. package/lib/sync/unknownBlock.js.map +1 -1
  171. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  172. package/lib/sync/utils/downloadByRange.js +6 -0
  173. package/lib/sync/utils/downloadByRange.js.map +1 -1
  174. package/lib/util/graffiti.d.ts +15 -0
  175. package/lib/util/graffiti.d.ts.map +1 -1
  176. package/lib/util/graffiti.js +55 -0
  177. package/lib/util/graffiti.js.map +1 -1
  178. package/package.json +19 -19
  179. package/src/api/impl/beacon/blocks/index.ts +3 -2
  180. package/src/api/impl/beacon/index.ts +1 -1
  181. package/src/api/impl/beacon/pool/index.ts +5 -53
  182. package/src/api/impl/beacon/state/index.ts +55 -3
  183. package/src/api/impl/beacon/state/utils.ts +68 -4
  184. package/src/api/impl/debug/index.ts +3 -2
  185. package/src/api/impl/lodestar/index.ts +2 -2
  186. package/src/api/impl/proof/index.ts +2 -2
  187. package/src/api/impl/utils.ts +51 -1
  188. package/src/api/impl/validator/index.ts +75 -67
  189. package/src/api/rest/base.ts +9 -0
  190. package/src/chain/blocks/importBlock.ts +2 -7
  191. package/src/chain/blocks/payloadEnvelopeProcessor.ts +17 -17
  192. package/src/chain/blocks/utils/chainSegment.ts +16 -5
  193. package/src/chain/blocks/verifyBlocksSanityChecks.ts +1 -1
  194. package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +2 -2
  195. package/src/chain/builderCircuitBreaker.ts +84 -0
  196. package/src/chain/chain.ts +7 -3
  197. package/src/chain/errors/blockError.ts +23 -6
  198. package/src/chain/errors/executionPayloadEnvelope.ts +9 -0
  199. package/src/chain/interface.ts +2 -2
  200. package/src/chain/lightClient/index.ts +12 -7
  201. package/src/chain/lightClient/proofs.ts +36 -1
  202. package/src/chain/lightClient/types.ts +3 -1
  203. package/src/chain/opPools/aggregatedAttestationPool.ts +1 -1
  204. package/src/chain/opPools/proposerPreferencesPool.ts +5 -1
  205. package/src/chain/options.ts +6 -0
  206. package/src/chain/prepareNextSlot.ts +11 -7
  207. package/src/chain/produceBlock/produceBlockBody.ts +9 -17
  208. package/src/chain/seenCache/index.ts +0 -1
  209. package/src/chain/stateCache/persistentCheckpointsCache.ts +3 -2
  210. package/src/chain/validation/block.ts +72 -4
  211. package/src/chain/validation/executionPayloadBid.ts +14 -9
  212. package/src/chain/validation/executionPayloadEnvelope.ts +39 -0
  213. package/src/chain/validation/proposerPreferences.ts +15 -5
  214. package/src/chain/validation/signatureSets/aggregateAndProof.ts +3 -3
  215. package/src/db/repositories/lightclientSyncCommitteeWitness.ts +57 -9
  216. package/src/execution/builder/http.ts +30 -17
  217. package/src/metrics/metrics/beacon.ts +19 -0
  218. package/src/network/core/metrics.ts +94 -0
  219. package/src/network/discv5/utils.ts +11 -3
  220. package/src/network/gossip/encoding.ts +20 -7
  221. package/src/network/gossip/gossipsub.ts +9 -3
  222. package/src/network/gossip/topic.ts +59 -4
  223. package/src/network/peers/peerManager.ts +11 -0
  224. package/src/network/peers/score/score.ts +8 -1
  225. package/src/network/peers/score/store.ts +8 -1
  226. package/src/network/peers/utils/prioritizePeers.ts +15 -0
  227. package/src/network/processor/gossipHandlers.ts +12 -7
  228. package/src/sync/range/chain.ts +4 -5
  229. package/src/sync/range/range.ts +10 -0
  230. package/src/sync/unknownBlock.ts +1 -1
  231. package/src/sync/utils/downloadByRange.ts +6 -0
  232. package/src/util/graffiti.ts +78 -0
  233. package/lib/chain/seenCache/seenProposerPreferences.d.ts +0 -16
  234. package/lib/chain/seenCache/seenProposerPreferences.d.ts.map +0 -1
  235. package/lib/chain/seenCache/seenProposerPreferences.js +0 -26
  236. package/lib/chain/seenCache/seenProposerPreferences.js.map +0 -1
  237. package/src/chain/seenCache/seenProposerPreferences.ts +0 -32
@@ -32,7 +32,9 @@ export class PeerRpcScoreStore implements IPeerRpcScoreStore {
32
32
  constructor(opts: PeerRpcScoreOpts = {}, metrics: NetworkCoreMetrics | null = null, logger: Logger | null = null) {
33
33
  this.metrics = metrics;
34
34
  this.logger = logger;
35
- this.scores = opts.disablePeerScoring ? new MapDef(() => new MaxScore()) : new MapDef(() => new RealScore());
35
+ this.scores = opts.disablePeerScoring
36
+ ? new MapDef(() => new MaxScore())
37
+ : new MapDef(() => new RealScore(this.metrics));
36
38
  }
37
39
 
38
40
  getScore(peer: PeerId): number {
@@ -75,6 +77,8 @@ export class PeerRpcScoreStore implements IPeerRpcScoreStore {
75
77
  }
76
78
 
77
79
  update(): void {
80
+ const timer = this.metrics?.peerManager.scoreUpdateDuration.startTimer();
81
+
78
82
  // Bound size of data structures
79
83
  pruneSetToMax(this.scores, MAX_ENTRIES);
80
84
 
@@ -86,6 +90,9 @@ export class PeerRpcScoreStore implements IPeerRpcScoreStore {
86
90
  this.scores.delete(peerIdStr);
87
91
  }
88
92
  }
93
+
94
+ this.metrics?.peerManager.scoreMapSize.set(this.scores.size);
95
+ timer?.();
89
96
  }
90
97
 
91
98
  updateGossipsubScore(peerId: PeerIdStr, newScore: number, ignore: boolean): void {
@@ -7,6 +7,7 @@ import {MapDef} from "@lodestar/utils";
7
7
  import {shuffle} from "../../../util/shuffle.js";
8
8
  import {sortBy} from "../../../util/sortBy.js";
9
9
  import {NetworkCoreMetrics} from "../../core/metrics.js";
10
+ import {SubnetType} from "../../metadata.js";
10
11
  import {RequestedSubnet} from "./subnetMap.js";
11
12
 
12
13
  /** Target number of peers we'd like to have connected to a given long-lived subnet */
@@ -189,6 +190,18 @@ export function prioritizePeers(
189
190
 
190
191
  const connectedPeerCount = connectedPeers.length;
191
192
 
193
+ // Track the outbound peers invariant (we keep at least OUTBOUND_PEERS_RATIO outbound peers).
194
+ // Report 0 when there are no peers so the gauge doesn't go stale at its last value.
195
+ if (metrics) {
196
+ let outboundPeerCount = 0;
197
+ for (const peer of connectedPeers) {
198
+ if (peer.direction === "outbound") {
199
+ outboundPeerCount++;
200
+ }
201
+ }
202
+ metrics.peerManager.outboundPeersRatio.set(connectedPeerCount > 0 ? outboundPeerCount / connectedPeerCount : 0);
203
+ }
204
+
192
205
  if (connectedPeerCount < targetPeers) {
193
206
  // Need more peers.
194
207
  // Instead of attempting to connect the exact amount necessary this will overshoot a little since the success
@@ -256,6 +269,7 @@ function requestSubnetPeers(
256
269
 
257
270
  for (const {subnet, toSlot} of activeAttnets) {
258
271
  const peersInSubnet = peersPerSubnet.get(subnet) ?? 0;
272
+ metrics?.peerManager.peersPerActiveSubnet.observe({type: SubnetType.attnets}, peersInSubnet);
259
273
  if (peersInSubnet < targetSubnetPeers) {
260
274
  // We need more peers
261
275
  attnetQueries.push({subnet, toSlot, maxPeersToDiscover: targetSubnetPeers - peersInSubnet});
@@ -282,6 +296,7 @@ function requestSubnetPeers(
282
296
 
283
297
  for (const {subnet, toSlot} of activeSyncnets) {
284
298
  const peersInSubnet = peersPerSubnet.get(subnet) ?? 0;
299
+ metrics?.peerManager.peersPerActiveSubnet.observe({type: SubnetType.syncnets}, peersInSubnet);
285
300
  if (peersInSubnet < targetSubnetPeers) {
286
301
  // We need more peers
287
302
  syncnetQueries.push({subnet, toSlot, maxPeersToDiscover: targetSubnetPeers - peersInSubnet});
@@ -176,7 +176,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
176
176
 
177
177
  // optimistically add gossip block to the seen cache
178
178
  // if validation fails, we will NOT forward this gossip block to peers
179
- // - if PARENT_UNKNOWN error, blockInput will then be queued inside BlockInputSync. If the gossip block is really invalid, it will be pruned there
179
+ // - if PARENT_BLOCK_UNKNOWN error, blockInput will then be queued inside BlockInputSync. If the gossip block is really invalid, it will be pruned there
180
180
  // - if other validator errors, blockInput will stay in the seen cache and will be pruned on finalization
181
181
  const blockInput = chain.seenBlockInputCache.getByBlock({
182
182
  block: signedBlock,
@@ -187,7 +187,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
187
187
  });
188
188
 
189
189
  // Optimistically seed the payload-envelope cache too, mirroring seenBlockInputCache above.
190
- // This ensures we have PayloadEnvelopeInput, even through "PARENT_UNKNOWN" error
190
+ // This ensures we have PayloadEnvelopeInput, even through "PARENT_BLOCK_UNKNOWN" error
191
191
  // see https://github.com/ChainSafe/lodestar/issues/9475
192
192
  if (isForkPostGloas(fork)) {
193
193
  chain.seenPayloadEnvelopeInputCache.add({
@@ -227,7 +227,8 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
227
227
  if (e instanceof BlockGossipError) {
228
228
  logger.debug("Gossip block has error", {slot, root: blockShortHex, code: e.type.code});
229
229
  if (
230
- (e.type.code === BlockErrorCode.PARENT_UNKNOWN || e.type.code === BlockErrorCode.PARENT_PAYLOAD_UNKNOWN) &&
230
+ (e.type.code === BlockErrorCode.PARENT_BLOCK_UNKNOWN ||
231
+ e.type.code === BlockErrorCode.PARENT_PAYLOAD_UNKNOWN) &&
231
232
  blockInput
232
233
  ) {
233
234
  chain.emitter.emit(ChainEvent.blockUnknownParent, {
@@ -661,9 +662,9 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
661
662
  break;
662
663
  }
663
664
  // ALREADY_KNOWN should not happen with ignoreIfKnown=true above
664
- // PARENT_UNKNOWN should not happen, we handled this in validateBeaconBlock() function above
665
+ // PARENT_BLOCK_UNKNOWN should not happen, we handled this in validateBeaconBlock() function above
665
666
  case BlockErrorCode.ALREADY_KNOWN:
666
- case BlockErrorCode.PARENT_UNKNOWN:
667
+ case BlockErrorCode.PARENT_BLOCK_UNKNOWN:
667
668
  case BlockErrorCode.PRESTATE_MISSING:
668
669
  case BlockErrorCode.EXECUTION_ENGINE_ERROR:
669
670
  // Errors might indicate an issue with our node or the connected EL client
@@ -1241,6 +1242,11 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
1241
1242
  payloadAttestationMessage.data.payloadPresent,
1242
1243
  payloadAttestationMessage.data.blobDataAvailable
1243
1244
  );
1245
+
1246
+ chain.emitter.emit(routes.events.EventType.payloadAttestationMessage, {
1247
+ version: config.getForkName(payloadAttestationMessage.data.slot),
1248
+ data: payloadAttestationMessage,
1249
+ });
1244
1250
  },
1245
1251
  [GossipType.execution_payload_bid]: async ({
1246
1252
  gossipData,
@@ -1273,9 +1279,8 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
1273
1279
  const signedProposerPreferences = sszDeserialize(topic, serializedData);
1274
1280
  await validateGossipProposerPreferences(chain, signedProposerPreferences);
1275
1281
 
1276
- chain.proposerPreferencesPool.add(signedProposerPreferences);
1277
1282
  chain.emitter.emit(routes.events.EventType.proposerPreferences, {
1278
- version: ForkName.gloas,
1283
+ version: config.getForkName(signedProposerPreferences.message.proposalSlot),
1279
1284
  data: signedProposerPreferences,
1280
1285
  });
1281
1286
  },
@@ -186,10 +186,6 @@ export class SyncChain {
186
186
  this.logger = logger;
187
187
  this.logId = `${syncType}-${nextChainId++}`;
188
188
 
189
- if (metrics) {
190
- metrics.syncRange.headSyncPeers.addCollect(() => this.scrapeMetrics(metrics));
191
- }
192
-
193
189
  // Trigger event on parent class
194
190
  this.sync().then(
195
191
  () => fns.onEnd(null, this.target),
@@ -775,7 +771,10 @@ export class SyncChain {
775
771
  });
776
772
  }
777
773
 
778
- private scrapeMetrics(metrics: Metrics): void {
774
+ /**
775
+ * Called by `RangeSync`'s to avoid collecting metrics of removed chains.
776
+ */
777
+ scrapeMetrics(metrics: Metrics): void {
779
778
  const syncPeersMetric =
780
779
  this.syncType === RangeSyncType.Finalized
781
780
  ? metrics.syncRange.finalizedSyncPeers
@@ -105,6 +105,16 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
105
105
 
106
106
  if (metrics) {
107
107
  metrics.syncStatus.addCollect(() => this.scrapeMetrics(metrics));
108
+ metrics.syncRange.headSyncPeers.addCollect(() => {
109
+ // Gauges retain their last set value, so a removed chain would keep reporting stale
110
+ // per-column peer counts (finalizedSyncPeers especially, as it is rarely recreated once
111
+ // synced)
112
+ metrics.syncRange.headSyncPeers.reset();
113
+ metrics.syncRange.finalizedSyncPeers.reset();
114
+ for (const syncChain of this.chains.values()) {
115
+ syncChain.scrapeMetrics(metrics);
116
+ }
117
+ });
108
118
  }
109
119
  }
110
120
 
@@ -819,7 +819,7 @@ export class BlockInputSync {
819
819
  // case BlockErrorCode.ALREADY_KNOWN:
820
820
  // case BlockErrorCode.GENESIS_BLOCK:
821
821
 
822
- case BlockErrorCode.PARENT_UNKNOWN:
822
+ case BlockErrorCode.PARENT_BLOCK_UNKNOWN:
823
823
  case BlockErrorCode.PRESTATE_MISSING:
824
824
  // Should not happen, mark as downloaded to try again latter
825
825
  this.logger.debug("Attempted to process block but its parent was still unknown", errorData, res.err);
@@ -981,6 +981,12 @@ export async function validateColumnsByRangeResponse(
981
981
  missingIndices: prettyPrintIndices(request.columns),
982
982
  })
983
983
  );
984
+ // Gloas: the bid commits to blobs even for payloads that get orphaned, whose columns are
985
+ // pruned and unservable. Skip instead of truncating + re-requesting forever; DA is enforced
986
+ // on envelope processing. Pre-Gloas commitments are canonical, so keep strict.
987
+ if (isForkPostGloas(forkName)) {
988
+ continue;
989
+ }
984
990
  break;
985
991
  }
986
992
 
@@ -37,3 +37,81 @@ export function getDefaultGraffiti(
37
37
  // No EL client info available. We still want to include CL info albeit not spec compliant
38
38
  return `${consensusClientVersion.code}${consensusClientVersion.commit.slice(0, 4)}`;
39
39
  }
40
+
41
+ function appendLongestFittingSuffix(userGraffiti: string, suffixes: string[]): string {
42
+ const userGraffitiBytes = Buffer.byteLength(userGraffiti, "utf8");
43
+ if (userGraffitiBytes >= GRAFFITI_SIZE) {
44
+ return userGraffiti;
45
+ }
46
+
47
+ const availableBytes = GRAFFITI_SIZE - userGraffitiBytes;
48
+
49
+ for (const suffix of suffixes) {
50
+ if (Buffer.byteLength(suffix, "utf8") <= availableBytes) {
51
+ return `${userGraffiti}${suffix}`;
52
+ }
53
+ }
54
+
55
+ return userGraffiti;
56
+ }
57
+
58
+ /**
59
+ * Appends the richest available client watermark that fits after user graffiti.
60
+ *
61
+ * Tiers are:
62
+ * - full EL/CL watermark, e.g. " BU9b0eLS80c2"
63
+ * - EL/CL client codes, e.g. " BULS"
64
+ * - CL client code, e.g. " LS"
65
+ */
66
+ export function appendClientInfoToGraffiti(
67
+ userGraffiti: string,
68
+ consensusClientVersion: ClientVersion,
69
+ executionClientVersion: ClientVersion | null | undefined,
70
+ opts: {private?: boolean} = {}
71
+ ): string {
72
+ if (opts.private) {
73
+ return userGraffiti;
74
+ }
75
+
76
+ // Graffiti supplied via the beacon API is decoded from a fixed 32-byte field (see
77
+ // fromGraffitiHex) and arrives right-padded with NUL bytes. Trim only trailing padding
78
+ // NULs; a NUL that appears in the middle of the string is data, not padding.
79
+ let end = userGraffiti.length;
80
+ while (end > 0 && userGraffiti.charCodeAt(end - 1) === 0) {
81
+ end--;
82
+ }
83
+ const graffiti = userGraffiti.slice(0, end);
84
+
85
+ const fullClientInfo = getDefaultGraffiti(consensusClientVersion, executionClientVersion, {private: false});
86
+ if (graffiti.length === 0) {
87
+ return fullClientInfo;
88
+ }
89
+
90
+ const suffixes =
91
+ executionClientVersion != null
92
+ ? [
93
+ ` ${fullClientInfo}`,
94
+ ` ${executionClientVersion.code}${consensusClientVersion.code}`,
95
+ ` ${consensusClientVersion.code}`,
96
+ ]
97
+ : [` ${fullClientInfo}`, ` ${consensusClientVersion.code}`];
98
+
99
+ return appendLongestFittingSuffix(graffiti, suffixes);
100
+ }
101
+
102
+ export function getBlockGraffiti(
103
+ userGraffiti: string | undefined,
104
+ consensusClientVersion: ClientVersion,
105
+ executionClientVersion: ClientVersion | null | undefined,
106
+ opts: {private?: boolean; graffitiAppend?: boolean}
107
+ ): string {
108
+ if (userGraffiti === undefined) {
109
+ return getDefaultGraffiti(consensusClientVersion, executionClientVersion, opts);
110
+ }
111
+
112
+ if (opts.graffitiAppend === false) {
113
+ return userGraffiti;
114
+ }
115
+
116
+ return appendClientInfoToGraffiti(userGraffiti, consensusClientVersion, executionClientVersion, opts);
117
+ }
@@ -1,16 +0,0 @@
1
- import { RootHex, Slot, ValidatorIndex } from "@lodestar/types";
2
- /**
3
- * Tracks signed proposer preferences we've already seen per (dependent_root, proposal_slot, validator_index).
4
- */
5
- export declare class SeenProposerPreferences {
6
- private readonly validatorByDependentRootBySlot;
7
- isKnown(dependentRoot: RootHex, proposalSlot: Slot, validatorIndex: ValidatorIndex): boolean;
8
- add(dependentRoot: RootHex, proposalSlot: Slot, validatorIndex: ValidatorIndex): void;
9
- /**
10
- * Entries are only load-bearing while `proposal_slot > current_slot`. Once the slot has
11
- * passed the `[IGNORE] proposal_slot > current_slot` gossip rule takes over, so drop them
12
- * on each slot tick.
13
- */
14
- prune(currentSlot: Slot): void;
15
- }
16
- //# sourceMappingURL=seenProposerPreferences.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"seenProposerPreferences.d.ts","sourceRoot":"","sources":["../../../src/chain/seenCache/seenProposerPreferences.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAE,IAAI,EAAE,cAAc,EAAC,MAAM,iBAAiB,CAAC;AAG9D;;GAEG;AACH,qBAAa,uBAAuB;IAClC,OAAO,CAAC,QAAQ,CAAC,8BAA8B,CAE7C;IAEF,OAAO,CAAC,aAAa,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,cAAc,GAAG,OAAO,CAE3F;IAED,GAAG,CAAC,aAAa,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,cAAc,GAAG,IAAI,CAEpF;IAED;;;;OAIG;IACH,KAAK,CAAC,WAAW,EAAE,IAAI,GAAG,IAAI,CAM7B;CACF"}
@@ -1,26 +0,0 @@
1
- import { MapDef } from "@lodestar/utils";
2
- /**
3
- * Tracks signed proposer preferences we've already seen per (dependent_root, proposal_slot, validator_index).
4
- */
5
- export class SeenProposerPreferences {
6
- validatorByDependentRootBySlot = new MapDef(() => new Map());
7
- isKnown(dependentRoot, proposalSlot, validatorIndex) {
8
- return this.validatorByDependentRootBySlot.get(proposalSlot)?.get(dependentRoot) === validatorIndex;
9
- }
10
- add(dependentRoot, proposalSlot, validatorIndex) {
11
- this.validatorByDependentRootBySlot.getOrDefault(proposalSlot).set(dependentRoot, validatorIndex);
12
- }
13
- /**
14
- * Entries are only load-bearing while `proposal_slot > current_slot`. Once the slot has
15
- * passed the `[IGNORE] proposal_slot > current_slot` gossip rule takes over, so drop them
16
- * on each slot tick.
17
- */
18
- prune(currentSlot) {
19
- for (const slot of this.validatorByDependentRootBySlot.keys()) {
20
- if (slot < currentSlot) {
21
- this.validatorByDependentRootBySlot.delete(slot);
22
- }
23
- }
24
- }
25
- }
26
- //# sourceMappingURL=seenProposerPreferences.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"seenProposerPreferences.js","sourceRoot":"","sources":["../../../src/chain/seenCache/seenProposerPreferences.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,MAAM,EAAC,MAAM,iBAAiB,CAAC;AAEvC;;GAEG;AACH,MAAM,OAAO,uBAAuB;IACjB,8BAA8B,GAAG,IAAI,MAAM,CAC1D,GAAG,EAAE,CAAC,IAAI,GAAG,EAA2B,CACzC,CAAC;IAEF,OAAO,CAAC,aAAsB,EAAE,YAAkB,EAAE,cAA8B,EAAW;QAC3F,OAAO,IAAI,CAAC,8BAA8B,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,GAAG,CAAC,aAAa,CAAC,KAAK,cAAc,CAAC;IAAA,CACrG;IAED,GAAG,CAAC,aAAsB,EAAE,YAAkB,EAAE,cAA8B,EAAQ;QACpF,IAAI,CAAC,8BAA8B,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;IAAA,CACnG;IAED;;;;OAIG;IACH,KAAK,CAAC,WAAiB,EAAQ;QAC7B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,8BAA8B,CAAC,IAAI,EAAE,EAAE,CAAC;YAC9D,IAAI,IAAI,GAAG,WAAW,EAAE,CAAC;gBACvB,IAAI,CAAC,8BAA8B,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;IAAA,CACF;CACF"}
@@ -1,32 +0,0 @@
1
- import {RootHex, Slot, ValidatorIndex} from "@lodestar/types";
2
- import {MapDef} from "@lodestar/utils";
3
-
4
- /**
5
- * Tracks signed proposer preferences we've already seen per (dependent_root, proposal_slot, validator_index).
6
- */
7
- export class SeenProposerPreferences {
8
- private readonly validatorByDependentRootBySlot = new MapDef<Slot, Map<RootHex, ValidatorIndex>>(
9
- () => new Map<RootHex, ValidatorIndex>()
10
- );
11
-
12
- isKnown(dependentRoot: RootHex, proposalSlot: Slot, validatorIndex: ValidatorIndex): boolean {
13
- return this.validatorByDependentRootBySlot.get(proposalSlot)?.get(dependentRoot) === validatorIndex;
14
- }
15
-
16
- add(dependentRoot: RootHex, proposalSlot: Slot, validatorIndex: ValidatorIndex): void {
17
- this.validatorByDependentRootBySlot.getOrDefault(proposalSlot).set(dependentRoot, validatorIndex);
18
- }
19
-
20
- /**
21
- * Entries are only load-bearing while `proposal_slot > current_slot`. Once the slot has
22
- * passed the `[IGNORE] proposal_slot > current_slot` gossip rule takes over, so drop them
23
- * on each slot tick.
24
- */
25
- prune(currentSlot: Slot): void {
26
- for (const slot of this.validatorByDependentRootBySlot.keys()) {
27
- if (slot < currentSlot) {
28
- this.validatorByDependentRootBySlot.delete(slot);
29
- }
30
- }
31
- }
32
- }