Skip to content

Commit 1c32eda

Browse files
authored
feat(p2p): persist node private p2p keys (#10324)
1 parent fcbff0d commit 1c32eda

24 files changed

+194
-108
lines changed

yarn-project/end-to-end/src/e2e_p2p/gossip_network.test.ts

-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ describe('e2e_p2p_network', () => {
7575
t.logger.info('Creating nodes');
7676
nodes = await createNodes(
7777
t.ctx.aztecNodeConfig,
78-
t.peerIdPrivateKeys,
7978
t.bootstrapNodeEnr,
8079
NUM_NODES,
8180
BOOT_NODE_UDP_PORT,

yarn-project/end-to-end/src/e2e_p2p/p2p_network.ts

-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import {
1717
PRIVATE_KEYS_START_INDEX,
1818
createValidatorConfig,
1919
generateNodePrivateKeys,
20-
generatePeerIdPrivateKeys,
2120
} from '../fixtures/setup_p2p_test.js';
2221
import {
2322
type ISnapshotManager,
@@ -66,7 +65,6 @@ export class P2PNetworkTest {
6665
this.baseAccount = privateKeyToAccount(`0x${getPrivateKeyFromIndex(0)!.toString('hex')}`);
6766
this.nodePrivateKeys = generateNodePrivateKeys(PRIVATE_KEYS_START_INDEX, numberOfNodes);
6867
this.nodePublicKeys = this.nodePrivateKeys.map(privateKey => privateKeyToAccount(privateKey).address);
69-
this.peerIdPrivateKeys = generatePeerIdPrivateKeys(numberOfNodes);
7068

7169
this.bootstrapNodeEnr = bootstrapNode.getENR().encodeTxt();
7270

yarn-project/end-to-end/src/e2e_p2p/rediscovery.test.ts

-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ describe('e2e_p2p_rediscovery', () => {
4646
const contexts: NodeContext[] = [];
4747
nodes = await createNodes(
4848
t.ctx.aztecNodeConfig,
49-
t.peerIdPrivateKeys,
5049
t.bootstrapNodeEnr,
5150
NUM_NODES,
5251
BOOT_NODE_UDP_PORT,
@@ -73,7 +72,6 @@ describe('e2e_p2p_rediscovery', () => {
7372

7473
const newNode = await createNode(
7574
t.ctx.aztecNodeConfig,
76-
t.peerIdPrivateKeys[i],
7775
i + 1 + BOOT_NODE_UDP_PORT,
7876
undefined,
7977
i,

yarn-project/end-to-end/src/e2e_p2p/reex.test.ts

-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ describe('e2e_p2p_reex', () => {
6565

6666
nodes = await createNodes(
6767
t.ctx.aztecNodeConfig,
68-
t.peerIdPrivateKeys,
6968
t.bootstrapNodeEnr,
7069
NUM_NODES,
7170
BOOT_NODE_UDP_PORT,

yarn-project/end-to-end/src/e2e_p2p/reqresp.test.ts

-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ describe('e2e_p2p_reqresp_tx', () => {
6565
t.logger.info('Creating nodes');
6666
nodes = await createNodes(
6767
t.ctx.aztecNodeConfig,
68-
t.peerIdPrivateKeys,
6968
t.bootstrapNodeEnr,
7069
NUM_NODES,
7170
BOOT_NODE_UDP_PORT,

yarn-project/end-to-end/src/e2e_p2p/upgrade_governance_proposer.test.ts

-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ describe('e2e_p2p_governance_proposer', () => {
130130
t.logger.info('Creating nodes');
131131
nodes = await createNodes(
132132
{ ...t.ctx.aztecNodeConfig, governanceProposerPayload: newPayloadAddress },
133-
t.peerIdPrivateKeys,
134133
t.bootstrapNodeEnr,
135134
NUM_NODES,
136135
BOOT_NODE_UDP_PORT,

yarn-project/end-to-end/src/fixtures/setup_p2p_test.ts

+1-29
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { type AztecAddress } from '@aztec/circuits.js';
77
import { type PXEService } from '@aztec/pxe';
88

99
import getPort from 'get-port';
10-
import { generatePrivateKey } from 'viem/accounts';
1110

1211
import { getPrivateKeyFromIndex } from './utils.js';
1312
import { getEndToEndTestTelemetryClient } from './with_telemetry_utils.js';
@@ -32,22 +31,8 @@ export function generateNodePrivateKeys(startIndex: number, numberOfNodes: numbe
3231
return nodePrivateKeys;
3332
}
3433

35-
export function generatePeerIdPrivateKey(): string {
36-
// magic number is multiaddr prefix: https://multiformats.io/multiaddr/ for secp256k1
37-
return '08021220' + generatePrivateKey().substr(2, 66);
38-
}
39-
40-
export function generatePeerIdPrivateKeys(numberOfPeers: number): string[] {
41-
const peerIdPrivateKeys = [];
42-
for (let i = 0; i < numberOfPeers; i++) {
43-
peerIdPrivateKeys.push(generatePeerIdPrivateKey());
44-
}
45-
return peerIdPrivateKeys;
46-
}
47-
4834
export function createNodes(
4935
config: AztecNodeConfig,
50-
peerIdPrivateKeys: string[],
5136
bootstrapNodeEnr: string,
5237
numNodes: number,
5338
bootNodePort: number,
@@ -60,15 +45,7 @@ export function createNodes(
6045
const port = bootNodePort + i + 1;
6146

6247
const dataDir = dataDirectory ? `${dataDirectory}-${i}` : undefined;
63-
const nodePromise = createNode(
64-
config,
65-
peerIdPrivateKeys[i],
66-
port,
67-
bootstrapNodeEnr,
68-
i + PRIVATE_KEYS_START_INDEX,
69-
dataDir,
70-
metricsPort,
71-
);
48+
const nodePromise = createNode(config, port, bootstrapNodeEnr, i + PRIVATE_KEYS_START_INDEX, dataDir, metricsPort);
7249
nodePromises.push(nodePromise);
7350
}
7451
return Promise.all(nodePromises);
@@ -77,7 +54,6 @@ export function createNodes(
7754
// creates a P2P enabled instance of Aztec Node Service
7855
export async function createNode(
7956
config: AztecNodeConfig,
80-
peerIdPrivateKey: string,
8157
tcpPort: number,
8258
bootstrapNode: string | undefined,
8359
publisherAddressIndex: number,
@@ -88,7 +64,6 @@ export async function createNode(
8864
config,
8965
bootstrapNode,
9066
tcpPort,
91-
peerIdPrivateKey,
9267
publisherAddressIndex,
9368
dataDirectory,
9469
);
@@ -105,11 +80,9 @@ export async function createValidatorConfig(
10580
config: AztecNodeConfig,
10681
bootstrapNodeEnr?: string,
10782
port?: number,
108-
peerIdPrivateKey?: string,
10983
accountIndex: number = 1,
11084
dataDirectory?: string,
11185
) {
112-
peerIdPrivateKey = peerIdPrivateKey ?? generatePeerIdPrivateKey();
11386
port = port ?? (await getPort());
11487

11588
const privateKey = getPrivateKeyFromIndex(accountIndex);
@@ -120,7 +93,6 @@ export async function createValidatorConfig(
12093

12194
const nodeConfig: AztecNodeConfig = {
12295
...config,
123-
peerIdPrivateKey: peerIdPrivateKey,
12496
udpListenAddress: `0.0.0.0:${port}`,
12597
tcpListenAddress: `0.0.0.0:${port}`,
12698
tcpAnnounceAddress: `127.0.0.1:${port}`,

yarn-project/kv-store/src/config.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { type EthAddress } from '@aztec/foundation/eth-address';
55
export type DataStoreConfig = {
66
dataDirectory: string | undefined;
77
dataStoreMapSizeKB: number;
8-
l1Contracts: { rollupAddress: EthAddress };
8+
l1Contracts?: { rollupAddress: EthAddress };
99
};
1010

1111
export const dataConfigMappings: ConfigMappingsType<DataStoreConfig> = {

yarn-project/kv-store/src/utils.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@ export function createStore(name: string, config: DataStoreConfig, log: Logger =
1818
? `Creating ${name} data store at directory ${dataDirectory} with map size ${config.dataStoreMapSizeKB} KB`
1919
: `Creating ${name} ephemeral data store with map size ${config.dataStoreMapSizeKB} KB`,
2020
);
21-
return initStoreForRollup(
22-
AztecLmdbStore.open(dataDirectory, config.dataStoreMapSizeKB, false),
23-
config.l1Contracts.rollupAddress,
24-
log,
25-
);
21+
22+
const store = AztecLmdbStore.open(dataDirectory, config.dataStoreMapSizeKB, false);
23+
if (config.l1Contracts?.rollupAddress) {
24+
return initStoreForRollup(store, config.l1Contracts.rollupAddress, log);
25+
}
26+
return store;
2627
}
2728

2829
/**

yarn-project/p2p-bootstrap/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
],
2626
"dependencies": {
2727
"@aztec/foundation": "workspace:^",
28+
"@aztec/kv-store": "workspace:^",
2829
"@aztec/p2p": "workspace:^",
2930
"@aztec/telemetry-client": "workspace:^",
3031
"dotenv": "^16.0.3",

yarn-project/p2p-bootstrap/src/index.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { createDebugLogger } from '@aztec/foundation/log';
2+
import { createStore } from '@aztec/kv-store/utils';
23
import { type BootnodeConfig, BootstrapNode } from '@aztec/p2p';
34
import { type TelemetryClient } from '@aztec/telemetry-client';
45
import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
@@ -18,7 +19,9 @@ async function main(
1819
telemetryClient: TelemetryClient = new NoopTelemetryClient(),
1920
logger = debugLogger,
2021
) {
21-
const bootstrapNode = new BootstrapNode(telemetryClient, logger);
22+
const store = await createStore('p2p-bootstrap', config, logger);
23+
24+
const bootstrapNode = new BootstrapNode(store, telemetryClient, logger);
2225
await bootstrapNode.start(config);
2326
logger.info('DiscV5 Bootnode started');
2427

yarn-project/p2p-bootstrap/tsconfig.json

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
{
1010
"path": "../foundation"
1111
},
12+
{
13+
"path": "../kv-store"
14+
},
1215
{
1316
"path": "../p2p"
1417
},

yarn-project/p2p/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
"@chainsafe/libp2p-noise": "^15.0.0",
7575
"@chainsafe/libp2p-yamux": "^6.0.2",
7676
"@libp2p/bootstrap": "10.0.0",
77-
"@libp2p/crypto": "4.0.3",
77+
"@libp2p/crypto": "^4.1.1",
7878
"@libp2p/identify": "1.0.18",
7979
"@libp2p/interface": "1.3.1",
8080
"@libp2p/kad-dht": "10.0.4",

yarn-project/p2p/src/bootstrap/bootstrap.ts

+11-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { createDebugLogger } from '@aztec/foundation/log';
2+
import { type AztecKVStore } from '@aztec/kv-store';
23
import { OtelMetricsAdapter, type TelemetryClient } from '@aztec/telemetry-client';
34

45
import { Discv5, type Discv5EventEmitter } from '@chainsafe/discv5';
@@ -8,8 +9,7 @@ import { type Multiaddr, multiaddr } from '@multiformats/multiaddr';
89

910
import type { BootnodeConfig } from '../config.js';
1011
import { AZTEC_ENR_KEY, AZTEC_NET } from '../service/discV5_service.js';
11-
import { createLibP2PPeerId } from '../service/index.js';
12-
import { convertToMultiaddr } from '../util.js';
12+
import { convertToMultiaddr, createLibP2PPeerIdFromPrivateKey, getPeerIdPrivateKey } from '../util.js';
1313

1414
/**
1515
* Encapsulates a 'Bootstrap' node, used for the purpose of assisting new joiners in acquiring peers.
@@ -18,16 +18,22 @@ export class BootstrapNode {
1818
private node?: Discv5 = undefined;
1919
private peerId?: PeerId;
2020

21-
constructor(private telemetry: TelemetryClient, private logger = createDebugLogger('aztec:p2p_bootstrap')) {}
21+
constructor(
22+
private store: AztecKVStore,
23+
private telemetry: TelemetryClient,
24+
private logger = createDebugLogger('aztec:p2p_bootstrap'),
25+
) {}
2226

2327
/**
2428
* Starts the bootstrap node.
2529
* @param config - A partial P2P configuration. No need for TCP values as well as aztec node specific values.
2630
* @returns An empty promise.
2731
*/
2832
public async start(config: BootnodeConfig) {
29-
const { peerIdPrivateKey, udpListenAddress, udpAnnounceAddress } = config;
30-
const peerId = await createLibP2PPeerId(peerIdPrivateKey);
33+
const { udpListenAddress, udpAnnounceAddress } = config;
34+
35+
const peerIdPrivateKey = await getPeerIdPrivateKey(config, this.store);
36+
const peerId = await createLibP2PPeerIdFromPrivateKey(peerIdPrivateKey);
3137
this.peerId = peerId;
3238
const enr = SignableENR.createFromPeerId(peerId);
3339

yarn-project/p2p/src/client/index.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import { type MemPools } from '../mem_pools/interface.js';
1616
import { AztecKVTxPool, type TxPool } from '../mem_pools/tx_pool/index.js';
1717
import { DiscV5Service } from '../service/discV5_service.js';
1818
import { DummyP2PService } from '../service/dummy_service.js';
19-
import { LibP2PService, createLibP2PPeerId } from '../service/index.js';
20-
import { configureP2PClientAddresses } from '../util.js';
19+
import { LibP2PService } from '../service/index.js';
20+
import { configureP2PClientAddresses, createLibP2PPeerIdFromPrivateKey, getPeerIdPrivateKey } from '../util.js';
2121

2222
export * from './p2p_client.js';
2323

@@ -49,7 +49,8 @@ export const createP2PClient = async (
4949
config = await configureP2PClientAddresses(_config);
5050

5151
// Create peer discovery service
52-
const peerId = await createLibP2PPeerId(config.peerIdPrivateKey);
52+
const peerIdPrivateKey = await getPeerIdPrivateKey(config, store);
53+
const peerId = await createLibP2PPeerIdFromPrivateKey(peerIdPrivateKey);
5354
const discoveryService = new DiscV5Service(peerId, config, telemetry);
5455

5556
p2pService = await LibP2PService.new(

yarn-project/p2p/src/config.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
numberConfigHelper,
77
pickConfigMappings,
88
} from '@aztec/foundation/config';
9+
import { type DataStoreConfig, dataConfigMappings } from '@aztec/kv-store/config';
910

1011
import { type P2PReqRespConfig, p2pReqRespConfigMappings } from './service/reqresp/config.js';
1112

@@ -318,14 +319,20 @@ export type BootnodeConfig = Pick<
318319
P2PConfig,
319320
'udpAnnounceAddress' | 'peerIdPrivateKey' | 'minPeerCount' | 'maxPeerCount'
320321
> &
321-
Required<Pick<P2PConfig, 'udpListenAddress'>>;
322+
Required<Pick<P2PConfig, 'udpListenAddress'>> &
323+
Pick<DataStoreConfig, 'dataDirectory' | 'dataStoreMapSizeKB'>;
322324

323325
const bootnodeConfigKeys: (keyof BootnodeConfig)[] = [
324326
'udpAnnounceAddress',
325327
'peerIdPrivateKey',
326328
'minPeerCount',
327329
'maxPeerCount',
328330
'udpListenAddress',
331+
'dataDirectory',
332+
'dataStoreMapSizeKB',
329333
];
330334

331-
export const bootnodeConfigMappings = pickConfigMappings(p2pConfigMappings, bootnodeConfigKeys);
335+
export const bootnodeConfigMappings = pickConfigMappings(
336+
{ ...p2pConfigMappings, ...dataConfigMappings },
337+
bootnodeConfigKeys,
338+
);

yarn-project/p2p/src/mocks/index.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
type WorldStateSynchronizer,
66
} from '@aztec/circuit-types';
77
import { type DataStoreConfig } from '@aztec/kv-store/config';
8+
import { openTmpStore } from '@aztec/kv-store/utils';
89
import { type TelemetryClient } from '@aztec/telemetry-client';
910
import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
1011

@@ -14,6 +15,7 @@ import { yamux } from '@chainsafe/libp2p-yamux';
1415
import { bootstrap } from '@libp2p/bootstrap';
1516
import { identify } from '@libp2p/identify';
1617
import { type PeerId } from '@libp2p/interface';
18+
import { createSecp256k1PeerId } from '@libp2p/peer-id-factory';
1719
import { tcp } from '@libp2p/tcp';
1820
import getPort from 'get-port';
1921
import { type Libp2p, type Libp2pOptions, createLibp2p } from 'libp2p';
@@ -22,7 +24,7 @@ import { BootstrapNode } from '../bootstrap/bootstrap.js';
2224
import { type BootnodeConfig, type P2PConfig } from '../config.js';
2325
import { type MemPools } from '../mem_pools/interface.js';
2426
import { DiscV5Service } from '../service/discV5_service.js';
25-
import { LibP2PService, createLibP2PPeerId } from '../service/libp2p_service.js';
27+
import { LibP2PService } from '../service/libp2p_service.js';
2628
import { type PeerManager } from '../service/peer_manager.js';
2729
import { type P2PReqRespConfig } from '../service/reqresp/config.js';
2830
import { pingHandler, statusHandler } from '../service/reqresp/handlers.js';
@@ -102,7 +104,7 @@ export async function createTestLibP2PService(
102104
port: number = 0,
103105
peerId?: PeerId,
104106
) {
105-
peerId = peerId ?? (await createLibP2PPeerId());
107+
peerId = peerId ?? (await createSecp256k1PeerId());
106108
const config = {
107109
tcpAnnounceAddress: `127.0.0.1:${port}`,
108110
udpAnnounceAddress: `127.0.0.1:${port}`,
@@ -231,6 +233,8 @@ export function createBootstrapNodeConfig(privateKey: string, port: number): Boo
231233
peerIdPrivateKey: privateKey,
232234
minPeerCount: 10,
233235
maxPeerCount: 100,
236+
dataDirectory: undefined,
237+
dataStoreMapSizeKB: 0,
234238
};
235239
}
236240

@@ -247,14 +251,16 @@ export async function createBootstrapNode(
247251
port: number,
248252
telemetry: TelemetryClient = new NoopTelemetryClient(),
249253
): Promise<BootstrapNode> {
250-
const peerId = await createLibP2PPeerId();
254+
const peerId = await createSecp256k1PeerId();
251255
const config = createBootstrapNodeConfig(Buffer.from(peerId.privateKey!).toString('hex'), port);
252256

253257
return startBootstrapNode(config, telemetry);
254258
}
255259

256260
async function startBootstrapNode(config: BootnodeConfig, telemetry: TelemetryClient) {
257-
const bootstrapNode = new BootstrapNode(telemetry);
261+
// Open an ephemeral store that will only exist in memory
262+
const store = openTmpStore(true);
263+
const bootstrapNode = new BootstrapNode(store, telemetry);
258264
await bootstrapNode.start(config);
259265
return bootstrapNode;
260266
}

0 commit comments

Comments
 (0)