more work on the BN/VC split

- fixed comments from the last review
- getting more data VIA RPC, moved some code back into the BN only
- attestation duties being requested as well
This commit is contained in:
Viktor Kirilov 2020-05-27 20:06:28 +03:00
parent 18eca263b1
commit cefd525ab3
13 changed files with 253 additions and 143 deletions

View File

@ -30,6 +30,7 @@ import
validator_duties, validator_api
const
genesisFile* = "genesis.ssz"
hasPrompt = not defined(withoutPrompt)
type
@ -61,6 +62,58 @@ declareHistogram beacon_attestation_received_seconds_from_slot_start,
logScope: topics = "beacnde"
proc getStateFromSnapshot(conf: BeaconNodeConf): NilableBeaconStateRef =
var
genesisPath = conf.dataDir/genesisFile
snapshotContents: TaintedString
writeGenesisFile = false
if conf.stateSnapshot.isSome:
let
snapshotPath = conf.stateSnapshot.get.string
snapshotExt = splitFile(snapshotPath).ext
if cmpIgnoreCase(snapshotExt, ".ssz") != 0:
error "The supplied state snapshot must be a SSZ file",
suppliedPath = snapshotPath
quit 1
snapshotContents = readFile(snapshotPath)
if fileExists(genesisPath):
let genesisContents = readFile(genesisPath)
if snapshotContents != genesisContents:
error "Data directory not empty. Existing genesis state differs from supplied snapshot",
dataDir = conf.dataDir.string, snapshot = snapshotPath
quit 1
else:
debug "No previous genesis state. Importing snapshot",
genesisPath, dataDir = conf.dataDir.string
writeGenesisFile = true
genesisPath = snapshotPath
else:
try:
snapshotContents = readFile(genesisPath)
except CatchableError as err:
error "Failed to read genesis file", err = err.msg
quit 1
result = try:
newClone(SSZ.decode(snapshotContents, BeaconState))
except SerializationError:
error "Failed to import genesis file", path = genesisPath
quit 1
info "Loaded genesis state", path = genesisPath
if writeGenesisFile:
try:
notice "Writing genesis to data directory", path = conf.dataDir/genesisFile
writeFile(conf.dataDir/genesisFile, snapshotContents.string)
except CatchableError as err:
error "Failed to persist genesis file to data dir",
err = err.msg, genesisFile = conf.dataDir/genesisFile
quit 1
proc enrForkIdFromState(state: BeaconState): ENRForkID =
let
forkVer = state.fork.current_version
@ -557,7 +610,7 @@ proc installDebugApiHandlers(rpcServer: RpcServer, node: BeaconNode) =
proc installRpcHandlers(rpcServer: RpcServer, node: BeaconNode) =
# TODO: remove this if statement later - here just to test the config option for now
if node.config.externalValidators:
if node.config.validatorApi:
rpcServer.installValidatorApiHandlers(node)
rpcServer.installBeaconApiHandlers(node)
rpcServer.installDebugApiHandlers(node)
@ -823,9 +876,7 @@ when hasPrompt:
# createThread(t, processPromptCommands, addr p)
programMain:
let
banner = clientId & "\p" & copyrights & "\p\p" & nimBanner
config = BeaconNodeConf.load(version = banner, copyrightBanner = banner)
let config = makeBannerAndConfig(clientId, BeaconNodeConf)
setupMainProc(config.logLevel)

View File

@ -135,3 +135,11 @@ proc updateHead*(node: BeaconNode): BlockRef =
beacon_head_root.set newHead.root.toGaugeValue
newHead
template findIt*(s: openarray, predicate: untyped): int64 =
var res = -1
for i, it {.inject.} in s:
if predicate:
res = i
break
res

View File

