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,
|
version: version,
|
||||||
justified: BalanceCheckpoint(
|
justified: BalanceCheckpoint(
|
||||||
checkpoint: checkpoint,
|
checkpoint: checkpoint,
|
||||||
|
total_active_balance: epochRef.total_active_balance,
|
||||||
balances: epochRef.effective_balances),
|
balances: epochRef.effective_balances),
|
||||||
finalized: checkpoint,
|
finalized: checkpoint,
|
||||||
best_justified: checkpoint))
|
best_justified: checkpoint))
|
||||||
|
@ -98,6 +99,7 @@ proc update_justified(
|
||||||
store = self.justified.checkpoint, state = justified
|
store = self.justified.checkpoint, state = justified
|
||||||
self.justified = BalanceCheckpoint(
|
self.justified = BalanceCheckpoint(
|
||||||
checkpoint: Checkpoint(root: blck.root, epoch: epochRef.epoch),
|
checkpoint: Checkpoint(root: blck.root, epoch: epochRef.epoch),
|
||||||
|
total_active_balance: epochRef.total_active_balance,
|
||||||
balances: epochRef.effective_balances)
|
balances: epochRef.effective_balances)
|
||||||
|
|
||||||
proc update_justified(
|
proc update_justified(
|
||||||
|
@ -319,10 +321,11 @@ proc process_block*(self: var ForkChoice,
|
||||||
|
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
func find_head*(
|
func find_head(
|
||||||
self: var ForkChoiceBackend,
|
self: var ForkChoiceBackend,
|
||||||
current_epoch: Epoch,
|
current_epoch: Epoch,
|
||||||
checkpoints: FinalityCheckpoints,
|
checkpoints: FinalityCheckpoints,
|
||||||
|
justified_total_active_balance: Gwei,
|
||||||
justified_state_balances: seq[Gwei],
|
justified_state_balances: seq[Gwei],
|
||||||
proposer_boost_root: Eth2Digest
|
proposer_boost_root: Eth2Digest
|
||||||
): FcResult[Eth2Digest] =
|
): FcResult[Eth2Digest] =
|
||||||
|
@ -341,7 +344,7 @@ func find_head*(
|
||||||
# Apply score changes
|
# Apply score changes
|
||||||
? self.proto_array.applyScoreChanges(
|
? self.proto_array.applyScoreChanges(
|
||||||
deltas, current_epoch, checkpoints,
|
deltas, current_epoch, checkpoints,
|
||||||
justified_state_balances, proposer_boost_root)
|
justified_total_active_balance, proposer_boost_root)
|
||||||
|
|
||||||
self.balances = justified_state_balances
|
self.balances = justified_state_balances
|
||||||
|
|
||||||
|
@ -365,6 +368,7 @@ proc get_head*(self: var ForkChoice,
|
||||||
FinalityCheckpoints(
|
FinalityCheckpoints(
|
||||||
justified: self.checkpoints.justified.checkpoint,
|
justified: self.checkpoints.justified.checkpoint,
|
||||||
finalized: self.checkpoints.finalized),
|
finalized: self.checkpoints.finalized),
|
||||||
|
self.checkpoints.justified.total_active_balance,
|
||||||
self.checkpoints.justified.balances,
|
self.checkpoints.justified.balances,
|
||||||
self.checkpoints.proposer_boost_root)
|
self.checkpoints.proposer_boost_root)
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,7 @@ type
|
||||||
|
|
||||||
BalanceCheckpoint* = object
|
BalanceCheckpoint* = object
|
||||||
checkpoint*: Checkpoint
|
checkpoint*: Checkpoint
|
||||||
|
total_active_balance*: Gwei
|
||||||
balances*: seq[Gwei]
|
balances*: seq[Gwei]
|
||||||
|
|
||||||
Checkpoints* = object
|
Checkpoints* = object
|
||||||
|
|
|
@ -126,18 +126,15 @@ iterator realizePendingCheckpoints*(
|
||||||
self.currentEpochTips.clear()
|
self.currentEpochTips.clear()
|
||||||
|
|
||||||
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/fork-choice.md#get_weight
|
# 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 =
|
func calculateProposerBoost(justifiedTotalActiveBalance: Gwei): Gwei =
|
||||||
var total_balance: uint64
|
let committee_weight = justifiedTotalActiveBalance div SLOTS_PER_EPOCH
|
||||||
for balance in validatorBalances:
|
|
||||||
total_balance += balance
|
|
||||||
let committee_weight = total_balance div SLOTS_PER_EPOCH
|
|
||||||
(committee_weight * PROPOSER_SCORE_BOOST) div 100
|
(committee_weight * PROPOSER_SCORE_BOOST) div 100
|
||||||
|
|
||||||
func applyScoreChanges*(self: var ProtoArray,
|
func applyScoreChanges*(self: var ProtoArray,
|
||||||
deltas: var openArray[Delta],
|
deltas: var openArray[Delta],
|
||||||
currentEpoch: Epoch,
|
currentEpoch: Epoch,
|
||||||
checkpoints: FinalityCheckpoints,
|
checkpoints: FinalityCheckpoints,
|
||||||
newBalances: openArray[Gwei],
|
justifiedTotalActiveBalance: Gwei,
|
||||||
proposerBoostRoot: Eth2Digest): FcResult[void] =
|
proposerBoostRoot: Eth2Digest): FcResult[void] =
|
||||||
## Iterate backwards through the array, touching all nodes and their parents
|
## Iterate backwards through the array, touching all nodes and their parents
|
||||||
## and potentially the best-child of each parent.
|
## and potentially the best-child of each parent.
|
||||||
|
@ -169,7 +166,7 @@ func applyScoreChanges*(self: var ProtoArray,
|
||||||
self.nodes.buf[nodePhysicalIdx]
|
self.nodes.buf[nodePhysicalIdx]
|
||||||
|
|
||||||
# Default value, if not otherwise set in first node loop
|
# 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`
|
# Iterate backwards through all the indices in `self.nodes`
|
||||||
for nodePhysicalIdx in countdown(self.nodes.len - 1, 0):
|
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
|
# 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:
|
if (not proposerBoostRoot.isZero) and proposerBoostRoot == node.bid.root:
|
||||||
proposerBoostScore = calculateProposerBoost(newBalances)
|
proposerBoostScore = calculateProposerBoost(justifiedTotalActiveBalance)
|
||||||
if nodeDelta >= 0 and
|
if nodeDelta >= 0 and
|
||||||
high(Delta) - nodeDelta < proposerBoostScore.int64:
|
high(Delta) - nodeDelta < proposerBoostScore.int64:
|
||||||
return err ForkChoiceError(
|
return err ForkChoiceError(
|
||||||
|
|
Loading…
Reference in New Issue