You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(replication): make the fresh-offer proof cap a lifetime budget
MAX_FRESH_OFFER_ATTEMPTS_PER_KEY gated on `pending.len()`, the queue's
instantaneous depth. The handler pops a proof before verifying it, so every
pop returned a slot that a fresh source could refill. Since the per-source
set only bars repeats, a stream of distinct peers kept one entry alive
indefinitely: unbounded sequential payment verifications — EVM and DHT
work — while holding an admission permit and one of only four fresh-offer
worker slots. Four such keys idle the whole pool. The staleness shed is no
backstop; it runs once before the loop, not inside it.
Count admissions instead, and never decrement. A popped proof has spent
its slot rather than returned it, so a key costs at most
CLOSE_GROUP_MAJORITY verifications no matter how many peers offer it. This
also bounds the entry's source set, which previously grew one PeerId per
sybil for the life of the entry.
Regression test drives pop-then-admit with a fresh source each time and
asserts the lifetime count holds; it accepted 16 proofs against a budget
of 4 before the fix. Reported by AI review of PR #165, independently
reproduced here before fixing.
Verified with the commands CI runs, including the no-default-features
build and test that the previous commit tripped.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
0 commit comments