@ -111,10 +111,10 @@ type
abbr: "v"
name: "validator" }: seq[ValidatorKeyPath]
externalValidators* {.
validatorApi* {.
defaultValue: false
desc: "Specify whether validators should be in an external process (a validator client) which communicates with the beacon node or they should be embedded."
name: "external-validators" }: bool
desc: "Specify whether the validator API should be enabled which would allow for external validators (validator clients) to use this beacon node."
name: "validator-api" }: bool
stateSnapshot* {.
desc: "Json file specifying a recent state snapshot."
@ -319,11 +319,6 @@ type
abbr: "v"
name: "validator" }: seq[ValidatorKeyPath]
stateSnapshot* {.
desc: "Json file specifying a recent state snapshot."
abbr: "s"
name: "state-snapshot" }: Option[InputFile]
delayStart* {.
defaultValue: 0
desc: "Seconds from now to delay the starting of the validator client (useful for debug purposes when starting before the beacon node in a script)."

View File

@ -3,7 +3,7 @@ import
tables, json,
# Nimble packages
stew/[bitseqs],
stew/[byteutils, bitseqs],
json_rpc/jsonmarshal,
# Local modules
@ -31,6 +31,12 @@ proc fromJson*(n: JsonNode, argName: string, result: var ValidatorSig) =
proc `%`*(value: ValidatorSig): JsonNode =
result = newJString($value)
proc fromJson*(n: JsonNode, argName: string, result: var Version) =
hexToByteArray(n.getStr(), array[4, byte](result))
proc `%`*(value: Version): JsonNode =
result = newJString($value)
template genFromJsonForIntType(t: untyped) =
proc fromJson*(n: JsonNode, argName: string, result: var t) =
n.kind.expect(JInt, argName)

View File

@ -5,75 +5,18 @@
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
# Common routines for a BeaconNode and a BeaconValidator node
# Common routines for a BeaconNode and a ValidatorClient
import
# Standard library
os, tables, random, strutils,
tables, random, strutils,
# Nimble packages
chronos,
chronicles, chronicles/helpers as chroniclesHelpers,
# Local modules
spec/[datatypes, crypto],
conf,
block_pool, eth2_network
const
genesisFile* = "genesis.ssz"
proc getStateFromSnapshot*(conf: BeaconNodeConf|ValidatorClientConf): NilableBeaconStateRef =
var
genesisPath = conf.dataDir/genesisFile
snapshotContents: TaintedString
writeGenesisFile = false
if conf.stateSnapshot.isSome:
let
snapshotPath = conf.stateSnapshot.get.string
snapshotExt = splitFile(snapshotPath).ext
if cmpIgnoreCase(snapshotExt, ".ssz") != 0:
error "The supplied state snapshot must be a SSZ file",
suppliedPath = snapshotPath
quit 1
snapshotContents = readFile(snapshotPath)
if fileExists(genesisPath):
let genesisContents = readFile(genesisPath)
if snapshotContents != genesisContents:
error "Data directory not empty. Existing genesis state differs from supplied snapshot",
dataDir = conf.dataDir.string, snapshot = snapshotPath
quit 1
else:
debug "No previous genesis state. Importing snapshot",
genesisPath, dataDir = conf.dataDir.string
writeGenesisFile = true
genesisPath = snapshotPath
else:
try:
snapshotContents = readFile(genesisPath)
except CatchableError as err:
error "Failed to read genesis file", err = err.msg
quit 1
result = try:
newClone(SSZ.decode(snapshotContents, BeaconState))
except SerializationError:
error "Failed to import genesis file", path = genesisPath
quit 1
info "Loaded genesis state", path = genesisPath
if writeGenesisFile:
try:
notice "Writing genesis to data directory", path = conf.dataDir/genesisFile
writeFile(conf.dataDir/genesisFile, snapshotContents.string)
except CatchableError as err:
error "Failed to persist genesis file to data dir",
err = err.msg, genesisFile = conf.dataDir/genesisFile
quit 1
spec/[datatypes, crypto], eth2_network
proc setupMainProc*(logLevel: string) =
when compiles(defaultChroniclesStream.output.writer):
@ -110,3 +53,7 @@ template ctrlCHandling*(extraCode: untyped) =
info "Shutting down after having received SIGINT"
extraCode
setControlCHook(controlCHandler)
template makeBannerAndConfig*(clientId: string, ConfType: type): untyped =
let banner = clientId & "\p" & copyrights & "\p\p" & nimBanner
ConfType.load(version = banner, copyrightBanner = banner)

View File

@ -8,10 +8,19 @@ import
# TODO check which arguments are part of the path in the REST API
# TODO this doesn't have "validator" in it's path but is used by the validators nonetheless
proc get_v1_beacon_states_fork(stateId: string): Fork
# TODO this doesn't have "validator" in it's path but is used by the validators nonetheless
proc get_v1_beacon_genesis(): BeaconGenesisTuple
proc get_v1_validator_blocks(slot: Slot, graffiti: Eth2Digest, randao_reveal: ValidatorSig): BeaconBlock
# TODO this doesn't have "validator" in it's path but is used by the validators nonetheless
proc post_v1_beacon_blocks(body: SignedBeaconBlock)
# TODO returns a bool even though in the API there is no return type - because of nim-json-rpc
proc post_v1_beacon_blocks(body: SignedBeaconBlock): bool
proc get_v1_validator_attestation_data(slot: Slot, committee_index: CommitteeIndex): AttestationData

View File

@ -15,7 +15,13 @@ type
validator_committee_index*: uint64
slot*: Slot
# TODO do we even need this? how about a simple tuple?
# TODO do we even need this? how about a simple tuple (alias)?
ValidatorPubkeySlotPair* = object
public_key*: ValidatorPubKey
slot*: Slot
# TODO do we even need this? how about a simple tuple (alias)?
BeaconGenesisTuple* = object
genesis_time*: uint64
genesis_validators_root*: Eth2Digest
genesis_fork_version*: Version

View File

@ -220,7 +220,7 @@ func get_beacon_proposer_indexes_for_epoch*(state: BeaconState, epoch: Epoch, st
result.add (currSlot, idx.get)
# https://github.com/ethereum/eth2.0-specs/blob/v0.11.3/specs/phase0/validator.md#validator-assignments
func get_committee_assignment(
func get_committee_assignment*(
state: BeaconState, epoch: Epoch, validator_index: ValidatorIndex):
Option[tuple[a: seq[ValidatorIndex], b: CommitteeIndex, c: Slot]] {.used.} =
# Return the committee assignment in the ``epoch`` for ``validator_index``.

View File

@ -27,19 +27,21 @@ type
BeaconTime* = distinct int64 ## Seconds from beacon genesis time
proc init*(T: type BeaconClock, state: BeaconState): T =
## Initialize time from a beacon state. The genesis time of a beacon state is
## constant throughout its lifetime, so the state from any slot will do,
## including the genesis state.
proc init*(T: type BeaconClock, genesis_time: uint64): T =
let
unixGenesis = fromUnix(state.genesis_time.int64)
unixGenesis = fromUnix(genesis_time.int64)
# GENESIS_SLOT offsets slot time, but to simplify calculations, we apply that
# offset to genesis instead of applying it at every time conversion
unixGenesisOffset = times.seconds(int(GENESIS_SLOT * SECONDS_PER_SLOT))
T(genesis: unixGenesis - unixGenesisOffset)
proc init*(T: type BeaconClock, state: BeaconState): T =
## Initialize time from a beacon state. The genesis time of a beacon state is
## constant throughout its lifetime, so the state from any slot will do,
## including the genesis state.
BeaconClock.init(state.genesis_time)
template `<`*(a, b: BeaconTime): bool =
int64(a) < int64(b)

View File

@ -26,8 +26,36 @@ type
proc installValidatorApiHandlers*(rpcServer: RpcServer, node: BeaconNode) =
# TODO Probably the `beacon` ones (and not `validator`) should be defined elsewhere...
rpcServer.rpc("get_v1_beacon_states_fork") do (stateId: string) -> Fork:
notice "== get_v1_beacon_states_fork", stateId = stateId
result = case stateId:
of "head":
discard node.updateHead() # TODO do we need this?
node.blockPool.headState.data.data.fork
of "genesis":
Fork(previous_version: Version(GENESIS_FORK_VERSION),
current_version: Version(GENESIS_FORK_VERSION),
epoch: 0.Epoch)
of "finalized":
# TODO
Fork()
of "justified":
# TODO
Fork()
else:
# TODO parse `stateId` as either a number (slot) or a hash (stateRoot)
Fork()
# TODO Probably the `beacon` ones (and not `validator`) should be defined elsewhere...
rpcServer.rpc("get_v1_beacon_genesis") do () -> BeaconGenesisTuple:
notice "== get_v1_beacon_genesis"
return BeaconGenesisTuple(genesis_time: node.blockPool.headState.data.data.genesis_time,
genesis_validators_root: node.blockPool.headState.data.data.genesis_validators_root,
genesis_fork_version: Version(GENESIS_FORK_VERSION))
rpcServer.rpc("get_v1_validator_blocks") do (slot: Slot, graffiti: Eth2Digest, randao_reveal: ValidatorSig) -> BeaconBlock:
notice "== get_v1_validator_blocks", slot = slot
var head = node.updateHead()
let proposer = node.blockPool.getProposer(head, slot)
@ -38,11 +66,16 @@ proc installValidatorApiHandlers*(rpcServer: RpcServer, node: BeaconNode) =
let res = makeBeaconBlockForHeadAndSlot(node, valInfo, proposer.get()[0], graffiti, head, slot)
# TODO how do we handle the case when we cannot return a meaningful block? 404...
doAssert(res.message.isSome())
return res.message.get()
# currently this fails often - perhaps because the block has already been
# processed and signed with the inProcess validator...
# doAssert(res.message.isSome())
return res.message.get(BeaconBlock()) # returning a default if empty
rpcServer.rpc("post_v1_beacon_blocks") do (body: SignedBeaconBlock):
rpcServer.rpc("post_v1_beacon_blocks") do (body: SignedBeaconBlock) -> bool :
notice "== post_v1_beacon_blocks"
# TODO make onBeaconBlock return a result and discard it wherever its unnecessary
onBeaconBlock(node, body)
return true
rpcServer.rpc("get_v1_validator_attestation_data") do (slot: Slot, committee_index: CommitteeIndex) -> AttestationData:
discard
@ -55,11 +88,22 @@ proc installValidatorApiHandlers*(rpcServer: RpcServer, node: BeaconNode) =
discard
rpcServer.rpc("post_v1_validator_duties_attester") do (epoch: Epoch, public_keys: seq[ValidatorPubKey]) -> seq[AttesterDuties]:
discard
notice "== post_v1_validator_duties_attester", epoch = epoch
for pubkey in public_keys:
let idx = node.blockPool.headState.data.data.validators.asSeq.findIt(it.pubKey == pubkey)
if idx != -1:
let res = node.blockPool.headState.data.data.get_committee_assignment(epoch, idx.ValidatorIndex)
if res.isSome:
result.add(AttesterDuties(public_key: pubkey,
committee_index: res.get.b,
committee_length: res.get.a.len.uint64,
validator_committee_index: res.get.a.find(idx.ValidatorIndex).uint64,
slot: res.get.c))
rpcServer.rpc("get_v1_validator_duties_proposer") do (epoch: Epoch) -> seq[ValidatorPubkeySlotPair]:
notice "== get_v1_validator_duties_proposer", epoch = epoch
var cache = get_empty_per_epoch_cache()
return get_beacon_proposer_indexes_for_epoch(node.blockPool.headState.data.data, epoch, cache).mapIt(ValidatorPubkeySlotPair(
result = get_beacon_proposer_indexes_for_epoch(node.blockPool.headState.data.data, epoch, cache).mapIt(ValidatorPubkeySlotPair(
public_key: node.blockPool.headState.data.data.validators[it.i].pubkey,
slot: it.s
))

View File

@ -12,6 +12,7 @@ import
# Nimble packages
stew/shims/[tables, macros],
chronos, confutils, metrics, json_rpc/[rpcclient, jsonmarshal],
chronicles,
blscurve, json_serialization/std/[options, sets, net],
# Local modules
@ -27,7 +28,7 @@ import
template sourceDir: string = currentSourcePath.rsplit(DirSep, 1)[0]
## Generate client convenience marshalling wrappers from forward declarations
createRpcSigs(RpcClient, sourceDir & DirSep & "spec" & DirSep & "eth2_apis" & DirSep & "validator_callsigs.nim")
createRpcSigs(RpcClient, sourceDir / "spec" / "eth2_apis" / "validator_callsigs.nim")
type
ValidatorClient = ref object
@ -35,9 +36,41 @@ type
client: RpcHttpClient
beaconClock: BeaconClock
attachedValidators: ValidatorPool
validatorDutiesForEpoch: Table[Slot, ValidatorPubKey]
fork: Fork
proposalsForEpoch: Table[Slot, ValidatorPubKey]
attestationsForEpoch: Table[Slot, AttesterDuties]
beaconGenesis: BeaconGenesisTuple
# TODO remove this and move to real logging once done experimenting
# it's much easier to distinguish such output from the one with timestamps
proc port_logged(vc: ValidatorClient, msg: string) =
echo "== ", vc.config.rpcPort, " ", msg
proc getValidatorDutiesForEpoch(vc: ValidatorClient, epoch: Epoch) {.gcsafe, async.} =
vc.port_logged "await 1"
let proposals = await vc.client.get_v1_validator_duties_proposer(epoch)
vc.port_logged "await 2"
# update the block proposal duties this VC should do during this epoch
vc.proposalsForEpoch.clear()
for curr in proposals:
if vc.attachedValidators.validators.contains curr.public_key:
vc.proposalsForEpoch.add(curr.slot, curr.public_key)
# couldn't use mapIt in ANY shape or form so reverting to raw loops - sorry Sean Parent :|
var validatorPubkeys: seq[ValidatorPubKey]
for key in vc.attachedValidators.validators.keys:
validatorPubkeys.add key
# update the attestation duties this VC should do during this epoch
let attestations = await vc.client.post_v1_validator_duties_attester(epoch, validatorPubkeys)
vc.attestationsForEpoch.clear()
for a in attestations:
vc.attestationsForEpoch.add(a.slot, a)
# for now we will get the fork each time we update the validator duties for each epoch
vc.fork = await vc.client.get_v1_beacon_states_fork("head")
proc onSlotStart(vc: ValidatorClient, lastSlot, scheduledSlot: Slot) {.gcsafe, async.} =
vc.port_logged "WAKE UP! slot " & $scheduledSlot
let
# The slot we should be at, according to the clock
@ -49,40 +82,49 @@ proc onSlotStart(vc: ValidatorClient, lastSlot, scheduledSlot: Slot) {.gcsafe, a
nextSlot = slot + 1
try:
# TODO think about handling attestations in addition to block proposals - is waitFor OK...?
# at the start of each epoch - request all validators which should propose
# during this epoch and match that against the validators in this VC instance
# at the start of each epoch - request all validator duties for the current epoch
# TODO perhaps call this not on the first slot of each Epoch but perhaps 1 slot earlier
# because there are a few back-and-forth requests which could take up time for attesting...
if scheduledSlot.isEpoch:
let validatorDutiesForEpoch = waitFor vc.client.get_v1_validator_duties_proposer(scheduledSlot.compute_epoch_at_slot)
# update the duties (block proposals) this VC client should do during this epoch
vc.validatorDutiesForEpoch.clear()
for curr in validatorDutiesForEpoch:
if vc.attachedValidators.validators.contains curr.public_key:
vc.validatorDutiesForEpoch.add(curr.slot, curr.public_key)
await getValidatorDutiesForEpoch(vc, scheduledSlot.compute_epoch_at_slot)
# check if we have a validator which needs to propose on this slot
if vc.validatorDutiesForEpoch.contains slot:
let pubkey = vc.validatorDutiesForEpoch[slot]
let validator = vc.attachedValidators.validators[pubkey]
if vc.proposalsForEpoch.contains slot:
let public_key = vc.proposalsForEpoch[slot]
let validator = vc.attachedValidators.validators[public_key]
# TODO get these from the BN and store them in the ValidatorClient
let fork = Fork()
let genesis_validators_root = Eth2Digest()
let randao_reveal = validator.genRandaoReveal(
vc.fork, vc.beaconGenesis.genesis_validators_root, slot)
let randao_reveal = validator.genRandaoReveal(fork, genesis_validators_root, slot)
vc.port_logged "await 3"
var newBlock = SignedBeaconBlock(
message: waitFor vc.client.get_v1_validator_blocks(slot, Eth2Digest(), randao_reveal)
message: await vc.client.get_v1_validator_blocks(slot, Eth2Digest(), randao_reveal)
)
vc.port_logged "await 4"
let blockRoot = hash_tree_root(newBlock.message)
newBlock.signature = waitFor validator.signBlockProposal(fork, genesis_validators_root, slot, blockRoot)
newBlock.signature = await validator.signBlockProposal(
vc.fork, vc.beaconGenesis.genesis_validators_root, slot, blockRoot)
discard waitFor vc.client.post_v1_beacon_blocks(newBlock)
vc.port_logged "about to await for the last time!"
discard await vc.client.post_v1_beacon_blocks(newBlock)
vc.port_logged "did we do it?"
# check if we have a validator which needs to propose on this slot
if vc.attestationsForEpoch.contains slot:
let a = vc.attestationsForEpoch[slot]
let validator = vc.attachedValidators.validators[a.public_key]
discard validator
vc.port_logged("attestation: " & $a.committee_index.int64 & " " & $a.validator_committee_index)
except CatchableError as err:
echo err.msg
error "Caught an unexpected error", err = err.msg
let
nextSlotStart = saturate(vc.beaconClock.fromNow(nextSlot))
@ -93,10 +135,7 @@ proc onSlotStart(vc: ValidatorClient, lastSlot, scheduledSlot: Slot) {.gcsafe, a
asyncCheck vc.onSlotStart(slot, nextSlot)
programMain:
let
clientIdVC = "Nimbus validator client v" & fullVersionStr
banner = clientIdVC & "\p" & copyrights & "\p\p" & nimBanner
config = ValidatorClientConf.load(version = banner, copyrightBanner = banner)
let config = makeBannerAndConfig("Nimbus validator client v" & fullVersionStr, ValidatorClientConf)
sleep(config.delayStart * 1000)
@ -113,29 +152,37 @@ programMain:
cmdParams = commandLineParams(),
config
# TODO: the genesis time should be obtained through calls to the beacon node
# this applies also for genesis_validators_root... and the fork!
var genesisState = config.getStateFromSnapshot()
var vc = ValidatorClient(
config: config,
client: newRpcHttpClient(),
beaconClock: BeaconClock.init(genesisState[]),
attachedValidators: ValidatorPool.init()
)
vc.validatorDutiesForEpoch.init()
vc.proposalsForEpoch.init()
vc.attestationsForEpoch.init()
# load all the validators from the data dir into memory
for curr in vc.config.validatorKeys:
vc.attachedValidators.addLocalValidator(curr.toPubKey, curr)
# TODO perhaps we should handle the case if the BN is down and try to connect to it
# untill success, and also later on disconnets we should continue trying to reconnect
waitFor vc.client.connect("localhost", Port(config.rpcPort)) # TODO: use config.rpcAddress
echo "connected to beacon node running on port ", config.rpcPort
info "Connected to beacon node", port = config.rpcPort
# init the beacon clock
vc.beaconGenesis = waitFor vc.client.get_v1_beacon_genesis()
vc.beaconClock = BeaconClock.init(vc.beaconGenesis.genesis_time)
let
curSlot = vc.beaconClock.now().slotOrZero()
nextSlot = curSlot + 1 # No earlier than GENESIS_SLOT + 1
fromNow = saturate(vc.beaconClock.fromNow(nextSlot))
# onSlotStart() requests the validator duties only on the start of each epoch
# so we should request the duties here when the VC binary boots up in order
# to handle the case when in the middle of an epoch. Also for the genesis slot.
waitFor vc.getValidatorDutiesForEpoch(curSlot.compute_epoch_at_slot)
info "Scheduling first slot action",
beaconTime = shortLog(vc.beaconClock.now()),
nextSlot = shortLog(nextSlot),

View File

@ -7,7 +7,7 @@
import
# Standard library
os, tables, strutils, times,
os, tables, strutils,
# Nimble packages
stew/[objects, bitseqs], stew/shims/macros,
@ -40,14 +40,6 @@ proc saveValidatorKey*(keyName, key: string, conf: BeaconNodeConf) =
writeFile(outputFile, key)
info "Imported validator key", file = outputFile
template findIt(s: openarray, predicate: untyped): int =
var res = -1
for i, it {.inject.} in s:
if predicate:
res = i
break
res
proc addLocalValidator*(node: BeaconNode,
state: BeaconState,
privKey: ValidatorPrivKey) =
@ -137,13 +129,13 @@ proc sendAttestation(node: BeaconNode,
beacon_attestations_sent.inc()
type
ValidatorInfoForMakeBeaconBlockType* = enum
ValidatorInfoForMakeBeaconBlockKind* = enum
viValidator
viRandao_reveal
ValidatorInfoForMakeBeaconBlock* = object
case kind*: ValidatorInfoForMakeBeaconBlockType
case kind*: ValidatorInfoForMakeBeaconBlockKind
of viValidator: validator*: AttachedValidator
else: randao_reveal*: ValidatorSig
of viRandao_reveal: randao_reveal*: ValidatorSig
proc makeBeaconBlockForHeadAndSlot*(node: BeaconNode,
val_info: ValidatorInfoForMakeBeaconBlock,
@ -170,9 +162,9 @@ proc makeBeaconBlockForHeadAndSlot*(node: BeaconNode,
# and it's causing problems when the function becomes a generic for 2 types...
proc getRandaoReveal(val_info: ValidatorInfoForMakeBeaconBlock): ValidatorSig =
if val_info.kind == viValidator:
val_info.validator.genRandaoReveal(state.fork, state.genesis_validators_root, slot)
else:
val_info.randao_reveal
return val_info.validator.genRandaoReveal(state.fork, state.genesis_validators_root, slot)
elif val_info.kind == viRandao_reveal:
return val_info.randao_reveal
let
poolPtr = unsafeAddr node.blockPool.dag # safe because restore is short-lived

View File

@ -63,15 +63,18 @@ cd "$DATA_DIR"
# uncomment to force always using an external VC binary for VC duties
# TODO remove this when done with implementing the VC - here just for convenience during dev
#EXTERNAL_VALIDATORS="yes"
#VALIDATOR_API="yes"
EXTERNAL_VALIDATORS_ARG=""
if [ "${EXTERNAL_VALIDATORS:-}" == "yes" ]; then
EXTERNAL_VALIDATORS_ARG="--external-validators"
VALIDATOR_API_ARG=""
if [ "${VALIDATOR_API:-}" == "yes" ]; then
VALIDATOR_API_ARG="--validator-api"
# we lass a few seconds as delay for the start ==> that way we can start the
# beacon node before the VC - otherwise we would have to add "&" conditionally to
# the command which starts the BN - makes the shell script much more complicated
# TODO launch the VC through the start.sh script in order to address this comment:
# https://github.com/status-im/nim-beacon-chain/pull/1055#discussion_r429540155
$VALIDATOR_CLIENT_BIN \
--log-level=${LOG_LEVEL:-DEBUG} \
--data-dir=$DATA_DIR \
--rpc-port="$(( $BASE_RPC_PORT + $NODE_ID ))" \
--delay-start=5 &
@ -86,7 +89,7 @@ $BEACON_NODE_BIN \
--tcp-port=$PORT \
--udp-port=$PORT \
$SNAPSHOT_ARG \
$EXTERNAL_VALIDATORS_ARG \
$VALIDATOR_API_ARG \
$NAT_ARG \
$WEB3_ARG \
--deposit-contract=$DEPOSIT_CONTRACT_ADDRESS \