Skip to content

zkWHIR 3.0 : Updated protocols for whir round integration and added mask proximity protocol (part 2)#3

Closed
ocdbytes wants to merge 23 commits into
aj/code-switch-protocolfrom
aj/zk-whir-3-2
Closed

zkWHIR 3.0 : Updated protocols for whir round integration and added mask proximity protocol (part 2)#3
ocdbytes wants to merge 23 commits into
aj/code-switch-protocolfrom
aj/zk-whir-3-2

Conversation

@ocdbytes

@ocdbytes ocdbytes commented Apr 9, 2026

Copy link
Copy Markdown
Owner

Refactors sumcheck, code-switch, and basecase protocols to extract mask commitment ownership into the orchestrator, and introduces a new mask_proximity protocol for per-iteration ZK mask verification via γ-combination.
This is the foundation for the new ZK WHIR orchestrator — each protocol component is now a clean, commitment-free building block that the orchestrator will wire together.

Changes

Sumcheck (sumcheck.rs)

  • Replaced mask_config: Option with plain mask_length: usize
  • Removed commit/receive_commitment calls from prove()/verify() — mask commitment moves to the orchestrator
  • Kept mask_sum/mask_rlc transcript exchange (sumcheck-internal algebra, Construction 6.3 p.38)
  • Replaced tuple returns with ProverResult { round_challenges, mask_sum, mask_rlc } / VerifierResult { round_challenges, mask_rlc }
  • Updated all call sites in whir/prover.rs, whir/verifier.rs, basecase.rs: .0 → .round_challenges
  • Added ZK vs non-ZK path invariant assertions in tests

Code Switch (code_switch.rs)

  • Removed mask_commit: Option and ZkQueryBudget — orchestrator owns mask config and query budgets
  • prove() now takes mask_oracle: Option<&MaskOracle> (pre-committed by orchestrator) instead of sampling + committing internally
  • verify() no longer takes or returns mask commitment — orchestrator tracks it directly
  • Config::new() accepts ood_samples and TargetConfigParams (including mask_length) from orchestrator
  • Added assertions: ood_samples > 0 (required for cross-oracle consistency), !unique_decoding, (mask_length > 0) == zk
  • Added ZK path test (test_zk) covering mask oracle OOD contribution
  • Added completeness check: ⟨f, sl'⟩ = μ' when source.mask_length == 0

Basecase (basecase.rs)

  • Replaced tuple returns (Vec, F) with ProverResult { evaluation_point, linear_form_evaluation } / VerifierResult { ... }

Mask Proximity (mask_proximity.rs) — NEW

  • Standalone protocol module implementing Construction 7.2 (p.43-44) specialized for zero-constraint mask oracles
  • Config wraps IrsConfig (shared mask tree) + num_masks
  • commit() — samples fresh mask-of-masks, commits all 2n vectors (originals + freshes) in one Merkle tree
  • prove() — receives γ, computes ξ*_i = s_i + γ·ξ_i, sends combined polynomials, opens tree
  • verify() — sends γ, reads combined polynomials, verifies tree, spot-checks at each opened position
  • Proptest arbitrary() delegating to IrsConfig::arbitrary() for valid parameter generation
  • Negative test: tampered mask polynomial → verifier correctly rejects

Mask Proximity Protocol

Implements Construction 7.2 from the paper (§7, p.43-48), specialized for zero-constraint masks (μ_i = 0, sl_{o,i} = 0).

Protocol flow:

  1. Prover commits 2n vectors in one tree: n original masks ξ_i and n fresh mask-of-masks s_i
  2. Verifier sends γ (combination randomness)
  3. Prover sends combined polynomials ξ*_i = s_i + γ·ξ_i and combined IRS randomness r*_i = r'_i + γ·r_i
  4. Shared tree is opened at random positions
  5. Verifier spot-checks: Enc(ξ*_i, r*_i)(y_j) = s_i(y_j) + γ·ξ_i(y_j) using linearity of RS encoding

Important

Soundness (Lemma 7.4, p.45): If ξ_i is δ-far from every C_zk codeword, then ξ*_i = s_i + γ·ξ_i is also far from s_i + γ·c for every codeword c, with high probability over γ. The spot-check catches disagreement at random positions with probability ≥ 1 − (1−δ)^{t_zk}.

Important

ZK safety (Lemma 7.3, p.44): Only ξ*_i = s_i + γ·ξ_i is revealed in full. Since s_i is uniformly random, ξ*_i is uniform regardless of ξ_i — the original mask is never exposed. The tree is opened at ≤ t_zk positions, within the ZK query budget of C_zk's encoding.

[MISSED IN DISCUSSIONS]
Why not just irs_commit.open/verify: irs_commit.verify() only checks Merkle binding (authentication paths). It does NOT verify proximity to C_zk — the doc comment in irs_commit confirms: "This does not verify the out-of-domain evaluations." Proximity requires the γ-combination: send the combined polynomial in full, then spot-check against the committed tree.

Next Steps

PR 2: Protocol Configs & Parameter Selection

  • Define OrchestratorConfig / IterationConfig structs
  • Implement parameter derivation chain: security_target → code rates → folding factors → per-iteration configs
  • Wire OOD sample computation (num_ood_samples) into orchestrator (moved out of code_switch)
  • Handle security reparameterization for ZK target configs (this will eliminate the need for checking if zk in each protocol and will centralise it)
  • Wire mask proximity config derivation (shared tree vector_size, num_vectors)

