@aztec/p2p 0.55.1 → 0.57.0

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 (80) hide show
  1. package/dest/attestation_pool/attestation_pool.d.ts +2 -1
  2. package/dest/attestation_pool/attestation_pool.d.ts.map +1 -1
  3. package/dest/attestation_pool/memory_attestation_pool.d.ts +2 -1
  4. package/dest/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
  5. package/dest/attestation_pool/memory_attestation_pool.js +48 -15
  6. package/dest/attestation_pool/mocks.d.ts +2 -1
  7. package/dest/attestation_pool/mocks.d.ts.map +1 -1
  8. package/dest/attestation_pool/mocks.js +7 -7
  9. package/dest/client/index.d.ts +4 -1
  10. package/dest/client/index.d.ts.map +1 -1
  11. package/dest/client/index.js +7 -3
  12. package/dest/client/p2p_client.d.ts +25 -6
  13. package/dest/client/p2p_client.d.ts.map +1 -1
  14. package/dest/client/p2p_client.js +28 -15
  15. package/dest/epoch_proof_quote_pool/epoch_proof_quote_pool.d.ts +7 -0
  16. package/dest/epoch_proof_quote_pool/epoch_proof_quote_pool.d.ts.map +1 -0
  17. package/dest/epoch_proof_quote_pool/epoch_proof_quote_pool.js +2 -0
  18. package/dest/epoch_proof_quote_pool/index.d.ts +4 -0
  19. package/dest/epoch_proof_quote_pool/index.d.ts.map +1 -0
  20. package/dest/epoch_proof_quote_pool/index.js +4 -0
  21. package/dest/epoch_proof_quote_pool/memory_epoch_proof_quote_pool.d.ts +10 -0
  22. package/dest/epoch_proof_quote_pool/memory_epoch_proof_quote_pool.d.ts.map +1 -0
  23. package/dest/epoch_proof_quote_pool/memory_epoch_proof_quote_pool.js +22 -0
  24. package/dest/epoch_proof_quote_pool/test_utils.d.ts +8 -0
  25. package/dest/epoch_proof_quote_pool/test_utils.d.ts.map +1 -0
  26. package/dest/epoch_proof_quote_pool/test_utils.js +21 -0
  27. package/dest/index.d.ts +4 -3
  28. package/dest/index.d.ts.map +1 -1
  29. package/dest/index.js +5 -4
  30. package/dest/mocks/index.d.ts +13 -4
  31. package/dest/mocks/index.d.ts.map +1 -1
  32. package/dest/mocks/index.js +26 -9
  33. package/dest/service/libp2p_service.d.ts +16 -1
  34. package/dest/service/libp2p_service.d.ts.map +1 -1
  35. package/dest/service/libp2p_service.js +55 -25
  36. package/dest/service/reqresp/interface.d.ts +7 -0
  37. package/dest/service/reqresp/interface.d.ts.map +1 -1
  38. package/dest/service/reqresp/interface.js +7 -1
  39. package/dest/service/reqresp/rate_limiter/rate_limiter.d.ts +13 -3
  40. package/dest/service/reqresp/rate_limiter/rate_limiter.d.ts.map +1 -1
  41. package/dest/service/reqresp/rate_limiter/rate_limiter.js +29 -7
  42. package/dest/service/reqresp/reqresp.d.ts +56 -6
  43. package/dest/service/reqresp/reqresp.d.ts.map +1 -1
  44. package/dest/service/reqresp/reqresp.js +79 -12
  45. package/dest/tx_validator/aggregate_tx_validator.d.ts +1 -0
  46. package/dest/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  47. package/dest/tx_validator/aggregate_tx_validator.js +10 -1
  48. package/dest/tx_validator/data_validator.d.ts +1 -0
  49. package/dest/tx_validator/data_validator.d.ts.map +1 -1
  50. package/dest/tx_validator/data_validator.js +4 -1
  51. package/dest/tx_validator/double_spend_validator.d.ts +1 -0
  52. package/dest/tx_validator/double_spend_validator.d.ts.map +1 -1
  53. package/dest/tx_validator/double_spend_validator.js +4 -1
  54. package/dest/tx_validator/metadata_validator.d.ts +1 -0
  55. package/dest/tx_validator/metadata_validator.d.ts.map +1 -1
  56. package/dest/tx_validator/metadata_validator.js +4 -1
  57. package/package.json +10 -6
  58. package/src/attestation_pool/attestation_pool.ts +2 -1
  59. package/src/attestation_pool/memory_attestation_pool.ts +56 -17
  60. package/src/attestation_pool/mocks.ts +11 -6
  61. package/src/client/index.ts +20 -3
  62. package/src/client/p2p_client.ts +46 -15
  63. package/src/epoch_proof_quote_pool/epoch_proof_quote_pool.ts +7 -0
  64. package/src/epoch_proof_quote_pool/index.ts +3 -0
  65. package/src/epoch_proof_quote_pool/memory_epoch_proof_quote_pool.ts +26 -0
  66. package/src/epoch_proof_quote_pool/test_utils.ts +26 -0
  67. package/src/index.ts +4 -3
  68. package/src/mocks/index.ts +35 -7
  69. package/src/service/libp2p_service.ts +59 -26
  70. package/src/service/reqresp/interface.ts +20 -0
  71. package/src/service/reqresp/rate_limiter/rate_limiter.ts +30 -7
  72. package/src/service/reqresp/reqresp.ts +91 -13
  73. package/src/tx_validator/aggregate_tx_validator.ts +10 -0
  74. package/src/tx_validator/data_validator.ts +4 -0
  75. package/src/tx_validator/double_spend_validator.ts +4 -0
  76. package/src/tx_validator/metadata_validator.ts +4 -0
  77. package/dest/client/mocks.d.ts +0 -65
  78. package/dest/client/mocks.d.ts.map +0 -1
  79. package/dest/client/mocks.js +0 -106
  80. package/src/client/mocks.ts +0 -129
