Merge branch 'master' of github.com:status-im/nim-beacon-chain

This commit is contained in:
Ștefan Talpalaru 2019-10-29 15:16:29 +01:00
commit 18d32f4882
No known key found for this signature in database
GPG Key ID: CBF7934204F1B6F9
29 changed files with 393 additions and 376 deletions

View File

@ -13,7 +13,7 @@ BUILD_SYSTEM_DIR := vendor/nimbus-build-system
# we don't want an error here, so we can handle things later, in the build-system-checks target
-include $(BUILD_SYSTEM_DIR)/makefiles/variables.mk
TOOLS := beacon_node bench_bls_sig_agggregation state_sim ncli_hash_tree_root ncli_pretty ncli_signing_root ncli_transition process_dashboard
TOOLS := beacon_node bench_bls_sig_agggregation state_sim ncli_hash_tree_root ncli_pretty ncli_signing_root ncli_transition process_dashboard deposit_contract
TOOLS_DIRS := beacon_chain benchmarks research ncli tests/simulation
TOOLS_CSV := $(subst $(SPACE),$(COMMA),$(TOOLS))

View File

@ -9,7 +9,7 @@
[![Gitter: #status-im/nimbus](https://img.shields.io/badge/gitter-status--im%2Fnimbus-orange.svg)](https://gitter.im/status-im/nimbus)
[![Status: #nimbus-general](https://img.shields.io/badge/status-nimbus--general-orange.svg)](https://get.status.im/chat/public/nimbus-general)
Nimbus beacon chain is a research implementation of the beacon chain component of the upcoming Ethereum Serenity upgrade, aka eth2. See the main [Nimbus](https://github.com/status-im/nimbus/) project for the bigger picture.
Nimbus beacon chain is a research implementation of the beacon chain component of the upcoming Ethereum Serenity upgrade, aka Eth2. See the main [Nimbus](https://github.com/status-im/nimbus/) project for the bigger picture.
## Interop (for other Eth2 clients)
@ -169,6 +169,17 @@ cd nim-beacon-chain
# Follow instructions above!
```
## Connecting to testnets
Nimbus should be able to connect to any of the testnets published in the [eth2-testnets repo](https://github.com/zah/eth2-testnets).
For example, connecting to our testnet0 is done with the following commands:
```bash
cd nim-beacon-chain
source env.sh
nim scripts/connect_to_testnet.nims nimbus/testnet0
```
## Beacon node simulation
The beacon node simulation will create a full peer-to-peer network of beacon nodes and validators, and run the beacon chain in real time. To change network parameters such as shard and validator counts, see [start.sh](tests/simulation/start.sh).

View File

@ -3,7 +3,7 @@ import
os, net, sequtils, tables, osproc, random, strutils, times, strformat,
# Nimble packages
stew/[objects, bitseqs],
stew/[objects, bitseqs, byteutils],
chronos, chronicles, confutils, metrics,
json_serialization/std/[options, sets], serialization/errors,
eth/trie/db, eth/trie/backends/rocksdb_backend, eth/async_utils,
@ -17,9 +17,7 @@ import
const
dataDirValidators = "validators"
networkMetadataFile = "network.json"
genesisFile = "genesis.json"
testnetsBaseUrl = "https://serenity-testnets.status.im"
hasPrompt = not defined(withoutPrompt)
# https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md#interop-metrics
@ -57,51 +55,6 @@ func databaseDir(conf: BeaconNodeConf): string =
template `//`(url, fragment: string): string =
url & "/" & fragment
proc downloadFile(url: string): Future[string] {.async.} =
# TODO We need a proper HTTP client able to perform HTTPS downloads
let tempFile = getTempDir() / "nimbus.download"
let cmd = "curl --fail -o " & quoteShell(tempFile) & " " & url
let (fileContents, errorCode) = execCmdEx(cmd, options = {poUsePath})
if errorCode != 0:
raise newException(IOError, "Failed external command: '" & cmd & "', exit code: " & $errorCode & ", output: '" & fileContents & "'")
return readFile(tempFile)
proc updateTestnetMetadata(conf: BeaconNodeConf): Future[NetworkMetadata] {.async.} =
let metadataUrl = testnetsBaseUrl // $conf.network // networkMetadataFile
let latestMetadata = await downloadFile(metadataUrl)
try:
result = Json.decode(latestMetadata, NetworkMetadata)
except SerializationError as err:
stderr.write "Error while loading the testnet metadata. Your client my be out of date.\n"
stderr.write err.formatMsg(metadataUrl), "\n"
stderr.write "Please follow the instructions at https://github.com/status-im/nim-beacon-chain " &
"in order to produce an up-to-date build.\n"
quit 1
let localMetadataFile = conf.dataDir / networkMetadataFile
if fileExists(localMetadataFile) and readFile(localMetadataFile).string == latestMetadata:
return
info "New testnet genesis data received. Starting with a fresh database."
createDir conf.dataDir.string
removeDir conf.databaseDir
writeFile localMetadataFile, latestMetadata
let newGenesis = await downloadFile(testnetsBaseUrl // $conf.network // genesisFile)
writeFile conf.dataDir / genesisFile, newGenesis
proc obtainTestnetKey(conf: BeaconNodeConf): Future[(string, string)] {.async.} =
let
metadata = await updateTestnetMetadata(conf)
privKeyName = validatorFileBaseName(rand(metadata.userValidatorsRange)) & ".privkey"
privKeyUrl = testnetsBaseUrl // $conf.network // privKeyName
privKeyContent = strip await downloadFile(privKeyUrl)
let key = ValidatorPrivKey.init(privKeyContent)
return (privKeyName, privKeyContent)
proc saveValidatorKey(keyName, key: string, conf: BeaconNodeConf) =
let validatorsDir = conf.dataDir / dataDirValidators
let outputFile = validatorsDir / keyName
@ -109,43 +62,40 @@ proc saveValidatorKey(keyName, key: string, conf: BeaconNodeConf) =
writeFile(outputFile, key)
info "Imported validator key", file = outputFile
proc initGenesis(node: BeaconNode) {.async.} =
template conf: untyped = node.config
var tailState: BeaconState
if conf.depositWeb3Url.len != 0:
info "Waiting for genesis state from eth1"
tailState = await node.mainchainMonitor.getGenesis()
func stateSnapshotPath*(conf: BeaconNodeConf): string =
if conf.stateSnapshot.isSome:
conf.stateSnapshot.get.string
else:
var snapshotFile = conf.dataDir / genesisFile
conf.dataDir / genesisFile
proc getStateFromSnapshot(node: BeaconNode, state: var BeaconState): bool =
template conf: untyped = node.config
let snapshotFile = conf.stateSnapshotPath
if fileExists(snapshotFile):
template loadSnapshot(Format) =
info "Importing snapshot file", path = snapshotFile
state = loadFile(Format, snapshotFile, BeaconState)
let ext = splitFile(snapshotFile).ext
try:
if conf.stateSnapshot.isSome:
snapshotFile = conf.stateSnapshot.get.string
if not fileExists(snapshotFile):
error "Nimbus database not initialized. Please specify the initial state snapshot file."
quit 1
template loadSnapshot(Format) =
info "Importing snapshot file", path = snapshotFile
tailState = loadFile(Format, snapshotFile, BeaconState)
let ext = splitFile(snapshotFile).ext
if cmpIgnoreCase(ext, ".ssz") == 0:
loadSnapshot SSZ
elif cmpIgnoreCase(ext, ".json") == 0:
loadSnapshot Json
else:
error "The --stateSnapshot option expects a json or a ssz file."
error "The --state-snapshot option expects a json or a ssz file."
quit 1
except SerializationError as err:
stderr.write "Failed to import ", snapshotFile, "\n"
stderr.write err.formatMsg(snapshotFile), "\n"
quit 1
result = true
proc commitGenesisState(node: BeaconNode, tailState: BeaconState) =
info "Got genesis state", hash = hash_tree_root(tailState)
node.forkVersion = tailState.fork.current_version
try:
let tailBlock = get_initial_beacon_block(tailState)
BlockPool.preInit(node.db, tailState, tailBlock)
@ -155,73 +105,33 @@ proc initGenesis(node: BeaconNode) {.async.} =
stderr.write getCurrentExceptionMsg(), "\n"
quit 1
proc addBootstrapNode(node: BeaconNode, bootstrapNode: BootstrapAddr) =
if bootstrapNode.isSameNode(node.networkIdentity):
node.isBootstrapNode = true
else:
node.bootstrapNodes.add bootstrapNode
proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async.} =
new result
result.onBeaconBlock = onBeaconBlock
result.config = conf
result.networkIdentity = getPersistentNetIdentity(conf)
result.nickname = if conf.nodename == "auto": shortForm(result.networkIdentity)
else: conf.nodename
result.nickname = if conf.nodeName == "auto": shortForm(result.networkIdentity)
else: conf.nodeName
template fail(args: varargs[untyped]) =
stderr.write args, "\n"
quit 1
if not conf.quickStart:
case conf.network
of "mainnet":
fail "The Serenity mainnet hasn't been launched yet"
of "testnet0", "testnet1":
result.networkMetadata = await updateTestnetMetadata(conf)
else:
try:
result.networkMetadata = Json.loadFile(conf.network, NetworkMetadata)
except SerializationError as err:
fail "Failed to load network metadata: \n", err.formatMsg(conf.network)
var metadataErrorMsg = ""
template checkCompatibility(metadataField, LOCAL_CONSTANT) =
let metadataValue = metadataField
if metadataValue != LOCAL_CONSTANT:
if metadataErrorMsg.len > 0: metadataErrorMsg.add " and"
metadataErrorMsg.add " -d:" & astToStr(LOCAL_CONSTANT) & "=" & $metadataValue &
" (instead of " & $LOCAL_CONSTANT & ")"
if result.networkMetadata.networkGeneration != semanticVersion:
let newerVersionRequired = result.networkMetadata.networkGeneration.int > semanticVersion
let newerOrOlder = if newerVersionRequired: "a newer" else: "an older"
stderr.write &"Connecting to '{conf.network}' requires {newerOrOlder} version of Nimbus. "
if newerVersionRequired:
stderr.write "Please follow the instructions at https://github.com/status-im/nim-beacon-chain " &
"in order to produce an up-to-date build.\n"
quit 1
checkCompatibility result.networkMetadata.numShards , SHARD_COUNT
checkCompatibility result.networkMetadata.slotDuration , SECONDS_PER_SLOT
checkCompatibility result.networkMetadata.slotsPerEpoch , SLOTS_PER_EPOCH
if metadataErrorMsg.len > 0:
fail "To connect to the ", conf.network, " network, please compile with", metadataErrorMsg
for bootNode in result.networkMetadata.bootstrapNodes:
if bootNode.isSameNode(result.networkIdentity):
result.isBootstrapNode = true
else:
result.bootstrapNodes.add bootNode
for bootNode in conf.bootstrapNodes:
result.bootstrapNodes.add BootstrapAddr.init(bootNode)
result.addBootstrapNode BootstrapAddr.init(bootNode)
let bootstrapFile = string conf.bootstrapNodesFile
if bootstrapFile.len > 0:
for ln in lines(bootstrapFile):
result.bootstrapNodes.add BootstrapAddr.init(string ln)
result.addBootstrapNode BootstrapAddr.init(string ln)
result.attachedValidators = ValidatorPool.init
if conf.depositWeb3Url.len != 0:
result.mainchainMonitor = MainchainMonitor.init(conf.depositWeb3Url, conf.depositContractAddress)
result.mainchainMonitor.start()
let trieDB = trieDB newChainDb(string conf.databaseDir)
result.db = BeaconChainDB.init(trieDB)
@ -231,8 +141,25 @@ proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async
# specified on command line? potentially, this should be the other way
# around...
var eth1MonitorStartBlock: Eth2Digest
if result.db.getHeadBlock().isNone():
await result.initGenesis()
var state: BeaconState
if not result.getStateFromSnapshot(state):
if conf.depositWeb3Url.len != 0:
result.mainchainMonitor = MainchainMonitor.init(conf.depositWeb3Url, conf.depositContractAddress, eth1MonitorStartBlock)
result.mainchainMonitor.start()
else:
stderr.write "No state snapshot (or web3 URL) provided\n"
quit 1
state = await result.mainchainMonitor.getGenesis()
else:
eth1MonitorStartBlock = state.eth1Data.block_hash
result.commitGenesisState(state)
if result.mainchainMonitor.isNil and conf.depositWeb3Url.len != 0:
result.mainchainMonitor = MainchainMonitor.init(conf.depositWeb3Url, conf.depositContractAddress, eth1MonitorStartBlock)
result.mainchainMonitor.start()
result.blockPool = BlockPool.init(result.db)
result.attestationPool = AttestationPool.init(result.blockPool)
@ -896,7 +823,7 @@ when hasPrompt:
else: Slot(0)
proc initPrompt(node: BeaconNode) =
if isatty(stdout) and node.config.statusbar:
if isatty(stdout) and node.config.statusBarEnabled:
enableTrueColors()
# TODO: nim-prompt seems to have threading issues at the moment
@ -951,17 +878,18 @@ when hasPrompt:
"$" & expr
var statusBar = StatusBarView.init(
node.config.statusbarContents,
node.config.statusBarContents,
dataResolver)
defaultChroniclesStream.output.writer =
proc (logLevel: LogLevel, msg: LogOutputStr) {.gcsafe.} =
# p.hidePrompt
erase statusBar
# p.writeLine msg
stdout.write msg
render statusBar
# p.showPrompt
when compiles(defaultChroniclesStream.output.writer):
defaultChroniclesStream.output.writer =
proc (logLevel: LogLevel, msg: LogOutputStr) {.gcsafe.} =
# p.hidePrompt
erase statusBar
# p.writeLine msg
stdout.write msg
render statusBar
# p.showPrompt
proc statusBarUpdatesPollingLoop() {.async.} =
while true:
@ -1010,10 +938,15 @@ when isMainModule:
stderr.write "Please regenerate the deposit files by running makeDeposits again\n"
quit 1
let eth1Hash = if config.depositWeb3Url.len == 0:
eth1BlockHash
else:
waitFor getLatestEth1BlockHash(config.depositWeb3Url)
var
startTime = uint64(times.toUnix(times.getTime()) + config.genesisOffset)
initialState = initialize_beacon_state_from_eth1(
eth1BlockHash, startTime, deposits, {skipValidation})
eth1Hash, startTime, deposits, {skipValidation})
# https://github.com/ethereum/eth2.0-pm/tree/6e41fcf383ebeb5125938850d8e9b4e9888389b4/interop/mocked_start#create-genesis-state
initialState.genesis_time = startTime
@ -1031,39 +964,24 @@ when isMainModule:
bootstrapAddress = getPersistenBootstrapAddr(
config, parseIpAddress(config.bootstrapAddress), Port config.bootstrapPort)
testnetMetadata = NetworkMetadata(
networkGeneration: semanticVersion,
genesisRoot:
if config.withGenesisRoot:
some(hash_tree_root(initialState))
else: none(Eth2Digest),
bootstrapNodes: @[bootstrapAddress],
numShards: SHARD_COUNT,
slotDuration: SECONDS_PER_SLOT,
slotsPerEpoch: SLOTS_PER_EPOCH,
totalValidators: config.totalValidators,
lastUserValidator: config.lastUserValidator)
Json.saveFile(config.outputNetworkMetadata.string, testnetMetadata, pretty = true)
echo "Wrote ", config.outputNetworkMetadata.string
let bootstrapFile = config.outputBootstrapNodes.string
let bootstrapFile = config.outputBootstrapFile.string
if bootstrapFile.len > 0:
let bootstrapAddrLine = when networkBackend == libp2pBackend:
let bootstrapAddrLine = when networkBackend != rlpxBackend:
$bootstrapAddress.addresses[0] & "/p2p/" & bootstrapAddress.peer.pretty
else:
$bootstrapAddress
writeFile(bootstrapFile, bootstrapAddrLine)
echo "Wrote ", bootstrapFile
of updateTestnet:
discard waitFor updateTestnetMetadata(config)
of importValidator:
template reportFailureFor(keyExpr) =
error "Failed to import validator key", key = keyExpr
programResult = 1
if config.keyFiles.len == 0:
stderr.write "Please specify at least one keyfile to import."
quit 1
for keyFile in config.keyFiles:
try:
saveValidatorKey(keyFile.string.extractFilename,
@ -1071,18 +989,6 @@ when isMainModule:
except:
reportFailureFor keyFile.string
if config.keyFiles.len == 0:
if config.network in ["testnet0", "testnet1"]:
try:
let (keyName, key) = waitFor obtainTestnetKey(config)
saveValidatorKey(keyName, key, config)
except:
stderr.write "Failed to download key\n", getCurrentExceptionMsg()
quit 1
else:
echo "Validator keys can be downloaded only for testnets"
quit 1
of noCommand:
createPidFile(config.dataDir.string / "beacon_node.pid")

View File

@ -1,2 +1,9 @@
-d:"chronicles_runtime_filtering=on"
@if testnet_docker_node:
-d:"chronicles_sinks=json"
-d:"withoutPrompt"
@else:
-d:"chronicles_default_output_device=dynamic"
@end

View File

@ -16,7 +16,6 @@ type
network*: Eth2Node
forkVersion*: array[4, byte]
networkIdentity*: Eth2NodeIdentity
networkMetadata*: NetworkMetadata
requestManager*: RequestManager
isBootstrapNode*: bool
bootstrapNodes*: seq[BootstrapAddr]
@ -244,22 +243,9 @@ type
RequestManager* = object
network*: Eth2Node
NetworkMetadata* = object
networkGeneration*: uint64
genesisRoot*: Option[Eth2Digest]
bootstrapNodes*: seq[BootstrapAddr]
numShards*: uint64
slotDuration*: uint64
slotsPerEpoch*: uint64
totalValidators*: uint64
lastUserValidator*: uint64
FetchRecord* = object
root*: Eth2Digest
historySlots*: uint64
proc userValidatorsRange*(d: NetworkMetadata): HSlice[int, int] =
0 .. d.lastUserValidator.int
proc shortLog*(v: AttachedValidator): string = shortLog(v.pubKey)

View File

@ -16,48 +16,58 @@ type
noCommand
importValidator
createTestnet
updateTestnet
makeDeposits
Eth1Network* = enum
custom
mainnet
rinkeby
goerli
BeaconNodeConf* = object
logLevel* {.
desc: "Sets the log level",
defaultValue: enabledLogLevel }: LogLevel
desc: "Sets the log level."
defaultValue: enabledLogLevel
longform: "log-level" }: LogLevel
network* {.
desc: "The network Nimbus should connect to. " &
"Possible values: testnet0, testnet1, mainnet, custom-network.json"
longform: "network"
shortform: "n"
defaultValue: DEFAULT_NETWORK }: string
eth1Network* {.
desc: "The Eth1 network tracked by the beacon node."
defaultValue: goerli
longform: "eth1-network" }: Eth1Network
quickStart* {.
desc: "Run in quickstart mode",
defaultValue: false }: bool
desc: "Run in quickstart mode"
defaultValue: false
longform: "quick-start" }: bool
dataDir* {.
desc: "The directory where nimbus will store all blockchain data."
defaultValue: config.defaultDataDir()
shortform: "d"
defaultValue: config.defaultDataDir() }: OutDir
longform: "data-dir" }: OutDir
depositWeb3Url* {.
desc: "URL of the Web3 server to observe Eth1",
defaultValue: "" }: string
desc: "URL of the Web3 server to observe Eth1."
defaultValue: ""
longform: "web3-url" }: string
depositContractAddress* {.
desc: "Address of the deposit contract",
defaultValue: "" }: string
desc: "Address of the deposit contract."
defaultValue: ""
longform: "deposit-contract" }: string
statusbar* {.
desc: "Display a status bar at the bottom of the terminal screen"
defaultValue: true }: bool
statusBarEnabled* {.
desc: "Display a status bar at the bottom of the terminal screen."
defaultValue: true
longform: "status-bar" }: bool
statusbarContents* {.
statusBarContents* {.
desc: ""
defaultValue: "peers: $connected_peers; " &
"epoch: $epoch, slot: $epoch_slot/$slots_per_epoch (..$slot_trailing_digits); " &
"finalized epoch: $last_finalized_epoch |" &
"ETH: $attached_validators_balance" }: string
"ETH: $attached_validators_balance"
longform: "status-bar-contents" }: string
case cmd* {.
command
@ -66,115 +76,132 @@ type
of noCommand:
bootstrapNodes* {.
desc: "Specifies one or more bootstrap nodes to use when connecting to the network."
longform: "bootstrapNode"
shortform: "b" }: seq[string]
shortform: "b"
longform: "bootstrap-node" }: seq[string]
bootstrapNodesFile* {.
desc: "Specifies a line-delimited file of bootsrap Ethereum network addresses"
shortform: "f"
defaultValue: "" }: InputFile
desc: "Specifies a line-delimited file of bootsrap Ethereum network addresses."
defaultValue: ""
longform: "bootstrap-file" }: InputFile
tcpPort* {.
desc: "TCP listening port"
defaultValue: defaultPort(config) }: int
desc: "TCP listening port."
defaultValue: defaultPort(config)
longform: "tcp-port" }: int
udpPort* {.
desc: "UDP listening port",
defaultValue: defaultPort(config) }: int
desc: "UDP listening port."
defaultValue: defaultPort(config)
longform: "udp-port" }: int
nat* {.
desc: "Specify method to use for determining public address. Must be one of: any, none, upnp, pmp, extip:<IP>"
defaultValue: "any" .}: string
desc: "Specify method to use for determining public address. " &
"Must be one of: any, none, upnp, pmp, extip:<IP>."
defaultValue: "any" }: string
validators* {.
required
desc: "Path to a validator private key, as generated by makeDeposits"
longform: "validator"
shortform: "v".}: seq[ValidatorKeyPath]
desc: "Path to a validator private key, as generated by makeDeposits."
shortform: "v"
longform: "validator" }: seq[ValidatorKeyPath]
stateSnapshot* {.
desc: "Json file specifying a recent state snapshot"
shortform: "s".}: Option[InputFile]
desc: "Json file specifying a recent state snapshot."
shortform: "s"
longform: "state-snapshot" }: Option[InputFile]
nodename* {.
nodeName* {.
desc: "A name for this node that will appear in the logs. " &
"If you set this to 'auto', a persistent automatically generated ID will be seleceted for each --dataDir folder"
defaultValue: ""}: string
"If you set this to 'auto', a persistent automatically generated ID will be seleceted for each --dataDir folder."
defaultValue: ""
longform: "node-name" }: string
metricsServer* {.
desc: "Enable the metrics server"
defaultValue: false.}: bool
desc: "Enable the metrics server."
defaultValue: false
longform: "metrics-server" }: bool
metricsServerAddress* {.
desc: "Listening address of the metrics server"
defaultValue: "0.0.0.0".}: string # TODO: use a validated type here
desc: "Listening address of the metrics server."
defaultValue: "0.0.0.0"
longform: "metrics-server-address" }: string # TODO: use a validated type here
metricsServerPort* {.
desc: "Listening HTTP port of the metrics server"
defaultValue: 8008 .}: uint16
desc: "Listening HTTP port of the metrics server."
defaultValue: 8008
longform: "metrics-server-port" }: uint16
of createTestnet:
validatorsDir* {.
desc: "Directory containing validator descriptors named vXXXXXXX.deposit.json"
shortform: "d".}: InputDir
desc: "Directory containing validator descriptors named 'vXXXXXXX.deposit.json'."
shortform: "d"
longform: "validators-dir" }: InputDir
totalValidators* {.
desc: "The number of validators in the newly created chain".}: uint64
desc: "The number of validators in the newly created chain."
longform: "total-validators" }: uint64
firstValidator* {.
desc: "Index of first validator to add to validator list"
defaultValue: 0 .}: uint64
desc: "Index of first validator to add to validator list."
defaultValue: 0
longform: "first-validator" }: uint64
lastUserValidator* {.
desc: "The last validator index that will free for taking from a testnet participant"
defaultValue: config.totalValidators - 1 .}: uint64
desc: "The last validator index that will free for taking from a testnet participant."
defaultValue: config.totalValidators - 1,
longform: "last-user-validator" }: uint64
bootstrapAddress* {.
desc: "The public IP address that will be advertised as a bootstrap node for the testnet"
defaultValue: "127.0.0.1".}: string
desc: "The public IP address that will be advertised as a bootstrap node for the testnet."
defaultValue: "127.0.0.1"
longform: "bootstrap-address" }: string
bootstrapPort* {.
desc: "The TCP/UDP port that will be used by the bootstrap node"
defaultValue: defaultPort(config) .}: int
desc: "The TCP/UDP port that will be used by the bootstrap node."
defaultValue: defaultPort(config)
longform: "bootstrap-port" }: int
genesisOffset* {.
desc: "Seconds from now to add to genesis time"
desc: "Seconds from now to add to genesis time."
defaultValue: 5
shortForm: "g"
defaultValue: 5 .}: int
longform: "genesis-offset" }: int
outputGenesis* {.
desc: "Output file where to write the initial state snapshot".}: OutFile
outputNetworkMetadata* {.
desc: "Output file where to write the initial state snapshot".}: OutFile
desc: "Output file where to write the initial state snapshot."
longform: "output-genesis" }: OutFile
withGenesisRoot* {.
desc: "Include a genesis root in network.json", defaultValue: false.}: bool
desc: "Include a genesis root in 'network.json'."
defaultValue: false
longform: "with-genesis-root" }: bool
outputBootstrapNodes* {.
desc: "Output file with list of bootstrap nodes for the network".}: OutFile
outputBootstrapFile* {.
desc: "Output file with list of bootstrap nodes for the network."
longform: "output-bootstrap-file" }: OutFile
of importValidator:
keyFiles* {.
longform: "keyfile"
desc: "File with validator key to be imported (in hex form)".}: seq[ValidatorKeyPath]
of updateTestnet:
discard
desc: "File with validator key to be imported (in hex form)."
longform: "keyfile" }: seq[ValidatorKeyPath]
of makeDeposits:
totalDeposits* {.
desc: "Total number of deposits and keys to generate".}: int
desc: "Total number of deposits and keys to generate."
longform: "total-deposits" }: int
depositsDir* {.
desc: "Folder to write deposits to", defaultValue: "validators".}: string
desc: "Folder to write deposits to."
defaultValue: "validators"
longform: "deposits-dir" }: string
randomKeys* {.
desc: "Use random keys (instead of interop keys)", defaultValue: false.}: bool
desc: "Use random keys (instead of interop keys)."
defaultValue: false
longform: "random-keys" }: bool
proc defaultPort*(config: BeaconNodeConf): int =
if config.network == "testnet1": 9100
else: 9000
9000
proc defaultDataDir*(conf: BeaconNodeConf): string =
let dataDir = when defined(windows):
@ -184,14 +211,7 @@ proc defaultDataDir*(conf: BeaconNodeConf): string =
else:
".cache" / "nimbus"
let networkDir = if conf.network in ["testnet0", "testnet1", "mainnet"]:
conf.network
else:
# TODO: This seems silly. Perhaps we should error out here and ask
# the user to specify dataDir as well.
"tempnet"
getHomeDir() / dataDir / "BeaconNode" / networkDir
getHomeDir() / dataDir / "BeaconNode"
proc validatorFileBaseName*(validatorIdx: int): string =
# there can apparently be tops 4M validators so we use 7 digits..

