Skip to content

fix: servers verify each client's opening before summing - #10

Merged
noot merged 5 commits into
mainfrom
noot/server-verifies-client-openings
Nov 4, 2026
Merged

noot merged 5 commits into
mainfrom
noot/server-verifies-client-openings

Conversation

@noot

@noot noot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

The server round now checks every canonical client's opening against that client's own commitment at the server's position before summing. A failing opening returns ServerRoundError::BadOpening(client) and the server posts nothing. run_server_round takes the commitment parameters and the clients' commitments off the bulletin, mirroring run_rs_node_round.

The per-client check uses the fresh norm bounds, β_cs on the randomness and ζ on the digits, rather than the aggregate bounds the recipient uses. verify is split into a bounded helper, with verify keeping the aggregate bounds and verify_fresh using the fresh ones, so any ρ ≤ ρ_max openings the server accepts sum to an opening the recipient accepts.

paper divergence

In "Constructing Relaxed Anonymous Broadcast" the server procedure decrypts each client's sealed opening, verifies it against that client's commitment at position i, and returns ⊥ for the whole round if any client fails. The code summed the openings unverified and left the check to the recipient, which verifies only the aggregate. The recipient's exclusion loop then treated a failed aggregate as the server's fault, so one bad opening from a client got an honest server dropped, and with the default threshold a few such clients could stall a round. The anonymity proof in "Anonymity against Malicious Clients" does not depend on the abort, so this is robustness and attribution, not privacy. The named client can now be excluded and the round re-run.

The commitment scheme's verify in "Preliminaries" bounds a fresh opening by β_cs; the code's verify only had the aggregate bound β_agg. Checking a single client against the aggregate bound would have let a client pass the server with oversized randomness and still push the sum past the recipient's bound.

verification

All 150 tests pass. New tests cover a tampered opening (the targeted server names the client, the remaining servers still reach the threshold), a swapped commitment, an opening for another server's position, a missing commitment, and a commitment made with randomness at the aggregate bound that the aggregate check accepts but the fresh check rejects.

noot added 3 commits October 29, 2026 14:37
Matches the paper's server step: every canonical client's opening must open
that client's own commitment at the server's position, or the server posts
nothing and names the client. Previously a bad opening made an honest server's
aggregate fail at the recipient, which then dropped the server.
@noot
noot requested a balanced review from Copilot October 30, 2026 18:37
@noot noot changed the title servers verify each client's opening before summing fix: servers verify each client's opening before summing Oct 30, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Missing per-client bounds let malicious openings cause honest servers to be blamed, while unchecked server indices can prevent correct attribution to the offending client.

2 open issues
What changed in this PR

This PR adds per-client opening verification to server rounds, aiming to identify invalid client input before aggregation rather than blame an honest server at the recipient.

Changes:

  • Pass commitment parameters and bulletin commitments into run_server_round, returning BadOpening(client) for failed verification.
  • Add regression tests for tampering, swapped commitments, wrong positions, and missing commitments.
  • Update callers, benchmarks, examples, and documentation for the new API.
File Description
tests/​rs_mode_e2e.rs Supply client commitments in RS-mode rounds.
tests/​recipient_e2e.rs Update recipient test setup for server verification.
tests/​prony_e2e.rs Pass commitments through Prony round tests.
tests/​mse_e2e.rs Update MSE tests for the new server API.
tests/​end_to_end.rs Add rejection tests and shared round setup; update callers.
src/​scaling_bench.rs Include opening verification in server benchmarks.
src/​protocol/​server.rs Verify individual openings and report offending clients.
README.md Document commitment inputs and rejection behavior.
examples/​profile.rs Update profiling rounds to supply commitments.
examples/​demo.rs Read bulletin commitments for server verification.

Review effort: Balanced

Comment thread src/protocol/server.rs Resolved
Comment thread src/protocol/server.rs
.par_iter()
.zip(opening_refs.par_iter())
.zip(comm_refs.par_iter())
.find_map_first(|((cid, op), comm)| {
@noot
noot requested a balanced review from Copilot November 3, 2026 18:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The opening check does not validate server_index against position, allowing a client to abort the server round with MalformedOpening instead of being identified by BadOpening(cid).

2 open issues
1 resolved since last review

Review effort: Balanced

Comment thread src/protocol/server.rs Resolved

@ameba23 ameba23 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great 🌟 - pending the remaining issue from Copilot.

Regarding performance impact, i ran the scaling_bench with and without these changes, and am seeing this sort of impact on total CPU time (adding together client, server and recipient processing):

  • Prony with 4kb message: 19% increase
  • Prony with 16kb message: 16% increase
  • IBLT with 4kb message: 36% increase
  • IBLT with 16kb message: 10% increase

with 300 clients, 8 servers.

I don't think its worth scrutinising this too much, as i totally think we need this check. But something to bear in mind.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@noot

noot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

i'll look into some performance improvements next! thanks for pointing that out

@noot
noot merged commit 9d79077 into main Nov 4, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants