@aztec/p2p 0.0.1-commit.c0b82b2 → 0.0.1-commit.c2eed6949

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 (230) hide show
  1. package/README.md +129 -3
  2. package/dest/client/factory.d.ts +2 -2
  3. package/dest/client/factory.d.ts.map +1 -1
  4. package/dest/client/factory.js +22 -9
  5. package/dest/client/p2p_client.d.ts +1 -1
  6. package/dest/client/p2p_client.d.ts.map +1 -1
  7. package/dest/client/p2p_client.js +22 -34
  8. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +3 -3
  9. package/dest/config.d.ts +32 -11
  10. package/dest/config.d.ts.map +1 -1
  11. package/dest/config.js +86 -32
  12. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +4 -4
  13. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  14. package/dest/mem_pools/attestation_pool/attestation_pool.js +8 -4
  15. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +6 -6
  16. package/dest/mem_pools/instrumentation.d.ts +4 -2
  17. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  18. package/dest/mem_pools/instrumentation.js +16 -14
  19. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
  20. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
  21. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +2 -1
  22. package/dest/mem_pools/tx_pool/priority.d.ts +2 -2
  23. package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
  24. package/dest/mem_pools/tx_pool/priority.js +4 -4
  25. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
  26. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
  27. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +3 -1
  28. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
  29. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
  30. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +2 -1
  31. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +7 -1
  32. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -1
  33. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +1 -1
  34. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -1
  35. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +8 -6
  36. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +2 -2
  37. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -1
  38. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +2 -2
  39. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +9 -5
  40. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
  41. package/dest/mem_pools/tx_pool_v2/interfaces.js +2 -1
  42. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +25 -10
  43. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
  44. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +33 -10
  45. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +1 -1
  46. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
  47. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +26 -43
  48. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +4 -2
  49. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
  50. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +6 -0
  51. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +2 -1
  52. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
  53. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +24 -6
  54. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +1 -1
  55. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  56. package/dest/msg_validators/attestation_validator/attestation_validator.js +5 -4
  57. package/dest/msg_validators/clock_tolerance.d.ts +1 -1
  58. package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
  59. package/dest/msg_validators/clock_tolerance.js +4 -3
  60. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +6 -4
  61. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
  62. package/dest/msg_validators/proposal_validator/block_proposal_validator.js +10 -2
  63. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +6 -4
  64. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
  65. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +16 -2
  66. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -8
  67. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
  68. package/dest/msg_validators/proposal_validator/proposal_validator.js +53 -41
  69. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +2 -1
  70. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -1
  71. package/dest/msg_validators/tx_validator/allowed_public_setup.js +24 -20
  72. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts +17 -0
  73. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts.map +1 -0
  74. package/dest/msg_validators/tx_validator/allowed_setup_helpers.js +24 -0
  75. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts +9 -0
  76. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts.map +1 -0
  77. package/dest/msg_validators/tx_validator/contract_instance_validator.js +48 -0
  78. package/dest/msg_validators/tx_validator/data_validator.d.ts +1 -1
  79. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  80. package/dest/msg_validators/tx_validator/data_validator.js +35 -2
  81. package/dest/msg_validators/tx_validator/factory.d.ts +23 -4
  82. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  83. package/dest/msg_validators/tx_validator/factory.js +36 -10
  84. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +1 -1
  85. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -1
  86. package/dest/msg_validators/tx_validator/fee_payer_balance.js +6 -2
  87. package/dest/msg_validators/tx_validator/gas_validator.d.ts +13 -4
  88. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  89. package/dest/msg_validators/tx_validator/gas_validator.js +39 -9
  90. package/dest/msg_validators/tx_validator/index.d.ts +2 -1
  91. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  92. package/dest/msg_validators/tx_validator/index.js +1 -0
  93. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +1 -1
  94. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  95. package/dest/msg_validators/tx_validator/metadata_validator.js +4 -4
  96. package/dest/msg_validators/tx_validator/phases_validator.d.ts +22 -2
  97. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  98. package/dest/msg_validators/tx_validator/phases_validator.js +72 -24
  99. package/dest/services/discv5/discV5_service.d.ts +1 -1
  100. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  101. package/dest/services/discv5/discV5_service.js +4 -2
  102. package/dest/services/encoding.d.ts +5 -1
  103. package/dest/services/encoding.d.ts.map +1 -1
  104. package/dest/services/encoding.js +7 -1
  105. package/dest/services/libp2p/libp2p_service.d.ts +7 -9
  106. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  107. package/dest/services/libp2p/libp2p_service.js +166 -72
  108. package/dest/services/peer-manager/metrics.d.ts +3 -1
  109. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  110. package/dest/services/peer-manager/metrics.js +6 -0
  111. package/dest/services/peer-manager/peer_manager.d.ts +1 -1
  112. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  113. package/dest/services/peer-manager/peer_manager.js +6 -3
  114. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +11 -8
  115. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
  116. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +69 -65
  117. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +3 -2
  118. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
  119. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +5 -4
  120. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
  121. package/dest/services/reqresp/batch-tx-requester/missing_txs.js +13 -7
  122. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +3 -1
  123. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
  124. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +3 -0
  125. package/dest/services/reqresp/reqresp.d.ts +1 -1
  126. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  127. package/dest/services/reqresp/reqresp.js +17 -9
  128. package/dest/services/service.d.ts +7 -1
  129. package/dest/services/service.d.ts.map +1 -1
  130. package/dest/services/tx_collection/fast_tx_collection.d.ts +1 -4
  131. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
  132. package/dest/services/tx_collection/fast_tx_collection.js +57 -73
  133. package/dest/services/tx_collection/proposal_tx_collector.d.ts +6 -7
  134. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -1
  135. package/dest/services/tx_collection/proposal_tx_collector.js +4 -4
  136. package/dest/services/tx_collection/request_tracker.d.ts +53 -0
  137. package/dest/services/tx_collection/request_tracker.d.ts.map +1 -0
  138. package/dest/services/tx_collection/request_tracker.js +84 -0
  139. package/dest/services/tx_collection/slow_tx_collection.js +1 -1
  140. package/dest/services/tx_collection/tx_collection.d.ts +3 -6
  141. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  142. package/dest/test-helpers/make-test-p2p-clients.d.ts +1 -1
  143. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  144. package/dest/test-helpers/mock-pubsub.d.ts +6 -1
  145. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  146. package/dest/test-helpers/mock-pubsub.js +9 -1
  147. package/dest/test-helpers/reqresp-nodes.d.ts +1 -1
  148. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  149. package/dest/test-helpers/testbench-utils.d.ts +1 -1
  150. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  151. package/dest/test-helpers/testbench-utils.js +22 -3
  152. package/dest/testbench/p2p_client_testbench_worker.js +5 -4
  153. package/dest/testbench/worker_client_manager.d.ts +3 -1
  154. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  155. package/dest/testbench/worker_client_manager.js +6 -2
  156. package/dest/util.d.ts +9 -4
  157. package/dest/util.d.ts.map +1 -1
  158. package/dest/util.js +2 -9
  159. package/package.json +14 -14
  160. package/src/client/factory.ts +37 -13
  161. package/src/client/p2p_client.ts +22 -34
  162. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +4 -6
  163. package/src/config.ts +124 -34
  164. package/src/mem_pools/attestation_pool/attestation_pool.ts +8 -7
  165. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +6 -6
  166. package/src/mem_pools/instrumentation.ts +17 -13
  167. package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +2 -1
  168. package/src/mem_pools/tx_pool/priority.ts +4 -4
  169. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +3 -1
  170. package/src/mem_pools/tx_pool_v2/README.md +9 -1
  171. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +2 -1
  172. package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +11 -1
  173. package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +15 -6
  174. package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +2 -1
  175. package/src/mem_pools/tx_pool_v2/interfaces.ts +9 -4
  176. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +52 -12
  177. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +29 -43
  178. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +16 -1
  179. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +28 -6
  180. package/src/msg_validators/attestation_validator/README.md +49 -0
  181. package/src/msg_validators/attestation_validator/attestation_validator.ts +5 -4
  182. package/src/msg_validators/clock_tolerance.ts +4 -3
  183. package/src/msg_validators/proposal_validator/README.md +123 -0
  184. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +14 -4
  185. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +20 -7
  186. package/src/msg_validators/proposal_validator/proposal_validator.ts +69 -45
  187. package/src/msg_validators/tx_validator/README.md +5 -1
  188. package/src/msg_validators/tx_validator/allowed_public_setup.ts +22 -27
  189. package/src/msg_validators/tx_validator/allowed_setup_helpers.ts +31 -0
  190. package/src/msg_validators/tx_validator/contract_instance_validator.ts +56 -0
  191. package/src/msg_validators/tx_validator/data_validator.ts +42 -1
  192. package/src/msg_validators/tx_validator/factory.ts +43 -3
  193. package/src/msg_validators/tx_validator/fee_payer_balance.ts +6 -2
  194. package/src/msg_validators/tx_validator/gas_validator.ts +41 -8
  195. package/src/msg_validators/tx_validator/index.ts +1 -0
  196. package/src/msg_validators/tx_validator/metadata_validator.ts +12 -4
  197. package/src/msg_validators/tx_validator/phases_validator.ts +82 -27
  198. package/src/services/discv5/discV5_service.ts +4 -2
  199. package/src/services/encoding.ts +9 -1
  200. package/src/services/libp2p/libp2p_service.ts +164 -80
  201. package/src/services/peer-manager/metrics.ts +7 -0
  202. package/src/services/peer-manager/peer_manager.ts +7 -3
  203. package/src/services/reqresp/README.md +229 -0
  204. package/src/services/reqresp/batch-tx-requester/README.md +46 -7
  205. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +64 -69
  206. package/src/services/reqresp/batch-tx-requester/interface.ts +2 -1
  207. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +13 -6
  208. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +5 -0
  209. package/src/services/reqresp/reqresp.ts +19 -11
  210. package/src/services/service.ts +7 -0
  211. package/src/services/tx_collection/fast_tx_collection.ts +57 -83
  212. package/src/services/tx_collection/proposal_tx_collector.ts +8 -13
  213. package/src/services/tx_collection/request_tracker.ts +127 -0
  214. package/src/services/tx_collection/slow_tx_collection.ts +1 -1
  215. package/src/services/tx_collection/tx_collection.ts +3 -5
  216. package/src/test-helpers/make-test-p2p-clients.ts +1 -1
  217. package/src/test-helpers/mock-pubsub.ts +9 -0
  218. package/src/test-helpers/reqresp-nodes.ts +1 -1
  219. package/src/test-helpers/testbench-utils.ts +29 -3
  220. package/src/testbench/p2p_client_testbench_worker.ts +5 -6
  221. package/src/testbench/worker_client_manager.ts +13 -5
  222. package/src/util.ts +9 -13
  223. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +0 -23
  224. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +0 -1
  225. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +0 -212
  226. package/dest/services/tx_collection/missing_txs_tracker.d.ts +0 -32
  227. package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +0 -1
  228. package/dest/services/tx_collection/missing_txs_tracker.js +0 -27
  229. package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +0 -230
  230. package/src/services/tx_collection/missing_txs_tracker.ts +0 -52
