@aztec/p2p 0.0.1-commit.ffe5b04ea → 0.0.1-commit.fff30aa

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 (144) hide show
  1. package/README.md +129 -3
  2. package/dest/client/factory.d.ts +2 -2
  3. package/dest/client/factory.d.ts.map +1 -1
  4. package/dest/client/factory.js +23 -11
  5. package/dest/client/p2p_client.d.ts +1 -1
  6. package/dest/client/p2p_client.d.ts.map +1 -1
  7. package/dest/client/p2p_client.js +16 -6
  8. package/dest/config.d.ts +15 -3
  9. package/dest/config.d.ts.map +1 -1
  10. package/dest/config.js +21 -1
  11. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +1 -1
  12. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  13. package/dest/mem_pools/attestation_pool/attestation_pool.js +1 -5
  14. package/dest/mem_pools/instrumentation.d.ts +2 -4
  15. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  16. package/dest/mem_pools/instrumentation.js +14 -16
  17. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
  18. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
  19. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +2 -1
  20. package/dest/mem_pools/tx_pool/priority.d.ts +2 -2
  21. package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
  22. package/dest/mem_pools/tx_pool/priority.js +4 -4
  23. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
  24. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
  25. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +3 -1
  26. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
  27. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
  28. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +2 -1
  29. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +3 -3
  30. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
  31. package/dest/mem_pools/tx_pool_v2/interfaces.js +0 -1
  32. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +14 -6
  33. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
  34. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +7 -1
  35. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +1 -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 +43 -26
  38. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +4 -2
  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 +3 -3
  41. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +1 -2
  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 +11 -14
  44. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts +9 -0
  45. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts.map +1 -0
  46. package/dest/msg_validators/tx_validator/contract_instance_validator.js +48 -0
  47. package/dest/msg_validators/tx_validator/data_validator.d.ts +1 -1
  48. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  49. package/dest/msg_validators/tx_validator/data_validator.js +35 -2
  50. package/dest/msg_validators/tx_validator/factory.d.ts +23 -4
  51. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  52. package/dest/msg_validators/tx_validator/factory.js +36 -10
  53. package/dest/msg_validators/tx_validator/gas_validator.d.ts +13 -4
  54. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  55. package/dest/msg_validators/tx_validator/gas_validator.js +39 -9
  56. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +1 -1
  57. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  58. package/dest/msg_validators/tx_validator/metadata_validator.js +4 -4
  59. package/dest/msg_validators/tx_validator/phases_validator.d.ts +21 -1
  60. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  61. package/dest/msg_validators/tx_validator/phases_validator.js +28 -1
  62. package/dest/services/encoding.d.ts +5 -1
  63. package/dest/services/encoding.d.ts.map +1 -1
  64. package/dest/services/encoding.js +7 -1
  65. package/dest/services/libp2p/libp2p_service.d.ts +1 -1
  66. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  67. package/dest/services/libp2p/libp2p_service.js +15 -5
  68. package/dest/services/peer-manager/metrics.d.ts +1 -3
  69. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  70. package/dest/services/peer-manager/metrics.js +0 -6
  71. package/dest/services/peer-manager/peer_manager.d.ts +1 -1
  72. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  73. package/dest/services/peer-manager/peer_manager.js +1 -2
  74. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +1 -1
  75. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
  76. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +37 -14
  77. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +11 -17
  78. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
  79. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +15 -49
  80. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +5 -4
  81. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
  82. package/dest/services/reqresp/rate-limiter/rate_limiter.js +10 -8
  83. package/dest/services/reqresp/reqresp.d.ts +1 -1
  84. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  85. package/dest/services/reqresp/reqresp.js +18 -11
  86. package/dest/services/tx_collection/file_store_tx_source.d.ts +5 -4
  87. package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -1
  88. package/dest/services/tx_collection/file_store_tx_source.js +39 -29
  89. package/dest/services/tx_collection/tx_source.d.ts +6 -5
  90. package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
  91. package/dest/services/tx_collection/tx_source.js +9 -7
  92. package/dest/test-helpers/make-test-p2p-clients.d.ts +1 -1
  93. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  94. package/dest/test-helpers/reqresp-nodes.d.ts +1 -1
  95. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  96. package/dest/test-helpers/testbench-utils.d.ts +1 -1
  97. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  98. package/dest/test-helpers/testbench-utils.js +2 -1
  99. package/dest/testbench/worker_client_manager.d.ts +1 -1
  100. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  101. package/dest/testbench/worker_client_manager.js +1 -2
  102. package/dest/util.d.ts +1 -1
  103. package/package.json +14 -14
  104. package/src/client/factory.ts +42 -15
  105. package/src/client/p2p_client.ts +16 -8
  106. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +1 -1
  107. package/src/config.ts +35 -2
  108. package/src/mem_pools/attestation_pool/attestation_pool.ts +4 -5
  109. package/src/mem_pools/instrumentation.ts +13 -17
  110. package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +2 -1
  111. package/src/mem_pools/tx_pool/priority.ts +4 -4
  112. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +3 -1
  113. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +2 -1
  114. package/src/mem_pools/tx_pool_v2/interfaces.ts +2 -3
  115. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +15 -5
  116. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +43 -29
  117. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +13 -4
  118. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +12 -15
  119. package/src/msg_validators/attestation_validator/README.md +49 -0
  120. package/src/msg_validators/proposal_validator/README.md +123 -0
  121. package/src/msg_validators/tx_validator/README.md +5 -1
  122. package/src/msg_validators/tx_validator/contract_instance_validator.ts +56 -0
  123. package/src/msg_validators/tx_validator/data_validator.ts +42 -1
  124. package/src/msg_validators/tx_validator/factory.ts +43 -3
  125. package/src/msg_validators/tx_validator/gas_validator.ts +41 -8
  126. package/src/msg_validators/tx_validator/metadata_validator.ts +4 -12
  127. package/src/msg_validators/tx_validator/phases_validator.ts +31 -1
  128. package/src/services/encoding.ts +9 -1
  129. package/src/services/libp2p/libp2p_service.ts +16 -5
  130. package/src/services/peer-manager/metrics.ts +0 -7
  131. package/src/services/peer-manager/peer_manager.ts +1 -2
  132. package/src/services/reqresp/README.md +229 -0
  133. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +42 -14
  134. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +24 -63
  135. package/src/services/reqresp/rate-limiter/rate_limiter.ts +13 -9
  136. package/src/services/reqresp/reqresp.ts +20 -14
  137. package/src/services/tx_collection/file_store_tx_source.ts +43 -31
  138. package/src/services/tx_collection/tx_source.ts +8 -7
  139. package/src/test-helpers/make-test-p2p-clients.ts +1 -1
  140. package/src/test-helpers/reqresp-nodes.ts +1 -1
  141. package/src/test-helpers/testbench-utils.ts +1 -0
  142. package/src/testbench/p2p_client_testbench_worker.ts +1 -1
  143. package/src/testbench/worker_client_manager.ts +1 -2
  144. package/src/util.ts +1 -1
