@aztec/p2p 0.0.1-commit.1142ef1 → 0.0.1-commit.1bea0213

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 (119) hide show
  1. package/dest/client/p2p_client.js +1 -1
  2. package/dest/config.js +2 -2
  3. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
  4. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  5. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +20 -9
  6. package/dest/mem_pools/attestation_pool/mocks.d.ts +4 -2
  7. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  8. package/dest/mem_pools/attestation_pool/mocks.js +8 -5
  9. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +15 -10
  10. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
  11. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +91 -50
  12. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +19 -5
  13. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +1 -1
  14. package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +59 -3
  15. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +79 -5
  16. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +1 -1
  17. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +47 -0
  18. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +16 -0
  19. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -0
  20. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +122 -0
  21. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +2 -2
  22. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -1
  23. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +4 -4
  24. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -1
  25. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +2 -0
  26. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +2 -2
  27. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +1 -1
  28. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +25 -0
  29. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +1 -0
  30. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +57 -0
  31. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +3 -3
  32. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  33. package/dest/msg_validators/attestation_validator/attestation_validator.js +41 -10
  34. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +3 -3
  35. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
  36. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +11 -4
  37. package/dest/msg_validators/clock_tolerance.d.ts +21 -0
  38. package/dest/msg_validators/clock_tolerance.d.ts.map +1 -0
  39. package/dest/msg_validators/clock_tolerance.js +37 -0
  40. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +3 -3
  41. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
  42. package/dest/msg_validators/proposal_validator/proposal_validator.js +52 -28
  43. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +3 -3
  44. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +1 -1
  45. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +93 -64
  46. package/dest/msg_validators/tx_validator/block_header_validator.d.ts +1 -1
  47. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  48. package/dest/msg_validators/tx_validator/block_header_validator.js +1 -1
  49. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +10 -0
  50. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -0
  51. package/dest/msg_validators/tx_validator/fee_payer_balance.js +20 -0
  52. package/dest/msg_validators/tx_validator/gas_validator.d.ts +1 -1
  53. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  54. package/dest/msg_validators/tx_validator/gas_validator.js +8 -14
  55. package/dest/msg_validators/tx_validator/index.d.ts +2 -1
  56. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  57. package/dest/msg_validators/tx_validator/index.js +1 -0
  58. package/dest/msg_validators/tx_validator/size_validator.d.ts +6 -0
  59. package/dest/msg_validators/tx_validator/size_validator.d.ts.map +1 -0
  60. package/dest/msg_validators/tx_validator/size_validator.js +20 -0
  61. package/dest/services/encoding.d.ts +1 -1
  62. package/dest/services/encoding.d.ts.map +1 -1
  63. package/dest/services/encoding.js +2 -3
  64. package/dest/services/libp2p/instrumentation.js +5 -5
  65. package/dest/services/libp2p/libp2p_service.d.ts +5 -5
  66. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  67. package/dest/services/libp2p/libp2p_service.js +26 -26
  68. package/dest/services/reqresp/constants.d.ts +12 -0
  69. package/dest/services/reqresp/constants.d.ts.map +1 -0
  70. package/dest/services/reqresp/constants.js +7 -0
  71. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +1 -1
  72. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
  73. package/dest/services/reqresp/protocols/block_txs/bitvector.js +7 -0
  74. package/dest/services/reqresp/protocols/status.d.ts +1 -1
  75. package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
  76. package/dest/services/reqresp/protocols/status.js +2 -1
  77. package/dest/services/tx_collection/slow_tx_collection.d.ts +3 -3
  78. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
  79. package/dest/services/tx_collection/tx_collection.d.ts +5 -5
  80. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  81. package/dest/services/tx_provider.d.ts +3 -3
  82. package/dest/services/tx_provider.d.ts.map +1 -1
  83. package/dest/testbench/p2p_client_testbench_worker.js +5 -6
  84. package/package.json +16 -16
  85. package/src/client/p2p_client.ts +6 -6
  86. package/src/config.ts +2 -2
  87. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +17 -9
  88. package/src/mem_pools/attestation_pool/mocks.ts +6 -4
  89. package/src/mem_pools/tx_pool/README.md +28 -13
  90. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +130 -75
  91. package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +66 -5
  92. package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +119 -4
  93. package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +162 -0
  94. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +4 -2
  95. package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +75 -0
  96. package/src/msg_validators/attestation_validator/attestation_validator.ts +26 -14
  97. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +6 -6
  98. package/src/msg_validators/clock_tolerance.ts +51 -0
  99. package/src/msg_validators/proposal_validator/proposal_validator.ts +28 -28
  100. package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +91 -67
  101. package/src/msg_validators/tx_validator/block_header_validator.ts +3 -1
  102. package/src/msg_validators/tx_validator/fee_payer_balance.ts +40 -0
  103. package/src/msg_validators/tx_validator/gas_validator.ts +8 -25
  104. package/src/msg_validators/tx_validator/index.ts +1 -0
  105. package/src/msg_validators/tx_validator/size_validator.ts +18 -0
  106. package/src/services/encoding.ts +2 -3
  107. package/src/services/libp2p/instrumentation.ts +5 -5
  108. package/src/services/libp2p/libp2p_service.ts +39 -27
  109. package/src/services/reqresp/constants.ts +14 -0
  110. package/src/services/reqresp/protocols/block_txs/bitvector.ts +9 -0
  111. package/src/services/reqresp/protocols/status.ts +5 -3
  112. package/src/services/tx_collection/slow_tx_collection.ts +2 -2
  113. package/src/services/tx_collection/tx_collection.ts +4 -4
  114. package/src/services/tx_provider.ts +2 -2
  115. package/src/testbench/p2p_client_testbench_worker.ts +6 -10
  116. package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts +0 -15
  117. package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts.map +0 -1
  118. package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.js +0 -88
  119. package/src/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.ts +0 -108
