use crate::error::{Error, Result};
use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};
use curve25519_dalek::scalar::Scalar;
pub trait Commitment: Clone + Send + Sync {
fn to_bytes(&self) -> Vec<u8>;
fn from_bytes(bytes: &[u8]) -> Result<Self>
where
Self: Sized;
}
pub trait Challenge: Clone + Send + Sync {
fn to_bytes(&self) -> Vec<u8>;
fn from_bytes(bytes: &[u8]) -> Result<Self>
where
Self: Sized;
}
pub trait Response: Clone + Send + Sync {
fn to_bytes(&self) -> Vec<u8>;
fn from_bytes(bytes: &[u8]) -> Result<Self>
where
Self: Sized;
}
pub trait SigmaProtocol {
type Statement: Clone + Send + Sync;
type Witness: Clone + Send + Sync;
type Commitment: Commitment;
type Challenge: Challenge;
type Response: Response;
fn prover_commit(
statement: &Self::Statement,
witness: &Self::Witness,
) -> (Self::Commitment, Vec<u8>);
fn prover_response(
statement: &Self::Statement,
witness: &Self::Witness,
state: &[u8],
challenge: &Self::Challenge,
) -> Result<Self::Response>;
fn verifier(
statement: &Self::Statement,
commitment: &Self::Commitment,
challenge: &Self::Challenge,
response: &Self::Response,
) -> Result<()>;
}
fn scalar_from_bytes(bytes: &[u8]) -> Result<Scalar> {
if bytes.len() != 32 {
return Err(Error::InvalidScalar);
}
let mut array = [0u8; 32];
array.copy_from_slice(bytes);
Scalar::from_canonical_bytes(array)
.into_option()
.ok_or(Error::InvalidScalar)
}
fn point_from_bytes(bytes: &[u8]) -> Result<RistrettoPoint> {
if bytes.len() != 32 {
return Err(Error::InvalidPoint);
}
let mut array = [0u8; 32];
array.copy_from_slice(bytes);
CompressedRistretto::from_slice(&array)
.map_err(|_| Error::InvalidPoint)?
.decompress()
.ok_or(Error::InvalidPoint)
}
#[derive(Clone, Debug)]
pub struct ScalarChallenge(pub Scalar);
impl Challenge for ScalarChallenge {
fn to_bytes(&self) -> Vec<u8> {
self.0.to_bytes().to_vec()
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
if bytes.len() != 32 {
return Err(Error::InvalidChallenge);
}
let mut array = [0u8; 32];
array.copy_from_slice(bytes);
Ok(ScalarChallenge(Scalar::from_bytes_mod_order(array)))
}
}
#[derive(Clone, Debug)]
pub struct PointCommitment(pub RistrettoPoint);
impl Commitment for PointCommitment {
fn to_bytes(&self) -> Vec<u8> {
self.0.compress().to_bytes().to_vec()
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
point_from_bytes(bytes)
.map(PointCommitment)
.map_err(|_| Error::InvalidCommitment)
}
}
#[derive(Clone, Debug)]
pub struct ScalarResponse(pub Scalar);
impl Response for ScalarResponse {
fn to_bytes(&self) -> Vec<u8> {
self.0.to_bytes().to_vec()
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
scalar_from_bytes(bytes)
.map(ScalarResponse)
.map_err(|_| Error::InvalidResponse)
}
}
#[derive(Clone, Debug)]
pub struct MultiPointCommitment(pub Vec<RistrettoPoint>);
impl Commitment for MultiPointCommitment {
fn to_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::with_capacity(self.0.len() * 32 + 4);
bytes.extend_from_slice(&(self.0.len() as u32).to_le_bytes());
for point in &self.0 {
bytes.extend_from_slice(&point.compress().to_bytes());
}
bytes
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
if bytes.len() < 4 {
return Err(Error::InvalidCommitment);
}
let len = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]) as usize;
if bytes.len() != 4 + len * 32 {
return Err(Error::InvalidCommitment);
}
let mut points = Vec::with_capacity(len);
for i in 0..len {
let start = 4 + i * 32;
let end = start + 32;
points.push(point_from_bytes(&bytes[start..end])?)
}
Ok(MultiPointCommitment(points))
}
}
#[derive(Clone, Debug)]
pub struct MultiScalarResponse(pub Vec<Scalar>);
impl Response for MultiScalarResponse {
fn to_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::with_capacity(self.0.len() * 32 + 4);
bytes.extend_from_slice(&(self.0.len() as u32).to_le_bytes());
for scalar in &self.0 {
bytes.extend_from_slice(&scalar.to_bytes());
}
bytes
}
fn from_bytes(bytes: &[u8]) -> Result<Self> {
if bytes.len() < 4 {
return Err(Error::InvalidResponse);
}
let len = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]) as usize;
if bytes.len() != 4 + len * 32 {
return Err(Error::InvalidResponse);
}
let mut scalars = Vec::with_capacity(len);
for i in 0..len {
let start = 4 + i * 32;
let end = start + 32;
scalars.push(scalar_from_bytes(&bytes[start..end])?)
}
Ok(MultiScalarResponse(scalars))
}
}