@@ -1,5 +1,7 @@
1
1
  import { MAX_FR_CALLDATA_TO_ALL_ENQUEUED_CALLS } from '@aztec/constants';
2
2
  import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
3
+ import { ContractClassPublishedEvent } from '@aztec/protocol-contracts/class-registry';
4
+ import { computeContractClassId } from '@aztec/stdlib/contract';
3
5
  import { computeCalldataHash } from '@aztec/stdlib/hash';
4
6
  import {
5
7
  TX_ERROR_CALLDATA_COUNT_MISMATCH,
@@ -9,7 +11,9 @@ import {
9
11
  TX_ERROR_CONTRACT_CLASS_LOG_LENGTH,
10
12
  TX_ERROR_CONTRACT_CLASS_LOG_SORTING,
11
13
  TX_ERROR_INCORRECT_CALLDATA,
14
+ TX_ERROR_INCORRECT_CONTRACT_CLASS_ID,
12
15
  TX_ERROR_INCORRECT_HASH,
16
+ TX_ERROR_MALFORMED_CONTRACT_CLASS_LOG,
13
17
  Tx,
14
18
  type TxValidationResult,
15
19
  type TxValidator,
@@ -26,7 +30,8 @@ export class DataTxValidator implements TxValidator<Tx> {
26
30
  const reason =
27
31
  (await this.#hasCorrectHash(tx)) ??
28
32
  (await this.#hasCorrectCalldata(tx)) ??
29
- (await this.#hasCorrectContractClassLogs(tx));
33
+ (await this.#hasCorrectContractClassLogs(tx)) ??
34
+ (await this.#hasCorrectContractClassIds(tx));
30
35
  return reason ? { result: 'invalid', reason: [reason] } : { result: 'valid' };
31
36
  }
32
37
 
@@ -127,4 +132,40 @@ export class DataTxValidator implements TxValidator<Tx> {
127
132
 
128
133
  return undefined;
129
134
  }
135
+
136
+ async #hasCorrectContractClassIds(tx: Tx): Promise<string | undefined> {
137
+ const contractClassLogs = tx.getContractClassLogs();
138
+ for (const log of contractClassLogs) {
139
+ if (!ContractClassPublishedEvent.isContractClassPublishedEvent(log)) {
140
+ continue;
141
+ }
142
+
143
+ let event;
144
+ try {
145
+ event = ContractClassPublishedEvent.fromLog(log);
146
+ } catch (e) {
147
+ this.#log.warn(`Rejecting tx ${tx.getTxHash()}: failed to parse contract class event: ${e}`);
148
+ return TX_ERROR_MALFORMED_CONTRACT_CLASS_LOG;
149
+ }
150
+
151
+ try {
152
+ const { publicBytecodeCommitment } = await event.toContractClassPublicWithBytecodeCommitment();
153
+ const computedClassId = await computeContractClassId({
154
+ artifactHash: event.artifactHash,
155
+ privateFunctionsRoot: event.privateFunctionsRoot,
156
+ publicBytecodeCommitment,
157
+ });
158
+ if (!computedClassId.equals(event.contractClassId)) {
159
+ this.#log.warn(
160
+ `Rejecting tx ${tx.getTxHash()}: contract class id mismatch. Claimed ${event.contractClassId}, computed ${computedClassId}`,
161
+ );
162
+ return TX_ERROR_INCORRECT_CONTRACT_CLASS_ID;
163
+ }
164
+ } catch (e) {
165
+ this.#log.warn(`Rejecting tx ${tx.getTxHash()}: failed to compute contract class id: ${e}`);
166
+ return TX_ERROR_MALFORMED_CONTRACT_CLASS_LOG;
167
+ }
168
+ }
169
+ return undefined;
170
+ }
130
171
  }
@@ -53,12 +53,13 @@ import type { TxMetaData } from '../../mem_pools/tx_pool_v2/tx_metadata.js';
53
53
  import { AggregateTxValidator } from './aggregate_tx_validator.js';
54
54
  import { ArchiveCache } from './archive_cache.js';
55
55
  import { type ArchiveSource, BlockHeaderTxValidator } from './block_header_validator.js';
56
+ import { ContractInstanceTxValidator } from './contract_instance_validator.js';
56
57
  import { DataTxValidator } from './data_validator.js';
57
58
  import { DoubleSpendTxValidator, type NullifierSource } from './double_spend_validator.js';
58
59
  import { GasLimitsValidator, GasTxValidator } from './gas_validator.js';
59
60
  import { MetadataTxValidator } from './metadata_validator.js';
60
61
  import { NullifierCache } from './nullifier_cache.js';
61
- import { PhasesTxValidator } from './phases_validator.js';
62
+ import { AllowedSetupCallsMetaValidator, PhasesTxValidator } from './phases_validator.js';
62
63
  import { SizeTxValidator } from './size_validator.js';
63
64
  import { TimestampTxValidator } from './timestamp_validator.js';
64
65
  import { TxPermittedValidator } from './tx_permitted_validator.js';
@@ -97,6 +98,7 @@ export function createFirstStageTxValidationsForGossipedTransactions(
97
98
  txsPermitted: boolean,
98
99
  allowedInSetup: AllowedElement[] = [],
99
100
  bindings?: LoggerBindings,
101
+ gasLimitOpts?: { rollupManaLimit?: number; maxBlockL2Gas?: number; maxBlockDAGas?: number },
100
102
  ): Record<string, TransactionValidator> {
101
103
  const merkleTree = worldStateSynchronizer.getCommitted();
102
104
 
@@ -158,6 +160,7 @@ export function createFirstStageTxValidationsForGossipedTransactions(
158
160
  ProtocolContractAddress.FeeJuice,
159
161
  gasFees,
160
162
  bindings,
163
+ gasLimitOpts,
161
164
  ),
162
165
  severity: PeerErrorSeverity.MidToleranceError,
163
166
  },
@@ -165,6 +168,10 @@ export function createFirstStageTxValidationsForGossipedTransactions(
165
168
  validator: new DataTxValidator(bindings),
166
169
  severity: PeerErrorSeverity.MidToleranceError,
167
170
  },
171
+ contractInstanceValidator: {
172
+ validator: new ContractInstanceTxValidator(bindings),
173
+ severity: PeerErrorSeverity.MidToleranceError,
174
+ },
168
175
  };
169
176
  }
170
177
 
@@ -216,6 +223,7 @@ function createTxValidatorForMinimumTxIntegrityChecks(
216
223
  ),
217
224
  new SizeTxValidator(bindings),
218
225
  new DataTxValidator(bindings),
226
+ new ContractInstanceTxValidator(bindings),
219
227
  new TxProofValidator(verifier, bindings),
220
228
  );
221
229
  }