@@ -25,6 +25,9 @@ export class MetadataTxValidator {
25
25
  }
26
26
  return Promise.resolve([validTxs, invalidTxs]);
27
27
  }
28
+ validateTx(tx) {
29
+ return Promise.resolve(__classPrivateFieldGet(this, _MetadataTxValidator_instances, "m", _MetadataTxValidator_hasCorrectChainId).call(this, tx) && __classPrivateFieldGet(this, _MetadataTxValidator_instances, "m", _MetadataTxValidator_isValidForBlockNumber).call(this, tx));
30
+ }
28
31
  }
29
32
  _MetadataTxValidator_log = new WeakMap(), _MetadataTxValidator_instances = new WeakSet(), _MetadataTxValidator_hasCorrectChainId = function _MetadataTxValidator_hasCorrectChainId(tx) {
30
33
  if (!tx.data.constants.txContext.chainId.equals(this.chainId)) {
@@ -47,4 +50,4 @@ _MetadataTxValidator_log = new WeakMap(), _MetadataTxValidator_instances = new W
47
50
  return true;
48
51
  }
49
52
  };
50
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0YWRhdGFfdmFsaWRhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3R4X3ZhbGlkYXRvci9tZXRhZGF0YV92YWxpZGF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxPQUFPLEVBQWMsRUFBRSxFQUFvQixNQUFNLHNCQUFzQixDQUFDO0FBRXhFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRTFELE1BQU0sT0FBTyxtQkFBbUI7SUFHOUIsWUFBb0IsT0FBVyxFQUFVLFdBQWU7O1FBQXBDLFlBQU8sR0FBUCxPQUFPLENBQUk7UUFBVSxnQkFBVyxHQUFYLFdBQVcsQ0FBSTtRQUZ4RCxtQ0FBTyxpQkFBaUIsQ0FBQywwQ0FBMEMsQ0FBQyxFQUFDO0lBRVYsQ0FBQztJQUU1RCxXQUFXLENBQUMsR0FBUTtRQUNsQixNQUFNLFFBQVEsR0FBUSxFQUFFLENBQUM7UUFDekIsTUFBTSxVQUFVLEdBQVEsRUFBRSxDQUFDO1FBQzNCLEtBQUssTUFBTSxFQUFFLElBQUksR0FBRyxFQUFFLENBQUM7WUFDckIsSUFBSSxDQUFDLHVCQUFBLElBQUksOEVBQW1CLE1BQXZCLElBQUksRUFBb0IsRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDakMsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDcEIsU0FBUztZQUNYLENBQUM7WUFFRCxJQUFJLENBQUMsdUJBQUEsSUFBSSxrRkFBdUIsTUFBM0IsSUFBSSxFQUF3QixFQUFFLENBQUMsRUFBRSxDQUFDO2dCQUNyQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNwQixTQUFTO1lBQ1gsQ0FBQztZQUVELFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDcEIsQ0FBQztRQUVELE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLFFBQVEsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQ2pELENBQUM7Q0FpQ0Y7bUxBL0JvQixFQUFLO0lBQ3RCLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUM5RCx1QkFBQSxJQUFJLGdDQUFLLENBQUMsSUFBSSxDQUNaLGdCQUFnQixFQUFFLENBQUMsT0FBTyxDQUN4QixFQUFFLENBQ0gsK0JBQStCLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUMvRyxDQUFDO1FBQ0YsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO1NBQU0sQ0FBQztRQUNOLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztBQUNILENBQUMsbUdBRXNCLEVBQUs7SUFDMUIsTUFBTSxNQUFNLEdBQ1YsRUFBRSxZQUFZLEVBQUU7UUFDZCxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsd0JBQXdCLElBQUksRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFVLENBQUMsa0JBQWtCLENBQUMsU0FBUztRQUNoRyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyx3QkFBd0IsQ0FBQztJQUN2QyxNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUMsY0FBYyxDQUFDO0lBRTdDLElBQUksY0FBYyxDQUFDLE1BQU0sSUFBSSxjQUFjLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNyRSx1QkFBQSxJQUFJLGdDQUFLLENBQUMsSUFBSSxDQUNaLGdCQUFnQixFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxtREFDNUIsY0FBYyxDQUFDLEtBQ2pCLDJCQUEyQixJQUFJLENBQUMsV0FBVyxHQUFHLENBQy9DLENBQUM7UUFDRixPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7U0FBTSxDQUFDO1FBQ04sT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0FBQ0gsQ0FBQyJ9
53
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0YWRhdGFfdmFsaWRhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3R4X3ZhbGlkYXRvci9tZXRhZGF0YV92YWxpZGF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxPQUFPLEVBQWMsRUFBRSxFQUFvQixNQUFNLHNCQUFzQixDQUFDO0FBRXhFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRTFELE1BQU0sT0FBTyxtQkFBbUI7SUFHOUIsWUFBb0IsT0FBVyxFQUFVLFdBQWU7O1FBQXBDLFlBQU8sR0FBUCxPQUFPLENBQUk7UUFBVSxnQkFBVyxHQUFYLFdBQVcsQ0FBSTtRQUZ4RCxtQ0FBTyxpQkFBaUIsQ0FBQywwQ0FBMEMsQ0FBQyxFQUFDO0lBRVYsQ0FBQztJQUU1RCxXQUFXLENBQUMsR0FBUTtRQUNsQixNQUFNLFFBQVEsR0FBUSxFQUFFLENBQUM7UUFDekIsTUFBTSxVQUFVLEdBQVEsRUFBRSxDQUFDO1FBQzNCLEtBQUssTUFBTSxFQUFFLElBQUksR0FBRyxFQUFFLENBQUM7WUFDckIsSUFBSSxDQUFDLHVCQUFBLElBQUksOEVBQW1CLE1BQXZCLElBQUksRUFBb0IsRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDakMsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDcEIsU0FBUztZQUNYLENBQUM7WUFFRCxJQUFJLENBQUMsdUJBQUEsSUFBSSxrRkFBdUIsTUFBM0IsSUFBSSxFQUF3QixFQUFFLENBQUMsRUFBRSxDQUFDO2dCQUNyQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNwQixTQUFTO1lBQ1gsQ0FBQztZQUVELFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDcEIsQ0FBQztRQUVELE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLFFBQVEsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFFRCxVQUFVLENBQUMsRUFBSztRQUNkLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyx1QkFBQSxJQUFJLDhFQUFtQixNQUF2QixJQUFJLEVBQW9CLEVBQUUsQ0FBQyxJQUFJLHVCQUFBLElBQUksa0ZBQXVCLE1BQTNCLElBQUksRUFBd0IsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN6RixDQUFDO0NBaUNGO21MQS9Cb0IsRUFBSztJQUN0QixJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDOUQsdUJBQUEsSUFBSSxnQ0FBSyxDQUFDLElBQUksQ0FDWixnQkFBZ0IsRUFBRSxDQUFDLE9BQU8sQ0FDeEIsRUFBRSxDQUNILCtCQUErQixFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FDL0csQ0FBQztRQUNGLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztTQUFNLENBQUM7UUFDTixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7QUFDSCxDQUFDLG1HQUVzQixFQUFLO0lBQzFCLE1BQU0sTUFBTSxHQUNWLEVBQUUsWUFBWSxFQUFFO1FBQ2QsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLHdCQUF3QixJQUFJLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBVSxDQUFDLGtCQUFrQixDQUFDLFNBQVM7UUFDaEcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsd0JBQXdCLENBQUM7SUFDdkMsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQztJQUU3QyxJQUFJLGNBQWMsQ0FBQyxNQUFNLElBQUksY0FBYyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDckUsdUJBQUEsSUFBSSxnQ0FBSyxDQUFDLElBQUksQ0FDWixnQkFBZ0IsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsbURBQzVCLGNBQWMsQ0FBQyxLQUNqQiwyQkFBMkIsSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUMvQyxDQUFDO1FBQ0YsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO1NBQU0sQ0FBQztRQUNOLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztBQUNILENBQUMifQ==
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/p2p",
3
- "version": "0.55.1",
3
+ "version": "0.57.0",
4
4
  "type": "module",