@@ -1,5 +1,6 @@
1
1
  import type { EpochCacheInterface } from '@aztec/epoch-cache';
2
2
  import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
3
+ import { maxBy } from '@aztec/foundation/collection';
3
4
  import { Fr } from '@aztec/foundation/curves/bn254';
4
5
  import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
5
6
  import { RunningPromise } from '@aztec/foundation/running-promise';
@@ -17,8 +18,8 @@ import {
17
18
  type CheckpointProposalCore,
18
19
  type Gossipable,
19
20
  P2PMessage,
20
- type ValidationResult as P2PValidationResult,
21
21
  PeerErrorSeverity,
22
+ PeerErrorSeverityByHarshness,
22
23
  TopicType,
23
24
  createTopicString,
24
25
  getTopicsForConfig,
@@ -50,9 +51,10 @@ import { yamux } from '@chainsafe/libp2p-yamux';
50
51
  import { bootstrap } from '@libp2p/bootstrap';
51
52
  import { identify } from '@libp2p/identify';
52
53
  import { type Message, type MultiaddrConnection, type PeerId, TopicValidatorResult } from '@libp2p/interface';
53
- import type { ConnectionManager } from '@libp2p/interface-internal';
54
+ import type { AddressManager, ConnectionManager } from '@libp2p/interface-internal';
54
55
  import { mplex } from '@libp2p/mplex';
55
56
  import { tcp } from '@libp2p/tcp';
57
+ import { multiaddr } from '@multiformats/multiaddr';
56
58
  import { ENR } from '@nethermindeth/enr';
57
59
  import { createLibp2p } from 'libp2p';
58
60
 
@@ -129,7 +131,7 @@ type ValidationOutcome = { allPassed: true } | { allPassed: false; failure: Vali
129
131
  // REFACTOR: Unify with the type above
130
132
  type ReceivedMessageValidationResult<T, M = undefined> =
131
133
  | { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject>; metadata?: M }
132
- | { obj?: T; result: TopicValidatorResult.Reject; metadata?: M };
134
+ | { obj?: T; result: TopicValidatorResult.Reject; metadata?: M; severity: PeerErrorSeverity };
133
135
 
134
136
  /**
135
137
  * Lib P2P implementation of the P2PService interface.
@@ -173,6 +175,10 @@ export class LibP2PService extends WithTracer implements P2PService {
173
175
  private checkpointReceivedCallback: P2PCheckpointReceivedCallback;
174
176
 
175
177
  private gossipSubEventHandler: (e: CustomEvent<GossipsubMessage>) => void;
178
+ private ipChangedHandler?: (ip: string) => void;
179
+
180
+ /** Discovered public IP address (set when queryForIp is enabled and no static IP was configured). */
181
+ private discoveredP2pIp?: string;
176
182
 
177
183
  private instrumentation: P2PInstrumentation;
178
184
 
@@ -222,10 +228,12 @@ export class LibP2PService extends WithTracer implements P2PService {
222
228
  this.protocolVersion,
223
229
  );
224
230
 
225
- this.blockProposalValidator = new BlockProposalValidator(epochCache, { txsPermitted: !config.disableTransactions });
226
- this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, {
231
+ const proposalValidatorOpts = {
227
232
  txsPermitted: !config.disableTransactions,
228
- });
233
+ maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint,
234
+ };
235
+ this.blockProposalValidator = new BlockProposalValidator(epochCache, proposalValidatorOpts);
236
+ this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts);
229
237
  this.checkpointAttestationValidator = config.fishermanMode
