Skip to main content

primitives/commitments/
pedersen.rs

1use rand::SeedableRng;
2
3use super::CommitmentScheme;
4use crate::{
5    algebra::elliptic_curve::{Curve, Point, ScalarAsExtension},
6    errors::PrimitiveError,
7    hashing::hash,
8    random::{BaseRng, CryptoRngCore, Random},
9};
10
11#[derive(Copy, Clone, Debug)]
12pub struct PedersenCommitment<C: Curve> {
13    pub g: Point<C>,
14    pub h: Point<C>,
15}
16
17impl<C: Curve> PedersenCommitment<C> {
18    // Create a new Pedersen commitment scheme by defining the two generators, using the curve's
19    // generator as the first generator (g) and the provided seed to derive the second generator
20    // (h). Use different seeds to instantiate separate sessions (e.g., with different SessionIds).
21    pub fn new<S: AsRef<[u8]>>(second_generator_seed: &S) -> Self {
22        let g = Point::generator();
23        let mut rng = BaseRng::from_seed(hash(&[second_generator_seed.as_ref()]).into());
24        let h = Point::random(&mut rng);
25        Self { g, h }
26    }
27}
28
29impl<C: Curve> CommitmentScheme<ScalarAsExtension<C>> for PedersenCommitment<C> {
30    type Commitment = Point<C>;
31    type Witness = ScalarAsExtension<C>;
32
33    fn commit<R: CryptoRngCore>(
34        &self,
35        input: &ScalarAsExtension<C>,
36        mut rng: R,
37    ) -> (Self::Commitment, Self::Witness) {
38        let witness = ScalarAsExtension::<C>::random(&mut rng);
39
40        let commitment = self.g * witness + self.h * input;
41        (commitment, witness)
42    }
43
44    fn open(
45        &self,
46        c: &Self::Commitment,
47        w: &Self::Witness,
48        input: &ScalarAsExtension<C>,
49    ) -> Result<(), PrimitiveError> {
50        let c_prime = self.g * w + self.h * input;
51        if *c == c_prime {
52            Ok(())
53        } else {
54            Err(PrimitiveError::WrongOpening(
55                format!("{c:?}"),
56                format!("{c_prime:?}"),
57            ))
58        }
59    }
60}