@aztec/p2p 4.0.0-rc.5 → 4.0.0-rc.7

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 (92) 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 +8 -20
  4. package/dest/client/interface.d.ts +6 -11
  5. package/dest/client/interface.d.ts.map +1 -1
  6. package/dest/client/p2p_client.d.ts +4 -11
  7. package/dest/client/p2p_client.d.ts.map +1 -1
  8. package/dest/client/p2p_client.js +5 -57
  9. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +1 -2
  10. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +1 -1
  11. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -1
  12. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +2 -0
  13. package/dest/mem_pools/tx_pool_v2/index.d.ts +2 -2
  14. package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
  15. package/dest/mem_pools/tx_pool_v2/index.js +1 -1
  16. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +5 -5
  17. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
  18. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +26 -4
  19. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
  20. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +48 -7
  21. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +1 -1
  22. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
  23. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +9 -10
  24. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +2 -2
  25. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
  26. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +2 -2
  27. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
  28. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +37 -28
  29. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +2 -2
  30. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  31. package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +3 -3
  32. package/dest/msg_validators/tx_validator/factory.d.ts +114 -6
  33. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  34. package/dest/msg_validators/tx_validator/factory.js +219 -58
  35. package/dest/msg_validators/tx_validator/gas_validator.d.ts +58 -3
  36. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  37. package/dest/msg_validators/tx_validator/gas_validator.js +72 -35
  38. package/dest/msg_validators/tx_validator/index.d.ts +2 -1
  39. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  40. package/dest/msg_validators/tx_validator/index.js +1 -0
  41. package/dest/msg_validators/tx_validator/nullifier_cache.d.ts +14 -0
  42. package/dest/msg_validators/tx_validator/nullifier_cache.d.ts.map +1 -0
  43. package/dest/msg_validators/tx_validator/nullifier_cache.js +24 -0
  44. package/dest/services/dummy_service.d.ts +4 -4
  45. package/dest/services/dummy_service.d.ts.map +1 -1
  46. package/dest/services/dummy_service.js +4 -4
  47. package/dest/services/encoding.d.ts +2 -2
  48. package/dest/services/encoding.d.ts.map +1 -1
  49. package/dest/services/encoding.js +7 -7
  50. package/dest/services/libp2p/libp2p_service.d.ts +11 -7
  51. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  52. package/dest/services/libp2p/libp2p_service.js +60 -70
  53. package/dest/services/reqresp/batch-tx-requester/tx_validator.js +2 -2
  54. package/dest/services/service.d.ts +5 -3
  55. package/dest/services/service.d.ts.map +1 -1
  56. package/dest/services/tx_provider.d.ts +3 -3
  57. package/dest/services/tx_provider.d.ts.map +1 -1
  58. package/dest/services/tx_provider.js +4 -4
  59. package/dest/test-helpers/mock-pubsub.d.ts +3 -2
  60. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  61. package/dest/test-helpers/mock-pubsub.js +6 -0
  62. package/dest/test-helpers/testbench-utils.d.ts +2 -2
  63. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  64. package/dest/util.d.ts +2 -2
  65. package/dest/util.d.ts.map +1 -1
  66. package/package.json +14 -14
  67. package/src/client/factory.ts +13 -33
  68. package/src/client/interface.ts +12 -11
  69. package/src/client/p2p_client.ts +7 -76
  70. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +1 -1
  71. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +3 -0
  72. package/src/mem_pools/tx_pool_v2/index.ts +1 -1
  73. package/src/mem_pools/tx_pool_v2/interfaces.ts +4 -4
  74. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +65 -10
  75. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +11 -11
  76. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +1 -1
  77. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +42 -28
  78. package/src/msg_validators/tx_validator/README.md +115 -0
  79. package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +3 -3
  80. package/src/msg_validators/tx_validator/factory.ts +353 -77
  81. package/src/msg_validators/tx_validator/gas_validator.ts +84 -29
  82. package/src/msg_validators/tx_validator/index.ts +1 -0
  83. package/src/msg_validators/tx_validator/nullifier_cache.ts +30 -0
  84. package/src/services/dummy_service.ts +6 -6
  85. package/src/services/encoding.ts +5 -6
  86. package/src/services/libp2p/libp2p_service.ts +74 -79
  87. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +2 -2
  88. package/src/services/service.ts +11 -2
  89. package/src/services/tx_provider.ts +2 -2
  90. package/src/test-helpers/mock-pubsub.ts +10 -0
  91. package/src/test-helpers/testbench-utils.ts +1 -1
  92. package/src/util.ts +7 -1
