@aztec/p2p 0.71.0 → 0.72.1

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 (107) hide show
  1. package/dest/client/p2p_client.d.ts.map +1 -1
  2. package/dest/client/p2p_client.js +6 -6
  3. package/dest/mem_pools/attestation_pool/mocks.d.ts +2 -1
  4. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  5. package/dest/mem_pools/attestation_pool/mocks.js +1 -1
  6. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
  7. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +2 -2
  8. package/dest/mocks/index.d.ts +3 -3
  9. package/dest/mocks/index.d.ts.map +1 -1
  10. package/dest/mocks/index.js +19 -18
  11. package/dest/services/dummy_service.d.ts +7 -0
  12. package/dest/services/dummy_service.d.ts.map +1 -1
  13. package/dest/services/dummy_service.js +10 -1
  14. package/dest/services/libp2p/libp2p_service.d.ts +17 -13
  15. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  16. package/dest/services/libp2p/libp2p_service.js +109 -101
  17. package/dest/services/peer-manager/metrics.d.ts +12 -0
  18. package/dest/services/peer-manager/metrics.d.ts.map +1 -0
  19. package/dest/services/peer-manager/metrics.js +26 -0
  20. package/dest/services/{peer_manager.d.ts → peer-manager/peer_manager.d.ts} +23 -8
  21. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -0
  22. package/dest/services/peer-manager/peer_manager.js +392 -0
  23. package/dest/services/{peer-scoring → peer-manager}/peer_scoring.d.ts +3 -0
  24. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -0
  25. package/dest/services/peer-manager/peer_scoring.js +84 -0
  26. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +45 -0
  27. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -0
  28. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +81 -0
  29. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +61 -0
  30. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -0
  31. package/dest/services/reqresp/connection-sampler/connection_sampler.js +175 -0
  32. package/dest/services/reqresp/interface.d.ts +17 -4
  33. package/dest/services/reqresp/interface.d.ts.map +1 -1
  34. package/dest/services/reqresp/interface.js +34 -11
  35. package/dest/services/reqresp/metrics.d.ts +15 -0
  36. package/dest/services/reqresp/metrics.d.ts.map +1 -0
  37. package/dest/services/reqresp/metrics.js +42 -0
  38. package/dest/services/reqresp/protocols/block.d.ts +4 -0
  39. package/dest/services/reqresp/protocols/block.d.ts.map +1 -0
  40. package/dest/services/reqresp/protocols/block.js +9 -0
  41. package/dest/services/reqresp/protocols/goodbye.d.ts +51 -0
  42. package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -0
  43. package/dest/services/reqresp/protocols/goodbye.js +92 -0
  44. package/dest/services/reqresp/protocols/index.d.ts +9 -0
  45. package/dest/services/reqresp/protocols/index.d.ts.map +1 -0
  46. package/dest/services/reqresp/protocols/index.js +9 -0
  47. package/dest/services/reqresp/protocols/ping.d.ts +9 -0
  48. package/dest/services/reqresp/protocols/ping.d.ts.map +1 -0
  49. package/dest/services/reqresp/protocols/ping.js +9 -0
  50. package/dest/services/reqresp/{handlers.d.ts → protocols/status.d.ts} +1 -7
  51. package/dest/services/reqresp/protocols/status.d.ts.map +1 -0
  52. package/dest/services/reqresp/protocols/status.js +9 -0
  53. package/dest/services/reqresp/protocols/tx.d.ts +13 -0
  54. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -0
  55. package/dest/services/reqresp/protocols/tx.js +23 -0
  56. package/dest/services/reqresp/rate-limiter/index.d.ts.map +1 -0
  57. package/dest/services/reqresp/{rate_limiter → rate-limiter}/index.js +1 -1
  58. package/dest/services/reqresp/{rate_limiter → rate-limiter}/rate_limiter.d.ts +3 -3
  59. package/dest/services/reqresp/{rate_limiter → rate-limiter}/rate_limiter.d.ts.map +1 -1
  60. package/dest/services/reqresp/{rate_limiter → rate-limiter}/rate_limiter.js +4 -4
  61. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -0
  62. package/dest/services/reqresp/rate-limiter/rate_limits.js +55 -0
  63. package/dest/services/reqresp/reqresp.d.ts +33 -6
  64. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  65. package/dest/services/reqresp/reqresp.js +414 -249
  66. package/dest/services/service.d.ts +8 -0
  67. package/dest/services/service.d.ts.map +1 -1
  68. package/dest/util.d.ts +4 -0
  69. package/dest/util.d.ts.map +1 -1
  70. package/dest/util.js +1 -1
  71. package/package.json +8 -8
  72. package/src/client/p2p_client.ts +5 -5
  73. package/src/mem_pools/attestation_pool/mocks.ts +2 -2
  74. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +0 -1
  75. package/src/mocks/index.ts +19 -20
  76. package/src/services/dummy_service.ts +13 -0
  77. package/src/services/libp2p/libp2p_service.ts +143 -128
  78. package/src/services/peer-manager/metrics.ts +41 -0
  79. package/src/services/{peer_manager.ts → peer-manager/peer_manager.ts} +67 -22
  80. package/src/services/{peer-scoring → peer-manager}/peer_scoring.ts +16 -3
  81. package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +94 -0
  82. package/src/services/reqresp/connection-sampler/connection_sampler.ts +211 -0
  83. package/src/services/reqresp/interface.ts +39 -16
  84. package/src/services/reqresp/metrics.ts +57 -0
  85. package/src/services/reqresp/protocols/block.ts +15 -0
  86. package/src/services/reqresp/protocols/goodbye.ts +101 -0
  87. package/src/services/reqresp/protocols/index.ts +8 -0
  88. package/src/services/reqresp/protocols/ping.ts +8 -0
  89. package/src/services/reqresp/{handlers.ts → protocols/status.ts} +0 -9
  90. package/src/services/reqresp/protocols/tx.ts +29 -0
  91. package/src/services/reqresp/{rate_limiter → rate-limiter}/rate_limiter.ts +3 -3
  92. package/src/services/reqresp/{rate_limiter → rate-limiter}/rate_limits.ts +24 -4
  93. package/src/services/reqresp/reqresp.ts +224 -25
  94. package/src/services/service.ts +12 -0
  95. package/src/util.ts +4 -0
  96. package/dest/services/peer-scoring/peer_scoring.d.ts.map +0 -1
  97. package/dest/services/peer-scoring/peer_scoring.js +0 -75
  98. package/dest/services/peer_manager.d.ts.map +0 -1
  99. package/dest/services/peer_manager.js +0 -358
  100. package/dest/services/reqresp/handlers.d.ts.map +0 -1
  101. package/dest/services/reqresp/handlers.js +0 -17
  102. package/dest/services/reqresp/rate_limiter/index.d.ts.map +0 -1
  103. package/dest/services/reqresp/rate_limiter/rate_limits.d.ts.map +0 -1
  104. package/dest/services/reqresp/rate_limiter/rate_limits.js +0 -35
  105. /package/dest/services/reqresp/{rate_limiter → rate-limiter}/index.d.ts +0 -0
  106. /package/dest/services/reqresp/{rate_limiter → rate-limiter}/rate_limits.d.ts +0 -0
  107. /package/src/services/reqresp/{rate_limiter → rate-limiter}/index.ts +0 -0
