@aztec/p2p 0.60.0 → 0.62.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 (35) hide show
  1. package/dest/client/index.js +2 -39
  2. package/dest/client/p2p_client.d.ts +33 -9
  3. package/dest/client/p2p_client.d.ts.map +1 -1
  4. package/dest/client/p2p_client.js +121 -30
  5. package/dest/config.d.ts +5 -1
  6. package/dest/config.d.ts.map +1 -1
  7. package/dest/config.js +7 -2
  8. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +3 -2
  9. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
  10. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +30 -5
  11. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +3 -2
  12. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -1
  13. package/dest/mem_pools/tx_pool/memory_tx_pool.js +26 -5
  14. package/dest/mem_pools/tx_pool/tx_pool.d.ts +8 -2
  15. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
  16. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
  17. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +30 -3
  18. package/dest/mocks/index.d.ts +18 -2
  19. package/dest/mocks/index.d.ts.map +1 -1
  20. package/dest/mocks/index.js +79 -5
  21. package/dest/service/peer_scoring.js +5 -5
  22. package/dest/util.d.ts +3 -0
  23. package/dest/util.d.ts.map +1 -1
  24. package/dest/util.js +38 -1
  25. package/package.json +12 -7
  26. package/src/client/index.ts +1 -48
  27. package/src/client/p2p_client.ts +156 -40
  28. package/src/config.ts +11 -1
  29. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +35 -6
  30. package/src/mem_pools/tx_pool/memory_tx_pool.ts +32 -6
  31. package/src/mem_pools/tx_pool/tx_pool.ts +9 -2
  32. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +34 -2
  33. package/src/mocks/index.ts +123 -5
  34. package/src/service/peer_scoring.ts +4 -4
  35. package/src/util.ts +53 -0
@@ -1,11 +1,27 @@
1
- import { type ClientProtocolCircuitVerifier, type Tx } from '@aztec/circuit-types';
1
+ import {
2
+ type ClientProtocolCircuitVerifier,
3
+ type L2BlockSource,
4
+ type Tx,
5
+ type WorldStateSynchronizer,
6
+ } from '@aztec/circuit-types';
7
+ import { type DataStoreConfig } from '@aztec/kv-store/utils';
8
+ import { type TelemetryClient } from '@aztec/telemetry-client';
2
9
 
10
+ import { gossipsub } from '@chainsafe/libp2p-gossipsub';
3
11
  import { noise } from '@chainsafe/libp2p-noise';
4
12
  import { yamux } from '@chainsafe/libp2p-yamux';
5
13
  import { bootstrap } from '@libp2p/bootstrap';
14
+ import { identify } from '@libp2p/identify';
15
+ import { type PeerId } from '@libp2p/interface';
6
16
  import { tcp } from '@libp2p/tcp';
17
+ import getPort from 'get-port';
7
18
  import { type Libp2p, type Libp2pOptions, createLibp2p } from 'libp2p';
8
19
 
20
+ import { BootstrapNode } from '../bootstrap/bootstrap.js';
21
+ import { type BootnodeConfig, type P2PConfig } from '../config.js';
22
+ import { type MemPools } from '../mem_pools/interface.js';
23
+ import { DiscV5Service } from '../service/discV5_service.js';
24
+ import { LibP2PService, createLibP2PPeerId } from '../service/libp2p_service.js';
9
25
  import { type PeerManager } from '../service/peer_manager.js';
10
26
  import { type P2PReqRespConfig } from '../service/reqresp/config.js';
11
27
  import { pingHandler, statusHandler } from '../service/reqresp/handlers.js';
@@ -18,20 +34,35 @@ import {
18
34
  noopValidator,
19
35
  } from '../service/reqresp/interface.js';
20
36
  import { ReqResp } from '../service/reqresp/reqresp.js';
37
+ import { type PubSubLibp2p } from '../util.js';
21
38
 
22
39
  /**
23
40
  * Creates a libp2p node, pre configured.
24
41
  * @param boostrapAddrs - an optional list of bootstrap addresses
25
42
  * @returns Lip2p node
26
43
  */
27
- export async function createLibp2pNode(boostrapAddrs: string[] = []): Promise<Libp2p> {
44
+ export async function createLibp2pNode(
45
+ boostrapAddrs: string[] = [],
46
+ peerId?: PeerId,
47
+ port?: number,
48
+ enableGossipSub: boolean = false,
49
+ start: boolean = true,
50
+ ): Promise<Libp2p> {
51
+ port = port ?? (await getPort());
28
52
  const options: Libp2pOptions = {
53
+ start,
29
54
  addresses: {
30
- listen: ['/ip4/0.0.0.0/tcp/0'],
55
+ listen: [`/ip4/0.0.0.0/tcp/${port}`],
56
+ announce: [`/ip4/0.0.0.0/tcp/${port}`],
31
57
  },
32
58
  connectionEncryption: [noise()],
33
59
  streamMuxers: [yamux()],
34
60
  transports: [tcp()],
61
+ services: {
62
+ identify: identify({
63
+ protocolPrefix: 'aztec',
64
+ }),
65
+ },
35
66
  };
36
67
 
37
68
  if (boostrapAddrs.length > 0) {
@@ -42,9 +73,65 @@ export async function createLibp2pNode(boostrapAddrs: string[] = []): Promise<Li
42
73
  ];
43
74
  }
44
75
 
76
+ if (peerId) {
77
+ options.peerId = peerId;
78
+ }
79
+
80
+ if (enableGossipSub) {
81
+ options.services!.pubsub = gossipsub({
82
+ allowPublishToZeroTopicPeers: true,
83
+ });
84
+ }
85
+
45
86
  return await createLibp2p(options);
46
87
  }
