Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions beacon_chain/consensus_object_pools/block_clearance.nim
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,60 @@ proc addHeadExecutionPayload*(

ok(blck)

proc addBackfillExecutionPayload*(
dag: ChainDAGRef,
signedEnvelope: gloas.SignedExecutionPayloadEnvelope,
# gloas.TrustedSignedExecutionPayloadEnvelope,
): Result[void, VerifierError] =
template blockRoot(): auto = signedEnvelope.message.beacon_block_root
template envelope(): auto = signedEnvelope.message

logScope:
blockRoot = shortLog(blockRoot)
slot = envelope.slot
signature = shortLog(signedEnvelope.signature)
backfill = shortLog(dag.backfill)

let startTick = Moment.now()

# When a valid block is backfilled, dag.backfill has already moved to next
# parent. So we need to check with finalizedHead and database.
if envelope.slot > dag.finalizedHead.slot:
return err(VerifierError.Invalid)
let bsi = dag.getBlockIdAtSlot(envelope.slot).valueOr:
# This should not be happening as we backfill envelope after the block is
# backfilled successfully.
return err(VerifierError.Invalid)
if blockRoot != bsi.bid.root:
return err(VerifierError.Invalid)
if dag.db.containsExecutionPayloadEnvelope(blockRoot):
return err(VerifierError.Duplicate)

# Verify signature
when signedEnvelope.signature isnot TrustedSig:
let builderKey = dag.validatorKey(envelope.builder_index).valueOr:
fatal "Invalid builder in backfill envelope - checkpoint state corrupt?",
head = shortLog(dag.head), tail = shortLog(dag.tail)
quit 1
if not verify_execution_payload_envelope_signature(
dag.forkAtEpoch(envelope.slot.epoch),
dag.genesis_validators_root,
envelope.slot.epoch,
envelope,
builderKey,
signedEnvelope.signature):
return err(VerifierError.Invalid)
let sigVerifyTick = Moment.now

dag.db.putExecutionPayloadEnvelope(signedEnvelope)
let putBlockTick = Moment.now

debug "Envelope backfilled",
sigVerifyDur = sigVerifyTick - startTick,
putBlockDur = putBlockTick - sigVerifyTick

ok()

proc verifyBlockSignatures*(
verifier: var BatchVerifier,
fork: Fork,
Expand Down
4 changes: 4 additions & 0 deletions beacon_chain/consensus_object_pools/envelope_quarantine.nim
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ func popOrphan*(
func delOrphan*(self: var EnvelopeQuarantine, blck: gloas.SignedBeaconBlock) =
self.orphans.del(blck.root)

func remove*(self: var EnvelopeQuarantine, root: Eth2Digest) =
self.orphans.del(root)
self.missing.excl(root)

func cleanupOrphans*(self: var EnvelopeQuarantine, finalizedSlot: Slot) =
var toDel: seq[Eth2Digest]

Expand Down
59 changes: 49 additions & 10 deletions beacon_chain/gossip_processing/block_processor.nim
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ from ../consensus_object_pools/block_quarantine import
from ../consensus_object_pools/blob_quarantine import
BlobQuarantine, ColumnQuarantine, GloasColumnQuarantine, popSidecars, put
from ../consensus_object_pools/envelope_quarantine import
EnvelopeQuarantine, addMissing, addOrphan, delOrphan, popOrphan
EnvelopeQuarantine, addMissing, addOrphan, delOrphan, popOrphan, remove
from ../validators/validator_monitor import
MsgSource, ValidatorMonitor, registerAttestationInBlock, registerBeaconBlock,
registerSyncAggregateInBlock
Expand Down Expand Up @@ -186,10 +186,12 @@ proc dumpBlock(
discard

from ../consensus_object_pools/block_clearance import
addBackfillBlock, addHeadBlockWithParent, checkHeadBlock, verifyBlockProposer
addBackfillBlock, addBackfillExecutionPayload,
addHeadBlockWithParent, checkHeadBlock, verifyBlockProposer

proc verifySidecars(
signedBlock: ForkySignedBeaconBlock,
envelope: NoEnvelope | gloas.SignedExecutionPayloadEnvelope,
sidecarsOpt: SomeOptSidecars,
): Result[void, VerifierError] =
const consensusFork = typeof(signedBlock).kind
Expand Down Expand Up @@ -262,7 +264,10 @@ proc storeBackfillBlock(
# In case the block was added to any part of the quarantine..
quarantine[].remove(signedBlock)

?verifySidecars(signedBlock, sidecarsOpt)
const consensusFork = typeof(signedBlock).kind

when consensusFork <= ConsensusFork.Fulu:
?verifySidecars(signedBlock, noEnvelope, sidecarsOpt)

let res = self.consensusManager.dag.addBackfillBlock(signedBlock)

Expand Down Expand Up @@ -490,7 +495,9 @@ proc onBlockAdded*(
)

proc verifyPayload(
self: ref BlockProcessor, signedBlock: ForkySignedBeaconBlock
self: ref BlockProcessor,
signedBlock: ForkySignedBeaconBlock,
signedEnvelope: NoEnvelope | gloas.SignedExecutionPayloadEnvelope,
): Result[OptimisticStatus, VerifierError] =
const consensusFork = typeof(signedBlock).kind
# When the execution layer is not available to verify the payload, we do the
Expand Down Expand Up @@ -647,14 +654,22 @@ proc storeBlock(
else:
Opt.some(OptimisticStatus.valid) # vacuously

let optimisticStatus = ?(optimisticStatusRes or verifyPayload(self, signedBlock))
let optimisticStatus =
when consensusFork >= ConsensusFork.Gloas:
# The execution payload validity is not known yet at block time as an
# envelope will be processed after its valid block. So always return
# `notValidated` and skip verifying payload.
OptimisticStatus.notValidated
else:
?(optimisticStatusRes or verifyPayload(self, signedBlock, noEnvelope))

if OptimisticStatus.invalidated == optimisticStatus:
return err(VerifierError.Invalid)

let newPayloadTick = Moment.now()

?verifySidecars(signedBlock, sidecarsOpt)
when consensusFork <= ConsensusFork.Fulu:
?verifySidecars(signedBlock, noEnvelope, sidecarsOpt)

let blck =
?dag.addHeadBlockWithParent(
Expand Down Expand Up @@ -873,6 +888,22 @@ proc addBlock*(
of VerifierError.Duplicate:
err(res.error())

proc storeBackfillPayload(
self: var BlockProcessor,
signedBlock: gloas.SignedBeaconBlock,
signedEnvelope: gloas.SignedExecutionPayloadEnvelope,
sidecarsOpt: Opt[gloas.DataColumnSidecars],
): Result[void, VerifierError] =
self.envelopeQuarantine[].remove(signedEnvelope.message.beacon_block_root)

?verifySidecars(signedBlock, signedEnvelope, sidecarsOpt)

self.consensusManager.dag.addBackfillExecutionPayload(signedEnvelope).isOkOr:
return err(error)

self.storeSidecars(sidecarsOpt)
ok()

proc storePayload(
self: ref BlockProcessor,
signedBlock: gloas.SignedBeaconBlock,
Expand Down Expand Up @@ -903,16 +934,24 @@ proc storePayload(

ok()

proc enqueuePayload*(
proc addPayload*(
self: ref BlockProcessor,
blck: gloas.SignedBeaconBlock,
envelope: gloas.SignedExecutionPayloadEnvelope,
sidecarsOpt: Opt[gloas.DataColumnSidecars],
) =
): Future[Result[void, VerifierError]] {.async: (raises: [CancelledError]).} =
if blck.message.slot <= self.consensusManager.dag.finalizedHead.slot:
debugGloasComment("backfilling")
return self[].storeBackfillPayload(blck, envelope, sidecarsOpt)

await self.storePayload(blck, envelope, sidecarsOpt)

discard self.storePayload(blck, envelope, sidecarsOpt)
proc enqueuePayload*(
self: ref BlockProcessor,
blck: gloas.SignedBeaconBlock,
envelope: gloas.SignedExecutionPayloadEnvelope,
sidecarsOpt: Opt[gloas.DataColumnSidecars],
) =
discard self.addPayload(blck, envelope, sidecarsOpt)

proc enqueuePayload*(self: ref BlockProcessor, blck: gloas.SignedBeaconBlock) =
## Enqueue payload processing by block that is a valid block.
Expand Down
2 changes: 1 addition & 1 deletion beacon_chain/spec/datatypes/gloas.nim
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ type

TrustedSignedExecutionPayloadEnvelope* = object
message*: TrustedExecutionPayloadEnvelope
signature*: ValidatorSig
signature*: TrustedSig

# https://github.com/ethereum/consensus-specs/blob/v1.6.0-alpha.6/specs/gloas/beacon-chain.md#payloadattestationdata
PayloadAttestationData* = object
Expand Down
7 changes: 4 additions & 3 deletions beacon_chain/spec/signatures.nim
Original file line number Diff line number Diff line change
Expand Up @@ -476,9 +476,10 @@ proc verify_execution_payload_envelope_signature*(
fork: Fork, genesis_validators_root: Eth2Digest, epoch: Epoch,
msg: ExecutionPayloadEnvelope | TrustedExecutionPayloadEnvelope,
pubkey: ValidatorPubKey | CookedPubKey, signature: SomeSig): bool =
let signing_root = compute_execution_payload_envelope_signing_root(
fork, genesis_validators_root, epoch, msg)
blsVerify(pubkey, signing_root.data, signature)
withTrust(signature):
let signing_root = compute_execution_payload_envelope_signing_root(
fork, genesis_validators_root, epoch, msg)
blsVerify(pubkey, signing_root.data, signature)

# https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/gloas/validator.md#constructing-a-payload-attestation
func compute_payload_attestation_message_signing_root*(
Expand Down