@aztec/p2p 0.55.1 → 0.56.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 (46) hide show
  1. package/dest/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
  2. package/dest/attestation_pool/memory_attestation_pool.js +8 -7
  3. package/dest/attestation_pool/mocks.d.ts.map +1 -1
  4. package/dest/attestation_pool/mocks.js +6 -5
  5. package/dest/client/p2p_client.d.ts.map +1 -1
  6. package/dest/client/p2p_client.js +1 -3
  7. package/dest/mocks/index.d.ts +13 -4
  8. package/dest/mocks/index.d.ts.map +1 -1
  9. package/dest/mocks/index.js +26 -9
  10. package/dest/service/libp2p_service.d.ts +16 -1
  11. package/dest/service/libp2p_service.d.ts.map +1 -1
  12. package/dest/service/libp2p_service.js +53 -23
  13. package/dest/service/reqresp/interface.d.ts +7 -0
  14. package/dest/service/reqresp/interface.d.ts.map +1 -1
  15. package/dest/service/reqresp/interface.js +7 -1
  16. package/dest/service/reqresp/rate_limiter/rate_limiter.d.ts +13 -3
  17. package/dest/service/reqresp/rate_limiter/rate_limiter.d.ts.map +1 -1
  18. package/dest/service/reqresp/rate_limiter/rate_limiter.js +29 -7
  19. package/dest/service/reqresp/reqresp.d.ts +56 -5
  20. package/dest/service/reqresp/reqresp.d.ts.map +1 -1
  21. package/dest/service/reqresp/reqresp.js +73 -9
  22. package/dest/tx_validator/aggregate_tx_validator.d.ts +1 -0
  23. package/dest/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  24. package/dest/tx_validator/aggregate_tx_validator.js +10 -1
  25. package/dest/tx_validator/data_validator.d.ts +1 -0
  26. package/dest/tx_validator/data_validator.d.ts.map +1 -1
  27. package/dest/tx_validator/data_validator.js +4 -1
  28. package/dest/tx_validator/double_spend_validator.d.ts +1 -0
  29. package/dest/tx_validator/double_spend_validator.d.ts.map +1 -1
  30. package/dest/tx_validator/double_spend_validator.js +4 -1
  31. package/dest/tx_validator/metadata_validator.d.ts +1 -0
  32. package/dest/tx_validator/metadata_validator.d.ts.map +1 -1
  33. package/dest/tx_validator/metadata_validator.js +4 -1
  34. package/package.json +6 -6
  35. package/src/attestation_pool/memory_attestation_pool.ts +7 -6
  36. package/src/attestation_pool/mocks.ts +6 -4
  37. package/src/client/p2p_client.ts +0 -2
  38. package/src/mocks/index.ts +35 -7
  39. package/src/service/libp2p_service.ts +57 -24
  40. package/src/service/reqresp/interface.ts +20 -0
  41. package/src/service/reqresp/rate_limiter/rate_limiter.ts +30 -7
  42. package/src/service/reqresp/reqresp.ts +82 -8
  43. package/src/tx_validator/aggregate_tx_validator.ts +10 -0
  44. package/src/tx_validator/data_validator.ts +4 -0
  45. package/src/tx_validator/double_spend_validator.ts +4 -0
  46. package/src/tx_validator/metadata_validator.ts +4 -0
@@ -24,6 +24,9 @@ export class DoubleSpendTxValidator {
24
24
  }
25
25
  return [validTxs, invalidTxs];
26
26
  }
27
+ validateTx(tx) {
28
+ return __classPrivateFieldGet(this, _DoubleSpendTxValidator_instances, "m", _DoubleSpendTxValidator_uniqueNullifiers).call(this, tx, new Set());
29
+ }
27
30
  }
