Skip to content

Commit

Permalink
feat: use kubo config file for configuration (#6)
Browse files Browse the repository at this point in the history
* feat: use kubo config file for configuration

* chore: update package-lock
  • Loading branch information
wemeetagain committed Oct 2, 2023
1 parent 0058fbb commit 5b2d520
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 18 deletions.
44 changes: 29 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@
"dependencies": {
"@chainsafe/libp2p-noise": "^13.0.1",
"@chainsafe/libp2p-yamux": "^5.0.0",
"@libp2p/bootstrap": "^9.0.6",
"@libp2p/crypto": "^2.0.4",
"@libp2p/interface": "^0.1.2",
"@libp2p/kad-dht": "^10.0.7",
"@libp2p/mplex": "^9.0.6",
"@libp2p/peer-id": "^3.0.2",
Expand All @@ -144,7 +147,8 @@
"@libp2p/websockets": "^7.0.7",
"@multiformats/multiaddr": "^12.1.7",
"libp2p": "^0.46.11",
"prom-client": "^14.2.0"
"prom-client": "^14.2.0",
"uint8arrays": "^4.0.6"
},
"devDependencies": {
"aegir": "^40.0.13"
Expand Down
85 changes: 83 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
#! /usr/bin/env node --trace-warnings
/* eslint-disable no-console */

import { readFile } from 'node:fs/promises'
import { createServer } from 'node:http'
import { isAbsolute, join } from 'node:path'
import { parseArgs } from 'node:util'
import { noise } from '@chainsafe/libp2p-noise'
import { yamux } from '@chainsafe/libp2p-yamux'
import { bootstrap } from '@libp2p/bootstrap'
import { unmarshalPrivateKey } from '@libp2p/crypto/keys'
import { kadDHT } from '@libp2p/kad-dht'
import { mplex } from '@libp2p/mplex'
import { peerIdFromKeys, peerIdFromString } from '@libp2p/peer-id'
import { prometheusMetrics } from '@libp2p/prometheus-metrics'
import { tcp } from '@libp2p/tcp'
import { webSockets } from '@libp2p/websockets'
import { createLibp2p } from 'libp2p'
import { autoNATService } from 'libp2p/autonat'
import { circuitRelayServer } from 'libp2p/circuit-relay'
import { register } from 'prom-client'
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
import type { PeerId } from '@libp2p/interface/peer-id'

async function main (): Promise<void> {
const options = {
Expand Down Expand Up @@ -56,9 +63,24 @@ async function main (): Promise<void> {
return
}

const configFilename = args.values.config
if (configFilename == null) {
fatal('--config must be provided')
}
const configFilepath = isAbsolute(configFilename) ? configFilename : join(process.cwd(), configFilename)
const config = await readConfig(configFilepath)

const peerId = await decodePeerId(config.Identity.PrivKey)
if (!peerIdFromString(config.Identity.PeerId).equals(peerId)) {
fatal('Config Identity.PeerId doesn\'t match Identity.PrivKey')
}

const services: Record<string, any> = {
relay: circuitRelayServer({
advertise: true
}),
bootstrap: bootstrap({
list: config.Bootstrap
})
}

Expand All @@ -71,6 +93,12 @@ async function main (): Promise<void> {
}

const node = await createLibp2p({
peerId,
addresses: {
listen: config.Addresses.Swarm,
announce: config.Addresses.Announce,
noAnnounce: config.Addresses.NoAnnounce
},
transports: [
webSockets(),
tcp()
Expand Down Expand Up @@ -105,6 +133,59 @@ async function main (): Promise<void> {
}

main().catch(err => {
console.error(err) // eslint-disable-line no-console
process.exit(1)
fatal(err)
})

function fatal (msg?: any): never {
console.error(msg)
process.exit(1)
}

/** Subset of options that we care about from an kubo config */
interface KuboConfig {
Bootstrap: string[]
Addresses: {
Swarm: string[]
Announce: string[]
NoAnnounce: string[]
}
Identity: {
PeerId: string
PrivKey: string
}
}

function validateKey (config: any, key: string, path: string): void {
if (config[key] == null) {
fatal(`Config key missing: ${path}`)
}
}

function validateConfig (config: any): config is KuboConfig {
validateKey(config, 'Bootstrap', 'Bootstrap')
validateKey(config, 'Addresses', 'Addresses')
validateKey(config.Addresses, 'Swarm', 'Addresses.Swarm')
validateKey(config.Addresses, 'Announce', 'Addresses.Announce')
validateKey(config.Addresses, 'NoAnnounce', 'Addresses.NoAnnounce')
validateKey(config, 'Identity', 'Identity')
validateKey(config.Identity, 'PeerId', 'Identity.PeerId')
validateKey(config.Identity, 'PrivKey', 'Identity.PrivKey')
return true
}

async function readConfig (filepath: string): Promise<KuboConfig> {
const configString = await readFile(filepath, 'utf8')
const config = JSON.parse(configString)
validateConfig(config)
return config
}

async function decodePeerId (privkeyStr: string): Promise<PeerId> {
try {
const privkeyBytes = uint8ArrayFromString(privkeyStr, 'base64pad')
const privkey = await unmarshalPrivateKey(privkeyBytes)
return await peerIdFromKeys(privkey.public.bytes, privkey.bytes)
} catch (e) {
fatal('Invalid peer-id private key')
}
}

0 comments on commit 5b2d520

Please sign in to comment.