@aztec/p2p 3.0.0-nightly.20251026 → 3.0.0-nightly.20251031

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 (40) hide show
  1. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +15 -0
  2. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  3. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  4. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +32 -0
  5. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +2 -0
  6. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
  7. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +16 -0
  8. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +2 -0
  9. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
  10. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +22 -0
  11. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +1 -0
  12. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
  13. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +8 -2
  14. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +1 -0
  15. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -1
  16. package/dest/mem_pools/tx_pool/memory_tx_pool.js +6 -0
  17. package/dest/mem_pools/tx_pool/tx_pool.d.ts +6 -0
  18. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
  19. package/dest/services/encoding.d.ts +24 -3
  20. package/dest/services/encoding.d.ts.map +1 -1
  21. package/dest/services/encoding.js +73 -5
  22. package/dest/services/libp2p/libp2p_service.d.ts +15 -8
  23. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  24. package/dest/services/libp2p/libp2p_service.js +78 -26
  25. package/dest/services/reqresp/reqresp.js +2 -2
  26. package/dest/testbench/p2p_client_testbench_worker.js +4 -1
  27. package/dest/testbench/testbench.js +2 -2
  28. package/package.json +14 -14
  29. package/src/mem_pools/attestation_pool/attestation_pool.ts +17 -0
  30. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +37 -0
  31. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +21 -0
  32. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +28 -0
  33. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +7 -2
  34. package/src/mem_pools/tx_pool/memory_tx_pool.ts +5 -0
  35. package/src/mem_pools/tx_pool/tx_pool.ts +7 -0
  36. package/src/services/encoding.ts +80 -5
  37. package/src/services/libp2p/libp2p_service.ts +75 -24
  38. package/src/services/reqresp/reqresp.ts +2 -2
  39. package/src/testbench/p2p_client_testbench_worker.ts +3 -0
  40. package/src/testbench/testbench.ts +2 -2
@@ -107,6 +107,11 @@ interface ValidationResult {
107
107
 
108
108
  type ValidationOutcome = { allPassed: true } | { allPassed: false; failure: ValidationResult };
109
109
 
110
+ // REFACTOR: Unify with the type above
111
+ type ReceivedMessageValidationResult<T> =
112
+ | { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject> }
113
+ | { obj?: undefined; result: TopicValidatorResult.Reject };
114
+
110
115
  /**
111
116
  * Lib P2P implementation of the P2PService interface.
112
117
  */
@@ -615,6 +620,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
615
620
  return result.recipients.length;
616
621
  }
617
622
 
623
+ /**
624
+ * Checks if this message has already been seen, based on its msgId computed from hashing the message data.
625
+ * Note that we do not rely on the seenCache from gossipsub since we want to keep a longer history of seen
626
+ * messages to avoid tx echoes across the network.
627
+ */
618
628
  protected preValidateReceivedMessage(
619
629
  msg: Message,
620
630
  msgId: string,
@@ -678,42 +688,57 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
678
688
  }
679
689
 
680
690
  protected async validateReceivedMessage<T>(
681
- validationFunc: () => Promise<{ result: boolean; obj: T }>,
691
+ validationFunc: () => Promise<ReceivedMessageValidationResult<T>>,
682
692
  msgId: string,
683
693
  source: PeerId,
684
694
  topicType: TopicType,
685
- ): Promise<{ result: boolean; obj: T | undefined }> {
686
- let resultAndObj: { result: boolean; obj: T | undefined } = { result: false, obj: undefined };
695
+ ): Promise<ReceivedMessageValidationResult<T>> {
696
+ let resultAndObj: ReceivedMessageValidationResult<T> = { result: TopicValidatorResult.Reject };
687
697
  const timer = new Timer();
688
698
  try {
689
699
  resultAndObj = await validationFunc();
690
700
  } catch (err) {
691
- this.logger.error(`Error deserializing and validating message `, err);
701
+ this.logger.error(`Error deserializing and validating gossipsub message`, err, {
702
+ msgId,
703
+ source: source.toString(),
704
+ topicType,
705
+ });
692
706
  }
693
707
 
694
- if (resultAndObj.result) {
708
+ if (resultAndObj.result === TopicValidatorResult.Accept) {
695
709
  this.instrumentation.recordMessageValidation(topicType, timer);
696
710
  }
697
711
 
698
- this.node.services.pubsub.reportMessageValidationResult(
699
- msgId,
700
- source.toString(),
701
- resultAndObj.result && resultAndObj.obj ? TopicValidatorResult.Accept : TopicValidatorResult.Reject,
702
- );
712
+ this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result);
703
713
  return resultAndObj;
704
714
  }