@@ -278,6 +286,9 @@ export function createTxValidatorForAcceptingTxsOverRPC(
278
286
  timestamp,
279
287
  blockNumber,
280
288
  txsPermitted,
289
+ rollupManaLimit,
290
+ maxBlockL2Gas,
291
+ maxBlockDAGas,
281
292
  }: {
282
293
  l1ChainId: number;
283
294
  rollupVersion: number;
@@ -287,6 +298,9 @@ export function createTxValidatorForAcceptingTxsOverRPC(
287
298
  timestamp: UInt64;
288
299
  blockNumber: BlockNumber;
289
300
  txsPermitted: boolean;
301
+ rollupManaLimit: number;
302
+ maxBlockL2Gas?: number;
303
+ maxBlockDAGas?: number;
290
304
  },
291
305
  bindings?: LoggerBindings,
292
306
  ): TxValidator<Tx> {
@@ -313,11 +327,16 @@ export function createTxValidatorForAcceptingTxsOverRPC(
313
327
  new BlockHeaderTxValidator(new ArchiveCache(db), bindings),
314
328
  new DoubleSpendTxValidator(new NullifierCache(db), bindings),
315
329
  new DataTxValidator(bindings),
330
+ new ContractInstanceTxValidator(bindings),
316
331
  ];
317
332
 
318
333
  if (!skipFeeEnforcement) {
319
334
  validators.push(
320
- new GasTxValidator(new DatabasePublicStateSource(db), ProtocolContractAddress.FeeJuice, gasFees, bindings),
335
+ new GasTxValidator(new DatabasePublicStateSource(db), ProtocolContractAddress.FeeJuice, gasFees, bindings, {
336
+ rollupManaLimit,
337
+ maxBlockL2Gas,
338
+ maxBlockDAGas,
339
+ }),
321
340
  );
322
341
  }
323
342
 
@@ -403,6 +422,7 @@ export async function createTxValidatorForTransactionsEnteringPendingTxPool(
403
422
  worldStateSynchronizer: WorldStateSynchronizer,
404
423
  timestamp: bigint,
405
424
  blockNumber: BlockNumber,
425
+ gasLimitOpts: { rollupManaLimit?: number; maxBlockL2Gas?: number; maxBlockDAGas?: number },
406
426
  bindings?: LoggerBindings,
407
427
  ): Promise<TxValidator<TxMetaData>> {
408
428
  await worldStateSynchronizer.syncImmediate();
@@ -419,9 +439,29 @@ export async function createTxValidatorForTransactionsEnteringPendingTxPool(
419
439
  },
420
440
  };
421
441
  return new AggregateTxValidator<TxMetaData>(
422
- new GasLimitsValidator<TxMetaData>(bindings),
442
+ new GasLimitsValidator<TxMetaData>({ ...gasLimitOpts, bindings }),
423
443
  new TimestampTxValidator<TxMetaData>({ timestamp, blockNumber }, bindings),
424
444
  new DoubleSpendTxValidator<TxMetaData>(nullifierSource, bindings),
425
445
  new BlockHeaderTxValidator<TxMetaData>(archiveSource, bindings),
446
+ new AllowedSetupCallsMetaValidator<TxMetaData>(bindings),
426
447
  );
427
448
  }
