Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

don't send fcUs every block if in lc-opt regime and block putatively finalized #5248

Merged
merged 1 commit into from
Aug 15, 2023

Conversation

tersec
Copy link
Contributor

@tersec tersec commented Aug 4, 2023

That is, render it consistent with the non-lc-opt regime, which already has this check for fcU.

Also remove a small optimization for now-irrelevant pre-Bellatrix which makes code a little less clear and more redundant (two different places it returns ZERO_HASH for the same reason).

@github-actions
Copy link

github-actions bot commented Aug 4, 2023

Unit Test Results

         9 files  ±0    1 077 suites  ±0   40m 14s ⏱️ + 1m 17s
  3 723 tests ±0    3 444 ✔️ ±0  279 💤 ±0  0 ±0 
15 874 runs  ±0  15 569 ✔️ ±0  305 💤 ±0  0 ±0 

Results for commit e540916. ± Comparison against base commit 1c55ef7.

♻️ This comment has been updated with latest results.

finalizedBlockHash = newHead.get.finalizedExecutionPayloadHash,
payloadAttributes = none attributes)
if NewPayloadStatus.noResponse != payloadStatus and
not self.consensusManager[].optimisticExecutionPayloadHash.isZero:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks weird - we use the finalized EPH from the block but the light client EPH for head? I thought the light client gives a finalized head too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticed this as well.

My read is that the LC isn't trusted for FC purposes here for finalization, which in theory might trigger the EL to act in irrevocable, or irrevocable without disproportionate computation/storage cost, ways.

Nimbus still effectively treats the LC as extra-consensus, purely on top of it, an aid to reaching consensus, rather than consensus itself, and it's okay for FC head to bounce around in case that goes wrong in a ways it's not for finalized/safe to.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, critically though it might happen that the FC consensus is behind (for example if LC connectivity is broken due to lack of peers)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly, the LC is used to optimistically sync the EL. It is not used to provide safety. Once DAG catches up, its head is used instead of the LC head. Safe/Finalized is always reported based on the fork choice store (highest finality observed on any branch by DAG).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, this feels kind of sketchy - seems like we should be looking at the max of the two syncs potentially ensuring that they share ancestry or something like that... otherwise, this code looks to me like finality from the block can end up being from a slot more recent than the block from LC?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this is guarded by if self.consensusManager[].shouldSyncOptimistically(wallSlot):

func shouldSyncOptimistically*(
    optimisticSlot, dagSlot, wallSlot: Slot): bool =
  ## Determine whether an optimistic execution block hash should be reported
  ## to the EL client instead of the current head as determined by fork choice.

  # Check whether optimistic head is sufficiently ahead of DAG
  const minProgress = 8 * SLOTS_PER_EPOCH  # Set arbitrarily
  if optimisticSlot < dagSlot or optimisticSlot - dagSlot < minProgress:
    return false

  # Check whether optimistic head has synced sufficiently close to wall slot
  const maxAge = 2 * SLOTS_PER_EPOCH  # Set arbitrarily
  if optimisticSlot < max(wallSlot, maxAge.Slot) - maxAge:
    return false

  true

func shouldSyncOptimistically*(self: ConsensusManager, wallSlot: Slot): bool =
  if self.optimisticHead.execution_block_hash.isZero:
    return false

  shouldSyncOptimistically(
    optimisticSlot = self.optimisticHead.bid.slot,
    dagSlot = getStateField(self.dag.headState, slot),
    wallSlot = wallSlot)

so, LC head is only used if DAG head is far behind and LC head is recent.

@tersec tersec merged commit af37a96 into unstable Aug 15, 2023
12 checks passed
@tersec tersec deleted the HWu branch August 15, 2023 09:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants