Dumbed down the validator key import procedure

The previous idempotent scheme proved to be too slow, making it
harder to quickly re-assign validators on the servers.
This commit is contained in:
Zahary Karadjov 2019-03-26 01:26:11 +02:00
parent 5b1caaff41
commit d94d4f2606
4 changed files with 24 additions and 30 deletions

View File

@ -1,6 +1,6 @@
import import
std_shims/[os_shims, objects], net, sequtils, options, tables, osproc, random, net, sequtils, options, tables, osproc, random, strutils, times,
times, std_shims/[os_shims, objects],
chronos, chronicles, confutils, serialization/errors, chronos, chronicles, confutils, serialization/errors,
spec/[bitfield, datatypes, digest, crypto, beaconstate, helpers, validator], spec/[bitfield, datatypes, digest, crypto, beaconstate, helpers, validator],
conf, time, conf, time,
@ -42,7 +42,7 @@ template `//`(url, fragment: string): string =
proc downloadFile(url: string): Future[string] {.async.} = proc downloadFile(url: string): Future[string] {.async.} =
let (fileContents, errorCode) = execCmdEx("curl --fail " & url, options = {poUsePath}) let (fileContents, errorCode) = execCmdEx("curl --fail " & url, options = {poUsePath})
if errorCode != 0: if errorCode != 0:
raise newException(IOError, "Failed to download URL: " & url) raise newException(IOError, "Failed to download URL: " & url & "\n" & fileContents)
return fileContents return fileContents
proc updateTestnetMetadata(conf: BeaconNodeConf): Future[NetworkMetadata] {.async.} = proc updateTestnetMetadata(conf: BeaconNodeConf): Future[NetworkMetadata] {.async.} =
@ -62,18 +62,21 @@ proc updateTestnetMetadata(conf: BeaconNodeConf): Future[NetworkMetadata] {.asyn
let newGenesis = await downloadFile(testnetsBaseUrl // $conf.network // genesisFile) let newGenesis = await downloadFile(testnetsBaseUrl // $conf.network // genesisFile)
writeFile conf.dataDir / genesisFile, newGenesis writeFile conf.dataDir / genesisFile, newGenesis
proc obtainTestnetKey(conf: BeaconNodeConf): Future[ValidatorPrivKey] {.async.} = proc obtainTestnetKey(conf: BeaconNodeConf): Future[(string, string)] {.async.} =
let let
metadata = await updateTestnetMetadata(conf) metadata = await updateTestnetMetadata(conf)
privKeyName = validatorFileBaseName(rand(metadata.userValidatorsRange)) & ".privkey" privKeyName = validatorFileBaseName(rand(metadata.userValidatorsRange)) & ".privkey"
privKeyContent = await downloadFile(testnetsBaseUrl // $conf.network // privKeyName) privKeyContent = strip await downloadFile(testnetsBaseUrl // $conf.network // privKeyName)
return ValidatorPrivKey.init(privKeyContent) let key = ValidatorPrivKey.init(privKeyContent)
return (privKeyName, privKeyContent)
proc saveValidatorKey(key: ValidatorPrivKey, conf: BeaconNodeConf) = proc saveValidatorKey(keyName, key: string, conf: BeaconNodeConf) =
let validatorsDir = conf.dataDir / dataDirValidators let validatorsDir = conf.dataDir / dataDirValidators
let outputFile = validatorsDir / keyName
createDir validatorsDir createDir validatorsDir
writeFile(validatorsDir / $key.pubKey, $key) writeFile(outputFile, key)
info "Imported validator key", file = outputFile
proc persistentNodeId*(conf: BeaconNodeConf): string = proc persistentNodeId*(conf: BeaconNodeConf): string =
($ensureNetworkKeys(conf).pubKey)[0..5] ($ensureNetworkKeys(conf).pubKey)[0..5]
@ -693,6 +696,7 @@ proc start(node: BeaconNode) =
node.run() node.run()
when isMainModule: when isMainModule:
randomize()
let config = BeaconNodeConf.load(version = fullVersionStr()) let config = BeaconNodeConf.load(version = fullVersionStr())
if config.logLevel != LogLevel.NONE: if config.logLevel != LogLevel.NONE:
@ -734,31 +738,25 @@ when isMainModule:
of updateTestnet: of updateTestnet:
discard waitFor updateTestnetMetadata(config) discard waitFor updateTestnetMetadata(config)
of importValidators: of importValidator:
template reportFailureFor(keyExpr) = template reportFailureFor(keyExpr) =
error "Failed to import validator key", key = keyExpr error "Failed to import validator key", key = keyExpr
programResult = 1 programResult = 1
for key in config.keys:
try:
ValidatorPrivKey.init(key).saveValidatorKey(config)
except:
reportFailureFor key
for keyFile in config.keyFiles: for keyFile in config.keyFiles:
try: try:
keyFile.load.saveValidatorKey(config) saveValidatorKey(keyFile.string.extractFilename,
readFile(keyFile.string), config)
except: except:
reportFailureFor keyFile.string reportFailureFor keyFile.string
if (config.keys.len + config.keyFiles.len) == 0: if config.keyFiles.len == 0:
if config.network in ["testnet0", "testnet1"]: if config.network in ["testnet0", "testnet1"]:
try: try:
let key = waitFor obtainTestnetKey(config) let (keyName, key) = waitFor obtainTestnetKey(config)
saveValidatorKey(key, config) saveValidatorKey(keyName, key, config)
info "Imported validator", pubkey = key.pubKey
except: except:
error "Failed to download key", err = getCurrentExceptionMsg() stderr.write "Failed to download key\n", getCurrentExceptionMsg()
quit 1 quit 1
else: else:
echo "Validator keys can be downloaded only for testnets" echo "Validator keys can be downloaded only for testnets"

View File

@ -12,7 +12,7 @@ type
StartUpCommand* = enum StartUpCommand* = enum
noCommand noCommand
createTestnet createTestnet
importValidators importValidator
updateTestnet updateTestnet
BeaconNodeConf* = object BeaconNodeConf* = object
@ -112,15 +112,11 @@ type
outputNetwork* {. outputNetwork* {.
desc: "Output file where to write the initial state snapshot".}: OutFile desc: "Output file where to write the initial state snapshot".}: OutFile
of importValidators: of importValidator:
keyFiles* {. keyFiles* {.
longform: "keyfile" longform: "keyfile"
desc: "File with validator key to be imported (in hex form)".}: seq[ValidatorKeyPath] desc: "File with validator key to be imported (in hex form)".}: seq[ValidatorKeyPath]
keys* {.
longform: "key"
desc: "Validator key to be imported (in hex form)".}: seq[string]
of updateTestnet: of updateTestnet:
discard discard

View File

@ -18,7 +18,7 @@ NETWORK_DIR=$WWW_DIR/$NETWORK_NAME
for i in $(seq $FIRST_VALIDATOR $LAST_VALIDATOR); do for i in $(seq $FIRST_VALIDATOR $LAST_VALIDATOR); do
VALIDATOR=v$(printf '%07d' $i) VALIDATOR=v$(printf '%07d' $i)
beacon_chain/beacon_node --dataDir="$DATA_DIR/node-$NODE_ID" importValidators \ beacon_chain/beacon_node --dataDir="$DATA_DIR/node-$NODE_ID" importValidator \
--keyfile="$NETWORK_DIR/$VALIDATOR.privkey" --keyfile="$NETWORK_DIR/$VALIDATOR.privkey"
done done

View File

@ -8,11 +8,11 @@ source "$NETWORK_NAME.env"
cd .. cd ..
NIM_FLAGS="-d:release --stacktraces:on -d:SHARD_COUNT=$SHARD_COUNT -d:SLOTS_PER_EPOCH=$SLOTS_PER_EPOCH" NIM_FLAGS="-d:release --lineTrace:on -d:SHARD_COUNT=$SHARD_COUNT -d:SLOTS_PER_EPOCH=$SLOTS_PER_EPOCH"
nim c $NIM_FLAGS beacon_chain/beacon_node nim c $NIM_FLAGS beacon_chain/beacon_node
if [ ! -d ~/.cache/nimbus/BeaconNode/$NETWORK_NAME/validators ]; then if [ ! -d ~/.cache/nimbus/BeaconNode/$NETWORK_NAME/validators ]; then
beacon_chain/beacon_node --network=$NETWORK_NAME importValidators beacon_chain/beacon_node --network=$NETWORK_NAME importValidator
fi fi
beacon_chain/beacon_node beacon_chain/beacon_node