Skip to content

Commit e78508c

Browse files
authored
feat: default MSM implementation for PrimeGroup (#74)
1 parent 37c76c9 commit e78508c

File tree

4 files changed

+43
-26
lines changed

4 files changed

+43
-26
lines changed

src/linear_relation/canonical.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use subtle::{Choice, ConstantTimeEq};
88

99
use super::{GroupMap, GroupVar, LinearCombination, LinearRelation, ScalarTerm, ScalarVar};
1010
use crate::errors::{Error, InvalidInstance};
11-
use crate::linear_relation::msm_pr;
11+
use crate::linear_relation::multi_scalar_mul::VariableMultiScalarMul;
1212

1313
/// A normalized form of the [`LinearRelation`], which is used for serialization into the transcript.
1414
///
@@ -62,7 +62,7 @@ impl<G: PrimeGroup> CanonicalLinearRelation<G> {
6262
.iter()
6363
.map(|(_, group_var)| self.group_elements.get(*group_var).unwrap())
6464
.collect::<Vec<_>>();
65-
msm_pr(&scalars, &bases)
65+
G::msm(&scalars, &bases)
6666
})
6767
.collect()
6868
}

src/linear_relation/mod.rs

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ mod ops;
2828
mod canonical;
2929
pub use canonical::CanonicalLinearRelation;
3030

31+
/// Implementation of multi-scalar multiplication (MSM) over scalars and points.
32+
mod multi_scalar_mul;
33+
pub use multi_scalar_mul::VariableMultiScalarMul;
34+
3135
/// A wrapper representing an index for a scalar variable.
3236
///
3337
/// Used to reference scalars in sparse linear combinations.
@@ -130,7 +134,7 @@ impl<G: PrimeGroup> LinearMap<G> {
130134
.map(|weighted| self.group_elements.get(weighted.term.elem))
131135
.collect::<Result<Vec<_>, InvalidInstance>>();
132136
match elements {
133-
Ok(elements) => Ok(msm_pr(&weighted_coefficients, &elements)),
137+
Ok(elements) => Ok(G::msm(&weighted_coefficients, &elements)),
134138
Err(error) => Err(error),
135139
}
136140
})
@@ -262,25 +266,6 @@ pub struct LinearMap<G: PrimeGroup> {
262266
pub num_elements: usize,
263267
}
264268

265-
/// Perform a simple multi-scalar multiplication (MSM) over scalars and points.
266-
///
267-
/// Given slices of scalars and corresponding group elements (bases),
268-
/// returns the sum of each base multiplied by its scalar coefficient.
269-
///
270-
/// # Parameters
271-
/// - `scalars`: slice of scalar multipliers.
272-
/// - `bases`: slice of group elements to be multiplied by the scalars.
273-
///
274-
/// # Returns
275-
/// The group element result of the MSM.
276-
pub fn msm_pr<G: PrimeGroup>(scalars: &[G::Scalar], bases: &[G]) -> G {
277-
let mut acc = G::identity();
278-
for (s, p) in scalars.iter().zip(bases.iter()) {
279-
acc += *p * s;
280-
}
281-
acc
282-
}
283-
284269
impl<G: PrimeGroup> LinearMap<G> {
285270
/// Creates a new empty [`LinearMap`].
286271
///
@@ -332,7 +317,7 @@ impl<G: PrimeGroup> LinearMap<G> {
332317
lc.0.iter()
333318
.map(|weighted| self.group_elements.get(weighted.term.elem))
334319
.collect::<Result<Vec<_>, _>>()?;
335-
Ok(msm_pr(&weighted_coefficients, &elements))
320+
Ok(G::msm(&weighted_coefficients, &elements))
336321
})
337322
.collect()
338323
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use group::prime::PrimeGroup;
2+
3+
pub trait VariableMultiScalarMul {
4+
type Scalar;
5+
type Point;
6+
7+
fn msm(scalars: &[Self::Scalar], bases: &[Self::Point]) -> Self;
8+
}
9+
10+
impl<G: PrimeGroup> VariableMultiScalarMul for G {
11+
type Scalar = G::Scalar;
12+
type Point = G;
13+
14+
/// Perform a simple multi-scalar multiplication (MSM) over scalars and points.
15+
///
16+
/// Given slices of scalars and corresponding group elements (bases),
17+
/// returns the sum of each base multiplied by its scalar coefficient.
18+
///
19+
/// # Parameters
20+
/// - `scalars`: slice of scalar multipliers.
21+
/// - `bases`: slice of group elements to be multiplied by the scalars.
22+
///
23+
/// # Returns
24+
/// The group element result of the MSM.
25+
fn msm(scalars: &[Self::Scalar], bases: &[Self::Point]) -> Self {
26+
let mut acc = Self::identity();
27+
for (s, p) in scalars.iter().zip(bases.iter()) {
28+
acc += *p * s;
29+
}
30+
acc
31+
}
32+
}

src/tests/test_relations.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::fiat_shamir::Nizk;
88
use crate::linear_relation::CanonicalLinearRelation;
99
use crate::schnorr_protocol::SchnorrProof;
1010

11-
use crate::linear_relation::{msm_pr, LinearRelation};
11+
use crate::linear_relation::{LinearRelation, VariableMultiScalarMul};
1212

1313
/// LinearMap for knowledge of a discrete logarithm relative to a fixed basepoint.
1414
#[allow(non_snake_case)]
@@ -178,8 +178,8 @@ pub fn pedersen_commitment_dleq<G: PrimeGroup, R: RngCore>(
178178
let witness = [G::Scalar::random(&mut *rng), G::Scalar::random(&mut *rng)];
179179
let mut relation = LinearRelation::new();
180180

181-
let X = msm_pr::<G>(&witness, &[generators[0], generators[1]]);
182-
let Y = msm_pr::<G>(&witness, &[generators[2], generators[3]]);
181+
let X = G::msm(&witness, &[generators[0], generators[1]]);
182+
let Y = G::msm(&witness, &[generators[2], generators[3]]);
183183

184184
let [var_x, var_r] = relation.allocate_scalars();
185185

0 commit comments

Comments
 (0)