@aztec-labs/p2p 6.0.0-rc.3 → 6.0.0-rc.4

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 (126) hide show
  1. package/dest/bootstrap/bootstrap.d.ts +2 -2
  2. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  3. package/dest/bootstrap/bootstrap.js +1 -3
  4. package/dest/client/p2p_client.js +1 -2
  5. package/dest/config.d.ts +1 -11
  6. package/dest/config.d.ts.map +1 -1
  7. package/dest/config.js +0 -16
  8. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +1 -1
  9. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -1
  10. package/dest/mem_pools/tx_pool_v2/deleted_pool.js +1 -0
  11. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts +2 -1
  12. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts.map +1 -1
  13. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.js +25 -1
  14. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +3 -3
  15. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -1
  16. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +2 -1
  17. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -1
  18. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +10 -1
  19. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +6 -1
  20. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
  21. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +1 -1
  22. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
  23. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +39 -8
  24. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +1 -1
  25. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  26. package/dest/msg_validators/attestation_validator/attestation_validator.js +25 -13
  27. package/dest/msg_validators/epoch_cache_lookup.d.ts +15 -12
  28. package/dest/msg_validators/epoch_cache_lookup.d.ts.map +1 -1
  29. package/dest/msg_validators/epoch_cache_lookup.js +27 -18
  30. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +1 -1
  31. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
  32. package/dest/msg_validators/proposal_validator/proposal_validator.js +23 -15
  33. package/dest/msg_validators/tx_validator/data_validator.d.ts +1 -1
  34. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  35. package/dest/msg_validators/tx_validator/data_validator.js +61 -13
  36. package/dest/services/discv5/discV5_service.d.ts +2 -2
  37. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  38. package/dest/services/discv5/discV5_service.js +2 -3
  39. package/dest/services/dummy_service.d.ts +2 -1
  40. package/dest/services/dummy_service.d.ts.map +1 -1
  41. package/dest/services/dummy_service.js +1 -0
  42. package/dest/services/encoding.d.ts +2 -1
  43. package/dest/services/encoding.d.ts.map +1 -1
  44. package/dest/services/encoding.js +1 -0
  45. package/dest/services/libp2p/libp2p_service.d.ts +6 -2
  46. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  47. package/dest/services/libp2p/libp2p_service.js +38 -9
  48. package/dest/services/peer-manager/peer_manager.d.ts +1 -1
  49. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  50. package/dest/services/peer-manager/peer_manager.js +5 -1
  51. package/dest/services/peer-manager/peer_scoring.d.ts +13 -1
  52. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  53. package/dest/services/peer-manager/peer_scoring.js +38 -0
  54. package/dest/services/reqresp/protocols/auth.d.ts +2 -1
  55. package/dest/services/reqresp/protocols/auth.d.ts.map +1 -1
  56. package/dest/services/reqresp/protocols/auth.js +1 -0
  57. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +2 -1
  58. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
  59. package/dest/services/reqresp/protocols/block_txs/bitvector.js +1 -0
  60. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +1 -1
  61. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
  62. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +13 -4
  63. package/dest/services/reqresp/protocols/goodbye.d.ts +2 -1
  64. package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -1
  65. package/dest/services/reqresp/protocols/goodbye.js +1 -0
  66. package/dest/services/reqresp/protocols/ping.d.ts +2 -1
  67. package/dest/services/reqresp/protocols/ping.d.ts.map +1 -1
  68. package/dest/services/reqresp/protocols/ping.js +1 -0
  69. package/dest/services/reqresp/reqresp.d.ts +2 -1
  70. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  71. package/dest/services/reqresp/reqresp.js +1 -0
  72. package/dest/test-helpers/mock-pubsub.d.ts +2 -1
  73. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  74. package/dest/test-helpers/mock-pubsub.js +1 -0
  75. package/dest/test-helpers/reqresp-nodes.d.ts +1 -1
  76. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  77. package/dest/test-helpers/reqresp-nodes.js +1 -0
  78. package/dest/test-helpers/testbench-utils.js +18 -6
  79. package/dest/testbench/p2p_client_testbench_worker.d.ts +1 -1
  80. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  81. package/dest/testbench/p2p_client_testbench_worker.js +1 -0
  82. package/dest/testbench/worker_client_manager.d.ts +1 -1
  83. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  84. package/dest/testbench/worker_client_manager.js +2 -1
  85. package/dest/util.d.ts +1 -1
  86. package/dest/util.d.ts.map +1 -1
  87. package/dest/util.js +1 -0
  88. package/dest/versioning.d.ts +1 -1
  89. package/dest/versioning.d.ts.map +1 -1
  90. package/dest/versioning.js +1 -0
  91. package/package.json +16 -16
  92. package/src/bootstrap/bootstrap.ts +1 -2
  93. package/src/client/p2p_client.ts +1 -1
  94. package/src/config.ts +0 -11
  95. package/src/mem_pools/tx_pool_v2/README.md +2 -0
  96. package/src/mem_pools/tx_pool_v2/deleted_pool.ts +1 -0
  97. package/src/mem_pools/tx_pool_v2/eviction/eviction_manager.ts +28 -1
  98. package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +2 -2
  99. package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +11 -1
  100. package/src/mem_pools/tx_pool_v2/interfaces.ts +5 -0
  101. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +46 -11
  102. package/src/msg_validators/attestation_validator/README.md +4 -3
  103. package/src/msg_validators/attestation_validator/attestation_validator.ts +23 -11
  104. package/src/msg_validators/epoch_cache_lookup.ts +33 -15
  105. package/src/msg_validators/proposal_validator/README.md +5 -4
  106. package/src/msg_validators/proposal_validator/proposal_validator.ts +23 -14
  107. package/src/msg_validators/tx_validator/data_validator.ts +63 -18
  108. package/src/services/discv5/discV5_service.ts +2 -2
  109. package/src/services/dummy_service.ts +1 -0
  110. package/src/services/encoding.ts +1 -0
  111. package/src/services/libp2p/libp2p_service.ts +37 -8
  112. package/src/services/peer-manager/peer_manager.ts +5 -1
  113. package/src/services/peer-manager/peer_scoring.ts +43 -0
  114. package/src/services/reqresp/protocols/auth.ts +1 -0
  115. package/src/services/reqresp/protocols/block_txs/bitvector.ts +1 -0
  116. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +17 -4
  117. package/src/services/reqresp/protocols/goodbye.ts +1 -0
  118. package/src/services/reqresp/protocols/ping.ts +2 -0
  119. package/src/services/reqresp/reqresp.ts +1 -0
  120. package/src/test-helpers/mock-pubsub.ts +1 -0
  121. package/src/test-helpers/reqresp-nodes.ts +1 -0
  122. package/src/test-helpers/testbench-utils.ts +6 -6
  123. package/src/testbench/p2p_client_testbench_worker.ts +1 -0
  124. package/src/testbench/worker_client_manager.ts +2 -1
  125. package/src/util.ts +1 -0
  126. package/src/versioning.ts +1 -0