View File

@ -14,10 +14,13 @@ type
CliConfig = object
depositWeb3Url* {.
desc: "URL of the Web3 server to observe Eth1"}: string
desc: "URL of the Web3 server to observe Eth1"
longform: "web3-url" }: string
privateKey* {.
desc: "Private key of the controlling account",
defaultValue: ""}: string
defaultValue: ""
longform: "private-key" }: string
case cmd* {.command.}: StartUpCommand
of deploy:
@ -26,17 +29,20 @@ type
of drain:
contractAddress* {.
desc: "Address of the contract to drain",
defaultValue: ""}: string
defaultValue: ""
longform: "deposit-contract" }: string
of sendEth:
toAddress: string
valueEth: string
toAddress {.longform: "to".}: string
valueEth {.longform: "eth".}: string
contract(Deposit):
proc drain()
proc getTransactionReceipt(web3: Web3, tx: TxHash): Future[ReceiptObject] {.async.} =
result = await web3.provider.eth_getTransactionReceipt(tx)
proc deployContract*(web3: Web3, code: string): Future[Address] {.async.} =
let provider = web3.provider
var code = code
if code[1] notin {'x', 'X'}:
code = "0x" & code
@ -47,7 +53,7 @@ proc deployContract*(web3: Web3, code: string): Future[Address] {.async.} =
gasPrice: 1.some)
let r = await web3.send(tr)
let receipt = await provider.eth_getTransactionReceipt(r)
let receipt = await web3.getTransactionReceipt(r)
result = receipt.contractAddress.get
proc sendEth(web3: Web3, to: string, valueEth: int): Future[TxHash] =