230
238
  ? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
231
239
  : new CheckpointAttestationValidator(epochCache);
@@ -233,11 +241,11 @@ export class LibP2PService extends WithTracer implements P2PService {
233
241
  this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
234
242
 
235
243
  this.blockReceivedCallback = async (block: BlockProposal): Promise<boolean> => {
236
- this.logger.debug(
237
- `Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber} from peer.`,
244
+ this.logger.warn(
245
+ `Handler for block received not yet registered on P2P service. Received block ${block.blockNumber} for slot ${block.slotNumber} from peer.`,
238
246
  { p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier() },
239
247
  );
240
- return false;
248
+ return true;
241
249
  };
242
250
 
243
251
  this.checkpointReceivedCallback = (
@@ -439,8 +447,9 @@ export class LibP2PService extends WithTracer implements P2PService {
439
447
  topics: topicScoreParams,
440
448
  }),
441
449
  }) as (components: GossipSubComponents) => GossipSub,
442
- components: (components: { connectionManager: ConnectionManager }) => ({
450
+ components: (components: { connectionManager: ConnectionManager; addressManager: AddressManager }) => ({
443
451
  connectionManager: components.connectionManager,
452
+ addressManager: components.addressManager,
444
453
  }),
445
454
  },
446
455
  logger: createLibp2pComponentLogger(logger.module, logger.getBindings()),
@@ -499,10 +508,10 @@ export class LibP2PService extends WithTracer implements P2PService {
499
508
 
500
509
  // Get listen & announce addresses for logging
501
510
  const { p2pIp, p2pPort } = this.config;
502
- if (!p2pIp) {
511
+ if (!p2pIp && !this.config.queryForIp) {
503
512
  throw new Error('Announce address not provided.');
504
513
  }
505
- const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
514
+ const announceTcpMultiaddr = p2pIp ? convertToMultiaddr(p2pIp, p2pPort, 'tcp') : undefined;
506
515
 
507
516
  // Create request response protocol handlers
508
517
  const txHandler = reqRespTxHandler(this.mempools);
@@ -556,6 +565,31 @@ export class LibP2PService extends WithTracer implements P2PService {
556
565
  if (!this.config.p2pDiscoveryDisabled) {
557
566
  await this.peerDiscoveryService.start();
558
567
  }
568
+
569
+ // When queryForIp is enabled and no static IP was configured, bridge discv5 IP discovery to libp2p.
570
+ // Discv5 discovers our public IP via peer WHOAREYOU exchanges (enrUpdate=true) and emits 'ip:changed'.
571
+ // We confirm the discovered address in the libp2p AddressManager so it appears in getMultiaddrs()
572
+ // and is pushed to all connected peers via the identify protocol.
573
+ if (this.config.queryForIp && !p2pIp) {
574
+ this.ipChangedHandler = (ip: string) => {
575
+ const addressManager = this.node.services.components.addressManager;
576
+ const newAddr = multiaddr(convertToMultiaddr(ip, this.config.p2pPort, 'tcp'));
577
+
578
+ // Remove old discovered IP if one exists
579
+ if (this.discoveredP2pIp) {
580
+ const oldAddr = multiaddr(convertToMultiaddr(this.discoveredP2pIp, this.config.p2pPort, 'tcp'));
581
+ addressManager.removeObservedAddr(oldAddr);
582
+ }
583
+
584
+ addressManager.addObservedAddr(newAddr);
585
+ addressManager.confirmObservedAddr(newAddr);
586
+ // Store discovered IP
587
+ this.discoveredP2pIp = ip;
588
+ this.logger.info('Public IP discovered via discv5', { ip });
589
+ };
590
+ this.peerDiscoveryService.on('ip:changed', this.ipChangedHandler);
591
+ }
592
+
559
593
  this.discoveryRunningPromise = new RunningPromise(
560
594
  async () => {
561
595
  await this.peerManager.heartbeat();
@@ -568,7 +602,7 @@ export class LibP2PService extends WithTracer implements P2PService {
568
602
  this.logger.info(`Started P2P service`, {
569
603
  listen: this.config.listenAddress,
570
604
  port: this.config.p2pPort,
571
- announce: announceTcpMultiaddr,
605
+ announce: announceTcpMultiaddr ?? 'pending (queryForIp=true)',
572
606
  peerId: this.node.peerId.toString(),
573
607
  });
574
608
  }
@@ -581,6 +615,12 @@ export class LibP2PService extends WithTracer implements P2PService {
581
615
  // Remove gossip sub listener
582
616
  this.node.services.pubsub.removeEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
583
617
 
618
+ // Remove ip:changed listener if registered
619
+ if (this.ipChangedHandler) {
620
+ this.peerDiscoveryService.off('ip:changed', this.ipChangedHandler);
621
+ this.ipChangedHandler = undefined;
622
+ }
623
+
584
624
  // Stop peer manager
585
625
  this.logger.debug('Stopping peer manager...');
586
626
  await this.peerManager.stop();
@@ -750,6 +790,9 @@ export class LibP2PService extends WithTracer implements P2PService {
750
790
  if (!validator || !validator.addMessage(msgId)) {
751
791
  this.instrumentation.incMessagePrevalidationStatus(false, topicType);
752
792
  this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
793
+ if (topicType === TopicType.tx) {
794
+ this.logger.verbose(`Ignoring already-seen tx gossip message`, { msgId, source: source.toString() });
795
+ }
753
796
  return { result: false, topicType };
754
797
  }
755
798
 
@@ -876,30 +919,56 @@ export class LibP2PService extends WithTracer implements P2PService {
876
919
  source: PeerId,
877
920
  topicType: TopicType,
878
921
  ): Promise<ReceivedMessageValidationResult<T, M>> {
879
- let resultAndObj: ReceivedMessageValidationResult<T, M> = { result: TopicValidatorResult.Reject };
922
+ // Default to reject result with a penalty if validation function throws an error
923
+ let resultAndObj: ReceivedMessageValidationResult<T, M> = {
924
+ result: TopicValidatorResult.Reject,
925
+ severity: PeerErrorSeverity.MidToleranceError,
926
+ };
880
927
  const timer = new Timer();
881
928
  try {
882
929
  resultAndObj = await validationFunc();
883
930
  } catch (err) {
884
- this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
885
- this.logger.error(`Error deserializing and validating gossipsub message`, err, {
886
- msgId,
887
- source: source.toString(),
888
- topicType,
889
- });
931
+ this.logger.error(`Error validating gossipsub message`, err, { msgId, source: source.toString(), topicType });
890
932
  }
891
933
 
892
934
  if (resultAndObj.result === TopicValidatorResult.Accept) {
935
+ this.logger.debug(`Message ${topicType} accepted by validator`, { msgId, source: source.toString(), topicType });
893
936
  this.instrumentation.recordMessageValidation(topicType, timer);
937
+ } else if (resultAndObj.result === TopicValidatorResult.Reject) {
938
+ this.logger.warn(`Message ${topicType} rejected by validator with severity ${resultAndObj.severity}`, {
939
+ msgId,
940
+ source: source.toString(),
941
+ topicType,
942
+ severity: resultAndObj.severity,
943
+ });
944
+ this.peerManager.penalizePeer(source, resultAndObj.severity);
945
+ } else {
946
+ this.logger.trace(`Message ${topicType} ignored by validator`, { msgId, source: source.toString(), topicType });
894
947
  }
895
948
 
896
949
  this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result);
897
950
  return resultAndObj;
898
951
  }
899
952
 
953
+ private tryDeserialize<T>(deserializeFunc: () => T, msgId: string, source: PeerId): T | undefined {
954
+ try {
955
+ return deserializeFunc();
956
+ } catch (err) {
957
+ this.logger.warn(`Failed to deserialize gossipsub message from buffer`, {
958
+ err,
959
+ msgId,
960
+ source: source.toString(),
961
+ });
962
+ return undefined;
963
+ }
964
+ }
965
+
900
966
  protected async handleGossipedTx(payloadData: Buffer, msgId: string, source: PeerId) {
901
967
  const validationFunc: () => Promise<ReceivedMessageValidationResult<Tx>> = async () => {
902
- const tx = Tx.fromBuffer(payloadData);
968
+ const tx = this.tryDeserialize(() => Tx.fromBuffer(payloadData), msgId, source);
969
+ if (!tx) {
970
+ return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.LowToleranceError };
971
+ }
903
972
 
904
973
  const currentBlockNumber = await this.archiver.getBlockNumber();
905
974
  const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
@@ -919,13 +988,20 @@ export class LibP2PService extends WithTracer implements P2PService {
919
988
  severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
920
989
  }
921
990
 
922
- this.peerManager.penalizePeer(source, severity);
923
- return { result: TopicValidatorResult.Reject };
991
+ this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 1 validation failed`, {
992
+ validator: name,
993
+ severity,
994
+ source: source.toString(),
995
+ });
996
+ return { result: TopicValidatorResult.Reject, severity };
924
997
  }
925
998
 
926
999
  // Pool pre-check: see if the pool would accept this tx before doing expensive proof verification
927
1000
  const canAdd = await this.mempools.txPool.canAddPendingTx(tx);
928
1001
  if (canAdd === 'ignored') {
1002
+ this.logger.verbose(`Ignoring gossiped tx ${tx.getTxHash().toString()}: pool pre-check returned ignored`, {
1003
+ source: source.toString(),
1004
+ });
929
1005
  return { result: TopicValidatorResult.Ignore, obj: tx };
930
1006
  }
931
1007
 
@@ -933,9 +1009,13 @@ export class LibP2PService extends WithTracer implements P2PService {
933
1009
  const secondStageValidators = this.createSecondStageMessageValidators();
934
1010
  const secondStageOutcome = await this.runValidations(tx, secondStageValidators);
935
1011
  if (!secondStageOutcome.allPassed) {
936
- const { severity } = secondStageOutcome.failure;
937
- this.peerManager.penalizePeer(source, severity);
938
- return { result: TopicValidatorResult.Reject };
1012
+ const { severity, name } = secondStageOutcome.failure;
1013
+ this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 2 validation failed`, {
1014
+ validator: name,
1015
+ severity,
1016
+ source: source.toString(),
1017
+ });
1018
+ return { result: TopicValidatorResult.Reject, severity };
939
1019
  }
940
1020
 
941
1021
  // Pool add: persist the tx
@@ -945,7 +1025,7 @@ export class LibP2PService extends WithTracer implements P2PService {
945
1025
  const wasAccepted = addResult.accepted.some(h => h.equals(txHash));
946
1026
  const wasIgnored = addResult.ignored.some(h => h.equals(txHash));
947
1027
 
948
- this.logger.trace(`Validate propagated tx`, {
1028
+ this.logger.verbose(`Validate propagated tx ${txHash.toString()}`, {
949
1029
  wasAccepted,
950
1030
  wasIgnored,
951
1031
  [Attributes.P2P_ID]: source.toString(),
@@ -956,7 +1036,11 @@ export class LibP2PService extends WithTracer implements P2PService {
956
1036
  } else if (wasIgnored) {
957
1037
  return { result: TopicValidatorResult.Ignore, obj: tx };
958
1038
  } else {
959
- return { result: TopicValidatorResult.Reject };
1039
+ this.logger.warn(`Gossiped tx ${txHash.toString()} unexpectedly rejected by pool`, {
1040
+ source: source.toString(),
1041
+ txHash: txHash.toString(),
1042
+ });
1043
+ return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.HighToleranceError };
960
1044
  }
961
1045
  };
962
1046
 
@@ -986,7 +1070,16 @@ export class LibP2PService extends WithTracer implements P2PService {
986
1070
  source: PeerId,
987
1071
  ): Promise<void> {
988
1072
  const { result, obj: attestation } = await this.validateReceivedMessage<CheckpointAttestation>(
989
- () => this.validateAndStoreCheckpointAttestation(source, CheckpointAttestation.fromBuffer(payloadData)),
1073
+ () => {
1074
+ const attestation = this.tryDeserialize(() => CheckpointAttestation.fromBuffer(payloadData), msgId, source);
1075
+ if (!attestation) {
1076
+ return Promise.resolve({
1077
+ result: TopicValidatorResult.Reject,
1078
+ severity: PeerErrorSeverity.LowToleranceError,
1079
+ });
1080
+ }
1081
+ return this.validateAndStoreCheckpointAttestation(source, attestation);
1082
+ },
990
1083
  msgId,
991
1084
  source,
992
1085
  TopicType.checkpoint_attestation,
@@ -1019,8 +1112,7 @@ export class LibP2PService extends WithTracer implements P2PService {
1019
1112
 
1020
1113
  if (validationResult.result === 'reject') {
1021
1114
  this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
1022
- this.peerManager.penalizePeer(peerId, validationResult.severity);
1023
- return { result: TopicValidatorResult.Reject };
1115
+ return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
1024
1116
  }
1025
1117
 
1026
1118
  if (validationResult.result === 'ignore') {
@@ -1046,16 +1138,16 @@ export class LibP2PService extends WithTracer implements P2PService {
1046
1138
  return { result: TopicValidatorResult.Ignore, obj: attestation };
1047
1139
  }
1048
1140
 
1049
- // Could not add (cap reached for signer), no need to re-broadcast
1141
+ // Could not add (cap reached for signer), penalize and do not re-broadcast
1050
1142
  if (!added) {
1051
- this.logger.warn(`Dropping checkpoint attestation due to cap`, {
1143
+ this.logger.warn(`Rejecting checkpoint attestation due to cap`, {
1052
1144
  slot: slot.toString(),
1053
1145
  archive: attestation.archive.toString(),
1054
1146
  source: peerId.toString(),
1055
1147
  attester: attestation.getSender()?.toString(),
1056
1148
  count,
1057
1149
  });
1058
- return { result: TopicValidatorResult.Ignore, obj: attestation };
1150
+ return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.HighToleranceError };
1059
1151
  }
1060
1152
 
1061
1153
  // Check if this is a duplicate attestation (signer attested to a different proposal at the same slot)
@@ -1110,8 +1202,7 @@ export class LibP2PService extends WithTracer implements P2PService {
1110
1202
 
1111
1203
  if (validationResult.result === 'reject') {
1112
1204
  this.logger.warn(`Penalizing peer ${peerId} for block proposal validation failure`);
1113
- this.peerManager.penalizePeer(peerId, validationResult.severity);
1114
- return { result: TopicValidatorResult.Reject };
1205
+ return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
1115
1206
  }
1116
1207
 
1117
1208
  if (validationResult.result === 'ignore') {
@@ -1135,7 +1226,6 @@ export class LibP2PService extends WithTracer implements P2PService {
1135
1226
 
1136
1227
  // Too many blocks received for this slot and index, penalize peer and do not re-broadcast
1137
1228
  if (!added) {
1138
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
1139
1229
  this.logger.warn(`Penalizing peer for block proposal exceeding per-position cap`, {
1140
1230
  ...block.toBlockInfo(),
1141
1231
  indexWithinCheckpoint: block.indexWithinCheckpoint,
@@ -1143,7 +1233,11 @@ export class LibP2PService extends WithTracer implements P2PService {
1143
1233
  proposer: block.getSender()?.toString(),
1144
1234
  source: peerId.toString(),
1145
1235
  });
1146
- return { result: TopicValidatorResult.Reject, metadata: { isEquivocated } };
1236
+ return {
1237
+ result: TopicValidatorResult.Reject,
1238
+ metadata: { isEquivocated },
1239
+ severity: PeerErrorSeverity.HighToleranceError,
1240
+ };
1147
1241
  }
1148
1242
 
1149
1243
  // If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
@@ -1188,7 +1282,7 @@ export class LibP2PService extends WithTracer implements P2PService {
1188
1282
  // Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
1189
1283
  const isValid = await this.blockReceivedCallback(block, sender);
1190
1284
  if (!isValid) {
1191
- this.logger.warn(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
1285
+ this.logger.info(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
1192
1286
  }
1193
1287
  }
1194
1288
 
@@ -1236,8 +1330,7 @@ export class LibP2PService extends WithTracer implements P2PService {
1236
1330
 
1237
1331
  if (validationResult.result === 'reject') {
1238
1332
  this.logger.warn(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
1239
- this.peerManager.penalizePeer(peerId, validationResult.severity);
1240
- return { result: TopicValidatorResult.Reject };
1333
+ return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
1241
1334
  }
1242
1335
 
1243
1336
  if (validationResult.result === 'ignore') {
@@ -1252,20 +1345,21 @@ export class LibP2PService extends WithTracer implements P2PService {
1252
1345
  [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
1253
1346
  [Attributes.P2P_ID]: peerId.toString(),
1254
1347
  });
1255
- const {
1256
- result,
1257
- obj,
1258
- metadata: { isEquivocated } = {},
1259
- } = await this.validateAndStoreBlockProposal(peerId, blockProposal);
1260
- if (result === TopicValidatorResult.Reject || !obj || isEquivocated) {
1348
+ const blockProposalResult = await this.validateAndStoreBlockProposal(peerId, blockProposal);
1349
+ const { obj, metadata: { isEquivocated } = {} } = blockProposalResult;
1350
+ if (blockProposalResult.result === TopicValidatorResult.Reject || !obj || isEquivocated) {
1261
1351
  this.logger.debug(`Rejecting checkpoint due to invalid last block proposal`, {
1262
1352
  [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
1263
1353
  [Attributes.P2P_ID]: peerId.toString(),
1264
1354
  isEquivocated,
1265
- result,
1355
+ result: blockProposalResult.result,
1266
1356
  });
1267
- return { result: TopicValidatorResult.Reject };
1268
- } else if (result === TopicValidatorResult.Accept && obj && !isEquivocated) {
1357
+ return {
1358
+ result: TopicValidatorResult.Reject,
1359
+ severity:
1360
+ 'severity' in blockProposalResult ? blockProposalResult.severity : PeerErrorSeverity.MidToleranceError,
1361
+ };
1362
+ } else if (blockProposalResult.result === TopicValidatorResult.Accept && obj && !isEquivocated) {
1269
1363
  processBlock = true;
1270
1364
  }
1271
1365
  }
@@ -1292,13 +1386,17 @@ export class LibP2PService extends WithTracer implements P2PService {
1292
1386
  // Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast
1293
1387
  // Note: We still return the checkpoint obj so the lastBlock can be processed if valid
1294
1388
  if (!added) {
1295
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
1296
1389
  this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
1297
1390
  ...checkpoint.toCheckpointInfo(),
1298
1391
  count,
1299
1392
  source: peerId.toString(),
1300
1393
  });
1301
- return { result: TopicValidatorResult.Reject, obj: checkpoint, metadata: { isEquivocated, processBlock } };
1394
+ return {
1395
+ result: TopicValidatorResult.Reject,
1396
+ obj: checkpoint,
1397
+ metadata: { isEquivocated, processBlock },
1398
+ severity: PeerErrorSeverity.HighToleranceError,
1399
+ };
1302
1400
  }
1303
1401
 
1304
1402
  // If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
@@ -1617,8 +1715,12 @@ export class LibP2PService extends WithTracer implements P2PService {
1617
1715
  nextSlotTimestamp: UInt64,
1618
1716
  ): Promise<Record<string, TransactionValidator>> {
1619
1717
  const gasFees = await this.getGasFees(currentBlockNumber);
1620
- const allowedInSetup = this.config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions());
1718
+ const allowedInSetup = [
1719
+ ...(await getDefaultAllowedSetupFunctions()),
1720
+ ...(this.config.txPublicSetupAllowListExtend ?? []),
1721
+ ];
1621
1722
  const blockNumber = BlockNumber(currentBlockNumber + 1);
1723
+ const l1Constants = await this.archiver.getL1Constants();
1622
1724
 
1623
1725
  return createFirstStageTxValidationsForGossipedTransactions(
1624
1726
  nextSlotTimestamp,
@@ -1632,6 +1734,11 @@ export class LibP2PService extends WithTracer implements P2PService {
1632
1734
  !this.config.disableTransactions,
1633
1735
  allowedInSetup,
1634
1736
  this.logger.getBindings(),
1737
+ {
1738
+ rollupManaLimit: l1Constants.rollupManaLimit,
1739
+ maxBlockL2Gas: this.config.validateMaxL2BlockGas,
1740
+ maxBlockDAGas: this.config.validateMaxDABlockGas,
1741
+ },
1635
1742
  );
1636
1743
  }
1637
1744
 
@@ -1657,8 +1764,10 @@ export class LibP2PService extends WithTracer implements P2PService {
1657
1764
 
1658
1765
  // A promise that resolves when all validations have been run
1659
1766
  const allValidations = await Promise.all(validationPromises);
1660
- const failed = allValidations.find(x => !x.isValid);
1661
- if (failed) {
1767
+ const failures = allValidations.filter(x => !x.isValid);
1768
+ if (failures.length > 0) {
1769
+ // Pick the most severe failure (lowest tolerance = harshest penalty)
1770
+ const failed = maxBy(failures, f => PeerErrorSeverityByHarshness.indexOf(f.severity))!;
1662
1771
  return {
1663
1772
  allPassed: false,
1664
1773
  failure: {
@@ -1711,31 +1820,6 @@ export class LibP2PService extends WithTracer implements P2PService {
1711
1820
  return PeerErrorSeverity.HighToleranceError;
1712
1821
  }
1713
1822
 
1714
- /**
1715
- * Validate a checkpoint attestation.
1716
- *
1717
- * @param attestation - The checkpoint attestation to validate.
1718
- * @returns True if the checkpoint attestation is valid, false otherwise.
1719
- */
1720
- @trackSpan('Libp2pService.validateCheckpointAttestation', async (_, attestation) => ({
1721
- [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
1722
- [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
1723
- [Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then(i => i.toString()),
1724
- }))
1725
- public async validateCheckpointAttestation(
1726
- peerId: PeerId,
1727
- attestation: CheckpointAttestation,
1728
- ): Promise<P2PValidationResult> {
1729
- const result = await this.checkpointAttestationValidator.validate(attestation);
1730
-
1731
- if (result.result === 'reject') {
1732
- this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
1733
- this.peerManager.penalizePeer(peerId, result.severity);
1734
- }
1735
-
1736
- return result;
1737
- }
1738
-
1739
1823
  public getPeerScore(peerId: PeerId): number {
1740
1824
  return this.node.services.pubsub.score.score(peerId.toString());
1741
1825
  }
@@ -18,6 +18,7 @@ export class PeerManagerMetrics {
18
18
  private sentGoodbyes: UpDownCounter;
19
19
  private receivedGoodbyes: UpDownCounter;
20
20
  private peerCount: Gauge;
21
+ private healthyPeerCount: Gauge;
21
22
  private lowScoreDisconnects: UpDownCounter;
22
23
  private peerConnectionDuration: Histogram;
23
24
 
@@ -49,6 +50,7 @@ export class PeerManagerMetrics {
49
50
  goodbyeReasonAttrs,
50
51
  );
51
52
  this.peerCount = meter.createGauge(Metrics.PEER_MANAGER_PEER_COUNT);
53
+ this.healthyPeerCount = meter.createGauge(Metrics.PEER_MANAGER_HEALTHY_PEER_COUNT);
52
54
  this.lowScoreDisconnects = createUpDownCounterWithDefault(meter, Metrics.PEER_MANAGER_LOW_SCORE_DISCONNECTS, {
53
55
  [Attributes.P2P_PEER_SCORE_STATE]: ['Banned', 'Disconnect'],
54
56
  });
@@ -67,6 +69,10 @@ export class PeerManagerMetrics {
67
69
  this.peerCount.record(count);
68
70
  }
69
71
 
72
+ public recordHealthyPeerCount(count: number) {
73
+ this.healthyPeerCount.record(count);
74
+ }
75
+
70
76
  public recordLowScoreDisconnect(scoreState: 'Banned' | 'Disconnect') {
71
77
  this.lowScoreDisconnects.add(1, { [Attributes.P2P_PEER_SCORE_STATE]: scoreState });
72
78
  }
@@ -79,6 +85,7 @@ export class PeerManagerMetrics {
79
85
  const connectedAt = this.peerConnectedAt.get(id.toString());
80
86
  if (connectedAt) {
81
87
  this.peerConnectionDuration.record(Date.now() - connectedAt);
88
+ this.peerConnectedAt.delete(id.toString());
82
89
  }
83
90
  }
84
91
  }
@@ -32,7 +32,7 @@ import { PeerScoreState, type PeerScoring } from './peer_scoring.js';
32
32
  const MAX_DIAL_ATTEMPTS = 3;
33
33
  const MAX_CACHED_PEERS = 100;
34
34
  const MAX_CACHED_PEER_AGE_MS = 5 * 60 * 1000; // 5 minutes
35
- const FAILED_PEER_BAN_TIME_MS = 5 * 60 * 1000; // 5 minutes timeout after failing MAX_DIAL_ATTEMPTS
35
+ const DEFAULT_FAILED_PEER_BAN_TIME_MS = 5 * 60 * 1000; // 5 minutes timeout after failing MAX_DIAL_ATTEMPTS
36
36
  const GOODBYE_DIAL_TIMEOUT_MS = 1000;
37
37
  const FAILED_AUTH_HANDSHAKE_EXPIRY_MS = 60 * 60 * 1000; // 1 hour
38
38
 
@@ -515,7 +515,8 @@ export class PeerManager implements PeerManagerInterface {
515
515
  ...this.peerScoring.getStats(),
516
516
  });
517
517
 
518
- this.metrics.recordPeerCount(healthyConnections.length);
518
+ this.metrics.recordPeerCount(connections.length);
519
+ this.metrics.recordHealthyPeerCount(healthyConnections.length);
519
520
 
520
521
  // Exit if no peers to connect
521
522
  if (peersToConnect <= 0) {
@@ -775,7 +776,8 @@ export class PeerManager implements PeerManagerInterface {
775
776
  // Add to timed out peers
776
777
  this.timedOutPeers.set(id, {
777
778
  peerId: id,
778
- timeoutUntilMs: this.dateProvider.now() + FAILED_PEER_BAN_TIME_MS,
779
+ timeoutUntilMs:
780
+ this.dateProvider.now() + (this.config.peerFailedBanTimeMs ?? DEFAULT_FAILED_PEER_BAN_TIME_MS),
779
781
  });
780
782
  }
781
783
  }
@@ -937,6 +939,8 @@ export class PeerManager implements PeerManagerInterface {
937
939
  `Received auth for validator ${sender.toString()} from peer ${peerIdString}, but this validator is already authenticated to peer ${peerForAddress.toString()}`,
938
940
  { ...logData, address: sender.toString() },
939
941
  );
942
+ this.markAuthHandshakeFailed(peerId);
943
+ this.markPeerForDisconnect(peerId);
940
944
  return;
941
945
  }
942
946