Make the persistent network keys compatible with the Go daemon

The daemon requires its key file to be encoded as ProtoBuf value
with a proper `key scheme` discriminator.
This commit is contained in:
Zahary Karadjov 2020-02-19 10:58:10 +02:00
parent 1b1cd915db
commit 3b9e9fefa8
No known key found for this signature in database
GPG Key ID: C8936F8A3073D609
2 changed files with 33 additions and 30 deletions

View File

@ -21,6 +21,9 @@ const
hasPrompt = not defined(withoutPrompt) hasPrompt = not defined(withoutPrompt)
maxEmptySlotCount = uint64(24*60*60) div SECONDS_PER_SLOT maxEmptySlotCount = uint64(24*60*60) div SECONDS_PER_SLOT
type
KeyPair = eth2_network.KeyPair
# https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md#interop-metrics # https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md#interop-metrics
declareGauge beacon_slot, declareGauge beacon_slot,
"Latest slot of the beacon chain state" "Latest slot of the beacon chain state"
@ -46,7 +49,7 @@ type
nickname: string nickname: string
network: Eth2Node network: Eth2Node
forkVersion: array[4, byte] forkVersion: array[4, byte]
netKeys: DiscKeyPair netKeys: KeyPair
requestManager: RequestManager requestManager: RequestManager
bootstrapNodes: seq[ENode] bootstrapNodes: seq[ENode]
bootstrapEnrs: seq[enr.Record] bootstrapEnrs: seq[enr.Record]
@ -187,7 +190,7 @@ proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async
if fileExists(persistentBootstrapFile): if fileExists(persistentBootstrapFile):
loadBootstrapFile(persistentBootstrapFile, bootNodes, bootEnrs) loadBootstrapFile(persistentBootstrapFile, bootNodes, bootEnrs)
bootNodes = filterIt(bootNodes, it.pubkey != netKeys.pubkey) bootNodes = filterIt(bootNodes, it.pubkey != netKeys.pubkey.skkey)
let let
network = await createEth2Node(conf, bootNodes) network = await createEth2Node(conf, bootNodes)
@ -1117,7 +1120,11 @@ when isMainModule:
tcpPort: Port config.bootstrapPort, tcpPort: Port config.bootstrapPort,
udpPort: Port config.bootstrapPort) udpPort: Port config.bootstrapPort)
bootstrapEnr = enr.Record.init(1, networkKeys.seckey, bootstrapAddress) bootstrapEnr = enr.Record.init(
1, # sequence number
networkKeys.seckey.asEthKey,
bootstrapAddress)
writeFile(bootstrapFile, bootstrapEnr.toURI) writeFile(bootstrapFile, bootstrapEnr.toURI)
echo "Wrote ", bootstrapFile echo "Wrote ", bootstrapFile

View File

