extern crate curve25519_dalek;
extern crate rand;
use rand::Rng;
use curve25519_dalek::{constants, ristretto::{multiscalar_mul, RistrettoPoint}, scalar::Scalar};
pub struct Commitment(RistrettoPoint);
pub struct CommitmentOpening(Scalar);
#[derive(Clone)]
pub struct VerifierPublicKey(RistrettoPoint);
pub struct CommitmentValue(Scalar);
pub struct Committer;
pub struct CommitVerifier {
pk: VerifierPublicKey,
commitment: Option<Commitment>,
}
impl CommitmentValue {
pub fn from_u64(x: u64) -> Self {
CommitmentValue(Scalar::from_u64(x))
}
}
impl CommitVerifier {
pub fn init<T: Rng>(mut rng: &mut T) -> (VerifierPublicKey, Self) {
let a = Scalar::random(&mut rng);
let G = &constants::RISTRETTO_BASEPOINT_POINT;
let H = a * G;
let pub_key = VerifierPublicKey(H);
(
pub_key.clone(),
CommitVerifier {
pk: pub_key,
commitment: None,
},
)
}
pub fn receive_commitment(&mut self, commitment: Commitment) {
self.commitment = Some(commitment);
}
pub fn verify(&self, val: &CommitmentValue, commitment_opening: &CommitmentOpening) -> bool {
if let Some(Commitment(C)) = self.commitment {
let VerifierPublicKey(H) = self.pk;
let G = &constants::RISTRETTO_BASEPOINT_POINT;
let &CommitmentOpening(r) = commitment_opening;
let &CommitmentValue(m) = val;
let C2 = multiscalar_mul(vec![r, m], vec![G, &H]);
C == C2
} else {
panic!("No commitment received");
}
}
}
impl Committer {
pub fn commit<T: Rng>(mut rng: &mut T, val: &CommitmentValue, pk: &VerifierPublicKey)
-> (Commitment, CommitmentOpening) {
let r = Scalar::random(&mut rng);
let &CommitmentValue(val_as_scalar) = val;
let G = &constants::RISTRETTO_BASEPOINT_POINT;
let &VerifierPublicKey(pub_key_point) = pk;
let C = multiscalar_mul(&[r, val_as_scalar], vec![G, &pub_key_point]);
(Commitment(C), CommitmentOpening(r))
}
}
#[cfg(test)]
mod test {
use super::*;
use rand::OsRng;
#[test]
fn good_commitment() {
let mut rng = OsRng::new().unwrap();
let val = CommitmentValue::from_u64(3);
let (verifier_pub_key, mut verifier) = CommitVerifier::init(&mut rng);
let (commitment, commitment_opening) = Committer::commit(&mut rng, &val, &verifier_pub_key);
verifier.receive_commitment(commitment);
let did_verify = verifier.verify(&val, &commitment_opening);
assert_eq!(did_verify, true);
}
#[test]
fn bad_commitment_opening() {
let mut rng = OsRng::new().unwrap();
let val = CommitmentValue::from_u64(3);
let (verifier_pub_key, mut verifier) = CommitVerifier::init(&mut rng);
let (commitment, _commitment_opening) = Committer::commit(&mut rng, &val, &verifier_pub_key);
verifier.receive_commitment(commitment);
let bad_commitment_opening = CommitmentOpening(Scalar::from_u64(4));
let did_verify = verifier.verify(&val, &bad_commitment_opening);
assert_eq!(did_verify, false);
}
#[test]
fn bad_commitment() {
let mut rng = OsRng::new().unwrap();
let val = CommitmentValue::from_u64(3);
let (verifier_pub_key, mut verifier) = CommitVerifier::init(&mut rng);
let (_commitment, commitment_opening) = Committer::commit(&mut rng, &val, &verifier_pub_key);
let bad_commitment = Commitment(Scalar::from_u64(2) * constants::RISTRETTO_BASEPOINT_POINT);
verifier.receive_commitment(bad_commitment);
let did_verify = verifier.verify(&val, &commitment_opening);
assert_eq!(did_verify, false);
}
}