@aztec/p2p 0.0.1-commit.5de5ca79e → 0.0.1-commit.6201a7b05

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 (257) hide show
  1. package/dest/client/factory.d.ts +3 -2
  2. package/dest/client/factory.d.ts.map +1 -1
  3. package/dest/client/factory.js +22 -20
  4. package/dest/client/interface.d.ts +9 -2
  5. package/dest/client/interface.d.ts.map +1 -1
  6. package/dest/client/p2p_client.d.ts +3 -2
  7. package/dest/client/p2p_client.d.ts.map +1 -1
  8. package/dest/client/p2p_client.js +30 -10
  9. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +20 -7
  10. package/dest/config.d.ts +106 -99
  11. package/dest/config.d.ts.map +1 -1
  12. package/dest/config.js +16 -7
  13. package/dest/errors/p2p-service.error.d.ts +9 -0
  14. package/dest/errors/p2p-service.error.d.ts.map +1 -0
  15. package/dest/errors/p2p-service.error.js +10 -0
  16. package/dest/index.d.ts +1 -2
  17. package/dest/index.d.ts.map +1 -1
  18. package/dest/index.js +0 -1
  19. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +4 -2
  20. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  21. package/dest/mem_pools/attestation_pool/attestation_pool.js +8 -5
  22. package/dest/mem_pools/attestation_pool/mocks.d.ts +1 -1
  23. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  24. package/dest/mem_pools/attestation_pool/mocks.js +6 -4
  25. package/dest/mem_pools/index.d.ts +1 -2
  26. package/dest/mem_pools/index.d.ts.map +1 -1
  27. package/dest/mem_pools/instrumentation.d.ts +1 -1
  28. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  29. package/dest/mem_pools/instrumentation.js +17 -1
  30. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +2 -1
  31. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
  32. package/dest/mem_pools/tx_pool_v2/eviction/index.js +1 -0
  33. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts +16 -0
  34. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts.map +1 -0
  35. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.js +62 -0
  36. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +2 -2
  37. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +4 -1
  38. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
  39. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +5 -2
  40. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
  41. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +13 -6
  42. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +1 -1
  43. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
  44. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +2 -1
  45. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +9 -3
  46. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  47. package/dest/msg_validators/attestation_validator/attestation_validator.js +34 -10
  48. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +7 -3
  49. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
  50. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +2 -2
  51. package/dest/msg_validators/clock_tolerance.d.ts +12 -1
  52. package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
  53. package/dest/msg_validators/clock_tolerance.js +57 -0
  54. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +4 -2
  55. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
  56. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +4 -2
  57. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
  58. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +6 -2
  59. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
  60. package/dest/msg_validators/proposal_validator/proposal_validator.js +32 -9
  61. package/dest/msg_validators/tx_validator/archive_cache.js +1 -1
  62. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts +9 -0
  63. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts.map +1 -0
  64. package/dest/msg_validators/tx_validator/contract_instance_validator.js +48 -0
  65. package/dest/msg_validators/tx_validator/data_validator.d.ts +1 -1
  66. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  67. package/dest/msg_validators/tx_validator/data_validator.js +35 -2
  68. package/dest/msg_validators/tx_validator/factory.d.ts +2 -2
  69. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  70. package/dest/msg_validators/tx_validator/factory.js +11 -5
  71. package/dest/msg_validators/tx_validator/gas_validator.d.ts +36 -4
  72. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  73. package/dest/msg_validators/tx_validator/gas_validator.js +50 -33
  74. package/dest/msg_validators/tx_validator/phases_validator.js +1 -1
  75. package/dest/services/data_store.d.ts +1 -1
  76. package/dest/services/data_store.d.ts.map +1 -1
  77. package/dest/services/data_store.js +5 -5
  78. package/dest/services/dummy_service.d.ts +6 -3
  79. package/dest/services/dummy_service.d.ts.map +1 -1
  80. package/dest/services/dummy_service.js +6 -1
  81. package/dest/services/gossipsub/topic_score_params.d.ts +13 -2
  82. package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
  83. package/dest/services/gossipsub/topic_score_params.js +21 -4
  84. package/dest/services/libp2p/instrumentation.d.ts +3 -1
  85. package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
  86. package/dest/services/libp2p/instrumentation.js +14 -0
  87. package/dest/services/libp2p/libp2p_service.d.ts +20 -21
  88. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  89. package/dest/services/libp2p/libp2p_service.js +151 -110
  90. package/dest/services/peer-manager/peer_manager.d.ts +6 -2
  91. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  92. package/dest/services/peer-manager/peer_manager.js +33 -8
  93. package/dest/services/peer-manager/peer_scoring.d.ts +7 -2
  94. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  95. package/dest/services/peer-manager/peer_scoring.js +32 -10
  96. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +1 -1
  97. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
  98. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +3 -0
  99. package/dest/services/reqresp/config.d.ts +3 -3
  100. package/dest/services/reqresp/config.d.ts.map +1 -1
  101. package/dest/services/reqresp/interface.d.ts +14 -9
  102. package/dest/services/reqresp/interface.d.ts.map +1 -1
  103. package/dest/services/reqresp/interface.js +10 -11
  104. package/dest/services/reqresp/metrics.d.ts +1 -1
  105. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  106. package/dest/services/reqresp/metrics.js +0 -1
  107. package/dest/services/reqresp/protocols/index.d.ts +1 -2
  108. package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
  109. package/dest/services/reqresp/protocols/index.js +0 -1
  110. package/dest/services/reqresp/protocols/tx.d.ts +1 -1
  111. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  112. package/dest/services/reqresp/protocols/tx.js +1 -3
  113. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +5 -4
  114. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
  115. package/dest/services/reqresp/rate-limiter/rate_limiter.js +10 -8
  116. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
  117. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
  118. package/dest/services/reqresp/rate-limiter/rate_limits.js +0 -10
  119. package/dest/services/reqresp/reqresp.d.ts +4 -2
  120. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  121. package/dest/services/reqresp/reqresp.js +11 -2
  122. package/dest/services/service.d.ts +5 -2
  123. package/dest/services/service.d.ts.map +1 -1
  124. package/dest/services/tx_collection/file_store_tx_source.d.ts +5 -4
  125. package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -1
  126. package/dest/services/tx_collection/file_store_tx_source.js +39 -29
  127. package/dest/services/tx_collection/tx_source.d.ts +6 -5
  128. package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
  129. package/dest/services/tx_collection/tx_source.js +9 -7
  130. package/dest/test-helpers/make-test-p2p-clients.d.ts +1 -1
  131. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  132. package/dest/test-helpers/make-test-p2p-clients.js +4 -1
  133. package/dest/test-helpers/mock-pubsub.d.ts +11 -3
  134. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  135. package/dest/test-helpers/mock-pubsub.js +36 -11
  136. package/dest/test-helpers/reqresp-nodes.d.ts +1 -1
  137. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  138. package/dest/test-helpers/reqresp-nodes.js +5 -3
  139. package/dest/test-helpers/testbench-utils.d.ts +1 -1
  140. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  141. package/dest/test-helpers/testbench-utils.js +1 -0
  142. package/dest/testbench/p2p_client_testbench_worker.d.ts +1 -1
  143. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  144. package/dest/testbench/p2p_client_testbench_worker.js +72 -17
  145. package/dest/testbench/worker_client_manager.d.ts +8 -1
  146. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  147. package/dest/testbench/worker_client_manager.js +49 -1
  148. package/package.json +14 -14
  149. package/src/client/factory.ts +31 -21
  150. package/src/client/interface.ts +9 -1
  151. package/src/client/p2p_client.ts +34 -11
  152. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +19 -6
  153. package/src/config.ts +27 -7
  154. package/src/errors/p2p-service.error.ts +11 -0
  155. package/src/index.ts +0 -1
  156. package/src/mem_pools/attestation_pool/attestation_pool.ts +9 -5
  157. package/src/mem_pools/attestation_pool/mocks.ts +13 -8
  158. package/src/mem_pools/index.ts +0 -3
  159. package/src/mem_pools/instrumentation.ts +5 -1
  160. package/src/mem_pools/tx_pool_v2/eviction/index.ts +1 -0
  161. package/src/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.ts +65 -0
  162. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +3 -3
  163. package/src/mem_pools/tx_pool_v2/interfaces.ts +3 -0
  164. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +20 -8
  165. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +2 -0
  166. package/src/msg_validators/attestation_validator/attestation_validator.ts +38 -7
  167. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +12 -2
  168. package/src/msg_validators/clock_tolerance.ts +75 -0
  169. package/src/msg_validators/proposal_validator/README.md +1 -1
  170. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +10 -2
  171. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +15 -2
  172. package/src/msg_validators/proposal_validator/proposal_validator.ts +33 -7
  173. package/src/msg_validators/tx_validator/README.md +11 -3
  174. package/src/msg_validators/tx_validator/archive_cache.ts +1 -1
  175. package/src/msg_validators/tx_validator/contract_instance_validator.ts +56 -0
  176. package/src/msg_validators/tx_validator/data_validator.ts +42 -1
  177. package/src/msg_validators/tx_validator/factory.ts +10 -1
  178. package/src/msg_validators/tx_validator/gas_validator.ts +82 -33
  179. package/src/msg_validators/tx_validator/phases_validator.ts +1 -1
  180. package/src/services/data_store.ts +5 -13
  181. package/src/services/dummy_service.ts +8 -2
  182. package/src/services/gossipsub/topic_score_params.ts +36 -4
  183. package/src/services/libp2p/instrumentation.ts +14 -0
  184. package/src/services/libp2p/libp2p_service.ts +155 -117
  185. package/src/services/peer-manager/peer_manager.ts +38 -8
  186. package/src/services/peer-manager/peer_scoring.ts +27 -5
  187. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +3 -0
  188. package/src/services/reqresp/config.ts +2 -2
  189. package/src/services/reqresp/interface.ts +21 -11
  190. package/src/services/reqresp/metrics.ts +0 -1
  191. package/src/services/reqresp/protocols/index.ts +0 -1
  192. package/src/services/reqresp/protocols/tx.ts +1 -3
  193. package/src/services/reqresp/rate-limiter/rate_limiter.ts +13 -9
  194. package/src/services/reqresp/rate-limiter/rate_limits.ts +0 -10
  195. package/src/services/reqresp/reqresp.ts +18 -1
  196. package/src/services/service.ts +6 -1
  197. package/src/services/tx_collection/file_store_tx_source.ts +43 -31
  198. package/src/services/tx_collection/tx_source.ts +8 -7
  199. package/src/test-helpers/make-test-p2p-clients.ts +2 -0
  200. package/src/test-helpers/mock-pubsub.ts +34 -5
  201. package/src/test-helpers/reqresp-nodes.ts +4 -2
  202. package/src/test-helpers/testbench-utils.ts +1 -0
  203. package/src/testbench/p2p_client_testbench_worker.ts +73 -12
  204. package/src/testbench/worker_client_manager.ts +55 -1
  205. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +0 -125
  206. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +0 -1
  207. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +0 -596
  208. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +0 -32
  209. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +0 -1
  210. package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +0 -112
  211. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +0 -157
  212. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +0 -1
  213. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +0 -52
  214. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +0 -16
  215. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +0 -1
  216. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +0 -123
  217. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +0 -17
  218. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +0 -1
  219. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +0 -84
  220. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +0 -19
  221. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +0 -1
  222. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +0 -78
  223. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +0 -26
  224. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +0 -1
  225. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +0 -84
  226. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +0 -25
  227. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +0 -1
  228. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +0 -57
  229. package/dest/mem_pools/tx_pool/index.d.ts +0 -3
  230. package/dest/mem_pools/tx_pool/index.d.ts.map +0 -1
  231. package/dest/mem_pools/tx_pool/index.js +0 -2
  232. package/dest/mem_pools/tx_pool/priority.d.ts +0 -12
  233. package/dest/mem_pools/tx_pool/priority.d.ts.map +0 -1
  234. package/dest/mem_pools/tx_pool/priority.js +0 -15
  235. package/dest/mem_pools/tx_pool/tx_pool.d.ts +0 -127
  236. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +0 -1
  237. package/dest/mem_pools/tx_pool/tx_pool.js +0 -3
  238. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +0 -7
  239. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +0 -1
  240. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +0 -402
  241. package/dest/services/reqresp/protocols/block.d.ts +0 -9
  242. package/dest/services/reqresp/protocols/block.d.ts.map +0 -1
  243. package/dest/services/reqresp/protocols/block.js +0 -32
  244. package/src/mem_pools/tx_pool/README.md +0 -270
  245. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +0 -746
  246. package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +0 -132
  247. package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +0 -208
  248. package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +0 -163
  249. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +0 -104
  250. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +0 -93
  251. package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +0 -106
  252. package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +0 -75
  253. package/src/mem_pools/tx_pool/index.ts +0 -2
  254. package/src/mem_pools/tx_pool/priority.ts +0 -20
  255. package/src/mem_pools/tx_pool/tx_pool.ts +0 -141
  256. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +0 -321
  257. package/src/services/reqresp/protocols/block.ts +0 -37