@ -1,13 +1,14 @@
import import
options, tables, strutils, sequtils, options, tables, strutils, sequtils,
json_serialization, json_serialization/std/net, json_serialization, json_serialization/std/net,
metrics, chronos, chronicles, metrics, libp2p/crypto/secp, metrics, chronos, chronicles, metrics, libp2p/crypto/crypto,
eth/keys, eth/p2p/enode, eth/net/nat, eth/p2p/discoveryv5/enr, eth/keys, eth/p2p/enode, eth/net/nat, eth/p2p/discoveryv5/enr,
eth2_discovery, version, conf eth2_discovery, version, conf
type type
DiscKeyPair* = keys.KeyPair KeyPair* = crypto.KeyPair
DiscPrivKey* = keys.PrivateKey PublicKey* = crypto.PublicKey
PrivateKey* = crypto.PrivateKey
const const
clientId* = "Nimbus beacon node v" & fullVersionStr clientId* = "Nimbus beacon node v" & fullVersionStr
@ -66,7 +67,7 @@ when networkBackend in [libp2p, libp2pDaemon]:
import import
os, random, os, random,
stew/io, eth/async_utils, stew/io, eth/async_utils,
libp2p/crypto/crypto as libp2pCrypto, libp2p/[multiaddress, multicodec], libp2p/[multiaddress, multicodec],
ssz ssz
export export
@ -99,12 +100,11 @@ when networkBackend in [libp2p, libp2pDaemon]:
netBackendName* = "libp2p" netBackendName* = "libp2p"
networkKeyFilename = "privkey.protobuf" networkKeyFilename = "privkey.protobuf"
func asLibp2pKey*(key: DiscPrivKey): libp2pCrypto.PrivateKey = func asLibp2pKey*(key: keys.PublicKey): PublicKey =
libp2pCrypto.PrivateKey(scheme: Secp256k1, PublicKey(scheme: Secp256k1, skkey: key)
skkey: SkPrivateKey(data: key.data))
func asLibp2pKey*(key: keys.PublicKey): libp2pCrypto.PublicKey = func asEthKey*(key: PrivateKey): keys.PrivateKey =
libp2pCrypto.PublicKey(scheme: Secp256k1, skkey: key) keys.PrivateKey(data: key.skkey.data)
proc initAddress*(T: type MultiAddress, str: string): T = proc initAddress*(T: type MultiAddress, str: string): T =
let address = MultiAddress.init(str) let address = MultiAddress.init(str)
@ -117,29 +117,25 @@ when networkBackend in [libp2p, libp2pDaemon]:
template tcpEndPoint(address, port): auto = template tcpEndPoint(address, port): auto =
MultiAddress.init(address, Protocol.IPPROTO_TCP, port) MultiAddress.init(address, Protocol.IPPROTO_TCP, port)
proc genRandomNetKey: DiscPrivKey =
let skkey = SkPrivateKey.random
DiscPrivKey(data: skkey.data)
proc ensureNetworkIdFile(conf: BeaconNodeConf): string = proc ensureNetworkIdFile(conf: BeaconNodeConf): string =
result = conf.dataDir / networkKeyFilename result = conf.dataDir / networkKeyFilename
if not fileExists(result): if not fileExists(result):
createDir conf.dataDir.string createDir conf.dataDir.string
let pk = genRandomNetKey() let pk = PrivateKey.random(Secp256k1)
writeFile(result, pk.data) writeFile(result, pk.getBytes)
proc getPersistentNetKeys*(conf: BeaconNodeConf): DiscKeyPair = proc getPersistentNetKeys*(conf: BeaconNodeConf): KeyPair =
let privKeyPath = conf.dataDir / networkKeyFilename let privKeyPath = conf.dataDir / networkKeyFilename
var privKey: DiscPrivKey var privKey: PrivateKey
if not fileExists(privKeyPath): if not fileExists(privKeyPath):
createDir conf.dataDir.string createDir conf.dataDir.string
privKey = genRandomNetKey() privKey = PrivateKey.random(Secp256k1)
writeFile(privKeyPath, privKey.data) writeFile(privKeyPath, privKey.getBytes())
else: else:
let strdata = readFile(privKeyPath) let keyBytes = readFile(privKeyPath)
privKey = initPrivateKey(cast[seq[byte]](strdata)) privKey = PrivateKey.init(keyBytes.toOpenArrayByte(0, keyBytes.high))
DiscKeyPair(seckey: privKey, pubkey: privKey.getPublicKey()) KeyPair(seckey: privKey, pubkey: privKey.getKey())
proc createEth2Node*(conf: BeaconNodeConf, proc createEth2Node*(conf: BeaconNodeConf,
bootstrapNodes: seq[ENode]): Future[Eth2Node] {.async.} = bootstrapNodes: seq[ENode]): Future[Eth2Node] {.async.} =
@ -158,9 +154,9 @@ when networkBackend in [libp2p, libp2pDaemon]:
# TODO nim-libp2p still doesn't have support for announcing addresses # TODO nim-libp2p still doesn't have support for announcing addresses
# that are different from the host address (this is relevant when we # that are different from the host address (this is relevant when we
# are running behind a NAT). # are running behind a NAT).
var switch = newStandardSwitch(some keys.seckey.asLibp2pKey, hostAddress, var switch = newStandardSwitch(some keys.seckey, hostAddress,
triggerSelf = true, gossip = false) triggerSelf = true, gossip = false)
result = Eth2Node.init(conf, switch, keys.seckey) result = Eth2Node.init(conf, switch, keys.seckey.skkey)
else: else:
let keyFile = conf.ensureNetworkIdFile let keyFile = conf.ensureNetworkIdFile
@ -188,10 +184,10 @@ when networkBackend in [libp2p, libp2pDaemon]:
proc getPersistenBootstrapAddr*(conf: BeaconNodeConf, proc getPersistenBootstrapAddr*(conf: BeaconNodeConf,
ip: IpAddress, port: Port): ENode = ip: IpAddress, port: Port): ENode =
let pair = getPersistentNetKeys(conf) let pair = getPersistentNetKeys(conf)
initENode(pair.pubkey, Address(ip: ip, udpPort: port)) initENode(pair.pubkey.skkey, Address(ip: ip, udpPort: port))
proc shortForm*(id: DiscKeyPair): string = proc shortForm*(id: KeyPair): string =
$PeerID.init(id.pubkey.asLibp2pKey) $PeerID.init(id.pubkey)
proc toPeerInfo(enode: ENode): PeerInfo = proc toPeerInfo(enode: ENode): PeerInfo =
let let