2019-03-05 22:54:08 +00:00
|
|
|
import
|
2019-03-18 03:54:08 +00:00
|
|
|
options, chronos, json_serialization,
|
|
|
|
spec/digest, version, conf
|
2019-03-05 22:54:08 +00:00
|
|
|
|
|
|
|
const
|
2019-03-18 03:54:08 +00:00
|
|
|
clientId = "Nimbus beacon node v" & fullVersionStr()
|
2019-03-05 22:54:08 +00:00
|
|
|
|
2019-03-18 03:54:08 +00:00
|
|
|
when useRLPx:
|
2019-03-05 22:54:08 +00:00
|
|
|
import
|
2019-03-18 03:54:08 +00:00
|
|
|
os,
|
2019-03-05 22:54:08 +00:00
|
|
|
eth/[rlp, p2p, keys], gossipsub_protocol
|
|
|
|
|
|
|
|
export
|
|
|
|
p2p, rlp, gossipsub_protocol
|
|
|
|
|
|
|
|
type
|
|
|
|
Eth2Node* = EthereumNode
|
|
|
|
BootstrapAddr* = ENode
|
|
|
|
|
|
|
|
template libp2pProtocol*(name, version: string) {.pragma.}
|
|
|
|
|
2019-03-18 03:54:08 +00:00
|
|
|
proc writeValue*(writer: var JsonWriter, value: BootstrapAddr) {.inline.} =
|
|
|
|
writer.writeValue $value
|
|
|
|
|
|
|
|
proc readValue*(reader: var JsonReader, value: var BootstrapAddr) {.inline.} =
|
|
|
|
value = initENode reader.readValue(string)
|
|
|
|
|
|
|
|
proc createEth2Node*(conf: BeaconNodeConf): Future[EthereumNode] {.async.} =
|
|
|
|
let privateKeyFile = conf.dataDir / "network.privkey"
|
|
|
|
var privKey: PrivateKey
|
|
|
|
if not fileExists(privateKeyFile):
|
|
|
|
privKey = newPrivateKey()
|
|
|
|
writeFile(privateKeyFile, $privKey)
|
|
|
|
else:
|
|
|
|
privKey = initPrivateKey(readFile(privateKeyFile).string)
|
|
|
|
|
2019-03-05 22:54:08 +00:00
|
|
|
let
|
2019-03-18 03:54:08 +00:00
|
|
|
keys = KeyPair(seckey: privKey, pubkey: privKey.getPublicKey())
|
2019-03-05 22:54:08 +00:00
|
|
|
address = Address(ip: parseIpAddress("127.0.0.1"),
|
2019-03-18 03:54:08 +00:00
|
|
|
tcpPort: Port conf.tcpPort,
|
|
|
|
udpPort: Port conf.udpPort)
|
2019-03-05 22:54:08 +00:00
|
|
|
|
2019-03-12 13:14:30 +00:00
|
|
|
return newEthereumNode(keys, address, 0,
|
|
|
|
nil, clientId, minPeers = 1)
|
2019-03-05 22:54:08 +00:00
|
|
|
|
|
|
|
proc saveConnectionAddressFile*(node: Eth2Node, filename: string) =
|
|
|
|
writeFile(filename, $node.listeningAddress)
|
|
|
|
|
|
|
|
proc init*(T: type BootstrapAddr, str: string): T =
|
|
|
|
initENode(str)
|
|
|
|
|
|
|
|
else:
|
|
|
|
import
|
2019-03-18 03:54:08 +00:00
|
|
|
libp2p/daemon/daemonapi, chronicles,
|
2019-03-05 22:54:08 +00:00
|
|
|
libp2p_backend
|
|
|
|
|
|
|
|
export
|
|
|
|
libp2p_backend
|
|
|
|
|
|
|
|
type
|
|
|
|
BootstrapAddr* = PeerInfo
|
|
|
|
|
|
|
|
proc writeValue*(writer: var JsonWriter, value: PeerID) {.inline.} =
|
|
|
|
writer.writeValue value.pretty
|
|
|
|
|
|
|
|
proc readValue*(reader: var JsonReader, value: var PeerID) {.inline.} =
|
|
|
|
value = PeerID.init reader.readValue(string)
|
|
|
|
|
|
|
|
proc writeValue*(writer: var JsonWriter, value: MultiAddress) {.inline.} =
|
|
|
|
writer.writeValue $value
|
|
|
|
|
|
|
|
proc readValue*(reader: var JsonReader, value: var MultiAddress) {.inline.} =
|
|
|
|
value = MultiAddress.init reader.readValue(string)
|
|
|
|
|
|
|
|
proc init*(T: type BootstrapAddr, str: string): T =
|
|
|
|
Json.decode(str, PeerInfo)
|
|
|
|
|
2019-03-18 03:54:08 +00:00
|
|
|
proc createEth2Node*(conf: BeaconNodeConf): Future[Eth2Node] {.async.} =
|
2019-03-05 22:54:08 +00:00
|
|
|
var node = new Eth2Node
|
|
|
|
await node.init()
|
|
|
|
return node
|
|
|
|
|
|
|
|
proc connectToNetwork*(node: Eth2Node, bootstrapNodes: seq[PeerInfo]) {.async.} =
|
|
|
|
# TODO: perhaps we should do these in parallel
|
|
|
|
for bootstrapNode in bootstrapNodes:
|
|
|
|
try:
|
|
|
|
await node.daemon.connect(bootstrapNode.peer, bootstrapNode.addresses)
|
2019-03-18 03:54:08 +00:00
|
|
|
let peer = node.getPeer(bootstrapNode.peer)
|
|
|
|
await peer.performProtocolHandshakes()
|
2019-03-05 22:54:08 +00:00
|
|
|
except PeerDisconnected:
|
|
|
|
error "Failed to connect to bootstrap node", node = bootstrapNode
|
|
|
|
|
|
|
|
proc saveConnectionAddressFile*(node: Eth2Node, filename: string) =
|
|
|
|
let id = waitFor node.daemon.identity()
|
|
|
|
Json.saveFile(filename, id, pretty = false)
|
|
|
|
|
|
|
|
proc loadConnectionAddressFile*(filename: string): PeerInfo =
|
|
|
|
Json.loadFile(filename, PeerInfo)
|
|
|
|
|
2019-03-18 03:54:08 +00:00
|
|
|
type
|
|
|
|
TestnetMetadata* = object
|
|
|
|
networkId*: uint64
|
|
|
|
genesisRoot*: Eth2Digest
|
|
|
|
bootstrapNodes*: BootstrapAddr
|
|
|
|
totalValidators*: int
|
|
|
|
userValidatorsStart*: int
|
|
|
|
userValidatorsEnd*: int
|
|
|
|
|
|
|
|
proc userValidatorsRange*(d: TestnetMetadata): HSlice[int, int] =
|
|
|
|
d.userValidatorsStart .. d.userValidatorsEnd
|
|
|
|
|