use crate::{
core::global_value::{curve_value::CurveValue, value::FieldValue},
traits::Reveal,
utils::field::ScalarField,
};
use std::{
ops::{Add, Mul, Sub},
sync::LazyLock,
};
use zk_elgamal_proof::encryption::pedersen::H;
pub struct Pedersen;
impl Pedersen {
#[allow(clippy::new_ret_no_self)]
pub fn new(amount: FieldValue<ScalarField>) -> (PedersenCommitment, PedersenOpening) {
let opening = PedersenOpening::new_rand();
let commitment = Pedersen::with(amount, &opening);
(commitment, opening)
}
pub fn with(amount: FieldValue<ScalarField>, opening: &PedersenOpening) -> PedersenCommitment {
let x = amount;
let r = opening.get_scalar();
PedersenCommitment(
CurveValue::multiscalar_mul(
vec![x, *r],
vec![
CurveValue::generator(),
CurveValue::from(*LazyLock::force(&H)),
],
)
.reveal(),
)
}
pub fn encode(amount: FieldValue<ScalarField>) -> PedersenCommitment {
PedersenCommitment((amount * CurveValue::generator()).reveal())
}
}
#[derive(Clone, Debug)]
pub struct PedersenOpening(FieldValue<ScalarField>);
impl PedersenOpening {
pub fn new(scalar: FieldValue<ScalarField>) -> Self {
assert!(!scalar.is_plaintext());
Self(scalar)
}
pub fn new_rand() -> Self {
PedersenOpening(FieldValue::<ScalarField>::random())
}
pub fn get_scalar(&self) -> &FieldValue<ScalarField> {
&self.0
}
}
impl Add<&PedersenOpening> for &PedersenOpening {
type Output = PedersenOpening;
fn add(self, opening: &PedersenOpening) -> PedersenOpening {
PedersenOpening(self.0 + opening.0)
}
}
impl Mul<FieldValue<ScalarField>> for &PedersenOpening {
type Output = PedersenOpening;
fn mul(self, scalar: FieldValue<ScalarField>) -> PedersenOpening {
PedersenOpening(self.0 * scalar)
}
}
#[derive(Clone, Copy, Debug)]
pub struct PedersenCommitment(CurveValue);
impl PedersenCommitment {
pub fn new(point: CurveValue) -> Self {
assert!(point.is_plaintext());
Self(point)
}
pub fn get_point(&self) -> &CurveValue {
&self.0
}
}
impl Add for PedersenCommitment {
type Output = PedersenCommitment;
fn add(self, commitment: PedersenCommitment) -> Self::Output {
PedersenCommitment(self.0 + commitment.0)
}
}
impl Sub for PedersenCommitment {
type Output = PedersenCommitment;
fn sub(self, commitment: PedersenCommitment) -> Self::Output {
PedersenCommitment(self.0 - commitment.0)
}
}
impl Mul<PedersenCommitment> for FieldValue<ScalarField> {
type Output = PedersenCommitment;
fn mul(self, rhs: PedersenCommitment) -> Self::Output {
PedersenCommitment(self * rhs.0)
}
}