Commit e2cf63f
authored
feat(frost/roast): RFC-21 Phase 4.4 -- multi-coordinator soak harness (#3975)
## Summary
**Closes Phase 4 of RFC-21.** Adds the soak harness the RFC asks
for: a synthetic-fault-injection test that drives the full
attempt → evidence → next-attempt loop across N coordinator
instances and asserts every honest signer arrives at a
byte-identical next-attempt context.
The harness bypasses the receive-loop wiring (unit-tested under the
\`frost_roast_retry\` tag in PRs 4.1-4.3) and drives the
\`Coordinator\` API directly with synthetic snapshots. The novel
property it exercises is **multi-instance agreement** — every
node's \`NextAttempt\` result must hash-match every other node's,
regardless of which fault-injection scenario was run.
Stacked on #3974 (Phase 4.3).
## Test scenarios (6)
| Scenario | Assertion |
|---|---|
| Clean attempt | IncludedSet unchanged, nothing excluded or parked |
| Overflow exclusion | 4 observers report overflow against member 3 (sum
= threshold) → member 3 permanently excluded |
| Silence parking | Silent member parked at next attempt (not
permanently excluded) |
| **Park + reinstate cycle** | N+1 parks; N+2 reinstates. The defining
test for "strictly transient" parking |
| Infeasibility | Threshold = 5 with 2 silenced → every node's
NextAttempt returns ErrAttemptInfeasible |
| Set preservation | \`\|Inc\| + \|Exc\| + \|Park\|\` invariant holds
across 3 consecutive transitions |
Every \`soakAttempt\` invocation computes \`NextAttempt\` on every
node's local Coordinator instance and refuses to return until every
result's hash matches every other's. A single divergence anywhere
causes the test to fail with a precise hash comparison.
## Signer / Verifier stand-ins
\`soakSigner\` produces \`SHA-256(memberID ‖ payload)\` signatures;
the matching \`soakVerifier\` accepts byte-identical recomputations.
The harness exercises the **policy + canonical-encoding contracts**,
not key infrastructure — that's Phase 5's job to wire from real
\`pkg/net\` operator keys.
## Why this test isn't under \`//go:build frost_roast_retry\`
The soak harness operates entirely within \`pkg/frost/roast\` and
uses no build-tag-gated APIs from \`pkg/frost/signing\`. Gating it
would only obscure the multi-instance-agreement property from the
default-build CI. The build-tag-gated paths in \`pkg/frost/signing\`
have their own dedicated tests under the tag.
## Verification
| Command | Result |
|---|---|
| \`go test ./pkg/frost/roast/...\` | pass |
| \`go test -race ./pkg/frost/roast/...\` | pass |
| \`go test -tags 'frost_native frost_tbtc_signer frost_roast_retry'
./pkg/frost/...\` | pass (5 packages) |
| \`staticcheck -checks '-SA1019' ./pkg/frost/...\` | silent |
| \`gofmt -l ./pkg/frost/roast/\` | silent |
## Phase 4 status — all open
| PR | Scope | State |
|---|---|---|
| 4.1 (#3972) | frost_roast_retry registry | open |
| 4.2 (#3973) | Receive loops opt into bounded recorder | open |
| 4.3 (#3974) | Submit signed snapshots on attempt completion | open |
| **4.4 (this)** | **Multi-coordinator soak harness** | **open** |
Phase 4 is now feature-complete. **Phase 5** wires the retry adapter
that drives \`SetCurrentAttemptHandleForSession\` and consumes
\`NextAttempt\` results, making the submission path live.
## Test plan
- [ ] CI green.
- [ ] Reviewer confirms the multi-instance-agreement assertion is the
right load-bearing property to test (i.e., not e.g. throughput or
latency under load).1 file changed
Lines changed: 430 additions & 0 deletions
0 commit comments