449
+
450
+ /**
451
+ * Creates a function that checks whether a tx's setup-phase calls are on the allow list.
452
+ *
453
+ * Uses the `PhasesTxValidator` on the full Tx. The result is stored as a boolean
454
+ * flag in `TxMetaData.allowedSetupCalls` at receipt time, so the pending pool
455
+ * migration validator can check it without needing the full Tx or its dependencies.
456
+ */
457
+ export function createCheckAllowedSetupCalls(
458
+ contractDataSource: ContractDataSource,
459
+ setupAllowList: AllowedElement[],
460
+ getTimestamp: () => UInt64,
461
+ ): (tx: Tx) => Promise<boolean> {
462
+ return async (tx: Tx) => {
463
+ const validator = new PhasesTxValidator(contractDataSource, setupAllowList, getTimestamp());
464
+ const result = await validator.validateTx(tx);
465
+ return result.result === 'valid';
466
+ };
467
+ }
@@ -1,4 +1,5 @@
1
1
  import {
2
+ MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT,
2
3
  MAX_PROCESSABLE_L2_GAS,
3
4
  PRIVATE_TX_L2_GAS_OVERHEAD,
4
5
  PUBLIC_TX_L2_GAS_OVERHEAD,
@@ -49,16 +50,31 @@ export interface HasGasLimitData {
49
50
  */
50
51
  export class GasLimitsValidator<T extends HasGasLimitData> implements TxValidator<T> {
51
52
  #log: Logger;
52
-
53
- constructor(bindings?: LoggerBindings) {
54
- this.#log = createLogger('sequencer:tx_validator:tx_gas', bindings);
53
+ #effectiveMaxL2Gas: number;
54
+ #effectiveMaxDAGas: number;
55
+ #rollupManaLimit: number;
56
+ #maxBlockL2Gas: number;
57
+ #maxBlockDAGas: number;
58
+
59
+ constructor(opts?: {
60
+ rollupManaLimit?: number;
61
+ maxBlockL2Gas?: number;
62
+ maxBlockDAGas?: number;
63
+ bindings?: LoggerBindings;
64
+ }) {
65
+ this.#log = createLogger('sequencer:tx_validator:tx_gas', opts?.bindings);
66
+ this.#rollupManaLimit = opts?.rollupManaLimit ?? Infinity;
67
+ this.#maxBlockL2Gas = opts?.maxBlockL2Gas ?? Infinity;
68
+ this.#maxBlockDAGas = opts?.maxBlockDAGas ?? Infinity;
69
+ this.#effectiveMaxL2Gas = Math.min(MAX_PROCESSABLE_L2_GAS, this.#rollupManaLimit, this.#maxBlockL2Gas);
70
+ this.#effectiveMaxDAGas = Math.min(MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT, this.#maxBlockDAGas);
55
71
  }
56
72
 
57
73
  validateTx(tx: T): Promise<TxValidationResult> {
58
74
  return Promise.resolve(this.validateGasLimit(tx));
59
75
  }
60
76
 
61
- /** Checks gas limits are >= fixed minimums and <= AVM max processable L2 gas. */
77
+ /** Checks gas limits are >= fixed minimums and <= effective max gas (L2 and DA). */
62
78
  validateGasLimit(tx: T): TxValidationResult {
63
79
  const gasLimits = tx.data.constants.txContext.gasSettings.gasLimits;
64
80
  const minGasLimits = new Gas(
@@ -74,10 +90,21 @@ export class GasLimitsValidator<T extends HasGasLimitData> implements TxValidato
74
90
  return { result: 'invalid', reason: [TX_ERROR_INSUFFICIENT_GAS_LIMIT] };
75
91
  }
76
92
 
77
- if (gasLimits.l2Gas > MAX_PROCESSABLE_L2_GAS) {
78
- this.#log.verbose(`Rejecting transaction due to the gas limit(s) being higher than the maximum processable gas`, {
93
+ if (gasLimits.l2Gas > this.#effectiveMaxL2Gas) {
94
+ this.#log.verbose(`Rejecting transaction due to the L2 gas limit being higher than the effective maximum`, {
79
95
  gasLimits,
80
- minGasLimits,
96
+ effectiveMaxL2Gas: this.#effectiveMaxL2Gas,
97
+ rollupManaLimit: this.#rollupManaLimit,
98
+ maxBlockL2Gas: this.#maxBlockL2Gas,
99
+ });
100
+ return { result: 'invalid', reason: [TX_ERROR_GAS_LIMIT_TOO_HIGH] };
101
+ }
102
+
103
+ if (gasLimits.daGas > this.#effectiveMaxDAGas) {
104
+ this.#log.verbose(`Rejecting transaction due to the DA gas limit being higher than the effective maximum`, {
105
+ gasLimits,
106
+ effectiveMaxDAGas: this.#effectiveMaxDAGas,
107
+ maxBlockDAGas: this.#maxBlockDAGas,
81
108
  });
82
109
  return { result: 'invalid', reason: [TX_ERROR_GAS_LIMIT_TOO_HIGH] };
83
110
  }
@@ -106,21 +133,27 @@ export class GasTxValidator implements TxValidator<Tx> {
106
133
  #publicDataSource: PublicStateSource;
107
134
  #feeJuiceAddress: AztecAddress;
108
135
  #gasFees: GasFees;
136
+ #gasLimitOpts?: { rollupManaLimit?: number; maxBlockL2Gas?: number; maxBlockDAGas?: number };
109
137
 
110
138
  constructor(
111
139
  publicDataSource: PublicStateSource,
112
140
  feeJuiceAddress: AztecAddress,
113
141
  gasFees: GasFees,
114
142
  private bindings?: LoggerBindings,
143
+ opts?: { rollupManaLimit?: number; maxBlockL2Gas?: number; maxBlockDAGas?: number },
115
144
  ) {
116
145
  this.#log = createLogger('sequencer:tx_validator:tx_gas', bindings);
117
146
  this.#publicDataSource = publicDataSource;
118
147
  this.#feeJuiceAddress = feeJuiceAddress;
119
148
  this.#gasFees = gasFees;
149
+ this.#gasLimitOpts = opts;
120
150
  }
121
151
 
122
152
  async validateTx(tx: Tx): Promise<TxValidationResult> {
123
- const gasLimitValidation = new GasLimitsValidator(this.bindings).validateGasLimit(tx);
153
+ const gasLimitValidation = new GasLimitsValidator({
154
+ ...this.#gasLimitOpts,
155
+ bindings: this.bindings,
156
+ }).validateGasLimit(tx);
124
157
  if (gasLimitValidation.result === 'invalid') {
125
158
  return Promise.resolve(gasLimitValidation);
126
159
  }
@@ -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
  }
@@ -40,7 +40,7 @@ export class PhasesTxValidator implements TxValidator<Tx> {
40
40
  // which are needed for public FPC flows, but fail if the account contract hasnt been deployed yet,
41
41
  // which is what we're trying to do as part of the current txs.
42
42
  // We only need to create/revert checkpoint here because of this addNewContracts call.
43
- await this.contractsDB.addNewContracts(tx);
43
+ this.contractsDB.addNewContracts(tx);
44
44
 
45
45
  if (!tx.data.forPublic) {
46
46
  this.#log.debug(
@@ -141,3 +141,33 @@ export class PhasesTxValidator implements TxValidator<Tx> {
141
141
  return TX_ERROR_SETUP_FUNCTION_NOT_ALLOWED;
142
142
  }
143
143
  }
144
+
145
+ /** Structural interface for the allowed-setup-calls flag check. */
146
+ export interface HasAllowedSetupCallsData {
147
+ txHash: { toString(): string };
148
+ allowedSetupCalls: boolean;
149
+ }
150
+
151
+ /**
152
+ * Validates that a transaction's setup-phase calls were allowed at receipt time.
153
+ *
154
+ * Checks the precomputed `allowedSetupCalls` flag on TxMetaData. The flag is
155
+ * computed by running the PhasesTxValidator on the full Tx when it first enters
156
+ * the pool. This lightweight validator is used during pending pool migration to
157
+ * reject txs whose setup calls are not on the allow list.
158
+ */
159
+ export class AllowedSetupCallsMetaValidator<T extends HasAllowedSetupCallsData> implements TxValidator<T> {
160
+ #log: Logger;
161
+
162
+ constructor(bindings?: LoggerBindings) {
163
+ this.#log = createLogger('sequencer:tx_validator:tx_phases_meta', bindings);
164
+ }
165
+
166
+ validateTx(tx: T): Promise<TxValidationResult> {
167
+ if (!tx.allowedSetupCalls) {
168
+ this.#log.verbose(`Rejecting tx ${tx.txHash} because its setup calls are not on the allow list`);
169
+ return Promise.resolve({ result: 'invalid', reason: [TX_ERROR_SETUP_FUNCTION_NOT_ALLOWED] });
170
+ }
171
+ return Promise.resolve({ result: 'valid' });
172
+ }
173
+ }
@@ -9,6 +9,14 @@ import { webcrypto } from 'node:crypto';
9
9
  import { compressSync, uncompressSync } from 'snappy';
10
10
  import xxhashFactory from 'xxhash-wasm';
11
11
 
12
+ /** Thrown when a Snappy-compressed response exceeds the allowed decompressed size. */
13
+ export class OversizedSnappyResponseError extends Error {
14
+ constructor(decompressedSize: number, maxSizeKb: number) {
15
+ super(`Decompressed size ${decompressedSize} exceeds maximum allowed size of ${maxSizeKb}kb`);
16
+ this.name = 'OversizedSnappyResponseError';
17
+ }
18
+ }
19
+
12
20
  // Load WASM
13
21
  const xxhash = await xxhashFactory();
14
22
 
@@ -86,7 +94,7 @@ export class SnappyTransform implements DataTransform {
86
94
  const { decompressedSize } = readSnappyPreamble(data);
87
95
  if (decompressedSize > maxSizeKb * 1024) {
88
96
  this.logger.warn(`Decompressed size ${decompressedSize} exceeds maximum allowed size of ${maxSizeKb}kb`);
89
- throw new Error(`Decompressed size ${decompressedSize} exceeds maximum allowed size of ${maxSizeKb}kb`);
97
+ throw new OversizedSnappyResponseError(decompressedSize, maxSizeKb);
90
98
  }
91
99
 
92
100
  return Buffer.from(uncompressSync(data, { asBuffer: true }));
@@ -226,7 +226,7 @@ export class LibP2PService extends WithTracer implements P2PService {
226
226
 
227
227
  const proposalValidatorOpts = {
228
228
  txsPermitted: !config.disableTransactions,
229
- maxTxsPerBlock: config.validateMaxTxsPerBlock,
229
+ maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint,
230
230
  };
231
231
  this.blockProposalValidator = new BlockProposalValidator(epochCache, proposalValidatorOpts);
232
232
  this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts);
@@ -237,11 +237,11 @@ export class LibP2PService extends WithTracer implements P2PService {
237
237
  this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
238
238
 
239
239
  this.blockReceivedCallback = async (block: BlockProposal): Promise<boolean> => {
240
- this.logger.debug(
241
- `Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber} from peer.`,
240
+ this.logger.warn(
241
+ `Handler for block received not yet registered on P2P service. Received block ${block.blockNumber} for slot ${block.slotNumber} from peer.`,
242
242
  { p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier() },
243
243
  );
244
- return false;
244
+ return true;
245
245
  };
246
246
 
247
247
  this.checkpointReceivedCallback = (
@@ -960,6 +960,11 @@ export class LibP2PService extends WithTracer implements P2PService {
960
960
  } else if (wasIgnored) {
961
961
  return { result: TopicValidatorResult.Ignore, obj: tx };
962
962
  } else {
963
+ this.logger.warn(`Gossiped tx ${txHash.toString()} unexpectedly rejected by pool`, {
964
+ source: source.toString(),
965
+ txHash: txHash.toString(),
966
+ });
967
+ this.peerManager.penalizePeer(source, PeerErrorSeverity.HighToleranceError);
963
968
  return { result: TopicValidatorResult.Reject };
964
969
  }
965
970
  };
@@ -1192,7 +1197,7 @@ export class LibP2PService extends WithTracer implements P2PService {
1192
1197
  // Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
1193
1198
  const isValid = await this.blockReceivedCallback(block, sender);
1194
1199
  if (!isValid) {
1195
- this.logger.warn(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
1200
+ this.logger.info(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
1196
1201
  }
1197
1202
  }
1198
1203
 
@@ -1626,6 +1631,7 @@ export class LibP2PService extends WithTracer implements P2PService {
1626
1631
  ...(this.config.txPublicSetupAllowListExtend ?? []),
1627
1632
  ];
1628
1633
  const blockNumber = BlockNumber(currentBlockNumber + 1);
1634
+ const l1Constants = await this.archiver.getL1Constants();
1629
1635
 
1630
1636
  return createFirstStageTxValidationsForGossipedTransactions(
1631
1637
  nextSlotTimestamp,
@@ -1639,6 +1645,11 @@ export class LibP2PService extends WithTracer implements P2PService {
1639
1645
  !this.config.disableTransactions,
1640
1646
  allowedInSetup,
1641
1647
  this.logger.getBindings(),
1648
+ {
1649
+ rollupManaLimit: l1Constants.rollupManaLimit,
1650
+ maxBlockL2Gas: this.config.validateMaxL2BlockGas,
1651
+ maxBlockDAGas: this.config.validateMaxDABlockGas,
1652
+ },
1642
1653
  );
1643
1654
  }
1644
1655
 
@@ -18,7 +18,6 @@ export class PeerManagerMetrics {
18
18
  private sentGoodbyes: UpDownCounter;
19
19
  private receivedGoodbyes: UpDownCounter;
20
20
  private peerCount: Gauge;
21
- private healthyPeerCount: Gauge;
22
21
  private lowScoreDisconnects: UpDownCounter;
23
22
  private peerConnectionDuration: Histogram;
24
23
 
@@ -50,7 +49,6 @@ export class PeerManagerMetrics {
50
49
  goodbyeReasonAttrs,
51
50
  );
52
51
  this.peerCount = meter.createGauge(Metrics.PEER_MANAGER_PEER_COUNT);
53
- this.healthyPeerCount = meter.createGauge(Metrics.PEER_MANAGER_HEALTHY_PEER_COUNT);
54
52
  this.lowScoreDisconnects = createUpDownCounterWithDefault(meter, Metrics.PEER_MANAGER_LOW_SCORE_DISCONNECTS, {
55
53
  [Attributes.P2P_PEER_SCORE_STATE]: ['Banned', 'Disconnect'],
56
54
  });
@@ -69,10 +67,6 @@ export class PeerManagerMetrics {
69
67
  this.peerCount.record(count);
70
68
  }
71
69
 
72
- public recordHealthyPeerCount(count: number) {
73
- this.healthyPeerCount.record(count);
74
- }
75
-
76
70
  public recordLowScoreDisconnect(scoreState: 'Banned' | 'Disconnect') {
77
71
  this.lowScoreDisconnects.add(1, { [Attributes.P2P_PEER_SCORE_STATE]: scoreState });
78
72
  }
@@ -85,7 +79,6 @@ export class PeerManagerMetrics {
85
79
  const connectedAt = this.peerConnectedAt.get(id.toString());
86
80
  if (connectedAt) {
87
81
  this.peerConnectionDuration.record(Date.now() - connectedAt);
88
- this.peerConnectedAt.delete(id.toString());
89
82
  }
90
83
  }
91
84
  }
@@ -515,8 +515,7 @@ export class PeerManager implements PeerManagerInterface {
515
515
  ...this.peerScoring.getStats(),
516
516
  });
517
517
 
518
- this.metrics.recordPeerCount(connections.length);
519
- this.metrics.recordHealthyPeerCount(healthyConnections.length);
518
+ this.metrics.recordPeerCount(healthyConnections.length);
520
519
 
521
520
  // Exit if no peers to connect
522
521
  if (peersToConnect <= 0) {