nimbus-eth2/beacon_chain/gossip_processing/optimistic_processor.nim
Etan Kissling 9fc870777c
remove Bellatrix EL syncing support from light client (#6352)
Bellatrix light client data does not contain the EL block hash, so we
had to follow blocks gossip to learn the EL `block_hash` of such blocks.
Now that Bellatrix is obsolete, we can simplify EL syncing logic under
light client scenarios. Bellatrix light client data can still be used
to advance the light client sync itself, but will no longer result in
`engine_forkchoiceUpdated` calls until the sync reaches Capella. This
also frees up some memory as we no longer have to retain blocks.
2024-06-14 01:23:17 +00:00

102 lines
3.5 KiB
Nim

# beacon_chain
# Copyright (c) 2019-2024 Status Research & Development GmbH
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://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
chronicles, chronos,
../spec/forks,
../beacon_clock,
./gossip_validation
from ./eth2_processor import ValidationRes
export gossip_validation
logScope:
topics = "gossip_opt"
type
OptimisticBlockVerifier* = proc(
signedBlock: ForkedSignedBeaconBlock
): Future[void] {.async: (raises: [CancelledError]).}
OptimisticProcessor* = ref object
getBeaconTime: GetBeaconTimeFn
optimisticVerifier: OptimisticBlockVerifier
processFut: Future[void].Raising([CancelledError])
proc initOptimisticProcessor*(
getBeaconTime: GetBeaconTimeFn,
optimisticVerifier: OptimisticBlockVerifier): OptimisticProcessor =
OptimisticProcessor(
getBeaconTime: getBeaconTime,
optimisticVerifier: optimisticVerifier)
proc validateBeaconBlock(
self: OptimisticProcessor,
signed_beacon_block: ForkySignedBeaconBlock,
wallTime: BeaconTime): Result[void, ValidationError] =
## Minimally validate a block for potential relevance.
if not (signed_beacon_block.message.slot <=
(wallTime + MAXIMUM_GOSSIP_CLOCK_DISPARITY).slotOrZero):
return errIgnore("BeaconBlock: slot too high")
if not signed_beacon_block.message.is_execution_block():
return errIgnore("BeaconBlock: no execution block")
ok()
proc processSignedBeaconBlock*(
self: OptimisticProcessor,
signedBlock: ForkySignedBeaconBlock): ValidationRes =
let
wallTime = self.getBeaconTime()
(afterGenesis, wallSlot) = wallTime.toSlot()
logScope:
blockRoot = shortLog(signedBlock.root)
blck = shortLog(signedBlock.message)
signature = shortLog(signedBlock.signature)
wallSlot
if not afterGenesis:
notice "Optimistic block before genesis"
return errIgnore("Block before genesis")
# Potential under/overflows are fine; would just create odd metrics and logs
let delay = wallTime - signedBlock.message.slot.start_beacon_time
# Start of block processing - in reality, we have already gone through SSZ
# decoding at this stage, which may be significant
debug "Optimistic block received", delay
let v = self.validateBeaconBlock(signedBlock, wallTime)
if v.isErr:
debug "Dropping optimistic block", error = v.error
return err(v.error)
# Only process one block at a time (backpressure)
trace "Optimistic block validated"
if self.processFut == nil:
self.processFut = self.optimisticVerifier(
ForkedSignedBeaconBlock.init(signedBlock))
proc handleFinishedProcess(future: pointer) =
self.processFut = nil
self.processFut.addCallback(handleFinishedProcess)
# Block validation is delegated to the sync committee and is done with delay.
# If we forward invalid spam blocks, we may be disconnected + IP banned,
# so we avoid accepting any blocks. Since we don't meaningfully contribute
# to the blocks gossip, we may also accummulate negative peer score over time.
# However, we are actively contributing to other topics, so some of the
# negative peer score may be offset through those different topics.
# The practical impact depends on the actually deployed scoring heuristics.
return errIgnore("Validation delegated to sync committee")