use ark_ec::CurveGroup;
use rand::thread_rng;
use sha3::{Digest, Sha3_256};
use crate::{
algebra::{CurvePoint, CurvePointResult, Scalar, ScalarResult},
fabric::ResultValue,
};
pub(crate) struct PedersenCommitment<C: CurveGroup> {
pub(crate) value: Scalar<C>,
pub(crate) blinder: Scalar<C>,
pub(crate) commitment: CurvePoint<C>,
}
impl<C: CurveGroup> PedersenCommitment<C> {
pub(crate) fn verify(&self) -> bool {
let generator = CurvePoint::generator();
let commitment = generator * self.value + generator * self.blinder;
commitment == self.commitment
}
}
pub(crate) struct PedersenCommitmentResult<C: CurveGroup> {
pub(crate) value: ScalarResult<C>,
pub(crate) blinder: Scalar<C>,
pub(crate) commitment: CurvePointResult<C>,
}
impl<C: CurveGroup> PedersenCommitmentResult<C> {
pub(crate) fn commit(value: ScalarResult<C>) -> PedersenCommitmentResult<C> {
let mut rng = thread_rng();
let blinder = Scalar::random(&mut rng);
let generator = CurvePoint::generator();
let commitment = generator * &value + generator * blinder;
PedersenCommitmentResult {
value,
blinder,
commitment,
}
}
}
pub(crate) struct HashCommitment<C: CurveGroup> {
pub(crate) value: CurvePoint<C>,
pub(crate) blinder: Scalar<C>,
pub(crate) commitment: Scalar<C>,
}
impl<C: CurveGroup> HashCommitment<C> {
pub(crate) fn verify(&self) -> bool {
let mut bytes = self.value.to_bytes();
bytes.append(&mut self.blinder.to_bytes_be());
let mut hasher = Sha3_256::new();
hasher.update(bytes);
let out_bytes = hasher.finalize();
let out = Scalar::from_be_bytes_mod_order(out_bytes.as_slice());
out == self.commitment
}
}
pub(crate) struct HashCommitmentResult<C: CurveGroup> {
pub(crate) value: CurvePointResult<C>,
pub(crate) blinder: Scalar<C>,
pub(crate) commitment: ScalarResult<C>,
}
impl<C: CurveGroup> HashCommitmentResult<C> {
pub(crate) fn commit(value: CurvePointResult<C>) -> HashCommitmentResult<C> {
let mut rng = thread_rng();
let blinder = Scalar::random(&mut rng);
let comm = value.fabric.new_gate_op(vec![value.id], move |mut args| {
let value: CurvePoint<C> = args.remove(0).into();
let mut bytes = value.to_bytes();
bytes.append(&mut blinder.to_bytes_be());
let mut hasher = Sha3_256::new();
hasher.update(bytes);
let out_bytes = hasher.finalize();
let out = Scalar::from_be_bytes_mod_order(out_bytes.as_slice());
ResultValue::Scalar(out)
});
HashCommitmentResult {
value,
blinder,
commitment: comm,
}
}
}