use rand::SeedableRng;
use subtle::ConstantTimeEq;
use super::CommitmentScheme;
use crate::{
algebra::elliptic_curve::{Curve, Point, ScalarAsExtension},
errors::PrimitiveError,
hashing::hash,
random::{BaseRng, CryptoRngCore, Random},
};
#[derive(Copy, Clone, Debug)]
pub struct PedersenCommitment<C: Curve> {
pub g: Point<C>,
pub h: Point<C>,
}
impl<C: Curve> PedersenCommitment<C> {
pub fn new<S: AsRef<[u8]>>(second_generator_seed: &S) -> Self {
let g = Point::generator();
let mut rng = BaseRng::from_seed(hash(&[second_generator_seed.as_ref()]).into());
let h = Point::random(&mut rng);
Self { g, h }
}
}
impl<C: Curve> CommitmentScheme<ScalarAsExtension<C>> for PedersenCommitment<C> {
type Commitment = Point<C>;
type Witness = ScalarAsExtension<C>;
fn commit<R: CryptoRngCore>(
&self,
input: &ScalarAsExtension<C>,
mut rng: R,
) -> (Self::Commitment, Self::Witness) {
let witness = ScalarAsExtension::<C>::random(&mut rng);
let commitment = self.g * witness + self.h * input;
(commitment, witness)
}
fn open(
&self,
c: &Self::Commitment,
w: &Self::Witness,
input: &ScalarAsExtension<C>,
) -> Result<(), PrimitiveError> {
let c_prime = self.g * w + self.h * input;
if bool::from(c.ct_eq(&c_prime)) {
Ok(())
} else {
Err(PrimitiveError::WrongOpening(
format!("{c:?}"),
format!("{c_prime:?}"),
))
}
}
}