@@ -20,6 +20,7 @@ import {
20
20
  type Gossipable,
21
21
  P2PClientType,
22
22
  P2PMessage,
23
+ type ValidationResult as P2PValidationResult,
23
24
  PeerErrorSeverity,
24
25
  TopicType,
25
26
  createTopicString,
@@ -66,6 +67,7 @@ import {
66
67
  CheckpointAttestationValidator,
67
68
  CheckpointProposalValidator,
68
69
  FishermanAttestationValidator,
70
+ SizeTxValidator,
69
71
  } from '../../msg_validators/index.js';
70
72
  import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
71
73
  import { getDefaultAllowedSetupFunctions } from '../../msg_validators/tx_validator/allowed_public_setup.js';
@@ -923,7 +925,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
923
925
  const validationFunc: () => Promise<ReceivedMessageValidationResult<CheckpointAttestation>> = async () => {
924
926
  const attestation = CheckpointAttestation.fromBuffer(payloadData);
925
927
  const pool = this.mempools.attestationPool;
926
- const isValid = await this.validateCheckpointAttestation(source, attestation);
928
+ const validationResult = await this.validateCheckpointAttestation(source, attestation);
929
+ const isValid = validationResult.result === 'accept';
927
930
  const exists = isValid && (await pool.hasCheckpointAttestation(attestation));
928
931
 
929
932
  let canAdd = true;
@@ -942,9 +945,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
942
945
  [Attributes.P2P_ID]: source.toString(),
943
946
  });
944
947
 