View File

@ -131,8 +131,9 @@ when networkBackend == rlpxBackend:
else:
import
os, random, stew/io,
eth/async_utils, ssz, libp2p/crypto/crypto
os, random,
stew/io, eth/async_utils, libp2p/crypto/crypto,
ssz
when networkBackend == libp2pBackend:
import
@ -157,7 +158,15 @@ else:
Eth2NodeIdentity* = PeerInfo
proc init*(T: type BootstrapAddr, str: string): T =
Json.decode(str, PeerInfo)
# TODO: The code below is quite awkward.
# How do we parse a PeerInfo object out of a bootstrap MultiAddress string such as:
# /ip4/10.20.30.40/tcp/9100/p2p/16Uiu2HAmEAmp4FdpPzypKwTMmsbCdnUafDvXZCpFrUDbYJZNk7hX
var parts = str.split("/p2p/")
if parts.len == 2:
result.peer = PeerID.init(parts[1])
result.addresses.add MultiAddress.init(parts[0])
else:
raise newException(ValueError, "Invalid bootstrap multi-address")
proc ensureNetworkIdFile(conf: BeaconNodeConf): string =
result = conf.dataDir / networkKeyFilename

View File

@ -23,11 +23,12 @@ type
QueueElement = (BlockHash, DepositData)
proc init*(T: type MainchainMonitor, web3Url, depositContractAddress: string): T =
proc init*(T: type MainchainMonitor, web3Url, depositContractAddress: string, startBlock: Eth2Digest): T =
result.new()
result.web3Url = web3Url
result.depositContractAddress = Address.fromHex(depositContractAddress)
result.depositQueue = newAsyncQueue[QueueElement]()
result.eth1Block = BlockHash(startBlock.data)
contract(DepositContract):
proc deposit(pubkey: Bytes48, withdrawalCredentials: Bytes32, signature: Bytes96, deposit_data_root: FixedBytes[32])
@ -83,7 +84,7 @@ proc run(m: MainchainMonitor) {.async.} =
m.web3 = await newWeb3(m.web3Url)
let ns = m.web3.contractSender(DepositContract, m.depositContractAddress)
let s = await ns.subscribe(DepositEvent, %*{"fromBlock": "0x0"}) do(pubkey: Bytes48, withdrawalCredentials: Bytes32, amount: Bytes8, signature: Bytes96, merkleTreeIndex: Bytes8, j: JsonNode):
let s = await ns.subscribe(DepositEvent, %*{"fromBlock": m.eth1Block}) do(pubkey: Bytes48, withdrawalCredentials: Bytes32, amount: Bytes8, signature: Bytes96, merkleTreeIndex: Bytes8, j: JsonNode):
let blkHash = BlockHash.fromHex(j["blockHash"].getStr())
let amount = bytes_to_int(array[8, byte](amount))
@ -125,3 +126,9 @@ proc getPendingDeposits*(m: MainchainMonitor): seq[Deposit] =
# # rather a more readable description of the change that can be packed
# # in a SpecialRecord by the client of the API.
# discard
proc getLatestEth1BlockHash*(url: string): Future[Eth2Digest] {.async.} =
let web3 = await newWeb3(url)
let blk = await web3.provider.eth_getBlockByNumber("latest", false)
result.data = array[32, byte](blk.hash)
await web3.close()

