fix broken metrics during replay (#2090)
* move metrics out of state transition * add validator count metric * remove expensive beacon_current_validators, beacon_previous_validators metrics (they should be reimplemented with cache), add cheap beacon_active_validators to approximate * remove unused validator count metrics * tidy imports/defects
This commit is contained in:
parent
d98f3ab948
commit
e7f2735271
|
@ -5,6 +5,8 @@
|
||||||
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
# * 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.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import
|
import
|
||||||
# Standard library
|
# Standard library
|
||||||
std/[deques, strformat, tables, hashes],
|
std/[deques, strformat, tables, hashes],
|
||||||
|
@ -206,22 +208,31 @@ template validator_keys*(e: EpochRef): untyped = e.validator_key_store[1][]
|
||||||
template head*(v: ChainDagRef): BlockRef = v.headState.blck
|
template head*(v: ChainDagRef): BlockRef = v.headState.blck
|
||||||
|
|
||||||
func shortLog*(v: BlockSlot): string =
|
func shortLog*(v: BlockSlot): string =
|
||||||
if v.blck.slot == v.slot:
|
try:
|
||||||
&"{v.blck.root.data.toOpenArray(0, 3).toHex()}:{v.blck.slot}"
|
if v.blck.slot == v.slot:
|
||||||
else: # There was a gap - log it
|
&"{v.blck.root.data.toOpenArray(0, 3).toHex()}:{v.blck.slot}"
|
||||||
&"{v.blck.root.data.toOpenArray(0, 3).toHex()}:{v.blck.slot}@{v.slot}"
|
else: # There was a gap - log it
|
||||||
|
&"{v.blck.root.data.toOpenArray(0, 3).toHex()}:{v.blck.slot}@{v.slot}"
|
||||||
|
except ValueError as err:
|
||||||
|
err.msg # Shouldn't happen - but also shouldn't crash!
|
||||||
|
|
||||||
func shortLog*(v: BlockRef): string =
|
func shortLog*(v: BlockRef): string =
|
||||||
if v == nil:
|
try:
|
||||||
"BlockRef(nil)"
|
if v == nil:
|
||||||
else:
|
"BlockRef(nil)"
|
||||||
&"{v.root.data.toOpenArray(0, 3).toHex()}:{v.slot}"
|
else:
|
||||||
|
&"{v.root.data.toOpenArray(0, 3).toHex()}:{v.slot}"
|
||||||
|
except ValueError as err:
|
||||||
|
err.msg # Shouldn't happen - but also shouldn't crash!
|
||||||
|
|
||||||
func shortLog*(v: EpochRef): string =
|
func shortLog*(v: EpochRef): string =
|
||||||
if v == nil:
|
try:
|
||||||
"EpochRef(nil)"
|
if v == nil:
|
||||||
else:
|
"EpochRef(nil)"
|
||||||
&"(epoch ref: {v.epoch})"
|
else:
|
||||||
|
&"(epoch ref: {v.epoch})"
|
||||||
|
except ValueError as err:
|
||||||
|
err.msg # Shouldn't happen - but also shouldn't crash!
|
||||||
|
|
||||||
chronicles.formatIt BlockSlot: shortLog(it)
|
chronicles.formatIt BlockSlot: shortLog(it)
|
||||||
chronicles.formatIt BlockRef: shortLog(it)
|
chronicles.formatIt BlockRef: shortLog(it)
|
||||||
|
|
|
@ -14,15 +14,28 @@ import
|
||||||
../spec/[
|
../spec/[
|
||||||
crypto, datatypes, digest, helpers, validator, state_transition,
|
crypto, datatypes, digest, helpers, validator, state_transition,
|
||||||
beaconstate],
|
beaconstate],
|
||||||
block_pools_types, quarantine
|
./block_pools_types, ./quarantine
|
||||||
|
|
||||||
export block_pools_types, helpers
|
export block_pools_types, helpers
|
||||||
|
|
||||||
|
# https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md#interop-metrics
|
||||||
|
declareGauge beacon_head_root, "Root of the head block of the beacon chain"
|
||||||
|
declareGauge beacon_head_slot, "Slot of the head block of the beacon chain"
|
||||||
|
|
||||||
|
# https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md#interop-metrics
|
||||||
|
declareGauge beacon_finalized_epoch, "Current finalized epoch" # On epoch transition
|
||||||
|
declareGauge beacon_finalized_root, "Current finalized root" # On epoch transition
|
||||||
|
declareGauge beacon_current_justified_epoch, "Current justified epoch" # On epoch transition
|
||||||
|
declareGauge beacon_current_justified_root, "Current justified root" # On epoch transition
|
||||||
|
declareGauge beacon_previous_justified_epoch, "Current previously justified epoch" # On epoch transition
|
||||||
|
declareGauge beacon_previous_justified_root, "Current previously justified root" # On epoch transition
|
||||||
|
|
||||||
declareCounter beacon_reorgs_total, "Total occurrences of reorganizations of the chain" # On fork choice
|
declareCounter beacon_reorgs_total, "Total occurrences of reorganizations of the chain" # On fork choice
|
||||||
declareCounter beacon_state_data_cache_hits, "EpochRef hits"
|
declareCounter beacon_state_data_cache_hits, "EpochRef hits"
|
||||||
declareCounter beacon_state_data_cache_misses, "EpochRef misses"
|
declareCounter beacon_state_data_cache_misses, "EpochRef misses"
|
||||||
declareCounter beacon_state_rewinds, "State database rewinds"
|
declareCounter beacon_state_rewinds, "State database rewinds"
|
||||||
|
|
||||||
|
declareGauge beacon_active_validators, "Number of validators in the active validator set"
|
||||||
declareGauge beacon_pending_deposits, "Number of pending deposits (state.eth1_data.deposit_count - state.eth1_deposit_index)" # On block
|
declareGauge beacon_pending_deposits, "Number of pending deposits (state.eth1_data.deposit_count - state.eth1_deposit_index)" # On block
|
||||||
declareGauge beacon_processed_deposits_total, "Number of total deposits included on chain" # On block
|
declareGauge beacon_processed_deposits_total, "Number of total deposits included on chain" # On block
|
||||||
|
|
||||||
|
@ -810,7 +823,6 @@ proc updateHead*(
|
||||||
|
|
||||||
let
|
let
|
||||||
lastHead = dag.head
|
lastHead = dag.head
|
||||||
dag.db.putHeadBlock(newHead.root)
|
|
||||||
|
|
||||||
# Start off by making sure we have the right state - updateStateData will try
|
# Start off by making sure we have the right state - updateStateData will try
|
||||||
# to use existing in-memory states to make this smooth
|
# to use existing in-memory states to make this smooth
|
||||||
|
@ -818,6 +830,15 @@ proc updateHead*(
|
||||||
updateStateData(
|
updateStateData(
|
||||||
dag, dag.headState, newHead.atSlot(newHead.slot), false, cache)
|
dag, dag.headState, newHead.atSlot(newHead.slot), false, cache)
|
||||||
|
|
||||||
|
dag.db.putHeadBlock(newHead.root)
|
||||||
|
|
||||||
|
let
|
||||||
|
finalizedHead = newHead.atEpochStart(
|
||||||
|
dag.headState.data.data.finalized_checkpoint.epoch)
|
||||||
|
|
||||||
|
doAssert (not finalizedHead.blck.isNil),
|
||||||
|
"Block graph should always lead to a finalized block"
|
||||||
|
|
||||||
if not lastHead.isAncestorOf(newHead):
|
if not lastHead.isAncestorOf(newHead):
|
||||||
notice "Updated head block with chain reorg",
|
notice "Updated head block with chain reorg",
|
||||||
lastHead = shortLog(lastHead),
|
lastHead = shortLog(lastHead),
|
||||||
|
@ -838,9 +859,6 @@ proc updateHead*(
|
||||||
stateSlot = shortLog(dag.headState.data.data.slot),
|
stateSlot = shortLog(dag.headState.data.data.slot),
|
||||||
justified = shortLog(dag.headState.data.data.current_justified_checkpoint),
|
justified = shortLog(dag.headState.data.data.current_justified_checkpoint),
|
||||||
finalized = shortLog(dag.headState.data.data.finalized_checkpoint)
|
finalized = shortLog(dag.headState.data.data.finalized_checkpoint)
|
||||||
let
|
|
||||||
finalizedHead = newHead.atEpochStart(
|
|
||||||
dag.headState.data.data.finalized_checkpoint.epoch)
|
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md#additional-metrics
|
# https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md#additional-metrics
|
||||||
if dag.headState.data.data.eth1_data.deposit_count < high(int64).uint64:
|
if dag.headState.data.data.eth1_data.deposit_count < high(int64).uint64:
|
||||||
|
@ -850,12 +868,28 @@ proc updateHead*(
|
||||||
beacon_processed_deposits_total.set(
|
beacon_processed_deposits_total.set(
|
||||||
dag.headState.data.data.eth1_deposit_index.int64)
|
dag.headState.data.data.eth1_deposit_index.int64)
|
||||||
|
|
||||||
doAssert (not finalizedHead.blck.isNil),
|
beacon_head_root.set newHead.root.toGaugeValue
|
||||||
"Block graph should always lead to a finalized block"
|
beacon_head_slot.set newHead.slot.int64
|
||||||
|
|
||||||
|
if lastHead.slot.epoch != newHead.slot.epoch:
|
||||||
|
# Epoch updated - in theory, these could happen when the wall clock
|
||||||
|
# changes epoch, even if there is no new block / head, but we'll delay
|
||||||
|
# updating them until a block confirms the change
|
||||||
|
beacon_current_justified_epoch.set(
|
||||||
|
dag.headState.data.data.current_justified_checkpoint.epoch.int64)
|
||||||
|
beacon_current_justified_root.set(
|
||||||
|
dag.headState.data.data.current_justified_checkpoint.root.toGaugeValue)
|
||||||
|
beacon_previous_justified_epoch.set(
|
||||||
|
dag.headState.data.data.previous_justified_checkpoint.epoch.int64)
|
||||||
|
beacon_previous_justified_root.set(
|
||||||
|
dag.headState.data.data.previous_justified_checkpoint.root.toGaugeValue)
|
||||||
|
|
||||||
|
let epochRef = getEpochRef(dag, newHead, newHead.slot.epoch)
|
||||||
|
beacon_active_validators.set(
|
||||||
|
epochRef.shuffled_active_validator_indices.lenu64().int64)
|
||||||
|
|
||||||
if finalizedHead != dag.finalizedHead:
|
if finalizedHead != dag.finalizedHead:
|
||||||
block: # Remove states, walking slot by slot
|
block: # Remove states, walking slot by slot
|
||||||
discard
|
|
||||||
var cur = finalizedHead
|
var cur = finalizedHead
|
||||||
while cur != dag.finalizedHead:
|
while cur != dag.finalizedHead:
|
||||||
# TODO This is a quick fix to prune some states from the database, but
|
# TODO This is a quick fix to prune some states from the database, but
|
||||||
|
@ -912,6 +946,11 @@ proc updateHead*(
|
||||||
finalizedHead = shortLog(finalizedHead),
|
finalizedHead = shortLog(finalizedHead),
|
||||||
heads = dag.heads.len
|
heads = dag.heads.len
|
||||||
|
|
||||||
|
beacon_finalized_epoch.set(
|
||||||
|
dag.headState.data.data.finalized_checkpoint.epoch.int64)
|
||||||
|
beacon_finalized_root.set(
|
||||||
|
dag.headState.data.data.finalized_checkpoint.root.toGaugeValue)
|
||||||
|
|
||||||
proc isInitialized*(T: type ChainDAGRef, db: BeaconChainDB): bool =
|
proc isInitialized*(T: type ChainDAGRef, db: BeaconChainDB): bool =
|
||||||
let
|
let
|
||||||
headBlockRoot = db.getHeadBlock()
|
headBlockRoot = db.getHeadBlock()
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
import
|
import
|
||||||
std/tables,
|
std/tables,
|
||||||
chronicles,
|
chronicles,
|
||||||
metrics, stew/results,
|
stew/results,
|
||||||
../extras, ../time,
|
../extras, ../time,
|
||||||
../spec/[crypto, datatypes, digest, helpers, signatures, state_transition],
|
../spec/[crypto, datatypes, digest, helpers, signatures, state_transition],
|
||||||
./block_pools_types, ./chain_dag, ./quarantine
|
./block_pools_types, ./chain_dag, ./quarantine
|
||||||
|
|
|
@ -5,20 +5,20 @@
|
||||||
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
# * 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.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import
|
import
|
||||||
chronicles, tables, options,
|
std/[tables, options],
|
||||||
|
chronicles,
|
||||||
stew/bitops2,
|
stew/bitops2,
|
||||||
metrics,
|
|
||||||
../spec/[crypto, datatypes, digest],
|
../spec/[crypto, datatypes, digest],
|
||||||
block_pools_types
|
./block_pools_types
|
||||||
|
|
||||||
export options, block_pools_types
|
export options, block_pools_types
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
topics = "quarant"
|
topics = "quarant"
|
||||||
|
|
||||||
{.push raises: [Defect].}
|
|
||||||
|
|
||||||
func checkMissing*(quarantine: var QuarantineRef): seq[FetchRecord] =
|
func checkMissing*(quarantine: var QuarantineRef): seq[FetchRecord] =
|
||||||
## Return a list of blocks that we should try to resolve from other client -
|
## Return a list of blocks that we should try to resolve from other client -
|
||||||
## to be called periodically but not too often (once per slot?)
|
## to be called periodically but not too often (once per slot?)
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
# * 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.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[algorithm, sequtils, sets],
|
std/[algorithm, sequtils, sets],
|
||||||
chronicles,
|
chronicles,
|
||||||
|
|
|
@ -36,10 +36,6 @@ declareHistogram beacon_block_delay,
|
||||||
declareHistogram beacon_store_block_duration_seconds,
|
declareHistogram beacon_store_block_duration_seconds,
|
||||||
"storeBlock() duration", buckets = [0.25, 0.5, 1, 2, 4, 8, Inf]
|
"storeBlock() duration", buckets = [0.25, 0.5, 1, 2, 4, 8, Inf]
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md#interop-metrics
|
|
||||||
declareGauge beacon_head_root, "Root of the head block of the beacon chain"
|
|
||||||
declareGauge beacon_head_slot, "Slot of the head block of the beacon chain"
|
|
||||||
|
|
||||||
type
|
type
|
||||||
GetWallTimeFn* = proc(): BeaconTime {.gcsafe, raises: [Defect].}
|
GetWallTimeFn* = proc(): BeaconTime {.gcsafe, raises: [Defect].}
|
||||||
|
|
||||||
|
@ -81,14 +77,15 @@ proc updateHead*(self: var Eth2Processor, wallSlot: Slot) =
|
||||||
|
|
||||||
# Store the new head in the chain DAG - this may cause epochs to be
|
# Store the new head in the chain DAG - this may cause epochs to be
|
||||||
# justified and finalized
|
# justified and finalized
|
||||||
let oldFinalized = self.chainDag.finalizedHead.blck
|
let
|
||||||
|
oldFinalized = self.chainDag.finalizedHead.blck
|
||||||
|
oldHead = self.chainDag.head
|
||||||
|
|
||||||
self.chainDag.updateHead(newHead, self.quarantine)
|
self.chainDag.updateHead(newHead, self.quarantine)
|
||||||
beacon_head_root.set newHead.root.toGaugeValue
|
|
||||||
beacon_head_slot.set newHead.slot.int64
|
|
||||||
|
|
||||||
# Cleanup the fork choice v2 if we have a finalized head
|
# Cleanup the fork choice v2 if we have a finalized head
|
||||||
if oldFinalized != self.chainDag.finalizedHead.blck:
|
if oldFinalized != self.chainDag.finalizedHead.blck:
|
||||||
|
|
||||||
self.attestationPool[].prune()
|
self.attestationPool[].prune()
|
||||||
|
|
||||||
proc dumpBlock[T](
|
proc dumpBlock[T](
|
||||||
|
|
|
@ -45,8 +45,8 @@ template init(T: type RpcHttpServer, ip: ValidIpAddress, port: Port): T =
|
||||||
newRpcHttpServer([initTAddress(ip, port)])
|
newRpcHttpServer([initTAddress(ip, port)])
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md#interop-metrics
|
# https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md#interop-metrics
|
||||||
declareGauge beacon_slot,
|
declareGauge beacon_slot, "Latest slot of the beacon chain state"
|
||||||
"Latest slot of the beacon chain state"
|
declareGauge beacon_current_epoch, "Current epoch"
|
||||||
|
|
||||||
# Finalization tracking
|
# Finalization tracking
|
||||||
declareGauge finalization_delay,
|
declareGauge finalization_delay,
|
||||||
|
@ -540,6 +540,8 @@ proc onSlotStart(node: BeaconNode, lastSlot, scheduledSlot: Slot) {.async.} =
|
||||||
nextSlot = slot + 1
|
nextSlot = slot + 1
|
||||||
|
|
||||||
beacon_slot.set slot.int64
|
beacon_slot.set slot.int64
|
||||||
|
beacon_current_epoch.set slot.epoch.int64
|
||||||
|
|
||||||
finalization_delay.set scheduledSlot.epoch.int64 - finalizedEpoch.int64
|
finalization_delay.set scheduledSlot.epoch.int64 - finalizedEpoch.int64
|
||||||
|
|
||||||
if node.config.verifyFinalization:
|
if node.config.verifyFinalization:
|
||||||
|
|
|
@ -8,8 +8,9 @@
|
||||||
{.push raises: [Defect].}
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import
|
import
|
||||||
tables, algorithm, math, sequtils, options,
|
std/[tables, algorithm, math, sequtils, options],
|
||||||
json_serialization/std/sets, chronicles,
|
json_serialization/std/sets,
|
||||||
|
chronicles,
|
||||||
../extras, ../ssz/merkleization,
|
../extras, ../ssz/merkleization,
|
||||||
./crypto, ./datatypes, ./digest, ./helpers, ./signatures, ./validator,
|
./crypto, ./datatypes, ./digest, ./helpers, ./signatures, ./validator,
|
||||||
../../nbench/bench_lab
|
../../nbench/bench_lab
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
# Standard library
|
# Standard library
|
||||||
std/[options, tables],
|
std/[options, hashes, tables],
|
||||||
# Internal
|
# Internal
|
||||||
./digest,
|
./digest,
|
||||||
# Status
|
# Status
|
||||||
|
@ -33,9 +33,7 @@ import
|
||||||
blscurve,
|
blscurve,
|
||||||
chronicles,
|
chronicles,
|
||||||
json_serialization,
|
json_serialization,
|
||||||
nimcrypto/utils as ncrutils,
|
nimcrypto/utils as ncrutils
|
||||||
# Standard library
|
|
||||||
hashes
|
|
||||||
|
|
||||||
export results, json_serialization
|
export results, json_serialization
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
{.push raises: [Defect].}
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import
|
import
|
||||||
macros, hashes, json, strutils, tables, typetraits,
|
std/[macros, hashes, json, strutils, tables, typetraits],
|
||||||
stew/[byteutils], chronicles,
|
stew/[byteutils], chronicles,
|
||||||
json_serialization/types as jsonTypes,
|
json_serialization/types as jsonTypes,
|
||||||
../version, ../ssz/types as sszTypes, ./crypto, ./digest, ./presets
|
../version, ../ssz/types as sszTypes, ./crypto, ./digest, ./presets
|
||||||
|
|
|
@ -28,7 +28,6 @@ import
|
||||||
chronicles,
|
chronicles,
|
||||||
nimcrypto/[sha2, hash],
|
nimcrypto/[sha2, hash],
|
||||||
stew/byteutils,
|
stew/byteutils,
|
||||||
hashes,
|
|
||||||
eth/common/eth_types_json_serialization,
|
eth/common/eth_types_json_serialization,
|
||||||
blscurve
|
blscurve
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
# * 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.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import
|
import
|
||||||
# Standard library
|
# Standard library
|
||||||
std/[algorithm, math, parseutils, strformat, strutils, typetraits, unicode],
|
std/[algorithm, math, parseutils, strformat, strutils, typetraits, unicode],
|
||||||
|
@ -24,7 +26,6 @@ import nimcrypto/utils as ncrutils
|
||||||
export
|
export
|
||||||
results, burnMem, writeValue, readValue
|
results, burnMem, writeValue, readValue
|
||||||
|
|
||||||
{.push raises: [Defect].}
|
|
||||||
{.localPassC: "-fno-lto".} # no LTO for crypto
|
{.localPassC: "-fno-lto".} # no LTO for crypto
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
import
|
# beacon_chain
|
||||||
macros, strutils, parseutils, tables,
|
# Copyright (c) 2018-2020 Status Research & Development GmbH
|
||||||
stew/endians2,
|
# Licensed and distributed under either of
|
||||||
preset_values
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
||||||
|
# * 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.
|
||||||
|
|
||||||
{.push raises: [Defect].}
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
|
import
|
||||||
|
std/[macros, strutils, parseutils, tables],
|
||||||
|
stew/endians2,
|
||||||
|
preset_values
|
||||||
|
|
||||||
export
|
export
|
||||||
PresetValue, toBytesBE
|
PresetValue, toBytesBE
|
||||||
|
|
||||||
|
|
|
@ -20,40 +20,14 @@
|
||||||
{.push raises: [Defect].}
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import
|
import
|
||||||
tables,
|
std/tables,
|
||||||
chronicles,
|
chronicles,
|
||||||
stew/results,
|
stew/results,
|
||||||
../extras, ../ssz/merkleization, metrics,
|
../extras, ../ssz/merkleization, metrics,
|
||||||
datatypes, crypto, digest, helpers, signatures, validator,
|
./datatypes, ./crypto, ./digest, ./helpers, ./signatures, ./validator,
|
||||||
state_transition_block, state_transition_epoch,
|
./state_transition_block, ./state_transition_epoch,
|
||||||
../../nbench/bench_lab
|
../../nbench/bench_lab
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md#additional-metrics
|
|
||||||
declareGauge beacon_current_validators, """Number of status="pending|active|exited|withdrawable" validators in current epoch""" # On epoch transition
|
|
||||||
declareGauge beacon_previous_validators, """Number of status="pending|active|exited|withdrawable" validators in previous epoch""" # On epoch transition
|
|
||||||
|
|
||||||
func get_epoch_validator_count(state: BeaconState): int64 {.nbench.} =
|
|
||||||
# https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md#additional-metrics
|
|
||||||
#
|
|
||||||
# This O(n) loop doesn't add to the algorithmic complexity of the epoch
|
|
||||||
# transition -- registry update already does this. It is not great, but
|
|
||||||
# isn't new, either. If profiling shows issues some of this can be loop
|
|
||||||
# fusion'ed.
|
|
||||||
for index, validator in state.validators:
|
|
||||||
# These work primarily for the `beacon_current_validators` metric defined
|
|
||||||
# as 'Number of status="pending|active|exited|withdrawable" validators in
|
|
||||||
# current epoch'. This is, in principle, equivalent to checking whether a
|
|
||||||
# validator's either at less than MAX_EFFECTIVE_BALANCE, or has withdrawn
|
|
||||||
# already because withdrawable_epoch has passed, which more precisely has
|
|
||||||
# intuitive meaning of all-the-current-relevant-validators. So, check for
|
|
||||||
# not-(either (not-even-pending) or withdrawn). That is validators change
|
|
||||||
# from not-even-pending to pending to active to exited to withdrawable to
|
|
||||||
# withdrawn, and this avoids bugs on potential edge cases and off-by-1's.
|
|
||||||
if (validator.activation_epoch != FAR_FUTURE_EPOCH or
|
|
||||||
validator.effective_balance > MAX_EFFECTIVE_BALANCE) and
|
|
||||||
validator.withdrawable_epoch > get_current_epoch(state):
|
|
||||||
result += 1
|
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function
|
||||||
proc verify_block_signature*(
|
proc verify_block_signature*(
|
||||||
state: BeaconState, signed_block: SomeSignedBeaconBlock): bool {.nbench.} =
|
state: BeaconState, signed_block: SomeSignedBeaconBlock): bool {.nbench.} =
|
||||||
|
@ -134,14 +108,11 @@ proc advance_slot(
|
||||||
let is_epoch_transition = (state.data.slot + 1).isEpoch
|
let is_epoch_transition = (state.data.slot + 1).isEpoch
|
||||||
if is_epoch_transition:
|
if is_epoch_transition:
|
||||||
# Note: Genesis epoch = 0, no need to test if before Genesis
|
# Note: Genesis epoch = 0, no need to test if before Genesis
|
||||||
beacon_previous_validators.set(get_epoch_validator_count(state.data))
|
|
||||||
process_epoch(state.data, updateFlags, epochCache)
|
process_epoch(state.data, updateFlags, epochCache)
|
||||||
clear_epoch_from_cache(
|
clear_epoch_from_cache(
|
||||||
epochCache, (state.data.slot + 1).compute_epoch_at_slot)
|
epochCache, (state.data.slot + 1).compute_epoch_at_slot)
|
||||||
|
|
||||||
state.data.slot += 1
|
state.data.slot += 1
|
||||||
if is_epoch_transition:
|
|
||||||
beacon_current_validators.set(get_epoch_validator_count(state.data))
|
|
||||||
|
|
||||||
# The root must be updated on every slot update, or the next `process_slot`
|
# The root must be updated on every slot update, or the next `process_slot`
|
||||||
# will be incorrect
|
# will be incorrect
|
||||||
|
|
|
@ -20,7 +20,8 @@
|
||||||
{.push raises: [Defect].}
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import
|
import
|
||||||
algorithm, collections/sets, chronicles, options, sequtils, sets,
|
std/[algorithm, collections/sets, options, sequtils, sets],
|
||||||
|
chronicles,
|
||||||
../extras, ../ssz/merkleization, metrics,
|
../extras, ../ssz/merkleization, metrics,
|
||||||
./beaconstate, ./crypto, ./datatypes, ./digest, ./helpers, ./validator,
|
./beaconstate, ./crypto, ./datatypes, ./digest, ./helpers, ./validator,
|
||||||
./signatures, ./presets,
|
./signatures, ./presets,
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[math, sequtils, tables, algorithm],
|
std/[math, sequtils, tables, algorithm],
|
||||||
stew/[bitops2], chronicles, metrics,
|
stew/[bitops2], chronicles,
|
||||||
../extras,
|
../extras,
|
||||||
../ssz/merkleization,
|
../ssz/merkleization,
|
||||||
./beaconstate, ./crypto, ./datatypes, ./digest, ./helpers, ./validator,
|
./beaconstate, ./crypto, ./datatypes, ./digest, ./helpers, ./validator,
|
||||||
|
@ -32,22 +32,6 @@ import
|
||||||
|
|
||||||
logScope: topics = "consens"
|
logScope: topics = "consens"
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md#interop-metrics
|
|
||||||
declareGauge beacon_finalized_epoch, "Current finalized epoch" # On epoch transition
|
|
||||||
declareGauge beacon_finalized_root, "Current finalized root" # On epoch transition
|
|
||||||
declareGauge beacon_current_justified_epoch, "Current justified epoch" # On epoch transition
|
|
||||||
declareGauge beacon_current_justified_root, "Current justified root" # On epoch transition
|
|
||||||
declareGauge beacon_previous_justified_epoch, "Current previously justified epoch" # On epoch transition
|
|
||||||
declareGauge beacon_previous_justified_root, "Current previously justified root" # On epoch transition
|
|
||||||
|
|
||||||
# Non-spec
|
|
||||||
declareGauge epoch_transition_justification_and_finalization, "Epoch transition justification and finalization time"
|
|
||||||
declareGauge epoch_transition_times_rewards_and_penalties, "Epoch transition reward and penalty time"
|
|
||||||
declareGauge epoch_transition_registry_updates, "Epoch transition registry updates time"
|
|
||||||
declareGauge epoch_transition_slashings, "Epoch transition slashings time"
|
|
||||||
declareGauge epoch_transition_final_updates, "Epoch transition final updates time"
|
|
||||||
declareGauge beacon_current_epoch, "Current epoch"
|
|
||||||
|
|
||||||
type
|
type
|
||||||
# Caches for computing justificiation, rewards and penalties - based on
|
# Caches for computing justificiation, rewards and penalties - based on
|
||||||
# implementation in Lighthouse:
|
# implementation in Lighthouse:
|
||||||
|
@ -633,16 +617,3 @@ proc process_epoch*(state: var BeaconState, updateFlags: UpdateFlags,
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#final-updates
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#final-updates
|
||||||
process_final_updates(state)
|
process_final_updates(state)
|
||||||
|
|
||||||
# Once per epoch metrics
|
|
||||||
beacon_current_epoch.set(currentEpoch.int64)
|
|
||||||
beacon_finalized_epoch.set(state.finalized_checkpoint.epoch.int64)
|
|
||||||
beacon_finalized_root.set(state.finalized_checkpoint.root.toGaugeValue)
|
|
||||||
beacon_current_justified_epoch.set(
|
|
||||||
state.current_justified_checkpoint.epoch.int64)
|
|
||||||
beacon_current_justified_root.set(
|
|
||||||
state.current_justified_checkpoint.root.toGaugeValue)
|
|
||||||
beacon_previous_justified_epoch.set(
|
|
||||||
state.previous_justified_checkpoint.epoch.int64)
|
|
||||||
beacon_previous_justified_root.set(
|
|
||||||
state.previous_justified_checkpoint.root.toGaugeValue)
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
{.push raises: [Defect].}
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import
|
import
|
||||||
options, math, tables,
|
std/[options, math, tables],
|
||||||
./datatypes, ./digest, ./helpers
|
./datatypes, ./digest, ./helpers
|
||||||
|
|
||||||
const
|
const
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
import
|
# beacon_chain
|
||||||
datatypes, digest, helpers
|
# Copyright (c) 2018-2020 Status Research & Development GmbH
|
||||||
|
# Licensed and distributed under either of
|
||||||
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
||||||
|
# * 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.
|
||||||
|
|
||||||
{.push raises: [Defect].}
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
|
import
|
||||||
|
./datatypes, ./digest, ./helpers
|
||||||
|
|
||||||
const
|
const
|
||||||
SAFETY_DECAY* = 10'u64
|
SAFETY_DECAY* = 10'u64
|
||||||
|
|
||||||
|
@ -28,6 +35,6 @@ func is_within_weak_subjectivity_period*(current_slot: Slot,
|
||||||
ws_period = compute_weak_subjectivity_period(ws_state)
|
ws_period = compute_weak_subjectivity_period(ws_state)
|
||||||
ws_state_epoch = compute_epoch_at_slot(ws_state.slot)
|
ws_state_epoch = compute_epoch_at_slot(ws_state.slot)
|
||||||
current_epoch = compute_epoch_at_slot(current_slot)
|
current_epoch = compute_epoch_at_slot(current_slot)
|
||||||
|
|
||||||
current_epoch <= ws_state_epoch + ws_period
|
current_epoch <= ws_state_epoch + ws_period
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
|
# beacon_chain
|
||||||
|
# Copyright (c) 2018-2020 Status Research & Development GmbH
|
||||||
|
# Licensed and distributed under either of
|
||||||
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
||||||
|
# * 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.
|
||||||
|
|
||||||
{.push raises: [Defect].}
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
{.pragma: raisesssz, raises: [Defect, MalformedSszError, SszSizeMismatchError].}
|
{.pragma: raisesssz, raises: [Defect, MalformedSszError, SszSizeMismatchError].}
|
||||||
|
|
||||||
import
|
import
|
||||||
typetraits, options,
|
std/[typetraits, options],
|
||||||
stew/[bitops2, endians2, objects],
|
stew/[bitops2, endians2, objects],
|
||||||
../spec/[digest, datatypes], ./types, ./spec_types, ./merkleization
|
../spec/[digest, datatypes], ./types, ./spec_types, ./merkleization
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
|
# beacon_chain
|
||||||
|
# Copyright (c) 2018-2020 Status Research & Development GmbH
|
||||||
|
# Licensed and distributed under either of
|
||||||
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
||||||
|
# * 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.
|
||||||
|
|
||||||
{.push raises: [Defect].}
|
{.push raises: [Defect].}
|
||||||
{.pragma: raisesssz, raises: [Defect, IOError, MalformedSszError, SszSizeMismatchError].}
|
{.pragma: raisesssz, raises: [Defect, IOError, MalformedSszError, SszSizeMismatchError].}
|
||||||
|
|
||||||
import
|
import
|
||||||
strutils, parseutils,
|
std/[strutils, parseutils],
|
||||||
stew/objects, faststreams/outputs, json_serialization/writer,
|
stew/objects, faststreams/outputs, json_serialization/writer,
|
||||||
../spec/datatypes,
|
../spec/datatypes,
|
||||||
./bytes_reader, ./types, ./navigator, ./spec_types
|
./bytes_reader, ./types, ./navigator, ./spec_types
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
# beacon_chain
|
||||||
|
# Copyright (c) 2018-2020 Status Research & Development GmbH
|
||||||
|
# Licensed and distributed under either of
|
||||||
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
||||||
|
# * 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.
|
||||||
|
|
||||||
{.push raises: [Defect].}
|
{.push raises: [Defect].}
|
||||||
{.pragma: raisesssz, raises: [Defect, MalformedSszError, SszSizeMismatchError].}
|
{.pragma: raisesssz, raises: [Defect, MalformedSszError, SszSizeMismatchError].}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
|
# beacon_chain
|
||||||
|
# Copyright (c) 2018-2020 Status Research & Development GmbH
|
||||||
|
# Licensed and distributed under either of
|
||||||
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
||||||
|
# * 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.
|
||||||
|
|
||||||
import
|
import
|
||||||
typetraits,
|
std/[typetraits],
|
||||||
../spec/[crypto, digest]
|
../spec/[crypto, digest]
|
||||||
|
|
||||||
# Eth2-spec-specific type handling that is not generic to SSZ
|
# Eth2-spec-specific type handling that is not generic to SSZ
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
# beacon_chain
|
||||||
|
# Copyright (c) 2018-2020 Status Research & Development GmbH
|
||||||
|
# Licensed and distributed under either of
|
||||||
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
||||||
|
# * 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.
|
||||||
|
|
||||||
# TODO Cannot override push, even though the function is annotated
|
# TODO Cannot override push, even though the function is annotated
|
||||||
# nimbus-eth2/beacon_chain/ssz.nim(212, 18) Error: can raise an unlisted exception: IOError
|
# nimbus-eth2/beacon_chain/ssz.nim(212, 18) Error: can raise an unlisted exception: IOError
|
||||||
# {.push raises: [Defect].}
|
# {.push raises: [Defect].}
|
||||||
|
@ -7,7 +14,7 @@
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/ssz/simple-serialize.md#serialization
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/ssz/simple-serialize.md#serialization
|
||||||
|
|
||||||
import
|
import
|
||||||
typetraits, options,
|
std/[typetraits, options],
|
||||||
stew/[bitops2, endians2, objects],
|
stew/[bitops2, endians2, objects],
|
||||||
serialization, serialization/testing/tracing,
|
serialization, serialization/testing/tracing,
|
||||||
../spec/[digest, datatypes],
|
../spec/[digest, datatypes],
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
|
# beacon_chain
|
||||||
|
# Copyright (c) 2018-2020 Status Research & Development GmbH
|
||||||
|
# Licensed and distributed under either of
|
||||||
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
||||||
|
# * 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.
|
||||||
|
|
||||||
{.push raises: [Defect].}
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import
|
import
|
||||||
tables, options, typetraits, strformat,
|
std/[tables, options, typetraits, strformat],
|
||||||
stew/shims/macros, stew/[byteutils, bitops2, objects],
|
stew/shims/macros, stew/[byteutils, bitops2, objects],
|
||||||
serialization/[object_serialization, errors],
|
serialization/[object_serialization, errors],
|
||||||
./spec_types, ./bitseqs,
|
./spec_types, ./bitseqs,
|
||||||
|
@ -14,7 +21,7 @@ const
|
||||||
bytesPerChunk* = 32
|
bytesPerChunk* = 32
|
||||||
|
|
||||||
type
|
type
|
||||||
UintN* = SomeUnsignedInt # TODO: Add StUint here
|
UintN* = SomeUnsignedInt
|
||||||
BasicType* = bool|UintN
|
BasicType* = bool|UintN
|
||||||
|
|
||||||
Limit* = int64
|
Limit* = int64
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import
|
import
|
||||||
tables, json, streams,
|
std/[tables, json, streams],
|
||||||
chronos, chronicles,
|
chronos, chronicles, metrics,
|
||||||
spec/[datatypes, crypto, digest, signatures, helpers],
|
|
||||||
beacon_node_types,
|
|
||||||
json_serialization/std/[sets, net],
|
json_serialization/std/[sets, net],
|
||||||
validator_slashing_protection,
|
eth/db/[kvstore, kvstore_sqlite3],
|
||||||
eth/db/[kvstore, kvstore_sqlite3]
|
./spec/[datatypes, crypto, digest, signatures, helpers],
|
||||||
|
./beacon_node_types, validator_slashing_protection
|
||||||
|
|
||||||
|
declareGauge validators,
|
||||||
|
"Number of validators attached to the beacon node"
|
||||||
|
|
||||||
func init*(T: type ValidatorPool,
|
func init*(T: type ValidatorPool,
|
||||||
slashingProtectionDB: SlashingProtectionDB): T =
|
slashingProtectionDB: SlashingProtectionDB): T =
|
||||||
|
@ -28,12 +30,16 @@ proc addLocalValidator*(pool: var ValidatorPool,
|
||||||
pool.validators[pubKey] = v
|
pool.validators[pubKey] = v
|
||||||
notice "Local validator attached", pubKey, validator = shortLog(v)
|
notice "Local validator attached", pubKey, validator = shortLog(v)
|
||||||
|
|
||||||
|
validators.set(pool.count().int64)
|
||||||
|
|
||||||
proc addRemoteValidator*(pool: var ValidatorPool,
|
proc addRemoteValidator*(pool: var ValidatorPool,
|
||||||
pubKey: ValidatorPubKey,
|
pubKey: ValidatorPubKey,
|
||||||
v: AttachedValidator) =
|
v: AttachedValidator) =
|
||||||
pool.validators[pubKey] = v
|
pool.validators[pubKey] = v
|
||||||
notice "Remote validator attached", pubKey, validator = shortLog(v)
|
notice "Remote validator attached", pubKey, validator = shortLog(v)
|
||||||
|
|
||||||
|
validators.set(pool.count().int64)
|
||||||
|
|
||||||
proc getValidator*(pool: ValidatorPool,
|
proc getValidator*(pool: ValidatorPool,
|
||||||
validatorKey: ValidatorPubKey): AttachedValidator =
|
validatorKey: ValidatorPubKey): AttachedValidator =
|
||||||
pool.validators.getOrDefault(validatorKey.initPubKey)
|
pool.validators.getOrDefault(validatorKey.initPubKey)
|
||||||
|
|
|
@ -316,16 +316,10 @@
|
||||||
"steppedLine": false,
|
"steppedLine": false,
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "beacon_current_validators{node=\"${node}\"}",
|
"expr": "beacon_active_validators{node=\"${node}\"}",
|
||||||
"interval": "",
|
"interval": "",
|
||||||
"legendFormat": "current validators",
|
"legendFormat": "current validators",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
},
|
|
||||||
{
|
|
||||||
"expr": "beacon_current_live_validators{node=\"${node}\"}",
|
|
||||||
"interval": "",
|
|
||||||
"legendFormat": "current live validators",
|
|
||||||
"refId": "B"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"thresholds": [],
|
"thresholds": [],
|
||||||
|
|
Loading…
Reference in New Issue