@aztec/p2p 1.2.1 → 2.0.0-nightly.20250813

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 (221) hide show
  1. package/dest/client/factory.d.ts +5 -1
  2. package/dest/client/factory.d.ts.map +1 -1
  3. package/dest/client/factory.js +29 -12
  4. package/dest/client/interface.d.ts +8 -13
  5. package/dest/client/interface.d.ts.map +1 -1
  6. package/dest/client/p2p_client.d.ts +18 -22
  7. package/dest/client/p2p_client.d.ts.map +1 -1
  8. package/dest/client/p2p_client.js +86 -83
  9. package/dest/config.d.ts +30 -1
  10. package/dest/config.d.ts.map +1 -1
  11. package/dest/config.js +34 -1
  12. package/dest/index.d.ts +1 -0
  13. package/dest/index.d.ts.map +1 -1
  14. package/dest/index.js +1 -0
  15. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +13 -1
  16. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  17. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  18. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +117 -10
  19. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +4 -1
  20. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
  21. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +22 -1
  22. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +4 -1
  23. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
  24. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +21 -1
  25. package/dest/mem_pools/attestation_pool/mocks.d.ts +1 -2
  26. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  27. package/dest/mem_pools/attestation_pool/mocks.js +2 -10
  28. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +8 -3
  29. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
  30. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +64 -37
  31. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +8 -3
  32. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -1
  33. package/dest/mem_pools/tx_pool/memory_tx_pool.js +18 -10
  34. package/dest/mem_pools/tx_pool/tx_pool.d.ts +11 -2
  35. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
  36. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
  37. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +73 -44
  38. package/dest/msg_validators/attestation_validator/attestation_validator.js +1 -1
  39. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  40. package/dest/msg_validators/tx_validator/block_header_validator.js +2 -2
  41. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  42. package/dest/msg_validators/tx_validator/data_validator.js +35 -59
  43. package/dest/msg_validators/tx_validator/double_spend_validator.js +2 -2
  44. package/dest/msg_validators/tx_validator/gas_validator.js +4 -4
  45. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  46. package/dest/msg_validators/tx_validator/metadata_validator.js +21 -21
  47. package/dest/msg_validators/tx_validator/phases_validator.js +3 -3
  48. package/dest/msg_validators/tx_validator/tx_proof_validator.js +3 -3
  49. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  50. package/dest/services/discv5/discV5_service.js +4 -1
  51. package/dest/services/dummy_service.d.ts +13 -3
  52. package/dest/services/dummy_service.d.ts.map +1 -1
  53. package/dest/services/dummy_service.js +26 -3
  54. package/dest/services/index.d.ts +3 -1
  55. package/dest/services/index.d.ts.map +1 -1
  56. package/dest/services/index.js +3 -1
  57. package/dest/services/libp2p/libp2p_service.d.ts +13 -20
  58. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  59. package/dest/services/libp2p/libp2p_service.js +123 -46
  60. package/dest/services/peer-manager/interface.d.ts +8 -1
  61. package/dest/services/peer-manager/interface.d.ts.map +1 -1
  62. package/dest/services/peer-manager/peer_manager.d.ts +70 -3
  63. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  64. package/dest/services/peer-manager/peer_manager.js +369 -39
  65. package/dest/services/reqresp/config.d.ts +3 -3
  66. package/dest/services/reqresp/config.d.ts.map +1 -1
  67. package/dest/services/reqresp/config.js +3 -3
  68. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +3 -4
  69. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
  70. package/dest/services/reqresp/connection-sampler/connection_sampler.js +35 -52
  71. package/dest/services/reqresp/index.d.ts +2 -1
  72. package/dest/services/reqresp/index.d.ts.map +1 -1
  73. package/dest/services/reqresp/index.js +2 -1
  74. package/dest/services/reqresp/interface.d.ts +61 -10
  75. package/dest/services/reqresp/interface.d.ts.map +1 -1
  76. package/dest/services/reqresp/interface.js +41 -6
  77. package/dest/services/reqresp/protocols/auth.d.ts +43 -0
  78. package/dest/services/reqresp/protocols/auth.d.ts.map +1 -0
  79. package/dest/services/reqresp/protocols/auth.js +71 -0
  80. package/dest/services/reqresp/protocols/block.d.ts +5 -0
  81. package/dest/services/reqresp/protocols/block.d.ts.map +1 -1
  82. package/dest/services/reqresp/protocols/block.js +28 -5
  83. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +30 -0
  84. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -0
  85. package/dest/services/reqresp/protocols/block_txs/bitvector.js +75 -0
  86. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +11 -0
  87. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -0
  88. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +39 -0
  89. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +49 -0
  90. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -0
  91. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +75 -0
  92. package/dest/services/reqresp/protocols/block_txs/index.d.ts +4 -0
  93. package/dest/services/reqresp/protocols/block_txs/index.d.ts.map +1 -0
  94. package/dest/services/reqresp/protocols/block_txs/index.js +3 -0
  95. package/dest/services/reqresp/protocols/goodbye.js +3 -5
  96. package/dest/services/reqresp/protocols/index.d.ts +2 -0
  97. package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
  98. package/dest/services/reqresp/protocols/index.js +2 -0
  99. package/dest/services/reqresp/protocols/status.d.ts +2 -0
  100. package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
  101. package/dest/services/reqresp/protocols/status.js +7 -0
  102. package/dest/services/reqresp/protocols/tx.d.ts +12 -1
  103. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  104. package/dest/services/reqresp/protocols/tx.js +34 -6
  105. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
  106. package/dest/services/reqresp/rate-limiter/rate_limits.js +20 -0
  107. package/dest/services/reqresp/reqresp.d.ts +37 -39
  108. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  109. package/dest/services/reqresp/reqresp.js +220 -220
  110. package/dest/services/reqresp/status.d.ts +8 -3
  111. package/dest/services/reqresp/status.d.ts.map +1 -1
  112. package/dest/services/reqresp/status.js +6 -2
  113. package/dest/services/service.d.ts +10 -10
  114. package/dest/services/service.d.ts.map +1 -1
  115. package/dest/services/tx_collection/config.d.ts +25 -0
  116. package/dest/services/tx_collection/config.d.ts.map +1 -0
  117. package/dest/services/tx_collection/config.js +58 -0
  118. package/dest/services/tx_collection/fast_tx_collection.d.ts +56 -0
  119. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -0
  120. package/dest/services/tx_collection/fast_tx_collection.js +295 -0
  121. package/dest/services/tx_collection/index.d.ts +3 -0
  122. package/dest/services/tx_collection/index.d.ts.map +1 -0
  123. package/dest/services/tx_collection/index.js +2 -0
  124. package/dest/services/tx_collection/instrumentation.d.ts +10 -0
  125. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -0
  126. package/dest/services/tx_collection/instrumentation.js +34 -0
  127. package/dest/services/tx_collection/slow_tx_collection.d.ts +54 -0
  128. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -0
  129. package/dest/services/tx_collection/slow_tx_collection.js +176 -0
  130. package/dest/services/tx_collection/tx_collection.d.ts +109 -0
  131. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -0
  132. package/dest/services/tx_collection/tx_collection.js +127 -0
  133. package/dest/services/tx_collection/tx_collection_sink.d.ts +30 -0
  134. package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -0
  135. package/dest/services/tx_collection/tx_collection_sink.js +81 -0
  136. package/dest/services/tx_collection/tx_source.d.ts +18 -0
  137. package/dest/services/tx_collection/tx_source.d.ts.map +1 -0
  138. package/dest/services/tx_collection/tx_source.js +31 -0
  139. package/dest/services/tx_provider.d.ts +49 -0
  140. package/dest/services/tx_provider.d.ts.map +1 -0
  141. package/dest/services/tx_provider.js +206 -0
  142. package/dest/services/{tx_collect_instrumentation.d.ts → tx_provider_instrumentation.d.ts} +2 -2
  143. package/dest/services/tx_provider_instrumentation.d.ts.map +1 -0
  144. package/dest/services/{tx_collect_instrumentation.js → tx_provider_instrumentation.js} +5 -5
  145. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  146. package/dest/test-helpers/make-test-p2p-clients.js +4 -3
  147. package/dest/test-helpers/mock-pubsub.d.ts +2 -1
  148. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  149. package/dest/test-helpers/mock-pubsub.js +2 -1
  150. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  151. package/dest/test-helpers/reqresp-nodes.js +8 -4
  152. package/dest/testbench/p2p_client_testbench_worker.js +11 -5
  153. package/dest/util.d.ts +1 -1
  154. package/dest/util.d.ts.map +1 -1
  155. package/package.json +14 -15
  156. package/src/client/factory.ts +87 -12
  157. package/src/client/interface.ts +19 -15
  158. package/src/client/p2p_client.ts +108 -92
  159. package/src/config.ts +52 -1
  160. package/src/index.ts +1 -0
  161. package/src/mem_pools/attestation_pool/attestation_pool.ts +15 -1
  162. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +155 -4
  163. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +28 -1
  164. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +28 -2
  165. package/src/mem_pools/attestation_pool/mocks.ts +1 -3
  166. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +59 -41
  167. package/src/mem_pools/tx_pool/memory_tx_pool.ts +19 -9
  168. package/src/mem_pools/tx_pool/tx_pool.ts +7 -2
  169. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +63 -40
  170. package/src/msg_validators/attestation_validator/attestation_validator.ts +1 -1
  171. package/src/msg_validators/tx_validator/block_header_validator.ts +2 -2
  172. package/src/msg_validators/tx_validator/data_validator.ts +36 -27
  173. package/src/msg_validators/tx_validator/double_spend_validator.ts +2 -2
  174. package/src/msg_validators/tx_validator/gas_validator.ts +4 -4
  175. package/src/msg_validators/tx_validator/metadata_validator.ts +22 -28
  176. package/src/msg_validators/tx_validator/phases_validator.ts +2 -2
  177. package/src/msg_validators/tx_validator/tx_proof_validator.ts +2 -2
  178. package/src/services/discv5/discV5_service.ts +4 -1
  179. package/src/services/dummy_service.ts +44 -4
  180. package/src/services/index.ts +3 -1
  181. package/src/services/libp2p/libp2p_service.ts +147 -55
  182. package/src/services/peer-manager/interface.ts +10 -1
  183. package/src/services/peer-manager/peer_manager.ts +441 -41
  184. package/src/services/reqresp/config.ts +3 -3
  185. package/src/services/reqresp/connection-sampler/connection_sampler.ts +38 -63
  186. package/src/services/reqresp/index.ts +2 -0
  187. package/src/services/reqresp/interface.ts +63 -17
  188. package/src/services/reqresp/protocols/auth.ts +83 -0
  189. package/src/services/reqresp/protocols/block.ts +24 -3
  190. package/src/services/reqresp/protocols/block_txs/bitvector.ts +90 -0
  191. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +53 -0
  192. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +79 -0
  193. package/src/services/reqresp/protocols/block_txs/index.ts +3 -0
  194. package/src/services/reqresp/protocols/goodbye.ts +3 -3
  195. package/src/services/reqresp/protocols/index.ts +2 -0
  196. package/src/services/reqresp/protocols/status.ts +20 -0
  197. package/src/services/reqresp/protocols/tx.ts +35 -6
  198. package/src/services/reqresp/rate-limiter/rate_limits.ts +20 -0
  199. package/src/services/reqresp/reqresp.ts +294 -264
  200. package/src/services/reqresp/status.ts +9 -3
  201. package/src/services/service.ts +23 -14
  202. package/src/services/tx_collection/config.ts +84 -0
  203. package/src/services/tx_collection/fast_tx_collection.ts +338 -0
  204. package/src/services/tx_collection/index.ts +2 -0
  205. package/src/services/tx_collection/instrumentation.ts +43 -0
  206. package/src/services/tx_collection/slow_tx_collection.ts +232 -0
  207. package/src/services/tx_collection/tx_collection.ts +214 -0
  208. package/src/services/tx_collection/tx_collection_sink.ts +98 -0
  209. package/src/services/tx_collection/tx_source.ts +37 -0
  210. package/src/services/tx_provider.ts +215 -0
  211. package/src/services/{tx_collect_instrumentation.ts → tx_provider_instrumentation.ts} +5 -5
  212. package/src/test-helpers/make-test-p2p-clients.ts +4 -2
  213. package/src/test-helpers/mock-pubsub.ts +1 -0
  214. package/src/test-helpers/reqresp-nodes.ts +7 -1
  215. package/src/testbench/p2p_client_testbench_worker.ts +9 -2
  216. package/src/util.ts +1 -1
  217. package/dest/services/tx_collect_instrumentation.d.ts.map +0 -1
  218. package/dest/services/tx_collector.d.ts +0 -23
  219. package/dest/services/tx_collector.d.ts.map +0 -1
  220. package/dest/services/tx_collector.js +0 -95
  221. package/src/services/tx_collector.ts +0 -134
