use crate::constants::BASEPOINT;
use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};
use curve25519_dalek::scalar::Scalar;
use sha2::Sha512;
use std::collections::HashSet;
#[derive(Debug, Clone)]
pub struct PublicSet(pub Vec<RistrettoPoint>);
impl PublicSet {
pub fn len(&self) -> usize {
self.0.len()
}
pub fn duplicates_exist(&self) -> bool {
let compressed_points: Vec<CompressedRistretto> =
self.0.iter().map(|point| point.compress()).collect();
let hashable_slice: Vec<&[u8; 32]> =
compressed_points.iter().map(|cp| cp.as_bytes()).collect();
let uniques: HashSet<_> = hashable_slice.iter().collect();
self.0.len() != uniques.len()
}
pub fn compress(&self) -> Vec<CompressedRistretto> {
self.0.iter().map(|point| point.compress()).collect()
}
}
#[derive(Debug, Clone)]
pub struct PrivateSet(pub(crate) Vec<Scalar>);
impl PrivateSet {
pub fn new(scalars: Vec<Scalar>) -> Self {
PrivateSet(scalars)
}
pub fn to_public_set(&self) -> PublicSet {
let public_keys = self
.0
.iter()
.map(|&x| x * BASEPOINT)
.collect::<Vec<RistrettoPoint>>();
PublicSet(public_keys)
}
pub fn compute_key_images(&self, public_set: &PublicSet) -> Vec<RistrettoPoint> {
assert_eq!(self.len(), public_set.len());
let num_public_keys = public_set.len();
let mut key_images: Vec<RistrettoPoint> = Vec::with_capacity(num_public_keys);
for i in 0..num_public_keys {
let public_key_i = public_set.0[i].compress();
let private_key_i = self.0[i];
let hashed_public_key =
RistrettoPoint::hash_from_bytes::<Sha512>(public_key_i.as_bytes());
let key_image = private_key_i * hashed_public_key;
key_images.push(key_image);
}
key_images
}
pub fn len(&self) -> usize {
self.0.len()
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::tests_helper::*;
#[test]
fn private_set_to_public_set() {
let private_set = generate_private_set(10);
let public_set = private_set.to_public_set();
assert_eq!(private_set.len(), public_set.len());
for i in 0..private_set.len() {
match (private_set.0.get(i), public_set.0.get(i)) {
(Some(private_key), Some(expected_public_key)) => {
let public_key = private_key * &BASEPOINT;
assert_eq!(public_key, *expected_public_key);
}
_ => panic!("could not get the private/public key at index {} ", i),
}
}
}
#[test]
fn check_duplicates_exist() {
let private_set = generate_private_set(10);
let mut public_set = private_set.to_public_set();
let dup_exists = public_set.duplicates_exist();
assert!(!dup_exists);
let last_element = public_set.0.last().unwrap().clone();
public_set.0[0] = last_element;
let dup_exists = public_set.duplicates_exist();
assert!(dup_exists);
}
}