View File

@ -40,6 +40,7 @@ RUN cd nim-beacon-chain \
&& ./env.sh nim \
-o:/usr/bin/beacon_node \
-d:release \
-d:insecure \
--debugger:native \
--debugInfo \
-d:"network_type=${NETWORK_TYPE}" \
@ -56,7 +57,7 @@ RUN cd nim-beacon-chain \
FROM debian:9-slim
RUN apt update \
&& apt install -y librocksdb-dev curl psmisc \
&& apt install -y librocksdb-dev psmisc \
&& apt clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

View File

@ -1,6 +1,6 @@
# These default settings can be overriden by exporting env variables
GIT_REVISION ?= $(git rev-parse HEAD)
GIT_REVISION ?= $(shell git rev-parse HEAD)
NETWORK ?= testnet1
NETWORK_TYPE ?= libp2p
@ -8,7 +8,7 @@ NETWORK_TYPE ?= libp2p
IMAGE_TAG ?= $(NETWORK)
IMAGE_NAME ?= statusteam/nimbus_beacon_node:$(IMAGE_TAG)
build: $(NIX_INSTALL)
build:
docker build \
--build-arg="GIT_REVISION=$(GIT_REVISION)" \
--build-arg="NETWORK=$(NETWORK)" \

View File

@ -33,23 +33,22 @@ LAST_VALIDATOR="$VALIDATORS_DIR/v$(printf '%07d' $LAST_VALIDATOR_NUM).deposit.js
if [ ! -f "${LAST_VALIDATOR}" ]; then
$BEACON_NODE_BIN makeDeposits \
--totalDeposits="${NUM_VALIDATORS}" \
--depositsDir="$VALIDATORS_DIR" \
--randomKeys=false
--total-deposits="${NUM_VALIDATORS}" \
--deposits-dir="$VALIDATORS_DIR" \
--random-keys=no
fi
if [ ! -f "${SNAPSHOT_FILE}" ]; then
$BEACON_NODE_BIN \
--dataDir="${SIMULATION_DIR}/node-0" \
--data-dir="${SIMULATION_DIR}/node-0" \
createTestnet \
--validatorsDir="${VALIDATORS_DIR}" \
--totalValidators="${NUM_VALIDATORS}" \
--outputGenesis="${SNAPSHOT_FILE}" \
--outputNetworkMetadata="${NETWORK_METADATA_FILE}" \
--outputBootstrapNodes="${SIMULATION_DIR}/bootstrap_nodes.txt" \
--bootstrapAddress=127.0.0.1 \
--bootstrapPort=50000 \
--genesisOffset=30 # Delay in seconds
--validators-dir="${VALIDATORS_DIR}" \
--total-validators="${NUM_VALIDATORS}" \
--output-genesis="${SNAPSHOT_FILE}" \
--output-bootstrap-file="${SIMULATION_DIR}/bootstrap_nodes.txt" \
--bootstrap-address=127.0.0.1 \
--bootstrap-port=50000 \
--genesis-offset=30 # Delay in seconds
fi
# Delete any leftover address files from a previous session

