during proposal duties, perform sync aggregation duties if not received (#6384)

Including sync contributions into a block affects validator rewards.
When we have not received aggregate sync contributions, but have seen
individual messages, we can produce the contributions locally, improving
validator rewards when subscribing to all subnets or when having a
non-aggregating attached validator in the sync committee.
This commit is contained in:
Etan Kissling 2024-06-24 11:13:15 +02:00 committed by GitHub
parent e4efe9ed75
commit cd4de1357a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 39 additions and 24 deletions

View File

@ -217,15 +217,16 @@ func produceContribution*(
else:
false
func addAggregateAux(bestVotes: var BestSyncSubcommitteeContributions,
contribution: SyncCommitteeContribution) =
func addContribution(
contributions: var BestSyncSubcommitteeContributions,
contribution: SyncCommitteeContribution) =
let
currentBestTotalParticipants =
bestVotes.subnets[contribution.subcommittee_index].totalParticipants
contributions.subnets[contribution.subcommittee_index].totalParticipants
newBestTotalParticipants = countOnes(contribution.aggregation_bits)
if newBestTotalParticipants > currentBestTotalParticipants:
bestVotes.subnets[contribution.subcommittee_index] =
contributions.subnets[contribution.subcommittee_index] =
BestSyncSubcommitteeContribution(
totalParticipants: newBestTotalParticipants,
participationBits: contribution.aggregation_bits,
@ -241,10 +242,10 @@ func isSeen*(
seenKey in pool.seenContributionByAuthor
func covers(
bestVotes: BestSyncSubcommitteeContributions,
contributions: BestSyncSubcommitteeContributions,
contribution: SyncCommitteeContribution): bool =
contribution.aggregation_bits.isSubsetOf(
bestVotes.subnets[contribution.subcommittee_index].participationBits)
contributions.subnets[contribution.subcommittee_index].participationBits)
func covers*(
pool: var SyncCommitteeMsgPool,
@ -271,22 +272,12 @@ proc addContribution(pool: var SyncCommitteeMsgPool,
pool.seenContributionByAuthor.incl seenKey
let target = pool.cfg.toSyncMsgTarget(bid, contribution.slot)
if target notin pool.bestContributions:
let totalParticipants = countOnes(contribution.aggregation_bits)
var initialBestContributions = BestSyncSubcommitteeContributions()
initialBestContributions.subnets[contribution.subcommittee_index] =
BestSyncSubcommitteeContribution(
totalParticipants: totalParticipants,
participationBits: contribution.aggregation_bits,
signature: signature)
pool.bestContributions[target] = initialBestContributions
else:
try:
addAggregateAux(pool.bestContributions[target], contribution)
except KeyError:
raiseAssert "We have checked for the key upfront"
pool.bestContributions.withValue(target, contributions):
contributions[].addContribution(contribution)
do:
var contributions: BestSyncSubcommitteeContributions
contributions.addContribution(contribution)
pool.bestContributions[target] = contributions
proc addContribution*(pool: var SyncCommitteeMsgPool,
scproof: SignedContributionAndProof,
@ -334,11 +325,35 @@ proc produceSyncAggregateAux(
aggregate
proc produceSyncAggregate*(
pool: SyncCommitteeMsgPool,
pool: var SyncCommitteeMsgPool,
bid: BlockId,
signatureSlot: Slot): SyncAggregate =
# Sync committee signs previous slot, relative to when new block is produced
let target = pool.cfg.toSyncMsgTarget(bid, max(signatureSlot, 1.Slot) - 1)
let
slot = max(signatureSlot, 1.Slot) - 1
target = pool.cfg.toSyncMsgTarget(bid, slot)
var contribution {.noinit.}: SyncCommitteeContribution
pool.bestContributions.withValue(target, contributions):
for subcommitteeIdx in SyncSubcommitteeIndex:
if contributions.subnets[subcommitteeIdx].totalParticipants == 0 and
pool.produceContribution(slot, bid, subcommitteeIdx, contribution):
debug "Did not receive contribution, did aggregate locally",
target, subcommitteeIdx
contributions[].addContribution(contribution)
do:
var
contributions: BestSyncSubcommitteeContributions
didAggregate = false
for subcommitteeIdx in SyncSubcommitteeIndex:
if pool.produceContribution(slot, bid, subcommitteeIdx, contribution):
debug "Did not receive contribution, did aggregate locally",
target, subcommitteeIdx
contributions.addContribution(contribution)
didAggregate = true
if didAggregate:
pool.bestContributions[target] = contributions
if target in pool.bestContributions:
try:
produceSyncAggregateAux(pool.bestContributions[target])