@aztec/p2p 0.0.1-commit.9ef841308 → 0.0.1-commit.a89ec08

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 (207) hide show
  1. package/dest/client/factory.d.ts +2 -2
  2. package/dest/client/factory.d.ts.map +1 -1
  3. package/dest/client/factory.js +1 -2
  4. package/dest/client/p2p_client.d.ts +1 -1
  5. package/dest/client/p2p_client.d.ts.map +1 -1
  6. package/dest/client/p2p_client.js +4 -6
  7. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +6 -17
  8. package/dest/config.d.ts +6 -6
  9. package/dest/config.d.ts.map +1 -1
  10. package/dest/config.js +6 -6
  11. package/dest/index.d.ts +2 -1
  12. package/dest/index.d.ts.map +1 -1
  13. package/dest/index.js +1 -0
  14. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +4 -4
  15. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  16. package/dest/mem_pools/attestation_pool/attestation_pool.js +4 -8
  17. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +6 -6
  18. package/dest/mem_pools/index.d.ts +2 -1
  19. package/dest/mem_pools/index.d.ts.map +1 -1
  20. package/dest/mem_pools/instrumentation.d.ts +2 -4
  21. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  22. package/dest/mem_pools/instrumentation.js +14 -16
  23. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +125 -0
  24. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -0
  25. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +596 -0
  26. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +32 -0
  27. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +1 -0
  28. package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +112 -0
  29. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +157 -0
  30. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +1 -0
  31. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +52 -0
  32. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +16 -0
  33. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -0
  34. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +123 -0
  35. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +17 -0
  36. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
  37. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +84 -0
  38. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +19 -0
  39. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -0
  40. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +78 -0
  41. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +26 -0
  42. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +1 -0
  43. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +84 -0
  44. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +25 -0
  45. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +1 -0
  46. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +57 -0
  47. package/dest/mem_pools/tx_pool/index.d.ts +3 -0
  48. package/dest/mem_pools/tx_pool/index.d.ts.map +1 -0
  49. package/dest/mem_pools/tx_pool/index.js +2 -0
  50. package/dest/mem_pools/tx_pool/priority.d.ts +12 -0
  51. package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -0
  52. package/dest/mem_pools/tx_pool/priority.js +15 -0
  53. package/dest/mem_pools/tx_pool/tx_pool.d.ts +127 -0
  54. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -0
  55. package/dest/mem_pools/tx_pool/tx_pool.js +3 -0
  56. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +7 -0
  57. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -0
  58. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +402 -0
  59. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +5 -7
  60. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
  61. package/dest/mem_pools/tx_pool_v2/interfaces.js +0 -1
  62. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +6 -5
  63. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
  64. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +1 -5
  65. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +1 -1
  66. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
  67. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +43 -26
  68. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +1 -1
  69. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
  70. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +0 -3
  71. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +1 -2
  72. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
  73. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +1 -18
  74. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +1 -1
  75. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  76. package/dest/msg_validators/attestation_validator/attestation_validator.js +4 -5
  77. package/dest/msg_validators/clock_tolerance.d.ts +1 -1
  78. package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
  79. package/dest/msg_validators/clock_tolerance.js +3 -4
  80. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +1 -1
  81. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
  82. package/dest/msg_validators/proposal_validator/proposal_validator.js +5 -5
  83. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +1 -1
  84. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  85. package/dest/msg_validators/tx_validator/metadata_validator.js +4 -4
  86. package/dest/services/discv5/discV5_service.d.ts +1 -1
  87. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  88. package/dest/services/discv5/discV5_service.js +2 -4
  89. package/dest/services/libp2p/libp2p_service.d.ts +9 -7
  90. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  91. package/dest/services/libp2p/libp2p_service.js +59 -137
  92. package/dest/services/peer-manager/metrics.d.ts +1 -3
  93. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  94. package/dest/services/peer-manager/metrics.js +0 -6
  95. package/dest/services/peer-manager/peer_manager.d.ts +2 -6
  96. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  97. package/dest/services/peer-manager/peer_manager.js +9 -24
  98. package/dest/services/peer-manager/peer_scoring.d.ts +2 -5
  99. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  100. package/dest/services/peer-manager/peer_scoring.js +10 -28
  101. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +8 -11
  102. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
  103. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +101 -82
  104. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +2 -3
  105. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
  106. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +4 -5
  107. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
  108. package/dest/services/reqresp/batch-tx-requester/missing_txs.js +7 -13
  109. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +11 -19
  110. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
  111. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +15 -52
  112. package/dest/services/reqresp/reqresp.d.ts +1 -1
  113. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  114. package/dest/services/reqresp/reqresp.js +3 -4
  115. package/dest/services/service.d.ts +1 -7
  116. package/dest/services/service.d.ts.map +1 -1
  117. package/dest/services/tx_collection/fast_tx_collection.d.ts +4 -1
  118. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
  119. package/dest/services/tx_collection/fast_tx_collection.js +73 -57
  120. package/dest/services/tx_collection/missing_txs_tracker.d.ts +32 -0
  121. package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +1 -0
  122. package/dest/services/tx_collection/missing_txs_tracker.js +27 -0
  123. package/dest/services/tx_collection/proposal_tx_collector.d.ts +7 -6
  124. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -1
  125. package/dest/services/tx_collection/proposal_tx_collector.js +4 -4
  126. package/dest/services/tx_collection/slow_tx_collection.js +1 -1
  127. package/dest/services/tx_collection/tx_collection.d.ts +6 -3
  128. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  129. package/dest/test-helpers/make-test-p2p-clients.d.ts +1 -1
  130. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  131. package/dest/test-helpers/mock-pubsub.d.ts +1 -6
  132. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  133. package/dest/test-helpers/mock-pubsub.js +1 -9
  134. package/dest/test-helpers/reqresp-nodes.d.ts +1 -1
  135. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  136. package/dest/test-helpers/testbench-utils.d.ts +1 -1
  137. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  138. package/dest/test-helpers/testbench-utils.js +2 -20
  139. package/dest/testbench/p2p_client_testbench_worker.js +15 -44
  140. package/dest/testbench/worker_client_manager.d.ts +1 -1
  141. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  142. package/dest/testbench/worker_client_manager.js +2 -2
  143. package/dest/util.d.ts +4 -9
  144. package/dest/util.d.ts.map +1 -1
  145. package/dest/util.js +9 -2
  146. package/package.json +14 -14
  147. package/src/client/factory.ts +2 -3
  148. package/src/client/p2p_client.ts +4 -6
  149. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +9 -19
  150. package/src/config.ts +10 -10
  151. package/src/index.ts +1 -0
  152. package/src/mem_pools/attestation_pool/attestation_pool.ts +7 -8
  153. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +6 -6
  154. package/src/mem_pools/index.ts +3 -0
  155. package/src/mem_pools/instrumentation.ts +13 -17
  156. package/src/mem_pools/tx_pool/README.md +270 -0
  157. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +746 -0
  158. package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +132 -0
  159. package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +208 -0
  160. package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +163 -0
  161. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +104 -0
  162. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +93 -0
  163. package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +106 -0
  164. package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +75 -0
  165. package/src/mem_pools/tx_pool/index.ts +2 -0
  166. package/src/mem_pools/tx_pool/priority.ts +20 -0
  167. package/src/mem_pools/tx_pool/tx_pool.ts +141 -0
  168. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +321 -0
  169. package/src/mem_pools/tx_pool_v2/interfaces.ts +4 -7
  170. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +5 -11
  171. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +43 -29
  172. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +0 -3
  173. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +1 -19
  174. package/src/msg_validators/attestation_validator/README.md +1 -1
  175. package/src/msg_validators/attestation_validator/attestation_validator.ts +4 -5
  176. package/src/msg_validators/clock_tolerance.ts +3 -4
  177. package/src/msg_validators/proposal_validator/README.md +4 -4
  178. package/src/msg_validators/proposal_validator/proposal_validator.ts +5 -6
  179. package/src/msg_validators/tx_validator/metadata_validator.ts +4 -12
  180. package/src/services/discv5/discV5_service.ts +2 -4
  181. package/src/services/libp2p/libp2p_service.ts +71 -135
  182. package/src/services/peer-manager/metrics.ts +0 -7
  183. package/src/services/peer-manager/peer_manager.ts +9 -28
  184. package/src/services/peer-manager/peer_scoring.ts +5 -21
  185. package/src/services/reqresp/batch-tx-requester/README.md +7 -46
  186. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +111 -78
  187. package/src/services/reqresp/batch-tx-requester/interface.ts +1 -2
  188. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +6 -13
  189. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +24 -68
  190. package/src/services/reqresp/reqresp.ts +3 -5
  191. package/src/services/service.ts +0 -7
  192. package/src/services/tx_collection/fast_tx_collection.ts +83 -57
  193. package/src/services/tx_collection/missing_txs_tracker.ts +52 -0
  194. package/src/services/tx_collection/proposal_tx_collector.ts +13 -8
  195. package/src/services/tx_collection/slow_tx_collection.ts +1 -1
  196. package/src/services/tx_collection/tx_collection.ts +5 -3
  197. package/src/test-helpers/make-test-p2p-clients.ts +1 -1
  198. package/src/test-helpers/mock-pubsub.ts +0 -9
  199. package/src/test-helpers/reqresp-nodes.ts +1 -1
  200. package/src/test-helpers/testbench-utils.ts +3 -28
  201. package/src/testbench/p2p_client_testbench_worker.ts +15 -44
  202. package/src/testbench/worker_client_manager.ts +2 -2
  203. package/src/util.ts +13 -9
  204. package/dest/services/tx_collection/request_tracker.d.ts +0 -53
  205. package/dest/services/tx_collection/request_tracker.d.ts.map +0 -1
  206. package/dest/services/tx_collection/request_tracker.js +0 -84
  207. package/src/services/tx_collection/request_tracker.ts +0 -127