View File

@ -34,11 +34,10 @@ set -x
trap 'kill -9 -- -$$' SIGINT EXIT SIGTERM
./env.sh $BEACON_NODE_BIN \
--statusbar:off \
--network:$NETWORK_METADATA_FILE \
--dataDir:$DATA_DIR \
--nodename:0 \
--tcpPort:$PORT \
--udpPort:$PORT \
--status-bar:off \
--data-dir:$DATA_DIR \
--node-name:0 \
--tcp-port:$PORT \
--udp-port:$PORT \
$NAT_FLAG \
--stateSnapshot:$SNAPSHOT_FILE
--state-snapshot:$SNAPSHOT_FILE

View File

@ -20,6 +20,6 @@ NUM_MISSING_NODES=${MISSING_NODES:-2}
SIMULATION_DIR="${SIM_ROOT}/data"
VALIDATORS_DIR="${SIM_ROOT}/validators"
SNAPSHOT_FILE="${SIMULATION_DIR}/state_snapshot.json"
NETWORK_METADATA_FILE="${SIMULATION_DIR}/network.json"
NETWORK_BOOTSTRAP_FILE="${SIMULATION_DIR}/bootstrap_nodes.txt"
BEACON_NODE_BIN="${SIMULATION_DIR}/beacon_node"
MASTER_NODE_ADDRESS_FILE="${SIMULATION_DIR}/node-0/beacon_node.address"

