mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-02-22 19:28:20 +00:00
Command-line and data storage handling for testnets
This commit is contained in:
parent
798197879b
commit
6bb38095c9
@ -202,7 +202,7 @@ proc add*(pool: var AttestationPool,
|
||||
# TODO inefficient data structures..
|
||||
|
||||
let
|
||||
attestationSlot = attestation.data.slot.Slot
|
||||
attestationSlot = attestation.data.slot
|
||||
idx = pool.slotIndex(state, attestationSlot)
|
||||
slotData = addr pool.slots[idx]
|
||||
validation = Validation(
|
||||
@ -350,4 +350,4 @@ proc resolve*(pool: var AttestationPool, state: BeaconState) =
|
||||
|
||||
proc latestAttestation*(
|
||||
pool: AttestationPool, pubKey: ValidatorPubKey): BlockRef =
|
||||
pool.latestAttestations.getOrDefault(pubKey)
|
||||
pool.latestAttestations.getOrDefault(pubKey)
|
||||
|
@ -1,10 +1,10 @@
|
||||
import
|
||||
std_shims/[os_shims, objects], net, sequtils, options, tables,
|
||||
std_shims/[os_shims, objects], net, sequtils, options, tables, osproc, random,
|
||||
chronos, chronicles, confutils,
|
||||
spec/[datatypes, digest, crypto, beaconstate, helpers, validator], conf, time,
|
||||
state_transition, fork_choice, ssz, beacon_chain_db, validator_pool, extras,
|
||||
attestation_pool, block_pool, eth2_network, beacon_node_types,
|
||||
mainchain_monitor, trusted_state_snapshots,
|
||||
mainchain_monitor, trusted_state_snapshots, version,
|
||||
eth/trie/db, eth/trie/backends/rocksdb_backend
|
||||
|
||||
const
|
||||
@ -12,6 +12,11 @@ const
|
||||
topicAttestations = "ethereum/2.1/beacon_chain/attestations"
|
||||
topicfetchBlocks = "ethereum/2.1/beacon_chain/fetch"
|
||||
|
||||
dataDirValidators = "validators"
|
||||
networkMetadataFile = "network.json"
|
||||
genesisFile = "genesis.json"
|
||||
testnetsBaseUrl = "http://node-01.do-ams3.nimbus.misc.statusim.net:8000/nimbus_testnets"
|
||||
|
||||
# #################################################
|
||||
# Careful handling of beacon_node <-> sync_protocol
|
||||
# to avoid recursive dependencies
|
||||
@ -23,17 +28,66 @@ import sync_protocol
|
||||
func shortValidatorKey(node: BeaconNode, validatorIdx: int): string =
|
||||
($node.state.data.validator_registry[validatorIdx].pubkey)[0..7]
|
||||
|
||||
func localValidatorsDir(conf: BeaconNodeConf): string =
|
||||
conf.dataDir / "validators"
|
||||
|
||||
func databaseDir(conf: BeaconNodeConf): string =
|
||||
conf.dataDir / "db"
|
||||
|
||||
func slotStart(node: BeaconNode, slot: Slot): Timestamp =
|
||||
node.state.data.slotStart(slot)
|
||||
|
||||
template `//`(url, fragment: string): string =
|
||||
url & "/" & fragment
|
||||
|
||||
proc downloadFile(url: string): Future[string] {.async.} =
|
||||
let (fileContents, errorCode) = execCmdEx("curl --fail " & url)
|
||||
if errorCode != 0:
|
||||
raise newException(IOError, "Failed to download URL: " & url)
|
||||
return fileContents
|
||||
|
||||
proc doUpdateTestnet(conf: BeaconNodeConf) {.async.} =
|
||||
let latestMetadata = await downloadFile(testnetsBaseUrl // $conf.network // networkMetadataFile)
|
||||
|
||||
let localMetadataFile = conf.dataDir / networkMetadataFile
|
||||
if fileExists(localMetadataFile) and readFile(localMetadataFile).string == latestMetadata:
|
||||
return
|
||||
|
||||
removeDir conf.databaseDir
|
||||
writeFile localMetadataFile, latestMetadata
|
||||
|
||||
let newGenesis = await downloadFile(testnetsBaseUrl // $conf.network // genesisFile)
|
||||
writeFile conf.dataDir / genesisFile, newGenesis
|
||||
|
||||
info "New testnet genesis data received. Starting with a fresh database."
|
||||
|
||||
proc loadTestnetMetadata(conf: BeaconNodeConf): TestnetMetadata =
|
||||
Json.loadFile(conf.dataDir / networkMetadataFile, TestnetMetadata)
|
||||
|
||||
proc obtainTestnetKey(conf: BeaconNodeConf): Future[ValidatorPrivKey] {.async.} =
|
||||
await doUpdateTestnet(conf)
|
||||
let
|
||||
metadata = loadTestnetMetadata(conf)
|
||||
privKeyName = validatorFileBaseName(rand(metadata.userValidatorsRange)) & ".privkey"
|
||||
privKeyContent = await downloadFile(testnetsBaseUrl // $conf.network // privKeyName)
|
||||
|
||||
return ValidatorPrivKey.init(privKeyContent)
|
||||
|
||||
proc saveValidatorKey(key: ValidatorPrivKey, conf: BeaconNodeConf) =
|
||||
let filename = conf.dataDir / dataDirValidators / $key.pubKey
|
||||
writeFile(filename, $key)
|
||||
|
||||
proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async.} =
|
||||
new result
|
||||
result.config = conf
|
||||
|
||||
if conf.network in {testnet0, testnet1}:
|
||||
await doUpdateTestnet(conf)
|
||||
|
||||
result.attachedValidators = ValidatorPool.init
|
||||
init result.mainchainMonitor, "", Port(0) # TODO: specify geth address and port
|
||||
|
||||
let trieDB = trieDB newChainDb(string conf.dataDir)
|
||||
let trieDB = trieDB newChainDb(string conf.databaseDir)
|
||||
result.db = BeaconChainDB.init(trieDB)
|
||||
|
||||
# TODO this is problably not the right place to ensure that db is sane..
|
||||
@ -43,8 +97,15 @@ proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async
|
||||
|
||||
let headBlock = result.db.getHeadBlock()
|
||||
if headBlock.isNone():
|
||||
var snapshotFile = conf.dataDir / genesisFile
|
||||
if conf.stateSnapshot.isSome:
|
||||
snapshotFile = conf.stateSnapshot.get.string
|
||||
elif not fileExists(snapshotFile):
|
||||
error "Nimbus database not initialized. Please specify the initial state snapshot file."
|
||||
quit 1
|
||||
|
||||
let
|
||||
tailState = result.config.stateSnapshot.get()
|
||||
tailState = Json.loadFile(snapshotFile, BeaconState)
|
||||
tailBlock = get_initial_beacon_block(tailState)
|
||||
blockRoot = hash_tree_root_final(tailBlock)
|
||||
|
||||
@ -62,11 +123,15 @@ proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async
|
||||
result.blockPool = BlockPool.init(result.db)
|
||||
result.attestationPool = AttestationPool.init(result.blockPool)
|
||||
|
||||
result.network = await createEth2Node(Port conf.tcpPort, Port conf.udpPort)
|
||||
result.network = await createEth2Node(conf)
|
||||
|
||||
let state = result.network.protocolState(BeaconSync)
|
||||
state.node = result
|
||||
state.db = result.db
|
||||
let sync = result.network.protocolState(BeaconSync)
|
||||
sync.networkId = case conf.network
|
||||
of mainnet: 1.uint64
|
||||
of ephemeralNetwork: 1000.uint64
|
||||
of testnet0, testnet1: loadTestnetMetadata(conf).networkId
|
||||
sync.node = result
|
||||
sync.db = result.db
|
||||
|
||||
let head = result.blockPool.get(result.db.getHeadBlock().get())
|
||||
|
||||
@ -86,6 +151,10 @@ proc connectToNetwork(node: BeaconNode) {.async.} =
|
||||
for ln in lines(bootstrapFile):
|
||||
bootstrapNodes.add BootstrapAddr.init(string ln)
|
||||
|
||||
if node.config.network in {testnet0, testnet1}:
|
||||
let metadata = loadTestnetMetadata(node.config)
|
||||
bootstrapNodes.add metadata.bootstrapNodes
|
||||
|
||||
if bootstrapNodes.len > 0:
|
||||
info "Connecting to bootstrap nodes", bootstrapNodes
|
||||
else:
|
||||
@ -147,18 +216,24 @@ template findIt(s: openarray, predicate: untyped): int =
|
||||
break
|
||||
res
|
||||
|
||||
proc addLocalValidators*(node: BeaconNode) =
|
||||
for privKey in node.config.validators:
|
||||
let
|
||||
pubKey = privKey.pubKey()
|
||||
proc addLocalValidator(node: BeaconNode, validatorKey: ValidatorPrivKey) =
|
||||
let pubKey = validatorKey.pubKey()
|
||||
|
||||
let idx = node.state.data.validator_registry.findIt(it.pubKey == pubKey)
|
||||
if idx == -1:
|
||||
warn "Validator not in registry", pubKey
|
||||
else:
|
||||
debug "Attaching validator", validator = shortValidatorKey(node, idx),
|
||||
idx, pubKey
|
||||
node.attachedValidators.addLocalValidator(idx, pubKey, privKey)
|
||||
let idx = node.state.data.validator_registry.findIt(it.pubKey == pubKey)
|
||||
if idx == -1:
|
||||
warn "Validator not in registry", pubKey
|
||||
else:
|
||||
debug "Attaching validator", validator = shortValidatorKey(node, idx),
|
||||
idx, pubKey
|
||||
node.attachedValidators.addLocalValidator(idx, pubKey, validatorKey)
|
||||
|
||||
proc addLocalValidators(node: BeaconNode) =
|
||||
for validatorKeyFile in node.config.validators:
|
||||
node.addLocalValidator validatorKeyFile.load
|
||||
|
||||
for kind, file in walkDir(node.config.localValidatorsDir):
|
||||
if kind in {pcFile, pcLinkToFile}:
|
||||
node.addLocalValidator ValidatorPrivKey.init(readFile(file).string)
|
||||
|
||||
info "Local validators attached ", count = node.attachedValidators.count
|
||||
|
||||
@ -584,7 +659,8 @@ proc createPidFile(filename: string) =
|
||||
addQuitProc proc {.noconv.} = removeFile gPidFile
|
||||
|
||||
when isMainModule:
|
||||
let config = load BeaconNodeConf
|
||||
let config = BeaconNodeConf.load(version = fullVersionStr())
|
||||
|
||||
if config.logLevel != LogLevel.NONE:
|
||||
setLogLevel(config.logLevel)
|
||||
|
||||
@ -595,6 +671,41 @@ when isMainModule:
|
||||
config.genesisOffset, config.outputStateFile.string)
|
||||
quit 0
|
||||
|
||||
of importValidator:
|
||||
template reportFailureFor(keyExpr) =
|
||||
error "Failed to import validator key", key = keyExpr
|
||||
programResult = 1
|
||||
|
||||
var downloadKey = true
|
||||
|
||||
if config.key.isSome:
|
||||
downloadKey = false
|
||||
try:
|
||||
ValidatorPrivKey.init(config.key.get).saveValidatorKey(config)
|
||||
except:
|
||||
reportFailureFor config.key.get
|
||||
|
||||
if config.keyFile.isSome:
|
||||
downloadKey = false
|
||||
try:
|
||||
config.keyFile.get.load.saveValidatorKey(config)
|
||||
except:
|
||||
reportFailureFor config.keyFile.get.string
|
||||
|
||||
if downloadKey:
|
||||
if config.network in {testnet0, testnet1}:
|
||||
try:
|
||||
(waitFor obtainTestnetKey(config)).saveValidatorKey(config)
|
||||
except:
|
||||
error "Failed to download key", err = getCurrentExceptionMsg()
|
||||
quit 1
|
||||
else:
|
||||
echo "Validator keys can be downloaded only for testnets"
|
||||
quit 1
|
||||
|
||||
of updateTestnet:
|
||||
waitFor doUpdateTestnet(config)
|
||||
|
||||
of noCommand:
|
||||
waitFor synchronizeClock()
|
||||
createPidFile(config.dataDir.string / "beacon_node.pid")
|
||||
|
@ -229,4 +229,4 @@ type
|
||||
connection*: ValidatorConnection
|
||||
|
||||
ValidatorPool* = object
|
||||
validators*: Table[ValidatorPubKey, AttachedValidator]
|
||||
validators*: Table[ValidatorPubKey, AttachedValidator]
|
||||
|
@ -1,24 +1,36 @@
|
||||
import
|
||||
os, options,
|
||||
os, options, strformat,
|
||||
confutils/defs, chronicles/options as chroniclesOptions,
|
||||
json_serialization,
|
||||
spec/[crypto, datatypes], time
|
||||
spec/[crypto, datatypes], time, version
|
||||
|
||||
export
|
||||
json_serialization
|
||||
defs
|
||||
|
||||
type
|
||||
ValidatorKeyPath* = distinct string
|
||||
ValidatorKeyPath* = TypedInputFile[ValidatorPrivKey, Txt, "privkey"]
|
||||
|
||||
StartUpCommand* = enum
|
||||
noCommand
|
||||
createChain
|
||||
importValidator
|
||||
updateTestnet
|
||||
|
||||
Network* = enum
|
||||
ephemeralNetwork
|
||||
testnet0
|
||||
testnet1
|
||||
mainnet
|
||||
|
||||
BeaconNodeConf* = object
|
||||
logLevel* {.
|
||||
desc: "Sets the log level",
|
||||
defaultValue: enabledLogLevel
|
||||
.}: LogLevel
|
||||
defaultValue: enabledLogLevel.}: LogLevel
|
||||
|
||||
network* {.
|
||||
desc: "The network Nimbus should connect to"
|
||||
longform: "network"
|
||||
shortform: "n"
|
||||
defaultValue: testnet0.}: Network
|
||||
|
||||
case cmd* {.
|
||||
command
|
||||
@ -28,7 +40,7 @@ type
|
||||
dataDir* {.
|
||||
desc: "The directory where nimbus will store all blockchain data."
|
||||
shortform: "d"
|
||||
defaultValue: getConfigDir() / "nimbus".}: DirPath
|
||||
defaultValue: config.defaultDataDir().}: OutDir
|
||||
|
||||
bootstrapNodes* {.
|
||||
desc: "Specifies one or more bootstrap nodes to use when connecting to the network."
|
||||
@ -38,36 +50,36 @@ type
|
||||
bootstrapNodesFile* {.
|
||||
desc: "Specifies a line-delimited file of bootsrap Ethereum network addresses"
|
||||
shortform: "f"
|
||||
defaultValue: "".}: FilePath
|
||||
defaultValue: "".}: InputFile
|
||||
|
||||
tcpPort* {.
|
||||
desc: "TCP listening port".}: int
|
||||
desc: "TCP listening port"
|
||||
defaultValue: config.defaultPort().}: int
|
||||
|
||||
udpPort* {.
|
||||
desc: "UDP listening port".}: int
|
||||
desc: "UDP listening port",
|
||||
defaultValue: config.defaultPort().}: int
|
||||
|
||||
validators* {.
|
||||
required
|
||||
desc: "Path to a validator private key, as generated by validator_keygen"
|
||||
longform: "validator"
|
||||
shortform: "v".}: seq[ValidatorPrivKey]
|
||||
shortform: "v".}: seq[ValidatorKeyPath]
|
||||
|
||||
stateSnapshot* {.
|
||||
desc: "Json file specifying a recent state snapshot"
|
||||
shortform: "s".}: Option[BeaconState]
|
||||
shortform: "s".}: Option[TypedInputFile[BeaconState, Json, "json"]]
|
||||
|
||||
of createChain:
|
||||
validatorsDir* {.
|
||||
desc: "Directory containing validator descriptors named vXXXXXXX.deposit.json"
|
||||
shortform: "d".}: DirPath
|
||||
shortform: "d".}: InputDir
|
||||
|
||||
numValidators* {.
|
||||
desc: ""
|
||||
shortform: "n".}: int
|
||||
desc: "The number of validators in the newly created chain".}: int
|
||||
|
||||
firstValidator* {.
|
||||
desc: "index of first validator to add to validator list"
|
||||
shortform: "o"
|
||||
defaultValue: 0.}: int
|
||||
|
||||
genesisOffset* {.
|
||||
@ -78,27 +90,36 @@ type
|
||||
outputStateFile* {.
|
||||
desc: "Output file where to write the initial state snapshot"
|
||||
longform: "out"
|
||||
shortform: "o".}: OutFilePath
|
||||
shortform: "o".}: OutFile
|
||||
|
||||
proc readFileBytes(path: string): seq[byte] =
|
||||
cast[seq[byte]](readFile(path))
|
||||
of importValidator:
|
||||
keyFile* {.
|
||||
desc: "File with validator key to be imported (in hex form)".}: Option[ValidatorKeyPath]
|
||||
|
||||
proc loadPrivKey*(p: ValidatorKeyPath): ValidatorPrivKey =
|
||||
ValidatorPrivKey.init(readFileBytes(string(p) & ".privkey"))
|
||||
key* {.
|
||||
desc: "Validator key to be imported (in hex form)".}: Option[string]
|
||||
|
||||
proc parseCmdArg*(T: type ValidatorKeyPath, input: TaintedString): T =
|
||||
result = T(input)
|
||||
discard loadPrivKey(result)
|
||||
of updateTestnet:
|
||||
discard
|
||||
|
||||
template mustBeFilePath(input: TaintedString) =
|
||||
if not fileExists(string input):
|
||||
raise newException(ValueError, "")
|
||||
proc defaultDataDir*(conf: BeaconNodeConf): string =
|
||||
if conf.network == ephemeralNetwork:
|
||||
getCurrentDir() / "beacon-node-cache"
|
||||
|
||||
template handledAsJsonFilename(T: untyped) {.dirty.} =
|
||||
proc parseCmdArg*(_: type T, input: TaintedString): T =
|
||||
input.mustBeFilePath
|
||||
return Json.loadFile(string(input), T)
|
||||
else:
|
||||
let dataDir = when defined(windows):
|
||||
"AppData" / "Roaming" / "Nimbus"
|
||||
elif defined(macosx):
|
||||
"Library" / "Application Support" / "Nimbus"
|
||||
else:
|
||||
".cache" / "nimbus"
|
||||
|
||||
getHomeDir() / dataDir / "BeaconNode" / $conf.network
|
||||
|
||||
proc defaultPort*(conf: BeaconNodeConf): int =
|
||||
(if conf.network == testnet0: 9630 else: 9632) + ord(useRLPx)
|
||||
|
||||
proc validatorFileBaseName*(validatorIdx: int): string =
|
||||
# there can apparently be tops 4M validators so we use 7 digits..
|
||||
fmt"v{validatorIdx:07}"
|
||||
|
||||
handledAsJsonFilename BeaconState
|
||||
handledAsJsonFilename Deposit
|
||||
handledAsJsonFilename ValidatorPrivKey
|
||||
|
@ -1,14 +1,13 @@
|
||||
const
|
||||
useDEVP2P = not defined(withLibP2P)
|
||||
|
||||
import
|
||||
options, chronos, version
|
||||
options, chronos, json_serialization,
|
||||
spec/digest, version, conf
|
||||
|
||||
const
|
||||
clientId = "Nimbus beacon node v" & versionAsStr
|
||||
clientId = "Nimbus beacon node v" & fullVersionStr()
|
||||
|
||||
when useDEVP2P:
|
||||
when useRLPx:
|
||||
import
|
||||
os,
|
||||
eth/[rlp, p2p, keys], gossipsub_protocol
|
||||
|
||||
export
|
||||
@ -20,12 +19,26 @@ when useDEVP2P:
|
||||
|
||||
template libp2pProtocol*(name, version: string) {.pragma.}
|
||||
|
||||
proc createEth2Node*(tcpPort, udpPort: Port): Future[EthereumNode] {.async.} =
|
||||
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)
|
||||
|
||||
let
|
||||
keys = newKeyPair()
|
||||
keys = KeyPair(seckey: privKey, pubkey: privKey.getPublicKey())
|
||||
address = Address(ip: parseIpAddress("127.0.0.1"),
|
||||
tcpPort: tcpPort,
|
||||
udpPort: udpPort)
|
||||
tcpPort: Port conf.tcpPort,
|
||||
udpPort: Port conf.udpPort)
|
||||
|
||||
return newEthereumNode(keys, address, 0,
|
||||
nil, clientId, minPeers = 1)
|
||||
@ -38,7 +51,7 @@ when useDEVP2P:
|
||||
|
||||
else:
|
||||
import
|
||||
libp2p/daemon/daemonapi, json_serialization, chronicles,
|
||||
libp2p/daemon/daemonapi, chronicles,
|
||||
libp2p_backend
|
||||
|
||||
export
|
||||
@ -62,7 +75,7 @@ else:
|
||||
proc init*(T: type BootstrapAddr, str: string): T =
|
||||
Json.decode(str, PeerInfo)
|
||||
|
||||
proc createEth2Node*(tcpPort, udpPort: Port): Future[Eth2Node] {.async.} =
|
||||
proc createEth2Node*(conf: BeaconNodeConf): Future[Eth2Node] {.async.} =
|
||||
var node = new Eth2Node
|
||||
await node.init()
|
||||
return node
|
||||
@ -72,7 +85,8 @@ else:
|
||||
for bootstrapNode in bootstrapNodes:
|
||||
try:
|
||||
await node.daemon.connect(bootstrapNode.peer, bootstrapNode.addresses)
|
||||
await node.getPeer(bootstrapNode.peer).performProtocolHandshakes()
|
||||
let peer = node.getPeer(bootstrapNode.peer)
|
||||
await peer.performProtocolHandshakes()
|
||||
except PeerDisconnected:
|
||||
error "Failed to connect to bootstrap node", node = bootstrapNode
|
||||
|
||||
@ -83,3 +97,15 @@ else:
|
||||
proc loadConnectionAddressFile*(filename: string): PeerInfo =
|
||||
Json.loadFile(filename, PeerInfo)
|
||||
|
||||
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
|
||||
|
||||
|
@ -77,6 +77,7 @@ type
|
||||
Bytes = seq[byte]
|
||||
|
||||
DisconnectionReason* = enum
|
||||
UselessPeer
|
||||
BreachOfProtocol
|
||||
|
||||
PeerDisconnected* = object of CatchableError
|
||||
|
@ -19,6 +19,7 @@ type
|
||||
ValidatorSet = seq[Validator]
|
||||
|
||||
BeaconSyncState* = ref object
|
||||
networkId*: uint64
|
||||
node*: BeaconNode
|
||||
db*: BeaconChainDB
|
||||
|
||||
@ -70,10 +71,10 @@ p2pProtocol BeaconSync(version = 1,
|
||||
networkState = BeaconSyncState):
|
||||
|
||||
onPeerConnected do(peer: Peer):
|
||||
const
|
||||
let
|
||||
protocolVersion = 1 # TODO: Spec doesn't specify this yet
|
||||
networkId = 1
|
||||
let node = peer.networkState.node
|
||||
node = peer.networkState.node
|
||||
networkId = peer.networkState.networkId
|
||||
|
||||
var
|
||||
latestFinalizedRoot: Eth2Digest # TODO
|
||||
@ -84,6 +85,11 @@ p2pProtocol BeaconSync(version = 1,
|
||||
let m = await handshake(peer, timeout = 500,
|
||||
status(networkId, latestFinalizedRoot,
|
||||
latestFinalizedEpoch, bestRoot, bestSlot))
|
||||
|
||||
if m.networkId != networkId:
|
||||
await peer.disconnect(UselessPeer)
|
||||
return
|
||||
|
||||
let bestDiff = cmp((latestFinalizedEpoch, bestSlot), (m.latestFinalizedEpoch, m.bestSlot))
|
||||
if bestDiff == 0:
|
||||
# Nothing to do?
|
||||
@ -116,7 +122,7 @@ p2pProtocol BeaconSync(version = 1,
|
||||
|
||||
proc status(
|
||||
peer: Peer,
|
||||
networkId: int,
|
||||
networkId: uint64,
|
||||
latestFinalizedRoot: Eth2Digest,
|
||||
latestFinalizedEpoch: Epoch,
|
||||
bestRoot: Eth2Digest,
|
||||
|
@ -1,27 +1,33 @@
|
||||
import
|
||||
os, ospaths, strutils, strformat,
|
||||
chronos, nimcrypto, json_serialization, confutils,
|
||||
chronos, blscurve, nimcrypto, json_serialization, confutils,
|
||||
spec/[datatypes, digest, crypto], conf, time, ssz,
|
||||
../tests/testutil
|
||||
|
||||
proc writeTextFile(filename: string, contents: string) =
|
||||
writeFile(filename, contents)
|
||||
echo "Wrote ", filename
|
||||
|
||||
proc writeFile(filename: string, value: auto) =
|
||||
Json.saveFile(filename, value, pretty = true)
|
||||
echo "Wrote ", filename
|
||||
|
||||
cli do (validators: int = 100000,
|
||||
outputDir: string = "validators"):
|
||||
cli do (validators: int = 125000,
|
||||
outputDir: string = "validators",
|
||||
generateFakeKeys = true):
|
||||
|
||||
for i in 0 ..< validators:
|
||||
# there can apparently be tops 4M validators so we use 7 digits..
|
||||
let
|
||||
depositFn = outputDir / &"v{i:07}.deposit.json"
|
||||
privKeyFn = outputDir / &"v{i:07}.privkey.json"
|
||||
v = validatorFileBaseName(i)
|
||||
depositFn = outputDir / v & ".deposit.json"
|
||||
privKeyFn = outputDir / v & ".privkey"
|
||||
|
||||
if existsFile(depositFn) and existsFile(privKeyFn):
|
||||
continue
|
||||
|
||||
let
|
||||
privKey = makeFakeValidatorPrivKey(i)
|
||||
privKey = if generateFakeKeys: makeFakeValidatorPrivKey(i)
|
||||
else: ValidatorPrivKey.random
|
||||
pubKey = privKey.pubKey()
|
||||
|
||||
let
|
||||
@ -46,7 +52,8 @@ cli do (validators: int = 100000,
|
||||
proof_of_possession: proofOfPossession,
|
||||
withdrawal_credentials: withdrawalCredentials)))
|
||||
|
||||
writeFile(privKeyFn, privKey)
|
||||
writeTextFile(privKeyFn, $privKey)
|
||||
writeFile(depositFn, deposit)
|
||||
|
||||
echo "Keys generated by this tool are only for testing!"
|
||||
if generateFakeKeys:
|
||||
echo "Keys generated by this tool are only for testing!"
|
||||
|
@ -1,3 +1,6 @@
|
||||
const
|
||||
useRLPx* = not defined(withLibP2P)
|
||||
|
||||
const
|
||||
versionMajor* = 0
|
||||
versionMinor* = 1
|
||||
@ -6,3 +9,5 @@ const
|
||||
template versionAsStr*: string =
|
||||
$versionMajor & "." & $versionMinor & "." & $versionBuild
|
||||
|
||||
proc fullVersionStr*: string =
|
||||
versionAsStr & (if useRLPx: " rlpx" else: " libp2p")
|
||||
|
@ -16,17 +16,18 @@ V_PREFIX="$VALIDATORS_DIR/v$(printf '%06d' ${1})"
|
||||
PORT=$(printf '5%04d' ${1})
|
||||
|
||||
$BEACON_NODE_BIN \
|
||||
--network:ephemeralNetwork \
|
||||
--dataDir:$DATA_DIR \
|
||||
--validator:${V_PREFIX}0.privkey.json \
|
||||
--validator:${V_PREFIX}1.privkey.json \
|
||||
--validator:${V_PREFIX}2.privkey.json \
|
||||
--validator:${V_PREFIX}3.privkey.json \
|
||||
--validator:${V_PREFIX}4.privkey.json \
|
||||
--validator:${V_PREFIX}5.privkey.json \
|
||||
--validator:${V_PREFIX}6.privkey.json \
|
||||
--validator:${V_PREFIX}7.privkey.json \
|
||||
--validator:${V_PREFIX}8.privkey.json \
|
||||
--validator:${V_PREFIX}9.privkey.json \
|
||||
--validator:${V_PREFIX}0.privkey \
|
||||
--validator:${V_PREFIX}1.privkey \
|
||||
--validator:${V_PREFIX}2.privkey \
|
||||
--validator:${V_PREFIX}3.privkey \
|
||||
--validator:${V_PREFIX}4.privkey \
|
||||
--validator:${V_PREFIX}5.privkey \
|
||||
--validator:${V_PREFIX}6.privkey \
|
||||
--validator:${V_PREFIX}7.privkey \
|
||||
--validator:${V_PREFIX}8.privkey \
|
||||
--validator:${V_PREFIX}9.privkey \
|
||||
--tcpPort:$PORT \
|
||||
--udpPort:$PORT \
|
||||
--stateSnapshot:$SNAPSHOT_FILE \
|
||||
|
Loading…
x
Reference in New Issue
Block a user