@@ -1,6 +1,6 @@
1
1
  import type { EthAddress } from '@aztec/foundation/eth-address';
2
2
  import type { PeerInfo } from '@aztec/stdlib/interfaces/server';
3
- import type { Gossipable, PeerErrorSeverity } from '@aztec/stdlib/p2p';
3
+ import type { Gossipable, PeerErrorSeverity, TopicType } from '@aztec/stdlib/p2p';
4
4
  import { Tx, TxHash } from '@aztec/stdlib/tx';
5
5
 
6
6
  import type { PeerId } from '@libp2p/interface';
@@ -44,6 +44,10 @@ export class DummyP2PService implements P2PService {
44
44
  return [];
45
45
  }
46
46
 
47
+ getGossipMeshPeerCount(_topicType: TopicType): number {
48
+ return 0;
49
+ }
50
+
47
51
  /**
48
52
  * Starts the dummy implementation.
49
53
  * @returns A resolved promise.
@@ -137,14 +141,10 @@ export class DummyP2PService implements P2PService {
137
141
  return undefined;
138
142
  }
139
143
 
140
- validate(_txs: Tx[]): Promise<void> {
144
+ validateTxsReceivedInBlockProposal(_txs: Tx[]): Promise<void> {
141
145
  return Promise.resolve();
142
146
  }
143
147
 
144
- validatePropagatedTx(_tx: Tx, _peerId: PeerId): Promise<boolean> {
145
- return Promise.resolve(true);
146
- }
147
-
148
148
  addReqRespSubProtocol(
149
149
  _subProtocol: ReqRespSubProtocol,
150
150
  _handler: ReqRespSubProtocolHandler,
@@ -1,11 +1,11 @@
1
1
  // Taken from lodestar: https://github.com/ChainSafe/lodestar
2
- import { sha256 } from '@aztec/foundation/crypto/sha256';
3
2
  import { createLogger } from '@aztec/foundation/log';
4
3
  import { MAX_TX_SIZE_KB, TopicType, getTopicFromString } from '@aztec/stdlib/p2p';
5
4
 
6
5
  import type { RPC } from '@chainsafe/libp2p-gossipsub/message';
7
6
  import type { DataTransform } from '@chainsafe/libp2p-gossipsub/types';
8
7
  import type { Message } from '@libp2p/interface';
8
+ import { webcrypto } from 'node:crypto';
9
9
  import { compressSync, uncompressSync } from 'snappy';
10
10
  import xxhashFactory from 'xxhash-wasm';
11
11
 
@@ -44,11 +44,10 @@ export function msgIdToStrFn(msgId: Uint8Array): string {
44
44
  * @param message - The libp2p message
45
45
  * @returns The message identifier
46
46
  */