@@ -56,6 +56,12 @@ const MIN_SCORE_BEFORE_BAN = -100;
56
56
  const MIN_SCORE_BEFORE_DISCONNECT = -50;
57
57
  const SCORE_CLEANUP_THRESHOLD = 0.1;
58
58
 
59
+ // Upper bounds on retained scoring state so a remote peer churning throwaway identities cannot grow the
60
+ // heartbeat-scanned maps without limit. Both sit far above any healthy non-connected count (maxPeerCount
61
+ // defaults to 100). Over the cap, the least-recently-updated score and the earliest-expiring ban are evicted.
62
+ const MAX_RETAINED_SCORED_PEERS = 4096;
63
+ const MAX_RETAINED_BANS = 4096;
64
+
59
65
  /** An active ban: the score the peer held when banned, and the timestamp at which the ban lifts. */
60
66
  type BanRecord = { score: number; expiry: number };
61
67
 
@@ -123,8 +129,13 @@ export class PeerScoring {
123
129
  // Apply new score delta
124
130
  currentScore += scoreDelta;
125
131
 
132
+ // Re-insert so the most recently updated peer moves to the end of iteration order; the first entry is
133
+ // then the least-recently-updated (most-decayed) peer, which is the one evicted when over the cap.
134
+ this.scores.delete(peerId);
135
+ this.lastUpdateTime.delete(peerId);
126
136
  this.scores.set(peerId, currentScore);
127
137
  this.lastUpdateTime.set(peerId, currentTime);
138
+ this.evictLeastRecentScoreIfOverCap(peerId);
128
139
 
129
140
  this.maybeBanPeer(peerId, currentScore);
130
141
 
@@ -143,6 +154,7 @@ export class PeerScoring {
143
154
  }
144
155
  const record: BanRecord = { score, expiry: this.dateProvider.now() + this.banDurationMs };
145
156
  this.bannedPeers.set(peerId, record);
157
+ this.evictEarliestBanIfOverCap(peerId);
146
158
  this.logger.verbose(`Banning peer ${peerId} until ${new Date(record.expiry).toISOString()}`, {
147
159
  peerId,
148
160
  score,
@@ -194,6 +206,37 @@ export class PeerScoring {
194
206
  this.lastUpdateTime.delete(peerId);
195
207
  }
196
208
 
209
+ /**
210
+ * Bounds the score maps. When retention exceeds MAX_RETAINED_SCORED_PEERS, drops the least-recently-updated
211
+ * peer (front of iteration order) - its score has decayed longest and is closest to healthy - never the peer
212
+ * just updated. Keeps a reconnecting recent offender's penalty while capping churn-driven growth.
213
+ */
214
+ private evictLeastRecentScoreIfOverCap(keep: string): void {
215
+ while (this.scores.size > MAX_RETAINED_SCORED_PEERS) {
216
+ const oldest = this.scores.keys().next().value;
217
+ if (oldest === undefined || oldest === keep) {
218
+ break;
219
+ }
220
+ this.scores.delete(oldest);
221
+ this.lastUpdateTime.delete(oldest);
222
+ }
223
+ }
224
+
225
+ /**
226
+ * Bounds the ban map. Bans share a fixed duration, so insertion order is expiry order; when over
227
+ * MAX_RETAINED_BANS the first entry is the earliest-expiring, so dropping it lifts the ban closest to
228
+ * expiring rather than letting identity churn grow the map without limit.
229
+ */
230
+ private evictEarliestBanIfOverCap(keep: string): void {
231
+ while (this.bannedPeers.size > MAX_RETAINED_BANS) {
232
+ const earliest = this.bannedPeers.keys().next().value;
233
+ if (earliest === undefined || earliest === keep) {
234
+ break;
235
+ }
236
+ this.bannedPeers.delete(earliest);
237
+ }
238
+ }
239
+
197
240
  /**
198
241
  * The single source of truth for whether a peer is banned. Returns the ban score while the ban is
199
242
  * active, or undefined if the peer is not banned. A ban that has expired is lazily lifted before
@@ -3,6 +3,7 @@ import { keccak256 } from '@aztec-labs/foundation/crypto/keccak';
3
3
  import { Fr } from '@aztec-labs/foundation/curves/bn254';
4
4
  import { Signature } from '@aztec-labs/foundation/eth-signature';
5
5
  import { BufferReader, serializeToBuffer } from '@aztec-labs/foundation/serialize';
6
+ import { Buffer } from 'buffer';
6
7
 
7
8
  import { StatusMessage } from './status.js';
8
9
 
@@ -1,4 +1,5 @@
1
1
  import { BufferReader, serializeToBuffer } from '@aztec-labs/foundation/serialize';
2
+ import { Buffer } from 'buffer';
2
3
 
3
4
  import { MAX_TXS_PER_BLOCK } from '../../constants.js';
4
5
 
@@ -35,10 +35,15 @@ export function reqRespBlockTxsHandler(
35
35
  throw new ReqRespStatusError(ReqRespStatus.BADLY_FORMED_REQUEST, { cause: err });
36
36
  }
37
37
 
38
- // The explicit-hash fallback is served even when the block is not found, so bound it:
39
- // otherwise a peer could name many hashes (with an empty bit list) and force
40
- // one response to serialize a full tx per hash.
41
- if (request.txHashes.length > MAX_BLOCK_TXS_PER_REQUEST) {
38
+ // Cheap early bound before any attestation-pool / archiver / tx-pool work: reject when the
39
+ // explicit-hash list, or the number of requested indices, already exceeds the per-request cap on
40
+ // its own. The index bitvector has no duplicate positions, so its set-bit count is a lower bound
41
+ // on the served set; the explicit-hash list is bounded as it was before. The deduplicated
42
+ // served-set cap below stays the authoritative gate for the dual-form (index + explicit) overlap.
43
+ if (
44
+ request.txHashes.length > MAX_BLOCK_TXS_PER_REQUEST ||
45
+ request.txIndices.getTrueIndices().length > MAX_BLOCK_TXS_PER_REQUEST
46
+ ) {
42
47
  throw new ReqRespStatusError(ReqRespStatus.BADLY_FORMED_REQUEST);
43
48
  }
44
49
 
@@ -75,6 +80,14 @@ export function reqRespBlockTxsHandler(
75
80
  }
76
81
  }
77
82
 
83
+ // One response is capped at MAX_BLOCK_TXS_PER_REQUEST transactions. Both request forms feed one
84
+ // deduplicated set - the dumb-peer requester sends the same txs by index and by explicit hash -
85
+ // so cap the deduplicated served count, not the raw sum, before fetching and serializing. This
86
+ // bounds the work one peer can drive while still accepting a legitimate dual-form batch.
87
+ if (requestedTxsHashes.size > MAX_BLOCK_TXS_PER_REQUEST) {
88
+ throw new ReqRespStatusError(ReqRespStatus.BADLY_FORMED_REQUEST);
89
+ }
90
+
78
91
  // Finally, get the txs from the pool and create the response.
79
92
  const responseTxs = (
80
93
  await txPool.getTxsByHash(Array.from(requestedTxsHashes).map(h => TxHash.fromString(h)))
@@ -1,5 +1,6 @@
1
1
  import { createLogger } from '@aztec-labs/foundation/log';
2
2
  import type { PeerId } from '@libp2p/interface';
3
+ import { Buffer } from 'buffer';
3
4
 
4
5
  import type { PeerManagerInterface } from '../../peer-manager/interface.js';
5
6
  import { ReqRespSubProtocol, type ReqRespSubProtocolHandler } from '../interface.js';
@@ -1,3 +1,5 @@
1
+ import { Buffer } from 'buffer';
2
+
1
3
  /**
2
4
  * Handles the ping request.
3
5
  * @param _msg - The ping request message.
@@ -5,6 +5,7 @@ import { executeTimeout } from '@aztec-labs/foundation/timer';
5
5
  import { PeerErrorSeverity } from '@aztec-labs/stdlib/p2p';
6
6
  import { Attributes, type TelemetryClient, getTelemetryClient, trackSpan } from '@aztec-labs/telemetry-client';
7
7
  import type { IncomingStreamData, PeerId, Stream } from '@libp2p/interface';
8
+ import { Buffer } from 'buffer';
8
9
  import type { Libp2p } from 'libp2p';
9
10
  import { pipeline } from 'node:stream/promises';
10
11
  import type { Uint8ArrayList } from 'uint8arraylist';
@@ -17,6 +17,7 @@ import {
17
17
  TypedEventEmitter,
18
18
  } from '@libp2p/interface';
19
19
  import { createSecp256k1PeerId } from '@libp2p/peer-id-factory';
20
+ import { Buffer } from 'buffer';
20
21
 
21
22
  import type { P2PConfig } from '../config.js';
22
23
  import type { MemPools } from '../mem_pools/interface.js';
@@ -26,6 +26,7 @@ import { createSecp256k1PeerId } from '@libp2p/peer-id-factory';
26
26
  import { tcp } from '@libp2p/tcp';
27
27
  import { multiaddr } from '@multiformats/multiaddr';
28
28
  import { SignableENR } from '@nethermindeth/enr';
29
+ import { Buffer } from 'buffer';
29
30
  import getPort from 'get-port';
30
31
  import { type Libp2p, type Libp2pOptions, createLibp2p } from 'libp2p';
31
32
 
@@ -308,7 +308,7 @@ export class InMemoryAttestationPool {
308
308
  */
309
309
  export function createMockEpochCache(): EpochCacheInterface {
310
310
  const cache: EpochCacheInterface = {
311
- getCommittee: () => Promise.resolve({ committee: [], seed: 1n, epoch: EpochNumber.ZERO, isEscapeHatchOpen: false }),
311
+ getCommittee: () => Promise.resolve({ state: 'open', seed: 1n, epoch: EpochNumber.ZERO, isEscapeHatchOpen: false }),
312
312
  getProposerIndexEncoding: () => '0x' as `0x${string}`,
313
313
  getSlotNow: () => SlotNumber.ZERO,
314
314
  getTargetSlot: () => SlotNumber.ZERO,
@@ -323,7 +323,7 @@ export function createMockEpochCache(): EpochCacheInterface {
323
323
  computeProposerIndex: () => 0n,
324
324
  getCurrentAndNextSlot: () => ({ currentSlot: SlotNumber.ZERO, nextSlot: SlotNumber.ZERO }),
325
325
  getTargetAndNextSlot: () => ({ targetSlot: SlotNumber.ZERO, nextSlot: SlotNumber.ZERO }),
326
- getProposerAttesterAddressInSlot: () => Promise.resolve(undefined),
326
+ lookupProposer: () => Promise.resolve({ state: 'open' }),
327
327
  getEpochAndSlotInNextL1Slot: () => ({
328
328
  epoch: EpochNumber.ZERO,
329
329
  slot: SlotNumber.ZERO,
@@ -336,11 +336,11 @@ export function createMockEpochCache(): EpochCacheInterface {
336
336
  ts: 0n,
337
337
  nowSeconds: 0n,
338
338
  }),
339
- isInCommittee: () => Promise.resolve(false),
339
+ lookupMembership: () => Promise.resolve({ state: 'open' }),
340
340
  getRegisteredValidators: () => Promise.resolve([]),
341
- filterInCommittee: () => Promise.resolve([]),
342
- isEscapeHatchOpen: () => Promise.resolve(false),
343
- isEscapeHatchOpenAtSlot: () => Promise.resolve(false),
341
+ filterInCommittee: () => Promise.resolve({ state: 'open' }),
342
+ lookupEscapeHatch: () => Promise.resolve({ state: 'open', isEscapeHatchOpen: false }),
343
+ lookupEscapeHatchAtSlot: () => Promise.resolve({ state: 'open', isEscapeHatchOpen: false }),
344
344
  getL1Constants: () => ({
345
345
  l1StartBlock: 0n,
346
346
  l1GenesisTime: 0n,
@@ -29,6 +29,7 @@ import { type TelemetryClient, getTelemetryClient } from '@aztec-labs/telemetry-
29
29
  import type { Message, PeerId } from '@libp2p/interface';
30
30
  import { TopicValidatorResult } from '@libp2p/interface';
31
31
  import { peerIdFromString } from '@libp2p/peer-id';
32
+ import { Buffer } from 'buffer';
32
33
 
33
34
  import type { P2PClient } from '../client/index.js';
34
35
  import type { P2PConfig } from '../config.js';
@@ -1,3 +1,4 @@
1
+ import { getEnv } from '@aztec-labs/foundation/config/env';
1
2
  import { EthAddress } from '@aztec-labs/foundation/eth-address';
2
3
  import type { Logger } from '@aztec-labs/foundation/log';
3
4
  import { retryUntil } from '@aztec-labs/foundation/retry';
@@ -115,7 +116,7 @@ class WorkerClientManager {
115
116
  }
116
117
 
117
118
  const env = {
118
- ...process.env,
119
+ ...getEnv(),
119
120
  TS_NODE_PROJECT: tsconfigPath,
120
121
  };
121
122
 
package/src/util.ts CHANGED
@@ -8,6 +8,7 @@ import type { Identify } from '@libp2p/identify';
8
8
  import type { PeerId, PrivateKey } from '@libp2p/interface';
9
9
  import type { AddressManager, ConnectionManager } from '@libp2p/interface-internal';
10
10
  import { createFromPrivKey } from '@libp2p/peer-id-factory';
11
+ import { Buffer } from 'buffer';
11
12
  import { resolve } from 'dns/promises';
12
13
  import { promises as fs } from 'fs';
13
14
  import type { Libp2p } from 'libp2p';
package/src/versioning.ts CHANGED
@@ -3,6 +3,7 @@ import { protocolContractsHash } from '@aztec-labs/protocol-contracts';
3
3
  import type { ChainConfig } from '@aztec-labs/stdlib/config';
4
4
  import { compressComponentVersions, getComponentsVersionsFromConfig } from '@aztec-labs/stdlib/versioning';
5
5
  import type { SignableENR } from '@nethermindeth/enr';
6
+ import { Buffer } from 'buffer';
6
7
 
7
8
  import { AZTEC_ENR_CLIENT_VERSION_KEY, AZTEC_ENR_KEY } from './types/index.js';
8
9