5
5
  "exports": "./dest/index.js",
6
6
  "typedocOptions": {
@@ -37,6 +37,9 @@
37
37
  "parser": {
38
38
  "syntax": "typescript",
39
39
  "decorators": true
40
+ },
41
+ "transform": {
42
+ "decoratorVersion": "2022-03"
40
43
  }
41
44
  }
42
45
  }
@@ -56,11 +59,11 @@
56
59
  "testTimeout": 15000
57
60
  },
58
61
  "dependencies": {
59
- "@aztec/circuit-types": "0.55.1",
60
- "@aztec/circuits.js": "0.55.1",
61
- "@aztec/foundation": "0.55.1",
62
- "@aztec/kv-store": "0.55.1",
63
- "@aztec/telemetry-client": "0.55.1",
62
+ "@aztec/circuit-types": "0.57.0",
63
+ "@aztec/circuits.js": "0.57.0",
64
+ "@aztec/foundation": "0.57.0",
65
+ "@aztec/kv-store": "0.57.0",
66
+ "@aztec/telemetry-client": "0.57.0",
64
67
  "@chainsafe/discv5": "9.0.0",
65
68
  "@chainsafe/enr": "3.0.0",
66
69
  "@chainsafe/libp2p-gossipsub": "13.0.0",
@@ -86,6 +89,7 @@
86
89
  "tslib": "^2.4.0"
87
90
  },