47
88
 
89
+ /**
90
+ * Test Libp2p service
91
+ * P2P functionality is operational, however everything else is default
92
+ *
93
+ * WORKTODO: more description
94
+ */
95
+ export async function createTestLibP2PService(
96
+ boostrapAddrs: string[] = [],
97
+ l2BlockSource: L2BlockSource,
98
+ worldStateSynchronizer: WorldStateSynchronizer,
99
+ mempools: MemPools,
100
+ telemetry: TelemetryClient,
101
+ port: number = 0,
102
+ peerId?: PeerId,
103
+ ) {
104
+ peerId = peerId ?? (await createLibP2PPeerId());
105
+ const config = {
106
+ tcpAnnounceAddress: `127.0.0.1:${port}`,
107
+ udpAnnounceAddress: `127.0.0.1:${port}`,
108
+ tcpListenAddress: `0.0.0.0:${port}`,
109
+ udpListenAddress: `0.0.0.0:${port}`,
110
+ bootstrapNodes: boostrapAddrs,
111
+ peerCheckIntervalMS: 1000,
112
+ minPeerCount: 1,
113
+ maxPeerCount: 5,
114
+ p2pEnabled: true,
115
+ peerIdPrivateKey: Buffer.from(peerId.privateKey!).toString('hex'),
116
+ } as P2PConfig & DataStoreConfig;
117
+ const discoveryService = new DiscV5Service(peerId, config);
118
+ const proofVerifier = new AlwaysTrueCircuitVerifier();
119
+
120
+ // No bootstrap nodes provided as the libp2p service will register them in the constructor
121
+ const p2pNode = await createLibp2pNode([], peerId, port, /*enable gossip */ true, /**start */ false);
122
+
123
+ return new LibP2PService(
124
+ config,
125
+ p2pNode as PubSubLibp2p,
126
+ discoveryService,
127
+ mempools,
128
+ l2BlockSource,
129
+ proofVerifier,
130
+ worldStateSynchronizer,
131
+ telemetry,
132
+ );
133
+ }
134
+
48
135
  /**
49
136
  * A p2p / req resp node pairing the req node will always contain the p2p node.
50
137
  * they are provided as a pair to allow access the p2p node directly
@@ -88,10 +175,12 @@ export const startNodes = async (
88
175
  };
89
176
 
90
177
  export const stopNodes = async (nodes: ReqRespNode[]): Promise<void> => {
178
+ const stopPromises = [];
91
179
  for (const node of nodes) {
92
- await node.req.stop();
93
- await node.p2p.stop();
180
+ stopPromises.push(node.req.stop());
181
+ stopPromises.push(node.p2p.stop());
94
182
  }
183
+ await Promise.all(stopPromises);
95
184
  };
96
185
 
97
186
  // Create a req resp node, exposing the underlying p2p node
@@ -132,3 +221,32 @@ export class AlwaysFalseCircuitVerifier implements ClientProtocolCircuitVerifier
132
221
  return Promise.resolve(false);
133
222
  }
134
223
  }
224
+
225
+ // Bootnodes
226
+ export function createBootstrapNodeConfig(privateKey: string, port: number): BootnodeConfig {
227
+ return {
228
+ udpListenAddress: `0.0.0.0:${port}`,
229
+ udpAnnounceAddress: `127.0.0.1:${port}`,
230
+ peerIdPrivateKey: privateKey,
231
+ minPeerCount: 10,
232
+ maxPeerCount: 100,
233
+ };
234
+ }
235
+
236
+ export function createBootstrapNodeFromPrivateKey(privateKey: string, port: number): Promise<BootstrapNode> {
237
+ const config = createBootstrapNodeConfig(privateKey, port);
238
+ return startBootstrapNode(config);
239
+ }
240
+
241
+ export async function createBootstrapNode(port: number): Promise<BootstrapNode> {
242
+ const peerId = await createLibP2PPeerId();
243
+ const config = createBootstrapNodeConfig(Buffer.from(peerId.privateKey!).toString('hex'), port);
244
+
245
+ return startBootstrapNode(config);
246
+ }
247
+
248
+ async function startBootstrapNode(config: BootnodeConfig) {
249
+ const bootstrapNode = new BootstrapNode();
250
+ await bootstrapNode.start(config);
251
+ return bootstrapNode;
252
+ }
@@ -32,14 +32,14 @@ export class PeerScoring {
32
32
  peerPenalties: { [key in PeerErrorSeverity]: number };
33
33
 
34
34
  constructor(config: P2PConfig) {
35
- const orderedValues = config.peerPenaltyValues.sort((a, b) => a - b);
35
+ const orderedValues = config.peerPenaltyValues?.sort((a, b) => a - b);
36
36
  this.peerPenalties = {
37
37
  [PeerErrorSeverity.HighToleranceError]:
38
- orderedValues[0] ?? DefaultPeerPenalties[PeerErrorSeverity.LowToleranceError],
38
+ orderedValues?.[0] ?? DefaultPeerPenalties[PeerErrorSeverity.LowToleranceError],
39
39
  [PeerErrorSeverity.MidToleranceError]:
40
- orderedValues[1] ?? DefaultPeerPenalties[PeerErrorSeverity.MidToleranceError],
40
+ orderedValues?.[1] ?? DefaultPeerPenalties[PeerErrorSeverity.MidToleranceError],
41
41
  [PeerErrorSeverity.LowToleranceError]:
42
- orderedValues[2] ?? DefaultPeerPenalties[PeerErrorSeverity.HighToleranceError],
42
+ orderedValues?.[2] ?? DefaultPeerPenalties[PeerErrorSeverity.HighToleranceError],
43
43
  };
44
44
  }
45
45
 
package/src/util.ts CHANGED
@@ -1,7 +1,11 @@
1
+ import { type DataStoreConfig } from '@aztec/kv-store/utils';
2
+
1
3
  import type { GossipSub } from '@chainsafe/libp2p-gossipsub';
2
4
  import { resolve } from 'dns/promises';
3
5
  import type { Libp2p } from 'libp2p';
4
6
 
7
+ import { type P2PConfig } from './config.js';
8
+
5
9
  export interface PubSubLibp2p extends Libp2p {
6
10
  services: {
7
11
  pubsub: GossipSub;
@@ -88,3 +92,52 @@ function addressToMultiAddressType(address: string): 'ip4' | 'ip6' | 'dns' {
88
92
  return 'dns';
89
93
  }
90
94
  }
95
+
96
+ export async function configureP2PClientAddresses(
97
+ _config: P2PConfig & DataStoreConfig,
98
+ ): Promise<P2PConfig & DataStoreConfig> {
99
+ const config = { ..._config };
100
+ const {
101
+ tcpAnnounceAddress: configTcpAnnounceAddress,
102
+ udpAnnounceAddress: configUdpAnnounceAddress,
103
+ queryForIp,
104
+ } = config;
105
+
106
+ config.tcpAnnounceAddress = configTcpAnnounceAddress
107
+ ? await resolveAddressIfNecessary(configTcpAnnounceAddress)
108
+ : undefined;
109
+ config.udpAnnounceAddress = configUdpAnnounceAddress
110
+ ? await resolveAddressIfNecessary(configUdpAnnounceAddress)
111
+ : undefined;
112
+
113
+ // create variable for re-use if needed
114
+ let publicIp;
115
+
116
+ // check if no announce IP was provided
117
+ const splitTcpAnnounceAddress = splitAddressPort(configTcpAnnounceAddress || '', true);
118
+ if (splitTcpAnnounceAddress.length == 2 && splitTcpAnnounceAddress[0] === '') {
119
+ if (queryForIp) {
120
+ publicIp = await getPublicIp();
121
+ const tcpAnnounceAddress = `${publicIp}:${splitTcpAnnounceAddress[1]}`;
122
+ config.tcpAnnounceAddress = tcpAnnounceAddress;
123
+ } else {
124
+ throw new Error(
125
+ `Invalid announceTcpAddress provided: ${configTcpAnnounceAddress}. Expected format: <addr>:<port>`,
126
+ );
127
+ }
128
+ }
129
+
130
+ const splitUdpAnnounceAddress = splitAddressPort(configUdpAnnounceAddress || '', true);
131
+ if (splitUdpAnnounceAddress.length == 2 && splitUdpAnnounceAddress[0] === '') {
132
+ // If announceUdpAddress is not provided, use announceTcpAddress
133
+ if (!queryForIp && config.tcpAnnounceAddress) {
134
+ config.udpAnnounceAddress = config.tcpAnnounceAddress;
135
+ } else if (queryForIp) {
136
+ const udpPublicIp = publicIp || (await getPublicIp());
137
+ const udpAnnounceAddress = `${udpPublicIp}:${splitUdpAnnounceAddress[1]}`;
138
+ config.udpAnnounceAddress = udpAnnounceAddress;
139
+ }
140
+ }
141
+
142
+ return config;
143
+ }