View File

@ -11,18 +11,12 @@
--passL:"-Wl,--stack,8388608"
# https://github.com/nim-lang/Nim/issues/4057
--tlsEmulation:off
# The dynamic Chronicles output currently prevents us from using colors on Windows
# because these require direct manipulations of the stdout File object.
-d:"chronicles_colors=off"
@end
@if testnet_docker_node:
-d:"chronicles_sinks=json"
-d:"withoutPrompt"
@else:
-d:"chronicles_default_output_device=dynamic"
@end
--threads:on
--opt:speed
--excessiveStackTrace:on

View File

@ -15,16 +15,15 @@ The `beacon_node` binary has a `createTestnet` command.
```bash
nim c -r beacon_chain/beacon_node \
--network=$NETWORK_NAME \
--dataDir=$DATA_DIR/node-0 \
--data-dir=$DATA_DIR/node-0 \
createTestnet \
--validatorsDir=$NETWORK_DIR \
--totalValidators=$VALIDATOR_COUNT \
--lastUserValidator=$LAST_USER_VALIDATOR \
--outputGenesis=$NETWORK_DIR/genesis.json \
--outputNetworkMetadata=$NETWORK_DIR/network.json \
--outputBootstrapNodes=$NETWORK_DIR/bootstrap_nodes.txt \
--bootstrapAddress=$PUBLIC_IP \
--genesisOffset=600 # Delay in seconds
--validators-dir=$NETWORK_DIR \
--total-validators=$VALIDATOR_COUNT \
--last-user-validator=$LAST_USER_VALIDATOR \
--output-genesis=$NETWORK_DIR/genesis.json \
--output-bootstrap-file=$NETWORK_DIR/bootstrap_nodes.txt \
--bootstrap-address=$PUBLIC_IP \
--genesis-offset=600 # Delay in seconds
```
Replace ENV vars with values that make sense to you.

View File

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

View File