@@ -35,6 +35,14 @@ export interface P2PService {
35
35
  * @returns The response type, corresponding to the protocol
36
36
  */
37
37
  sendRequest<Protocol extends ReqRespSubProtocol>(protocol: Protocol, request: InstanceType<SubProtocolMap[Protocol]['request']>): Promise<InstanceType<SubProtocolMap[Protocol]['response']> | undefined>;
38
+ /**
39
+ * Send a batch of requests to peers, and return the responses
40
+ *
41
+ * @param protocol - The request response protocol to use
42
+ * @param requests - The requests to send to the peers
43
+ * @returns The responses to the requests
44
+ */
45
+ sendBatchRequest<Protocol extends ReqRespSubProtocol>(protocol: Protocol, requests: InstanceType<SubProtocolMap[Protocol]['request']>[]): Promise<InstanceType<SubProtocolMap[Protocol]['response']>[] | undefined>;
38
46
  registerBlockReceivedCallback(callback: (block: BlockProposal) => Promise<BlockAttestation | undefined>): void;
39
47
  getEnr(): ENR | undefined;
40
48
  getPeers(includePending?: boolean): PeerInfo[];
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/services/service.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAElG,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,YAAY,MAAM,QAAQ,CAAC;AAEvC,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAEtF,oBAAY,kBAAkB;IAC5B,OAAO,YAAY;IACnB,OAAO,YAAY;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;;OAGG;IACH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtB;;;OAGG;IACH,SAAS,CAAC,CAAC,SAAS,UAAU,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC;IAElD;;;;;;OAMG;IACH,WAAW,CAAC,QAAQ,SAAS,kBAAkB,EAC7C,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,YAAY,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,GACzD,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAG3E,6BAA6B,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC;IAE/G,MAAM,IAAI,GAAG,GAAG,SAAS,CAAC;IAE1B,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,QAAQ,EAAE,CAAC;CAChD;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,YAAY;IACxD;;SAEK;IACL,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;SAEK;IACL,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtB;;;OAGG;IACH,WAAW,IAAI,GAAG,EAAE,CAAC;IAErB;;OAEG;IACH,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAErC;;;;OAIG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IAEzC;;OAEG;IACH,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI,CAAC;IACjE,IAAI,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC;IAElD,SAAS,IAAI,kBAAkB,CAAC;IAEhC,MAAM,IAAI,GAAG,GAAG,SAAS,CAAC;CAC3B"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/services/service.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAElG,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,YAAY,MAAM,QAAQ,CAAC;AAEvC,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAEtF,oBAAY,kBAAkB;IAC5B,OAAO,YAAY;IACnB,OAAO,YAAY;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;;OAGG;IACH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtB;;;OAGG;IACH,SAAS,CAAC,CAAC,SAAS,UAAU,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC;IAElD;;;;;;OAMG;IACH,WAAW,CAAC,QAAQ,SAAS,kBAAkB,EAC7C,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,YAAY,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,GACzD,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAE3E;;;;;;OAMG;IACH,gBAAgB,CAAC,QAAQ,SAAS,kBAAkB,EAClD,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,YAAY,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,GAC5D,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC,CAAC;IAG7E,6BAA6B,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC;IAE/G,MAAM,IAAI,GAAG,GAAG,SAAS,CAAC;IAE1B,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,QAAQ,EAAE,CAAC;CAChD;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,YAAY;IACxD;;SAEK;IACL,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;SAEK;IACL,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtB;;;OAGG;IACH,WAAW,IAAI,GAAG,EAAE,CAAC;IAErB;;OAEG;IACH,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAErC;;;;OAIG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IAEzC;;OAEG;IACH,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI,CAAC;IACjE,IAAI,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC;IAElD,SAAS,IAAI,kBAAkB,CAAC;IAEhC,MAAM,IAAI,GAAG,GAAG,SAAS,CAAC;CAC3B"}
package/dest/util.d.ts CHANGED
@@ -2,11 +2,15 @@ import { type AztecKVStore } from '@aztec/kv-store';
2
2
  import { type DataStoreConfig } from '@aztec/kv-store/config';
