nimbus-eth2/beacon_chain/validators/validator_duties.nim

75 lines
3.2 KiB
Nim

# beacon_chain
# Copyright (c) 2018-2024 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: [].}
import
chronos,
results,
../consensus_object_pools/block_dag,
../beacon_clock,
"."/[validator_pool]
export chronos, results, block_dag, beacon_clock
## The validator_duties module contains logic and utilities related to performing
## validator duties that are shared between beacon node and validator client.
type
RegisteredAttestation* = object
# A registered attestation is one that has been successfully registered in
# the slashing protection database and is therefore ready to be signed and
# sent
validator*: AttachedValidator
index_in_committee*: uint64
committee_len*: int
data*: AttestationData
proc toAttestation*(
registered: RegisteredAttestation, signature: ValidatorSig):
phase0.Attestation =
phase0.Attestation.init(
[registered.index_in_committee], registered.committee_len,
registered.data, signature).expect("valid data")
proc waitAfterBlockCutoff*(clock: BeaconClock, slot: Slot,
head: Opt[BlockRef] = Opt.none(BlockRef))
{.async: (raises: [CancelledError]).} =
# The expected block arrived (or expectBlock was called again which
# shouldn't happen as this is the only place we use it) - in our async
# loop however, we might have been doing other processing that caused delays
# here so we'll cap the waiting to the time when we would have sent out
# attestations had the block not arrived.
# An opposite case is that we received (or produced) a block that has
# not yet reached our neighbours. To protect against our attestations
# being dropped (because the others have not yet seen the block), we'll
# impose a minimum delay of 2000ms. The delay is enforced only when we're
# not hitting the "normal" cutoff time for sending out attestations.
# An earlier delay of 250ms has proven to be not enough, increasing the
# risk of losing attestations, and with growing block sizes, 1000ms
# started to be risky as well.
# Regardless, because we "just" received the block, we'll impose the
# delay.
# Take into consideration chains with a different slot time
const afterBlockDelay = nanos(attestationSlotOffset.nanoseconds div 2)
let
afterBlockTime = clock.now() + afterBlockDelay
afterBlockCutoff = clock.fromNow(
min(afterBlockTime, slot.attestation_deadline() + afterBlockDelay))
if afterBlockCutoff.inFuture:
if head.isSome():
debug "Got block, waiting to send attestations",
head = shortLog(head.get()), slot = slot,
afterBlockCutoff = shortLog(afterBlockCutoff.offset)
else:
debug "Got block, waiting to send attestations",
slot = slot, afterBlockCutoff = shortLog(afterBlockCutoff.offset)
await sleepAsync(afterBlockCutoff.offset)