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: else:
false false
func addAggregateAux(bestVotes: var BestSyncSubcommitteeContributions, func addContribution(
contribution: SyncCommitteeContribution) = contributions: var BestSyncSubcommitteeContributions,
contribution: SyncCommitteeContribution) =
let let
currentBestTotalParticipants = currentBestTotalParticipants =
bestVotes.subnets[contribution.subcommittee_index].totalParticipants contributions.subnets[contribution.subcommittee_index].totalParticipants
newBestTotalParticipants = countOnes(contribution.aggregation_bits) newBestTotalParticipants = countOnes(contribution.aggregation_bits)
if newBestTotalParticipants > currentBestTotalParticipants: if newBestTotalParticipants > currentBestTotalParticipants:
bestVotes.subnets[contribution.subcommittee_index] = contributions.subnets[contribution.subcommittee_index] =
BestSyncSubcommitteeContribution( BestSyncSubcommitteeContribution(
totalParticipants: newBestTotalParticipants, totalParticipants: newBestTotalParticipants,
participationBits: contribution.aggregation_bits, participationBits: contribution.aggregation_bits,
@ -241,10 +242,10 @@ func isSeen*(
seenKey in pool.seenContributionByAuthor seenKey in pool.seenContributionByAuthor
func covers( func covers(
bestVotes: BestSyncSubcommitteeContributions, contributions: BestSyncSubcommitteeContributions,
contribution: SyncCommitteeContribution): bool = contribution: SyncCommitteeContribution): bool =
contribution.aggregation_bits.isSubsetOf( contribution.aggregation_bits.isSubsetOf(
bestVotes.subnets[contribution.subcommittee_index].participationBits) contributions.subnets[contribution.subcommittee_index].participationBits)
func covers*( func covers*(
pool: var SyncCommitteeMsgPool, pool: var SyncCommitteeMsgPool,
@ -271,22 +272,12 @@ proc addContribution(pool: var SyncCommitteeMsgPool,
pool.seenContributionByAuthor.incl seenKey pool.seenContributionByAuthor.incl seenKey
let target = pool.cfg.toSyncMsgTarget(bid, contribution.slot) let target = pool.cfg.toSyncMsgTarget(bid, contribution.slot)
if target notin pool.bestContributions: pool.bestContributions.withValue(target, contributions):
let totalParticipants = countOnes(contribution.aggregation_bits) contributions[].addContribution(contribution)
var initialBestContributions = BestSyncSubcommitteeContributions() do:
var contributions: BestSyncSubcommitteeContributions
initialBestContributions.subnets[contribution.subcommittee_index] = contributions.addContribution(contribution)
BestSyncSubcommitteeContribution( pool.bestContributions[target] = contributions
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"
proc addContribution*(pool: var SyncCommitteeMsgPool, proc addContribution*(pool: var SyncCommitteeMsgPool,
scproof: SignedContributionAndProof, scproof: SignedContributionAndProof,
@ -334,11 +325,35 @@ proc produceSyncAggregateAux(
aggregate aggregate
proc produceSyncAggregate*( proc produceSyncAggregate*(
pool: SyncCommitteeMsgPool, pool: var SyncCommitteeMsgPool,
bid: BlockId, bid: BlockId,
signatureSlot: Slot): SyncAggregate = signatureSlot: Slot): SyncAggregate =
# Sync committee signs previous slot, relative to when new block is produced # 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: if target in pool.bestContributions:
try: try:
produceSyncAggregateAux(pool.bestContributions[target]) produceSyncAggregateAux(pool.bestContributions[target])