mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-02-23 11:48:33 +00:00
misc fixes (#2027)
* log when database is loading (to avoid confusion) * generate network keys later during startup * fix quarantine not scheduling chain of parents for download and increase size to one epoch * log validator count, enr and peerid more clearly on startup
This commit is contained in:
parent
7ba541a564
commit
a6b188bfd4
@ -2,6 +2,8 @@ Next
|
|||||||
=================
|
=================
|
||||||
|
|
||||||
* Avoid pcre dependency
|
* Avoid pcre dependency
|
||||||
|
* Increase quarantine size to 32 and fix parents not being downloaded
|
||||||
|
consistently
|
||||||
|
|
||||||
2020-11-12 v0.6.2
|
2020-11-12 v0.6.2
|
||||||
=================
|
=================
|
||||||
|
@ -52,8 +52,7 @@ proc init*(T: type AttestationPool, chainDag: ChainDAGRef, quarantine: Quarantin
|
|||||||
blocks.add cur
|
blocks.add cur
|
||||||
cur = cur.parent
|
cur = cur.parent
|
||||||
|
|
||||||
info "Initializing fork choice from block database",
|
info "Initializing fork choice", unfinalized_blocks = blocks.len
|
||||||
unfinalized_blocks = blocks.len
|
|
||||||
|
|
||||||
var epochRef = finalizedEpochRef
|
var epochRef = finalizedEpochRef
|
||||||
for i in 0..<blocks.len:
|
for i in 0..<blocks.len:
|
||||||
|
@ -33,7 +33,7 @@ func getOrResolve*(dag: ChainDAGRef, quarantine: var QuarantineRef, root: Eth2Di
|
|||||||
result = dag.getRef(root)
|
result = dag.getRef(root)
|
||||||
|
|
||||||
if result.isNil:
|
if result.isNil:
|
||||||
quarantine.missing[root] = MissingBlock()
|
quarantine.addMissing(root)
|
||||||
|
|
||||||
proc addRawBlock*(
|
proc addRawBlock*(
|
||||||
dag: var ChainDAGRef, quarantine: var QuarantineRef,
|
dag: var ChainDAGRef, quarantine: var QuarantineRef,
|
||||||
@ -223,18 +223,11 @@ proc addRawBlock*(
|
|||||||
|
|
||||||
return ok dag.clearanceState.blck
|
return ok dag.clearanceState.blck
|
||||||
|
|
||||||
# TODO already checked hash though? main reason to keep this is because
|
# This is an unresolved block - add it to the quarantine, which will cause its
|
||||||
# the pending dag calls this function back later in a loop, so as long
|
# parent to be scheduled for downloading
|
||||||
# as dag.add(...) requires a SignedBeaconBlock, easier to keep them in
|
|
||||||
# pending too.
|
|
||||||
if not quarantine.add(dag, signedBlock):
|
if not quarantine.add(dag, signedBlock):
|
||||||
debug "Block quarantine full"
|
debug "Block quarantine full"
|
||||||
|
|
||||||
# TODO possibly, it makes sense to check the database - that would allow sync
|
|
||||||
# to simply fill up the database with random blocks the other clients
|
|
||||||
# think are useful - but, it would also risk filling the database with
|
|
||||||
# junk that's not part of the block graph
|
|
||||||
|
|
||||||
if blck.parent_root in quarantine.missing or
|
if blck.parent_root in quarantine.missing or
|
||||||
containsOrphan(quarantine, signedBlock):
|
containsOrphan(quarantine, signedBlock):
|
||||||
debug "Unresolved block (parent missing or orphaned)",
|
debug "Unresolved block (parent missing or orphaned)",
|
||||||
@ -243,7 +236,6 @@ proc addRawBlock*(
|
|||||||
|
|
||||||
return err((ValidationResult.Ignore, MissingParent))
|
return err((ValidationResult.Ignore, MissingParent))
|
||||||
|
|
||||||
# This is an unresolved block - put its parent on the missing list for now...
|
|
||||||
# TODO if we receive spam blocks, one heurestic to implement might be to wait
|
# TODO if we receive spam blocks, one heurestic to implement might be to wait
|
||||||
# for a couple of attestations to appear before fetching parents - this
|
# for a couple of attestations to appear before fetching parents - this
|
||||||
# would help prevent using up network resources for spam - this serves
|
# would help prevent using up network resources for spam - this serves
|
||||||
@ -253,9 +245,6 @@ proc addRawBlock*(
|
|||||||
# them out without penalty - but signing invalid attestations carries
|
# them out without penalty - but signing invalid attestations carries
|
||||||
# a risk of being slashed, making attestations a more valuable spam
|
# a risk of being slashed, making attestations a more valuable spam
|
||||||
# filter.
|
# filter.
|
||||||
# TODO when we receive the block, we don't know how many others we're missing
|
|
||||||
# from that branch, so right now, we'll just do a blind guess
|
|
||||||
|
|
||||||
debug "Unresolved block (parent missing)",
|
debug "Unresolved block (parent missing)",
|
||||||
orphans = quarantine.orphans.len,
|
orphans = quarantine.orphans.len,
|
||||||
missing = quarantine.missing.len
|
missing = quarantine.missing.len
|
||||||
@ -348,7 +337,7 @@ proc isValidBeaconBlock*(
|
|||||||
debug "parent unknown, putting block in quarantine",
|
debug "parent unknown, putting block in quarantine",
|
||||||
current_slot = wallTime.toSlot()
|
current_slot = wallTime.toSlot()
|
||||||
if not quarantine.add(dag, signed_beacon_block):
|
if not quarantine.add(dag, signed_beacon_block):
|
||||||
warn "Block quarantine full"
|
debug "Block quarantine full"
|
||||||
return err((ValidationResult.Ignore, MissingParent))
|
return err((ValidationResult.Ignore, MissingParent))
|
||||||
|
|
||||||
# [REJECT] The current finalized_checkpoint is an ancestor of block -- i.e.
|
# [REJECT] The current finalized_checkpoint is an ancestor of block -- i.e.
|
||||||
|
@ -31,8 +31,6 @@ func checkMissing*(quarantine: var QuarantineRef): seq[FetchRecord] =
|
|||||||
inc v.tries
|
inc v.tries
|
||||||
|
|
||||||
for k in done:
|
for k in done:
|
||||||
# TODO Need to potentially remove from quarantine.pending - this is currently a
|
|
||||||
# memory leak here!
|
|
||||||
quarantine.missing.del(k)
|
quarantine.missing.del(k)
|
||||||
|
|
||||||
# simple (simplistic?) exponential backoff for retries..
|
# simple (simplistic?) exponential backoff for retries..
|
||||||
@ -66,11 +64,16 @@ func removeOrphan*(
|
|||||||
quarantine: var QuarantineRef, signedBlock: SignedBeaconBlock) =
|
quarantine: var QuarantineRef, signedBlock: SignedBeaconBlock) =
|
||||||
quarantine.orphans.del((signedBlock.root, signedBlock.signature))
|
quarantine.orphans.del((signedBlock.root, signedBlock.signature))
|
||||||
|
|
||||||
|
func isViableOrphan(dag: ChainDAGRef, signedBlock: SignedBeaconBlock): bool =
|
||||||
|
# The orphan must be newer than the finalization point so that its parent
|
||||||
|
# either is the finalized block or more recent
|
||||||
|
signedBlock.message.slot > dag.finalizedHead.slot
|
||||||
|
|
||||||
func removeOldBlocks(quarantine: var QuarantineRef, dag: ChainDAGRef) =
|
func removeOldBlocks(quarantine: var QuarantineRef, dag: ChainDAGRef) =
|
||||||
var oldBlocks: seq[(Eth2Digest, ValidatorSig)]
|
var oldBlocks: seq[(Eth2Digest, ValidatorSig)]
|
||||||
|
|
||||||
for k, v in quarantine.orphans.pairs():
|
for k, v in quarantine.orphans.pairs():
|
||||||
if v.message.slot <= dag.finalizedHead.slot:
|
if not isViableOrphan(dag, v):
|
||||||
oldBlocks.add k
|
oldBlocks.add k
|
||||||
|
|
||||||
for k in oldBlocks:
|
for k in oldBlocks:
|
||||||
@ -97,16 +100,24 @@ func add*(quarantine: var QuarantineRef, dag: ChainDAGRef,
|
|||||||
# for future slots are rejected before reaching quarantine, this usually
|
# for future slots are rejected before reaching quarantine, this usually
|
||||||
# will be a block for the last couple of slots for which the parent is a
|
# will be a block for the last couple of slots for which the parent is a
|
||||||
# likely imminent arrival.
|
# likely imminent arrival.
|
||||||
const MAX_QUARANTINE_ORPHANS = 10
|
|
||||||
|
# Since we start forward sync when about one epoch is missing, that's as
|
||||||
|
# good a number as any.
|
||||||
|
const MAX_QUARANTINE_ORPHANS = SLOTS_PER_EPOCH
|
||||||
|
|
||||||
|
if not isViableOrphan(dag, signedBlock):
|
||||||
|
return false
|
||||||
|
|
||||||
quarantine.removeOldBlocks(dag)
|
quarantine.removeOldBlocks(dag)
|
||||||
|
|
||||||
if quarantine.orphans.len >= MAX_QUARANTINE_ORPHANS:
|
# Even if the quarantine is full, we need to schedule its parent for
|
||||||
|
# downloading or we'll never get to the bottom of things
|
||||||
|
quarantine.addMissing(signedBlock.message.parent_root)
|
||||||
|
|
||||||
|
if quarantine.orphans.lenu64 >= MAX_QUARANTINE_ORPHANS:
|
||||||
return false
|
return false
|
||||||
|
|
||||||
quarantine.orphans[(signedBlock.root, signedBlock.signature)] = signedBlock
|
quarantine.orphans[(signedBlock.root, signedBlock.signature)] = signedBlock
|
||||||
quarantine.missing.del(signedBlock.root)
|
quarantine.missing.del(signedBlock.root)
|
||||||
|
|
||||||
quarantine.addMissing(signedBlock.message.parent_root)
|
|
||||||
|
|
||||||
true
|
true
|
||||||
|
@ -470,13 +470,6 @@ template raisePeerDisconnected(msg: string, r: DisconnectionReason) =
|
|||||||
e.reason = r
|
e.reason = r
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
proc disconnectAndRaise(peer: Peer,
|
|
||||||
reason: DisconnectionReason,
|
|
||||||
msg: string) {.async.} =
|
|
||||||
let r = reason
|
|
||||||
await peer.disconnect(r)
|
|
||||||
raisePeerDisconnected(msg, r)
|
|
||||||
|
|
||||||
proc writeChunk*(conn: Connection,
|
proc writeChunk*(conn: Connection,
|
||||||
responseCode: Option[ResponseCode],
|
responseCode: Option[ResponseCode],
|
||||||
payload: Bytes): Future[void] =
|
payload: Bytes): Future[void] =
|
||||||
@ -1396,7 +1389,7 @@ proc createEth2Node*(rng: ref BrHmacDrbgContext,
|
|||||||
announcedAddresses = if extIp.isNone(): @[]
|
announcedAddresses = if extIp.isNone(): @[]
|
||||||
else: @[tcpEndPoint(extIp.get(), extTcpPort)]
|
else: @[tcpEndPoint(extIp.get(), extTcpPort)]
|
||||||
|
|
||||||
info "Initializing networking", hostAddress,
|
debug "Initializing networking", hostAddress,
|
||||||
network_public_key = netKeys.pubkey,
|
network_public_key = netKeys.pubkey,
|
||||||
announcedAddresses
|
announcedAddresses
|
||||||
|
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
|
|
||||||
import
|
import
|
||||||
# Standard library
|
# Standard library
|
||||||
std/[os, tables, strutils, sequtils, times, math, terminal, osproc, random],
|
std/[os, tables, strutils, strformat, sequtils, times, math, terminal, osproc,
|
||||||
|
random],
|
||||||
|
|
||||||
# Nimble packages
|
# Nimble packages
|
||||||
stew/[objects, byteutils, endians2, io2], stew/shims/macros,
|
stew/[objects, byteutils, endians2, io2], stew/shims/macros,
|
||||||
@ -72,13 +73,9 @@ proc init*(T: type BeaconNode,
|
|||||||
genesisStateContents: ref string,
|
genesisStateContents: ref string,
|
||||||
eth1Network: Option[Eth1Network]): Future[BeaconNode] {.async.} =
|
eth1Network: Option[Eth1Network]): Future[BeaconNode] {.async.} =
|
||||||
let
|
let
|
||||||
netKeys = getPersistentNetKeys(rng[], conf)
|
|
||||||
nickname = if conf.nodeName == "auto": shortForm(netKeys)
|
|
||||||
else: conf.nodeName
|
|
||||||
db = BeaconChainDB.init(conf.runtimePreset, conf.databaseDir)
|
db = BeaconChainDB.init(conf.runtimePreset, conf.databaseDir)
|
||||||
|
|
||||||
var
|
var
|
||||||
eth1Monitor: Eth1Monitor
|
|
||||||
genesisState, checkpointState: ref BeaconState
|
genesisState, checkpointState: ref BeaconState
|
||||||
checkpointBlock: SignedBeaconBlock
|
checkpointBlock: SignedBeaconBlock
|
||||||
|
|
||||||
@ -114,6 +111,7 @@ proc init*(T: type BeaconNode,
|
|||||||
fatal "--finalized-checkpoint-block cannot be specified without --finalized-checkpoint-state"
|
fatal "--finalized-checkpoint-block cannot be specified without --finalized-checkpoint-state"
|
||||||
quit 1
|
quit 1
|
||||||
|
|
||||||
|
var eth1Monitor: Eth1Monitor
|
||||||
if not ChainDAGRef.isInitialized(db):
|
if not ChainDAGRef.isInitialized(db):
|
||||||
var
|
var
|
||||||
tailState: ref BeaconState
|
tailState: ref BeaconState
|
||||||
@ -181,7 +179,7 @@ proc init*(T: type BeaconNode,
|
|||||||
try:
|
try:
|
||||||
genesisState = newClone(SSZ.decode(genesisStateContents[], BeaconState))
|
genesisState = newClone(SSZ.decode(genesisStateContents[], BeaconState))
|
||||||
except CatchableError as err:
|
except CatchableError as err:
|
||||||
raiseAssert "The baked-in state must be valid"
|
raiseAssert "Invalid baked-in state: " & err.msg
|
||||||
|
|
||||||
if checkpointState != nil:
|
if checkpointState != nil:
|
||||||
tailState = checkpointState
|
tailState = checkpointState
|
||||||
@ -197,11 +195,13 @@ proc init*(T: type BeaconNode,
|
|||||||
error "Failed to initialize database", err = e.msg
|
error "Failed to initialize database", err = e.msg
|
||||||
quit 1
|
quit 1
|
||||||
|
|
||||||
|
info "Loading block dag from database", path = conf.databaseDir
|
||||||
|
|
||||||
# TODO(zah) check that genesis given on command line (if any) matches database
|
# TODO(zah) check that genesis given on command line (if any) matches database
|
||||||
let
|
let
|
||||||
chainDagFlags = if conf.verifyFinalization: {verifyFinalization}
|
chainDagFlags = if conf.verifyFinalization: {verifyFinalization}
|
||||||
else: {}
|
else: {}
|
||||||
chainDag = init(ChainDAGRef, conf.runtimePreset, db, chainDagFlags)
|
chainDag = ChainDAGRef.init(conf.runtimePreset, db, chainDagFlags)
|
||||||
beaconClock = BeaconClock.init(chainDag.headState.data.data)
|
beaconClock = BeaconClock.init(chainDag.headState.data.data)
|
||||||
quarantine = QuarantineRef()
|
quarantine = QuarantineRef()
|
||||||
|
|
||||||
@ -252,6 +252,9 @@ proc init*(T: type BeaconNode,
|
|||||||
nil
|
nil
|
||||||
|
|
||||||
let
|
let
|
||||||
|
netKeys = getPersistentNetKeys(rng[], conf)
|
||||||
|
nickname = if conf.nodeName == "auto": shortForm(netKeys)
|
||||||
|
else: conf.nodeName
|
||||||
enrForkId = enrForkIdFromState(chainDag.headState.data.data)
|
enrForkId = enrForkIdFromState(chainDag.headState.data.data)
|
||||||
topicBeaconBlocks = getBeaconBlocksTopic(enrForkId.forkDigest)
|
topicBeaconBlocks = getBeaconBlocksTopic(enrForkId.forkDigest)
|
||||||
topicAggregateAndProofs = getAggregateAndProofsTopic(enrForkId.forkDigest)
|
topicAggregateAndProofs = getAggregateAndProofsTopic(enrForkId.forkDigest)
|
||||||
@ -278,6 +281,7 @@ proc init*(T: type BeaconNode,
|
|||||||
topicAggregateAndProofs: topicAggregateAndProofs,
|
topicAggregateAndProofs: topicAggregateAndProofs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
info "Loading slashing protection database", path = conf.validatorsDir()
|
||||||
res.attachedValidators = ValidatorPool.init(
|
res.attachedValidators = ValidatorPool.init(
|
||||||
SlashingProtectionDB.init(
|
SlashingProtectionDB.init(
|
||||||
chainDag.headState.data.data.genesis_validators_root,
|
chainDag.headState.data.data.genesis_validators_root,
|
||||||
@ -801,6 +805,7 @@ proc createPidFile(filename: string) =
|
|||||||
addQuitProc proc {.noconv.} = discard io2.removeFile(gPidFile)
|
addQuitProc proc {.noconv.} = discard io2.removeFile(gPidFile)
|
||||||
|
|
||||||
proc initializeNetworking(node: BeaconNode) {.async.} =
|
proc initializeNetworking(node: BeaconNode) {.async.} =
|
||||||
|
info "Listening to incoming network requests"
|
||||||
await node.network.startListening()
|
await node.network.startListening()
|
||||||
|
|
||||||
let addressFile = node.config.dataDir / "beacon_node.enr"
|
let addressFile = node.config.dataDir / "beacon_node.enr"
|
||||||
@ -808,10 +813,6 @@ proc initializeNetworking(node: BeaconNode) {.async.} =
|
|||||||
|
|
||||||
await node.network.start()
|
await node.network.start()
|
||||||
|
|
||||||
notice "Networking initialized",
|
|
||||||
enr = node.network.announcedENR.toURI,
|
|
||||||
libp2p = shortLog(node.network.switch.peerInfo)
|
|
||||||
|
|
||||||
proc start(node: BeaconNode) =
|
proc start(node: BeaconNode) =
|
||||||
let
|
let
|
||||||
head = node.chainDag.head
|
head = node.chainDag.head
|
||||||
@ -820,16 +821,17 @@ proc start(node: BeaconNode) =
|
|||||||
|
|
||||||
notice "Starting beacon node",
|
notice "Starting beacon node",
|
||||||
version = fullVersionStr,
|
version = fullVersionStr,
|
||||||
nim = shortNimBanner(),
|
enr = node.network.announcedENR.toURI,
|
||||||
|
peerId = $node.network.switch.peerInfo.peerId,
|
||||||
timeSinceFinalization =
|
timeSinceFinalization =
|
||||||
finalizedHead.slot.toBeaconTime() -
|
node.beaconClock.now() - finalizedHead.slot.toBeaconTime(),
|
||||||
node.beaconClock.now(),
|
|
||||||
head = shortLog(head),
|
head = shortLog(head),
|
||||||
finalizedHead = shortLog(finalizedHead),
|
finalizedHead = shortLog(finalizedHead),
|
||||||
SLOTS_PER_EPOCH,
|
SLOTS_PER_EPOCH,
|
||||||
SECONDS_PER_SLOT,
|
SECONDS_PER_SLOT,
|
||||||
SPEC_VERSION,
|
SPEC_VERSION,
|
||||||
dataDir = node.config.dataDir.string
|
dataDir = node.config.dataDir.string,
|
||||||
|
validators = node.attachedValidators.count
|
||||||
|
|
||||||
if genesisTime.inFuture:
|
if genesisTime.inFuture:
|
||||||
notice "Waiting for genesis", genesisIn = genesisTime.offset
|
notice "Waiting for genesis", genesisIn = genesisTime.offset
|
||||||
@ -1145,7 +1147,7 @@ programMain:
|
|||||||
if config.metricsEnabled:
|
if config.metricsEnabled:
|
||||||
let metricsAddress = config.metricsAddress
|
let metricsAddress = config.metricsAddress
|
||||||
notice "Starting metrics HTTP server",
|
notice "Starting metrics HTTP server",
|
||||||
address = metricsAddress, port = config.metricsPort
|
url = "http://" & $metricsAddress & ":" & $config.metricsPort & "/metrics"
|
||||||
metrics.startHttpServer($metricsAddress, config.metricsPort)
|
metrics.startHttpServer($metricsAddress, config.metricsPort)
|
||||||
|
|
||||||
# There are no managed event loops in here, to do a graceful shutdown, but
|
# There are no managed event loops in here, to do a graceful shutdown, but
|
||||||
|
@ -59,7 +59,6 @@ proc addLocalValidator*(node: BeaconNode,
|
|||||||
proc addLocalValidators*(node: BeaconNode) =
|
proc addLocalValidators*(node: BeaconNode) =
|
||||||
for validatorKey in node.config.validatorKeys:
|
for validatorKey in node.config.validatorKeys:
|
||||||
node.addLocalValidator node.chainDag.headState.data.data, validatorKey
|
node.addLocalValidator node.chainDag.headState.data.data, validatorKey
|
||||||
notice "Local validators attached ", count = node.attachedValidators.count
|
|
||||||
|
|
||||||
proc addRemoteValidators*(node: BeaconNode) =
|
proc addRemoteValidators*(node: BeaconNode) =
|
||||||
# load all the validators from the child process - loop until `end`
|
# load all the validators from the child process - loop until `end`
|
||||||
@ -76,7 +75,6 @@ proc addRemoteValidators*(node: BeaconNode) =
|
|||||||
outStream: node.vcProcess.outputStream,
|
outStream: node.vcProcess.outputStream,
|
||||||
pubKeyStr: $key))
|
pubKeyStr: $key))
|
||||||
node.attachedValidators.addRemoteValidator(key, v)
|
node.attachedValidators.addRemoteValidator(key, v)
|
||||||
notice "Remote validators attached ", count = node.attachedValidators.count
|
|
||||||
|
|
||||||
proc getAttachedValidator*(node: BeaconNode,
|
proc getAttachedValidator*(node: BeaconNode,
|
||||||
pubkey: ValidatorPubKey): AttachedValidator =
|
pubkey: ValidatorPubKey): AttachedValidator =
|
||||||
|
2
vendor/nim-json-rpc
vendored
2
vendor/nim-json-rpc
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 99455437ba3d83d5af1c38007fedeeff295e959e
|
Subproject commit 5b6312a18be4001ef644411b579138a09d853e8c
|
2
vendor/nim-metrics
vendored
2
vendor/nim-metrics
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 77305f3b3ddfef5aff65b685effc7e7a1d1cf59c
|
Subproject commit 22a3867341f7b0a9d55661b41d7ee5febe35c86b
|
Loading…
x
Reference in New Issue
Block a user