Skip to content
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
b29db22
feat : updated sumcheck according to construction 6.3 in paper
ocdbytes Apr 9, 2026
77d7fa4
Merge branch 'aj/code-switch-protocol' into aj/zk-whir-3-2
ocdbytes Apr 17, 2026
980bce0
Merge branch 'aj/code-switch-protocol' into aj/zk-whir-3-2
ocdbytes Apr 17, 2026
aa402c2
feat : updated sumcheck and code switch for integration in main whir …
ocdbytes Apr 20, 2026
03e0818
feat : added mask proximity protocol
ocdbytes Apr 21, 2026
0c811ab
refactor : cleanup and added few tests
ocdbytes Apr 21, 2026
fa27b13
tiny change
ocdbytes Apr 21, 2026
b5239bd
feat : added assert for interleaving depth == 1 in mask proximity pro…
ocdbytes Apr 21, 2026
e33f3d3
resolved comments
ocdbytes Apr 24, 2026
9944f33
feat : added some tests in code switch
ocdbytes Apr 27, 2026
8b4f75b
Merge branch 'aj/code-switch-protocol' into aj/zk-whir-3-2
ocdbytes Apr 28, 2026
31e3776
merged code switch from parent
ocdbytes Apr 28, 2026
09e7c6a
Merge branch 'aj/code-switch-protocol' into aj/zk-whir-3-2
ocdbytes Apr 28, 2026
f4e3069
Merge branch 'aj/code-switch-protocol' into aj/zk-whir-3-2
ocdbytes Apr 28, 2026
ec7aa32
Merge pull request #249 from ocdbytes/aj/code-switch-protocol
Bisht13 Apr 28, 2026
c57f8a9
feat : updated code switch protocol for parameter selection logic
ocdbytes Apr 29, 2026
7af9775
feat : added support for interleaving depth > 1 for code switch
ocdbytes Apr 30, 2026
f857c42
fix : tests in runner
ocdbytes Apr 30, 2026
b8a60bf
Merge branch 'main' of https://github.com/WizardOfMenlo/whir into aj/…
ocdbytes May 1, 2026
2765ba8
nits: comment and type
ocdbytes May 1, 2026
8ec42d9
feat : comments resolved, added asserts, fixed test coverage
ocdbytes May 5, 2026
84a4a19
added security comment for verifier
ocdbytes May 5, 2026
a1190bd
fix: rust nits
ocdbytes May 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions proptest-regressions/protocols/mask_proximity.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Seeds for failure cases proptest has generated in the past. It is
# automatically read and these particular cases re-run before any
# novel cases are generated.
#
# It is recommended to check this file in to source control so that
# everyone who runs the test benefits from these saved cases.
cc 6a96626efcf88c8458e112fceda942463479dfd2637ca89ecaa4c89e49bf8f8e # shrinks to seed = 0, config = Config { c_zk: Config { embedding: Identity { field: FieldInfo { characteristic: [255, 255, 255, 255, 0, 0, 0, 1], extension_degree: 1 } }, num_vectors: 2, vector_size: 2, mask_length: 3, codeword_length: 4, interleaving_depth: 1, matrix_commit: Config { element_type: FieldInfo { characteristic: [255, 255, 255, 255, 0, 0, 0, 1], extension_degree: 1 }, num_cols: 2, leaf_hash_id: 03e01749ebcc0477924254eb482066b864a8dd4d77252464ca6f5b6f5cc05b4c, merkle_tree: Config { num_leaves: 4, layers: [LayerConfig { hash_id: 03e01749ebcc0477924254eb482066b864a8dd4d77252464ca6f5b6f5cc05b4c }, LayerConfig { hash_id: 03e01749ebcc0477924254eb482066b864a8dd4d77252464ca6f5b6f5cc05b4c }] } }, johnson_slack: 0.05590169943749475, in_domain_samples: 0, out_domain_samples: 1, deduplicate_in_domain: false }, num_masks: 1 }
7 changes: 7 additions & 0 deletions proptest-regressions/protocols/sumcheck.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Seeds for failure cases proptest has generated in the past. It is
# automatically read and these particular cases re-run before any
# novel cases are generated.
#
# It is recommended to check this file in to source control so that
# everyone who runs the test benefits from these saved cases.
cc 3a705bcc9147c4da8cf518feed3a83ca5031e1ccc09c3b20ba272427ee701cd2 # shrinks to seed = 0, config = Config { field: FieldInfo { characteristic: [255, 255, 255, 255, 0, 0, 0, 1], extension_degree: 1 }, initial_size: 2, round_pow: Config { hash_id: 03e01749ebcc0477924254eb482066b864a8dd4d77252464ca6f5b6f5cc05b4c, threshold: 18446744073709551615 }, num_rounds: 1, mask_length: 9, mask_config: Some(Config { embedding: Identity { field: FieldInfo { characteristic: [255, 255, 255, 255, 0, 0, 0, 1], extension_degree: 1 } }, num_vectors: 1, vector_size: 9, mask_length: 0, codeword_length: 18, interleaving_depth: 1, matrix_commit: Config { element_type: FieldInfo { characteristic: [255, 255, 255, 255, 0, 0, 0, 1], extension_degree: 1 }, num_cols: 1, leaf_hash_id: 03e01749ebcc0477924254eb482066b864a8dd4d77252464ca6f5b6f5cc05b4c, merkle_tree: Config { num_leaves: 18, layers: [LayerConfig { hash_id: 03e01749ebcc0477924254eb482066b864a8dd4d77252464ca6f5b6f5cc05b4c }, LayerConfig { hash_id: 03e01749ebcc0477924254eb482066b864a8dd4d77252464ca6f5b6f5cc05b4c }, LayerConfig { hash_id: 03e01749ebcc0477924254eb482066b864a8dd4d77252464ca6f5b6f5cc05b4c }, LayerConfig { hash_id: 03e01749ebcc0477924254eb482066b864a8dd4d77252464ca6f5b6f5cc05b4c }, LayerConfig { hash_id: 03e01749ebcc0477924254eb482066b864a8dd4d77252464ca6f5b6f5cc05b4c }] } }, johnson_slack: 0.035355339059327376, in_domain_samples: 75, out_domain_samples: 1, deduplicate_in_domain: false }) }
82 changes: 63 additions & 19 deletions src/protocols/basecase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,25 @@ use crate::{
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
ocdbytes marked this conversation as resolved.
Outdated
pub struct ProverResult<F: Field> {
pub evaluation_points: Vec<F>,
pub linear_form_evaluation: F,
}

/// Verifier output from the base case.
pub struct VerifierResult<F: Field> {
pub evaluation_points: Vec<F>,
pub linear_form_evaluation: F,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(bound = "")]
pub struct Config<F: Field> {
pub commit: irs_commit::Config<Identity<F>>,
pub sumcheck: sumcheck::Config<F>,

/// Whether to mask the vectors, whichs adds HVZK.
/// Whether to mask the vectors, which adds HVZK.
pub masked: bool,
}

Expand All @@ -46,7 +58,7 @@ impl<F: Field> Config<F> {
witness: &irs_commit::Witness<F>,
mut covector: Vec<F>,
mut sum: F,
) -> (Vec<F>, F)
) -> ProverResult<F>
where
H: DuplexSpongeInterface,
R: RngCore + CryptoRng,
Expand All @@ -63,7 +75,10 @@ impl<F: Field> Config<F> {
assert_eq!(self.sumcheck.final_size(), 1.min(self.commit.vector_size));
debug_assert_eq!(dot(&vector, &covector), sum);
if self.size() == 0 {
return (Vec::new(), F::ZERO);
return ProverResult {
evaluation_points: Vec::new(),
linear_form_evaluation: F::ZERO,
};
}

// Even more trivial non-zk protocol: send f an r directly.
Expand All @@ -74,9 +89,12 @@ impl<F: Field> Config<F> {
let point = self
.sumcheck
.prove(prover_state, &mut vector, &mut covector, &mut sum, &[])
.0;
.round_challenges;
assert!(!vector[0].is_zero(), "Proof failed");
return (point, covector[0]);
return ProverResult {
evaluation_points: point,
linear_form_evaluation: covector[0],
};
}

// Create masking vector.
Expand Down Expand Up @@ -113,24 +131,26 @@ impl<F: Field> Config<F> {
&mut masked_sum,
&[],
)
.0;
.round_challenges;

// If the MLE of `masked_vector` evaluates to zero, the verifier can not proceed.
// Basically the sumcheck equation has degenerated to 0 * l(r) = 0, which provides
// no constraints on l(r) that the verifier can return.
// This event is cryptographically unlikely as `F` is challenge sized.
assert!(!masked_vector[0].is_zero(), "Proof failed");

// Return evaluation point and value of the covector.
(point, covector[0])
ProverResult {
evaluation_points: point,
linear_form_evaluation: covector[0],
}
}