88
91
  "devDependencies": {
92
+ "@aztec/archiver": "workspace:^",
89
93
  "@jest/globals": "^29.5.0",
90
94
  "@types/jest": "^29.5.0",
91
95
  "@types/node": "^18.14.6",
@@ -36,7 +36,8 @@ export interface AttestationPool {
36
36
  * Retrieve all of the attestations observed pertaining to a given slot
37
37
  *
38
38
  * @param slot - The slot to query
39
+ * @param proposalId - The proposal to query
39
40
  * @return BlockAttestations
40
41
  */
41
- getAttestationsForSlot(slot: bigint): Promise<BlockAttestation[]>;
42
+ getAttestationsForSlot(slot: bigint, proposalId: string): Promise<BlockAttestation[]>;
42
43
  }
@@ -4,33 +4,38 @@ import { createDebugLogger } from '@aztec/foundation/log';
4
4
  import { type AttestationPool } from './attestation_pool.js';
5
5
 
6
6
  export class InMemoryAttestationPool implements AttestationPool {
7
- private attestations: Map</*slot=*/ bigint, Map</*address=*/ string, BlockAttestation>>;
7
+ private attestations: Map</*slot=*/ bigint, Map</*proposalId*/ string, Map</*address=*/ string, BlockAttestation>>>;
8
8
 
9
9
  constructor(private log = createDebugLogger('aztec:attestation_pool')) {
10
10
  this.attestations = new Map();
11
11
  }
12
12
 
13
- public getAttestationsForSlot(slot: bigint): Promise<BlockAttestation[]> {
13
+ public getAttestationsForSlot(slot: bigint, proposalId: string): Promise<BlockAttestation[]> {
14
14
  const slotAttestationMap = this.attestations.get(slot);
15
15
  if (slotAttestationMap) {
16
- return Promise.resolve(Array.from(slotAttestationMap.values()));
17
- } else {
18
- return Promise.resolve([]);
16
+ const proposalAttestationMap = slotAttestationMap.get(proposalId);
17
+ if (proposalAttestationMap) {
18
+ return Promise.resolve(Array.from(proposalAttestationMap.values()));
19
+ }
19
20
  }
21
+ return Promise.resolve([]);
20
22
  }
21
23
 
22
- public async addAttestations(attestations: BlockAttestation[]): Promise<void> {
24
+ public addAttestations(attestations: BlockAttestation[]): Promise<void> {
23
25
  for (const attestation of attestations) {
24
26
  // Perf: order and group by slot before insertion
25
- const slotNumber = attestation.header.globalVariables.slotNumber;
27
+ const slotNumber = attestation.payload.header.globalVariables.slotNumber;
26
28
 
27
- const address = await attestation.getSender();
29
+ const proposalId = attestation.p2pMessageIdentifier().toString();
30
+ const address = attestation.getSender();
28
31
 
29
32
  const slotAttestationMap = getSlotOrDefault(this.attestations, slotNumber.toBigInt());
30
- slotAttestationMap.set(address.toString(), attestation);
33
+ const proposalAttestationMap = getProposalOrDefault(slotAttestationMap, proposalId);
34
+ proposalAttestationMap.set(address.toString(), attestation);
31
35
 
32
36
  this.log.verbose(`Added attestation for slot ${slotNumber} from ${address}`);
33
37
  }
38
+ return Promise.resolve();
34
39
  }
35
40
 
36
41
  public deleteAttestationsForSlot(slot: bigint): Promise<void> {
@@ -40,14 +45,27 @@ export class InMemoryAttestationPool implements AttestationPool {
40
45
  return Promise.resolve();
41
46
  }
42
47
 
43
- public async deleteAttestations(attestations: BlockAttestation[]): Promise<void> {
48
+ public deleteAttestationsForSlotAndProposal(slot: bigint, proposalId: string): Promise<void> {
49
+ const slotAttestationMap = this.attestations.get(slot);
50
+ if (slotAttestationMap) {
51
+ slotAttestationMap.delete(proposalId);
52
+ this.log.verbose(`Removed attestation for slot ${slot}`);
53
+ }
54
+ return Promise.resolve();
55
+ }
56
+
57
+ public deleteAttestations(attestations: BlockAttestation[]): Promise<void> {
44
58
  for (const attestation of attestations) {
45
- const slotNumber = attestation.header.globalVariables.slotNumber;
59
+ const slotNumber = attestation.payload.header.globalVariables.slotNumber;
46
60
  const slotAttestationMap = this.attestations.get(slotNumber.toBigInt());
47
61
  if (slotAttestationMap) {
48
- const address = await attestation.getSender();
49
- slotAttestationMap.delete(address.toString());
50
- this.log.verbose(`Deleted attestation for slot ${slotNumber} from ${address}`);
62
+ const proposalId = attestation.p2pMessageIdentifier().toString();
63
+ const proposalAttestationMap = getProposalOrDefault(slotAttestationMap, proposalId);
64
+ if (proposalAttestationMap) {
65
+ const address = attestation.getSender();
66
+ proposalAttestationMap.delete(address.toString());
67
+ this.log.debug(`Deleted attestation for slot ${slotNumber} from ${address}`);
68
+ }
51
69
  }
52
70
  }
53
71
  return Promise.resolve();
@@ -58,13 +76,34 @@ export class InMemoryAttestationPool implements AttestationPool {
58
76
  * Get Slot or Default
59
77
  *
60
78
  * Fetch the slot mapping, if it does not exist, then create a mapping and return it
79
+ * @param map - The map to fetch from
80
+ * @param slot - The slot to fetch
81
+ * @returns The slot mapping
61
82
  */
62
83
  function getSlotOrDefault(
63
- map: Map<bigint, Map<string, BlockAttestation>>,
84
+ map: Map<bigint, Map<string, Map<string, BlockAttestation>>>,
64
85
  slot: bigint,
65
- ): Map<string, BlockAttestation> {
86
+ ): Map<string, Map<string, BlockAttestation>> {
66
87
  if (!map.has(slot)) {
67
- map.set(slot, new Map<string, BlockAttestation>());
88
+ map.set(slot, new Map<string, Map<string, BlockAttestation>>());
68
89
  }
69
90
  return map.get(slot)!;
70
91
  }
92
+
93
+ /**
94
+ * Get Proposal or Default
95
+ *
96
+ * Fetch the proposal mapping, if it does not exist, then create a mapping and return it
97
+ * @param map - The map to fetch from
98
+ * @param proposalId - The proposal id to fetch
99
+ * @returns The proposal mapping
100
+ */
101
+ function getProposalOrDefault(
102
+ map: Map<string, Map<string, BlockAttestation>>,
103
+ proposalId: string,
104
+ ): Map<string, BlockAttestation> {
105
+ if (!map.has(proposalId)) {
106
+ map.set(proposalId, new Map<string, BlockAttestation>());
107
+ }
108
+ return map.get(proposalId)!;
109
+ }
@@ -1,7 +1,7 @@
1
- import { BlockAttestation, Signature, TxHash } from '@aztec/circuit-types';
1
+ import { BlockAttestation, ConsensusPayload, TxHash } from '@aztec/circuit-types';
2
2
  import { makeHeader } from '@aztec/circuits.js/testing';
3
+ import { Signature } from '@aztec/foundation/eth-signature';
3
4
  import { Fr } from '@aztec/foundation/fields';
4
- import { serializeToBuffer } from '@aztec/foundation/serialize';
5
5
 
6
6
  import { type PrivateKeyAccount } from 'viem';
7
7
  import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
@@ -22,15 +22,20 @@ export const generateAccount = () => {
22
22
  * @param slot The slot number the attestation is for
23
23
  * @returns A Block Attestation
24
24
  */
25
- export const mockAttestation = async (signer: PrivateKeyAccount, slot: number = 0): Promise<BlockAttestation> => {
25
+ export const mockAttestation = async (
26
+ signer: PrivateKeyAccount,
27
+ slot: number = 0,
28
+ archive: Fr = Fr.random(),
29
+ ): Promise<BlockAttestation> => {
26
30
  // Use arbitrary numbers for all other than slot
27
31
  const header = makeHeader(1, 2, slot);
28
- const archive = Fr.random();
29
32
  const txs = [0, 1, 2, 3, 4, 5].map(() => TxHash.random());
30
33
 
31
- const message: `0x${string}` = `0x${serializeToBuffer([archive, txs]).toString('hex')}`;
34
+ const payload = new ConsensusPayload(header, archive, txs);
35
+
36
+ const message: `0x${string}` = `0x${payload.getPayloadToSign().toString('hex')}`;
32
37
  const sigString = await signer.signMessage({ message });
33
38
 
34
39
  const signature = Signature.from0xString(sigString);
35
- return new BlockAttestation(header, archive, txs, signature);
40
+ return new BlockAttestation(payload, signature);
36
41
  };
@@ -6,8 +6,11 @@ import { type TelemetryClient } from '@aztec/telemetry-client';
6
6
  import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
7
7
 
8
8
  import { type AttestationPool } from '../attestation_pool/attestation_pool.js';
9
+ import { InMemoryAttestationPool } from '../attestation_pool/memory_attestation_pool.js';
9
10
  import { P2PClient } from '../client/p2p_client.js';
10
11
  import { type P2PConfig } from '../config.js';
12
+ import { type EpochProofQuotePool } from '../epoch_proof_quote_pool/epoch_proof_quote_pool.js';
13
+ import { MemoryEpochProofQuotePool } from '../epoch_proof_quote_pool/memory_epoch_proof_quote_pool.js';
11
14
  import { DiscV5Service } from '../service/discV5_service.js';
12
15
  import { DummyP2PService } from '../service/dummy_service.js';
13
16
  import { LibP2PService, createLibP2PPeerId } from '../service/index.js';
@@ -18,16 +21,22 @@ export * from './p2p_client.js';
18
21
 
19
22
  export const createP2PClient = async (
20
23
  _config: P2PConfig & DataStoreConfig,
21
- attestationsPool: AttestationPool,
22
24
  l2BlockSource: L2BlockSource,
23
25
  proofVerifier: ClientProtocolCircuitVerifier,
24
26
  worldStateSynchronizer: WorldStateSynchronizer,
25
27
  telemetry: TelemetryClient = new NoopTelemetryClient(),
26
- deps: { txPool?: TxPool; store?: AztecKVStore } = {},
28
+ deps: {
29
+ txPool?: TxPool;
30
+ store?: AztecKVStore;
31
+ attestationsPool?: AttestationPool;
32
+ epochProofQuotePool?: EpochProofQuotePool;
33
+ } = {},
27
34
  ) => {
28
35
  let config = { ..._config };
29
36
  const store = deps.store ?? (await createStore('p2p', config, createDebugLogger('aztec:p2p:lmdb')));
30
37
  const txPool = deps.txPool ?? new AztecKVTxPool(store, telemetry);
38
+ const attestationsPool = deps.attestationsPool ?? new InMemoryAttestationPool();
39
+ const epochProofQuotePool = deps.epochProofQuotePool ?? new MemoryEpochProofQuotePool();
31
40
 
32
41
  let p2pService;
33
42
 
@@ -52,7 +61,15 @@ export const createP2PClient = async (
52
61
  } else {
53
62
  p2pService = new DummyP2PService();
54
63
  }
55
- return new P2PClient(store, l2BlockSource, txPool, attestationsPool, p2pService, config.keepProvenTxsInPoolFor);
64
+ return new P2PClient(
65
+ store,
66
+ l2BlockSource,
67
+ txPool,
68
+ attestationsPool,
69
+ epochProofQuotePool,
70
+ p2pService,
71
+ config.keepProvenTxsInPoolFor,
72
+ );
56
73
  };
57
74
 
58
75
  async function configureP2PClientAddresses(_config: P2PConfig & DataStoreConfig): Promise<P2PConfig & DataStoreConfig> {
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  type BlockAttestation,
3
3
  type BlockProposal,
4
+ type EpochProofQuote,
4
5
  type L2Block,
5
6
  L2BlockDownloader,
6
7
  type L2BlockSource,
@@ -15,6 +16,7 @@ import { type ENR } from '@chainsafe/enr';
15
16
 
16
17
  import { type AttestationPool } from '../attestation_pool/attestation_pool.js';
17
18
  import { getP2PConfigEnvVars } from '../config.js';
19
+ import { type EpochProofQuotePool } from '../epoch_proof_quote_pool/epoch_proof_quote_pool.js';
18
20
  import { TX_REQ_PROTOCOL } from '../service/reqresp/interface.js';
19
21
  import type { P2PService } from '../service/service.js';
20
22
  import { type TxPool } from '../tx_pool/index.js';
@@ -58,9 +60,25 @@ export interface P2P {
58
60
  * Queries the Attestation pool for attestations for the given slot
59
61
  *
60
62
  * @param slot - the slot to query
63
+ * @param proposalId - the proposal id to query
61
64
  * @returns BlockAttestations
62
65
  */
63
- getAttestationsForSlot(slot: bigint): Promise<BlockAttestation[]>;
66
+ getAttestationsForSlot(slot: bigint, proposalId: string): Promise<BlockAttestation[]>;
67
+
68
+ /**
69
+ * Queries the EpochProofQuote pool for quotes for the given epoch
70
+ *
71
+ * @param epoch - the epoch to query
72
+ * @returns EpochProofQuotes
73
+ */
74
+ getEpochProofQuotes(epoch: bigint): Promise<EpochProofQuote[]>;
75
+
76
+ /**
77
+ * Broadcasts an EpochProofQuote to other peers.
78
+ *
79
+ * @param quote - the quote to broadcast
80
+ */
81
+ broadcastEpochProofQuote(quote: EpochProofQuote): void;
64
82
 
65
83
  /**
66
84
  * Registers a callback from the validator client that determines how to behave when
@@ -134,7 +152,7 @@ export interface P2P {
134
152
  * Indicates if the p2p client is ready for transaction submission.
135
153
  * @returns A boolean flag indicating readiness.
136
154
  */
137
- isReady(): Promise<boolean>;
155
+ isReady(): boolean;
138
156
 
139
157
  /**
140
158
  * Returns the current status of the p2p client.
@@ -186,6 +204,7 @@ export class P2PClient implements P2P {
186
204
  private l2BlockSource: L2BlockSource,
187
205
  private txPool: TxPool,
188
206
  private attestationPool: AttestationPool,
207
+ private epochProofQuotePool: EpochProofQuotePool,
189
208
  private p2pService: P2PService,
190
209
  private keepProvenTxsFor: number,
191
210
  private log = createDebugLogger('aztec:p2p'),
@@ -202,6 +221,22 @@ export class P2PClient implements P2P {
202
221
  this.synchedProvenBlockNumber = store.openSingleton('p2p_pool_last_proven_l2_block');
203
222
  }
204
223
 
224
+ #assertIsReady() {
225
+ if (!this.isReady()) {
226
+ throw new Error('P2P client not ready');
227
+ }
228
+ }
229
+
230
+ getEpochProofQuotes(epoch: bigint): Promise<EpochProofQuote[]> {
231
+ return Promise.resolve(this.epochProofQuotePool.getQuotes(epoch));
232
+ }
233
+
234
+ broadcastEpochProofQuote(quote: EpochProofQuote): void {
235
+ this.#assertIsReady();
236
+ this.epochProofQuotePool.addQuote(quote);
237
+ return this.p2pService.propagate(quote);
238
+ }
239
+
205
240
  /**
206
241
  * Starts the P2P client.
207
242
  * @returns An empty promise signalling the synching process.
@@ -281,8 +316,8 @@ export class P2PClient implements P2P {
281
316
  return this.p2pService.propagate(proposal);
282
317
  }
283
318
 
284
- public getAttestationsForSlot(slot: bigint): Promise<BlockAttestation[]> {
285
- return Promise.resolve(this.attestationPool.getAttestationsForSlot(slot));
319
+ public getAttestationsForSlot(slot: bigint, proposalId: string): Promise<BlockAttestation[]> {
320
+ return Promise.resolve(this.attestationPool.getAttestationsForSlot(slot, proposalId));
286
321
  }
287
322
 
288
323
  // REVIEW: https://github.com/AztecProtocol/aztec-packages/issues/7963
@@ -319,8 +354,6 @@ export class P2PClient implements P2P {
319
354
 
320
355
  this.log.debug(`Requested ${txHash.toString()} from peer | success = ${!!tx}`);
321
356
  if (tx) {
322
- // TODO(https://github.com/AztecProtocol/aztec-packages/issues/8485): This check is not sufficient to validate the transaction. We need to validate the entire proof.
323
- // TODO(https://github.com/AztecProtocol/aztec-packages/issues/8483): alter peer scoring system for a validator that returns an invalid transcation
324
357
  await this.txPool.addTxs([tx]);
325
358
  }
326
359
 
@@ -365,10 +398,7 @@ export class P2PClient implements P2P {
365
398
  * @returns Empty promise.
366
399
  **/
367
400
  public async sendTx(tx: Tx): Promise<void> {
368
- const ready = await this.isReady();
369
- if (!ready) {
370
- throw new Error('P2P client not ready');
371
- }
401
+ this.#assertIsReady();
372
402
  await this.txPool.addTxs([tx]);
373
403
  this.p2pService.propagate(tx);
374
404
  }
@@ -393,10 +423,7 @@ export class P2PClient implements P2P {
393
423
  * @returns Empty promise.
394
424
  **/
395
425
  public async deleteTxs(txHashes: TxHash[]): Promise<void> {
396
- const ready = await this.isReady();
397
- if (!ready) {
398
- throw new Error('P2P client not ready');
399
- }
426
+ this.#assertIsReady();
400
427
  await this.txPool.deleteTxs(txHashes);
401
428
  }
402
429
 
@@ -405,7 +432,7 @@ export class P2PClient implements P2P {
405
432
  * @returns True if the P2P client is ready to receive txs.
406
433
  */
407
434
  public isReady() {
408
- return Promise.resolve(this.currentState === P2PClientState.RUNNING);
435
+ return this.currentState === P2PClientState.RUNNING;
409
436
  }
410
437
 
411
438
  /**
@@ -501,6 +528,10 @@ export class P2PClient implements P2P {
501
528
 
502
529
  await this.synchedProvenBlockNumber.set(lastBlockNum);
503
530
  this.log.debug(`Synched to proven block ${lastBlockNum}`);
531
+ const provenEpochNumber = await this.l2BlockSource.getProvenL2EpochNumber();
532
+ if (provenEpochNumber !== undefined) {
533
+ this.epochProofQuotePool.deleteQuotesToEpoch(BigInt(provenEpochNumber));
534
+ }
504
535
  await this.startServiceIfSynched();
505
536
  }
506
537
 
@@ -0,0 +1,7 @@
1
+ import { type EpochProofQuote } from '@aztec/circuit-types';
2
+
3
+ export interface EpochProofQuotePool {
4
+ addQuote(quote: EpochProofQuote): void;
5
+ getQuotes(epoch: bigint): EpochProofQuote[];
6
+ deleteQuotesToEpoch(epoch: bigint): void;
7
+ }
@@ -0,0 +1,3 @@
1
+ export * from './epoch_proof_quote_pool.js';
2
+ export * from './memory_epoch_proof_quote_pool.js';
3
+ export * from './test_utils.js';
@@ -0,0 +1,26 @@
1
+ import { type EpochProofQuote } from '@aztec/circuit-types';
2
+
3
+ import { type EpochProofQuotePool } from './epoch_proof_quote_pool.js';
4
+
5
+ export class MemoryEpochProofQuotePool implements EpochProofQuotePool {
6
+ private quotes: Map<bigint, EpochProofQuote[]>;
7
+ constructor() {
8
+ this.quotes = new Map();
9
+ }
10
+ addQuote(quote: EpochProofQuote) {
11
+ const epoch = quote.payload.epochToProve;
12
+ if (!this.quotes.has(epoch)) {
13
+ this.quotes.set(epoch, []);
14
+ }
15
+ this.quotes.get(epoch)!.push(quote);
16
+ }
17
+ getQuotes(epoch: bigint): EpochProofQuote[] {
18
+ return this.quotes.get(epoch) || [];
19
+ }
20
+ deleteQuotesToEpoch(epoch: bigint): void {
21
+ const expiredEpochs = Array.from(this.quotes.keys()).filter(k => k <= epoch);
22
+ for (const expiredEpoch of expiredEpochs) {
23
+ this.quotes.delete(expiredEpoch);
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ import { EpochProofQuote, EpochProofQuotePayload } from '@aztec/circuit-types';
2
+ import { EthAddress } from '@aztec/circuits.js';
3
+ import { Buffer32 } from '@aztec/foundation/buffer';
4
+ import { Secp256k1Signer, randomBigInt, randomInt } from '@aztec/foundation/crypto';
5
+
6
+ export function makeRandomEpochProofQuotePayload(): EpochProofQuotePayload {
7
+ return EpochProofQuotePayload.from({
8
+ basisPointFee: randomInt(10000),
9
+ bondAmount: 1000000000000000000n,
10
+ epochToProve: randomBigInt(1000000n),
11
+ prover: EthAddress.random(),
12
+ validUntilSlot: randomBigInt(1000000n),
13
+ });
14
+ }
15
+
16
+ export function makeRandomEpochProofQuote(payload?: EpochProofQuotePayload): {
17
+ quote: EpochProofQuote;
18
+ signer: Secp256k1Signer;
19
+ } {
20
+ const signer = Secp256k1Signer.random();
21
+
22
+ return {
23
+ quote: EpochProofQuote.new(Buffer32.random(), payload ?? makeRandomEpochProofQuotePayload(), signer),
24
+ signer,
25
+ };
26
+ }
package/src/index.ts CHANGED
@@ -1,7 +1,8 @@
1
+ export * from './attestation_pool/index.js';
2
+ export * from './bootstrap/bootstrap.js';
1
3
  export * from './client/index.js';
2
4
  export * from './config.js';
3
- export * from './tx_pool/index.js';
4
- export * from './attestation_pool/index.js';
5
+ export * from './epoch_proof_quote_pool/index.js';
5
6
  export * from './service/index.js';
6
- export * from './bootstrap/bootstrap.js';
7
+ export * from './tx_pool/index.js';
7
8
  export * from './tx_validator/index.js';
@@ -1,16 +1,21 @@
1
+ import { type ClientProtocolCircuitVerifier, type Tx } from '@aztec/circuit-types';
2
+
1
3
  import { noise } from '@chainsafe/libp2p-noise';
2
4
  import { yamux } from '@chainsafe/libp2p-yamux';
3
5
  import { bootstrap } from '@libp2p/bootstrap';
4
6
  import { tcp } from '@libp2p/tcp';
5
7
  import { type Libp2p, type Libp2pOptions, createLibp2p } from 'libp2p';
6
8
 
9
+ import { type PeerManager } from '../service/peer_manager.js';
7
10
  import { type P2PReqRespConfig } from '../service/reqresp/config.js';
8
11
  import { pingHandler, statusHandler } from '../service/reqresp/handlers.js';
9
12
  import {
10
13
  PING_PROTOCOL,
11
14
  type ReqRespSubProtocolHandlers,
15
+ type ReqRespSubProtocolValidators,
12
16
  STATUS_PROTOCOL,
13
17
  TX_REQ_PROTOCOL,
18
+ noopValidator,
14
19
  } from '../service/reqresp/interface.js';
15
20
  import { ReqResp } from '../service/reqresp/reqresp.js';
16
21
 
@@ -56,18 +61,29 @@ export const MOCK_SUB_PROTOCOL_HANDLERS: ReqRespSubProtocolHandlers = {
56
61
  [TX_REQ_PROTOCOL]: (_msg: any) => Promise.resolve(Uint8Array.from(Buffer.from('tx'))),
57
62
  };
58
63
 
64
+ // By default, all requests are valid
65
+ // If you want to test an invalid response, you can override the validator
66
+ export const MOCK_SUB_PROTOCOL_VALIDATORS: ReqRespSubProtocolValidators = {
67
+ [PING_PROTOCOL]: noopValidator,
68
+ [STATUS_PROTOCOL]: noopValidator,
69
+ [TX_REQ_PROTOCOL]: noopValidator,
70
+ };
71
+
59
72
  /**
60
73
  * @param numberOfNodes - the number of nodes to create
61
74
  * @returns An array of the created nodes
62
75
  */
63
- export const createNodes = async (numberOfNodes: number): Promise<ReqRespNode[]> => {
64
- return await Promise.all(Array.from({ length: numberOfNodes }, () => createReqResp()));
76
+ export const createNodes = async (peerManager: PeerManager, numberOfNodes: number): Promise<ReqRespNode[]> => {
77
+ return await Promise.all(Array.from({ length: numberOfNodes }, () => createReqResp(peerManager)));
65
78
  };
66
79
 
67
- // TODO: think about where else this can go
68
- export const startNodes = async (nodes: ReqRespNode[], subProtocolHandlers = MOCK_SUB_PROTOCOL_HANDLERS) => {
80
+ export const startNodes = async (
81
+ nodes: ReqRespNode[],
82
+ subProtocolHandlers = MOCK_SUB_PROTOCOL_HANDLERS,
83
+ subProtocolValidators = MOCK_SUB_PROTOCOL_VALIDATORS,
84
+ ) => {
69
85
  for (const node of nodes) {
70
- await node.req.start(subProtocolHandlers);
86
+ await node.req.start(subProtocolHandlers, subProtocolValidators);
71
87
  }
72
88
  };
73
89
 
@@ -79,13 +95,13 @@ export const stopNodes = async (nodes: ReqRespNode[]): Promise<void> => {
79
95
  };
80
96
 
81
97
  // Create a req resp node, exposing the underlying p2p node
82
- export const createReqResp = async (): Promise<ReqRespNode> => {
98
+ export const createReqResp = async (peerManager: PeerManager): Promise<ReqRespNode> => {
83
99
  const p2p = await createLibp2pNode();
84
100
  const config: P2PReqRespConfig = {
85
101
  overallRequestTimeoutMs: 4000,
86
102
  individualRequestTimeoutMs: 2000,
87
103
  };
88
- const req = new ReqResp(config, p2p);
104
+ const req = new ReqResp(config, p2p, peerManager);
89
105
  return {
90
106
  p2p,
91
107
  req,
@@ -104,3 +120,15 @@ export const connectToPeers = async (nodes: ReqRespNode[]): Promise<void> => {
104
120
  }
105
121
  }
106
122
  };
123
+
124
+ // Mock circuit verifier for testing - reimplementation from bb to avoid dependency
125
+ export class AlwaysTrueCircuitVerifier implements ClientProtocolCircuitVerifier {
126
+ verifyProof(_tx: Tx): Promise<boolean> {
127
+ return Promise.resolve(true);
128
+ }
129
+ }
130
+ export class AlwaysFalseCircuitVerifier implements ClientProtocolCircuitVerifier {
131
+ verifyProof(_tx: Tx): Promise<boolean> {
132
+ return Promise.resolve(false);
133
+ }
134
+ }