47
- export function getMsgIdFn(message: Message) {
48
- const { topic } = message;
49
-
50
- const vec = [Buffer.from(topic), message.data];
51
- return sha256(Buffer.concat(vec)).subarray(0, 20);
47
+ export async function getMsgIdFn({ topic, data }: Message): Promise<Uint8Array> {
48
+ const buffer = Buffer.concat([Buffer.from(topic), data]);
49
+ const hash = await webcrypto.subtle.digest('SHA-256', buffer);
50
+ return Buffer.from(hash.slice(0, 20));
52
51
  }
53
52
 
54
53
  const DefaultMaxSizesKb: Record<TopicType, number> = {
@@ -69,9 +69,11 @@ import {
69
69
  } from '../../msg_validators/index.js';
70
70
  import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
71
71
  import {
72
- type MessageValidator,
73
- createTxMessageValidators,
74
- createTxReqRespValidator,
72
+ type TransactionValidator,
73
+ createFirstStageTxValidationsForGossipedTransactions,
74
+ createSecondStageTxValidationsForGossipedTransactions,
75
+ createTxValidatorForBlockProposalReceivedTxs,
76
+ createTxValidatorForReqResponseReceivedTxs,
75
77
  } from '../../msg_validators/tx_validator/factory.js';
76
78
  import { GossipSubEvent } from '../../types/index.js';
77
79
  import { type PubSubLibp2p, convertToMultiaddr } from '../../util.js';
@@ -87,6 +89,9 @@ import { PeerScoring } from '../peer-manager/peer_scoring.js';
87
89
  import type { BatchTxRequesterLibP2PService } from '../reqresp/batch-tx-requester/interface.js';
88
90
  import type { P2PReqRespConfig } from '../reqresp/config.js';
89
91
  import {
92
+ AuthRequest,
93
+ BlockTxsRequest,
94
+ BlockTxsResponse,
90
95
  DEFAULT_SUB_PROTOCOL_VALIDATORS,
91
96
  type ReqRespInterface,
92
97
  type ReqRespResponse,
@@ -94,14 +99,9 @@ import {
94
99
  type ReqRespSubProtocolHandler,
95
100
  type ReqRespSubProtocolHandlers,
96
101
  type ReqRespSubProtocolValidators,
102
+ StatusMessage,
97
103
  type SubProtocolMap,
98
104
  ValidationError,
99
- } from '../reqresp/index.js';
100
- import {
101
- AuthRequest,
102
- BlockTxsRequest,
103
- BlockTxsResponse,
104
- StatusMessage,
105
105
  pingHandler,
106
106
  reqGoodbyeHandler,
107
107
  reqRespBlockHandler,
@@ -615,6 +615,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
615
615
  return this.peerManager.getPeers(includePending);
616
616
  }
617
617
 
618
+ public getGossipMeshPeerCount(topicType: TopicType): number {
619
+ return this.node.services.pubsub.getMeshPeers(this.topicStrings[topicType]).length;
620
+ }
621
+
618
622
  private handleGossipSubEvent(e: CustomEvent<GossipsubMessage>) {
619
623
  this.logger.trace(`Received PUBSUB message.`);
620
624
 
@@ -902,15 +906,45 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
902
906
  protected async handleGossipedTx(payloadData: Buffer, msgId: string, source: PeerId) {
903
907
  const validationFunc: () => Promise<ReceivedMessageValidationResult<Tx>> = async () => {
904
908
  const tx = Tx.fromBuffer(payloadData);
905
- const isValid = await this.validatePropagatedTx(tx, source);
906
- if (!isValid) {
907
- this.logger.trace(`Rejecting invalid propagated tx`, {
908
- [Attributes.P2P_ID]: source.toString(),
909
- });
909
+
910
+ const currentBlockNumber = await this.archiver.getBlockNumber();
911
+ const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
912
+
913
+ // Stage 1: fast validators (metadata, data, timestamps, double-spend, gas, phases, block header)
914
+ const firstStageValidators = await this.createFirstStageMessageValidators(currentBlockNumber, nextSlotTimestamp);
915
+ const firstStageOutcome = await this.runValidations(tx, firstStageValidators);
916
+ if (!firstStageOutcome.allPassed) {
917
+ const { name } = firstStageOutcome.failure;
918
+ let { severity } = firstStageOutcome.failure;
919
+
920
+ // Double spend validator has a special case handler. We perform more detailed examination
921
+ // as to how recently the nullifier was entered into the tree and if the transaction should
922
+ // have 'known' the nullifier existed. This determines the severity of the penalty applied to the peer.
923
+ if (name === 'doubleSpendValidator') {
924
+ const txBlockNumber = BlockNumber(currentBlockNumber + 1);
925
+ severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
926
+ }
927
+
928
+ this.peerManager.penalizePeer(source, severity);
929
+ return { result: TopicValidatorResult.Reject };
930
+ }
931
+
932
+ // Pool pre-check: see if the pool would accept this tx before doing expensive proof verification
933
+ const canAdd = await this.mempools.txPool.canAddPendingTx(tx);
934
+ if (canAdd === 'ignored') {
935
+ return { result: TopicValidatorResult.Ignore, obj: tx };
936
+ }
937
+
938
+ // Stage 2: expensive proof verification
939
+ const secondStageValidators = this.createSecondStageMessageValidators();
940
+ const secondStageOutcome = await this.runValidations(tx, secondStageValidators);
941
+ if (!secondStageOutcome.allPassed) {
942
+ const { severity } = secondStageOutcome.failure;
943
+ this.peerManager.penalizePeer(source, severity);
910
944
  return { result: TopicValidatorResult.Reject };
911
945
  }
912
946
 
913
- // Propagate only on pool acceptance
947
+ // Pool add: persist the tx
914
948
  const txHash = tx.getTxHash();
915
949
  const addResult = await this.mempools.txPool.addPendingTxs([tx], { source: 'gossip' });
916
950
 
@@ -918,7 +952,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
918
952
  const wasIgnored = addResult.ignored.some(h => h.equals(txHash));
919
953
 
920
954
  this.logger.trace(`Validate propagated tx`, {
921
- isValid,
922
955
  wasAccepted,
923
956
  wasIgnored,
924
957
  [Attributes.P2P_ID]: source.toString(),
@@ -1533,43 +1566,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1533
1566
  }
1534
1567
 
1535
1568
  protected createRequestedTxValidator(): TxValidator {
1536
- return createTxReqRespValidator(this.proofVerifier, {
1569
+ return createTxValidatorForReqResponseReceivedTxs(this.proofVerifier, {
1537
1570
  l1ChainId: this.config.l1ChainId,
1538
1571
  rollupVersion: this.config.rollupVersion,
1539
1572
  });
1540
1573
  }
1541
1574
 
1542
- @trackSpan('Libp2pService.validatePropagatedTx', tx => ({
1543
- [Attributes.TX_HASH]: tx.getTxHash().toString(),
1544
- }))
1545
- protected async validatePropagatedTx(tx: Tx, peerId: PeerId): Promise<boolean> {
1546
- const currentBlockNumber = await this.archiver.getBlockNumber();
1547
-
1548
- // We accept transactions if they are not expired by the next slot (checked based on the ExpirationTimestamp field)
1549
- const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
1550
- const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
1551
-
1552
- for (const validator of messageValidators) {
1553
- const outcome = await this.runValidations(tx, validator);
1554
-
1555
- if (outcome.allPassed) {
1556
- continue;
1557
- }
1558
- const { name } = outcome.failure;
1559
- let { severity } = outcome.failure;
1560
-
1561
- // Double spend validator has a special case handler
1562
- if (name === 'doubleSpendValidator') {
1563
- const txBlockNumber = BlockNumber(currentBlockNumber + 1); // tx is expected to be in the next block
1564
- severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
1565
- }
1566
-
1567
- this.peerManager.penalizePeer(peerId, severity);
1568
- return false;
1569
- }
1570
- return true;
1571
- }
1572
-
1573
1575
  private async getGasFees(blockNumber: BlockNumber): Promise<GasFees> {
1574
1576
  if (blockNumber === this.feesCache?.blockNumber) {
1575
1577
  return this.feesCache.gasFees;
@@ -1597,60 +1599,53 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1597
1599
  };
1598
1600
  }
1599
1601
 
1600
- public async validate(txs: Tx[]): Promise<void> {
1601
- const currentBlockNumber = await this.archiver.getBlockNumber();
1602
-
1603
- // We accept transactions if they are not expired by the next slot (checked based on the ExpirationTimestamp field)
1604
- const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
1605
- const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
1602
+ public async validateTxsReceivedInBlockProposal(txs: Tx[]): Promise<void> {
1603
+ const validator = createTxValidatorForBlockProposalReceivedTxs(
1604
+ this.proofVerifier,
1605
+ { l1ChainId: this.config.l1ChainId, rollupVersion: this.config.rollupVersion },
1606
+ this.logger.getBindings(),
1607
+ );
1606
1608
 
1607
- await Promise.all(
1609
+ const results = await Promise.all(
1608
1610
  txs.map(async tx => {
1609
- for (const validator of messageValidators) {
1610
- const outcome = await this.runValidations(tx, validator);
1611
- if (!outcome.allPassed) {
1612
- throw new Error('Invalid tx detected', { cause: { outcome } });
1613
- }
1614
- }
1611
+ const result = await validator.validateTx(tx);
1612
+ return result.result !== 'invalid';
1615
1613
  }),
1616
1614
  );
1615
+ if (results.some(value => value === false)) {
1616
+ throw new Error('Invalid tx detected');
1617
+ }
1617
1618
  }
1618
1619
 
1619
- /**
1620
- * Create message validators for the given block number and timestamp.
1621
- *
1622
- * Each validator is a pair of a validator and a severity.
1623
- * If a validator fails, the peer is penalized with the severity of the validator.
1624
- *
1625
- * @param currentBlockNumber - The current synced block number.
1626
- * @param nextSlotTimestamp - The timestamp of the next slot (used to validate txs are not expired).
1627
- * @returns The message validators.
1628
- */
1629
- private async createMessageValidators(
1620
+ /** Creates the first stage (fast) validators for gossiped transactions. */
1621
+ protected async createFirstStageMessageValidators(
1630
1622
  currentBlockNumber: BlockNumber,
1631
1623
  nextSlotTimestamp: UInt64,
1632
- ): Promise<Record<string, MessageValidator>[]> {
1624
+ ): Promise<Record<string, TransactionValidator>> {
1633
1625
  const gasFees = await this.getGasFees(currentBlockNumber);
1634
1626
  const allowedInSetup = this.config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions());
1627
+ const blockNumber = BlockNumber(currentBlockNumber + 1);
1635
1628
 
1636
- const blockNumberInWhichTheTxIsConsideredToBeIncluded = BlockNumber(currentBlockNumber + 1);
1637
-
1638
- return createTxMessageValidators(
1629
+ return createFirstStageTxValidationsForGossipedTransactions(
1639
1630
  nextSlotTimestamp,
1640
- blockNumberInWhichTheTxIsConsideredToBeIncluded,
1631
+ blockNumber,
1641
1632
  this.worldStateSynchronizer,
1642
1633
  gasFees,
1643
1634
  this.config.l1ChainId,
1644
1635
  this.config.rollupVersion,
1645
1636
  protocolContractsHash,
1646
1637
  this.archiver,
1647
- this.proofVerifier,
1648
1638
  !this.config.disableTransactions,
1649
1639
  allowedInSetup,
1650
1640
  this.logger.getBindings(),
1651
1641
  );
1652
1642
  }
1653
1643
 
1644
+ /** Creates the second stage (expensive proof verification) validators for gossiped transactions. */
1645
+ protected createSecondStageMessageValidators(): Record<string, TransactionValidator> {
1646
+ return createSecondStageTxValidationsForGossipedTransactions(this.proofVerifier, this.logger.getBindings());
1647
+ }
1648
+
1654
1649
  /**
1655
1650
  * Run validations on a tx.
1656
1651
  * @param tx - The tx to validate.
@@ -1659,7 +1654,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1659
1654
  */
1660
1655
  private async runValidations(
1661
1656
  tx: Tx,
1662
- messageValidators: Record<string, MessageValidator>,
1657
+ messageValidators: Record<string, TransactionValidator>,
1663
1658
  ): Promise<ValidationOutcome> {
1664
1659
  const validationPromises = Object.entries(messageValidators).map(async ([name, { validator, severity }]) => {
1665
1660
  const { result } = await validator.validateTx(tx);
@@ -1,7 +1,7 @@
1
1
  import type { ClientProtocolCircuitVerifier } from '@aztec/stdlib/interfaces/server';
2
2
  import { Tx, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
3
3
 
4
- import { createTxReqRespValidator } from '../../../msg_validators/tx_validator/factory.js';
4
+ import { createTxValidatorForReqResponseReceivedTxs } from '../../../msg_validators/index.js';
5
5
 
6
6
  export interface BatchRequestTxValidatorConfig {
7
7
  l1ChainId: number;
@@ -29,7 +29,7 @@ export class BatchRequestTxValidator implements IBatchRequestTxValidator {
29
29
  }
30
30
 
31
31
  static createRequestedTxValidator(config: BatchRequestTxValidatorConfig): TxValidator {
32
- return createTxReqRespValidator(config.proofVerifier, {
32
+ return createTxValidatorForReqResponseReceivedTxs(config.proofVerifier, {
33
33
  l1ChainId: config.l1ChainId,
34
34
  rollupVersion: config.rollupVersion,
35
35
  });
@@ -1,7 +1,13 @@
1
1
  import type { SlotNumber } from '@aztec/foundation/branded-types';
2
2
  import type { EthAddress } from '@aztec/foundation/eth-address';
3
3
  import type { PeerInfo } from '@aztec/stdlib/interfaces/server';
4
- import type { BlockProposal, CheckpointAttestation, CheckpointProposalCore, Gossipable } from '@aztec/stdlib/p2p';
4
+ import type {
5
+ BlockProposal,
6
+ CheckpointAttestation,
7
+ CheckpointProposalCore,
8
+ Gossipable,
9
+ TopicType,
10
+ } from '@aztec/stdlib/p2p';
5
11
  import type { Tx } from '@aztec/stdlib/tx';
6
12
 
7
13
  import type { PeerId } from '@libp2p/interface';
@@ -130,7 +136,10 @@ export interface P2PService {
130
136
 
131
137
  getPeers(includePending?: boolean): PeerInfo[];
132
138
 
133
- validate(txs: Tx[]): Promise<void>;
139
+ /** Returns the number of peers in the GossipSub mesh for a given topic type. */
140
+ getGossipMeshPeerCount(topicType: TopicType): number;
141
+
142
+ validateTxsReceivedInBlockProposal(txs: Tx[]): Promise<void>;
134
143
 
135
144
  addReqRespSubProtocol(
136
145
  subProtocol: ReqRespSubProtocol,
@@ -25,7 +25,7 @@ export class TxProvider implements ITxProvider {
25
25
  constructor(
26
26
  private txCollection: TxCollection,
27
27
  private txPool: TxPoolV2,
28
- private txValidator: Pick<P2PClient, 'validate'>,
28
+ private blockProposalTransactionValidator: Pick<P2PClient, 'validateTxsReceivedInBlockProposal'>,
29
29
  private log: Logger = createLogger('p2p:tx-collector'),
30
30
  client: TelemetryClient = getTelemetryClient(),
31
31
  ) {
@@ -227,7 +227,7 @@ export class TxProvider implements ITxProvider {
227
227
  if (txs.length === 0) {
228
228
  return;
229
229
  }
230
- await this.txValidator.validate(txs);
230
+ await this.blockProposalTransactionValidator.validateTxsReceivedInBlockProposal(txs);
231
231
  await this.txPool.addProtectedTxs(txs, blockHeader);
232
232
  }
233
233
  }
@@ -270,6 +270,16 @@ class MockGossipSubService extends TypedEventEmitter<GossipsubEvents> implements
270
270
  { msgId, propagationSource, acceptance },
271
271
  );
272
272
  }
273
+
274
+ getMeshPeers(topic?: TopicStr): PeerIdStr[] {
275
+ if (topic && !this.subscribedTopics.has(topic)) {
276
+ return [];
277
+ }
278
+ return this.network
279
+ .getPeers()
280
+ .filter(peer => !this.peerId.equals(peer))
281
+ .map(peer => peer.toString());
282
+ }
273
283
  }
274
284
 
275
285
  /**
@@ -76,7 +76,7 @@ export class InMemoryTxPool extends EventEmitter implements TxPoolV2 {
76
76
  return Promise.resolve({ accepted, ignored: [], rejected: [] });
77
77
  }
78
78
 
79
- canAddPendingTx(tx: Tx): Promise<'accepted' | 'ignored' | 'rejected'> {
79
+ canAddPendingTx(tx: Tx): Promise<'accepted' | 'ignored'> {
80
80
  const key = tx.getTxHash().toString();
81
81
  if (this.txsByHash.has(key)) {
82
82
  return Promise.resolve('ignored');
package/src/util.ts CHANGED
@@ -23,7 +23,13 @@ export interface PubSubLibp2p extends Pick<Libp2p, 'status' | 'start' | 'stop' |
23
23
  services: {
24
24
  pubsub: Pick<
25
25
  GossipSub,
26
- 'addEventListener' | 'removeEventListener' | 'publish' | 'subscribe' | 'reportMessageValidationResult' | 'direct'
26
+ | 'addEventListener'
27
+ | 'removeEventListener'
28
+ | 'publish'
29
+ | 'subscribe'
30
+ | 'reportMessageValidationResult'
31
+ | 'direct'
32
+ | 'getMeshPeers'
27
33
  > & { score: Pick<GossipSub['score'], 'score'> };
28
34
  };
29
35
  }