705
715
 
706
716
  protected async handleGossipedTx(payloadData: Buffer, msgId: string, source: PeerId) {
707
- const validationFunc = async () => {
717
+ const validationFunc: () => Promise<ReceivedMessageValidationResult<Tx>> = async () => {
708
718
  const tx = Tx.fromBuffer(payloadData);
709
- const result = await this.validatePropagatedTx(tx, source);
710
- return { result, obj: tx };
719
+ const isValid = await this.validatePropagatedTx(tx, source);
720
+ const exists = isValid && (await this.mempools.txPool.hasTx(tx.getTxHash()));
721
+
722
+ this.logger.trace(`Validate propagated tx`, {
723
+ isValid,
724
+ exists,
725
+ [Attributes.P2P_ID]: source.toString(),
726
+ });
727
+
728
+ if (!isValid) {
729
+ return { result: TopicValidatorResult.Reject };
730
+ } else if (exists) {
731
+ return { result: TopicValidatorResult.Ignore, obj: tx };
732
+ } else {
733
+ return { result: TopicValidatorResult.Accept, obj: tx };
734
+ }
711
735
  };
712
736
 
713
737
  const { result, obj: tx } = await this.validateReceivedMessage<Tx>(validationFunc, msgId, source, TopicType.tx);
714
- if (!result || !tx) {
738
+ if (result !== TopicValidatorResult.Accept || !tx) {
715
739
  return;
716
740
  }
741
+
717
742
  const txHash = tx.getTxHash();
718
743
  const txHashString = txHash.toString();
719
744
  this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()} via gossip`, {
@@ -722,7 +747,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
722
747
  });
723
748
 
724
749
  if (this.config.dropTransactions && randomInt(1000) < this.config.dropTransactionsProbability * 1000) {
725
- this.logger.debug(`Intentionally dropping tx ${txHashString} (probability rule)`);
750
+ this.logger.warn(`Intentionally dropping tx ${txHashString} (probability rule)`);
726
751
  return;
727
752
  }
728
753
 
@@ -736,14 +761,25 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
736
761
  * @param attestation - The attestation to process.
737
762
  */
738
763
  private async processAttestationFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
739
- const validationFunc = async () => {
764
+ const validationFunc: () => Promise<ReceivedMessageValidationResult<BlockAttestation>> = async () => {
740
765
  const attestation = BlockAttestation.fromBuffer(payloadData);
741
- const result = await this.validateAttestation(source, attestation);
742
- this.logger.trace(`validatePropagatedAttestation: ${result}`, {
766
+ const isValid = await this.validateAttestation(source, attestation);
767
+ const exists = isValid && (await this.mempools.attestationPool!.hasAttestation(attestation));
768
+
769
+ this.logger.trace(`Validate propagated block attestation`, {
770
+ isValid,
771
+ exists,
743
772
  [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
744
773
  [Attributes.P2P_ID]: source.toString(),
745
774
  });
746
- return { result, obj: attestation };
775
+
776
+ if (!isValid) {
777
+ return { result: TopicValidatorResult.Reject };
778
+ } else if (exists) {
779
+ return { result: TopicValidatorResult.Ignore, obj: attestation };
780
+ } else {
781
+ return { result: TopicValidatorResult.Accept, obj: attestation };
782
+ }
747
783
  };
748
784
 
749
785
  const { result, obj: attestation } = await this.validateReceivedMessage<BlockAttestation>(
@@ -752,9 +788,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
752
788
  source,
753
789
  TopicType.block_attestation,
754
790
  );
755
- if (!result || !attestation) {
791
+
792
+ if (result !== TopicValidatorResult.Accept || !attestation) {
756
793
  return;
757
794
  }
795
+
758
796
  this.logger.debug(
759
797
  `Received attestation for slot ${attestation.slotNumber.toNumber()} from external peer ${source.toString()}`,
760
798
  {
@@ -764,18 +802,30 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
764
802
  source: source.toString(),
765
803
  },
766
804
  );
805
+
767
806
  await this.mempools.attestationPool!.addAttestations([attestation]);
768
807
  }
769
808
 
770
809
  private async processBlockFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
771
- const validationFunc = async () => {
810
+ const validationFunc: () => Promise<ReceivedMessageValidationResult<BlockProposal>> = async () => {
772
811
  const block = BlockProposal.fromBuffer(payloadData);
773
- const result = await this.validateBlockProposal(source, block);
774
- this.logger.trace(`validatePropagatedBlock: ${result}`, {
812
+ const isValid = await this.validateBlockProposal(source, block);
813
+ const exists = isValid && (await this.mempools.attestationPool!.hasBlockProposal(block));
814
+
815
+ this.logger.trace(`Validate propagated block proposal`, {
816
+ isValid,
817
+ exists,
775
818
  [Attributes.SLOT_NUMBER]: block.payload.header.slotNumber.toString(),
776
819
  [Attributes.P2P_ID]: source.toString(),
777
820
  });
778
- return { result, obj: block };
821
+
822
+ if (!isValid) {
823
+ return { result: TopicValidatorResult.Reject };
824
+ } else if (exists) {
825
+ return { result: TopicValidatorResult.Ignore, obj: block };
826
+ } else {
827
+ return { result: TopicValidatorResult.Accept, obj: block };
828
+ }
779
829
  };
780
830
 
781
831
  const { result, obj: block } = await this.validateReceivedMessage<BlockProposal>(
@@ -784,6 +834,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
784
834
  source,
785
835
  TopicType.block_proposal,
786
836
  );
837
+
787
838
  if (!result || !block) {
788
839
  return;
789
840
  }
@@ -489,7 +489,7 @@ export class ReqResp implements ReqRespInterface {
489
489
  }
490
490
 
491
491
  const messageData = Buffer.concat(chunks);
492
- const message: Buffer = this.snappyTransform.inboundTransformNoTopic(messageData);
492
+ const message: Buffer = this.snappyTransform.inboundTransformData(messageData);
493
493
 
494
494
  return {
495
495
  status: status ?? ReqRespStatus.UNKNOWN,
@@ -618,7 +618,7 @@ export class ReqResp implements ReqRespInterface {
618
618
  stream.metadata.written = true; // Mark the stream as written to;
619
619
 
620
620
  yield SUCCESS;
621
- yield snappy.outboundTransformNoTopic(response);
621
+ yield snappy.outboundTransformData(response);
622
622
  }
623
623
  },
624
624
  stream.sink,
@@ -52,6 +52,7 @@ function mockTxPool(): TxPool {
52
52
  getTxStatus: () => Promise.resolve(TxStatus.PENDING),
53
53
  getTxsByHash: () => Promise.resolve([]),
54
54
  hasTxs: () => Promise.resolve([]),
55
+ hasTx: () => Promise.resolve(false),
55
56
  updateConfig: () => {},
56
57
  markTxsAsNonEvictable: () => Promise.resolve(),
57
58
  cleanupDeletedMinedTxs: () => Promise.resolve(0),
@@ -71,6 +72,8 @@ function mockAttestationPool(): AttestationPool {
71
72
  getAttestationsForSlotAndProposal: () => Promise.resolve([]),
72
73
  addBlockProposal: () => Promise.resolve(),
73
74
  getBlockProposal: () => Promise.resolve(undefined),
75
+ hasBlockProposal: () => Promise.resolve(false),
76
+ hasAttestation: () => Promise.resolve(false),
74
77
  };
75
78
  }
76
79
 
@@ -1,6 +1,6 @@
1
1
  import { createLogger } from '@aztec/foundation/log';
2
2
  import { sleep } from '@aztec/foundation/sleep';
3
- import { ClientIvcProof } from '@aztec/stdlib/proofs';
3
+ import { ChonkProof } from '@aztec/stdlib/proofs';
4
4
  import { mockTx } from '@aztec/stdlib/testing';
5
5
 
6
6
  import assert from 'assert';
@@ -35,7 +35,7 @@ async function main() {
35
35
 
36
36
  // Send tx from client 0
37
37
  const tx = await mockTx(1, {
38
- clientIvcProof: ClientIvcProof.random(),
38
+ chonkProof: ChonkProof.random(),
39
39
  });
40
40
 
41
41
  workerClientManager.processes[0].send({ type: 'SEND_TX', tx: tx.toBuffer() });