945
- if (!isValid) {
948
+ if (validationResult.result === 'reject') {
946
949
  return { result: TopicValidatorResult.Reject };
947
- } else if (exists) {
950
+ } else if (validationResult.result === 'ignore' || exists) {
948
951
  return { result: TopicValidatorResult.Ignore, obj: attestation };
949
952
  } else if (!canAdd) {
950
953
  this.logger.warn(`Dropping checkpoint attestation due to per-(slot, proposalId) attestation cap`, {
@@ -985,7 +988,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
985
988
  private async processBlockFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
986
989
  const validationFunc: () => Promise<ReceivedMessageValidationResult<BlockProposal>> = async () => {
987
990
  const block = BlockProposal.fromBuffer(payloadData);
988
- const isValid = await this.validateBlockProposal(source, block);
991
+ const validationResult = await this.validateBlockProposal(source, block);
992
+ const isValid = validationResult.result === 'accept';
989
993
  const pool = this.mempools.attestationPool;
990
994
 
991
995
  const exists = isValid && (await pool.hasBlockProposal(block));
@@ -999,9 +1003,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
999
1003
  [Attributes.P2P_ID]: source.toString(),
1000
1004
  });
1001
1005
 
1002
- if (!isValid) {
1006
+ if (validationResult.result === 'reject') {
1003
1007
  return { result: TopicValidatorResult.Reject };
1004
- } else if (exists) {
1008
+ } else if (validationResult.result === 'ignore' || exists) {
1005
1009
  return { result: TopicValidatorResult.Ignore, obj: block };
1006
1010
  } else if (!canAdd) {
1007
1011
  this.peerManager.penalizePeer(source, PeerErrorSeverity.MidToleranceError);
@@ -1081,7 +1085,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1081
1085
  // TODO(palla/mbps): This pattern is repeated across multiple message handlers, consider abstracting it.
1082
1086
  const validationFunc: () => Promise<ReceivedMessageValidationResult<CheckpointProposal>> = async () => {
1083
1087
  const checkpoint = CheckpointProposal.fromBuffer(payloadData);
1084
- const isValid = await this.validateCheckpointProposal(source, checkpoint);
1088
+ const validationResult = await this.validateCheckpointProposal(source, checkpoint);
1089
+ const isValid = validationResult.result === 'accept';
1085
1090
  const pool = this.mempools.attestationPool;
1086
1091
 
1087
1092
  const exists = isValid && (await pool.hasCheckpointProposal(checkpoint));
@@ -1095,9 +1100,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1095
1100
  [Attributes.P2P_ID]: source.toString(),
1096
1101
  });
1097
1102
 
1098
- if (!isValid) {
1103
+ if (validationResult.result === 'reject') {
1099
1104
  return { result: TopicValidatorResult.Reject };
1100
- } else if (exists) {
1105
+ } else if (validationResult.result === 'ignore' || exists) {
1101
1106
  return { result: TopicValidatorResult.Ignore, obj: checkpoint };
1102
1107
  } else if (!canAdd) {
1103
1108
  this.peerManager.penalizePeer(source, PeerErrorSeverity.MidToleranceError);
@@ -1370,6 +1375,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1370
1375
  private createRequestedTxValidator(): TxValidator {
1371
1376
  return new AggregateTxValidator(
1372
1377
  new DataTxValidator(),
1378
+ new SizeTxValidator(),
1373
1379
  new MetadataTxValidator({
1374
1380
  l1ChainId: new Fr(this.config.l1ChainId),
1375
1381
  rollupVersion: new Fr(this.config.rollupVersion),
@@ -1574,15 +1580,18 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1574
1580
  [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
1575
1581
  [Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then(i => i.toString()),
1576
1582
  }))
1577
- public async validateCheckpointAttestation(peerId: PeerId, attestation: CheckpointAttestation): Promise<boolean> {
1578
- const severity = await this.checkpointAttestationValidator.validate(attestation);
1579
- if (severity) {
1583
+ public async validateCheckpointAttestation(
1584
+ peerId: PeerId,
1585
+ attestation: CheckpointAttestation,
1586
+ ): Promise<P2PValidationResult> {
1587
+ const result = await this.checkpointAttestationValidator.validate(attestation);
1588
+
1589
+ if (result.result === 'reject') {
1580
1590
  this.logger.debug(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
1581
- this.peerManager.penalizePeer(peerId, severity);
1582
- return false;
1591
+ this.peerManager.penalizePeer(peerId, result.severity);
1583
1592
  }
1584
1593
 
1585
- return true;
1594
+ return result;
1586
1595
  }
1587
1596
 
1588
1597
  /**
@@ -1594,15 +1603,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1594
1603
  @trackSpan('Libp2pService.validateBlockProposal', (_peerId, block) => ({
1595
1604
  [Attributes.SLOT_NUMBER]: block.slotNumber.toString(),
1596
1605
  }))
1597
- public async validateBlockProposal(peerId: PeerId, block: BlockProposal): Promise<boolean> {
1598
- const severity = await this.blockProposalValidator.validate(block);
1599
- if (severity) {
1606
+ public async validateBlockProposal(peerId: PeerId, block: BlockProposal): Promise<P2PValidationResult> {
1607
+ const result = await this.blockProposalValidator.validate(block);
1608
+
1609
+ if (result.result === 'reject') {
1600
1610
  this.logger.debug(`Penalizing peer ${peerId} for block proposal validation failure`);
1601
- this.peerManager.penalizePeer(peerId, severity);
1602
- return false;
1611
+ this.peerManager.penalizePeer(peerId, result.severity);
1603
1612
  }
1604
1613
 
1605
- return true;
1614
+ return result;
1606
1615
  }
1607
1616
 
1608
1617
  /**
@@ -1614,15 +1623,18 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1614
1623
  @trackSpan('Libp2pService.validateCheckpointProposal', (_peerId, checkpoint) => ({
1615
1624
  [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
1616
1625
  }))
1617
- public async validateCheckpointProposal(peerId: PeerId, checkpoint: CheckpointProposal): Promise<boolean> {
1618
- const severity = await this.checkpointProposalValidator.validate(checkpoint);
1619
- if (severity) {
1626
+ public async validateCheckpointProposal(
1627
+ peerId: PeerId,
1628
+ checkpoint: CheckpointProposal,
1629
+ ): Promise<P2PValidationResult> {
1630
+ const result = await this.checkpointProposalValidator.validate(checkpoint);
1631
+
1632
+ if (result.result === 'reject') {
1620
1633
  this.logger.debug(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
1621
- this.peerManager.penalizePeer(peerId, severity);
1622
- return false;
1634
+ this.peerManager.penalizePeer(peerId, result.severity);
1623
1635
  }
1624
1636
 
1625
- return true;
1637
+ return result;
1626
1638
  }
1627
1639
 
1628
1640
  public getPeerScore(peerId: PeerId): number {
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Constants for P2P message deserialization bounds checking.
3
+ * These constants define maximum allowed sizes during deserialization
4
+ * to prevent DoS attacks via maliciously crafted messages.
5
+ */
6
+
7
+ /** Max transactions per block for deserialization validation (~300x default of 32) */
8
+ export { MAX_TXS_PER_BLOCK } from '@aztec/stdlib/deserialization';
9
+
10
+ /** Max version string length (e.g., "1.0.0-alpha.123") */
11
+ export const MAX_VERSION_STRING_LENGTH = 64;
12
+
13
+ /** Max block hash string length (hex: 0x + 64 chars, with generous headroom) */
14
+ export const MAX_BLOCK_HASH_STRING_LENGTH = 128;
@@ -1,5 +1,7 @@
1
1
  import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
2
2
 
3
+ import { MAX_TXS_PER_BLOCK } from '../../constants.js';
4
+
3
5
  /**
4
6
  * BitVector helper class for representing and serializing bit vectors
5
7
  */
@@ -80,6 +82,13 @@ export class BitVector {
80
82
  const reader = BufferReader.asReader(buffer);
81
83
  const length = reader.readNumber();
82
84
 
85
+ if (length < 0) {
86
+ throw new Error(`BitVector length ${length} cannot be negative`);
87
+ }
88
+ if (length > MAX_TXS_PER_BLOCK) {
89
+ throw new Error(`BitVector length ${length} exceeds maximum ${MAX_TXS_PER_BLOCK}`);
90
+ }
91
+
83
92
  const bitBuffer = reader.readBytes(BitVector.byteLength(length));
84
93
  return new BitVector(bitBuffer, length);
85
94
  }
@@ -7,6 +7,8 @@ import type { WorldStateSyncStatus, WorldStateSynchronizer } from '@aztec/stdlib
7
7
 
8
8
  import type { PeerId } from '@libp2p/interface';
9
9
 
10
+ import { MAX_BLOCK_HASH_STRING_LENGTH, MAX_VERSION_STRING_LENGTH } from '../constants.js';
11
+
10
12
  /*
11
13
  * P2P Status Message
12
14
  * It is used to establish Status handshake between to peers
@@ -32,12 +34,12 @@ export class StatusMessage {
32
34
  static fromBuffer(buffer: Buffer | BufferReader): StatusMessage {
33
35
  const reader = BufferReader.asReader(buffer);
34
36
  return new StatusMessage(
35
- reader.readString(), // compressedComponentsVersion
37
+ reader.readString(MAX_VERSION_STRING_LENGTH), // compressedComponentsVersion
36
38
  BlockNumber(reader.readNumber()), // latestBlockNumber
37
- reader.readString(), // latestBlockHash
39
+ reader.readString(MAX_BLOCK_HASH_STRING_LENGTH), // latestBlockHash
38
40
  BlockNumber(reader.readNumber()), // finalizedBlockNumber
39
41
  //TODO: add finalizedBlockHash
40
- //reader.readString(), // finalizedBlockHash
42
+ //reader.readString(MAX_BLOCK_HASH_STRING_LENGTH), // finalizedBlockHash
41
43
  );
42
44
  }
43
45
 
@@ -4,7 +4,7 @@ import { type Logger, createLogger } from '@aztec/foundation/log';
4
4
  import { boundInclusive } from '@aztec/foundation/number';
5
5
  import { RunningPromise } from '@aztec/foundation/promise';
6
6
  import { DateProvider } from '@aztec/foundation/timer';
7
- import type { L2BlockNew } from '@aztec/stdlib/block';
7
+ import type { L2Block } from '@aztec/stdlib/block';
8
8
  import { type L1RollupConstants, getEpochAtSlot, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
9
9
  import { type Tx, TxHash } from '@aztec/stdlib/tx';
10
10
 
@@ -76,7 +76,7 @@ export class SlowTxCollection {
76
76
  }
77
77
 
78
78
  /** Starts collecting the given tx hashes for the given L2Block in the slow loop */
79
- public startCollecting(block: L2BlockNew, txHashes: TxHash[]) {
79
+ public startCollecting(block: L2Block, txHashes: TxHash[]) {
80
80
  const slot = block.header.getSlot();
81
81
  const deadline = this.getDeadlineForSlot(slot);
82
82
  if (+deadline < this.dateProvider.now()) {
@@ -3,7 +3,7 @@ import { compactArray } from '@aztec/foundation/collection';
3
3
  import { type Logger, createLogger } from '@aztec/foundation/log';
4
4
  import { type PromiseWithResolvers, RunningPromise } from '@aztec/foundation/promise';
5
5
  import { DateProvider } from '@aztec/foundation/timer';
6
- import type { L2BlockInfo, L2BlockNew } from '@aztec/stdlib/block';
6
+ import type { L2Block, L2BlockInfo } from '@aztec/stdlib/block';
7
7
  import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
8
8
  import type { BlockProposal } from '@aztec/stdlib/p2p';
9
9
  import { Tx, TxHash } from '@aztec/stdlib/tx';
@@ -25,7 +25,7 @@ export type CollectionMethod = 'fast-req-resp' | 'fast-node-rpc' | 'slow-req-res
25
25
  export type MissingTxInfo = { blockNumber: BlockNumber; deadline: Date; readyForReqResp: boolean };
26
26
 
27
27
  export type FastCollectionRequestInput =
28
- | { type: 'block'; block: L2BlockNew }
28
+ | { type: 'block'; block: L2Block }
29
29
  | { type: 'proposal'; blockProposal: BlockProposal; blockNumber: BlockNumber };
30
30
 
31
31
  export type FastCollectionRequest = FastCollectionRequestInput & {
@@ -146,7 +146,7 @@ export class TxCollection {
146
146
  }
147
147
 
148
148
  /** Starts collecting the given tx hashes for the given L2Block in the slow loop */
149
- public startCollecting(block: L2BlockNew, txHashes: TxHash[]) {
149
+ public startCollecting(block: L2Block, txHashes: TxHash[]) {
150
150
  return this.slowCollection.startCollecting(block, txHashes);
151
151
  }
152
152
 
@@ -162,7 +162,7 @@ export class TxCollection {
162
162
 
163
163
  /** Collects the set of txs for the given mined block as fast as possible */
164
164
  public collectFastForBlock(
165
- block: L2BlockNew,
165
+ block: L2Block,
166
166
  txHashes: TxHash[] | string[],
167
167
  opts: { deadline: Date; pinnedPeer?: PeerId },
168
168
  ) {
@@ -2,7 +2,7 @@ import { BlockNumber } from '@aztec/foundation/branded-types';
2
2
  import { compactArray } from '@aztec/foundation/collection';
3
3
  import { type Logger, createLogger } from '@aztec/foundation/log';
4
4
  import { elapsed } from '@aztec/foundation/timer';
5
- import type { L2BlockInfo, L2BlockNew } from '@aztec/stdlib/block';
5
+ import type { L2Block, L2BlockInfo } from '@aztec/stdlib/block';
6
6
  import type { ITxProvider } from '@aztec/stdlib/interfaces/server';
7
7
  import type { BlockProposal } from '@aztec/stdlib/p2p';
8
8
  import { Tx, TxHash } from '@aztec/stdlib/tx';
@@ -68,7 +68,7 @@ export class TxProvider implements ITxProvider {
68
68
  }
69
69
 
70
70
  /** Gathers txs from the tx pool, remote rpc nodes, and reqresp. */
71
- public getTxsForBlock(block: L2BlockNew, opts: { deadline: Date }): Promise<{ txs: Tx[]; missingTxs: TxHash[] }> {
71
+ public getTxsForBlock(block: L2Block, opts: { deadline: Date }): Promise<{ txs: Tx[]; missingTxs: TxHash[] }> {
72
72
  return this.getOrderedTxsFromAllSources(
73
73
  { type: 'block', block },
74
74
  block.toBlockInfo(),
@@ -7,7 +7,6 @@ import { MockL2BlockSource } from '@aztec/archiver/test';
7
7
  import type { EpochCacheInterface } from '@aztec/epoch-cache';
8
8
  import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
9
9
  import { SecretValue } from '@aztec/foundation/config';
10
- import { EthAddress } from '@aztec/foundation/eth-address';
11
10
  import { createLogger } from '@aztec/foundation/log';
12
11
  import { sleep } from '@aztec/foundation/sleep';
13
12
  import type { DataStoreConfig } from '@aztec/kv-store/config';
@@ -88,17 +87,14 @@ function mockAttestationPool(): AttestationPool {
88
87
 
89
88
  function mockEpochCache(): EpochCacheInterface {
90
89
  return {
91
- getCommittee: () => Promise.resolve({ committee: [], seed: 1n, epoch: EpochNumber.ZERO }),
90
+ getCommittee: () => Promise.resolve({ committee: [], seed: 1n, epoch: EpochNumber.ZERO, isEscapeHatchOpen: false }),
92
91
  getProposerIndexEncoding: () => '0x' as `0x${string}`,
93
- getEpochAndSlotNow: () => ({ epoch: EpochNumber.ZERO, slot: SlotNumber.ZERO, ts: 0n }),
92
+ getEpochAndSlotNow: () => ({ epoch: EpochNumber.ZERO, slot: SlotNumber.ZERO, ts: 0n, nowMs: 0n }),
94
93
  computeProposerIndex: () => 0n,
95
- getProposerAttesterAddressInCurrentOrNextSlot: () =>
96
- Promise.resolve({
97
- currentProposer: EthAddress.ZERO,
98
- nextProposer: EthAddress.ZERO,
99
- currentSlot: SlotNumber.ZERO,
100
- nextSlot: SlotNumber.ZERO,
101
- }),
94
+ getCurrentAndNextSlot: () => ({
95
+ currentSlot: SlotNumber.ZERO,
96
+ nextSlot: SlotNumber.ZERO,
97
+ }),
102
98
  getProposerAttesterAddressInSlot: () => Promise.resolve(undefined),
103
99
  getEpochAndSlotInNextL1Slot: () => ({ epoch: EpochNumber.ZERO, slot: SlotNumber.ZERO, ts: 0n, now: 0n }),
104
100
  isInCommittee: () => Promise.resolve(false),
@@ -1,15 +0,0 @@
1
- import type { ReadonlyWorldStateAccess } from '@aztec/stdlib/interfaces/server';
2
- import type { TxPoolOptions } from '../tx_pool.js';
3
- import { type EvictionContext, type EvictionResult, type EvictionRule, type TxPoolOperations } from './eviction_strategy.js';
4
- export declare class InsufficientFeePayerBalanceRule implements EvictionRule {
5
- private worldState;
6
- readonly name: string;
7
- readonly reason: string;
8
- constructor(worldState: ReadonlyWorldStateAccess);
9
- private log;
10
- evict(context: EvictionContext, txPool: TxPoolOperations): Promise<EvictionResult>;
11
- private evictTxs;
12
- private createGasTxValidator;
13
- updateConfig(_config: TxPoolOptions): void;
14
- }
15
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zdWZmaWNpZW50X2ZlZV9wYXllcl9iYWxhbmNlX3J1bGUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9tZW1fcG9vbHMvdHhfcG9vbC9ldmljdGlvbi9pbnN1ZmZpY2llbnRfZmVlX3BheWVyX2JhbGFuY2VfcnVsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQSxPQUFPLEtBQUssRUFBRSx3QkFBd0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBS2hGLE9BQU8sS0FBSyxFQUFFLGFBQWEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNuRCxPQUFPLEVBQ0wsS0FBSyxlQUFlLEVBRXBCLEtBQUssY0FBYyxFQUNuQixLQUFLLFlBQVksRUFFakIsS0FBSyxnQkFBZ0IsRUFDdEIsTUFBTSx3QkFBd0IsQ0FBQztBQUVoQyxxQkFBYSwrQkFBZ0MsWUFBVyxZQUFZO0lBSS9DLE9BQU8sQ0FBQyxVQUFVO0lBSHJDLFNBQWdCLElBQUksU0FBaUM7SUFDckQsU0FBZ0IsTUFBTSxTQUE0QjtJQUVsRCxZQUEyQixVQUFVLEVBQUUsd0JBQXdCLEVBQUk7SUFFbkUsT0FBTyxDQUFDLEdBQUcsQ0FBMkU7SUFFaEYsS0FBSyxDQUFDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxFQUFFLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FrQ3ZGO1lBRWEsUUFBUTtJQXdDdEIsT0FBTyxDQUFDLG9CQUFvQjtJQUk1QixZQUFZLENBQUMsT0FBTyxFQUFFLGFBQWEsR0FBRyxJQUFJLENBQUc7Q0FDOUMifQ==
@@ -1 +0,0 @@
1
- {"version":3,"file":"insufficient_fee_payer_balance_rule.d.ts","sourceRoot":"","sources":["../../../../src/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAKhF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EACL,KAAK,eAAe,EAEpB,KAAK,cAAc,EACnB,KAAK,YAAY,EAEjB,KAAK,gBAAgB,EACtB,MAAM,wBAAwB,CAAC;AAEhC,qBAAa,+BAAgC,YAAW,YAAY;IAI/C,OAAO,CAAC,UAAU;IAHrC,SAAgB,IAAI,SAAiC;IACrD,SAAgB,MAAM,SAA4B;IAElD,YAA2B,UAAU,EAAE,wBAAwB,EAAI;IAEnE,OAAO,CAAC,GAAG,CAA2E;IAEhF,KAAK,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,CAAC,CAkCvF;YAEa,QAAQ;IAwCtB,OAAO,CAAC,oBAAoB;IAI5B,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAG;CAC9C"}
@@ -1,88 +0,0 @@
1
- import { createLogger } from '@aztec/foundation/log';
2
- import { ProtocolContractAddress } from '@aztec/protocol-contracts';
3
- import { GasFees } from '@aztec/stdlib/gas';
4
- import { DatabasePublicStateSource } from '@aztec/stdlib/trees';
5
- import { GasTxValidator } from '../../../msg_validators/index.js';
6
- import { EvictionEvent } from './eviction_strategy.js';
7
- export class InsufficientFeePayerBalanceRule {
8
- worldState;
9
- name;
10
- reason;
11
- constructor(worldState){
12
- this.worldState = worldState;
13
- this.name = 'InsufficientFeePayerBalance';
14
- this.reason = 'insufficient_fee_juice';
15
- this.log = createLogger('p2p:mempool:tx_pool:insufficient_fee_payer_balance_rule');
16
- }
17
- log;
18
- async evict(context, txPool) {
19
- try {
20
- if (context.event === EvictionEvent.CHAIN_PRUNED) {
21
- const affectedTxs = await txPool.getPendingTxInfos();
22
- return this.evictTxs(affectedTxs, context.blockNumber, txPool);
23
- }
24
- if (context.event === EvictionEvent.BLOCK_MINED) {
25
- const affectedTxs = await txPool.getPendingTxsWithFeePayer(context.minedFeePayers);
26
- // TODO: fix this edge-case
27
- // This can lead to a race condition if we are catching up in the p2p client.
28
- // Let's say we have 3 txs for the same fee payer, which get mined in blocks 1, 2, 3.
29
- // Tx1 consumes fee juice, tx2 increases it, tx3 consumes it again. We see block1 with tx1 first, run this rule, and evict tx3.
30
- // But tx3 was valid (due to tx2) and mined on block3. And we have just removed from the mempool a tx we needed for proving/reexec.
31
- // -----
32
- // Proposed fix: evict only if node is synched
33
- return this.evictTxs(affectedTxs, context.block.getBlockNumber(), txPool);
34
- }
35
- return {
36
- reason: this.reason,
37
- success: true,
38
- txsEvicted: []
39
- };
40
- } catch (err) {
41
- this.log.error('Failed to evict invalid transactions after mining', {
42
- err
43
- });
44
- return {
45
- reason: this.reason,
46
- success: false,
47
- txsEvicted: [],
48
- error: new Error('Failed to evict invalid txs after mining', {
49
- cause: err
50
- })
51
- };
52
- }
53
- }
54
- async evictTxs(candidateTxs, blockNumber, txPool) {
55
- const txsToEvict = [];
56
- const gasValidator = this.createGasTxValidator(this.worldState.getSnapshot(blockNumber));
57
- for (const { txHash, isEvictable } of candidateTxs){
58
- if (!isEvictable) {
59
- continue;
60
- }
61
- const tx = await txPool.getTxByHash(txHash);
62
- if (!tx) {
63
- continue;
64
- }
65
- this.log.debug(`Validating tx balance ${txHash}`);
66
- if ((await gasValidator.validateTxFee(tx)).result === 'invalid') {
67
- this.log.verbose(`Evicting tx ${txHash} from pool due to an insufficient fee payer balance`);
68
- txsToEvict.push(txHash);
69
- continue;
70
- }
71
- }
72
- if (txsToEvict.length > 0) {
73
- await txPool.deleteTxs(txsToEvict);
74
- }
75
- this.log.verbose(`Evicted ${txsToEvict.length} invalid txs after block mined`, {
76
- txsToEvict
77
- });
78
- return {
79
- reason: this.reason,
80
- success: true,
81
- txsEvicted: txsToEvict
82
- };
83
- }
84
- createGasTxValidator(db) {
85
- return new GasTxValidator(new DatabasePublicStateSource(db), ProtocolContractAddress.FeeJuice, GasFees.empty());
86
- }
87
- updateConfig(_config) {}
88
- }
@@ -1,108 +0,0 @@
1
- import { createLogger } from '@aztec/foundation/log';
2
- import { ProtocolContractAddress } from '@aztec/protocol-contracts';
3
- import { GasFees } from '@aztec/stdlib/gas';
4
- import type { ReadonlyWorldStateAccess } from '@aztec/stdlib/interfaces/server';
5
- import { DatabasePublicStateSource, type MerkleTreeReadOperations } from '@aztec/stdlib/trees';
6
- import type { TxHash } from '@aztec/stdlib/tx';
7
-
8
- import { GasTxValidator } from '../../../msg_validators/index.js';
9
- import type { TxPoolOptions } from '../tx_pool.js';
10
- import {
11
- type EvictionContext,
12
- EvictionEvent,
13
- type EvictionResult,
14
- type EvictionRule,
15
- type PendingTxInfo,
16
- type TxPoolOperations,
17
- } from './eviction_strategy.js';
18
-
19
- export class InsufficientFeePayerBalanceRule implements EvictionRule {
20
- public readonly name = 'InsufficientFeePayerBalance';
21
- public readonly reason = 'insufficient_fee_juice';
22
-
23
- public constructor(private worldState: ReadonlyWorldStateAccess) {}
24
-
25
- private log = createLogger('p2p:mempool:tx_pool:insufficient_fee_payer_balance_rule');
26
-
27
- async evict(context: EvictionContext, txPool: TxPoolOperations): Promise<EvictionResult> {
28
- try {
29
- if (context.event === EvictionEvent.CHAIN_PRUNED) {
30
- const affectedTxs = await txPool.getPendingTxInfos();
31
- return this.evictTxs(affectedTxs, context.blockNumber, txPool);
32
- }
33
-
34
- if (context.event === EvictionEvent.BLOCK_MINED) {
35
- const affectedTxs = await txPool.getPendingTxsWithFeePayer(context.minedFeePayers);
36
-
37
- // TODO: fix this edge-case
38
- // This can lead to a race condition if we are catching up in the p2p client.
39
- // Let's say we have 3 txs for the same fee payer, which get mined in blocks 1, 2, 3.
40
- // Tx1 consumes fee juice, tx2 increases it, tx3 consumes it again. We see block1 with tx1 first, run this rule, and evict tx3.
41
- // But tx3 was valid (due to tx2) and mined on block3. And we have just removed from the mempool a tx we needed for proving/reexec.
42
- // -----
43
- // Proposed fix: evict only if node is synched
44
- return this.evictTxs(affectedTxs, context.block.getBlockNumber(), txPool);
45
- }
46
-
47
- return {
48
- reason: this.reason,
49
- success: true,
50
- txsEvicted: [],
51
- };
52
- } catch (err) {
53
- this.log.error('Failed to evict invalid transactions after mining', { err });
54
- return {
55
- reason: this.reason,
56
- success: false,
57
- txsEvicted: [],
58
- error: new Error('Failed to evict invalid txs after mining', { cause: err }),
59
- };
60
- }
61
- }
62
-
63
- private async evictTxs(
64
- candidateTxs: PendingTxInfo[],
65
- blockNumber: number,
66
- txPool: TxPoolOperations,
67
- ): Promise<EvictionResult> {
68
- const txsToEvict: TxHash[] = [];
69
- const gasValidator = this.createGasTxValidator(this.worldState.getSnapshot(blockNumber));
70
-
71
- for (const { txHash, isEvictable } of candidateTxs) {
72
- if (!isEvictable) {
73
- continue;
74
- }
75
-
76
- const tx = await txPool.getTxByHash(txHash);
77
- if (!tx) {
78
- continue;
79
- }
80
-
81
- this.log.debug(`Validating tx balance ${txHash}`);
82
-
83
- if ((await gasValidator.validateTxFee(tx)).result === 'invalid') {
84
- this.log.verbose(`Evicting tx ${txHash} from pool due to an insufficient fee payer balance`);
85
- txsToEvict.push(txHash);
86
- continue;
87
- }
88
- }
89
-
90
- if (txsToEvict.length > 0) {
91
- await txPool.deleteTxs(txsToEvict);
92
- }
93
-
94
- this.log.verbose(`Evicted ${txsToEvict.length} invalid txs after block mined`, { txsToEvict });
95
-
96
- return {
97
- reason: this.reason,
98
- success: true,
99
- txsEvicted: txsToEvict,
100
- };
101
- }
102
-
103
- private createGasTxValidator(db: MerkleTreeReadOperations): GasTxValidator {
104
- return new GasTxValidator(new DatabasePublicStateSource(db), ProtocolContractAddress.FeeJuice, GasFees.empty());
105
- }
106
-
107
- updateConfig(_config: TxPoolOptions): void {}
108
- }