28
31
  _DoubleSpendTxValidator_log = new WeakMap(), _DoubleSpendTxValidator_nullifierSource = new WeakMap(), _DoubleSpendTxValidator_instances = new WeakSet(), _DoubleSpendTxValidator_uniqueNullifiers = async function _DoubleSpendTxValidator_uniqueNullifiers(tx, thisBlockNullifiers) {
29
32
  const nullifiers = tx.data.getNonEmptyNullifiers().map(x => x.toBigInt());
@@ -50,4 +53,4 @@ _DoubleSpendTxValidator_log = new WeakMap(), _DoubleSpendTxValidator_nullifierSo
50
53
  }
51
54
  return true;
52
55
  };
53
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG91YmxlX3NwZW5kX3ZhbGlkYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90eF92YWxpZGF0b3IvZG91YmxlX3NwZW5kX3ZhbGlkYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLE9BQU8sRUFBYyxFQUFFLEVBQW9CLE1BQU0sc0JBQXNCLENBQUM7QUFDeEUsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3hDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBTTFELE1BQU0sT0FBTyxzQkFBc0I7SUFJakMsWUFBWSxlQUFnQyxFQUFtQixvQkFBNkIsSUFBSTs7UUFBakMsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFnQjtRQUhoRyxzQ0FBTyxpQkFBaUIsQ0FBQyw4Q0FBOEMsQ0FBQyxFQUFDO1FBQ3pFLDBEQUFrQztRQUdoQyx1QkFBQSxJQUFJLDJDQUFvQixlQUFlLE1BQUEsQ0FBQztJQUMxQyxDQUFDO0lBRUQsS0FBSyxDQUFDLFdBQVcsQ0FBQyxHQUFRO1FBQ3hCLE1BQU0sUUFBUSxHQUFRLEVBQUUsQ0FBQztRQUN6QixNQUFNLFVBQVUsR0FBUSxFQUFFLENBQUM7UUFDM0IsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO1FBRTlDLEtBQUssTUFBTSxFQUFFLElBQUksR0FBRyxFQUFFLENBQUM7WUFDckIsSUFBSSxDQUFDLENBQUMsTUFBTSx1QkFBQSxJQUFJLG1GQUFrQixNQUF0QixJQUFJLEVBQW1CLEVBQUUsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDN0QsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDcEIsU0FBUztZQUNYLENBQUM7WUFFRCxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3BCLENBQUM7UUFFRCxPQUFPLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ2hDLENBQUM7Q0FpQ0Y7b01BL0JDLEtBQUssbURBQW1CLEVBQVMsRUFBRSxtQkFBZ0M7SUFDakUsTUFBTSxVQUFVLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBRTFFLDhDQUE4QztJQUM5QyxNQUFNLGdCQUFnQixHQUFHLElBQUksR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzdDLElBQUksZ0JBQWdCLENBQUMsSUFBSSxLQUFLLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNoRCx1QkFBQSxJQUFJLG1DQUFLLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxvQ0FBb0MsQ0FBQyxDQUFDO1FBQ25GLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVELElBQUksSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFDM0IsS0FBSyxNQUFNLFNBQVMsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNuQyxJQUFJLG1CQUFtQixDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO2dCQUN2Qyx1QkFBQSxJQUFJLG1DQUFLLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO2dCQUM3RixPQUFPLEtBQUssQ0FBQztZQUNmLENBQUM7WUFFRCxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDckMsQ0FBQztJQUNILENBQUM7SUFFRCxNQUFNLGdCQUFnQixHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsdUJBQUEsSUFBSSwrQ0FBaUIsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUVwSCxNQUFNLGFBQWEsR0FBRyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLEtBQUssU0FBUyxDQUFDLENBQUM7SUFDMUUsSUFBSSxhQUFhLEVBQUUsQ0FBQztRQUNsQix1QkFBQSxJQUFJLG1DQUFLLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxrREFBa0QsQ0FBQyxDQUFDO1FBQ2pHLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVELE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQyJ9
56
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG91YmxlX3NwZW5kX3ZhbGlkYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90eF92YWxpZGF0b3IvZG91YmxlX3NwZW5kX3ZhbGlkYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLE9BQU8sRUFBYyxFQUFFLEVBQW9CLE1BQU0sc0JBQXNCLENBQUM7QUFDeEUsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3hDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBTTFELE1BQU0sT0FBTyxzQkFBc0I7SUFJakMsWUFBWSxlQUFnQyxFQUFtQixvQkFBNkIsSUFBSTs7UUFBakMsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFnQjtRQUhoRyxzQ0FBTyxpQkFBaUIsQ0FBQyw4Q0FBOEMsQ0FBQyxFQUFDO1FBQ3pFLDBEQUFrQztRQUdoQyx1QkFBQSxJQUFJLDJDQUFvQixlQUFlLE1BQUEsQ0FBQztJQUMxQyxDQUFDO0lBRUQsS0FBSyxDQUFDLFdBQVcsQ0FBQyxHQUFRO1FBQ3hCLE1BQU0sUUFBUSxHQUFRLEVBQUUsQ0FBQztRQUN6QixNQUFNLFVBQVUsR0FBUSxFQUFFLENBQUM7UUFDM0IsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO1FBRTlDLEtBQUssTUFBTSxFQUFFLElBQUksR0FBRyxFQUFFLENBQUM7WUFDckIsSUFBSSxDQUFDLENBQUMsTUFBTSx1QkFBQSxJQUFJLG1GQUFrQixNQUF0QixJQUFJLEVBQW1CLEVBQUUsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDN0QsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDcEIsU0FBUztZQUNYLENBQUM7WUFFRCxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3BCLENBQUM7UUFFRCxPQUFPLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFFRCxVQUFVLENBQUMsRUFBSztRQUNkLE9BQU8sdUJBQUEsSUFBSSxtRkFBa0IsTUFBdEIsSUFBSSxFQUFtQixFQUFFLEVBQUUsSUFBSSxHQUFHLEVBQVUsQ0FBQyxDQUFDO0lBQ3ZELENBQUM7Q0FpQ0Y7b01BL0JDLEtBQUssbURBQW1CLEVBQVMsRUFBRSxtQkFBZ0M7SUFDakUsTUFBTSxVQUFVLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBRTFFLDhDQUE4QztJQUM5QyxNQUFNLGdCQUFnQixHQUFHLElBQUksR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzdDLElBQUksZ0JBQWdCLENBQUMsSUFBSSxLQUFLLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNoRCx1QkFBQSxJQUFJLG1DQUFLLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxvQ0FBb0MsQ0FBQyxDQUFDO1FBQ25GLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVELElBQUksSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFDM0IsS0FBSyxNQUFNLFNBQVMsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNuQyxJQUFJLG1CQUFtQixDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO2dCQUN2Qyx1QkFBQSxJQUFJLG1DQUFLLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO2dCQUM3RixPQUFPLEtBQUssQ0FBQztZQUNmLENBQUM7WUFFRCxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDckMsQ0FBQztJQUNILENBQUM7SUFFRCxNQUFNLGdCQUFnQixHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsdUJBQUEsSUFBSSwrQ0FBaUIsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUVwSCxNQUFNLGFBQWEsR0FBRyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLEtBQUssU0FBUyxDQUFDLENBQUM7SUFDMUUsSUFBSSxhQUFhLEVBQUUsQ0FBQztRQUNsQix1QkFBQSxJQUFJLG1DQUFLLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxrREFBa0QsQ0FBQyxDQUFDO1FBQ2pHLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVELE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQyJ9
@@ -6,5 +6,6 @@ export declare class MetadataTxValidator<T extends AnyTx> implements TxValidator
6
6
  private blockNumber;
