2019-10-28 23:07:31 +00:00
|
|
|
import
|
2019-11-12 14:57:33 +00:00
|
|
|
confutils, strutils, strformat, os
|
2019-10-28 23:07:31 +00:00
|
|
|
|
|
|
|
const
|
|
|
|
rootDir = thisDir() / ".."
|
2020-01-13 00:03:52 +00:00
|
|
|
bootstrapTxtFileName = "bootstrap_nodes.txt"
|
|
|
|
bootstrapYamlFileName = "boot_enr.yaml"
|
|
|
|
depositContractFileName = "deposit_contract.txt"
|
2019-10-28 23:07:31 +00:00
|
|
|
genesisFile = "genesis.ssz"
|
2020-04-27 19:03:03 +00:00
|
|
|
configFile = "config.yaml"
|
2019-10-28 23:07:31 +00:00
|
|
|
testnetsRepo = "eth2-testnets"
|
2020-02-07 07:13:38 +00:00
|
|
|
web3Url = "wss://goerli.infura.io/ws/v3/809a18497dd74102b5f37d25aae3c85a"
|
2019-11-05 13:00:11 +00:00
|
|
|
|
|
|
|
let
|
2019-11-09 10:46:34 +00:00
|
|
|
testnetsOrg = getEnv("ETH2_TESTNETS_ORG", "eth2-clients")
|
2019-11-05 13:00:11 +00:00
|
|
|
testnetsGitUrl = getEnv("ETH2_TESTNETS_GIT_URL", "https://github.com/" & testnetsOrg & "/" & testnetsRepo)
|
2019-10-28 23:07:31 +00:00
|
|
|
|
2019-11-09 10:46:34 +00:00
|
|
|
mode = Verbose
|
|
|
|
|
2019-10-28 23:07:31 +00:00
|
|
|
proc validateTestnetName(parts: openarray[string]): auto =
|
|
|
|
if parts.len != 2:
|
|
|
|
echo "The testnet name should have the format `client/network-name`"
|
|
|
|
quit 1
|
|
|
|
(parts[0], parts[1])
|
|
|
|
|
2020-02-25 01:49:47 +00:00
|
|
|
cli do (skipGoerliKey {.
|
|
|
|
desc: "Don't prompt for an Eth1 Goerli key to become a validator" .}: bool,
|
2020-04-27 19:03:03 +00:00
|
|
|
|
|
|
|
constPreset {.
|
|
|
|
desc: "The Ethereum 2.0 const preset of the network (optional)"
|
2020-04-28 10:43:40 +00:00
|
|
|
name: "const-preset" .} = "",
|
|
|
|
|
|
|
|
devBuild {.
|
|
|
|
desc: "Enables more extensive logging and debugging support"
|
|
|
|
name: "dev-build" .} = false,
|
2020-04-27 19:03:03 +00:00
|
|
|
|
|
|
|
testnetName {.argument .}: string):
|
2019-10-28 23:07:31 +00:00
|
|
|
let
|
|
|
|
nameParts = testnetName.split "/"
|
|
|
|
(team, testnet) = if nameParts.len > 1: validateTestnetName nameParts
|
|
|
|
else: ("nimbus", testnetName)
|
|
|
|
|
|
|
|
let
|
|
|
|
buildDir = rootDir / "build"
|
|
|
|
allTestnetsDir = buildDir / testnetsRepo
|
|
|
|
|
2019-11-07 20:10:59 +00:00
|
|
|
rmDir(allTestnetsDir)
|
|
|
|
cd buildDir
|
2019-12-10 19:49:42 +00:00
|
|
|
|
2020-01-13 00:03:52 +00:00
|
|
|
exec &"git clone --quiet --depth=1 {testnetsGitUrl}"
|
|
|
|
|
|
|
|
var
|
|
|
|
depositContractOpt = ""
|
|
|
|
bootstrapFileOpt = ""
|
2019-10-28 23:07:31 +00:00
|
|
|
|
|
|
|
let testnetDir = allTestnetsDir / team / testnet
|
2019-11-12 14:57:33 +00:00
|
|
|
if not system.dirExists(testnetDir):
|
2019-10-28 23:07:31 +00:00
|
|
|
echo &"No metadata files exists for the '{testnetName}' testnet"
|
|
|
|
quit 1
|
|
|
|
|
|
|
|
proc checkRequiredFile(fileName: string) =
|
|
|
|
let filePath = testnetDir / fileName
|
2019-11-12 14:57:33 +00:00
|
|
|
if not system.fileExists(filePath):
|
2019-10-28 23:07:31 +00:00
|
|
|
echo &"The required file {fileName} is not present in '{testnetDir}'."
|
|
|
|
quit 1
|
|
|
|
|
|
|
|
checkRequiredFile genesisFile
|
|
|
|
|
2020-01-13 00:03:52 +00:00
|
|
|
let bootstrapTxtFile = testnetDir / bootstrapTxtFileName
|
|
|
|
if system.fileExists(bootstrapTxtFile):
|
|
|
|
bootstrapFileOpt = &"--bootstrap-file=\"{bootstrapTxtFile}\""
|
|
|
|
else:
|
|
|
|
let bootstrapYamlFile = testnetDir / bootstrapYamlFileName
|
|
|
|
if system.fileExists(bootstrapYamlFile):
|
|
|
|
bootstrapFileOpt = &"--enr-bootstrap-file=\"{bootstrapYamlFile}\""
|
|
|
|
else:
|
|
|
|
echo "Warning: the network metadata doesn't include a bootstrap file"
|
|
|
|
|
2020-04-27 19:03:03 +00:00
|
|
|
var preset = testnetDir / configFile
|
|
|
|
if not system.fileExists(preset):
|
|
|
|
preset = constPreset
|
|
|
|
if preset.len == 0: preset = "minimal"
|
|
|
|
|
2019-10-28 23:07:31 +00:00
|
|
|
let
|
|
|
|
dataDirName = testnetName.replace("/", "_")
|
2020-01-27 18:53:12 +00:00
|
|
|
.replace("(", "_")
|
|
|
|
.replace(")", "_")
|
2019-10-28 23:07:31 +00:00
|
|
|
dataDir = buildDir / "data" / dataDirName
|
2019-12-02 23:27:59 +00:00
|
|
|
validatorsDir = dataDir / "validators"
|
2019-12-03 11:32:27 +00:00
|
|
|
dumpDir = dataDir / "dump"
|
2019-10-28 23:07:31 +00:00
|
|
|
beaconNodeBinary = buildDir / "beacon_node_" & dataDirName
|
2020-02-06 11:44:11 +00:00
|
|
|
var
|
2020-02-03 16:06:35 +00:00
|
|
|
nimFlags = "-d:chronicles_log_level=TRACE " & getEnv("NIM_PARAMS")
|
2019-10-28 23:07:31 +00:00
|
|
|
|
2020-04-28 10:43:40 +00:00
|
|
|
if devBuild:
|
|
|
|
nimFlags.add """ -d:"chronicles_sinks=textlines,json[file(nbc.log)]" """
|
|
|
|
|
2020-01-13 00:03:52 +00:00
|
|
|
let depositContractFile = testnetDir / depositContractFileName
|
2019-11-12 14:57:33 +00:00
|
|
|
if system.fileExists(depositContractFile):
|
2019-10-29 00:27:13 +00:00
|
|
|
depositContractOpt = "--deposit-contract=" & readFile(depositContractFile).strip
|
|
|
|
|
2019-11-12 14:57:33 +00:00
|
|
|
if system.dirExists(dataDir):
|
2019-12-09 15:30:02 +00:00
|
|
|
block resetDataDir:
|
|
|
|
# We reset the testnet data dir if the existing data dir is
|
|
|
|
# incomplete (it misses a genesis file) or if it has a genesis
|
|
|
|
# file from an older testnet:
|
|
|
|
if system.fileExists(dataDir/genesisFile):
|
|
|
|
let localGenesisContent = readFile(dataDir/genesisFile)
|
|
|
|
let testnetGenesisContent = readFile(testnetDir/genesisFile)
|
|
|
|
if localGenesisContent == testnetGenesisContent:
|
|
|
|
break
|
|
|
|
echo "Detected testnet restart. Deleting previous database..."
|
|
|
|
rmDir dataDir
|
2019-11-09 10:46:34 +00:00
|
|
|
|
2019-10-28 23:07:31 +00:00
|
|
|
cd rootDir
|
2020-04-28 10:43:40 +00:00
|
|
|
exec &"""nim c {nimFlags} -d:"const_preset={preset}" -o:"{beaconNodeBinary}" beacon_chain/beacon_node.nim"""
|
2019-12-02 23:27:59 +00:00
|
|
|
|
2019-12-03 11:32:27 +00:00
|
|
|
mkDir dumpDir
|
|
|
|
|
2019-12-04 17:56:36 +00:00
|
|
|
proc execIgnoringExitCode(s: string) =
|
|
|
|
# reduces the error output when interrupting an external command with Ctrl+C
|
|
|
|
try:
|
|
|
|
exec s
|
|
|
|
except OsError:
|
|
|
|
discard
|
|
|
|
|
2020-02-25 01:49:47 +00:00
|
|
|
if not skipGoerliKey and depositContractOpt.len > 0 and not system.dirExists(validatorsDir):
|
2019-12-02 23:27:59 +00:00
|
|
|
mode = Silent
|
2019-12-04 17:56:36 +00:00
|
|
|
echo "\nPlease enter your Goerli Eth1 private key in hex form (e.g. 0x1a2...f3c) in order to become a validator (you'll need access to 32 GoETH)."
|
|
|
|
echo "Hit Enter to skip this."
|
|
|
|
# is there no other way to print without a trailing newline?
|
|
|
|
exec "printf '> '"
|
|
|
|
let privKey = readLineFromStdin()
|
|
|
|
if privKey.len > 0:
|
|
|
|
mkDir validatorsDir
|
|
|
|
mode = Verbose
|
2020-04-18 13:02:58 +00:00
|
|
|
exec replace(&"""{beaconNodeBinary} makeDeposits
|
2019-12-04 17:56:36 +00:00
|
|
|
--random-deposits=1
|
|
|
|
--deposits-dir="{validatorsDir}"
|
|
|
|
--deposit-private-key={privKey}
|
2020-02-07 07:13:38 +00:00
|
|
|
--web3-url={web3Url}
|
2019-12-04 17:56:36 +00:00
|
|
|
{depositContractOpt}
|
|
|
|
""", "\n", " ")
|
2020-02-07 07:13:38 +00:00
|
|
|
mode = Silent
|
|
|
|
echo "\nDeposit sent, wait for confirmation then press enter to continue"
|
|
|
|
discard readLineFromStdin()
|
2019-12-02 23:27:59 +00:00
|
|
|
|
2020-02-07 23:57:48 +00:00
|
|
|
let logLevel = getEnv("LOG_LEVEL")
|
|
|
|
var logLevelOpt = ""
|
|
|
|
if logLevel.len > 0:
|
2020-04-27 22:39:04 +00:00
|
|
|
logLevelOpt = &"""--log-level="{logLevel}" """
|
2020-02-07 23:57:48 +00:00
|
|
|
|
2019-12-02 23:27:59 +00:00
|
|
|
mode = Verbose
|
2019-12-04 17:56:36 +00:00
|
|
|
execIgnoringExitCode replace(&"""{beaconNodeBinary}
|
2019-10-28 23:07:31 +00:00
|
|
|
--data-dir="{dataDir}"
|
2020-03-18 19:36:22 +00:00
|
|
|
--dump
|
2020-02-07 07:13:38 +00:00
|
|
|
--web3-url={web3Url}
|
2020-01-13 00:03:52 +00:00
|
|
|
{bootstrapFileOpt}
|
2020-02-07 23:57:48 +00:00
|
|
|
{logLevelOpt}
|
2020-03-24 11:13:07 +00:00
|
|
|
{depositContractOpt}
|
2020-04-26 21:05:17 +00:00
|
|
|
--state-snapshot="{testnetDir/genesisFile}" """, "\n", " ")
|
2019-10-28 23:07:31 +00:00
|
|
|
|