Skip to content

Commit 2c826bb

Browse files
committed
chore: Push evaluation of the linear map into CanonicalLinearRelation.
1 parent d5f0f94 commit 2c826bb

File tree

4 files changed

+46
-49
lines changed

4 files changed

+46
-49
lines changed

src/linear_relation/canonical.rs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ use crate::errors::{Error, InvalidInstance};
1313
/// This struct represents a normalized form of a linear relation where each
1414
/// constraint is of the form: image_i = Σ (scalar_j * group_element_k)
1515
/// without weights or extra scalars.
16+
///
17+
/// XXX. this definition is uncomfortably similar to LinearRelation, exception made for the weights.
18+
/// It'd be nice to squash the two together.
1619
#[derive(Clone, Debug, Default)]
1720
pub struct CanonicalLinearRelation<G: PrimeGroup> {
1821
/// The image group elements (left-hand side of equations)
@@ -35,7 +38,7 @@ type WeightedGroupCache<G> = HashMap<GroupVar<G>, Vec<(<G as group::Group>::Scal
3538

3639
impl<G: PrimeGroup> CanonicalLinearRelation<G> {
3740
/// Create a new empty canonical linear relation
38-
pub fn new() -> Self {
41+
fn new() -> Self {
3942
Self {
4043
image: Vec::new(),
4144
linear_combinations: Vec::new(),
@@ -44,6 +47,22 @@ impl<G: PrimeGroup> CanonicalLinearRelation<G> {
4447
}
4548
}
4649

50+
/// Evaluate the canonical linear relation with the provided scalars
51+
pub fn evaluate(&self, scalars: &[G::Scalar]) -> Result<Vec<G>, Error> {
52+
self.linear_combinations
53+
.iter()
54+
.map(|constraint| {
55+
let mut result = G::identity();
56+
for (scalar_var, group_var) in constraint {
57+
let scalar_val = scalars[scalar_var.index()];
58+
let group_val = self.group_elements.get(*group_var)?;
59+
result += group_val * scalar_val;
60+
}
61+
Ok(result)
62+
})
63+
.collect()
64+
}
65+
4766
/// Get or create a GroupVar for a weighted group element, with deduplication
4867
fn get_or_create_weighted_group_var(
4968
&mut self,
@@ -378,11 +397,10 @@ impl<G: PrimeGroup> TryFrom<&LinearRelation<G>> for CanonicalLinearRelation<G> {
378397
.map_err(|_| InvalidInstance::new("Unassigned group variable in image"))?;
379398

380399
// If the linear combination is trivial, check it directly and skip processing.
381-
if rhs
382-
.0
383-
.iter()
384-
.all(|weighted| matches!(weighted.term.scalar, ScalarTerm::Unit) || weighted.weight.is_zero_vartime())
385-
{
400+
if rhs.0.iter().all(|weighted| {
401+
matches!(weighted.term.scalar, ScalarTerm::Unit)
402+
|| weighted.weight.is_zero_vartime()
403+
}) {
386404
let rhs_value = rhs.0.iter().fold(G::identity(), |acc, weighted| {
387405
acc + relation
388406
.linear_map

src/linear_relation/mod.rs

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -118,23 +118,24 @@ pub type LinearCombination<G> = Sum<Weighted<Term<G>, <G as group::Group>::Scala
118118

119119
impl<G: PrimeGroup> LinearMap<G> {
120120
fn map(&self, scalars: &[G::Scalar]) -> Result<Vec<G>, InvalidInstance> {
121-
self.linear_combinations.iter().map(
122-
|lc| {
123-
let weighted_coefficients =
124-
lc.0.iter()
125-
.map(|weighted| weighted.term.scalar.value(scalars) * weighted.weight)
126-
.collect::<Vec<_>>();
127-
let elements =
128-
lc.0.iter()
129-
.map(|weighted| self.group_elements.get(weighted.term.elem))
130-
.collect::<Result<Vec<_>, InvalidInstance>>();
131-
match elements {
132-
Ok(elements) => Ok(msm_pr(&weighted_coefficients, &elements)),
133-
Err(error) => Err(error),
134-
}
135-
}
136-
).
137-
collect::<Result<Vec<_>, InvalidInstance>>().into()
121+
self.linear_combinations
122+
.iter()
123+
.map(|lc| {
124+
let weighted_coefficients =
125+
lc.0.iter()
126+
.map(|weighted| weighted.term.scalar.value(scalars) * weighted.weight)
127+
.collect::<Vec<_>>();
128+
let elements =
129+
lc.0.iter()
130+
.map(|weighted| self.group_elements.get(weighted.term.elem))
131+
.collect::<Result<Vec<_>, InvalidInstance>>();
132+
match elements {
133+
Ok(elements) => Ok(msm_pr(&weighted_coefficients, &elements)),
134+
Err(error) => Err(error),
135+
}
136+
})
137+
.collect::<Result<Vec<_>, InvalidInstance>>()
138+
.into()
138139
}
139140
}
140141

@@ -489,11 +490,7 @@ impl<G: PrimeGroup> LinearRelation<G> {
489490

490491
let mapped_scalars = self.linear_map.map(scalars)?;
491492

492-
for (mapped_scalar, lhs) in iter::zip(
493-
mapped_scalars,
494-
&self.image,
495-
) {
496-
493+
for (mapped_scalar, lhs) in iter::zip(mapped_scalars, &self.image) {
497494
self.linear_map
498495
.group_elements
499496
.assign_element(*lhs, mapped_scalar)

src/schnorr_protocol.rs

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,6 @@ impl<G: PrimeGroup> SchnorrProof<G> {
3838
self.0.linear_combinations.len()
3939
}
4040

41-
/// Evaluate the canonical linear relation with the provided scalars
42-
fn evaluate(&self, scalars: &[G::Scalar]) -> Result<Vec<G>, Error> {
43-
self.0
44-
.linear_combinations
45-
.iter()
46-
.map(|constraint| {
47-
let mut result = G::identity();
48-
for (scalar_var, group_var) in constraint {
49-
let scalar_val = scalars[scalar_var.index()];
50-
let group_val = self.0.group_elements.get(*group_var)?;
51-
result += group_val * scalar_val;
52-
}
53-
Ok(result)
54-
})
55-
.collect()
56-
}
57-
5841
/// Internal method to commit using provided nonces (for deterministic testing)
5942
pub fn commit_with_nonces(
6043
&self,
@@ -80,7 +63,7 @@ impl<G: PrimeGroup> SchnorrProof<G> {
8063
return Err(Error::InvalidInstanceWitnessPair);
8164
}
8265

83-
let commitment = self.evaluate(nonces)?;
66+
let commitment = self.0.evaluate(nonces)?;
8467
let prover_state = ProverState(nonces.to_vec(), witness.to_vec());
8568
Ok((commitment, prover_state))
8669
}
@@ -193,7 +176,7 @@ impl<G: PrimeGroup> SigmaProtocol for SchnorrProof<G> {
193176
return Err(Error::InvalidInstanceWitnessPair);
194177
}
195178

196-
let lhs = self.evaluate(response)?;
179+
let lhs = self.0.evaluate(response)?;
197180
let mut rhs = Vec::new();
198181
for (i, g) in commitment.iter().enumerate() {
199182
rhs.push(self.0.image[i] * challenge + g);
@@ -366,7 +349,7 @@ where
366349
return Err(Error::InvalidInstanceWitnessPair);
367350
}
368351

369-
let response_image = self.evaluate(response)?;
352+
let response_image = self.0.evaluate(response)?;
370353
let image = &self.0.image;
371354

372355
let commitment = response_image

src/tests/test_validation_criteria.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ mod instance_validation {
6262
relation.set_element(var_X, G::identity());
6363
let result = CanonicalLinearRelation::try_from(&relation);
6464
assert!(result.is_ok());
65-
6665
}
6766

6867
#[test]

0 commit comments

Comments
 (0)