1
1
import Common from '@ethereumjs/common'
2
2
import VM from '@ethereumjs/vm'
3
+ import { genPrivateKey } from '@ethereumjs/devp2p'
3
4
import Multiaddr from 'multiaddr'
4
5
import { getLogger , Logger } from './logging'
5
6
import { Libp2pServer , RlpxServer } from './net/server'
6
7
import { parseTransports } from './util'
8
+ import type { LevelUp } from 'levelup'
9
+ const level = require ( 'level' )
7
10
8
11
export interface ConfigOptions {
9
12
/**
@@ -40,6 +43,13 @@ export interface ConfigOptions {
40
43
*/
41
44
datadir ?: string
42
45
46
+ /**
47
+ * Private key for the client.
48
+ * Use return value of `await Config.getClientKey(datadir, common)`
49
+ * If left blank, a random key will be generated and used.
50
+ */
51
+ key ?: Buffer
52
+
43
53
/**
44
54
* Network transports ('rlpx' and/or 'libp2p')
45
55
*
@@ -172,6 +182,7 @@ export class Config {
172
182
public readonly vm ?: VM
173
183
public readonly lightserv : boolean
174
184
public readonly datadir : string
185
+ public readonly key : Buffer
175
186
public readonly transports : string [ ]
176
187
public readonly bootnodes ?: Multiaddr [ ]
177
188
public readonly multiaddrs ?: Multiaddr [ ]
@@ -199,6 +210,7 @@ export class Config {
199
210
this . bootnodes = options . bootnodes
200
211
this . multiaddrs = options . multiaddrs
201
212
this . datadir = options . datadir ?? Config . DATADIR_DEFAULT
213
+ this . key = options . key ?? genPrivateKey ( )
202
214
this . rpc = options . rpc ?? Config . RPC_DEFAULT
203
215
this . rpcport = options . rpcport ?? Config . RPCPORT_DEFAULT
204
216
this . rpcaddr = options . rpcaddr ?? Config . RPCADDR_DEFAULT
@@ -243,25 +255,33 @@ export class Config {
243
255
const bootnodes = this . bootnodes ?? this . chainCommon . bootstrapNodes ( )
244
256
const dnsNetworks = options . dnsNetworks ?? this . chainCommon . dnsNetworks ( )
245
257
return new RlpxServer ( { config : this , bootnodes, dnsNetworks } )
246
- } else {
247
- // t.name === 'libp2p'
258
+ } else if ( t . name === 'libp2p' ) {
248
259
const multiaddrs = this . multiaddrs
249
260
const bootnodes = this . bootnodes
250
261
return new Libp2pServer ( { config : this , multiaddrs, bootnodes } )
262
+ } else {
263
+ throw new Error ( `unknown transport: ${ t . name } ` )
251
264
}
252
265
} )
253
266
}
254
267
}
255
268
269
+ /**
270
+ * Returns the network directory for the chain.
271
+ */
272
+ getNetworkDirectory ( ) : string {
273
+ const networkDirName = this . chainCommon . chainName ( )
274
+ const dataDir = `${ this . datadir } /${ networkDirName } `
275
+ return dataDir
276
+ }
277
+
256
278
/**
257
279
* Returns the directory for storing the client chain data
258
280
* based on syncmode and selected chain (subdirectory of 'datadir')
259
281
*/
260
282
getChainDataDirectory ( ) : string {
261
- const networkDirName = this . chainCommon . chainName ( )
262
283
const chainDataDirName = this . syncmode === 'light' ? 'lightchain' : 'chain'
263
-
264
- const dataDir = `${ this . datadir } /${ networkDirName } /${ chainDataDirName } `
284
+ const dataDir = `${ this . getNetworkDirectory ( ) } /${ chainDataDirName } `
265
285
return dataDir
266
286
}
267
287
@@ -270,10 +290,36 @@ export class Config {
270
290
* based selected chain (subdirectory of 'datadir')
271
291
*/
272
292
getStateDataDirectory ( ) : string {
273
- const networkDirName = this . chainCommon . chainName ( )
293
+ return `${ this . getNetworkDirectory ( ) } /state`
294
+ }
274
295
275
- const dataDir = `${ this . datadir } /${ networkDirName } /state`
276
- return dataDir
296
+ /**
297
+ * Returns the config level db.
298
+ */
299
+ static getConfigDB ( networkDir : string ) : LevelUp {
300
+ const db = level ( `${ networkDir } /config` as any )
301
+ return db
302
+ }
303
+
304
+ /**
305
+ * Gets the client private key from the config db.
306
+ */
307
+ static async getClientKey ( datadir : string , common : Common ) {
308
+ const networkDir = `${ datadir } /${ common . chainName ( ) } `
309
+ const db = this . getConfigDB ( networkDir )
310
+ const encodingOpts = { keyEncoding : 'utf8' , valueEncoding : 'binary' }
311
+ const dbKey = 'config:client_key'
312
+ let key
313
+ try {
314
+ key = await db . get ( dbKey , encodingOpts )
315
+ } catch ( error ) {
316
+ if ( error . type === 'NotFoundError' ) {
317
+ // generate and save a new key
318
+ key = genPrivateKey ( )
319
+ await db . put ( dbKey , key , encodingOpts )
320
+ }
321
+ }
322
+ return key
277
323
}
278
324
279
325
/**
0 commit comments