@@ -44,8 +44,6 @@ export type TxPoolV2Config = {
44
44
  minTxPoolAgeMs: number;
45
45
  /** Maximum number of evicted tx hashes to remember for metrics tracking */
46
46
  evictedTxCacheSize: number;
47
- /** The probability (0-1) that a transaction is discarded. 0 disables dropping. For testing purposes only. */
48
- dropTransactionsProbability: number;
49
47
  /** Minimum percentage fee increase required to replace an existing tx via RPC (0 = no bump). */
50
48
  priceBumpPercentage: bigint;
51
49
  };
@@ -58,7 +56,6 @@ export const DEFAULT_TX_POOL_V2_CONFIG: TxPoolV2Config = {
58
56
  archivedTxLimit: 0, // 0 = disabled
59
57
  minTxPoolAgeMs: 2_000,
60
58
  evictedTxCacheSize: 10_000,
61
- dropTransactionsProbability: 0,
62
59
  priceBumpPercentage: 10n,
63
60
  };
64
61
 
@@ -160,10 +157,10 @@ export interface TxPoolV2 extends TypedEventEmitter<TxPoolV2Events> {
160
157
  handleMinedBlock(block: L2Block): Promise<void>;
161
158
 
162
159
  /**
163
- * Prepares the pool for a new slot by unprotecting transactions from earlier
164
- * slots and re-validating them before returning to pending state.
165
- * @param slotNumber - The pipeline slot we are building for (i.e. the slot
166
- * the resulting blocks will target on L1).
160
+ * Prepares the pool for a new slot.
161
+ * Unprotects transactions from earlier slots and validates them before
162
+ * returning to pending state.
163
+ * @param slotNumber - The slot number to prepare for
167
164
  */
168
165
  prepareForSlot(slotNumber: SlotNumber): Promise<void>;
169
166
 
@@ -1,4 +1,3 @@
1
- import { minBigint } from '@aztec/foundation/bigint';
2
1
  import { BlockNumber } from '@aztec/foundation/branded-types';
3
2
  import { Fr } from '@aztec/foundation/curves/bn254';
4
3
  import { ProtocolContractAddress } from '@aztec/protocol-contracts';
@@ -7,6 +6,7 @@ import { Gas } from '@aztec/stdlib/gas';
7
6
  import { type Tx, TxHash } from '@aztec/stdlib/tx';
8
7
 
9
8
  import { getFeePayerBalanceDelta } from '../../msg_validators/tx_validator/fee_payer_balance.js';
9
+ import { getTxPriorityFee } from '../tx_pool/priority.js';
10
10
  import { type PreAddResult, TxPoolRejectionCode } from './eviction/interfaces.js';
11
11
 
12
12
  /** Validator-compatible data interface, mirroring the subset of PrivateKernelTailCircuitPublicInputs used by validators. */
@@ -166,13 +166,13 @@ export function txHashFromBigInt(value: bigint): string {
166
166
  }
167
167
 
168
168
  /** Minimal fields required for priority comparison. */
169
- export type PriorityComparable = Pick<TxMetaData, 'txHash' | 'txHashBigInt' | 'priorityFee'>;
169
+ type PriorityComparable = Pick<TxMetaData, 'txHashBigInt' | 'priorityFee'>;
170
170
 
171
171
  /**
172
172
  * Compares two priority fees in ascending order.
173
173
  * Returns negative if a < b, positive if a > b, 0 if equal.
174
174
  */
175
- export function compareFee(a: bigint, b: bigint): -1 | 0 | 1 {
175
+ export function compareFee(a: bigint, b: bigint): number {
176
176
  return a < b ? -1 : a > b ? 1 : 0;
177
177
  }
178
178
 
@@ -181,7 +181,7 @@ export function compareFee(a: bigint, b: bigint): -1 | 0 | 1 {
181
181
  * Uses field element comparison for deterministic ordering.
182
182
  * Returns negative if a < b, positive if a > b, 0 if equal.
183
183
  */
184
- export function compareTxHash(a: bigint, b: bigint): -1 | 0 | 1 {
184
+ export function compareTxHash(a: bigint, b: bigint): number {
185
185
  return Fr.cmpAsBigInt(a, b);
186
186
  }
187
187
 
@@ -190,7 +190,7 @@ export function compareTxHash(a: bigint, b: bigint): -1 | 0 | 1 {
190
190
  * Returns negative if a < b, positive if a > b, 0 if equal.
191
191
  * Use with sort() for ascending order, or negate/reverse for descending.
192
192
  */
193
- export function comparePriority(a: PriorityComparable, b: PriorityComparable): -1 | 0 | 1 {
193
+ export function comparePriority(a: PriorityComparable, b: PriorityComparable): number {
194
194
  const feeComparison = compareFee(a.priorityFee, b.priorityFee);
195
195
  if (feeComparison !== 0) {
196
196
  return feeComparison;
@@ -335,9 +335,3 @@ export function stubTxMetaData(
335
335
  data: stubTxMetaValidationData({ expirationTimestamp }),
336
336
  };
337
337
  }
338
-
339
- /** Returns the priority fee for a tx, based on the L2 priority fee capped by the max fee per gas. */
340
- function getTxPriorityFee(tx: Tx): bigint {
341
- const { maxPriorityFeesPerGas: priorityFees, maxFeesPerGas } = tx.getGasSettings();
342
- return minBigint(maxFeesPerGas.feePerL2Gas, priorityFees.feePerL2Gas);
343
- }
@@ -1,8 +1,7 @@
1
- import { insertIntoSortedArray, removeFromSortedArray } from '@aztec/foundation/array';
2
1
  import { SlotNumber } from '@aztec/foundation/branded-types';
3
2
  import type { L2BlockId } from '@aztec/stdlib/block';
4
3
 
5
- import { type PriorityComparable, type TxMetaData, type TxState, comparePriority } from './tx_metadata.js';
4
+ import { type TxMetaData, type TxState, compareFee, compareTxHash, txHashFromBigInt } from './tx_metadata.js';
6
5
 
7
6
  /**
8
7
  * Manages in-memory indices for the transaction pool.
@@ -23,8 +22,8 @@ export class TxPoolIndices {
23
22
  #nullifierToTxHash: Map<string, string> = new Map();
24
23
  /** Fee payer to txHashes index (pending txs only) */
25
24
  #feePayerToTxHashes: Map<string, Set<string>> = new Map();
26
- /** Pending transactions sorted ascending by priority fee, ties broken by txHash */
27
- #pendingByPriority: PriorityComparable[] = [];
25
+ /** Pending txHash bigints grouped by priority fee */
26
+ #pendingByPriority: Map<bigint, Set<bigint>> = new Map();
28
27
  /** Protected transactions: txHash -> slotNumber */
29
28
  #protectedTransactions: Map<string, SlotNumber> = new Map();
30
29
 
@@ -74,14 +73,20 @@ export class TxPoolIndices {
74
73
  * @param order - 'desc' for highest priority first, 'asc' for lowest priority first
75
74
  */
76
75
  *iteratePendingByPriority(order: 'asc' | 'desc', filter?: (hash: string) => boolean): Generator<string> {
77
- const arr = this.#pendingByPriority;
78
- const start = order === 'asc' ? 0 : arr.length - 1;
79
- const step = order === 'asc' ? 1 : -1;
80
- const inBounds = order === 'asc' ? (i: number) => i < arr.length : (i: number) => i >= 0;
81
-
82
- for (let i = start; inBounds(i); i += step) {
83
- if (filter === undefined || filter(arr[i].txHash)) {
84
- yield arr[i].txHash;
76
+ const feeCompareFn = order === 'desc' ? (a: bigint, b: bigint) => compareFee(b, a) : compareFee;
77
+ const hashCompareFn =
78
+ order === 'desc' ? (a: bigint, b: bigint) => compareTxHash(b, a) : (a: bigint, b: bigint) => compareTxHash(a, b);
79
+
80
+ const sortedFees = [...this.#pendingByPriority.keys()].sort(feeCompareFn);
81
+
82
+ for (const fee of sortedFees) {
83
+ const hashesAtFee = this.#pendingByPriority.get(fee)!;
84
+ const sortedHashes = [...hashesAtFee].sort(hashCompareFn);
85
+ for (const hashBigInt of sortedHashes) {
86
+ const hash = txHashFromBigInt(hashBigInt);
87
+ if (filter === undefined || filter(hash)) {
88
+ yield hash;
89
+ }
85
90
  }
86
91
  }
87
92
  }
@@ -222,7 +227,11 @@ export class TxPoolIndices {
222
227
 
223
228
  /** Gets the count of pending transactions */
224
229
  getPendingTxCount(): number {
225
- return this.#pendingByPriority.length;
230
+ let count = 0;
231
+ for (const hashes of this.#pendingByPriority.values()) {
232
+ count += hashes.size;
233
+ }
234
+ return count;
226
235
  }
227
236
 
228
237
  /** Gets the lowest priority pending transaction hashes (up to limit) */
@@ -255,10 +264,12 @@ export class TxPoolIndices {
255
264
  /** Gets all pending transactions */
256
265
  getPendingTxs(): TxMetaData[] {
257
266
  const result: TxMetaData[] = [];
258
- for (const entry of this.#pendingByPriority) {
259
- const meta = this.#metadata.get(entry.txHash);
260
- if (meta) {
261
- result.push(meta);
267
+ for (const hashSet of this.#pendingByPriority.values()) {
268
+ for (const txHashBigInt of hashSet) {
269
+ const meta = this.#metadata.get(txHashFromBigInt(txHashBigInt));
270
+ if (meta) {
271
+ result.push(meta);
272
+ }
262
273
  }
263
274
  }
264
275
  return result;
@@ -397,12 +408,13 @@ export class TxPoolIndices {
397
408
  }
398
409
  feePayerSet.add(meta.txHash);
399
410
 
400
- insertIntoSortedArray(
401
- this.#pendingByPriority,
402
- { txHash: meta.txHash, priorityFee: meta.priorityFee, txHashBigInt: meta.txHashBigInt },
403
- comparePriority,
404
- false,
405
- );
411
+ // Add to priority bucket
412
+ let prioritySet = this.#pendingByPriority.get(meta.priorityFee);
413
+ if (!prioritySet) {
414
+ prioritySet = new Set();
415
+ this.#pendingByPriority.set(meta.priorityFee, prioritySet);
416
+ }
417
+ prioritySet.add(meta.txHashBigInt);
406
418
  }
407
419
 
408
420
  #removeFromPendingIndices(meta: TxMetaData): void {
@@ -420,11 +432,13 @@ export class TxPoolIndices {
420
432
  }
421
433
  }
422
434
 
423
- // Remove from priority array
424
- removeFromSortedArray(
425
- this.#pendingByPriority,
426
- { txHash: meta.txHash, priorityFee: meta.priorityFee, txHashBigInt: meta.txHashBigInt },
427
- comparePriority,
428
- );
435
+ // Remove from priority map
436
+ const hashSet = this.#pendingByPriority.get(meta.priorityFee);
437
+ if (hashSet) {
438
+ hashSet.delete(meta.txHashBigInt);
439
+ if (hashSet.size === 0) {
440
+ this.#pendingByPriority.delete(meta.priorityFee);
441
+ }
442
+ }
429
443
  }
430
444
  }
@@ -65,9 +65,6 @@ export class AztecKVTxPoolV2 extends (EventEmitter as new () => TypedEventEmitte
65
65
  const hashes = txHashes.map(h => (typeof h === 'string' ? TxHash.fromString(h) : TxHash.fromBigInt(h)));
66
66
  this.emit('txs-removed', { txHashes: hashes });
67
67
  },
68
- onTxsMined: (txHashes: string[]) => {
69
- this.#metrics?.transactionsRemoved(txHashes);
70
- },
71
68
  };
72
69
 
73
70
  // Create the implementation
@@ -45,7 +45,6 @@ import { TxPoolIndices } from './tx_pool_indices.js';
45
45
  export interface TxPoolV2Callbacks {
46
46
  onTxsAdded: (txs: Tx[], opts: { source?: string }) => void;
47
47
  onTxsRemoved: (txHashes: string[] | bigint[]) => void;
48
- onTxsMined: (txHashes: string[]) => void;
49
48
  }
50
49
 
51
50
  /**
@@ -340,12 +339,6 @@ export class TxPoolV2Impl {
340
339
  }
341
340
  }
342
341
 
343
- // Randomly drop the transaction for testing purposes (report as accepted so it propagates)
344
- if (this.#config.dropTransactionsProbability > 0 && Math.random() < this.#config.dropTransactionsProbability) {
345
- this.#log.debug(`Dropping tx ${txHashStr} (simulated drop for testing)`);
346
- return { status: 'accepted' };
347
- }
348
-
349
342
  // Add the transaction
350
343
  await this.#addTx(tx, 'pending', opts, precomputedMeta);
351
344
  return { status: 'accepted' };
@@ -356,7 +349,6 @@ export class TxPoolV2Impl {
356
349
 
357
350
  // Check if already in pool
358
351
  if (this.#indices.has(txHashStr)) {
359
- this.#log.verbose(`canAddPendingTx: tx ${txHashStr} already in pool`);
360
352
  return 'ignored';
361
353
  }
362
354
 
@@ -365,13 +357,7 @@ export class TxPoolV2Impl {
365
357
  const poolAccess = this.#createPreAddPoolAccess();
366
358
  const preAddResult = await this.#evictionManager.runPreAddRules(meta, poolAccess);
367
359
 
368
- if (preAddResult.shouldIgnore) {
369
- this.#log.verbose(`canAddPendingTx: tx ${txHashStr} ignored by pre-add rule`, {
370
- reason: preAddResult.reason?.message ?? 'no reason provided',
371
- });
372
- return 'ignored';
373
- }
374
- return 'accepted';
360
+ return preAddResult.shouldIgnore ? 'ignored' : 'accepted';
375
361
  }
376
362
 
377
363
  async addProtectedTxs(txs: Tx[], block: BlockHeader, opts: { source?: string }): Promise<void> {
@@ -515,10 +501,6 @@ export class TxPoolV2Impl {
515
501
  await this.#evictionManager.evictAfterNewBlock(block.header, nullifiers, feePayers);
516
502
  });
517
503
 
518
- if (found.length > 0) {
519
- this.#callbacks.onTxsMined(found.map(m => m.txHash));
520
- }
521
-
522
504
  this.#log.info(`Marked ${found.length} txs as mined in block ${blockId.number}`);
523
505
  }
524
506
 
@@ -24,7 +24,7 @@ This module validates `CheckpointAttestation` gossipsub messages. Attestations a
24
24
  |---|------|-------------|
25
25
  | 8 | Sender recoverable (pool-side) | Silent drop |
26
26
  | 9 | Not a duplicate (same slot + proposalId + signer) | IGNORE |
27
- | 10 | Per-signer cap: `MAX_ATTESTATIONS_PER_SLOT_AND_SIGNER` = 2 | IGNORE |
27
+ | 10 | Per-signer cap: `MAX_ATTESTATIONS_PER_SLOT_AND_SIGNER` = 3 | IGNORE |
28
28
 
29
29
  Own attestations added via `addOwnCheckpointAttestations` bypass the per-signer cap.
30
30
 
@@ -23,14 +23,13 @@ export class CheckpointAttestationValidator implements P2PValidator<CheckpointAt
23
23
  const slotNumber = message.payload.header.slotNumber;
24
24
 
25
25
  try {
26
- // Use target slots since proposals target pipeline slots (slot + 1 when pipelining)
27
- const { targetSlot, nextSlot } = this.epochCache.getTargetAndNextSlot();
26
+ const { currentSlot, nextSlot } = this.epochCache.getCurrentAndNextSlot();
28
27
 
29
- if (slotNumber !== targetSlot && slotNumber !== nextSlot) {
28
+ if (slotNumber !== currentSlot && slotNumber !== nextSlot) {
30
29
  // Check if message is for previous slot and within clock tolerance
31
- if (!isWithinClockTolerance(slotNumber, targetSlot, this.epochCache)) {
30
+ if (!isWithinClockTolerance(slotNumber, currentSlot, this.epochCache)) {
32
31
  this.logger.warn(
33
- `Checkpoint attestation slot ${slotNumber} is not current (${targetSlot}) or next (${nextSlot}) slot`,
32
+ `Checkpoint attestation slot ${slotNumber} is not current (${currentSlot}) or next (${nextSlot}) slot`,
34
33
  );
35
34
  return { result: 'reject', severity: PeerErrorSeverity.HighToleranceError };
36
35
  }
@@ -36,11 +36,10 @@ export function isWithinClockTolerance(
36
36
  }
37
37
 
38
38
  // Check how far we are into the current slot (in milliseconds)
39
- const { ts: slotStartTs, nowMs } = epochCache.getEpochAndSlotNow();
40
- const targetSlot = epochCache.getTargetSlot();
39
+ const { ts: slotStartTs, nowMs, slot } = epochCache.getEpochAndSlotNow();
41
40
 
42
- // Sanity check: ensure the epoch cache's target slot matches the expected current slot
43
- if (targetSlot !== currentSlot) {
41
+ // Sanity check: ensure the epoch cache's current slot matches the expected current slot
42
+ if (slot !== currentSlot) {
44
43
  return false;
45
44
  }
46
45
 
@@ -28,7 +28,7 @@ Deserialization guards: `BlockProposal.fromBuffer` and `SignedTxs.fromBuffer` bo
28
28
  | # | Rule | Consequence |
29
29
  |---|------|-------------|
30
30
  | 9 | **Duplicate**: same archive root already stored | IGNORE (no penalty) |
31
- | 10 | **Per-position cap**: max 2 proposals per (slot, indexWithinCheckpoint) | REJECT + HighToleranceError |
31
+ | 10 | **Per-position cap**: max 3 proposals per (slot, indexWithinCheckpoint) | REJECT + HighToleranceError |
32
32
  | 11 | **Equivocation**: >1 distinct proposal for same (slot, index) | ACCEPT (rebroadcast for detection). At count=2: `duplicateProposalCallback` fires -> slash event (`OffenseType.DUPLICATE_PROPOSAL`, configured via `slashDuplicateProposalPenalty`) |
33
33
 
34
34
  ### Stage 3: Validator-Client Processing (BlockProposalHandler)
@@ -53,7 +53,7 @@ Only runs on validator nodes. Non-validator nodes use a default handler that tri
53
53
 
54
54
  **Escape hatch**: during escape hatch periods (`isEscapeHatchOpenAtSlot`), re-execution and slashing are both disabled, and the proposal is rejected locally.
55
55
 
56
- **Conditional re-execution**: rules 22-24 only run when at least one condition is true: `fishermanMode` enabled, `slashBroadcastedInvalidBlockPenalty > 0`, committee membership, `alwaysReexecuteBlockProposals`, or `blobClient.canUpload()`.
56
+ **Conditional re-execution**: rules 22-24 only run when at least one condition is true: `fishermanMode` enabled, `slashBroadcastedInvalidBlockPenalty > 0` with `validatorReexecute`, committee membership with `validatorReexecute`, `alwaysReexecuteBlockProposals`, or `blobClient.canUpload()`.
57
57
 
58
58
  **Slashing**: only `state_mismatch` and `failed_txs` trigger on-chain slashing (`OffenseType.BROADCASTED_INVALID_BLOCK_PROPOSAL`, gated by `slashBroadcastedInvalidBlockPenalty > 0`). Unknown errors during re-execution do NOT slash.
59
59
 
@@ -84,7 +84,7 @@ The checkpoint's embedded `lastBlock` is extracted via `getBlockProposal()` and
84
84
  | Rule | Consequence | File |
85
85
  |------|-------------|------|
86
86
  | Block proposal must pass `BlockProposalValidator.validate()` | If REJECT: entire checkpoint REJECTED | `libp2p_service.ts` |
87
- | Block proposal must not exceed per-position cap (2) | Checkpoint REJECTED + HighToleranceError | same |
87
+ | Block proposal must not exceed per-position cap (3) | Checkpoint REJECTED + HighToleranceError | same |
88
88
  | Block equivocation detected (>1 proposals for same slot+index) | Checkpoint REJECTED (block itself is ACCEPT for re-broadcast) | same |
89
89
 
90
90
  ### Stage 3: Mempool (Attestation Pool)
@@ -92,7 +92,7 @@ The checkpoint's embedded `lastBlock` is extracted via `getBlockProposal()` and
92
92
  | Rule | Consequence | File |
93
93
  |------|-------------|------|
94
94
  | Duplicate (same archive ID) | IGNORE (no penalty). Embedded block still processed if valid. | `attestation_pool.ts` |
95
- | Per-slot cap: `MAX_CHECKPOINT_PROPOSALS_PER_SLOT` = 2 | REJECT + HighToleranceError. Embedded block still processed. | same |
95
+ | Per-slot cap: `MAX_CHECKPOINT_PROPOSALS_PER_SLOT` = 5 | REJECT + HighToleranceError. Embedded block still processed. | same |
96
96
 
97
97
  ### Stage 4: Equivocation Detection
98
98
 
@@ -31,14 +31,13 @@ export class ProposalValidator {
31
31
  /** Validates header-level fields: slot, signature, and proposer. */
32
32
  public async validate(proposal: BlockProposal | CheckpointProposalCore): Promise<ValidationResult> {
33
33
  try {
34
- // Slot check: use target slots since proposals target pipeline slots (slot + 1 when pipelining)
35
- const { targetSlot, nextSlot } = this.epochCache.getTargetAndNextSlot();
36
-
34
+ // Slot check
35
+ const { currentSlot, nextSlot } = this.epochCache.getCurrentAndNextSlot();
37
36
  const slotNumber = proposal.slotNumber;
38
- if (slotNumber !== targetSlot && slotNumber !== nextSlot) {
37
+ if (slotNumber !== currentSlot && slotNumber !== nextSlot) {
39
38
  // Check if message is for previous slot and within clock tolerance
40
- if (!isWithinClockTolerance(slotNumber, targetSlot, this.epochCache)) {
41
- this.logger.warn(`Penalizing peer for invalid slot number ${slotNumber}`, { targetSlot, nextSlot });
39
+ if (!isWithinClockTolerance(slotNumber, currentSlot, this.epochCache)) {
40
+ this.logger.warn(`Penalizing peer for invalid slot number ${slotNumber}`, { currentSlot, nextSlot });
42
41
  return { result: 'reject', severity: PeerErrorSeverity.HighToleranceError };
43
42
  }
44
43
  this.logger.verbose(`Ignoring proposal for previous slot ${slotNumber} within clock tolerance`);
@@ -28,24 +28,16 @@ export class MetadataTxValidator<T extends AnyTx> implements TxValidator<T> {
28
28
  validateTx(tx: T): Promise<TxValidationResult> {
29
29
  const errors = [];
30
30
  if (!this.#hasCorrectL1ChainId(tx)) {
31
- errors.push(
32
- `${TX_ERROR_INCORRECT_L1_CHAIN_ID} (tx: ${tx.data.constants.txContext.chainId.toNumber()}, expected: ${this.values.l1ChainId.toNumber()})`,
33
- );
31
+ errors.push(TX_ERROR_INCORRECT_L1_CHAIN_ID);
34
32
  }
35
33
  if (!this.#hasCorrectRollupVersion(tx)) {
36
- errors.push(
37
- `${TX_ERROR_INCORRECT_ROLLUP_VERSION} (tx: ${tx.data.constants.txContext.version.toNumber()}, expected: ${this.values.rollupVersion.toNumber()})`,
38
- );
34
+ errors.push(TX_ERROR_INCORRECT_ROLLUP_VERSION);
39
35
  }
40
36
  if (!this.#hasCorrectVkTreeRoot(tx)) {
41
- errors.push(
42
- `${TX_ERROR_INCORRECT_VK_TREE_ROOT} (tx: ${tx.data.constants.vkTreeRoot.toString()}, expected: ${this.values.vkTreeRoot.toString()})`,
43
- );
37
+ errors.push(TX_ERROR_INCORRECT_VK_TREE_ROOT);
44
38
  }
45
39
  if (!this.#hasCorrectprotocolContractsHash(tx)) {
46
- errors.push(
47
- `${TX_ERROR_INCORRECT_PROTOCOL_CONTRACTS_HASH} (tx: ${tx.data.constants.protocolContractsHash.toString()}, expected: ${this.values.protocolContractsHash.toString()})`,
48
- );
40
+ errors.push(TX_ERROR_INCORRECT_PROTOCOL_CONTRACTS_HASH);
49
41
  }
50
42
  return Promise.resolve(errors.length > 0 ? { result: 'invalid', reason: errors } : { result: 'valid' });
51
43
  }
@@ -96,7 +96,7 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService
96
96
  lookupTimeout: 2000,
97
97
  requestTimeout: 2000,
98
98
  allowUnverifiedSessions: true,
99
- enrUpdate: config.queryForIp && !p2pIp, // Enable native ENR IP discovery when no static IP is configured
99
+ enrUpdate: !p2pIp ? true : false, // If no p2p IP is set, enrUpdate can automatically resolve it
100
100
  ...configOverrides.config,
101
101
  },
102
102
  metricsRegistry,
@@ -129,11 +129,9 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService
129
129
  private onMultiaddrUpdated(m: Multiaddr) {
130
130
  // We want to update our tcp port to match the udp port
131
131
  // p2pBroadcastPort is optional on config, however it is set to default within the p2p client factory
132
- const address = m.nodeAddress().address;
133
- const multiAddrTcp = multiaddr(convertToMultiaddr(address, this.config.p2pBroadcastPort!, 'tcp'));
132
+ const multiAddrTcp = multiaddr(convertToMultiaddr(m.nodeAddress().address, this.config.p2pBroadcastPort!, 'tcp'));
134
133
  this.enr.setLocationMultiaddr(multiAddrTcp);
135
134
  this.logger.info('Multiaddr updated', { multiaddr: multiAddrTcp.toString() });
136
- this.emit('ip:changed', address);
137
135
  }
138
136
 
139
137
  public async start(): Promise<void> {