compute correct withdrawals for lookahead proposal fcUs at epoch boundaries (#4820)

This commit is contained in:
tersec 2023-04-15 21:48:24 +00:00 committed by GitHub
parent ae45e11f8e
commit f6062a2be1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 23 additions and 11 deletions

View File

@ -310,27 +310,39 @@ proc runProposalForkchoiceUpdated*(
debug "runProposalForkchoiceUpdated: expected to be proposing next slot", debug "runProposalForkchoiceUpdated: expected to be proposing next slot",
nextWallSlot, validatorIndex, nextProposer nextWallSlot, validatorIndex, nextProposer
withState(self.dag.headState):
let
nextSlotFork = self.dag.cfg.forkAtEpoch(nextWallSlot.epoch)
nextSlotForkVersion = self.dag.cfg.forkVersionAtEpoch(nextWallSlot.epoch)
if nextSlotForkVersion == self.dag.cfg.CAPELLA_FORK_VERSION and
forkyState.data.fork.current_version != nextSlotFork.current_version:
debug "runProposalForkchoiceUpdated: about to do Capella transition; don't have appropriate state to fcU ahead",
nextWallSlot, validatorIndex, nextProposer, nextSlotFork,
nextSlotForkVersion, stateFork = forkyState.data.fork
# Approximately lines up with validator_duties version. Used optimistically/ # Approximately lines up with validator_duties version. Used optimistically/
# opportunistically, so mismatches are fine if not too frequent. # opportunistically, so mismatches are fine if not too frequent.
let let
timestamp = withState(self.dag.headState): timestamp = withState(self.dag.headState):
compute_timestamp_at_slot(forkyState.data, nextWallSlot) compute_timestamp_at_slot(forkyState.data, nextWallSlot)
# If the current head block still forms the basis of the eventual proposal
# state, then its `get_randao_mix` will remain unchanged as well, as it is
# constant until the next block.
randomData = withState(self.dag.headState): randomData = withState(self.dag.headState):
get_randao_mix(forkyState.data, get_current_epoch(forkyState.data)).data get_randao_mix(forkyState.data, get_current_epoch(forkyState.data)).data
feeRecipient = self[].getFeeRecipient( feeRecipient = self[].getFeeRecipient(
nextProposer, Opt.some(validatorIndex), nextWallSlot.epoch) nextProposer, Opt.some(validatorIndex), nextWallSlot.epoch)
withdrawals = withState(self.dag.headState): withdrawals = withState(self.dag.headState):
when consensusFork >= ConsensusFork.Capella: when consensusFork >= ConsensusFork.Capella:
# Within an epoch, so long as there's no block, the withdrawals also
# remain unchanged. Balances change at epoch boundaries, however, so
# if and only if the proposal slot is the first slot of an epoch the
# beacon node must transition epochs to compute correct balances.
if nextWallSlot.is_epoch:
var cache: StateCache
let proposalState = self.dag.getProposalState(
self.dag.head, nextWallSlot, cache).valueOr:
warn "Failed to create proposal state for withdrawals",
err = error, nextWallSlot, validatorIndex, nextProposer
return
withState(proposalState[]):
when consensusFork >= ConsensusFork.Capella:
Opt.some get_expected_withdrawals(forkyState.data)
else:
Opt.none(seq[Withdrawal])
else:
# Head state is not eventual proposal state, but withdrawals will be
# identical.
Opt.some get_expected_withdrawals(forkyState.data) Opt.some get_expected_withdrawals(forkyState.data)
else: else:
Opt.none(seq[Withdrawal]) Opt.none(seq[Withdrawal])