avoid repeated total active balance computation in fork choice (#5437)
We currently compute `justified_total_active_balance` inside `calculateProposerBoost`, despite that sum already being known in the `EpochRef` cache. Tracking `justified_total_active_balance` whenever the justified checkpoint updates allows replacing the repeated computation with a lookup, at minimal memory cost.
This commit is contained in:
parent
ee75d45a8b
commit
c1b43d166b
|
@ -73,6 +73,7 @@ proc init*(
|
|||
version: version,
|
||||
justified: BalanceCheckpoint(
|
||||
checkpoint: checkpoint,
|
||||
total_active_balance: epochRef.total_active_balance,
|
||||
balances: epochRef.effective_balances),
|
||||
finalized: checkpoint,
|
||||
best_justified: checkpoint))
|
||||
|
@ -98,6 +99,7 @@ proc update_justified(
|
|||
store = self.justified.checkpoint, state = justified
|
||||
self.justified = BalanceCheckpoint(
|
||||
checkpoint: Checkpoint(root: blck.root, epoch: epochRef.epoch),
|
||||
total_active_balance: epochRef.total_active_balance,
|
||||
balances: epochRef.effective_balances)
|
||||
|
||||
proc update_justified(
|
||||
|
@ -319,10 +321,11 @@ proc process_block*(self: var ForkChoice,
|
|||
|
||||
ok()
|
||||
|
||||
func find_head*(
|
||||
func find_head(
|
||||
self: var ForkChoiceBackend,
|
||||
current_epoch: Epoch,
|
||||
checkpoints: FinalityCheckpoints,
|
||||
justified_total_active_balance: Gwei,
|
||||
justified_state_balances: seq[Gwei],
|
||||
proposer_boost_root: Eth2Digest
|
||||
): FcResult[Eth2Digest] =
|
||||
|
@ -341,7 +344,7 @@ func find_head*(
|
|||
# Apply score changes
|
||||
? self.proto_array.applyScoreChanges(
|
||||
deltas, current_epoch, checkpoints,
|
||||
justified_state_balances, proposer_boost_root)
|
||||
justified_total_active_balance, proposer_boost_root)
|
||||
|
||||
self.balances = justified_state_balances
|
||||
|
||||
|
@ -365,6 +368,7 @@ proc get_head*(self: var ForkChoice,
|
|||
FinalityCheckpoints(
|
||||
justified: self.checkpoints.justified.checkpoint,
|
||||
finalized: self.checkpoints.finalized),
|
||||
self.checkpoints.justified.total_active_balance,
|
||||
self.checkpoints.justified.balances,
|
||||
self.checkpoints.proposer_boost_root)
|
||||
|
||||
|
|
|
@ -113,6 +113,7 @@ type
|
|||
|
||||
BalanceCheckpoint* = object
|
||||
checkpoint*: Checkpoint
|
||||
total_active_balance*: Gwei
|
||||
balances*: seq[Gwei]
|
||||
|
||||
Checkpoints* = object
|
||||
|
|
|
@ -126,18 +126,15 @@ iterator realizePendingCheckpoints*(
|
|||
self.currentEpochTips.clear()
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/fork-choice.md#get_weight
|
||||
func calculateProposerBoost(validatorBalances: openArray[Gwei]): uint64 =
|
||||
var total_balance: uint64
|
||||
for balance in validatorBalances:
|
||||
total_balance += balance
|
||||
let committee_weight = total_balance div SLOTS_PER_EPOCH
|
||||
func calculateProposerBoost(justifiedTotalActiveBalance: Gwei): Gwei =
|
||||
let committee_weight = justifiedTotalActiveBalance div SLOTS_PER_EPOCH
|
||||
(committee_weight * PROPOSER_SCORE_BOOST) div 100
|
||||
|
||||
func applyScoreChanges*(self: var ProtoArray,
|
||||
deltas: var openArray[Delta],
|
||||
currentEpoch: Epoch,
|
||||
checkpoints: FinalityCheckpoints,
|
||||
newBalances: openArray[Gwei],
|
||||
justifiedTotalActiveBalance: Gwei,
|
||||
proposerBoostRoot: Eth2Digest): FcResult[void] =
|
||||
## Iterate backwards through the array, touching all nodes and their parents
|
||||
## and potentially the best-child of each parent.
|
||||
|
@ -169,7 +166,7 @@ func applyScoreChanges*(self: var ProtoArray,
|
|||
self.nodes.buf[nodePhysicalIdx]
|
||||
|
||||
# Default value, if not otherwise set in first node loop
|
||||
var proposerBoostScore: uint64
|
||||
var proposerBoostScore: Gwei
|
||||
|
||||
# Iterate backwards through all the indices in `self.nodes`
|
||||
for nodePhysicalIdx in countdown(self.nodes.len - 1, 0):
|
||||
|
@ -194,7 +191,7 @@ func applyScoreChanges*(self: var ProtoArray,
|
|||
#
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/fork-choice.md#get_weight
|
||||
if (not proposerBoostRoot.isZero) and proposerBoostRoot == node.bid.root:
|
||||
proposerBoostScore = calculateProposerBoost(newBalances)
|
||||
proposerBoostScore = calculateProposerBoost(justifiedTotalActiveBalance)
|
||||
if nodeDelta >= 0 and
|
||||
high(Delta) - nodeDelta < proposerBoostScore.int64:
|
||||
return err ForkChoiceError(
|
||||
|
|
Loading…
Reference in New Issue