@@ -1,5 +1,6 @@
1
1
  import { median } from '@aztec/foundation/collection';
2
2
  import { createLogger } from '@aztec/foundation/log';
3
+ import { DateProvider } from '@aztec/foundation/timer';
3
4
  import { PeerErrorSeverity } from '@aztec/stdlib/p2p';
4
5
  import {
5
6
  Attributes,
@@ -54,6 +55,7 @@ export enum PeerScoreState {
54
55
  // TODO: move into config / constants
55
56
  const MIN_SCORE_BEFORE_BAN = -100;
56
57
  const MIN_SCORE_BEFORE_DISCONNECT = -50;
58
+ const SCORE_CLEANUP_THRESHOLD = 0.1;
57
59
 
58
60
  export class PeerScoring {
59
61
  private logger = createLogger('p2p:peer-scoring');
@@ -65,7 +67,11 @@ export class PeerScoring {
65
67
 
66
68
  private peerStateCounter: UpDownCounter;
67
69
 
68
- constructor(config: P2PConfig, telemetry: TelemetryClient = getTelemetryClient()) {
70
+ constructor(
71
+ config: P2PConfig,
72
+ telemetry: TelemetryClient = getTelemetryClient(),
73
+ private readonly dateProvider: DateProvider = new DateProvider(),
74
+ ) {
69
75
  const orderedValues = config.peerPenaltyValues?.sort((a, b) => a - b);
70
76
  this.peerPenalties = {
71
77
  [PeerErrorSeverity.HighToleranceError]:
@@ -92,7 +98,7 @@ export class PeerScoring {
92
98
  }
93
99
 
94
100
  updateScore(peerId: string, scoreDelta: number): number {
95
- const currentTime = Date.now();
101
+ const currentTime = this.dateProvider.now();
96
102
  const lastUpdate = this.lastUpdateTime.get(peerId) || currentTime;
97
103
  const timePassed = currentTime - lastUpdate;
98
104
  const decayPeriods = Math.floor(timePassed / this.decayInterval);
@@ -111,19 +117,35 @@ export class PeerScoring {
111
117
  }
112
118
 
113
119
  decayAllScores(): void {
114
- const currentTime = Date.now();
120
+ const currentTime = this.dateProvider.now();
115
121
  for (const [peerId, lastUpdate] of this.lastUpdateTime.entries()) {
116
122
  const timePassed = currentTime - lastUpdate;
117
123
  const decayPeriods = Math.floor(timePassed / this.decayInterval);
118
124
  if (decayPeriods > 0) {
119
125
  let score = this.scores.get(peerId) || 0;
120
126
  score *= Math.pow(this.decayFactor, decayPeriods);
121
- this.scores.set(peerId, score);
122
- this.lastUpdateTime.set(peerId, currentTime);
127
+ if (Math.abs(score) < SCORE_CLEANUP_THRESHOLD) {
128
+ this.scores.delete(peerId);
129
+ this.lastUpdateTime.delete(peerId);
130
+ } else {
131
+ this.scores.set(peerId, score);
132
+ this.lastUpdateTime.set(peerId, currentTime);
133
+ }
123
134
  }
124
135
  }
125
136
  }
126
137
 
138
+ /** Resets all peer scores. Useful for benchmarks to prevent cross-case contamination. */
139
+ resetAllScores(): void {
140
+ this.scores.clear();
141
+ this.lastUpdateTime.clear();
142
+ }
143
+
144
+ removePeer(peerId: string): void {
145
+ this.scores.delete(peerId);
146
+ this.lastUpdateTime.delete(peerId);
147
+ }
148
+
127
149
  getScore(peerId: string): number {
128
150
  return this.scores.get(peerId) || 0;
129
151
  }
@@ -514,6 +514,9 @@ export class BatchTxRequester {
514
514
  });
515
515
 
516
516
  if (hasInvalidTx) {
517
+ this.logger.warn(`Penalizing peer ${peerId.toString()} for sending invalid transactions in batch response`, {
518
+ peerId,
519
+ });
517
520
  this.peers.penalisePeer(peerId, PeerErrorSeverity.LowToleranceError);
518
521
  } else {
519
522
  // If we have received successful response from the peer, they have "redeemed" themselves and not considered bad anymore
@@ -1,4 +1,4 @@
1
- import { type ConfigMapping, booleanConfigHelper, numberConfigHelper } from '@aztec/foundation/config';
1
+ import { type ConfigMappingsType, booleanConfigHelper, numberConfigHelper } from '@aztec/foundation/config';
2
2
 
3
3
  export const DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS = 10_000;
4
4
  export const DEFAULT_OVERALL_REQUEST_TIMEOUT_MS = 10_000; // Not currently used
@@ -27,7 +27,7 @@ export interface P2PReqRespConfig {
27
27
  dialTimeoutMs: number;
28
28
  }
29
29
 
30
- export const p2pReqRespConfigMappings: Record<keyof P2PReqRespConfig, ConfigMapping> = {
30
+ export const p2pReqRespConfigMappings: ConfigMappingsType<P2PReqRespConfig> = {
31
31
  overallRequestTimeoutMs: {
32
32
  env: 'P2P_REQRESP_OVERALL_REQUEST_TIMEOUT_MS',
33
33
  description: 'The overall timeout for a request response operation.',
@@ -1,6 +1,3 @@
1
- import { Fr } from '@aztec/foundation/curves/bn254';
2
- import { L2Block } from '@aztec/stdlib/block';
3
- import { MAX_L2_BLOCK_SIZE_KB } from '@aztec/stdlib/p2p';
4
1
  import { TxArray, TxHashArray } from '@aztec/stdlib/tx';
5
2
 
6
3
  import type { PeerId } from '@libp2p/interface';
@@ -24,7 +21,6 @@ export const PING_PROTOCOL = '/aztec/req/ping/1.0.0';
24
21
  export const STATUS_PROTOCOL = '/aztec/req/status/1.0.0';
25
22
  export const GOODBYE_PROTOCOL = '/aztec/req/goodbye/1.0.0';
26
23
  export const TX_REQ_PROTOCOL = '/aztec/req/tx/1.0.0';
27
- export const BLOCK_REQ_PROTOCOL = '/aztec/req/block/1.0.0';
28
24
  export const AUTH_PROTOCOL = '/aztec/req/auth/1.0.0';
29
25
  export const BLOCK_TXS_REQ_PROTOCOL = '/aztec/req/block_txs/1.0.0';
30
26
 
@@ -33,7 +29,6 @@ export enum ReqRespSubProtocol {
33
29
  STATUS = STATUS_PROTOCOL,
34
30
  GOODBYE = GOODBYE_PROTOCOL,
35
31
  TX = TX_REQ_PROTOCOL,
36
- BLOCK = BLOCK_REQ_PROTOCOL,
37
32
  AUTH = AUTH_PROTOCOL,
38
33
  BLOCK_TXS = BLOCK_TXS_REQ_PROTOCOL,
39
34
  }
@@ -100,12 +95,29 @@ export type ReqRespSubProtocolValidators = {
100
95
  [S in ReqRespSubProtocol]: ResponseValidator<any, any>;
101
96
  };
102
97
 
98
+ /**
99
+ * Protocols that are always allowed without authentication, even when p2pAllowOnlyValidators is enabled.
100
+ * These are needed for the handshake and connection management flow.
101
+ * All other protocols require the remote peer to be authenticated.
102
+ */
103
+ export const UNAUTHENTICATED_ALLOWED_PROTOCOLS: ReadonlySet<ReqRespSubProtocol> = new Set([
104
+ ReqRespSubProtocol.PING,
105
+ ReqRespSubProtocol.STATUS,
106
+ ReqRespSubProtocol.AUTH,
107
+ ReqRespSubProtocol.GOODBYE,
108
+ ]);
109
+
110
+ /**
111
+ * Callback that checks whether a peer should be rejected from req/resp data protocols.
112
+ * Returns true if the peer should be rejected (i.e. p2pAllowOnlyValidators is on and peer is unauthenticated).
113
+ */
114
+ export type ShouldRejectPeer = (peerId: string) => boolean;
115
+
103
116
  export const DEFAULT_SUB_PROTOCOL_VALIDATORS: ReqRespSubProtocolValidators = {
104
117
  [ReqRespSubProtocol.PING]: noopValidator,
105
118
  [ReqRespSubProtocol.STATUS]: noopValidator,
106
119
  [ReqRespSubProtocol.TX]: noopValidator,
107
120
  [ReqRespSubProtocol.GOODBYE]: noopValidator,
108
- [ReqRespSubProtocol.BLOCK]: noopValidator,
109
121
  [ReqRespSubProtocol.AUTH]: noopValidator,
110
122
  [ReqRespSubProtocol.BLOCK_TXS]: noopValidator,
111
123
  };
@@ -203,10 +215,6 @@ export const subProtocolMap = {
203
215
  request: RequestableBuffer,
204
216
  response: RequestableBuffer,
205
217
  },
206
- [ReqRespSubProtocol.BLOCK]: {
207
- request: Fr, // block number
208
- response: L2Block,
209
- },
210
218
  [ReqRespSubProtocol.AUTH]: {
211
219
  request: AuthRequest,
212
220
  response: AuthResponse,
@@ -229,7 +237,6 @@ export type ExpectedResponseSizeCalculator = (requestBuffer: Buffer) => number;
229
237
  export const subProtocolSizeCalculators: Record<ReqRespSubProtocol, ExpectedResponseSizeCalculator> = {
230
238
  [ReqRespSubProtocol.TX]: calculateTxResponseSize,
231
239
  [ReqRespSubProtocol.BLOCK_TXS]: calculateBlockTxsResponseSize,
232
- [ReqRespSubProtocol.BLOCK]: () => MAX_L2_BLOCK_SIZE_KB,
233
240
  [ReqRespSubProtocol.STATUS]: () => 1,
234
241
  [ReqRespSubProtocol.PING]: () => 1,
235
242
  [ReqRespSubProtocol.AUTH]: () => 1,
@@ -264,5 +271,8 @@ export interface ReqRespInterface {
264
271
 
265
272
  updateConfig(config: Partial<P2PReqRespConfig>): void;
266
273
 
274
+ /** Sets the callback used to reject unauthenticated peers on gated req/resp protocols. */
275
+ setShouldRejectPeer(checker: ShouldRejectPeer): void;
276
+
267
277
  getConnectionSampler(): Pick<ConnectionSampler, 'getPeerListSortedByConnectionCountAsc'>;
268
278
  }
@@ -26,7 +26,6 @@ export class ReqRespMetrics {
26
26
  ReqRespSubProtocol.STATUS,
27
27
  ReqRespSubProtocol.GOODBYE,
28
28
  ReqRespSubProtocol.TX,
29
- ReqRespSubProtocol.BLOCK,
30
29
  ReqRespSubProtocol.AUTH,
31
30
  ReqRespSubProtocol.BLOCK_TXS,
32
31
  ],
@@ -5,6 +5,5 @@ export * from './ping.js';
5
5
  export * from './status.js';
6
6
  export * from './tx.js';
7
7
  export * from './goodbye.js';
8
- export * from './block.js';
9
8
  export * from './auth.js';
10
9
  export * from './block_txs/index.js';
@@ -51,9 +51,7 @@ export function reqRespTxHandler(mempools: MemPools): ReqRespSubProtocolHandler
51
51
  * Per: https://github.com/AztecProtocol/aztec-packages/issues/15149#issuecomment-2999054485
52
52
  * we define Q as max number of transactions per batch, the comment explains why we use 8.
53
53
  */
54
- //TODO: (mralj) chunk size should by default be 8, this is just temporary until the protocol is implemented correctly
55
- //more info: https://github.com/AztecProtocol/aztec-packages/pull/15516#pullrequestreview-2995474321
56
- export function chunkTxHashesRequest(hashes: TxHash[], chunkSize = 1): Array<TxHashArray> {
54
+ export function chunkTxHashesRequest(hashes: TxHash[], chunkSize = 8): Array<TxHashArray> {
57
55
  return chunk(hashes, chunkSize).map(chunk => new TxHashArray(...chunk));
58
56
  }
59
57
 
@@ -97,9 +97,10 @@ export function prettyPrintRateLimitStatus(status: RateLimitStatus) {
97
97
  * 2. Individual rate limits for each peer.
98
98
  *
99
99
  * How it works:
100
- * - When a request comes in, it first checks against the global rate limit.
101
- * - If the global limit allows, it then checks against the specific peer's rate limit.
102
- * - The request is only allowed if both the global and peer-specific limits allow it.
100
+ * - When a request comes in, it first checks against the peer's individual rate limit.
101
+ * - If the peer limit allows, it then checks against the global rate limit.
102
+ * - The request is only allowed if both the peer-specific and global limits allow it.
103
+ * - Checking peer limit first ensures a rate-limited peer cannot exhaust the global quota.
103
104
  * - It automatically creates and manages rate limiters for new peers as they make requests.
104
105
  * - It periodically cleans up rate limiters for inactive peers to conserve memory.
105
106
  *
@@ -119,10 +120,6 @@ export class SubProtocolRateLimiter {
119
120
  }
120
121
 
121
122
  allow(peerId: PeerId): RateLimitStatus {
122
- if (!this.globalLimiter.allow()) {
123
- return RateLimitStatus.DeniedGlobal;
124
- }
125
-
126
123
  const peerIdStr = peerId.toString();
127
124
  let peerLimiter: PeerRateLimiter | undefined = this.peerLimiters.get(peerIdStr);
128
125
  if (!peerLimiter) {
@@ -135,10 +132,17 @@ export class SubProtocolRateLimiter {
135
132
  } else {
136
133
  peerLimiter.lastAccess = Date.now();
137
134
  }
138
- const peerLimitAllowed = peerLimiter.limiter.allow();
139
- if (!peerLimitAllowed) {
135
+
136
+ // Check peer limit first: a rate-limited peer must not consume global quota,
137
+ // otherwise one spamming peer can starve all others by exhausting the global bucket.
138
+ if (!peerLimiter.limiter.allow()) {
140
139
  return RateLimitStatus.DeniedPeer;
141
140
  }
141
+
142
+ if (!this.globalLimiter.allow()) {
143
+ return RateLimitStatus.DeniedGlobal;
144
+ }
145
+
142
146
  return RateLimitStatus.Allowed;
143
147
  }
144
148
 
@@ -42,16 +42,6 @@ export const DEFAULT_RATE_LIMITS: ReqRespSubProtocolRateLimits = {
42
42
  quotaCount: 200,
43
43
  },
44
44
  },
45
- [ReqRespSubProtocol.BLOCK]: {
46
- peerLimit: {
47
- quotaTimeMs: 1000,
48
- quotaCount: 2,
49
- },
50
- globalLimit: {
51
- quotaTimeMs: 1000,
52
- quotaCount: 5,
53
- },
54
- },
55
45
  [ReqRespSubProtocol.GOODBYE]: {
56
46
  peerLimit: {
57
47
  quotaTimeMs: 1000,
@@ -34,7 +34,9 @@ import {
34
34
  type ReqRespSubProtocolHandlers,
35
35
  type ReqRespSubProtocolRateLimits,
36
36
  type ReqRespSubProtocolValidators,
37
+ type ShouldRejectPeer,
37
38
  type SubProtocolMap,
39
+ UNAUTHENTICATED_ALLOWED_PROTOCOLS,
38
40
  responseFromBuffer,
39
41
  subProtocolSizeCalculators,
40
42
  } from './interface.js';
@@ -72,6 +74,8 @@ export class ReqResp implements ReqRespInterface {
72
74
 
73
75
  private snappyTransform: SnappyTransform;
74
76
 
77
+ private shouldRejectPeer: ShouldRejectPeer | undefined;
78
+
75
79
  private metrics: ReqRespMetrics;
76
80
 
77
81
  constructor(
@@ -108,6 +112,10 @@ export class ReqResp implements ReqRespInterface {
108
112
  }
109
113
  }
110
114
 
115
+ public setShouldRejectPeer(checker: ShouldRejectPeer): void {
116
+ this.shouldRejectPeer = checker;
117
+ }
118
+
111
119
  get tracer() {
112
120
  return this.metrics.tracer;
113
121
  }
@@ -462,7 +470,7 @@ export class ReqResp implements ReqRespInterface {
462
470
  );
463
471
  return resp;
464
472
  } catch (e: any) {
465
- this.logger.warn(`SUBPROTOCOL: ${subProtocol}\n`, e);
473
+ this.logger.debug(`SUBPROTOCOL: ${subProtocol}\n`, e);
466
474
  // On error we immediately abort the stream, this is preferred way,
467
475
  // because it signals to the sender that error happened, whereas
468
476
  // closing the stream only closes our side and is much slower
@@ -596,6 +604,15 @@ export class ReqResp implements ReqRespInterface {
596
604
  throw new ReqRespStatusError(ReqRespStatus.RATE_LIMIT_EXCEEDED);
597
605
  }
598
606
 
607
+ // When p2pAllowOnlyValidators is enabled, reject unauthenticated peers on data protocols
608
+ if (
609
+ !UNAUTHENTICATED_ALLOWED_PROTOCOLS.has(protocol) &&
610
+ (this.shouldRejectPeer?.(connection.remotePeer.toString()) ?? false)
611
+ ) {
612
+ this.logger.debug(`Rejecting unauthenticated peer ${connection.remotePeer} on gated protocol ${protocol}`);
613
+ throw new ReqRespStatusError(ReqRespStatus.FAILURE);
614
+ }
615
+
599
616
  await this.processStream(protocol, incomingStream);
600
617
  } catch (err: any) {
601
618
  this.metrics.recordResponseError(protocol);
@@ -117,7 +117,12 @@ export interface P2PService {
117
117
  // Leaky abstraction: fix https://github.com/AztecProtocol/aztec-packages/issues/7963
118
118
  registerBlockReceivedCallback(callback: P2PBlockReceivedCallback): void;
119
119
 
120
- registerCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback): void;
120
+ registerValidatorCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback): void;
121
+
122
+ registerAllNodesCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback): void;
123
+
124
+ /** Fires the all-nodes checkpoint callback for our own proposal (gossipsub doesn't deliver own messages). */
125
+ notifyOwnCheckpointProposal(checkpoint: CheckpointProposalCore): Promise<void>;
121
126
 
122
127
  /**
123
128
  * Registers a callback invoked when a duplicate proposal is detected (equivocation).
@@ -1,7 +1,8 @@
1
+ import { partitionAsync } from '@aztec/foundation/collection';
1
2
  import { type Logger, createLogger } from '@aztec/foundation/log';
2
3
  import { Timer } from '@aztec/foundation/timer';
3
4
  import { type ReadOnlyFileStore, createReadOnlyFileStore } from '@aztec/stdlib/file-store';
4
- import { Tx, type TxHash } from '@aztec/stdlib/tx';
5
+ import { Tx, type TxHash, type TxValidator } from '@aztec/stdlib/tx';
5
6
  import {
6
7
  type Histogram,
7
8
  Metrics,
@@ -23,6 +24,7 @@ export class FileStoreTxSource implements TxSource {
23
24
  private readonly fileStore: ReadOnlyFileStore,
24
25
  private readonly baseUrl: string,
25
26
  private readonly basePath: string,
27
+ private readonly txValidator: TxValidator,
26
28
  private readonly log: Logger,
27
29
  telemetry: TelemetryClient,
28
30
  ) {
@@ -44,6 +46,7 @@ export class FileStoreTxSource implements TxSource {
44
46
  public static async create(
45
47
  url: string,
46
48
  basePath: string,
49
+ txValidator: TxValidator,
47
50
  log: Logger = createLogger('p2p:file_store_tx_source'),
48
51
  telemetry: TelemetryClient = getTelemetryClient(),
49
52
  ): Promise<FileStoreTxSource | undefined> {
@@ -53,7 +56,7 @@ export class FileStoreTxSource implements TxSource {
53
56
  log.warn(`Failed to create file store for URL: ${url}`);
54
57
  return undefined;
55
58
  }
56
- return new FileStoreTxSource(fileStore, url, basePath, log, telemetry);
59
+ return new FileStoreTxSource(fileStore, url, basePath, txValidator, log, telemetry);
57
60
  } catch (err) {
58
61
  log.warn(`Error creating file store for URL: ${url}`, { error: err });
59
62
  return undefined;
@@ -65,35 +68,41 @@ export class FileStoreTxSource implements TxSource {
65
68
  }
66
69
 
67
70
  public async getTxsByHash(txHashes: TxHash[]): Promise<TxSourceCollectionResult> {
68
- const invalidTxHashes: string[] = [];
71
+ const results = await Promise.all(
72
+ txHashes.map(async txHash => {
73
+ const path = `${this.basePath}/txs/${txHash.toString()}.bin`;
74
+ const timer = new Timer();
75
+ try {
76
+ const buffer = await this.fileStore.read(path);
77
+ const tx = Tx.fromBuffer(buffer);
78
+ return { tx, downloadDuration: timer.ms(), downloadSize: buffer.length };
79
+ } catch {
80
+ this.downloadsFailed.add(1);
81
+ return undefined;
82
+ }
83
+ }),
84
+ );
85
+
86
+ const txs = results.filter(tx => tx !== undefined);
87
+ const [validTxs, invalidTxs] = await partitionAsync(
88
+ txs,
89
+ async ({ tx, downloadDuration, downloadSize }): Promise<boolean> => {
90
+ const valid = await this.txValidator.validateTx(tx);
91
+ if (valid.result === 'valid') {
92
+ this.downloadsSuccess.add(1);
93
+ this.downloadDuration.record(Math.ceil(downloadDuration));
94
+ this.downloadSize.record(downloadSize);
95
+ return true;
96
+ } else {
97
+ this.downloadsFailed.add(1);
98
+ return false;
99
+ }
100
+ },
101
+ );
102
+
69
103
  return {
70
- validTxs: (
71
- await Promise.all(
72
- txHashes.map(async txHash => {
73
- const path = `${this.basePath}/txs/${txHash.toString()}.bin`;
74
- const timer = new Timer();
75
- try {
76
- const buffer = await this.fileStore.read(path);
77
- const tx = Tx.fromBuffer(buffer);
78
- if ((await tx.validateTxHash()) && txHash.equals(tx.txHash)) {
79
- this.downloadsSuccess.add(1);
80
- this.downloadDuration.record(Math.ceil(timer.ms()));
81
- this.downloadSize.record(buffer.length);
82
- return tx;
83
- } else {
84
- invalidTxHashes.push(tx.txHash.toString());
85
- this.downloadsFailed.add(1);
86
- return undefined;
87
- }
88
- } catch {
89
- // Tx not found or error reading - return undefined
90
- this.downloadsFailed.add(1);
91
- return undefined;
92
- }
93
- }),
94
- )
95
- ).filter(tx => tx !== undefined),
96
- invalidTxHashes: invalidTxHashes,
104
+ validTxs: validTxs.map(({ tx }) => tx),
105
+ invalidTxHashes: invalidTxs.map(({ tx }) => tx.getTxHash().toString()),
97
106
  };
98
107
  }
99
108
  }
@@ -109,9 +118,12 @@ export class FileStoreTxSource implements TxSource {
109
118
  export async function createFileStoreTxSources(
110
119
  urls: string[],
111
120
  basePath: string,
121
+ txValidator: TxValidator,
112
122
  log: Logger = createLogger('p2p:file_store_tx_source'),
113
123
  telemetry: TelemetryClient = getTelemetryClient(),
114
124
  ): Promise<FileStoreTxSource[]> {
115
- const sources = await Promise.all(urls.map(url => FileStoreTxSource.create(url, basePath, log, telemetry)));
125
+ const sources = await Promise.all(
126
+ urls.map(url => FileStoreTxSource.create(url, basePath, txValidator, log, telemetry)),
127
+ );
116
128
  return sources.filter((s): s is FileStoreTxSource => s !== undefined);
117
129
  }
@@ -2,7 +2,7 @@ import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
2
2
  import { protocolContractsHash } from '@aztec/protocol-contracts';
3
3
  import type { ChainConfig } from '@aztec/stdlib/config';
4
4
  import { type AztecNode, createAztecNodeClient } from '@aztec/stdlib/interfaces/client';
5
- import type { Tx, TxHash } from '@aztec/stdlib/tx';
5
+ import type { Tx, TxHash, TxValidator } from '@aztec/stdlib/tx';
6
6
  import { type ComponentsVersions, getComponentsVersionsFromConfig } from '@aztec/stdlib/versioning';
7
7
  import { makeTracedFetch } from '@aztec/telemetry-client';
8
8
 
@@ -16,12 +16,13 @@ export interface TxSource {
16
16
  export class NodeRpcTxSource implements TxSource {
17
17
  constructor(
18
18
  private readonly client: Pick<AztecNode, 'getTxsByHash'>,
19
+ private readonly txValidator: TxValidator,
19
20
  private readonly info: string,
20
21
  ) {}
21
22
 
22
- public static fromUrl(nodeUrl: string, versions: ComponentsVersions): NodeRpcTxSource {
23
+ public static fromUrl(nodeUrl: string, txValidator: TxValidator, versions: ComponentsVersions): NodeRpcTxSource {
23
24
  const client = createAztecNodeClient(nodeUrl, versions, makeTracedFetch([1, 2, 3], false));
24
- return new NodeRpcTxSource(client, nodeUrl);
25
+ return new NodeRpcTxSource(client, txValidator, nodeUrl);
25
26
  }
26
27
 
27
28
  public getInfo() {
@@ -38,8 +39,8 @@ export class NodeRpcTxSource implements TxSource {
38
39
  const invalidTxHashes: string[] = [];
39
40
  await Promise.all(
40
41
  txs.map(async tx => {
41
- const isValid = await tx.validateTxHash();
42
- if (isValid) {
42
+ const validation = await this.txValidator.validateTx(tx);
43
+ if (validation.result === 'valid') {
43
44
  validTxs.push(tx);
44
45
  } else {
45
46
  invalidTxHashes.push(tx.getTxHash().toString());
@@ -50,7 +51,7 @@ export class NodeRpcTxSource implements TxSource {
50
51
  }
51
52
  }
52
53
 
53
- export function createNodeRpcTxSources(urls: string[], chainConfig: ChainConfig) {
54
+ export function createNodeRpcTxSources(urls: string[], txValidator: TxValidator, chainConfig: ChainConfig) {
54
55
  const versions = getComponentsVersionsFromConfig(chainConfig, protocolContractsHash, getVKTreeRoot());
55
- return urls.map(url => NodeRpcTxSource.fromUrl(url, versions));
56
+ return urls.map(url => NodeRpcTxSource.fromUrl(url, txValidator, versions));
56
57
  }
@@ -5,6 +5,7 @@ import { type Logger, createLogger } from '@aztec/foundation/log';
5
5
  import { retryUntil } from '@aztec/foundation/retry';
6
6
  import { sleep } from '@aztec/foundation/sleep';
7
7
  import { openTmpStore } from '@aztec/kv-store/lmdb-v2';
8
+ import { GasFees } from '@aztec/stdlib/gas';
8
9
  import type { WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
9
10
  import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
10
11
 
@@ -102,6 +103,7 @@ export async function makeTestP2PClient(
102
103
  proofVerifier,
103
104
  mockWorldState,
104
105
  mockEpochCache,
106
+ { getCurrentMinFees: () => Promise.resolve(GasFees.empty()) },
105
107
  'test-p2p-client',
106
108
  undefined,
107
109
  undefined,
@@ -1,8 +1,10 @@
1
1
  import type { EpochCacheInterface } from '@aztec/epoch-cache';
2
2
  import { type Logger, createLogger } from '@aztec/foundation/log';
3
+ import { sleep } from '@aztec/foundation/sleep';
3
4
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
4
5
  import type { L2BlockSource } from '@aztec/stdlib/block';
5
6
  import type { ContractDataSource } from '@aztec/stdlib/contract';
7
+ import type { BlockMinFeesProvider } from '@aztec/stdlib/gas';
6
8
  import type { ClientProtocolCircuitVerifier, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
7
9
  import type { TelemetryClient } from '@aztec/telemetry-client';
8
10
 
@@ -55,6 +57,7 @@ export function getMockPubSubP2PServiceFactory(
55
57
  proofVerifier: ClientProtocolCircuitVerifier;
56
58
  worldStateSynchronizer: WorldStateSynchronizer;
57
59
  peerStore: AztecAsyncKVStore;
60
+ blockMinFeesProvider: BlockMinFeesProvider;
58
61
  telemetry: TelemetryClient;
59
62
  logger: Logger;
60
63
  },
@@ -75,6 +78,7 @@ export function getMockPubSubP2PServiceFactory(
75
78
  deps.epochCache,
76
79
  deps.proofVerifier,
77
80
  deps.worldStateSynchronizer,
81
+ deps.blockMinFeesProvider,
78
82
  deps.telemetry,
79
83
  deps.logger,
80
84
  );
@@ -100,6 +104,7 @@ class MockReqResp implements ReqRespInterface {
100
104
  }
101
105
 
102
106
  updateConfig(_config: Partial<P2PReqRespConfig>): void {}
107
+ setShouldRejectPeer(): void {}
103
108
 
104
109
  start(
105
110
  subProtocolHandlers: Partial<ReqRespSubProtocolHandlers>,
@@ -138,6 +143,11 @@ class MockReqResp implements ReqRespInterface {
138
143
  const responses: InstanceType<SubProtocolMap[SubProtocol]['response']>[] = [];
139
144
  const peers = this.network.getReqRespPeers().filter(p => !p.peerId.equals(this.peerId));
140
145
  const targetPeers = pinnedPeer ? peers.filter(p => p.peerId.equals(pinnedPeer)) : peers;
146
+ const delayMs = this.network.getPropagationDelayMs();
147
+
148
+ if (delayMs > 0) {
149
+ await sleep(delayMs);
150
+ }
141
151
 
142
152
  for (const request of requests) {
143
153
  const requestBuffer = request.toBuffer();
@@ -174,7 +184,12 @@ class MockReqResp implements ReqRespInterface {
174
184
  return { status: ReqRespStatus.SUCCESS, data: Buffer.from([]) };
175
185
  }
176
186
  try {
187
+ const delayMs = this.network.getPropagationDelayMs();
188
+ if (delayMs > 0) {
189
+ await sleep(delayMs);
190
+ }
177
191
  const data = await handler(this.peerId, payload);
192
+
178
193
  return { status: ReqRespStatus.SUCCESS, data };
179
194
  } catch {
180
195
  return { status: ReqRespStatus.FAILURE };
@@ -242,10 +257,10 @@ class MockGossipSubService extends TypedEventEmitter<GossipsubEvents> implements
242
257
  score: (_peerId: PeerIdStr) => 0,
243
258
  };
244
259
 
245
- publish(topic: TopicStr, data: Uint8Array, _opts?: PublishOpts): Promise<PublishResult> {
260
+ async publish(topic: TopicStr, data: Uint8Array, _opts?: PublishOpts): Promise<PublishResult> {
246
261
  this.logger.debug(`Publishing message on topic ${topic}`, { topic, sender: this.peerId.toString() });
247
- this.network.publishToPeers(topic, data, this.peerId);
248
- return Promise.resolve({ recipients: this.network.getPeers().filter(peer => !this.peerId.equals(peer)) });
262
+ await this.network.publishToPeers(topic, data, this.peerId);
263
+ return { recipients: this.network.getPeers().filter(peer => !this.peerId.equals(peer)) };
249
264
  }
250
265
 
251
266
  receive(msg: GossipsubMessage) {
@@ -281,7 +296,8 @@ class MockGossipSubService extends TypedEventEmitter<GossipsubEvents> implements
281
296
 
282
297
  /**
283
298
  * Mock gossip sub network used for testing.
284
- * All instances of MockGossipSubService connected to the same network will instantly receive the same messages.
299
+ * All instances of MockGossipSubService connected to the same network receive the same messages,
300
+ * optionally delayed by a configurable propagation time.
285
301
  */
286
302
  export class MockGossipSubNetwork {
287
303
  private peers: MockGossipSubService[] = [];
@@ -290,6 +306,15 @@ export class MockGossipSubNetwork {
290
306
 
291
307
  private logger = createLogger('p2p:test:mock-gossipsub-network');
292
308
 
309
+ constructor(
310
+ /** Artificial propagation delay in milliseconds applied to each message delivery. */
311
+ private propagationDelayMs: number = 0,
312
+ ) {}
313
+
314
+ public getPropagationDelayMs(): number {
315
+ return this.propagationDelayMs;
316
+ }
317
+
293
318
  public getPeers(): PeerId[] {
294
319
  return this.peers.map(peer => peer.peerId);
295
320
  }
@@ -306,7 +331,7 @@ export class MockGossipSubNetwork {
306
331
  return this.reqRespPeers;
307
332
  }
308
333
 
309
- public publishToPeers(topic: TopicStr, data: Uint8Array, sender: PeerId): void {
334
+ public async publishToPeers(topic: TopicStr, data: Uint8Array, sender: PeerId): Promise<void> {
310
335
  const msgId = (this.nextMsgId++).toString();
311
336
  this.logger.debug(`Network is distributing message on topic ${topic}`, {
312
337
  topic,
@@ -315,6 +340,10 @@ export class MockGossipSubNetwork {
315
340
  msgId,
316
341
  });
317
342
 
343
+ if (this.propagationDelayMs > 0) {
344
+ await sleep(this.propagationDelayMs);
345
+ }
346
+
318
347
  const gossipSubMsg: GossipsubMessage = { msgId, msg: { type: 'unsigned', topic, data }, propagationSource: sender };
319
348
  for (const peer of this.peers) {
320
349
  if (peer.subscribedTopics.has(topic)) {