PR 3: Orchestrator Prover + Verifier Loops

  • Implement the iteration loop from Theorem 10.2 (p.62-65):
    • Phase 1: mask_proximity.commit() (ZK only)
    • Phase 2: sumcheck.prove()
    • Phase 3: code_switch.prove()
    • Phase 4: mask_proximity.prove() (ZK only)
    • Phase 5: wire outputs to next iteration
  • Terminal: basecase.prove()
  • End-to-end integration tests (all possibilities)

Caution

Cannot be merged as it depends on PR #249

@ocdbytes ocdbytes changed the title zkWHIR 3.0 : Updated sumcheck protocol for whir round integration zkWHIR 3.0 : Updated protocols for whir round integration and added mask proximity protocol (part 2) Apr 21, 2026
@ocdbytes ocdbytes marked this pull request as ready for review April 21, 2026 10:19
Comment thread src/protocols/code_switch.rs Outdated
masks: &[M::Source],
witness: &IrsWitness<M::Source, M::Target>,
covector: &mut [M::Target],
mask_oracle: Option<&MaskOracle<M::Target>>,

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.

This still represents ZK mode as zk: bool plus Option<&MaskOracle<_>> with runtime consistency checks. Can this boundary be made unrepresentable at the type/API level instead?

@ocdbytes ocdbytes Apr 22, 2026

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

This is for the ease of individual protocols. This can be done when the parameters are finalised right now protocol correctness is the main goal. These were added in tune with other protocols on how they have zk but that will also change as the Configs explicitly demand to have zk in them and other params which are not concrete

Comment thread src/protocols/code_switch.rs Outdated
verifier_state.verifier_message_vec(self.out_domain_samples);
let ood_answers: Vec<M::Target> =
verifier_state.prover_messages_vec(self.out_domain_samples)?;
let _ood_points: Vec<M::Target> = verifier_state.verifier_message_vec(self.ood_samples);

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.

In ZK mode the verifier consumes masked OOD answers, but the corresponding mask-side check is neither performed here nor reflected in the returned Commitment. Please make that deferred obligation explicit in the API, or wire the matching verification step into this flow.

@ocdbytes ocdbytes Apr 22, 2026

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

mask proximity protocol does this that's why here there is no need to check. Will add a comment here

Comment thread src/protocols/code_switch.rs Outdated
pub out_domain_samples: usize,
pub mask_commit: Option<IrsConfig<Identity<M::Target>>>,
pub ood_samples: usize,
pub zk: bool,

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.

This still represents ZK mode as zk: bool plus Option<&MaskOracle<_>> with runtime consistency checks. Can this boundary be made unrepresentable at the type/API level instead?

@ocdbytes ocdbytes Apr 22, 2026

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

After parameter finalisation we can do this. This is out of the scope of this PR. Only protocol correctness. Same reason : #3 (comment)

Comment thread src/protocols/code_switch.rs Outdated
let mut covector: Vec<F> = random_vector(&mut rng, config.source.message_length());
let initial_mu = dot(&message, &covector);

// MaskOracle with a random mask polynomial.

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.

test_zk() currently shows transcript plumbing, but not that the composed ZK invariant is enforced. Please add a negative integration test where the OOD masking relation is inconsistent with the companion mask-side proof and make sure the full composed flow rejects.

@ocdbytes ocdbytes Apr 22, 2026

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

we only check transcript plumbing as we can't have explicit tests for individual protocols without test logic being too complicated. (same as the last PR)

This will be tested in the orch PR as there we would have proper configs and zk comes from the top not in individual protocols

pub type Commitment<F> = IrsCommitment<F>;

impl<F: Field> Config<F> {
pub fn new(c_zk_commit: IrsConfig<Identity<F>>, num_masks: usize) -> Self {

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.

this protocol claims to reveal only the combined ξ*, but c_zk_commit still carries IRS out-of-domain openings by default. Since we commit [originals..., freshes...] through irs_commit, the verifier can receive raw OOD evaluations of the original masks before the γ-combination checks. That seems inconsistent with the intended ZK contract here. Can we require out_domain_samples == 0 for this protocol, or otherwise justify/encode this disclosure explicitly?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

in irs_commit

  // TODO : Remove this logic after main whir protocol is updated
  // as this is not required in the new construction.

this will be removed so assertion not needed here but can add for robustness.

Comment thread src/protocols/sumcheck.rs Outdated
Comment thread src/protocols/sumcheck.rs Outdated
Comment thread src/protocols/sumcheck.rs Outdated
Comment thread src/protocols/basecase.rs Outdated
verify,
};

/// Prover output from the base case.

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.

Both are { evaluation_points: Vec, linear_form_evaluation: F }. Collapse to a single Opening (or similar).

Comment thread src/protocols/basecase.rs Outdated
@Bisht13

Bisht13 commented Apr 22, 2026

Copy link
Copy Markdown
Collaborator

The planned orchestrator order (mask_proximity.commit → sumcheck → code_switch → mask_proximity.prove) sends s before g; the paper sends them together in Step 1. This shouldn't break Fiat-Shamir soundness, but Lemma 9.9's RBR proof doesn't transfer verbatim.

@Bisht13

Bisht13 commented Apr 22, 2026

Copy link
Copy Markdown
Collaborator

Right now the ZK invariant is expressed via bool + Option + runtime asserts in three separate files that the orchestrator must keep in lockstep. Type-level unification removes an entire class of bugs before PR 3 lands.

@ocdbytes ocdbytes closed this May 5, 2026
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.

2 participants