@aztec/p2p 0.0.1-commit.b9865e97 → 0.0.1-commit.be03c316

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 (153) hide show
  1. package/README.md +7 -6
  2. package/dest/bootstrap/bootstrap.d.ts +1 -1
  3. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  4. package/dest/bootstrap/bootstrap.js +20 -12
  5. package/dest/client/factory.d.ts +2 -2
  6. package/dest/client/factory.d.ts.map +1 -1
  7. package/dest/client/factory.js +10 -5
  8. package/dest/client/interface.d.ts +36 -8
  9. package/dest/client/interface.d.ts.map +1 -1
  10. package/dest/client/p2p_client.d.ts +23 -12
  11. package/dest/client/p2p_client.d.ts.map +1 -1
  12. package/dest/client/p2p_client.js +38 -35
  13. package/dest/config.d.ts +19 -13
  14. package/dest/config.d.ts.map +1 -1
  15. package/dest/config.js +27 -26
  16. package/dest/errors/reqresp.error.d.ts +13 -1
  17. package/dest/errors/reqresp.error.d.ts.map +1 -1
  18. package/dest/errors/reqresp.error.js +14 -0
  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 +9 -2
  22. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
  23. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  24. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +43 -0
  25. package/dest/mem_pools/instrumentation.d.ts +9 -4
  26. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  27. package/dest/mem_pools/instrumentation.js +11 -8
  28. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +3 -3
  29. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -1
  30. package/dest/mem_pools/tx_pool_v2/deleted_pool.js +6 -6
  31. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +1 -1
  32. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +30 -5
  33. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
  34. package/dest/mem_pools/tx_pool_v2/interfaces.js +2 -1
  35. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +15 -1
  36. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
  37. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +31 -0
  38. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +9 -3
  39. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
  40. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +19 -8
  41. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +17 -4
  42. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
  43. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +133 -34
  44. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +6 -5
  45. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  46. package/dest/msg_validators/attestation_validator/attestation_validator.js +24 -26
  47. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +4 -4
  48. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
  49. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +2 -2
  50. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +4 -3
  51. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
  52. package/dest/msg_validators/proposal_validator/block_proposal_validator.js +2 -2
  53. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +4 -3
  54. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
  55. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +8 -2
  56. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +19 -5
  57. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
  58. package/dest/msg_validators/proposal_validator/proposal_validator.js +66 -30
  59. package/dest/msg_validators/tx_validator/factory.d.ts +9 -11
  60. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  61. package/dest/msg_validators/tx_validator/factory.js +15 -6
  62. package/dest/msg_validators/tx_validator/gas_validator.d.ts +12 -7
  63. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  64. package/dest/msg_validators/tx_validator/gas_validator.js +15 -15
  65. package/dest/msg_validators/tx_validator/phases_validator.js +2 -2
  66. package/dest/services/discv5/discV5_service.d.ts +12 -2
  67. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  68. package/dest/services/discv5/discV5_service.js +84 -15
  69. package/dest/services/discv5/persisted_enr_store.d.ts +38 -0
  70. package/dest/services/discv5/persisted_enr_store.d.ts.map +1 -0
  71. package/dest/services/discv5/persisted_enr_store.js +145 -0
  72. package/dest/services/dummy_service.d.ts +6 -2
  73. package/dest/services/dummy_service.d.ts.map +1 -1
  74. package/dest/services/dummy_service.js +3 -0
  75. package/dest/services/encoding.d.ts +19 -6
  76. package/dest/services/encoding.d.ts.map +1 -1
  77. package/dest/services/encoding.js +25 -15
  78. package/dest/services/gossipsub/topic_score_params.d.ts +6 -23
  79. package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
  80. package/dest/services/gossipsub/topic_score_params.js +4 -31
  81. package/dest/services/libp2p/libp2p_service.d.ts +11 -3
  82. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  83. package/dest/services/libp2p/libp2p_service.js +135 -53
  84. package/dest/services/peer-manager/peer_manager.d.ts +15 -2
  85. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  86. package/dest/services/peer-manager/peer_manager.js +46 -18
  87. package/dest/services/peer-manager/peer_scoring.d.ts +28 -1
  88. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  89. package/dest/services/peer-manager/peer_scoring.js +70 -3
  90. package/dest/services/reqresp/config.d.ts +13 -1
  91. package/dest/services/reqresp/config.d.ts.map +1 -1
  92. package/dest/services/reqresp/config.js +11 -0
  93. package/dest/services/reqresp/rate-limiter/rate_limits.js +3 -3
  94. package/dest/services/reqresp/reqresp.d.ts +1 -1
  95. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  96. package/dest/services/reqresp/reqresp.js +34 -3
  97. package/dest/services/service.d.ts +17 -1
  98. package/dest/services/service.d.ts.map +1 -1
  99. package/dest/services/tx_collection/tx_source.d.ts +1 -1
  100. package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
  101. package/dest/services/tx_collection/tx_source.js +4 -1
  102. package/dest/test-helpers/testbench-utils.d.ts +4 -1
  103. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  104. package/dest/test-helpers/testbench-utils.js +9 -0
  105. package/dest/testbench/p2p_client_testbench_worker.d.ts +1 -1
  106. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  107. package/dest/testbench/p2p_client_testbench_worker.js +19 -2
  108. package/package.json +16 -17
  109. package/src/bootstrap/bootstrap.ts +15 -9
  110. package/src/client/factory.ts +9 -5
  111. package/src/client/interface.ts +29 -6
  112. package/src/client/p2p_client.ts +46 -48
  113. package/src/config.ts +50 -38
  114. package/src/errors/reqresp.error.ts +19 -0
  115. package/src/mem_pools/attestation_pool/attestation_pool.ts +12 -2
  116. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +40 -1
  117. package/src/mem_pools/instrumentation.ts +13 -11
  118. package/src/mem_pools/tx_pool_v2/deleted_pool.ts +7 -7
  119. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +1 -1
  120. package/src/mem_pools/tx_pool_v2/interfaces.ts +28 -4
  121. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +35 -0
  122. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +22 -8
  123. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +158 -33
  124. package/src/msg_validators/attestation_validator/attestation_validator.ts +26 -26
  125. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +4 -3
  126. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +4 -2
  127. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +10 -2
  128. package/src/msg_validators/proposal_validator/proposal_validator.ts +69 -30
  129. package/src/msg_validators/tx_validator/README.md +2 -0
  130. package/src/msg_validators/tx_validator/factory.ts +19 -13
  131. package/src/msg_validators/tx_validator/gas_validator.ts +16 -20
  132. package/src/msg_validators/tx_validator/phases_validator.ts +2 -2
  133. package/src/services/discv5/discV5_service.ts +88 -9
  134. package/src/services/discv5/persisted_enr_store.ts +158 -0
  135. package/src/services/dummy_service.ts +6 -0
  136. package/src/services/encoding.ts +28 -20
  137. package/src/services/gossipsub/README.md +33 -11
  138. package/src/services/gossipsub/topic_score_params.ts +9 -50
  139. package/src/services/libp2p/libp2p_service.ts +159 -56
  140. package/src/services/peer-manager/peer_manager.ts +48 -17
  141. package/src/services/peer-manager/peer_scoring.ts +75 -3
  142. package/src/services/reqresp/README.md +2 -23
  143. package/src/services/reqresp/config.ts +17 -0
  144. package/src/services/reqresp/rate-limiter/rate_limits.ts +3 -3
  145. package/src/services/reqresp/reqresp.ts +42 -2
  146. package/src/services/service.ts +19 -0
  147. package/src/services/tx_collection/tx_source.ts +2 -1
  148. package/src/test-helpers/testbench-utils.ts +12 -0
  149. package/src/testbench/p2p_client_testbench_worker.ts +22 -2
  150. package/dest/msg_validators/clock_tolerance.d.ts +0 -32
  151. package/dest/msg_validators/clock_tolerance.d.ts.map +0 -1
  152. package/dest/msg_validators/clock_tolerance.js +0 -90
  153. package/src/msg_validators/clock_tolerance.ts +0 -121
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/p2p",
3
- "version": "0.0.1-commit.b9865e97",
3
+ "version": "0.0.1-commit.be03c316",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -67,18 +67,18 @@
67
67
  ]