pub fn verify<H>(
&self,
verifier_state: &mut VerifierState<H>,
commitment: &irs_commit::Commitment<F>,
mut sum: F,
) -> VerificationResult<(Vec<F>, F)>
) -> VerificationResult<VerifierResult<F>>
where
H: DuplexSpongeInterface,
F: Codec<[H::U]>,
Expand All @@ -144,7 +164,10 @@ impl<F: Field> Config<F> {
assert_eq!(self.commit.vector_size, self.sumcheck.initial_size);
assert_eq!(self.sumcheck.final_size(), 1.min(self.commit.vector_size));
if self.size() == 0 {
return Ok((Vec::new(), F::ZERO));
return Ok(VerifierResult {
evaluation_points: Vec::new(),
linear_form_evaluation: F::ZERO,
});
}

// Unmasked protocol
Expand All @@ -153,7 +176,10 @@ impl<F: Field> Config<F> {
let masks = verifier_state
.prover_messages_vec(self.commit.mask_length * self.commit.num_messages())?;
let evals = self.commit.verify(verifier_state, &[commitment])?;
let point = self.sumcheck.verify(verifier_state, &mut sum)?.0;
let point = self
.sumcheck
.verify(verifier_state, &mut sum)?
.round_challenges;

for (&point, value) in zip_strict(&evals.points, evals.values(&[F::ONE])) {
// We expected `f(x) + x^l · g(x)` where l = deg(f) + 1, f is the message and g the mask.
Expand All @@ -165,7 +191,10 @@ impl<F: Field> Config<F> {
let mle = multilinear_extend(&vector, &point);
verify!(!mle.is_zero());
let linear_mle = sum / mle;
return Ok((point, linear_mle));
return Ok(VerifierResult {
evaluation_points: point,
linear_form_evaluation: linear_mle,
});
}

let mask_commitment = self.commit.receive_commitment(verifier_state)?;
Expand All @@ -191,15 +220,21 @@ impl<F: Field> Config<F> {

// Sumcheck on masked inner product
let mut masked_sum = mask_sum + mask_rlc * sum;
let point = self.sumcheck.verify(verifier_state, &mut masked_sum)?.0;
let point = self
.sumcheck
.verify(verifier_state, &mut masked_sum)?
.round_challenges;

// Compute implied MLE of the linear form
// f*(r) · l(r) = sum => l(r) = sum / f*(r)
let masked_mle = multilinear_extend(&masked_vector, &point);
verify!(!masked_mle.is_zero());
let linear_mle = masked_sum / masked_mle;

Ok((point, linear_mle))
Ok(VerifierResult {
evaluation_points: point,
linear_form_evaluation: linear_mle,
})
}
}

Expand Down Expand Up @@ -255,14 +290,17 @@ mod tests {
// Prover
let mut prover_state = ProverState::new_std(&ds);
let witness = config.commit.commit(&mut prover_state, &[&vector]);
let (point, value) = config.prove(
let prover_result = config.prove(
&mut prover_state,
vector.clone(),
&witness,
covector.clone(),
sum,
);
assert_eq!(multilinear_extend(&covector, &point), value);
assert_eq!(
multilinear_extend(&covector, &prover_result.evaluation_points),
prover_result.linear_form_evaluation
);
let proof = prover_state.proof();

// Verifier
Expand All @@ -271,11 +309,17 @@ mod tests {
.commit
.receive_commitment(&mut verifier_state)
.unwrap();
let (verifier_point, verifier_value) = config
let verifier_result = config
.verify(&mut verifier_state, &commitment, sum)
.unwrap();
assert_eq!(verifier_point, point);
assert_eq!(verifier_value, value);
assert_eq!(
verifier_result.evaluation_points,
prover_result.evaluation_points
);
assert_eq!(
verifier_result.linear_form_evaluation,
prover_result.linear_form_evaluation
);
verifier_state.check_eof().unwrap();
}

Expand Down
Loading
Loading