@aztec/p2p 4.1.0-rc.2 → 4.1.0-rc.3

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 (53) hide show
  1. package/dest/client/factory.d.ts +1 -1
  2. package/dest/client/factory.d.ts.map +1 -1
  3. package/dest/client/factory.js +6 -1
  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 +8 -2
  7. package/dest/config.d.ts +10 -1
  8. package/dest/config.d.ts.map +1 -1
  9. package/dest/config.js +15 -0
  10. package/dest/mem_pools/tx_pool/priority.d.ts +2 -2
  11. package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
  12. package/dest/mem_pools/tx_pool/priority.js +4 -4
  13. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
  14. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
  15. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +3 -1
  16. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +1 -1
  17. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -1
  18. package/dest/msg_validators/tx_validator/allowed_public_setup.js +15 -29
  19. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts +17 -0
  20. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts.map +1 -0
  21. package/dest/msg_validators/tx_validator/allowed_setup_helpers.js +24 -0
  22. package/dest/msg_validators/tx_validator/factory.d.ts +15 -4
  23. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  24. package/dest/msg_validators/tx_validator/factory.js +13 -6
  25. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +1 -1
  26. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -1
  27. package/dest/msg_validators/tx_validator/fee_payer_balance.js +6 -2
  28. package/dest/msg_validators/tx_validator/gas_validator.d.ts +13 -4
  29. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  30. package/dest/msg_validators/tx_validator/gas_validator.js +39 -9
  31. package/dest/msg_validators/tx_validator/index.d.ts +2 -1
  32. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  33. package/dest/msg_validators/tx_validator/index.js +1 -0
  34. package/dest/services/libp2p/libp2p_service.d.ts +1 -1
  35. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  36. package/dest/services/libp2p/libp2p_service.js +16 -8
  37. package/dest/test-helpers/testbench-utils.d.ts +1 -1
  38. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  39. package/dest/test-helpers/testbench-utils.js +2 -1
  40. package/package.json +14 -14
  41. package/src/client/factory.ts +6 -0
  42. package/src/client/p2p_client.ts +5 -4
  43. package/src/config.ts +25 -0
  44. package/src/mem_pools/tx_pool/priority.ts +4 -4
  45. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +3 -1
  46. package/src/msg_validators/tx_validator/allowed_public_setup.ts +9 -34
  47. package/src/msg_validators/tx_validator/allowed_setup_helpers.ts +31 -0
  48. package/src/msg_validators/tx_validator/factory.ts +15 -2
  49. package/src/msg_validators/tx_validator/fee_payer_balance.ts +6 -2
  50. package/src/msg_validators/tx_validator/gas_validator.ts +41 -8
  51. package/src/msg_validators/tx_validator/index.ts +1 -0
  52. package/src/services/libp2p/libp2p_service.ts +17 -7
  53. package/src/test-helpers/testbench-utils.ts +1 -0
@@ -0,0 +1,31 @@
1
+ import type { Fr } from '@aztec/foundation/curves/bn254';
2
+ import { FunctionSelector, countArgumentsSize, getAllFunctionAbis } from '@aztec/stdlib/abi';
3
+ import type { ContractArtifact } from '@aztec/stdlib/abi';
4
+ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
5
+ import type { AllowedElement } from '@aztec/stdlib/interfaces/server';
6
+
7
+ /**
8
+ * Builds an AllowedElement from a contract artifact, deriving both the function selector
9
+ * and calldata length from the artifact instead of hardcoding signature strings.
10
+ */
11
+ export async function buildAllowedElement(
12
+ artifact: ContractArtifact,
13
+ target: { address: AztecAddress } | { classId: Fr },
14
+ functionName: string,
15
+ opts?: { onlySelf?: boolean; rejectNullMsgSender?: boolean },
16
+ ): Promise<AllowedElement> {
17
+ const allFunctions = getAllFunctionAbis(artifact);
18
+ const fn = allFunctions.find(f => f.name === functionName);
19
+ if (!fn) {
20
+ throw new Error(`Unknown function ${functionName} in artifact ${artifact.name}`);
21
+ }
22
+ const selector = await FunctionSelector.fromNameAndParameters(fn.name, fn.parameters);
23
+ const calldataLength = 1 + countArgumentsSize(fn);
24
+ return {
25
+ ...target,
26
+ selector,
27
+ calldataLength,
28
+ ...(opts?.onlySelf ? { onlySelf: true } : {}),
29
+ ...(opts?.rejectNullMsgSender ? { rejectNullMsgSender: true } : {}),
30
+ } as AllowedElement;
31
+ }
@@ -97,6 +97,7 @@ export function createFirstStageTxValidationsForGossipedTransactions(
97
97
  txsPermitted: boolean,
98
98
  allowedInSetup: AllowedElement[] = [],
99
99
  bindings?: LoggerBindings,
100
+ gasLimitOpts?: { rollupManaLimit?: number; maxBlockL2Gas?: number; maxBlockDAGas?: number },
100
101
  ): Record<string, TransactionValidator> {
101
102
  const merkleTree = worldStateSynchronizer.getCommitted();
102
103
 
@@ -158,6 +159,7 @@ export function createFirstStageTxValidationsForGossipedTransactions(
158
159
  ProtocolContractAddress.FeeJuice,
159
160
  gasFees,
160
161
  bindings,
162
+ gasLimitOpts,
161
163
  ),
162
164
  severity: PeerErrorSeverity.MidToleranceError,
163
165
  },