68
68
  },
69
69
  "dependencies": {
70
- "@aztec/constants": "0.0.1-commit.b9865e97",
71
- "@aztec/epoch-cache": "0.0.1-commit.b9865e97",
72
- "@aztec/ethereum": "0.0.1-commit.b9865e97",
73
- "@aztec/foundation": "0.0.1-commit.b9865e97",
74
- "@aztec/kv-store": "0.0.1-commit.b9865e97",
75
- "@aztec/noir-contracts.js": "0.0.1-commit.b9865e97",
76
- "@aztec/noir-protocol-circuits-types": "0.0.1-commit.b9865e97",
77
- "@aztec/protocol-contracts": "0.0.1-commit.b9865e97",
78
- "@aztec/simulator": "0.0.1-commit.b9865e97",
79
- "@aztec/standard-contracts": "0.0.1-commit.b9865e97",
80
- "@aztec/stdlib": "0.0.1-commit.b9865e97",
81
- "@aztec/telemetry-client": "0.0.1-commit.b9865e97",
70
+ "@aztec/constants": "0.0.1-commit.be03c316",
71
+ "@aztec/epoch-cache": "0.0.1-commit.be03c316",
72
+ "@aztec/ethereum": "0.0.1-commit.be03c316",
73
+ "@aztec/foundation": "0.0.1-commit.be03c316",
74
+ "@aztec/kv-store": "0.0.1-commit.be03c316",
75
+ "@aztec/noir-contracts.js": "0.0.1-commit.be03c316",
76
+ "@aztec/noir-protocol-circuits-types": "0.0.1-commit.be03c316",
77
+ "@aztec/protocol-contracts": "0.0.1-commit.be03c316",
78
+ "@aztec/simulator": "0.0.1-commit.be03c316",
79
+ "@aztec/standard-contracts": "0.0.1-commit.be03c316",
80
+ "@aztec/stdlib": "0.0.1-commit.be03c316",
81
+ "@aztec/telemetry-client": "0.0.1-commit.be03c316",
82
82
  "@chainsafe/libp2p-gossipsub": "13.0.0",
83
83
  "@chainsafe/libp2p-noise": "^15.0.0",
84
84
  "@chainsafe/libp2p-yamux": "^6.0.2",
@@ -101,12 +101,11 @@
101
101
  "semver": "^7.6.0",
102
102
  "sha3": "^2.1.4",
103
103
  "snappy": "^7.2.2",
104
- "tslib": "^2.4.0",
105
- "xxhash-wasm": "^1.1.0"
104
+ "tslib": "^2.4.0"
106
105
  },
107
106
  "devDependencies": {
108
- "@aztec/archiver": "0.0.1-commit.b9865e97",
109
- "@aztec/world-state": "0.0.1-commit.b9865e97",
107
+ "@aztec/archiver": "0.0.1-commit.be03c316",
108
+ "@aztec/world-state": "0.0.1-commit.be03c316",
110
109
  "@jest/globals": "^30.0.0",
111
110
  "@types/jest": "^30.0.0",
112
111
  "@types/node": "^22.15.17",
@@ -84,15 +84,21 @@ export class BootstrapNode implements P2PBootstrapApi {
84
84
  this.logger.info('Advertised socket address updated', { addr: addr.toString() });
85
85
  });