@ -0,0 +1,73 @@
import
confutils, strutils, strformat, ospaths
const
rootDir = thisDir() / ".."
bootstrapFile = "bootstrap_nodes.txt"
depositContractFile = "deposit_contract.txt"
genesisFile = "genesis.ssz"
configFile = "config.yaml"
clientsOrg = "zah" # "eth2-clients"
testnetsRepo = "eth2-testnets"
testnetsRepoGitUrl = "git://github.com/" & clientsOrg & "/" & testnetsRepo
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])
cli do (testnetName {.argument.}: string):
let
nameParts = testnetName.split "/"
(team, testnet) = if nameParts.len > 1: validateTestnetName nameParts
else: ("nimbus", testnetName)
let
buildDir = rootDir / "build"
allTestnetsDir = buildDir / testnetsRepo
if not dirExists(allTestnetsDir):
cd buildDir
exec &"git clone {testnetsRepoGitUrl}"
cd allTestnetsDir
exec &"git remote set-url origin {testnetsRepoGitUrl}"
exec "git reset --hard master"
exec "git pull"
let testnetDir = allTestnetsDir / team / testnet
if not dirExists(testnetDir):
echo &"No metadata files exists for the '{testnetName}' testnet"
quit 1
proc checkRequiredFile(fileName: string) =
let filePath = testnetDir / fileName
if not fileExists(filePath):
echo &"The required file {fileName} is not present in '{testnetDir}'."
quit 1
checkRequiredFile bootstrapFile
checkRequiredFile genesisFile
var preset = testnetDir / configFile
if not fileExists(preset): preset = "minimal"
let
dataDirName = testnetName.replace("/", "_")
dataDir = buildDir / "data" / dataDirName
beaconNodeBinary = buildDir / "beacon_node_" & dataDirName
nimFlags = "-d:release --lineTrace:on -d:chronicles_log_level=DEBUG"
var depositContractOpt = ""
let depositContractFile = testnetDir / depositContractFile
if fileExists(depositContractFile):
depositContractOpt = "--deposit-contract=" & readFile(depositContractFile).strip
cd rootDir
exec &"""nim c {nimFlags} -d:"const_preset={preset}" -o:"{beaconNodeBinary}" beacon_chain/beacon_node.nim"""
exec replace(&"""{beaconNodeBinary}
--data-dir="{dataDir}"
--bootstrap-file="{testnetDir/bootstrapFile}"
--state-snapshot="{testnetDir/genesisFile}" """ & depositContractOpt, "\n", " ")

View File

@ -13,6 +13,6 @@ mkdir -p $VALIDATORS_DIR
FIRST_IDX=$(printf '%07d' $FIRST_VALIDATOR)
LAST_IDX=$(printf '%07d' $LAST_VALIDATOR)
curl "https://serenity-testnets.status.im/${NETWORK_NAME}/v[$FIRST_IDX-$LAST_IDX].privkey" \
curl "https://raw.githubusercontent.com/status-im/nim-eth2-testnet-data/master/www/${NETWORK_NAME}/v[$FIRST_IDX-$LAST_IDX].privkey" \
-o "$VALIDATORS_DIR/v#1.privkey" -s -w '%{url_effective} > %{filename_effective}\n'

View File