@@ -278,6 +280,9 @@ export function createTxValidatorForAcceptingTxsOverRPC(
278
280
  timestamp,
279
281
  blockNumber,
280
282
  txsPermitted,
283
+ rollupManaLimit,
284
+ maxBlockL2Gas,
285
+ maxBlockDAGas,
281
286
  }: {
282
287
  l1ChainId: number;
283
288
  rollupVersion: number;
@@ -287,6 +292,9 @@ export function createTxValidatorForAcceptingTxsOverRPC(
287
292
  timestamp: UInt64;
288
293
  blockNumber: BlockNumber;
289
294
  txsPermitted: boolean;
295
+ rollupManaLimit: number;
296
+ maxBlockL2Gas?: number;
297
+ maxBlockDAGas?: number;
290
298
  },
291
299
  bindings?: LoggerBindings,
292
300
  ): TxValidator<Tx> {
@@ -317,7 +325,11 @@ export function createTxValidatorForAcceptingTxsOverRPC(
317
325
 
318
326
  if (!skipFeeEnforcement) {
319
327
  validators.push(
320
- new GasTxValidator(new DatabasePublicStateSource(db), ProtocolContractAddress.FeeJuice, gasFees, bindings),
328
+ new GasTxValidator(new DatabasePublicStateSource(db), ProtocolContractAddress.FeeJuice, gasFees, bindings, {
329
+ rollupManaLimit,
330
+ maxBlockL2Gas,
331
+ maxBlockDAGas,
332
+ }),
321
333
  );
322
334
  }
323
335
 
@@ -403,6 +415,7 @@ export async function createTxValidatorForTransactionsEnteringPendingTxPool(
403
415
  worldStateSynchronizer: WorldStateSynchronizer,
404
416
  timestamp: bigint,
405
417
  blockNumber: BlockNumber,
418
+ gasLimitOpts: { rollupManaLimit?: number; maxBlockL2Gas?: number; maxBlockDAGas?: number },
406
419
  bindings?: LoggerBindings,
407
420
  ): Promise<TxValidator<TxMetaData>> {
408
421
  await worldStateSynchronizer.syncImmediate();
@@ -419,7 +432,7 @@ export async function createTxValidatorForTransactionsEnteringPendingTxPool(
419
432
  },
420
433
  };
421
434
  return new AggregateTxValidator<TxMetaData>(
422
- new GasLimitsValidator<TxMetaData>(bindings),
435
+ new GasLimitsValidator<TxMetaData>({ ...gasLimitOpts, bindings }),
423
436
  new TimestampTxValidator<TxMetaData>({ timestamp, blockNumber }, bindings),
424
437
  new DoubleSpendTxValidator<TxMetaData>(nullifierSource, bindings),
425
438
  new BlockHeaderTxValidator<TxMetaData>(archiveSource, bindings),
@@ -1,5 +1,6 @@
1
+ import { FeeJuiceArtifact } from '@aztec/protocol-contracts/fee-juice';
1
2
  import { getCallRequestsWithCalldataByPhase } from '@aztec/simulator/server';
2
- import { FunctionSelector } from '@aztec/stdlib/abi';
3
+ import { FunctionSelector, getAllFunctionAbis } from '@aztec/stdlib/abi';
3
4
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
4
5
  import { type Tx, TxExecutionPhase } from '@aztec/stdlib/tx';
5
6
 
@@ -8,7 +9,10 @@ export type FeePayerBalanceDelta = {
8
9
  claimAmount: bigint;
9
10
  };
10
11
 
11
- const increasePublicBalanceSelectorPromise = FunctionSelector.fromSignature('_increase_public_balance((Field),u128)');
12
+ const increasePublicBalanceSelectorPromise = (() => {
13
+ const fn = getAllFunctionAbis(FeeJuiceArtifact).find(f => f.name === '_increase_public_balance')!;
14
+ return FunctionSelector.fromNameAndParameters(fn.name, fn.parameters);
15
+ })();
12
16
 
13
17
  export function getTxFeeLimit(tx: Tx): bigint {
14
18
  return tx.data.constants.txContext.gasSettings.getFeeLimit().toBigInt();
@@ -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
  }
@@ -8,6 +8,7 @@ export * from './gas_validator.js';
8
8
  export * from './phases_validator.js';
9
9
  export * from './test_utils.js';
10
10
  export * from './allowed_public_setup.js';
11
+ export * from './allowed_setup_helpers.js';
11
12
  export * from './archive_cache.js';
12
13
  export * from './tx_permitted_validator.js';
13
14
  export * from './timestamp_validator.js';
@@ -1,5 +1,6 @@
1
1
  import type { EpochCacheInterface } from '@aztec/epoch-cache';
2
2
  import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
3
+ import { maxBy } from '@aztec/foundation/collection';
3
4
  import { Fr } from '@aztec/foundation/curves/bn254';
4
5
  import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
5
6
  import { RunningPromise } from '@aztec/foundation/running-promise';
@@ -19,6 +20,7 @@ import {
19
20
  P2PMessage,
20
21
  type ValidationResult as P2PValidationResult,
21
22
  PeerErrorSeverity,
23
+ PeerErrorSeverityByHarshness,
22
24
  TopicType,
23
25
  createTopicString,
24
26
  getTopicsForConfig,
@@ -224,7 +226,7 @@ export class LibP2PService extends WithTracer implements P2PService {
224
226
 
225
227
  const proposalValidatorOpts = {
226
228
  txsPermitted: !config.disableTransactions,
227
- maxTxsPerBlock: config.validateMaxTxsPerBlock,
229
+ maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint,
228
230
  };
229
231
  this.blockProposalValidator = new BlockProposalValidator(epochCache, proposalValidatorOpts);
230
232
  this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts);
@@ -235,11 +237,11 @@ export class LibP2PService extends WithTracer implements P2PService {
235
237
  this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
236
238
 
237
239
  this.blockReceivedCallback = async (block: BlockProposal): Promise<boolean> => {
238
- this.logger.debug(
239
- `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.`,
240
242
  { p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier() },
241
243
  );
242
- return false;
244
+ return true;
243
245
  };
244
246
 
245
247
  this.checkpointReceivedCallback = (
@@ -1190,7 +1192,7 @@ export class LibP2PService extends WithTracer implements P2PService {
1190
1192
  // Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
1191
1193
  const isValid = await this.blockReceivedCallback(block, sender);
1192
1194
  if (!isValid) {
1193
- this.logger.warn(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
1195
+ this.logger.info(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
1194
1196
  }
1195
1197
  }
1196
1198
 
@@ -1624,6 +1626,7 @@ export class LibP2PService extends WithTracer implements P2PService {
1624
1626
  ...(this.config.txPublicSetupAllowListExtend ?? []),
1625
1627
  ];
1626
1628
  const blockNumber = BlockNumber(currentBlockNumber + 1);
1629
+ const l1Constants = await this.archiver.getL1Constants();
1627
1630
 
1628
1631
  return createFirstStageTxValidationsForGossipedTransactions(
1629
1632
  nextSlotTimestamp,
@@ -1637,6 +1640,11 @@ export class LibP2PService extends WithTracer implements P2PService {
1637
1640
  !this.config.disableTransactions,
1638
1641
  allowedInSetup,
1639
1642
  this.logger.getBindings(),
1643
+ {
1644
+ rollupManaLimit: l1Constants.rollupManaLimit,
1645
+ maxBlockL2Gas: this.config.validateMaxL2BlockGas,
1646
+ maxBlockDAGas: this.config.validateMaxDABlockGas,
1647
+ },
1640
1648
  );
1641
1649
  }
1642
1650
 
@@ -1662,8 +1670,10 @@ export class LibP2PService extends WithTracer implements P2PService {
1662
1670
 
1663
1671
  // A promise that resolves when all validations have been run
1664
1672
  const allValidations = await Promise.all(validationPromises);
1665
- const failed = allValidations.find(x => !x.isValid);
1666
- if (failed) {
1673
+ const failures = allValidations.filter(x => !x.isValid);
1674
+ if (failures.length > 0) {
1675
+ // Pick the most severe failure (lowest tolerance = harshest penalty)
1676
+ const failed = maxBy(failures, f => PeerErrorSeverityByHarshness.indexOf(f.severity))!;
1667
1677
  return {
1668
1678
  allPassed: false,
1669
1679
  failure: {
@@ -292,6 +292,7 @@ export function createMockEpochCache(): EpochCacheInterface {
292
292
  ethereumSlotDuration: 1,
293
293
  proofSubmissionEpochs: 1,
294
294
  targetCommitteeSize: 48,
295
+ rollupManaLimit: Number.MAX_SAFE_INTEGER,
295
296
  }),
296
297
  };
297
298
  }