86
86
  this.node.on('discovered', async (enr: SignableENR) => {
87
- const addr = await enr.getFullMultiaddr('udp');
88
- this.logger.verbose(`Discovered new peer`, { enr: enr.encodeTxt(), addr: addr?.toString() });
89
- // discv5's discovered() only updates routing table entries that already exist. Nodes that
90
- // established a session with an empty-IP ENR are never inserted, so even after their ENR
91
- // gains a valid socket address the routing table stays empty and FINDNODE always returns 0
92
- // peers. Calling addEnr() here does an insertOrUpdate regardless of prior state, fixing
93
- // the routing table so these nodes become discoverable to other peers.
94
- if (addr) {
95
- this.node.addEnr(enr);
87
+ try {
88
+ const addr = await enr.getFullMultiaddr('udp');
89
+ this.logger.verbose(`Discovered new peer`, { enr: enr.encodeTxt(), addr: addr?.toString() });
90
+ // discv5's discovered() only updates routing table entries that already exist. Nodes that
91
+ // established a session with an empty-IP ENR are never inserted, so even after their ENR
92
+ // gains a valid socket address the routing table stays empty and FINDNODE always returns 0
93
+ // peers. Calling addEnr() here does an insertOrUpdate regardless of prior state, fixing
94
+ // the routing table so these nodes become discoverable to other peers.
95
+ if (addr) {
96
+ this.node.addEnr(enr);
97
+ }
98
+ } catch (err) {
99
+ // A malformed ENR address field makes the parser throw. As an async listener this would crash
100
+ // the bootnode on an unhandled rejection — catch, log, and drop the ENR instead.
101
+ this.logger.warn(`Dropping discovered ENR with unparseable address`, { err });
96
102
  }
97
103
  });
98
104
 
@@ -7,7 +7,7 @@ import { AztecLMDBStoreV2, createStore } from '@aztec/kv-store/lmdb-v2';
7
7
  import type { BlockHash, L2BlockSource } from '@aztec/stdlib/block';
8
8
  import type { ChainConfig } from '@aztec/stdlib/config';
9
9
  import type { ContractDataSource } from '@aztec/stdlib/contract';
10
- import type { BlockMinFeesProvider } from '@aztec/stdlib/gas';
10
+ import { type BlockMinFeesProvider, getNetworkTxGasLimits } from '@aztec/stdlib/gas';
11
11
  import type { AztecNode, ClientProtocolCircuitVerifier, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
12
12
  import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
13
13
  import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
@@ -75,7 +75,10 @@ export async function createP2PClient(
75
75
  }
76
76
 
77
77
  const bindings = logger.getBindings();
78
- const store = deps.store ?? (await createStore(P2P_STORE_NAME, 2, config, bindings));
78
+ // Schema version 4: L2 tips store resolves checkpoint tips from per-tip ids in l2_tip_checkpoints; the
79
+ // block->checkpoint mapping and checkpoint maps were dropped. Bumped to wipe stores whose tips predate
80
+ // per-tip ids, which would otherwise make getL2Tips throw on every read.
81
+ const store = deps.store ?? (await createStore(P2P_STORE_NAME, 4, config, bindings));
79
82
  const archive = await createStore(P2P_ARCHIVE_STORE_NAME, 1, config, bindings);
80
83
  const peerStore = await createStore(P2P_PEER_STORE_NAME, 1, config, bindings);
81
84
  const attestationStore = await createStore(P2P_ATTESTATION_STORE_NAME, 2, config, bindings);
@@ -108,14 +111,14 @@ export async function createP2PClient(
108
111
  const { ts: nextSlotTimestamp } = epochCache.getEpochAndSlotInNextL1Slot();
109
112
  const l1Constants = await archiver.getL1Constants();
110
113
  const gasFees = await blockMinFeesProvider.getCurrentMinFees();
114
+ const networkTxGasLimits = getNetworkTxGasLimits(config, l1Constants);
111
115
  return createTxValidatorForTransactionsEnteringPendingTxPool(
112
116
  worldStateSynchronizer,
113
117
  nextSlotTimestamp,
114
118
  BlockNumber(currentBlockNumber + 1),
115
119
  {
116
- rollupManaLimit: l1Constants.rollupManaLimit,
117
- maxBlockL2Gas: config.validateMaxL2BlockGas,
118
- maxBlockDAGas: config.validateMaxDABlockGas,
120
+ maxTxL2Gas: networkTxGasLimits.l2Gas,
121
+ maxTxDAGas: networkTxGasLimits.daGas,
119
122
  },
120
123
  gasFees,
121
124
  );
@@ -129,6 +132,7 @@ export async function createP2PClient(
129
132
  minTxPoolAgeMs: config.minTxPoolAgeMs,
130
133
  dropTransactionsProbability: config.dropTransactionsProbability,
131
134
  priceBumpPercentage: config.priceBumpPercentage,
135
+ keepFinalizedTxsForSlots: config.keepFinalizedTxsForSlots,
132
136
  },
133
137
  dateProvider,
134
138
  );
@@ -13,6 +13,7 @@ import type { ReqRespSubProtocol, ReqRespSubProtocolHandler } from '../services/
13
13
  import type {
14
14
  DuplicateAttestationInfo,
15
15
  DuplicateProposalInfo,
16
+ OversizedProposalInfo,
16
17
  P2PBlockReceivedCallback,
17
18
  P2PCheckpointAttestationCallback,
18
19
  P2PCheckpointReceivedCallback,
@@ -97,6 +98,14 @@ export type P2P = P2PClient & {
97
98
  */
98
99
  registerDuplicateProposalCallback(callback: (info: DuplicateProposalInfo) => void): void;
99
100
 
101
+ /**
102
+ * Registers a callback invoked when an oversized block proposal (index at or beyond the consensus
103
+ * per-checkpoint block limit) is stored and re-broadcast as slashing evidence.
104
+ *
105
+ * @param callback - Function called with info about the oversized proposal
106
+ */
107
+ registerOversizedProposalCallback(callback: (info: OversizedProposalInfo) => void): void;
108
+
100
109
  /**
101
110
  * Registers a callback invoked when a duplicate attestation is detected (equivocation).
102
111
  * A validator signing attestations for different proposals at the same slot.
@@ -124,16 +133,18 @@ export type P2P = P2PClient & {
124
133
  /**
125
134
  * Returns a transaction in the transaction pool by its hash.
126
135
  * @param txHash - Hash of tx to return.
136
+ * @param opts - Set `includeProof: false` to skip loading the tx proof from the DB.
127
137
  * @returns A single tx or undefined.
128
138
  */
129
- getTxByHashFromPool(txHash: TxHash): Promise<Tx | undefined>;
139
+ getTxByHashFromPool(txHash: TxHash, opts?: { includeProof?: boolean }): Promise<Tx | undefined>;
130
140
 
131
141
  /**
132
142
  * Returns transactions in the transaction pool by hash.
133
143
  * @param txHashes - Hashes of txs to return.
144
+ * @param opts - Set `includeProof: false` to skip loading tx proofs from the DB.
134
145
  * @returns An array of txs or undefined.
135
146
  */
136
- getTxsByHashFromPool(txHashes: TxHash[]): Promise<(Tx | undefined)[]>;
147
+ getTxsByHashFromPool(txHashes: TxHash[], opts?: { includeProof?: boolean }): Promise<(Tx | undefined)[]>;
137
148
 
138
149
  /**
139
150
  * Checks if transactions exist in the pool
@@ -156,15 +167,27 @@ export type P2P = P2PClient & {
156
167
  */
157
168
  getTxStatus(txHash: TxHash): Promise<'pending' | 'mined' | 'deleted' | undefined>;
158
169
 
159
- /** Returns an iterator over pending txs on the mempool. */
160
- iteratePendingTxs(): AsyncIterableIterator<Tx>;
170
+ /**
171
+ * Returns an iterator over pending txs on the mempool.
172
+ * Set `includeProof: false` to skip loading tx proofs from the DB.
173
+ */
174
+ iteratePendingTxs(opts?: { includeProof?: boolean }): AsyncIterableIterator<Tx>;
161
175
 
162
- /** Returns an iterator over pending txs that have been in the pool long enough to be eligible for block building. */
163
- iterateEligiblePendingTxs(): AsyncIterableIterator<Tx>;
176
+ /**
177
+ * Returns an iterator over pending txs that have been in the pool long enough to be eligible for block building.
178
+ * Set `includeProof: false` to skip loading tx proofs from the DB.
179
+ */
180
+ iterateEligiblePendingTxs(opts?: { includeProof?: boolean }): AsyncIterableIterator<Tx>;
164
181
 
165
182
  /** Returns the number of pending txs in the mempool. */
166
183
  getPendingTxCount(): Promise<number>;
167
184
 
185
+ /**
186
+ * Returns whether at least `minCount` pending txs have been in the pool long enough to be eligible for block
187
+ * building. Early-exits once the threshold is met instead of counting every eligible tx.
188
+ */
189
+ hasEligiblePendingTxs(minCount: number): Promise<boolean>;
190
+
168
191
  /**
169
192
  * Protects existing transactions by hash for a given slot.
170
193
  * Returns hashes of transactions that weren't found in the pool.
@@ -6,7 +6,6 @@ import {
6
6
  SlotNumber,
7
7
  } from '@aztec/foundation/branded-types';
8
8
  import { createLogger } from '@aztec/foundation/log';
9
- import { RunningPromise } from '@aztec/foundation/promise';
10
9
  import { DateProvider } from '@aztec/foundation/timer';
11
10
  import type { AztecAsyncKVStore, AztecAsyncSingleton } from '@aztec/kv-store';
12
11
  import { L2TipsKVStore } from '@aztec/kv-store/stores';
@@ -15,17 +14,17 @@ import {
15
14
  type BlockHash,
16
15
  type CheckpointId,
17
16
  type EthAddress,
17
+ EventDrivenL2BlockStream,
18
18
  type L2Block,
19
19
  type L2BlockId,
20
20
  type L2BlockSource,
21
- L2BlockStream,
22
21
  type L2BlockStreamEvent,
23
- type L2Tips,
24
22
  type L2TipsStore,
23
+ type LocalL2Tips,
25
24
  } from '@aztec/stdlib/block';
26
25
  import type { ContractDataSource } from '@aztec/stdlib/contract';
27
26
  import { getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
28
- import { type PeerInfo, tryStop } from '@aztec/stdlib/interfaces/server';
27
+ import { type GetTxByHashOptions, type PeerInfo, tryStop } from '@aztec/stdlib/interfaces/server';
29
28
  import { type BlockProposal, CheckpointAttestation, type CheckpointProposal, type TopicType } from '@aztec/stdlib/p2p';
30
29
  import type { BlockHeader, Tx, TxHash } from '@aztec/stdlib/tx';
31
30
  import { Attributes, type TelemetryClient, WithTracer, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
@@ -43,6 +42,7 @@ import { ReqRespSubProtocol, type ReqRespSubProtocolHandler } from '../services/
43
42
  import type {
44
43
  DuplicateAttestationInfo,
45
44
  DuplicateProposalInfo,
45
+ OversizedProposalInfo,
46
46
  P2PBlockReceivedCallback,
47
47
  P2PCheckpointReceivedCallback,
48
48
  P2PService,
@@ -74,7 +74,7 @@ export class P2PClient extends WithTracer implements P2P {
74
74
 
75
75
  private config: P2PConfig;
76
76
 
77
- private blockStream: L2BlockStream | undefined;
77
+ private blockStream: EventDrivenL2BlockStream | undefined;
78
78
 
79
79
  private txProvider: TxProvider;
80
80
 
@@ -83,9 +83,6 @@ export class P2PClient extends WithTracer implements P2P {
83
83
  /** Tracks the last slot for which we called prepareForSlot */
84
84
  private lastSlotProcessed: SlotNumber = SlotNumber.ZERO;
85
85
 
86
- /** Polls for slot changes and calls prepareForSlot on the tx pool */
87
- private slotMonitor: RunningPromise | undefined;
88
-
89
86
  constructor(
90
87
  private store: AztecAsyncKVStore,
91
88
  private l2BlockSource: L2BlockSource & ContractDataSource,
@@ -152,7 +149,7 @@ export class P2PClient extends WithTracer implements P2P {
152
149
  this.p2pService.updateConfig(config);
153
150
  }
154
151
 
155
- public getL2Tips(): Promise<L2Tips> {
152
+ public getL2Tips(): Promise<LocalL2Tips> {
156
153
  return this.l2Tips.getL2Tips();
157
154
  }
158
155
 
@@ -178,10 +175,12 @@ export class P2PClient extends WithTracer implements P2P {
178
175
  break;
179
176
  case 'chain-pruned':
180
177
  this.txCollection.stopCollectingForBlocksAfter(event.block.number);
181
- await this.handlePruneL2Blocks(event.block, event.checkpoint);
178
+ await this.handlePruneL2Blocks(event.block, event.checkpointed.checkpoint);
182
179
  break;
183
180
  case 'chain-checkpointed':
184
181
  break;
182
+ case 'chain-proposed':
183
+ break;
185
184
  default: {
186
185
  const _: never = event;
187
186
  break;
@@ -268,14 +267,6 @@ export class P2PClient extends WithTracer implements P2P {
268
267
  this.blockStream.start();
269
268
  this.txFileStore?.start();
270
269
 
271
- // Start slot monitor to call prepareForSlot when the slot changes
272
- this.slotMonitor = new RunningPromise(
273
- () => this.maybeCallPrepareForSlot(),
274
- this.log,
275
- this.config.slotCheckIntervalMS,
276
- );
277
- this.slotMonitor.start();
278
-
279
270
  return this.syncPromise;
280
271
  }
281
272
 
@@ -286,7 +277,7 @@ export class P2PClient extends WithTracer implements P2P {
286
277
  private initBlockStream(startingBlock?: BlockNumber) {
287
278
  if (!this.blockStream) {
288
279
  const { blockRequestBatchSize: batchSize, blockCheckIntervalMS: pollIntervalMS } = this.config;
289
- this.blockStream = new L2BlockStream(
280
+ this.blockStream = new EventDrivenL2BlockStream(
290
281
  this.l2BlockSource,
291
282
  this,
292
283
  this,
@@ -302,8 +293,6 @@ export class P2PClient extends WithTracer implements P2P {
302
293
  */
303
294
  public async stop() {
304
295
  this.log.debug('Stopping p2p client...');
305
- await this.slotMonitor?.stop();
306
- this.log.debug('Stopped slot monitor');
307
296
  await tryStop(this.txCollection);
308
297
  this.log.debug('Stopped tx collection service');
309
298
  await this.txFileStore?.stop();
@@ -406,6 +395,10 @@ export class P2PClient extends WithTracer implements P2P {
406
395
  return this.attestationPool.hasBlockProposalsForSlot(slot);
407
396
  }
408
397
 
398
+ public hasCheckpointProposalForSlot(slot: SlotNumber): Promise<boolean> {
399
+ return this.attestationPool.hasCheckpointProposalForSlot(slot);
400
+ }
401
+
409
402
  // REVIEW: https://github.com/AztecProtocol/aztec-packages/issues/7963
410
403
  // ^ This pattern is not my favorite (md)
411
404
  public registerBlockProposalHandler(handler: P2PBlockReceivedCallback): void {
@@ -424,6 +417,10 @@ export class P2PClient extends WithTracer implements P2P {
424
417
  this.p2pService.registerDuplicateProposalCallback(callback);
425
418
  }
426
419
 
420
+ public registerOversizedProposalCallback(callback: (info: OversizedProposalInfo) => void): void {
421
+ this.p2pService.registerOversizedProposalCallback(callback);
422
+ }
423
+
427
424
  public registerDuplicateAttestationCallback(callback: (info: DuplicateAttestationInfo) => void): void {
428
425
  this.p2pService.registerDuplicateAttestationCallback(callback);
429
426
  }
@@ -432,7 +429,7 @@ export class P2PClient extends WithTracer implements P2P {
432
429
  this.p2pService.registerCheckpointAttestationCallback(callback);
433
430
  }
434
431
 
435
- public async getPendingTxs(limit?: number, after?: TxHash): Promise<Tx[]> {
432
+ public async getPendingTxs(limit?: number, after?: TxHash, options?: GetTxByHashOptions): Promise<Tx[]> {
436
433
  if (limit !== undefined && limit <= 0) {
437
434
  throw new TypeError('limit must be greater than 0');
438
435
  }
@@ -451,7 +448,9 @@ export class P2PClient extends WithTracer implements P2P {
451
448
  const endIndex = limit !== undefined ? startIndex + limit : undefined;
452
449
  txHashes = txHashes.slice(startIndex, endIndex);
453
450
 
454
- const maybeTxs = await Promise.all(txHashes.map(txHash => this.txPool.getTxByHash(txHash)));
451
+ // This is a public-facing API (exposed via both the node and the p2p RPC), so proofs are opt-in.
452
+ const includeProof = !!options?.includeProof;
453
+ const maybeTxs = await Promise.all(txHashes.map(txHash => this.txPool.getTxByHash(txHash, { includeProof })));
455
454
  return maybeTxs.filter((tx): tx is Tx => !!tx);
456
455
  }
457
456
 
@@ -459,18 +458,22 @@ export class P2PClient extends WithTracer implements P2P {
459
458
  return this.txPool.getPendingTxCount();
460
459
  }
461
460
 
462
- public async *iteratePendingTxs(): AsyncIterableIterator<Tx> {
461
+ public hasEligiblePendingTxs(minCount: number): Promise<boolean> {
462
+ return this.txPool.hasEligiblePendingTxs(minCount);
463
+ }
464
+
465
+ public async *iteratePendingTxs(opts?: { includeProof?: boolean }): AsyncIterableIterator<Tx> {
463
466
  for (const txHash of await this.txPool.getPendingTxHashes()) {
464
- const tx = await this.txPool.getTxByHash(txHash);
467
+ const tx = await this.txPool.getTxByHash(txHash, opts);
465
468
  if (tx) {
466
469
  yield tx;
467
470
  }
468
471
  }
469
472
  }
470
473
 
471
- public async *iterateEligiblePendingTxs(): AsyncIterableIterator<Tx> {
474
+ public async *iterateEligiblePendingTxs(opts?: { includeProof?: boolean }): AsyncIterableIterator<Tx> {
472
475
  for (const txHash of await this.txPool.getEligiblePendingTxHashes()) {
473
- const tx = await this.txPool.getTxByHash(txHash);
476
+ const tx = await this.txPool.getTxByHash(txHash, opts);
474
477
  if (tx) {
475
478
  yield tx;
476
479
  }
@@ -480,19 +483,21 @@ export class P2PClient extends WithTracer implements P2P {
480
483
  /**
481
484
  * Returns a transaction in the transaction pool by its hash.
482
485
  * @param txHash - Hash of the transaction to look for in the pool.
486
+ * @param opts - Set `includeProof: false` to skip loading the tx proof from the DB.
483
487
  * @returns A single tx or undefined.
484
488
  */
485
- getTxByHashFromPool(txHash: TxHash): Promise<Tx | undefined> {
486
- return this.txPool.getTxByHash(txHash);
489
+ getTxByHashFromPool(txHash: TxHash, opts?: { includeProof?: boolean }): Promise<Tx | undefined> {
490
+ return this.txPool.getTxByHash(txHash, opts);
487
491
  }
488
492
 
489
493
  /**
490
494
  * Returns transactions in the transaction pool by hash.
491
495
  * @param txHashes - Hashes of the transactions to look for.
496
+ * @param opts - Set `includeProof: false` to skip loading tx proofs from the DB.
492
497
  * @returns The txs found, in the same order as the requested hashes. If a tx is not found, it will be undefined.
493
498
  */
494
- getTxsByHashFromPool(txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
495
- return this.txPool.getTxsByHash(txHashes);
499
+ getTxsByHashFromPool(txHashes: TxHash[], opts?: { includeProof?: boolean }): Promise<(Tx | undefined)[]> {
500
+ return this.txPool.getTxsByHash(txHashes, opts);
496
501
  }
497
502
 
498
503
  hasTxsInPool(txHashes: TxHash[]): Promise<boolean[]> {
@@ -634,11 +639,16 @@ export class P2PClient extends WithTracer implements P2P {
634
639
  return;
635
640
  }
636
641
 
642
+ const lastBlock = blocks.at(-1)!;
643
+ const lastSlot = lastBlock.header.getSlot();
644
+
645
+ // Mark txs mined before releasing protections: a block landing at this slot supersedes any
646
+ // protection for txs it includes, so mined-marking must run first to keep just-landed txs from
647
+ // being unprotected into pending where they could be evicted before they are recorded as mined.
637
648
  await this.handleMinedBlocks(blocks);
638
- await this.maybeCallPrepareForSlot();
649
+ await this.maybeCallPrepareForSlot(lastSlot);
639
650
  await this.collectingMissingTxs(blocks);
640
- const lastBlock = blocks.at(-1)!;
641
- await this.synchedLatestSlot.set(BigInt(lastBlock.header.getSlot()));
651
+ await this.synchedLatestSlot.set(BigInt(lastSlot));
642
652
  }
643
653
 
644
654
  /** Request txs for unproven blocks so the prover node can prove. */
@@ -733,20 +743,8 @@ export class P2PClient extends WithTracer implements P2P {
733
743
  return isEpochPrune;
734
744
  }
735
745
 
736
- /** Checks if the slot has changed and calls prepareForSlot if so. */
737
- private async maybeCallPrepareForSlot(): Promise<void> {
738
- // If we have a proposed checkpoint available, we want to prepare the target slot - otherwise we prepare the current slot
739
- const l2Tips = await this.l2Tips.getL2Tips();
740
- const hasProposedCheckpoint = l2Tips.proposedCheckpoint.checkpoint.number > l2Tips.checkpointed.checkpoint.number;
741
-
742
- let slot;
743
- if (hasProposedCheckpoint) {
744
- const { targetSlot } = this.epochCache.getTargetAndNextSlot();
745
- slot = targetSlot;
746
- } else {
747
- const { currentSlot } = this.epochCache.getCurrentAndNextSlot();
748
- slot = currentSlot;
749
- }
746
+ /** Calls prepareForSlot for the given slot if it advances past the last slot we prepared for. */
747
+ private async maybeCallPrepareForSlot(slot: SlotNumber): Promise<void> {
750
748
  if (slot <= this.lastSlotProcessed) {
751
749
  return;
752
750
  }
package/src/config.ts CHANGED
@@ -3,6 +3,7 @@ import {
3
3
  SecretValue,
4
4
  bigintConfigHelper,
5
5
  booleanConfigHelper,
6
+ floatConfigHelper,
6
7
  getConfigFromMappings,
7
8
  getDefaultConfig,
8
9
  numberConfigHelper,
@@ -42,34 +43,26 @@ export interface P2PConfig
42
43
  TxFileStoreConfig,
43
44
  Pick<
44
45
  SequencerConfig,
45
- | 'blockDurationMs'
46
46
  | 'expectedBlockProposalsPerSlot'
47
- | 'l1PublishingTime'
48
47
  | 'maxTxsPerBlock'
49
- | 'attestationPropagationTime'
48
+ | 'checkpointProposalSyncGraceSeconds'
50
49
  | 'maxBlocksPerCheckpoint'
51
- > {
50
+ >,
51
+ // `blockDurationMs` is optional on the loose `SequencerConfig` but is always populated for p2p via
52
+ // the shared `numberConfigHelper(3000)` mapping, so it is required here.
53
+ Required<Pick<SequencerConfig, 'blockDurationMs'>> {
52
54
  /** Maximum transactions per block for validation. Overrides maxTxsPerBlock for gossip validation when set. */
53
55
  validateMaxTxsPerBlock?: number;
54
56
 
55
57
  /** Maximum transactions per checkpoint for validation. Used as fallback for maxTxsPerBlock when that is not set. */
56
58
  validateMaxTxsPerCheckpoint?: number;
57
59
 
58
- /** Maximum L2 gas per block for validation. When set, txs exceeding this limit are rejected. */
59
- validateMaxL2BlockGas?: number;
60
-
61
- /** Maximum DA gas per block for validation. When set, txs exceeding this limit are rejected. */
62
- validateMaxDABlockGas?: number;
63
-
64
60
  /** A flag dictating whether the P2P subsystem should be enabled. */
65
61
  p2pEnabled: boolean;
66
62
 
67
63
  /** The frequency in which to check for new L2 blocks. */
68
64
  blockCheckIntervalMS: number;
69
65
 
70
- /** The frequency in which to check for new L2 slots. */
71
- slotCheckIntervalMS: number;
72
-
73
66
  /** The number of blocks to fetch in a single batch. */
74
67
  blockRequestBatchSize: number;
75
68
 
@@ -150,6 +143,13 @@ export interface P2PConfig
150
143
  /** How long to keep message IDs in the seen cache (ms). */
151
144
  gossipsubSeenTTL: number;
152
145
 
146
+ /**
147
+ * Maximum clock-disparity tolerance (ms) applied to proposal/attestation gossip receive windows. Both
148
+ * ends of each acceptance window are widened by this much so peers are not penalized for messages valid
149
+ * when sent but arriving slightly early or late due to clock skew (Ethereum's MAXIMUM_GOSSIP_CLOCK_DISPARITY).
150
+ */
151
+ maxGossipClockDisparityMs: number;
152
+
153
153
  /** The 'age' (in # of L2 blocks) of a processed tx after which we heavily penalize a peer for re-sending it. */
154
154
  doubleSpendSeverePeerPenaltyWindow: number;
155
155
 
@@ -165,6 +165,9 @@ export interface P2PConfig
165
165
  /** The values for the peer scoring system. Passed as a comma separated list of values in order: low, mid, high tolerance errors. */
166
166
  peerPenaltyValues: number[];
167
167
 
168
+ /** How long (in seconds) a peer is banned for once its score drops below the ban threshold. */
169
+ peerBanDurationSeconds: number;
170
+
168
171
  /** Limit of transactions to archive in the tx pool. Once the archived tx limit is reached, the oldest archived txs will be purged. */
169
172
  archivedTxLimit: number;
170
173
 
@@ -241,6 +244,12 @@ export interface P2PConfig
241
244
  /** Minimum percentage fee increase required to replace an existing tx via RPC (0 = no bump). */
242
245
  priceBumpPercentage: bigint;
243
246
 
247
+ /**
248
+ * Number of slots behind the finalized tip to keep finalized txs for before deleting them. 0 deletes
249
+ * at the finalized tip (default).
250
+ */
251
+ keepFinalizedTxsForSlots: number;
252
+
244
253
  /** Drop incoming block and checkpoint proposals at the libp2p dispatch layer (for testing only) */
245
254
  skipIncomingProposals?: boolean;
246
255
 
@@ -278,16 +287,6 @@ export const p2pConfigMappings: ConfigMappingsType<P2PConfig> = {
278
287
  'Maximum transactions per checkpoint for validation. Used as fallback for maxTxsPerBlock when that is not set.',
279
288
  ...optionalNumberConfigHelper(),
280
289
  },
281
- validateMaxL2BlockGas: {
282
- env: 'VALIDATOR_MAX_L2_BLOCK_GAS',
283
- description: 'Maximum L2 gas per block for validation. When set, txs exceeding this limit are rejected.',
284
- ...optionalNumberConfigHelper(),
285
- },
286
- validateMaxDABlockGas: {
287
- env: 'VALIDATOR_MAX_DA_BLOCK_GAS',
288
- description: 'Maximum DA gas per block for validation. When set, txs exceeding this limit are rejected.',
289
- ...optionalNumberConfigHelper(),
290
- },
291
290
  p2pEnabled: {
292
291
  env: 'P2P_ENABLED',
293
292
  description: 'A flag dictating whether the P2P subsystem should be enabled.',
@@ -303,11 +302,6 @@ export const p2pConfigMappings: ConfigMappingsType<P2PConfig> = {
303
302
  description: 'The frequency in which to check for new L2 blocks.',
304
303
  ...numberConfigHelper(100),
305
304
  },
306
- slotCheckIntervalMS: {
307
- env: 'P2P_SLOT_CHECK_INTERVAL_MS',
308
- description: 'The frequency in which to check for new L2 slots.',
309
- ...numberConfigHelper(1000),
310
- },
311
305
  debugDisableColocationPenalty: {
312
306
  env: 'DEBUG_P2P_DISABLE_COLOCATION_PENALTY',
313
307
  description: 'DEBUG: Disable colocation penalty - NEVER set to true in production',
@@ -439,20 +433,26 @@ export const p2pConfigMappings: ConfigMappingsType<P2PConfig> = {
439
433
  description: 'How long to keep message IDs in the seen cache.',
440
434
  ...numberConfigHelper(20 * 60 * 1000),
441
435
  },
436
+ maxGossipClockDisparityMs: {
437
+ env: 'P2P_MAX_GOSSIP_CLOCK_DISPARITY_MS',
438
+ description:
439
+ 'Maximum clock-disparity tolerance (ms) applied to both ends of proposal/attestation gossip receive windows.',
440
+ ...numberConfigHelper(500),
441
+ },
442
442
  gossipsubTxTopicWeight: {
443
443
  env: 'P2P_GOSSIPSUB_TX_TOPIC_WEIGHT',
444
444
  description: 'The weight of the tx topic for the gossipsub protocol.',
445
- ...numberConfigHelper(1),
445
+ ...floatConfigHelper(1),
446
446
  },
447
447
  gossipsubTxInvalidMessageDeliveriesWeight: {
448
448
  env: 'P2P_GOSSIPSUB_TX_INVALID_MESSAGE_DELIVERIES_WEIGHT',
449
449
  description: 'The weight of the tx invalid message deliveries for the gossipsub protocol.',
450
- ...numberConfigHelper(-20),
450
+ ...floatConfigHelper(-20),
451
451
  },
452
452
  gossipsubTxInvalidMessageDeliveriesDecay: {
453
453
  env: 'P2P_GOSSIPSUB_TX_INVALID_MESSAGE_DELIVERIES_DECAY',
454
454
  description: 'Determines how quickly the penalty for invalid message deliveries decays over time. Between 0 and 1.',
455
- ...numberConfigHelper(0.5),
455
+ ...floatConfigHelper(0.5),
456
456
  },
457
457
  peerPenaltyValues: {
458
458
  env: 'P2P_PEER_PENALTY_VALUES',
@@ -461,6 +461,11 @@ export const p2pConfigMappings: ConfigMappingsType<P2PConfig> = {
461
461
  'The values for the peer scoring system. Passed as a comma separated list of values in order: low, mid, high tolerance errors.',
462
462
  defaultValue: [2, 10, 50],
463
463
  },
464
+ peerBanDurationSeconds: {
465
+ env: 'P2P_PEER_BAN_DURATION_SECONDS',
466
+ description: 'How long (in seconds) a peer is banned for once its score drops below the ban threshold.',
467
+ ...numberConfigHelper(24 * 60 * 60),
468
+ },
464
469
  doubleSpendSeverePeerPenaltyWindow: {
465
470
  env: 'P2P_DOUBLE_SPEND_SEVERE_PEER_PENALTY_WINDOW',
466
471
  description: 'The "age" (in L2 blocks) of a tx after which we heavily penalize a peer for sending it.',
@@ -563,11 +568,6 @@ export const p2pConfigMappings: ConfigMappingsType<P2PConfig> = {
563
568
  description: 'Alters the format of p2p messages to include things like broadcast timestamp FOR TESTING ONLY',
564
569
  ...booleanConfigHelper(false),
565
570
  },
566
- l1PublishingTime: {
567
- env: 'SEQ_L1_PUBLISHING_TIME_ALLOWANCE_IN_SLOT',
568
- description: 'How much time (in seconds) we allow in the slot for publishing the L1 tx (defaults to 1 L1 slot).',
569
- ...optionalNumberConfigHelper(),
570
- },
571
571
  fishermanMode: {
572
572
  env: 'FISHERMAN_MODE',
573
573
  description:
@@ -615,7 +615,19 @@ export const p2pConfigMappings: ConfigMappingsType<P2PConfig> = {
615
615
  'Minimum percentage fee increase required to replace an existing tx via RPC. Even at 0%, replacement still requires paying at least 1 unit more.',
616
616
  ...bigintConfigHelper(10n),
617
617
  },
618
- ...sharedSequencerConfigMappings,
618
+ keepFinalizedTxsForSlots: {
619
+ env: 'P2P_KEEP_FINALIZED_TXS_FOR_SLOTS',
620
+ description:
621
+ 'Number of slots behind the finalized tip to keep finalized txs for before deleting them. 0 deletes at the finalized tip.',
622
+ ...numberConfigHelper(0),
623
+ },
624
+ ...pickConfigMappings(sharedSequencerConfigMappings, [
625
+ 'expectedBlockProposalsPerSlot',
626
+ 'maxTxsPerBlock',
627
+ 'checkpointProposalSyncGraceSeconds',
628
+ 'maxBlocksPerCheckpoint',
629
+ 'blockDurationMs',
630
+ ]),
619
631
  ...p2pReqRespConfigMappings,
620
632
  ...batchTxRequesterConfigMappings,
621
633
  ...chainConfigMappings,
@@ -741,7 +753,7 @@ export function parseAllowList(value: string): AllowedElement[] {
741
753
 
742
754
  if (typeString === 'I') {
743
755
  entries.push({
744
- address: AztecAddress.fromString(identifierString),
756
+ address: AztecAddress.fromStringUnsafe(identifierString),
745
757
  selector,
746
758
  ...flags,
747
759
  });