3
3
  import type { GossipSub } from '@chainsafe/libp2p-gossipsub';
4
4
  import { type PeerId } from '@libp2p/interface';
5
+ import { type ConnectionManager } from '@libp2p/interface-internal';
5
6
  import type { Libp2p } from 'libp2p';
6
7
  import { type P2PConfig } from './config.js';
7
8
  export interface PubSubLibp2p extends Libp2p {
8
9
  services: {
9
10
  pubsub: GossipSub;
11
+ components: {
12
+ connectionManager: ConnectionManager;
13
+ };
10
14
  };
11
15
  }
12
16
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAuB,MAAM,iBAAiB,CAAC;AACzE,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,EAAE,KAAK,MAAM,EAAmB,MAAM,mBAAmB,CAAC;AAGjE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,YAAa,SAAQ,MAAM;IAC1C,QAAQ,EAAE;QACR,MAAM,EAAE,SAAS,CAAC;KACnB,CAAC;CACH;AAED;;;;;;;6CAO6C;AAC7C,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CASnF;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAoB9F;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAInD;AAED,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAYhF;AAcD,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,SAAS,GAAG,eAAe,GACnC,OAAO,CAAC,SAAS,GAAG,eAAe,CAAC,CA6CtC;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBrH;AAED;;;;GAIG;AACH,wBAAsB,gCAAgC,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAS1F"}
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAuB,MAAM,iBAAiB,CAAC;AACzE,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,EAAE,KAAK,MAAM,EAAmB,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAGpE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,YAAa,SAAQ,MAAM;IAC1C,QAAQ,EAAE;QACR,MAAM,EAAE,SAAS,CAAC;QAClB,UAAU,EAAE;YACV,iBAAiB,EAAE,iBAAiB,CAAC;SACtC,CAAC;KACH,CAAC;CACH;AAED;;;;;;;6CAO6C;AAC7C,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CASnF;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAoB9F;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAInD;AAED,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAYhF;AAcD,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,SAAS,GAAG,eAAe,GACnC,OAAO,CAAC,SAAS,GAAG,eAAe,CAAC,CA6CtC;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBrH;AAED;;;;GAIG;AACH,wBAAsB,gCAAgC,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAS1F"}
package/dest/util.js CHANGED
@@ -148,4 +148,4 @@ export async function createLibP2PPeerIdFromPrivateKey(privateKey) {
148
148
  const asLibp2pPrivateKey = await unmarshalPrivateKey(new Uint8Array(Buffer.from(privateKey, 'hex')));
149
149
  return await createFromPrivKey(asLibp2pPrivateKey);
150
150
  }
151
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy91dGlsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUlBLE9BQU8sRUFBRSxlQUFlLEVBQUUsaUJBQWlCLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUU5RixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBV3ZDOzs7Ozs7OzZDQU82QztBQUM3QyxNQUFNLFVBQVUsa0JBQWtCLENBQUMsT0FBZSxFQUFFLFFBQXVCO0lBQ3pFLE1BQU0sQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEdBQUcsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBRXRELE1BQU0sZUFBZSxHQUFHLHlCQUF5QixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3hELElBQUksZUFBZSxLQUFLLEtBQUssRUFBRSxDQUFDO1FBQzlCLE1BQU0sSUFBSSxLQUFLLENBQUMsMkRBQTJELENBQUMsQ0FBQztJQUMvRSxDQUFDO0lBRUQsT0FBTyxJQUFJLGVBQWUsSUFBSSxJQUFJLElBQUksUUFBUSxJQUFJLElBQUksRUFBRSxDQUFDO0FBQzNELENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsT0FBZSxFQUFFLGlCQUEwQjtJQUMxRSxJQUFJLElBQVksQ0FBQztJQUNqQixJQUFJLElBQVksQ0FBQztJQUVqQixJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUM1QiwyQ0FBMkM7UUFDM0MsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBQ3BELElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNYLE1BQU0sSUFBSSxLQUFLLENBQUMsK0JBQStCLE9BQU8sb0NBQW9DLENBQUMs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
151
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy91dGlsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUlBLE9BQU8sRUFBRSxlQUFlLEVBQUUsaUJBQWlCLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUc5RixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBY3ZDOzs7Ozs7OzZDQU82QztBQUM3QyxNQUFNLFVBQVUsa0JBQWtCLENBQUMsT0FBZSxFQUFFLFFBQXVCO0lBQ3pFLE1BQU0sQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEdBQUcsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBRXRELE1BQU0sZUFBZSxHQUFHLHlCQUF5QixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3hELElBQUksZUFBZSxLQUFLLEtBQUssRUFBRSxDQUFDO1FBQzlCLE1BQU0sSUFBSSxLQUFLLENBQUMsMkRBQTJELENBQUMsQ0FBQztJQUMvRSxDQUFDO0lBRUQsT0FBTyxJQUFJLGVBQWUsSUFBSSxJQUFJLElBQUksUUFBUSxJQUFJLElBQUksRUFBRSxDQUFDO0FBQzNELENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsT0FBZSxFQUFFLGlCQUEwQjtJQUMxRSxJQUFJLElBQVksQ0FBQztJQUNqQixJQUFJLElBQVksQ0FBQztJQUVqQixJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUM1QiwyQ0FBMkM7UUFDM0MsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBQ3BELElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNYLE1BQU0sSUFBSSxLQUFLLENBQUMsK0JBQStCLE9BQU8sb0NBQW9DLENBQUMs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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/p2p",
3
- "version": "0.71.0",
3
+ "version": "0.72.1",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -63,12 +63,12 @@
63
63
  ]