@@ -1,9 +1,11 @@
1
1
  import type { EpochCacheInterface } from '@aztec/epoch-cache';
2
2
  import { type Logger, createLogger } from '@aztec/foundation/log';
3
+ import { DateProvider } from '@aztec/foundation/timer';
3
4
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
4
5
  import type { DataStoreConfig } from '@aztec/kv-store/config';
5
- import { createStore } from '@aztec/kv-store/lmdb-v2';
6
+ import { AztecLMDBStoreV2, createStore } from '@aztec/kv-store/lmdb-v2';
6
7
  import type { L2BlockSource } from '@aztec/stdlib/block';
8
+ import type { ChainConfig } from '@aztec/stdlib/config';
7
9
  import type { ContractDataSource } from '@aztec/stdlib/contract';
8
10
  import type { ClientProtocolCircuitVerifier, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
9
11
  import { P2PClientType } from '@aztec/stdlib/p2p';
@@ -17,6 +19,8 @@ import type { MemPools } from '../mem_pools/interface.js';
17
19
  import { AztecKVTxPool, type TxPool } from '../mem_pools/tx_pool/index.js';
18
20
  import { DummyP2PService } from '../services/dummy_service.js';
19
21
  import { LibP2PService } from '../services/index.js';
22
+ import { TxCollection } from '../services/tx_collection/tx_collection.js';
23
+ import { type TxSource, createNodeRpcTxSources } from '../services/tx_collection/tx_source.js';
20
24
  import { configureP2PClientAddresses, createLibP2PPeerIdFromPrivateKey, getPeerIdPrivateKey } from '../util.js';
21
25
 
22
26
  export type P2PClientDeps<T extends P2PClientType> = {
@@ -24,6 +28,7 @@ export type P2PClientDeps<T extends P2PClientType> = {
24
28
  store?: AztecAsyncKVStore;
25
29
  attestationPool?: T extends P2PClientType.Full ? AttestationPool : undefined;
26
30
  logger?: Logger;
31
+ txCollectionNodeSources?: TxSource[];
27
32
  p2pServiceFactory?: (...args: Parameters<(typeof LibP2PService)['new']>) => Promise<LibP2PService<T>>;
28
33
  };
29
34
 
@@ -31,22 +36,28 @@ export const P2P_STORE_NAME = 'p2p';
31
36
  export const P2P_ARCHIVE_STORE_NAME = 'p2p-archive';
32
37
  export const P2P_PEER_STORE_NAME = 'p2p-peers';
33
38
 
34
- export const createP2PClient = async <T extends P2PClientType>(
39
+ export async function createP2PClient<T extends P2PClientType>(
35
40
  clientType: T,
36
- _config: P2PConfig & DataStoreConfig,
41
+ inputConfig: P2PConfig & DataStoreConfig & ChainConfig,
37
42
  archiver: L2BlockSource & ContractDataSource,
38
43
  proofVerifier: ClientProtocolCircuitVerifier,
39
44
  worldStateSynchronizer: WorldStateSynchronizer,
40
45
  epochCache: EpochCacheInterface,
41
46
  packageVersion: string,
47
+ dateProvider: DateProvider = new DateProvider(),
42
48
  telemetry: TelemetryClient = getTelemetryClient(),
43
49
  deps: P2PClientDeps<T> = {},
44
- ) => {
45
- let config = { ..._config, dataStoreMapSizeKB: _config.p2pStoreMapSizeKb ?? _config.dataStoreMapSizeKB };
50
+ ) {
51
+ const config = await configureP2PClientAddresses({
52
+ ...inputConfig,
53
+ dataStoreMapSizeKB: inputConfig.p2pStoreMapSizeKb ?? inputConfig.dataStoreMapSizeKB,
54
+ });
55
+
46
56
  const logger = deps.logger ?? createLogger('p2p');
47
57
  const store = deps.store ?? (await createStore(P2P_STORE_NAME, 2, config, createLogger('p2p:lmdb-v2')));
48
58
  const archive = await createStore(P2P_ARCHIVE_STORE_NAME, 1, config, createLogger('p2p-archive:lmdb-v2'));
49
59
  const peerStore = await createStore(P2P_PEER_STORE_NAME, 1, config, createLogger('p2p-peer:lmdb-v2'));
60
+ const l1Constants = await archiver.getL1Constants();
50
61
 
51
62
  const mempools: MemPools<T> = {
52
63
  txPool:
@@ -63,19 +74,83 @@ export const createP2PClient = async <T extends P2PClientType>(
63
74
  : undefined,
64
75
  };
65
76
 
66
- if (!_config.p2pEnabled) {
77
+ const p2pService = await createP2PService<T>(
78
+ config,
79
+ clientType,
80
+ archiver,
81
+ proofVerifier,
82
+ worldStateSynchronizer,
83
+ epochCache,
84
+ store,
85
+ peerStore,
86
+ mempools,
87
+ deps.p2pServiceFactory,
88
+ packageVersion,
89
+ logger.createChild('libp2p_service'),
90
+ telemetry,
91
+ );
92
+
93
+ const nodeSources = [
94
+ ...createNodeRpcTxSources(config.txCollectionNodeRpcUrls, config),
95
+ ...(deps.txCollectionNodeSources ?? []),
96
+ ];
97
+ if (nodeSources.length > 0) {
98
+ logger.info(`Using ${nodeSources.length} node RPC sources for tx collection.`, {
99
+ nodes: nodeSources.map(n => n.getInfo()),
100
+ });
101
+ }
102
+
103
+ const txCollection = new TxCollection(
104
+ p2pService,
105
+ nodeSources,
106
+ l1Constants,
107
+ mempools.txPool,
108
+ config,
109
+ dateProvider,
110
+ telemetry,
111
+ logger.createChild('tx-collection'),
112
+ );
113
+
114
+ return new P2PClient(
115
+ clientType,
116
+ store,
117
+ archiver,
118
+ mempools,
119
+ p2pService,
120
+ txCollection,
121
+ config,
122
+ dateProvider,
123
+ telemetry,
124
+ );
125
+ }
126
+
127
+ async function createP2PService<T extends P2PClientType>(
128
+ config: P2PConfig & DataStoreConfig,
129
+ clientType: T,
130
+ archiver: L2BlockSource & ContractDataSource,
131
+ proofVerifier: ClientProtocolCircuitVerifier,
132
+ worldStateSynchronizer: WorldStateSynchronizer,
133
+ epochCache: EpochCacheInterface,
134
+ store: AztecAsyncKVStore,
135
+ peerStore: AztecLMDBStoreV2,
136
+ mempools: MemPools<T>,
137
+ p2pServiceFactory: P2PClientDeps<T>['p2pServiceFactory'],
138
+ packageVersion: string,
139
+ logger: Logger,
140
+ telemetry: TelemetryClient,
141
+ ) {
142
+ if (!config.p2pEnabled) {
67
143
  logger.verbose('P2P is disabled. Using dummy P2P service.');
68
- return new P2PClient(clientType, store, archiver, mempools, new DummyP2PService(), config, telemetry);
144
+ return new DummyP2PService();
69
145
  }
70
146
 
71
147
  logger.verbose('P2P is enabled. Using LibP2P service.');
72
- config = await configureP2PClientAddresses(_config);
73
148
 
74
149
  // Create peer discovery service
75
150
  const peerIdPrivateKey = await getPeerIdPrivateKey(config, store, logger);
76
151
  const peerId = await createLibP2PPeerIdFromPrivateKey(peerIdPrivateKey.getValue());
77
152
 
78
- const p2pService = await (deps.p2pServiceFactory ?? LibP2PService.new<T>)(clientType, config, peerId, {
153
+ const p2pService = await (p2pServiceFactory ?? LibP2PService.new<T>)(clientType, config, peerId, {
79
154
  packageVersion,
80
155
  mempools,
81
156
  l2BlockSource: archiver,
@@ -84,8 +159,8 @@ export const createP2PClient = async <T extends P2PClientType>(
84
159
  worldStateSynchronizer,
85
160
  peerStore,
86
161
  telemetry,
87
- logger: createLogger(`${logger.module}:libp2p_service`),
162
+ logger: logger.createChild(`libp2p_service`),
88
163
  });
89
164
 
90
- return new P2PClient(clientType, store, archiver, mempools, p2pService, config, telemetry);
91
- };
165
+ return p2pService;
166
+ }
@@ -1,4 +1,4 @@
1
- import type { L2BlockId } from '@aztec/stdlib/block';
1
+ import type { EthAddress, L2BlockId } from '@aztec/stdlib/block';
2
2
  import type { P2PApiFull } from '@aztec/stdlib/interfaces/server';
3
3
  import type { BlockProposal, P2PClientType } from '@aztec/stdlib/p2p';
4
4
  import type { Tx, TxHash } from '@aztec/stdlib/tx';
@@ -7,6 +7,12 @@ import type { ENR } from '@chainsafe/enr';
7
7
  import type { PeerId } from '@libp2p/interface';
8
8
 
9
9
  import type { P2PConfig } from '../config.js';
10
+ import type { AuthRequest, StatusMessage } from '../services/index.js';
11
+ import type {
12
+ ReqRespSubProtocol,
13
+ ReqRespSubProtocolHandler,
14
+ ReqRespSubProtocolValidators,
15
+ } from '../services/reqresp/interface.js';
10
16
  import type { P2PBlockReceivedCallback } from '../services/service.js';
11
17
 
12
18
  /**
@@ -60,13 +66,7 @@ export type P2P<T extends P2PClientType = P2PClientType.Full> = P2PApiFull<T> &
60
66
  * @param pinnedPeerId - An optional peer id that will be used to request the tx from (in addition to other random peers).
61
67
  * @returns A list of transactions or undefined if the transactions are not found.
62
68
  */
63
- requestTxsByHash(txHashes: TxHash[], pinnedPeerId: PeerId): Promise<(Tx | undefined)[]>;
64
-
65
- /**
66
- * Request a transaction from another peer by its tx hash.
67
- * @param txHash - Hash of the tx to query.
68
- */
69
- requestTxByHash(txHash: TxHash): Promise<Tx | undefined>;
69
+ requestTxsByHash(txHashes: TxHash[], pinnedPeerId: PeerId): Promise<Tx[]>;
70
70
 
71
71
  /**
72
72
  * Verifies the 'tx' and, if valid, adds it to local tx pool and forwards it to other peers.
@@ -109,13 +109,6 @@ export type P2P<T extends P2PClientType = P2PClientType.Full> = P2PApiFull<T> &
109
109
  */
110
110
  hasTxsInPool(txHashes: TxHash[]): Promise<boolean[]>;
111
111
 
112
- /**
113
- * Returns a transaction in the transaction pool by its hash, requesting it from the network if it is not found.
114
- * @param txHash - Hash of tx to return.
115
- * @returns A single tx or undefined.
116
- */
117
- getTxByHash(txHash: TxHash): Promise<Tx | undefined>;
118
-
119
112
  /**
120
113
  * Returns transactions in the transaction pool by hash, requesting from the network if not found.
121
114
  * @param txHashes - Hashes of tx to return.
@@ -188,4 +181,15 @@ export type P2P<T extends P2PClientType = P2PClientType.Full> = P2PApiFull<T> &
188
181
 
189
182
  /** Clears the db. */
190
183
  clear(): Promise<void>;
184
+
185
+ addReqRespSubProtocol(
186
+ subProtocol: ReqRespSubProtocol,
187
+ handler: ReqRespSubProtocolHandler,
188
+ validator?: ReqRespSubProtocolValidators[ReqRespSubProtocol],
189
+ ): Promise<void>;
190
+
191
+ handleAuthRequestFromPeer(authRequest: AuthRequest, peerId: PeerId): Promise<StatusMessage>;
192
+
193
+ /** If node running this P2P stack is validator, passes in validator address to P2P layer */
194
+ registerThisValidatorAddresses(address: EthAddress[]): void;
191
195
  };
@@ -1,7 +1,9 @@
1
1
  import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
2
2
  import { createLogger } from '@aztec/foundation/log';
3
+ import { DateProvider } from '@aztec/foundation/timer';
3
4
  import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncSingleton } from '@aztec/kv-store';
4
5
  import type {
6
+ EthAddress,
5
7
  L2Block,
6
8
  L2BlockId,
7
9
  L2BlockSource,
@@ -11,7 +13,8 @@ import type {
11
13
  PublishedL2Block,
12
14
  } from '@aztec/stdlib/block';
13
15
  import type { ContractDataSource } from '@aztec/stdlib/contract';
14
- import type { PeerInfo } from '@aztec/stdlib/interfaces/server';
16
+ import { getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
17
+ import { type PeerInfo, tryStop } from '@aztec/stdlib/interfaces/server';
15
18
  import { BlockAttestation, type BlockProposal, type P2PClientType } from '@aztec/stdlib/p2p';
16
19
  import type { Tx, TxHash } from '@aztec/stdlib/tx';
17
20
  import {
@@ -30,9 +33,16 @@ import { type P2PConfig, getP2PDefaultConfig } from '../config.js';
30
33
  import type { AttestationPool } from '../mem_pools/attestation_pool/attestation_pool.js';
31
34
  import type { MemPools } from '../mem_pools/interface.js';
32
35
  import type { TxPool } from '../mem_pools/tx_pool/index.js';
33
- import { ReqRespSubProtocol } from '../services/reqresp/interface.js';
36
+ import type { AuthRequest, StatusMessage } from '../services/index.js';
37
+ import {
38
+ ReqRespSubProtocol,
39
+ type ReqRespSubProtocolHandler,
40
+ type ReqRespSubProtocolValidators,
41
+ } from '../services/reqresp/interface.js';
42
+ import { chunkTxHashesRequest } from '../services/reqresp/protocols/tx.js';
34
43
  import type { P2PBlockReceivedCallback, P2PService } from '../services/service.js';
35
- import { TxCollector } from '../services/tx_collector.js';
44
+ import { TxCollection } from '../services/tx_collection/tx_collection.js';
45
+ import { TxProvider } from '../services/tx_provider.js';
36
46
  import { type P2P, P2PClientState, type P2PSyncState } from './interface.js';
37
47
 
38
48
  /**
@@ -65,6 +75,10 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
65
75
 
66
76
  private blockStream: L2BlockStream | undefined;
67
77
 
78
+ private txProvider: TxProvider;
79
+
80
+ private validatorAddresses: EthAddress[] = [];
81
+
68
82
  /**
69
83
  * In-memory P2P client constructor.
70
84
  * @param store - The client's instance of the KV store.
@@ -79,7 +93,9 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
79
93
  private l2BlockSource: L2BlockSource & ContractDataSource,
80
94
  mempools: MemPools<T>,
81
95
  private p2pService: P2PService,
96
+ private txCollection: TxCollection,
82
97
  config: Partial<P2PConfig> = {},
98
+ private _dateProvider: DateProvider = new DateProvider(),
83
99
  private telemetry: TelemetryClient = getTelemetryClient(),
84
100
  private log = createLogger('p2p'),
85
101
  ) {
@@ -89,12 +105,25 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
89
105
  this.txPool = mempools.txPool;
90
106
  this.attestationPool = mempools.attestationPool!;
91
107
 
108
+ this.txProvider = new TxProvider(
109
+ this.txCollection,
110
+ this.txPool,
111
+ this,
112
+ this.log.createChild('tx-provider'),
113
+ this.telemetry,
114
+ );
115
+
92
116
  // Default to collecting all txs when we see a valid proposal
93
- // This can be overridden by the validator client to attest, and it will call collectForBlockProposal on its own
94
- const txCollector = new TxCollector(this, this.log);
117
+ // This can be overridden by the validator client to attest, and it will call getTxsForBlockProposal on its own
118
+ // TODO(palla/txs): We should not trigger a request for txs on a proposal before fully validating it. We need to bring
119
+ // validator-client code into here so we can validate a proposal is reasonable.
95
120
  this.registerBlockProposalHandler(async (block, sender) => {
96
121
  this.log.debug(`Received block proposal from ${sender.toString()}`);
97
- await txCollector.collectForBlockProposal(block, sender);
122
+ // TODO(palla/txs): Need to subtract validatorReexecuteDeadlineMs from this deadline (see ValidatorClient.getReexecutionDeadline)
123
+ const constants = this.txCollection.getConstants();
124
+ const nextSlotTimestampSeconds = Number(getTimestampForSlot(block.slotNumber.toBigInt() + 1n, constants));
125
+ const deadline = new Date(nextSlotTimestampSeconds * 1000);
126
+ await this.txProvider.getTxsForBlockProposal(block, { pinnedPeer: sender, deadline });
98
127
  return undefined;
99
128
  });
100
129
 
@@ -106,6 +135,11 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
106
135
  this.synchedLatestSlot = store.openSingleton('p2p_pool_last_l2_slot');
107
136
  }
108
137
 
138
+ public registerThisValidatorAddresses(addresses: EthAddress[]): void {
139
+ this.validatorAddresses = [...addresses];
140
+ this.p2pService.registerThisValidatorAddresses(this.validatorAddresses);
141
+ }
142
+
109
143
  public clear(): Promise<void> {
110
144
  return this.store.clear();
111
145
  }
@@ -114,6 +148,10 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
114
148
  return true;
115
149
  }
116
150
 
151
+ public getTxProvider(): TxProvider {
152
+ return this.txProvider;
153
+ }
154
+
117
155
  public getPeers(includePending?: boolean): Promise<PeerInfo[]> {
118
156
  return Promise.resolve(this.p2pService.getPeers(includePending));
119
157
  }
@@ -184,11 +222,13 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
184
222
  }
185
223
  case 'chain-proven': {
186
224
  await this.setBlockHash(event.block);
225
+ this.txCollection.stopCollectingForBlocksUpTo(event.block.number);
187
226
  await this.synchedProvenBlockNumber.set(event.block.number);
188
227
  break;
189
228
  }
190
229
  case 'chain-pruned':
191
230
  await this.setBlockHash(event.block);
231
+ this.txCollection.stopCollectingForBlocksAfter(event.block.number);
192
232
  await this.handlePruneL2Blocks(event.block.number);
193
233
  break;
194
234
  default: {
@@ -274,9 +314,18 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
274
314
  }
275
315
 
276
316
  this.blockStream!.start();
317
+ await this.txCollection.start();
277
318
  return this.syncPromise;
278
319
  }
279
320
 
321
+ addReqRespSubProtocol(
322
+ subProtocol: ReqRespSubProtocol,
323
+ handler: ReqRespSubProtocolHandler,
324
+ validator: ReqRespSubProtocolValidators[ReqRespSubProtocol],
325
+ ): Promise<void> {
326
+ return this.p2pService.addReqRespSubProtocol(subProtocol, handler, validator);
327
+ }
328
+
280
329
  private initBlockStream(startingBlock?: number) {
281
330
  if (!this.blockStream) {
282
331
  const { blockRequestBatchSize: batchSize, blockCheckIntervalMS: pollIntervalMS } = this.config;
@@ -298,6 +347,8 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
298
347
  */
299
348
  public async stop() {
300
349
  this.log.debug('Stopping p2p client...');
350
+ await tryStop(this.txCollection);
351
+ this.log.debug('Stopped tx collection service');
301
352
  await this.p2pService.stop();
302
353
  this.log.debug('Stopped p2p service');
303
354
  await this.blockStream?.stop();
@@ -342,52 +393,31 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
342
393
  this.p2pService.registerBlockReceivedCallback(handler);
343
394
  }
344
395
 
345
- /**
346
- * Uses the Request Response protocol to request a transaction from the network.
347
- *
348
- * If the underlying request response protocol fails, then we return undefined.
349
- * If it succeeds then we add the transaction to our transaction pool and return.
350
- *
351
- * @param txHash - The hash of the transaction to request.
352
- * @returns A promise that resolves to a transaction or undefined.
353
- */
354
- public async requestTxByHash(txHash: TxHash): Promise<Tx | undefined> {
355
- const tx = await this.p2pService.sendRequest(ReqRespSubProtocol.TX, txHash);
356
-
357
- if (tx) {
358
- this.log.debug(`Received tx ${txHash.toString()} from peer`);
359
- await this.txPool.addTxs([tx]);
360
- } else {
361
- this.log.debug(`Failed to receive tx ${txHash.toString()} from peer`);
362
- }
363
-
364
- return tx;
365
- }
366
-
367
396
  /**
368
397
  * Uses the batched Request Response protocol to request a set of transactions from the network.
369
398
  */
370
- public async requestTxsByHash(txHashes: TxHash[], pinnedPeerId: PeerId | undefined): Promise<(Tx | undefined)[]> {
399
+ public async requestTxsByHash(txHashes: TxHash[], pinnedPeerId: PeerId | undefined): Promise<Tx[]> {
371
400
  const timeoutMs = 8000; // Longer timeout for now
372
- const maxPeers = Math.min(Math.ceil(txHashes.length / 3), 10);
373
401
  const maxRetryAttempts = 10; // Keep retrying within the timeout
402
+ const requests = chunkTxHashesRequest(txHashes);
403
+ const maxPeers = Math.min(Math.ceil(requests.length / 3), 10);
374
404
 
375
- const txs = await this.p2pService.sendBatchRequest(
405
+ const txBatches = await this.p2pService.sendBatchRequest(
376
406
  ReqRespSubProtocol.TX,
377
- txHashes,
407
+ requests,
378
408
  pinnedPeerId,
379
409
  timeoutMs,
380
410
  maxPeers,
381
411
  maxRetryAttempts,
382
412
  );
383
413
 
384
- // Some transactions may return undefined, so we filter them out
385
- const filteredTxs = txs.filter((tx): tx is Tx => !!tx);
386
- if (filteredTxs.length > 0) {
387
- await this.txPool.addTxs(filteredTxs);
414
+ const txs = txBatches.flat();
415
+ if (txs.length > 0) {
416
+ await this.txPool.addTxs(txs);
388
417
  }
418
+
389
419
  const txHashesStr = txHashes.map(tx => tx.toString()).join(', ');
390
- this.log.debug(`Requested txs ${txHashesStr} (${filteredTxs.length} / ${txHashes.length}) from peers`);
420
+ this.log.debug(`Requested txs ${txHashesStr} (${txs.length} / ${txHashes.length}) from peers`);
391
421
 
392
422
  // We return all transactions, even the not found ones to the caller, such they can handle missing items themselves.
393
423
  return txs;
@@ -490,20 +520,6 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
490
520
  return this.txPool.hasTxs(txHashes);
491
521
  }
492
522
 
493
- /**
494
- * Returns a transaction in the transaction pool by its hash.
495
- * If the transaction is not in the pool, it will be requested from the network.
496
- * @param txHash - Hash of the transaction to look for in the pool.
497
- * @returns A single tx or undefined.
498
- */
499
- async getTxByHash(txHash: TxHash): Promise<Tx | undefined> {
500
- const tx = await this.txPool.getTxByHash(txHash);
501
- if (tx) {
502
- return tx;
503
- }
504
- return this.requestTxByHash(txHash);
505
- }
506
-
507
523
  /**
508
524
  * Returns transactions in the transaction pool by hash.
509
525
  * If a transaction is not in the pool, it will be requested from the network.
@@ -522,21 +538,20 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
522
538
  }
523
539
 
524
540
  const missingTxs = await this.requestTxsByHash(missingTxHashes, pinnedPeerId);
525
- const fetchedMissingTxs = missingTxs.filter((tx): tx is Tx => !!tx);
526
-
527
541
  // TODO: optimize
528
542
  // Merge the found txs in order
529
- const mergingTxsPromises = txHashes.map(async txHash => {
543
+ const mergingTxs = txHashes.map(txHash => {
530
544
  // Is it in the txs list from the mempool?
531
545
  for (const tx of txs) {
532
- if (tx !== undefined && (await tx.getTxHash()).equals(txHash)) {
546
+ if (tx !== undefined && tx.getTxHash().equals(txHash)) {
533
547
  return tx;
534
548
  }
535
549
  }
536
550
 
537
551
  // Is it in the fetched missing txs?
538
- for (const tx of fetchedMissingTxs) {
539
- if (tx !== undefined && (await tx.getTxHash()).equals(txHash)) {
552
+ // Note: this is an O(n^2) operation, but we expect the number of missing txs to be small.
553
+ for (const tx of missingTxs) {
554
+ if (tx.getTxHash().equals(txHash)) {
540
555
  return tx;
541
556
  }
542
557
  }
@@ -545,7 +560,7 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
545
560
  return undefined;
546
561
  });
547
562
 
548
- return await Promise.all(mergingTxsPromises);
563
+ return mergingTxs;
549
564
  }
550
565
 
551
566
  /**
@@ -696,7 +711,7 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
696
711
  }
697
712
 
698
713
  await this.markTxsAsMinedFromBlocks(blocks.map(b => b.block));
699
- void this.requestMissingTxsFromUnprovenBlocks(blocks.map(b => b.block));
714
+ await this.startCollectingMissingTxs(blocks.map(b => b.block));
700
715
 
701
716
  const lastBlock = blocks.at(-1)!.block;
702
717
 
@@ -716,25 +731,31 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
716
731
  }
717
732
 
718
733
  /** Request txs for unproven blocks so the prover node has more chances to get them. */
719
- private async requestMissingTxsFromUnprovenBlocks(blocks: L2Block[]): Promise<void> {
734
+ private async startCollectingMissingTxs(blocks: L2Block[]): Promise<void> {
720
735
  try {
721
- const provenBlockNumber = Math.max(await this.getSyncedProvenBlockNum(), this.provenBlockNumberAtStart);
736
+ // TODO(#15435): If the archiver has lagged behind L1, the reported proven block number may
737
+ // be much lower than the actual one, and it does not update until the pending chain is
738
+ // fully synced. This could lead to a ton of tx collection requests for blocks that
739
+ // are already proven, but the archiver has not yet updated its state. Until this is properly
740
+ // fixed, it is mitigated by the expiration date of collection requests, which depends on
741
+ // the slot number of the block.
742
+ const provenBlockNumber = await this.l2BlockSource.getProvenBlockNumber();
722
743
  const unprovenBlocks = blocks.filter(block => block.number > provenBlockNumber);
723
- const txHashes = unprovenBlocks.flatMap(block => block.body.txEffects.map(txEffect => txEffect.txHash));
724
- const missingTxHashes = await this.txPool
725
- .hasTxs(txHashes)
726
- .then(availability => txHashes.filter((_, index) => !availability[index]));
727
- if (missingTxHashes.length > 0) {
728
- this.log.verbose(
729
- `Requesting ${missingTxHashes.length} missing txs from peers for ${unprovenBlocks.length} unproven mined blocks`,
730
- { missingTxHashes, unprovenBlockNumbers: unprovenBlocks.map(block => block.number) },
731
- );
732
- await this.requestTxsByHash(missingTxHashes, undefined);
744
+ for (const block of unprovenBlocks) {
745
+ const txHashes = block.body.txEffects.map(txEffect => txEffect.txHash);
746
+ const missingTxHashes = await this.txPool
747
+ .hasTxs(txHashes)
748
+ .then(availability => txHashes.filter((_, index) => !availability[index]));
749
+ if (missingTxHashes.length > 0) {
750
+ this.log.verbose(
751
+ `Starting collection of ${missingTxHashes.length} missing txs for unproven mined block ${block.number}`,
752
+ { missingTxHashes, blockNumber: block.number, blockHash: await block.hash().then(h => h.toString()) },
753
+ );
754
+ this.txCollection.startCollecting(block, missingTxHashes);
755
+ }
733
756
  }
734
757
  } catch (err) {
735
- this.log.error(`Error requesting missing txs from unproven blocks`, err, {
736
- blocks: blocks.map(block => block.number),
737
- });
758
+ this.log.error(`Error while starting collection of missing txs for unproven blocks`, err);
738
759
  }
739
760
  }
740
761
 
@@ -766,21 +787,14 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
766
787
  * @param latestBlock - The block number the chain was pruned to.
767
788
  */
768
789
  private async handlePruneL2Blocks(latestBlock: number): Promise<void> {
769
- // NOTE: temporary fix for alphanet, deleting ALL txs that were in the epoch from the pool #13723
770
- // TODO: undo once fixed: #13770
771
790
  const txsToDelete = new Map<string, TxHash>();
772
791
  const minedTxs = await this.txPool.getMinedTxHashes();
773
- for (const [txHash, blockNumber] of minedTxs) {
774
- if (blockNumber > latestBlock) {
775
- txsToDelete.set(txHash.toString(), txHash);
776
- }
777
- }
778
792
 
779
793
  // Find transactions that reference pruned blocks in their historical header
780
794
  for (const tx of await this.txPool.getAllTxs()) {
781
795
  // every tx that's been generated against a block that has now been pruned is no longer valid
782
796
  if (tx.data.constants.historicalHeader.globalVariables.blockNumber > latestBlock) {
783
- const txHash = await tx.getTxHash();
797
+ const txHash = tx.getTxHash();
784
798
  txsToDelete.set(txHash.toString(), txHash);
785
799
  }
786
800
  }
@@ -799,17 +813,15 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
799
813
  // NOTE: we can't move _all_ txs back to pending because the tx pool could keep hold of mined txs for longer
800
814
  // (see this.keepProvenTxsFor)
801
815
 
802
- // NOTE: given current fix for alphanet, the code below is redundant as all these txs will be deleted.
803
- // TODO: bring back once fixed: #13770
804
- // const txsToMoveToPending: TxHash[] = [];
805
- // for (const [txHash, blockNumber] of minedTxs) {
806
- // if (blockNumber > latestBlock) {
807
- // txsToMoveToPending.push(txHash);
808
- // }
809
- // }
816
+ const txsToMoveToPending: TxHash[] = [];
817
+ for (const [txHash, blockNumber] of minedTxs) {
818
+ if (blockNumber > latestBlock) {
819
+ txsToMoveToPending.push(txHash);
820
+ }
821
+ }
810
822
 
811
- // this.log.info(`Moving ${txsToMoveToPending.length} mined txs back to pending`);
812
- // await this.txPool.markMinedAsPending(txsToMoveToPending);
823
+ this.log.info(`Moving ${txsToMoveToPending.length} mined txs back to pending`);
824
+ await this.txPool.markMinedAsPending(txsToMoveToPending);
813
825
 
814
826
  await this.synchedLatestBlockNumber.set(latestBlock);
815
827
  // no need to update block hashes, as they will be updated as new blocks are added
@@ -862,4 +874,8 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
862
874
  public markTxsAsNonEvictable(txHashes: TxHash[]): Promise<void> {
863
875
  return this.txPool.markTxsAsNonEvictable(txHashes);
864
876
  }
877
+
878
+ public handleAuthRequestFromPeer(authRequest: AuthRequest, peerId: PeerId): Promise<StatusMessage> {
879
+ return this.p2pService.handleAuthRequestFromPeer(authRequest, peerId);
880
+ }
865
881
  }