Skip to content

Zook : Parameter Selection #257

Open
ocdbytes wants to merge 3 commits into
worldfnd:mainfrom
ocdbytes:aj/zk-whir-3-3
Open

Zook : Parameter Selection #257
ocdbytes wants to merge 3 commits into
worldfnd:mainfrom
ocdbytes:aj/zk-whir-3-3

Conversation

@ocdbytes

@ocdbytes ocdbytes commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Changes :

  • Added proper param selection.
    • All paths for param selection are protected using type safety.
    • Any individual config cannot be modified within param selection.
    • Added analytical bit helper for each sub protocol param selection which also accounts for security bits.
    • Derived bounds for our modfied params can be found here : Derived Bounds.
    • All the bounds are verified by @WizardOfMenlo
  • Added Mode enum for each sub protocol for cleaner branching of the execution flow.
  • POW Grinding added for all the sub protocols.
  • Added getters instead of pub access of config fields for safety.

Tests :

  • Added proptests for each param selection path and protocol.

This PR was squashed from 47 commits during conflict resolution against PR #251 (merged to main)
Commit history maintained in personal fork.

@ocdbytes ocdbytes changed the title Aj/zk whir 3 3 Zook : Parameter Selection Jun 15, 2026
@ocdbytes
ocdbytes marked this pull request as ready for review June 15, 2026 14:38
@shreyas-londhe

Copy link
Copy Markdown
Collaborator

@ocdbytes Can you please resolve the merge conflicts on this PR? I'm reviewing it and we are planning to merge it by this week.

Resolve conflicts with the buffer abstraction while preserving parameter-selection protocol semantics.
@zkfriendly

Copy link
Copy Markdown
Collaborator

Hey @shreyas-londhe, this branch did not have any conflicts with main before merging buffer abstraction. I opened a PR to this branch here ocdbytes#11, which adds buffer abstraction. Merging it will make this branch conflict free again. cc @ocdbytes

@ocdbytes

Copy link
Copy Markdown
Contributor Author

Thanks @zkfriendly I have merged your PR now there are no conflicts. I skimmed through the changes will go through them properly tomorrow to see if there is anything to be changed.
cc @shreyas-londhe

@codspeed-hq

codspeed-hq Bot commented Jul 12, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 10 untouched benchmarks
⏩ 22 skipped benchmarks1


Comparing ocdbytes:aj/zk-whir-3-3 (3f019f1) with main (10aa7d0)

Open in CodSpeed

Footnotes

  1. 22 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Comment on lines +31 to +37
#[derive(Clone, Debug)]
pub struct ProtocolConfig<M: Embedding> {
security: SecuritySpec,
tuning: TuningSpec,
rounds: Vec<RoundConfig<M>>,
basecase: BasecasePlan<M::Target>,
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Can ProtocolConfig derive Serialize/Deserialize? It's #[derive(Clone, Debug)] today, so nothing downstream can embed it in a serialized scheme.

Context for why I'm asking: ProveKit builds its Fiat-Shamir domain separator by serializing the whole scheme (WHIR config included) and hashing that. whir::Config already handles it, with Serialize/Deserialize and #[serde(bound = "")] for the embedding generic. Once this stack has a prover/verifier runtime and replaces whir::Config as what schemes carry, ProtocolConfig will need the same.

It's not a one-liner though. RoundConfig, RoundMode, MaskOracleConfig, BasecasePlan in this file, plus Solved and CodeSwitchConfig, all need it too, and none of them derive it yet (SecuritySpec and TuningSpec already do). The embedding-generic ones want #[serde(bound = "")] like whir::Config.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hey @BornPsych
I have added these derives in wiring PR (next PR). Ig missed it here in this PR

MCA_FIELD_BITS,
);
let bcss25_const = (2.0 * 10.5_f64.powi(5) / 3.0).log2();
let expected = bcss25_const + (MCA_MESSAGE_LENGTH as f64).log2() + 2.5 * MCA_LOG_INV_RATE

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

issue (non-blocking): expected is built from the same expression as the implementation, so this test can't catch a transcription error in the bound itself.

A wrong constant or exponent in eps_mca_log2 would update both sides equally and the test would stay green. Since this file is where the soundness math lives, I'd anchor at least one case per regime to a hand-computed number: fix k, ρ, and |F|, work out the bits from the theorem by hand, and assert against that literal with the derivation in a comment. The analytic_error_*_formula tests in the solver modules and privacy_error_bits_matches_bound_3_sum in derive.rs have the same shape.

let regime = DecodingRegimeParams::from_policy(decoding_regime, rate);
// Query error is (1 - δ)^q in bits = -q · log2(1 - δ).
let log_one_minus_delta = regime.one_minus_distance_log2(-rate.log2());
let q = (security_target / -log_one_minus_delta).ceil() as usize;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

issue (non-blocking): num_in_domain_queries divides by zero when rate == 1.

At log_inv_rate = 0 the Unique branch gives 1 − δ = 1, so log_one_minus_delta is 0 and q saturates to usize::MAX through the ceil() as usize cast. TuningSpec doesn't reject starting_log_inv_rate == 0 and -r 0 sets it directly from the CLI, so this is reachable from the binary. A starting_log_inv_rate ≥ 1 check in round_layout (or a new LayoutError variant) would turn this into a clean error.

let error = match self {
Self::Unique => log_k + log_inv_rate,
Self::Johnson { slack } => {
debug_assert!(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

suggestion (non-blocking): keep these as hard assert!s like the pre-PR code.

The baseline enforced the η lower bound with assert!, so release builds kept the backstop. The DecodingRegimeParams variants are pub, so a future caller can construct Johnson { slack } directly with an out-of-range η and silently get an over-optimistic error bound in release. The check is two float ops on a cold path, so keeping it hard costs nothing. Same applies to the Capacity guard on line 121.

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.

4 participants