7
7
  constructor(chainId: Fr, blockNumber: Fr);
8
8
  validateTxs(txs: T[]): Promise<[validTxs: T[], invalidTxs: T[]]>;
9
+ validateTx(tx: T): Promise<boolean>;
9
10
  }
10
11
  //# sourceMappingURL=metadata_validator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"metadata_validator.d.ts","sourceRoot":"","sources":["../../src/tx_validator/metadata_validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAM,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,KAAK,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAG7C,qBAAa,mBAAmB,CAAC,CAAC,SAAS,KAAK,CAAE,YAAW,WAAW,CAAC,CAAC,CAAC;;IAG7D,OAAO,CAAC,OAAO;IAAM,OAAO,CAAC,WAAW;gBAAhC,OAAO,EAAE,EAAE,EAAU,WAAW,EAAE,EAAE;IAExD,WAAW,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;CAmDjE"}
1
+ {"version":3,"file":"metadata_validator.d.ts","sourceRoot":"","sources":["../../src/tx_validator/metadata_validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAM,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,KAAK,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAG7C,qBAAa,mBAAmB,CAAC,CAAC,SAAS,KAAK,CAAE,YAAW,WAAW,CAAC,CAAC,CAAC;;IAG7D,OAAO,CAAC,OAAO;IAAM,OAAO,CAAC,WAAW;gBAAhC,OAAO,EAAE,EAAE,EAAU,WAAW,EAAE,EAAE;IAExD,WAAW,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;IAoBhE,UAAU,CAAC,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;CAmCpC"}
@@ -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.56.0",
4
4
  "type": "module",
5
5
  "exports": "./dest/index.js",
6
6
  "typedocOptions": {
@@ -56,11 +56,11 @@
56
56
  "testTimeout": 15000
57
57
  },
58
58
  "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",
59
+ "@aztec/circuit-types": "0.56.0",
60
+ "@aztec/circuits.js": "0.56.0",
61
+ "@aztec/foundation": "0.56.0",
62
+ "@aztec/kv-store": "0.56.0",
63
+ "@aztec/telemetry-client": "0.56.0",
64
64
  "@chainsafe/discv5": "9.0.0",
65
65
  "@chainsafe/enr": "3.0.0",
66
66
  "@chainsafe/libp2p-gossipsub": "13.0.0",
@@ -19,18 +19,19 @@ export class InMemoryAttestationPool implements AttestationPool {
19
19
  }
20
20
  }
21
21
 
22
- public async addAttestations(attestations: BlockAttestation[]): Promise<void> {
22
+ public addAttestations(attestations: BlockAttestation[]): Promise<void> {
23
23
  for (const attestation of attestations) {
24
24
  // Perf: order and group by slot before insertion
25
- const slotNumber = attestation.header.globalVariables.slotNumber;
25
+ const slotNumber = attestation.payload.header.globalVariables.slotNumber;
26
26
 
27
- const address = await attestation.getSender();
27
+ const address = attestation.getSender();
28
28
 
29
29
  const slotAttestationMap = getSlotOrDefault(this.attestations, slotNumber.toBigInt());
30
30
  slotAttestationMap.set(address.toString(), attestation);
31
31
 
32
32
  this.log.verbose(`Added attestation for slot ${slotNumber} from ${address}`);
33
33
  }
34
+ return Promise.resolve();
34
35
  }
35
36
 
36
37
  public deleteAttestationsForSlot(slot: bigint): Promise<void> {
@@ -40,12 +41,12 @@ export class InMemoryAttestationPool implements AttestationPool {
40
41
  return Promise.resolve();
41
42
  }
42
43
 
43
- public async deleteAttestations(attestations: BlockAttestation[]): Promise<void> {
44
+ public deleteAttestations(attestations: BlockAttestation[]): Promise<void> {
44
45
  for (const attestation of attestations) {
45
- const slotNumber = attestation.header.globalVariables.slotNumber;
46
+ const slotNumber = attestation.payload.header.globalVariables.slotNumber;
46
47
  const slotAttestationMap = this.attestations.get(slotNumber.toBigInt());
47
48
  if (slotAttestationMap) {
48
- const address = await attestation.getSender();
49
+ const address = attestation.getSender();
49
50
  slotAttestationMap.delete(address.toString());
50
51
  this.log.verbose(`Deleted attestation for slot ${slotNumber} from ${address}`);
51
52
  }
@@ -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';
@@ -28,9 +28,11 @@ export const mockAttestation = async (signer: PrivateKeyAccount, slot: number =
28
28
  const archive = Fr.random();
29
29
  const txs = [0, 1, 2, 3, 4, 5].map(() => TxHash.random());
30
30
 
31
- const message: `0x${string}` = `0x${serializeToBuffer([archive, txs]).toString('hex')}`;
31
+ const payload = new ConsensusPayload(header, archive, txs);
32
+
33
+ const message: `0x${string}` = `0x${payload.getPayloadToSign().toString('hex')}`;
32
34
  const sigString = await signer.signMessage({ message });
33
35
 
34
36
  const signature = Signature.from0xString(sigString);
35
- return new BlockAttestation(header, archive, txs, signature);
37
+ return new BlockAttestation(payload, signature);
36
38
  };
@@ -319,8 +319,6 @@ export class P2PClient implements P2P {
319
319
 
320
320
  this.log.debug(`Requested ${txHash.toString()} from peer | success = ${!!tx}`);
321
321
  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
322
  await this.txPool.addTxs([tx]);
325
323
  }
326
324
 
@@ -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
+ }
@@ -47,13 +47,13 @@ import { PeerErrorSeverity } from './peer_scoring.js';
47
47
  import { pingHandler, statusHandler } from './reqresp/handlers.js';
48
48
  import {
49
49
  DEFAULT_SUB_PROTOCOL_HANDLERS,
50
+ DEFAULT_SUB_PROTOCOL_VALIDATORS,
50
51
  PING_PROTOCOL,
51
52
  type ReqRespSubProtocol,
52
53
  type ReqRespSubProtocolHandlers,
53
54
  STATUS_PROTOCOL,
54
55
  type SubProtocolMap,
55
56
  TX_REQ_PROTOCOL,
56
- subProtocolMap,
57
57
  } from './reqresp/interface.js';
58
58
  import { ReqResp } from './reqresp/reqresp.js';
59
59
  import type { P2PService, PeerDiscoveryService } from './service.js';
@@ -109,7 +109,7 @@ export class LibP2PService implements P2PService {
109
109
  return this.peerManager.getPeerScore(peerId);
110
110
  };
111
111
  this.node.services.pubsub.score.params.appSpecificWeight = 10;
112
- this.reqresp = new ReqResp(config, node);
112
+ this.reqresp = new ReqResp(config, node, this.peerManager);
113
113
 
114
114
  this.blockReceivedCallback = (block: BlockProposal): Promise<BlockAttestation | undefined> => {
115
115
  this.logger.verbose(
@@ -162,7 +162,13 @@ export class LibP2PService implements P2PService {
162
162
  this.peerManager.heartbeat();
163
163
  }, this.config.peerCheckIntervalMS);
164
164
  this.discoveryRunningPromise.start();
165
- await this.reqresp.start(this.requestResponseHandlers);
165
+
166
+ // Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
167
+ const reqrespSubProtocolValidators = {
168
+ ...DEFAULT_SUB_PROTOCOL_VALIDATORS,
169
+ [TX_REQ_PROTOCOL]: this.validateRequestedTx.bind(this),
170
+ };
171
+ await this.reqresp.start(this.requestResponseHandlers, reqrespSubProtocolValidators);
166
172
  }
167
173
 
168
174
  /**
@@ -302,18 +308,11 @@ export class LibP2PService implements P2PService {
302
308
  * @param request The request type to send
303
309
  * @returns
304
310
  */
305
- async sendRequest<SubProtocol extends ReqRespSubProtocol>(
311
+ sendRequest<SubProtocol extends ReqRespSubProtocol>(
306
312
  protocol: SubProtocol,
307
313
  request: InstanceType<SubProtocolMap[SubProtocol]['request']>,
308
314
  ): Promise<InstanceType<SubProtocolMap[SubProtocol]['response']> | undefined> {
309
- const pair = subProtocolMap[protocol];
310
-
311
- const res = await this.reqresp.sendRequest(protocol, request.toBuffer());
312
- if (!res) {
313
- return undefined;
314
- }
315
-
316
- return pair.response.fromBuffer(res!);
315
+ return this.reqresp.sendRequest(protocol, request);
317
316
  }
318
317
 
319
318
  /**
@@ -418,19 +417,53 @@ export class LibP2PService implements P2PService {
418
417
  const txHashString = txHash.toString();
419
418
  this.logger.verbose(`Received tx ${txHashString} from external peer.`);
420
419
 
421
- const isValidTx = await this.validateTx(tx, peerId);
420
+ const isValidTx = await this.validatePropagatedTx(tx, peerId);
422
421
 
423
422
  if (isValidTx) {
424
423
  await this.txPool.addTxs([tx]);
425
424
  }
426
425
  }
427
426
 
428
- private async validateTx(tx: Tx, peerId: PeerId): Promise<boolean> {
427
+ /**
428
+ * Validate a tx that has been requested from a peer.
429
+ *
430
+ * The core component of this validator is that the tx hash MUST match the requested tx hash,
431
+ * In order to perform this check, the tx proof must be verified.
432
+ *
433
+ * Note: This function is called from within `ReqResp.sendRequest` as part of the
434
+ * TX_REQ_PROTOCOL subprotocol validation.
435
+ *
436
+ * @param requestedTxHash - The hash of the tx that was requested.
437
+ * @param responseTx - The tx that was received as a response to the request.
438
+ * @param peerId - The peer ID of the peer that sent the tx.
439
+ * @returns True if the tx is valid, false otherwise.
440
+ */
441
+ private async validateRequestedTx(requestedTxHash: TxHash, responseTx: Tx, peerId: PeerId): Promise<boolean> {
442
+ const proofValidator = new TxProofValidator(this.proofVerifier);
443
+ const validProof = await proofValidator.validateTx(responseTx);
444
+
445
+ // If the node returns the wrong data, we penalize it
446
+ if (!requestedTxHash.equals(responseTx.getTxHash())) {
447
+ // Returning the wrong data is a low tolerance error
448
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
449
+ return false;
450
+ }
451
+
452
+ if (!validProof) {
453
+ // If the proof is invalid, but the txHash is correct, then this is an active attack and we severly punish
454
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
455
+ return false;
456
+ }
457
+
458
+ return true;
459
+ }
460
+
461
+ private async validatePropagatedTx(tx: Tx, peerId: PeerId): Promise<boolean> {
429
462
  const blockNumber = (await this.l2BlockSource.getBlockNumber()) + 1;
430
463
  // basic data validation
431
464
  const dataValidator = new DataTxValidator();
432
- const [_, dataInvalidTxs] = await dataValidator.validateTxs([tx]);
433
- if (dataInvalidTxs.length > 0) {
465
+ const validData = await dataValidator.validateTx(tx);
466
+ if (!validData) {
434
467
  // penalize
435
468
  this.node.services.pubsub.score.markInvalidMessageDelivery(peerId.toString(), Tx.p2pTopic);
436
469
  return false;
@@ -438,8 +471,8 @@ export class LibP2PService implements P2PService {
438
471
 
439
472
  // metadata validation
440
473
  const metadataValidator = new MetadataTxValidator(new Fr(this.config.l1ChainId), new Fr(blockNumber));
441
- const [__, metaInvalidTxs] = await metadataValidator.validateTxs([tx]);
442
- if (metaInvalidTxs.length > 0) {
474
+ const validMetadata = await metadataValidator.validateTx(tx);
475
+ if (!validMetadata) {
443
476
  // penalize
444
477
  this.node.services.pubsub.score.markInvalidMessageDelivery(peerId.toString(), Tx.p2pTopic);
445
478
  return false;
@@ -453,8 +486,8 @@ export class LibP2PService implements P2PService {
453
486
  return index;
454
487
  },
455
488
  });
456
- const [___, doubleSpendInvalidTxs] = await doubleSpendValidator.validateTxs([tx]);
457
- if (doubleSpendInvalidTxs.length > 0) {
489
+ const validDoubleSpend = await doubleSpendValidator.validateTx(tx);
490
+ if (!validDoubleSpend) {
458
491
  // check if nullifier is older than 20 blocks
459
492
  if (blockNumber - this.config.severePeerPenaltyBlockLength > 0) {
460
493
  const snapshotValidator = new DoubleSpendTxValidator({
@@ -467,9 +500,9 @@ export class LibP2PService implements P2PService {
467
500
  },
468
501
  });
469
502
 
470
- const [____, snapshotInvalidTxs] = await snapshotValidator.validateTxs([tx]);
503
+ const validSnapshot = await snapshotValidator.validateTx(tx);
471
504
  // High penalty if nullifier is older than 20 blocks
472
- if (snapshotInvalidTxs.length > 0) {
505
+ if (!validSnapshot) {
473
506
  // penalize
474
507
  this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
475
508
  return false;
@@ -482,8 +515,8 @@ export class LibP2PService implements P2PService {
482
515
 
483
516
  // proof validation
484
517
  const proofValidator = new TxProofValidator(this.proofVerifier);
485
- const [_____, proofInvalidTxs] = await proofValidator.validateTxs([tx]);
486
- if (proofInvalidTxs.length > 0) {
518
+ const validProof = await proofValidator.validateTx(tx);
519
+ if (!validProof) {
487
520
  // penalize
488
521
  this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
489
522
  return false;
@@ -1,5 +1,7 @@
1
1
  import { Tx, TxHash } from '@aztec/circuit-types';
2
2
 
3
+ import { type PeerId } from '@libp2p/interface';
4
+
3
5
  /*
4
6
  * Request Response Sub Protocols
5
7
  */
@@ -46,11 +48,29 @@ export interface ProtocolRateLimitQuota {
46
48
  globalLimit: RateLimitQuota;
47
49
  }
48
50
 
51
+ export const noopValidator = () => Promise.resolve(true);
52
+
49
53
  /**
50
54
  * A type mapping from supprotocol to it's handling funciton
51
55
  */
52
56
  export type ReqRespSubProtocolHandlers = Record<ReqRespSubProtocol, ReqRespSubProtocolHandler>;
53
57
 
58
+ type ResponseValidator<RequestIdentifier, Response> = (
59
+ request: RequestIdentifier,
60
+ response: Response,
61
+ peerId: PeerId,
62
+ ) => Promise<boolean>;
63
+
64
+ export type ReqRespSubProtocolValidators = {
65
+ [S in ReqRespSubProtocol]: ResponseValidator<any, any>;
66
+ };
67
+
68
+ export const DEFAULT_SUB_PROTOCOL_VALIDATORS: ReqRespSubProtocolValidators = {
69
+ [PING_PROTOCOL]: noopValidator,
70
+ [STATUS_PROTOCOL]: noopValidator,
71
+ [TX_REQ_PROTOCOL]: noopValidator,
72
+ };
73
+
54
74
  /**
55
75
  * Sub protocol map determines the request and response types for each
56
76
  * Req Resp protocol
@@ -5,6 +5,8 @@
5
5
  */
6
6
  import { type PeerId } from '@libp2p/interface';
7
7
 
8
+ import { type PeerManager } from '../../peer_manager.js';
9
+ import { PeerErrorSeverity } from '../../peer_scoring.js';
8
10
  import { type ReqRespSubProtocol, type ReqRespSubProtocolRateLimits } from '../interface.js';
9
11
  import { DEFAULT_RATE_LIMITS } from './rate_limits.js';
10
12
 
@@ -69,6 +71,12 @@ interface PeerRateLimiter {
69
71
  lastAccess: number;
70
72
  }
71
73
 
74
+ enum RateLimitStatus {
75
+ Allowed,
76
+ DeniedGlobal,
77
+ DeniedPeer,
78
+ }
79
+
72
80
  /**
73
81
  * SubProtocolRateLimiter: A rate limiter for managing request rates on a per-peer and global basis for a specific subprotocol.
74
82
  *
@@ -98,9 +106,9 @@ export class SubProtocolRateLimiter {
98
106
  this.peerQuotaTimeMs = peerQuotaTimeMs;
99
107
  }
100
108
 
101
- allow(peerId: PeerId): boolean {
109
+ allow(peerId: PeerId): RateLimitStatus {
102
110
  if (!this.globalLimiter.allow()) {
103
- return false;
111
+ return RateLimitStatus.DeniedGlobal;
104
112
  }
105
113
 
106
114
  const peerIdStr = peerId.toString();
@@ -115,7 +123,11 @@ export class SubProtocolRateLimiter {
115
123
  } else {
116
124
  peerLimiter.lastAccess = Date.now();
117
125
  }
118
- return peerLimiter.limiter.allow();
126
+ const peerLimitAllowed = peerLimiter.limiter.allow();
127
+ if (!peerLimitAllowed) {
128
+ return RateLimitStatus.DeniedPeer;
129
+ }
130
+ return RateLimitStatus.Allowed;
119
131
  }
120
132
 
121
133
  cleanupInactivePeers() {
@@ -138,14 +150,16 @@ export class SubProtocolRateLimiter {
138
150
  * - Initializes with a set of rate limit configurations for different subprotocols.
139
151
  * - Creates a separate SubProtocolRateLimiter for each configured subprotocol.
140
152
  * - When a request comes in, it routes the rate limiting decision to the appropriate subprotocol limiter.
153
+ * - Peers who exceed their peer rate limits will be penalised by the peer manager.
141
154
  *
142
155
  * Usage:
143
156
  * ```
157
+ * const peerManager = new PeerManager(...);
144
158
  * const rateLimits = {
145
159
  * subprotocol1: { peerLimit: { quotaCount: 10, quotaTimeMs: 1000 }, globalLimit: { quotaCount: 100, quotaTimeMs: 1000 } },
146
160
  * subprotocol2: { peerLimit: { quotaCount: 5, quotaTimeMs: 1000 }, globalLimit: { quotaCount: 50, quotaTimeMs: 1000 } }
147
161
  * };
148
- * const limiter = new RequestResponseRateLimiter(rateLimits);
162
+ * const limiter = new RequestResponseRateLimiter(peerManager, rateLimits);
149
163
  *
150
164
  * Note: Ensure to call `stop()` when shutting down to properly clean up all subprotocol limiters.
151
165
  */
@@ -154,7 +168,7 @@ export class RequestResponseRateLimiter {
154
168
 
155
169
  private cleanupInterval: NodeJS.Timeout | undefined = undefined;
156
170
 
157
- constructor(rateLimits: ReqRespSubProtocolRateLimits = DEFAULT_RATE_LIMITS) {
171
+ constructor(private peerManager: PeerManager, rateLimits: ReqRespSubProtocolRateLimits = DEFAULT_RATE_LIMITS) {
158
172
  this.subProtocolRateLimiters = new Map();
159
173
 
160
174
  for (const [subProtocol, protocolLimits] of Object.entries(rateLimits)) {
@@ -179,10 +193,19 @@ export class RequestResponseRateLimiter {
179
193
  allow(subProtocol: ReqRespSubProtocol, peerId: PeerId): boolean {
180
194
  const limiter = this.subProtocolRateLimiters.get(subProtocol);
181
195
  if (!limiter) {
182
- // TODO: maybe throw an error here if no rate limiter is configured?
183
196
  return true;
184
197
  }
185
- return limiter.allow(peerId);
198
+ const rateLimitStatus = limiter.allow(peerId);
199
+
200
+ switch (rateLimitStatus) {
201
+ case RateLimitStatus.DeniedPeer:
202
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
203
+ return false;
204
+ case RateLimitStatus.DeniedGlobal:
205
+ return false;
206
+ default:
207
+ return true;
208
+ }
186
209
  }
187
210
 
188
211
  cleanupInactivePeers() {