64
64
  },
65
65
  "dependencies": {
66
- "@aztec/circuit-types": "0.71.0",
67
- "@aztec/circuits.js": "0.71.0",
68
- "@aztec/epoch-cache": "0.71.0",
69
- "@aztec/foundation": "0.71.0",
70
- "@aztec/kv-store": "0.71.0",
71
- "@aztec/telemetry-client": "0.71.0",
66
+ "@aztec/circuit-types": "0.72.1",
67
+ "@aztec/circuits.js": "0.72.1",
68
+ "@aztec/epoch-cache": "0.72.1",
69
+ "@aztec/foundation": "0.72.1",
70
+ "@aztec/kv-store": "0.72.1",
71
+ "@aztec/telemetry-client": "0.72.1",
72
72
  "@chainsafe/discv5": "9.0.0",
73
73
  "@chainsafe/enr": "3.0.0",
74
74
  "@chainsafe/libp2p-gossipsub": "13.0.0",
@@ -109,7 +109,7 @@
109
109
  "ts-node": "^10.9.1",
110
110
  "typescript": "^5.0.4",
111
111
  "uint8arrays": "^5.0.3",
112
- "viem": "^2.7.15"
112
+ "viem": "2.22.8"
113
113
  },
114
114
  "files": [
115
115
  "dest",
@@ -32,7 +32,7 @@ import { type AttestationPool } from '../mem_pools/attestation_pool/attestation_
32
32
  import { type EpochProofQuotePool } from '../mem_pools/epoch_proof_quote_pool/epoch_proof_quote_pool.js';
33
33
  import { type MemPools } from '../mem_pools/interface.js';
34
34
  import { type TxPool } from '../mem_pools/tx_pool/index.js';
35
- import { TX_REQ_PROTOCOL } from '../services/reqresp/interface.js';
35
+ import { ReqRespSubProtocol } from '../services/reqresp/interface.js';
36
36
  import type { P2PService } from '../services/service.js';
37
37
 
38
38
  /**
@@ -444,9 +444,9 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
444
444
  * @param txHashes - The hashes of the transactions to request.
445
445
  * @returns A promise that resolves to an array of transactions or undefined.
446
446
  */
447
- public requestTxs(txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
448
- const requestPromises = txHashes.map(txHash => this.requestTxByHash(txHash));
449
- return Promise.all(requestPromises);
447
+ public async requestTxs(txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
448
+ const res = await this.p2pService.sendBatchRequest(ReqRespSubProtocol.TX, txHashes);
449
+ return Promise.resolve(res ?? []);
450
450
  }
451
451
 
452
452
  /**
@@ -459,7 +459,7 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
459
459
  * @returns A promise that resolves to a transaction or undefined.
460
460
  */
461
461
  public async requestTxByHash(txHash: TxHash): Promise<Tx | undefined> {
462
- const tx = await this.p2pService.sendRequest(TX_REQ_PROTOCOL, txHash);
462
+ const tx = await this.p2pService.sendRequest(ReqRespSubProtocol.TX, txHash);
463
463
 
464
464
  if (tx) {
465
465
  this.log.debug(`Received tx ${txHash.toString()} from peer`);
@@ -9,14 +9,14 @@ import { makeHeader } from '@aztec/circuits.js/testing';
9
9
  import { type Secp256k1Signer } from '@aztec/foundation/crypto';
10
10
  import { Fr } from '@aztec/foundation/fields';
11
11
 
12
- import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
12
+ import { type LocalAccount, generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
13
13
 
14
14
  /** Generate Account
15
15
  *
16
16
  * Create a random signer
17
17
  * @returns A random viem signer
18
18
  */
19
- export const generateAccount = () => {
19
+ export const generateAccount = (): LocalAccount => {
20
20
  const privateKey = generatePrivateKey();
21
21
  return privateKeyToAccount(privateKey);
22
22
  };
@@ -283,7 +283,6 @@ export class AztecKVTxPool implements TxPool {
283
283
  const archivedTx: Tx = new Tx(
284
284
  tx.data,
285
285
  ClientIvcProof.empty(),
286
- tx.unencryptedLogs,
287
286
  tx.contractClassLogs,
288
287
  tx.enqueuedPublicFunctionCalls,
289
288
  tx.publicTeardownFunctionCall,
@@ -6,6 +6,7 @@ import {
6
6
  type WorldStateSynchronizer,
7
7
  } from '@aztec/circuit-types';
8
8
  import { type EpochCache } from '@aztec/epoch-cache';
9
+ import { timesParallel } from '@aztec/foundation/collection';
9
10
  import { type DataStoreConfig } from '@aztec/kv-store/config';
10
11
  import { openTmpStore } from '@aztec/kv-store/lmdb';
11
12
  import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
@@ -26,17 +27,15 @@ import { type BootnodeConfig, type P2PConfig } from '../config.js';
26
27
  import { type MemPools } from '../mem_pools/interface.js';
27
28
  import { DiscV5Service } from '../services/discv5/discV5_service.js';
28
29
  import { LibP2PService } from '../services/libp2p/libp2p_service.js';
29
- import { type PeerManager } from '../services/peer_manager.js';
30
+ import { type PeerScoring } from '../services/peer-manager/peer_scoring.js';
30
31
  import { type P2PReqRespConfig } from '../services/reqresp/config.js';
31
- import { pingHandler, statusHandler } from '../services/reqresp/handlers.js';
32
32
  import {
33
- PING_PROTOCOL,
33
+ ReqRespSubProtocol,
34
34
  type ReqRespSubProtocolHandlers,
35
35
  type ReqRespSubProtocolValidators,
36
- STATUS_PROTOCOL,
37
- TX_REQ_PROTOCOL,
38
36
  noopValidator,
39
37
  } from '../services/reqresp/interface.js';
38
+ import { pingHandler, statusHandler } from '../services/reqresp/protocols/index.js';
40
39
  import { ReqResp } from '../services/reqresp/reqresp.js';
41
40
  import { type PubSubLibp2p } from '../util.js';
42
41
 
@@ -151,25 +150,29 @@ export type ReqRespNode = {
151
150
 
152
151
  // Mock sub protocol handlers
153
152
  export const MOCK_SUB_PROTOCOL_HANDLERS: ReqRespSubProtocolHandlers = {
154
- [PING_PROTOCOL]: pingHandler,
155
- [STATUS_PROTOCOL]: statusHandler,
156
- [TX_REQ_PROTOCOL]: (_msg: any) => Promise.resolve(Buffer.from('tx')),
153
+ [ReqRespSubProtocol.PING]: pingHandler,
154
+ [ReqRespSubProtocol.STATUS]: statusHandler,
155
+ [ReqRespSubProtocol.TX]: (_msg: any) => Promise.resolve(Buffer.from('tx')),
156
+ [ReqRespSubProtocol.GOODBYE]: (_msg: any) => Promise.resolve(Buffer.from('goodbye')),
157
+ [ReqRespSubProtocol.BLOCK]: (_msg: any) => Promise.resolve(Buffer.from('block')),
157
158
  };
158
159
 
159
160
  // By default, all requests are valid
160
161
  // If you want to test an invalid response, you can override the validator
161
162
  export const MOCK_SUB_PROTOCOL_VALIDATORS: ReqRespSubProtocolValidators = {
162
- [PING_PROTOCOL]: noopValidator,
163
- [STATUS_PROTOCOL]: noopValidator,
164
- [TX_REQ_PROTOCOL]: noopValidator,
163
+ [ReqRespSubProtocol.PING]: noopValidator,
164
+ [ReqRespSubProtocol.STATUS]: noopValidator,
165
+ [ReqRespSubProtocol.TX]: noopValidator,
166
+ [ReqRespSubProtocol.GOODBYE]: noopValidator,
167
+ [ReqRespSubProtocol.BLOCK]: noopValidator,
165
168
  };
166
169
 
167
170
  /**
168
171
  * @param numberOfNodes - the number of nodes to create
169
172
  * @returns An array of the created nodes
170
173
  */
171
- export const createNodes = async (peerManager: PeerManager, numberOfNodes: number): Promise<ReqRespNode[]> => {
172
- return await Promise.all(Array.from({ length: numberOfNodes }, () => createReqResp(peerManager)));
174
+ export const createNodes = (peerScoring: PeerScoring, numberOfNodes: number): Promise<ReqRespNode[]> => {
175
+ return timesParallel(numberOfNodes, () => createReqResp(peerScoring));
173
176
  };
174
177
 
175
178
  export const startNodes = async (
@@ -183,22 +186,18 @@ export const startNodes = async (
183
186
  };
184
187
 
185
188
  export const stopNodes = async (nodes: ReqRespNode[]): Promise<void> => {
186
- const stopPromises = [];
187
- for (const node of nodes) {
188
- stopPromises.push(node.req.stop());
189
- stopPromises.push(node.p2p.stop());
190
- }
189
+ const stopPromises = nodes.flatMap(node => [node.req.stop(), node.p2p.stop()]);
191
190
  await Promise.all(stopPromises);
192
191
  };
193
192
 
194
193
  // Create a req resp node, exposing the underlying p2p node
195
- export const createReqResp = async (peerManager: PeerManager): Promise<ReqRespNode> => {
194
+ export const createReqResp = async (peerScoring: PeerScoring): Promise<ReqRespNode> => {
196
195
  const p2p = await createLibp2pNode();
197
196
  const config: P2PReqRespConfig = {
198
197
  overallRequestTimeoutMs: 4000,
199
198
  individualRequestTimeoutMs: 2000,
200
199
  };
201
- const req = new ReqResp(config, p2p, peerManager);
200
+ const req = new ReqResp(config, p2p, peerScoring);
202
201
  return {
203
202
  p2p,
204
203
  req,
@@ -61,6 +61,19 @@ export class DummyP2PService implements P2PService {
61
61
  return Promise.resolve(undefined);
62
62
  }
63
63
 
64
+ /**
65
+ * Sends a batch request to a peer.
66
+ * @param _protocol - The protocol to send the request on.
67
+ * @param _requests - The requests to send.
68
+ * @returns The responses from the peer, otherwise undefined.
69
+ */
70
+ public sendBatchRequest<Protocol extends ReqRespSubProtocol>(
71
+ _protocol: Protocol,
72
+ _requests: InstanceType<SubProtocolMap[Protocol]['request']>[],
73
+ ): Promise<InstanceType<SubProtocolMap[Protocol]['response']>[]> {
74
+ return Promise.resolve([]);
75
+ }
76
+
64
77
  /**
65
78
  * Returns the ENR of the peer.
66
79
  * @returns The ENR of the peer, otherwise undefined.
@@ -12,7 +12,7 @@ import {
12
12
  type RawGossipMessage,
13
13
  TopicTypeMap,
14
14
  Tx,
15
- TxHash,
15
+ type TxHash,
16
16
  type TxValidationResult,
17
17
  type WorldStateSynchronizer,
18
18
  getTopicTypeForClientType,
@@ -38,6 +38,7 @@ import { noise } from '@chainsafe/libp2p-noise';
38
38
  import { yamux } from '@chainsafe/libp2p-yamux';
39
39
  import { identify } from '@libp2p/identify';
40
40
  import { type Message, type PeerId, TopicValidatorResult } from '@libp2p/interface';
41
+ import { type ConnectionManager } from '@libp2p/interface-internal';
41
42
  import '@libp2p/kad-dht';
42
43
  import { mplex } from '@libp2p/mplex';
43
44
  import { tcp } from '@libp2p/tcp';
@@ -56,18 +57,11 @@ import {
56
57
  import { type PubSubLibp2p, convertToMultiaddr } from '../../util.js';
57
58
  import { AztecDatastore } from '../data_store.js';
58
59
  import { SnappyTransform, fastMsgIdFn, getMsgIdFn, msgIdToStrFn } from '../encoding.js';
59
- import { PeerManager } from '../peer_manager.js';
60
- import { pingHandler, statusHandler } from '../reqresp/handlers.js';
61
- import {
62
- DEFAULT_SUB_PROTOCOL_HANDLERS,
63
- DEFAULT_SUB_PROTOCOL_VALIDATORS,
64
- PING_PROTOCOL,
65
- type ReqRespSubProtocol,
66
- type ReqRespSubProtocolHandlers,
67
- STATUS_PROTOCOL,
68
- type SubProtocolMap,
69
- TX_REQ_PROTOCOL,
70
- } from '../reqresp/interface.js';
60
+ import { PeerManager } from '../peer-manager/peer_manager.js';
61
+ import { PeerScoring } from '../peer-manager/peer_scoring.js';
62
+ import { DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol, type SubProtocolMap } from '../reqresp/interface.js';
63
+ import { reqGoodbyeHandler } from '../reqresp/protocols/goodbye.js';
64
+ import { pingHandler, reqRespBlockHandler, reqRespTxHandler, statusHandler } from '../reqresp/protocols/index.js';
71
65
  import { ReqResp } from '../reqresp/reqresp.js';
72
66
  import type { P2PService, PeerDiscoveryService } from '../service.js';
73
67
  import { GossipSubEvent } from '../types.js';
@@ -117,21 +111,32 @@ export class LibP2PService<T extends P2PClientType> extends WithTracer implement
117
111
  private peerDiscoveryService: PeerDiscoveryService,
118
112
  private mempools: MemPools<T>,
119
113
  private l2BlockSource: L2BlockSource,
120
- private epochCache: EpochCache,
114
+ epochCache: EpochCache,
121
115
  private proofVerifier: ClientProtocolCircuitVerifier,
122
116
  private worldStateSynchronizer: WorldStateSynchronizer,
123
- private telemetry: TelemetryClient,
124
- private requestResponseHandlers: ReqRespSubProtocolHandlers = DEFAULT_SUB_PROTOCOL_HANDLERS,
117
+ telemetry: TelemetryClient,
125
118
  private logger = createLogger('p2p:libp2p_service'),
126
119
  ) {
127
120
  super(telemetry, 'LibP2PService');
128
121
 
129
- this.peerManager = new PeerManager(node, peerDiscoveryService, config, telemetry, logger);
122
+ const peerScoring = new PeerScoring(config);
123
+ this.reqresp = new ReqResp(config, node, peerScoring);
124
+
125
+ this.peerManager = new PeerManager(
126
+ node,
127
+ peerDiscoveryService,
128
+ config,
129
+ telemetry,
130
+ logger,
131
+ peerScoring,
132
+ this.reqresp,
133
+ );
134
+
135
+ // Update gossipsub score params
130
136
  this.node.services.pubsub.score.params.appSpecificScore = (peerId: string) => {
131
137
  return this.peerManager.getPeerScore(peerId);
132
138
  };
133
139
  this.node.services.pubsub.score.params.appSpecificWeight = 10;
134
- this.reqresp = new ReqResp(config, node, this.peerManager);
135
140
 
136
141
  this.attestationValidator = new AttestationValidator(epochCache);
137
142
  this.blockProposalValidator = new BlockProposalValidator(epochCache);
@@ -145,95 +150,6 @@ export class LibP2PService<T extends P2PClientType> extends WithTracer implement
145
150
  };
146
151
  }
147
152
 
148
- /**
149
- * Starts the LibP2P service.
150
- * @returns An empty promise.
151
- */
152
- public async start() {
153
- // Check if service is already started
154
- if (this.node.status === 'started') {
155
- throw new Error('P2P service already started');
156
- }
157
-
158
- // Get listen & announce addresses for logging
159
- const { tcpListenAddress, tcpAnnounceAddress } = this.config;
160
- if (!tcpAnnounceAddress) {
161
- throw new Error('Announce address not provided.');
162
- }
163
- const announceTcpMultiaddr = convertToMultiaddr(tcpAnnounceAddress, 'tcp');
164
-
165
- // Start job queue, peer discovery service and libp2p node
166
- this.jobQueue.start();
167
- await this.peerDiscoveryService.start();
168
- await this.node.start();
169
-
170
- // Subscribe to standard GossipSub topics by default
171
- for (const topic of getTopicTypeForClientType(this.clientType)) {
172
- this.subscribeToTopic(TopicTypeMap[topic].p2pTopic);
173
- }
174
-
175
- // Add p2p topic validators
176
- // As they are stored within a kv pair, there is no need to register them conditionally
177
- // based on the client type
178
- const topicValidators = {
179
- [Tx.p2pTopic]: this.validatePropagatedTxFromMessage.bind(this),
180
- [BlockAttestation.p2pTopic]: this.validatePropagatedAttestationFromMessage.bind(this),
181
- [BlockProposal.p2pTopic]: this.validatePropagatedBlockFromMessage.bind(this),
182
- [EpochProofQuote.p2pTopic]: this.validatePropagatedEpochProofQuoteFromMessage.bind(this),
183
- };
184
- for (const [topic, validator] of Object.entries(topicValidators)) {
185
- this.node.services.pubsub.topicValidators.set(topic, validator);
186
- }
187
-
188
- // add GossipSub listener
189
- this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.handleGossipSubEvent.bind(this));
190
-
191
- // Start running promise for peer discovery
192
- this.discoveryRunningPromise = new RunningPromise(
193
- () => this.peerManager.heartbeat(),
194
- this.logger,
195
- this.config.peerCheckIntervalMS,
196
- );
197
- this.discoveryRunningPromise.start();
198
-
199
- // Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
200
- const reqrespSubProtocolValidators = {
201
- ...DEFAULT_SUB_PROTOCOL_VALIDATORS,
202
- [TX_REQ_PROTOCOL]: this.validateRequestedTx.bind(this),
203
- };
204
- await this.reqresp.start(this.requestResponseHandlers, reqrespSubProtocolValidators);
205
- this.logger.info(`Started P2P service`, {
206
- listen: tcpListenAddress,
207
- announce: announceTcpMultiaddr,
208
- peerId: this.node.peerId.toString(),
209
- });
210
- }
211
-
212
- /**
213
- * Stops the LibP2P service.
214
- * @returns An empty promise.
215
- */
216
- public async stop() {
217
- // Remove gossip sub listener
218
- this.node.services.pubsub.removeEventListener(GossipSubEvent.MESSAGE, this.handleGossipSubEvent.bind(this));
219
-
220
- // Stop peer manager
221
- this.logger.debug('Stopping peer manager...');
222
- this.peerManager.stop();
223
-
224
- this.logger.debug('Stopping job queue...');
225
- await this.jobQueue.end();
226
- this.logger.debug('Stopping running promise...');
227
- await this.discoveryRunningPromise?.stop();
228
- this.logger.debug('Stopping peer discovery service...');
229
- await this.peerDiscoveryService.stop();
230
- this.logger.debug('Request response service stopped...');
231
- await this.reqresp.stop();
232
- this.logger.debug('Stopping LibP2P...');
233
- await this.stopLibP2P();
234
- this.logger.info('LibP2P service stopped');
235
- }
236
-
237
153
  /**
238
154
  * Creates an instance of the LibP2P service.
239
155
  * @param config - The configuration to use when creating the service.
@@ -333,28 +249,12 @@ export class LibP2PService<T extends P2PClientType> extends WithTracer implement
333
249
  },
334
250
  }),
335
251
  }) as (components: GossipSubComponents) => GossipSub,
252
+ components: (components: { connectionManager: ConnectionManager }) => ({
253
+ connectionManager: components.connectionManager,
254
+ }),
336
255
  },
337
256
  });
338
257
 
339
- // Create request response protocol handlers
340
- /**
341
- * Handler for tx requests
342
- * @param msg - the tx request message
343
- * @returns the tx response message
344
- */
345
- const txHandler = (msg: Buffer): Promise<Buffer> => {
346
- const txHash = TxHash.fromBuffer(msg);
347
- const foundTx = mempools.txPool.getTxByHash(txHash);
348
- const buf = foundTx ? foundTx.toBuffer() : Buffer.alloc(0);
349
- return Promise.resolve(buf);
350
- };
351
-
352
- const requestResponseHandlers = {
353
- [PING_PROTOCOL]: pingHandler,
354
- [STATUS_PROTOCOL]: statusHandler,
355
- [TX_REQ_PROTOCOL]: txHandler,
356
- };
357
-
358
258
  return new LibP2PService(
359
259
  clientType,
360
260
  config,
@@ -366,10 +266,112 @@ export class LibP2PService<T extends P2PClientType> extends WithTracer implement
366
266
  proofVerifier,
367
267
  worldStateSynchronizer,
368
268
  telemetry,
369
- requestResponseHandlers,
370
269
  );
371
270
  }
372
271
 
272
+ /**
273
+ * Starts the LibP2P service.
274
+ * @returns An empty promise.
275
+ */
276
+ public async start() {
277
+ // Check if service is already started
278
+ if (this.node.status === 'started') {
279
+ throw new Error('P2P service already started');
280
+ }
281
+
282
+ // Get listen & announce addresses for logging
283
+ const { tcpListenAddress, tcpAnnounceAddress } = this.config;
284
+ if (!tcpAnnounceAddress) {
285
+ throw new Error('Announce address not provided.');
286
+ }
287
+ const announceTcpMultiaddr = convertToMultiaddr(tcpAnnounceAddress, 'tcp');
288
+
289
+ // Start job queue, peer discovery service and libp2p node
290
+ this.jobQueue.start();
291
+ await this.peerDiscoveryService.start();
292
+ await this.node.start();
293
+
294
+ // Subscribe to standard GossipSub topics by default
295
+ for (const topic of getTopicTypeForClientType(this.clientType)) {
296
+ this.subscribeToTopic(TopicTypeMap[topic].p2pTopic);
297
+ }
298
+
299
+ // Create request response protocol handlers
300
+ const txHandler = reqRespTxHandler(this.mempools);
301
+ const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
302
+ const blockHandler = reqRespBlockHandler(this.l2BlockSource);
303
+
304
+ const requestResponseHandlers = {
305
+ [ReqRespSubProtocol.PING]: pingHandler,
306
+ [ReqRespSubProtocol.STATUS]: statusHandler,
307
+ [ReqRespSubProtocol.TX]: txHandler.bind(this),
308
+ [ReqRespSubProtocol.GOODBYE]: goodbyeHandler.bind(this),
309
+ [ReqRespSubProtocol.BLOCK]: blockHandler.bind(this),
310
+ };
311
+
312
+ // Add p2p topic validators
313
+ // As they are stored within a kv pair, there is no need to register them conditionally
314
+ // based on the client type
315
+ const topicValidators = {
316
+ [Tx.p2pTopic]: this.validatePropagatedTxFromMessage.bind(this),
317
+ [BlockAttestation.p2pTopic]: this.validatePropagatedAttestationFromMessage.bind(this),
318
+ [BlockProposal.p2pTopic]: this.validatePropagatedBlockFromMessage.bind(this),
319
+ [EpochProofQuote.p2pTopic]: this.validatePropagatedEpochProofQuoteFromMessage.bind(this),
320
+ };
321
+ for (const [topic, validator] of Object.entries(topicValidators)) {
322
+ this.node.services.pubsub.topicValidators.set(topic, validator);
323
+ }
324
+
325
+ // add GossipSub listener
326
+ this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.handleGossipSubEvent.bind(this));
327
+
328
+ // Start running promise for peer discovery
329
+ this.discoveryRunningPromise = new RunningPromise(
330
+ () => this.peerManager.heartbeat(),
331
+ this.logger,
332
+ this.config.peerCheckIntervalMS,
333
+ );
334
+ this.discoveryRunningPromise.start();
335
+
336
+ // Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
337
+ const reqrespSubProtocolValidators = {
338
+ ...DEFAULT_SUB_PROTOCOL_VALIDATORS,
339
+ // TODO(#11336): A request validator for blocks
340
+ [ReqRespSubProtocol.TX]: this.validateRequestedTx.bind(this),
341
+ };
342
+ await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
343
+ this.logger.info(`Started P2P service`, {
344
+ listen: tcpListenAddress,
345
+ announce: announceTcpMultiaddr,
346
+ peerId: this.node.peerId.toString(),
347
+ });
348
+ }
349
+
350
+ /**
351
+ * Stops the LibP2P service.
352
+ * @returns An empty promise.
353
+ */
354
+ public async stop() {
355
+ // Remove gossip sub listener
356
+ this.node.services.pubsub.removeEventListener(GossipSubEvent.MESSAGE, this.handleGossipSubEvent.bind(this));
357
+
358
+ // Stop peer manager
359
+ this.logger.debug('Stopping peer manager...');
360
+ await this.peerManager.stop();
361
+
362
+ this.logger.debug('Stopping job queue...');
363
+ await this.jobQueue.end();
364
+ this.logger.debug('Stopping running promise...');
365
+ await this.discoveryRunningPromise?.stop();
366
+ this.logger.debug('Stopping peer discovery service...');
367
+ await this.peerDiscoveryService.stop();
368
+ this.logger.debug('Request response service stopped...');
369
+ await this.reqresp.stop();
370
+ this.logger.debug('Stopping LibP2P...');
371
+ await this.stopLibP2P();
372
+ this.logger.info('LibP2P service stopped');
373
+ }
374
+
373
375
  public getPeers(includePending?: boolean): PeerInfo[] {
374
376
  return this.peerManager.getPeers(includePending);
375
377
  }
@@ -398,6 +400,19 @@ export class LibP2PService<T extends P2PClientType> extends WithTracer implement
398
400
  return this.reqresp.sendRequest(protocol, request);
399
401
  }
400
402
 
403
+ /**
404
+ * Send a batch of requests to peers, and return the responses
405
+ * @param protocol - The request response protocol to use
406
+ * @param requests - The requests to send to the peers
407
+ * @returns The responses to the requests
408
+ */
409
+ sendBatchRequest<SubProtocol extends ReqRespSubProtocol>(
410
+ protocol: SubProtocol,
411
+ requests: InstanceType<SubProtocolMap[SubProtocol]['request']>[],
412
+ ): Promise<InstanceType<SubProtocolMap[SubProtocol]['response']>[] | undefined> {
413
+ return this.reqresp.sendBatchRequest(protocol, requests);
414
+ }
415
+
401
416
  /**
402
417
  * Get the ENR of the node
403
418
  * @returns The ENR of the node
@@ -548,7 +563,7 @@ export class LibP2PService<T extends P2PClientType> extends WithTracer implement
548
563
  * In order to perform this check, the tx proof must be verified.
549
564
  *
550
565
  * Note: This function is called from within `ReqResp.sendRequest` as part of the
551
- * TX_REQ_PROTOCOL subprotocol validation.
566
+ * ReqRespSubProtocol.TX subprotocol validation.
552
567
  *
553
568
  * @param requestedTxHash - The hash of the tx that was requested.
554
569
  * @param responseTx - The tx that was received as a response to the request.