@ -10,7 +10,7 @@ source "$NETWORK_NAME.env"
cd ..
if [ -f .env ]; then
# allow server overrides for ETH2_TESTNET_DATA_DIR and DATA_DIR
# allow server overrides for ETH2_TESTNET_DATA_DIR, DATA_DIR and ETH1_PRIVATE_KEY
source .env
fi
@ -41,8 +41,19 @@ ETH2_TESTNET_DATA_DIR_ABS=$(cd "$ETH2_TESTNET_DATA_DIR"; pwd)
DATA_DIR_ABS=$(mkdir -p "$DATA_DIR"; cd "$DATA_DIR"; pwd)
NETWORK_DIR_ABS="$ETH2_TESTNET_DATA_DIR_ABS/www/$NETWORK_NAME"
if [ "$WEB3_URL" != "" ]; then
WEB3_URL_ARG="--web3-url=$WEB3_URL"
fi
DOCKER_BEACON_NODE="docker run -v $NETWORK_DIR_ABS:/network_dir -v $DATA_DIR_ABS:/data_dir statusteam/nimbus_beacon_node:$NETWORK_NAME"
make deposit_contract
if [ "$ETH1_PRIVATE_KEY" != "" ]; then
DEPOSIT_CONTRACT_ADDRESS=$(./build/deposit_contract deploy $WEB3_URL_ARG --private-key=$ETH1_PRIVATE_KEY)
DEPOSIT_CONTRACT_ADDRESS_ARG="--deposit-contract=$DEPOSIT_CONTRACT_ADDRESS"
fi
cd docker
export GIT_REVISION=$(git rev-parse HEAD)
@ -51,24 +62,24 @@ make build
if [ ! -f $NETWORK_DIR_ABS/genesis.ssz ]; then
rm -f $NETWORK_DIR_ABS/*
$DOCKER_BEACON_NODE makeDeposits \
--totalDeposits=$VALIDATOR_COUNT \
--depositsDir=/network_dir \
--randomKeys=false
--total-deposits=$VALIDATOR_COUNT \
--deposits-dir=/network_dir \
--random-keys=no
fi
$DOCKER_BEACON_NODE \
--network=$NETWORK_NAME \
--dataDir=/data_dir \
--data-dir=/data_dir \
createTestnet \
--validatorsDir=/network_dir \
--totalValidators=$VALIDATOR_COUNT \
--lastUserValidator=$LAST_USER_VALIDATOR \
--outputGenesis=/network_dir/genesis.json \
--outputBootstrapNodes=/network_dir/bootstrap_nodes.txt \
--outputNetworkMetadata=/network_dir/network.json \
--bootstrapAddress=$BOOTSTRAP_IP \
--bootstrapPort=$BOOTSTRAP_PORT \
--genesisOffset=60 # Delay in seconds
--validators-dir=/network_dir \
--total-validators=$VALIDATOR_COUNT \
--last-user-validator=$LAST_USER_VALIDATOR \
--output-genesis=/network_dir/genesis.json \
--output-bootstrap-file=/network_dir/bootstrap_nodes.txt \
--bootstrap-address=$BOOTSTRAP_IP \
--bootstrap-port=$BOOTSTRAP_PORT \
$WEB3_URL_ARG $DEPOSIT_CONTRACT_ADDRESS_ARG \
--genesis-offset=60 # Delay in seconds
if [[ $PUBLISH_TESTNET_RESETS != "0" ]]; then
echo Persisting testnet data to git...
@ -78,14 +89,6 @@ if [[ $PUBLISH_TESTNET_RESETS != "0" ]]; then
git push
popd
echo Updating https://serenity-testnets.status.im/${NETWORK_NAME}...
ssh $BOOTSTRAP_HOST <<-SSH
cd /opt/nim-eth2-testnet-data
git reset --hard HEAD
git checkout master
git pull
SSH
echo Redistributing validator keys to server nodes...
# TODO If we try to use direct piping here, bash doesn't execute all of the commands.
# The reasons for this are unclear at the moment.

View File

@ -1,10 +1,9 @@
CONST_PRESET=minimal
NETWORK_ID=10
NETWORK_TYPE=rlpx
NETWORK_TYPE=libp2p_daemon
SHARD_COUNT=16
SLOTS_PER_EPOCH=16
SECONDS_PER_SLOT=30
VALIDATOR_COUNT=1000
LAST_USER_VALIDATOR=199
BOOTSTRAP_PORT=9000
WEB3_URL=wss://goerli.infura.io/ws/v3/809a18497dd74102b5f37d25aae3c85a

View File

@ -1,10 +1,9 @@
CONST_PRESET=minimal
NETWORK_ID=20
NETWORK_TYPE=libp2p
NETWORK_TYPE=libp2p_daemon
SHARD_COUNT=8
SLOTS_PER_EPOCH=8
SECONDS_PER_SLOT=6
VALIDATOR_COUNT=1000
LAST_USER_VALIDATOR=199
BOOTSTRAP_PORT=9100
WEB3_URL=wss://goerli.infura.io/ws/v3/809a18497dd74102b5f37d25aae3c85a

View File

@ -29,17 +29,17 @@ pushd $VALIDATORS_DIR >/dev/null
popd >/dev/null
$BEACON_NODE_BIN \
--network:$NETWORK_METADATA_FILE \
--dataDir:$DATA_DIR \
--nodename:$NODE_ID \
--tcpPort:$PORT \
--udpPort:$PORT \
--bootstrap-file=$NETWORK_BOOTSTRAP_FILE \
--data-dir=$DATA_DIR \
--node-name=$NODE_ID \
--tcp-port=$PORT \
--udp-port=$PORT \
$NAT_FLAG \
--stateSnapshot:$SNAPSHOT_FILE \
--state-snapshot=$SNAPSHOT_FILE \
$DEPOSIT_WEB3_URL_ARG \
--depositContractAddress=$DEPOSIT_CONTRACT_ADDRESS \
--metricsServer=true \
--metricsServerAddress="127.0.0.1" \
--metricsServerPort="$(( $BASE_METRICS_PORT + $NODE_ID ))" \
--deposit-contract=$DEPOSIT_CONTRACT_ADDRESS \
--metrics-server=on \
--metrics-server-address="127.0.0.1" \
--metrics-server-port="$(( $BASE_METRICS_PORT + $NODE_ID ))" \
"$@"

View File

@ -9,7 +9,7 @@ source "$(dirname "$0")/vars.sh"
source "${SIM_ROOT}/../../env.sh"
# Set DEPOSIT_WEB3_URL_ARG to empty to get genesis state from file, not using web3
# export DEPOSIT_WEB3_URL_ARG=--depositWeb3Url=ws://localhost:8545
# export DEPOSIT_WEB3_URL_ARG=--web3-url=ws://localhost:8545
export DEPOSIT_WEB3_URL_ARG=
export DEPOSIT_CONTRACT_ADDRESS=0x
@ -44,25 +44,24 @@ if [ ! -f "${LAST_VALIDATOR}" ]; then
fi
$BEACON_NODE_BIN makeDeposits \
--totalDeposits="${NUM_VALIDATORS}" \
--depositsDir="$VALIDATORS_DIR" \
--randomKeys=false \
--total-deposits="${NUM_VALIDATORS}" \
--deposits-dir="$VALIDATORS_DIR" \
--random-keys=no \
$DEPOSIT_WEB3_URL_ARG \
--depositContractAddress="${DEPOSIT_CONTRACT_ADDRESS}"
--deposit-contract="${DEPOSIT_CONTRACT_ADDRESS}"
fi
if [ ! -f "${SNAPSHOT_FILE}" ]; then
$BEACON_NODE_BIN \
--dataDir="${SIMULATION_DIR}/node-0" \
--data-dir="${SIMULATION_DIR}/node-0" \
createTestnet \
--validatorsDir="${VALIDATORS_DIR}" \
--totalValidators="${NUM_VALIDATORS}" \
--outputGenesis="${SNAPSHOT_FILE}" \
--outputNetworkMetadata="${NETWORK_METADATA_FILE}" \
--outputBootstrapNodes="${SIMULATION_DIR}/bootstrap_nodes.txt" \
--bootstrapAddress=127.0.0.1 \
--bootstrapPort=50000 \
--genesisOffset=5 # Delay in seconds
--validators-dir="${VALIDATORS_DIR}" \
--total-validators="${NUM_VALIDATORS}" \
--output-genesis="${SNAPSHOT_FILE}" \
--output-bootstrap-file="${NETWORK_BOOTSTRAP_FILE}" \
--bootstrap-address=127.0.0.1 \
--bootstrap-port=50000 \
--genesis-offset=5 # Delay in seconds
fi
# Delete any leftover address files from a previous session
@ -117,7 +116,7 @@ for i in $(seq 0 $LAST_NODE); do
done
fi
CMD="${SIM_ROOT}/run_node.sh $i --statusbar:off"
CMD="${SIM_ROOT}/run_node.sh $i --status-bar:off"
if [[ "$USE_MULTITAIL" != "no" ]]; then
if [[ "$i" == "0" ]]; then

View File

@ -23,7 +23,7 @@ SIMULATION_DIR="${SIM_ROOT}/data"
METRICS_DIR="${SIM_ROOT}/prometheus"
VALIDATORS_DIR="${SIM_ROOT}/validators"
SNAPSHOT_FILE="${SIMULATION_DIR}/state_snapshot.json"
NETWORK_METADATA_FILE="${SIMULATION_DIR}/network.json"
NETWORK_BOOTSTRAP_FILE="${SIMULATION_DIR}/bootstrap_nodes.txt"
BEACON_NODE_BIN="${SIMULATION_DIR}/beacon_node"
DEPLOY_DEPOSIT_CONTRACT_BIN="${SIMULATION_DIR}/deploy_deposit_contract"
MASTER_NODE_ADDRESS_FILE="${SIMULATION_DIR}/node-0/beacon_node.address"

2
vendor/news vendored

@ -1 +1 @@
Subproject commit 0c44ff9cd31e0f644f10d9adfbfc8e0c181ea724
Subproject commit 8ea2ee260207c57a4b495931508569e181bb7b93

2
vendor/nim-bearssl vendored

@ -1 +1 @@
Subproject commit f6133ec47de1900cc17db91fc0f929d0dcbaa63f
Subproject commit 993372dd78fa935e051e2d1f3c874d068d7171e6

2
vendor/nim-libp2p vendored

@ -1 +1 @@
Subproject commit 21af0810663901abc832ff7f29e3920a9f22392a
Subproject commit 6d8f21b611c715d19ac73901e981bf463267e797

2
vendor/nim-metrics vendored

@ -1 +1 @@
Subproject commit dc9873ebacb789c971d5496737cca0cbebcc7a9f
Subproject commit d4492f0d0ae9d2c46cc3dde2d947bc175ae420de