Commit 5fa67b1
authored
hardening(frost/roast): verifiable blame — accuser quorum for exclusion; overflow can only park (#4029)
Stacked on #3866 (base: `feat/frost-schnorr-migration-scaffold`).
Implements item 2 of the review feedback on the FROST/ROAST stack
(verifiable blame, not counted blame).
## Problem
`NextAttempt` permanently excluded members on unverifiable observer
counters — reject/conflict threshold 1, overflow 4 — **summed across
observers and across reasons**, so a single byzantine observer
fabricating counters could permanently exclude any honest member, and by
repetition grind the included set below threshold
(`ErrAttemptInfeasible`). That inverts ROAST's robustness guarantee: the
design's whole point is liveness with t honest of n, and the blame layer
handed a liveness-and-membership veto to any single member. Bundle
evidence (`OverflowEntry`/`RejectEntry`/`ConflictEntry`) is
observer-signed *claims* — nothing in a counter lets a third party
re-check that the accused misbehaved.
## What changed
**Accuser-quorum gate (`ExclusionAccuserQuorum`).** An accusation only
produces action when made by at least `f+1 = groupSize − threshold + 1`
distinct credible observers (f = the byzantine tolerance). At f+1, at
least one accuser is honest under the protocol's own t-of-n assumption,
so the group may act as if the fault were verified. Real faults reach
quorum naturally — contributions are broadcast, every honest member
observes the same bytes — while f colluding members can never reach f+1
by fabrication. Production shape (n=100, t=51): quorum 50 vs. 49
worst-case byzantine.
**Counting hygiene.** Observers count once per accused per category
regardless of claimed `Count` magnitude; reject reasons no longer
multiply accusers; categories tally independently (reject + conflict
claims no longer sum); only previous-`IncludedSet` members are credible
accusers; accusations against non-original-set members are ignored.
**Overflow can never be permanent.** Transport pressure is observable
only at the transport layer and can never be made self-incriminating. An
*established* (quorum-corroborated) overflow accusation now parks the
member for one attempt — same transient mechanics as silence parking —
instead of excluding forever.
**Sub-quorum claims are ignored entirely**, not parked: acting on a
single unverifiable claim would let one byzantine observer impose an
attempt of liveness cost on any honest member at will.
Established reject/conflict accusations still exclude permanently, and
the policy remains a pure deterministic function of `(prev, bundle,
threshold)`.
## Why quorum rather than self-incriminating proofs now
The review's endgame is proof-carrying blame: the accused's own two
operator-signed conflicting payloads (conflicts), or their signed
contribution plus a re-checkable deterministic validation failure
(rejects). That requires wire-format and verification-routine changes
(the current bundle carries only counters). The quorum gate delivers the
safety property — fabricated blame can never become permanent, and the
grinding-to-infeasibility vector is closed — with no wire change, and is
the correct *floor* even after proofs land (proof-verified entries can
then bypass the quorum per category). RFC-21 Layer B now documents the
policy, the rationale, and that roadmap; the residual cost
(sub-quorum-observed faults burn retry attempts instead of excluding) is
explicitly folded into the serial-attempt latency budget.
## Tests
New regression coverage: quorum boundary at f vs f+1 for both permanent
categories; fabricated-blame grinding across six attempts (single
byzantine accuser, max counters, honest members never move);
count-magnitude fabrication; cross-category non-summing; reason
non-multiplication; non-credible accusers; non-original accused;
established-overflow park-and-reinstate cycle; production-shape quorum
pin `(100, 51) = 50`. Existing overflow/categories/soak tests updated to
the new semantics. `go test ./pkg/frost/... ./pkg/tbtc/...` passes; `go
vet` clean.
🤖 Generated with [Claude Code](https://claude.com/claude-code)5 files changed
Lines changed: 789 additions & 184 deletions
Lines changed: 71 additions & 32 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
307 | 307 | | |
308 | 308 | | |
309 | 309 | | |
310 | | - | |
311 | | - | |
312 | | - | |
313 | | - | |
314 | | - | |
315 | | - | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
316 | 344 | | |
317 | 345 | | |
318 | | - | |
319 | | - | |
320 | | - | |
321 | | - | |
322 | | - | |
323 | | - | |
324 | | - | |
325 | | - | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
326 | 357 | | |
327 | 358 | | |
328 | 359 | | |
329 | 360 | | |
330 | | - | |
331 | | - | |
332 | | - | |
333 | | - | |
334 | | - | |
335 | | - | |
336 | | - | |
337 | | - | |
338 | | - | |
339 | | - | |
340 | | - | |
341 | | - | |
342 | | - | |
343 | | - | |
344 | | - | |
345 | | - | |
346 | | - | |
347 | | - | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
348 | 387 | | |
349 | 388 | | |
350 | 389 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
265 | 265 | | |
266 | 266 | | |
267 | 267 | | |
268 | | - | |
| 268 | + | |
269 | 269 | | |
270 | 270 | | |
271 | 271 | | |
272 | 272 | | |
273 | | - | |
274 | | - | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
275 | 277 | | |
276 | 278 | | |
277 | 279 | | |
| |||
280 | 282 | | |
281 | 283 | | |
282 | 284 | | |
283 | | - | |
284 | | - | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
285 | 293 | | |
286 | 294 | | |
287 | 295 | | |
| |||
0 commit comments