Skip to content

Commit 73e600a

Browse files
authored
[r3.8] cl/phase1/network/registry: let one peer forward a slot's aggregates at once (#25250)
Cherry-pick of #25236 to release/3.8. The `beacon_aggregate_and_proof` topic allowed 8 messages per second per peer, with a burst of 16. Aggregates for a slot arrive in a burst, and an aggregate the limiter ignored was also dropped from every other peer because gossipsub had already marked it as seen, so the node lost whole committees. One peer may now forward a whole slot's expected aggregates in one burst (`MaxCommitteesPerSlot * TargetAggregatorsPerCommittee`), refilled over the slot. Fixes #25235 on release/3.8. Clean cherry-pick of 2cedbab. `go test -race ./cl/phase1/network/registry/` passes; `make lint` is clean twice; `make erigon integration` builds. The same change has run on a release/3.8-based mainnet node since 2026-10-22 (see #25236).
1 parent 981bff9 commit 73e600a

2 files changed

Lines changed: 33 additions & 1 deletion

File tree

‎cl/phase1/network/registry/register.go‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func RegisterGossipServices(
5050
// register services
5151
add(gossip.RegisterGossipService(gm, blockService, withRateLimiterByPeer(1, 2)))
5252
add(gossip.RegisterGossipService(gm, syncContributionService, waitReady, withRateLimiterByPeer(8, 16)))
53-
add(gossip.RegisterGossipService(gm, aggregateAndProofService, waitReady, withRateLimiterByPeer(8, 16)))
53+
add(gossip.RegisterGossipService(gm, aggregateAndProofService, waitReady, withAggregateAndProofRateLimiter(beaconCfg)))
5454
add(gossip.RegisterGossipService(gm, syncCommitteeMessagesService, waitReady, withRateLimiterByPeer(8, 16)))
5555
add(gossip.RegisterGossipService(gm, attesterSlashingService, waitReady, withRateLimiterByPeer(2, 8)))
5656
add(gossip.RegisterGossipService(gm, voluntaryExitService, waitReady, withRateLimiterByPeer(2, 8)))
@@ -107,6 +107,15 @@ func withPayloadAttestationRateLimiter() gossip.ConditionFunc {
107107
return withRateLimiterByPeer(float64(clparams.MaxPtcSize), int(clparams.MaxPtcSize))
108108
}
109109

110+
// withAggregateAndProofRateLimiter lets one peer forward every aggregate expected in a slot at once
111+
// (TARGET_AGGREGATORS_PER_COMMITTEE for each committee), refilled over the slot. Aggregates are
112+
// published at the same point in the slot, and one ignored here is also dropped from every other
113+
// peer, because gossipsub has already marked it as seen.
114+
func withAggregateAndProofRateLimiter(beaconCfg *clparams.BeaconChainConfig) gossip.ConditionFunc {
115+
perSlot := beaconCfg.MaxCommitteesPerSlot * beaconCfg.TargetAggregatorsPerCommittee
116+
return withRateLimiterByPeer(float64(perSlot)/float64(beaconCfg.SecondsPerSlot), int(perSlot))
117+
}
118+
110119
// withProposerPreferencesRateLimiter lets one peer relay one preference for every slot of the
111120
// accepted lookahead epochs at once: as with payload attestations, an ignored preference cannot be
112121
// redelivered by another peer.

‎cl/phase1/network/registry/register_test.go‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,26 @@ func TestProposerPreferencesRateLimiterAdmitsLookaheadWindowFromOnePeer(t *testi
5959
})
6060
}
6161
}
62+
63+
// Aggregates for a slot are published at one point in the slot, so a single peer can forward
64+
// every committee's aggregators in one burst.
65+
func TestAggregateAndProofRateLimiterAdmitsSlotBurstFromOnePeer(t *testing.T) {
66+
minimal := clparams.MainnetBeaconConfig
67+
clparams.ApplyMinimalPreset(&minimal)
68+
for _, test := range []struct {
69+
name string
70+
cfg clparams.BeaconChainConfig
71+
burst int
72+
}{
73+
{name: "mainnet", cfg: clparams.MainnetBeaconConfig, burst: 1024},
74+
{name: "minimal", cfg: minimal, burst: 64},
75+
} {
76+
t.Run(test.name, func(t *testing.T) {
77+
condition := withAggregateAndProofRateLimiter(&test.cfg)
78+
pid := peer.ID("aggregate-peer")
79+
for i := range test.burst {
80+
require.True(t, condition(pid, nil, clparams.FuluVersion), "aggregate %d", i)
81+
}
82+
})
83+
}
84+
}

0 commit comments

Comments
 (0)