use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::scalar::Scalar;
use rand::rngs::OsRng;
use rand::TryRngCore;
use crate::error::{Error, Result};
use crate::sigma::{MultiScalarResponse, PointCommitment, ScalarChallenge, SigmaProtocol};
#[derive(Clone, Debug)]
pub struct PedersenStatement {
pub g: RistrettoPoint,
pub h: RistrettoPoint,
pub commitment: RistrettoPoint,
}
#[derive(Clone, Debug)]
pub struct PedersenWitness {
pub value: Scalar,
pub randomness: Scalar,
}
pub struct PedersenProof;
impl SigmaProtocol for PedersenProof {
type Statement = PedersenStatement;
type Witness = PedersenWitness;
type Commitment = PointCommitment;
type Challenge = ScalarChallenge;
type Response = MultiScalarResponse;
fn prover_commit(
statement: &Self::Statement,
_witness: &Self::Witness,
) -> (Self::Commitment, Vec<u8>) {
let mut r_v_bytes = [0u8; 32];
OsRng
.try_fill_bytes(&mut r_v_bytes)
.expect("Failed to generate random bytes");
let r_v = Scalar::from_bytes_mod_order(r_v_bytes);
let mut r_r_bytes = [0u8; 32];
OsRng
.try_fill_bytes(&mut r_r_bytes)
.expect("Failed to generate random bytes");
let r_r = Scalar::from_bytes_mod_order(r_r_bytes);
let commitment = r_v * statement.g + r_r * statement.h;
let mut state = Vec::with_capacity(64);
state.extend_from_slice(&r_v.to_bytes());
state.extend_from_slice(&r_r.to_bytes());
(PointCommitment(commitment), state)
}
fn prover_response(
_statement: &Self::Statement,
witness: &Self::Witness,
state: &[u8],
challenge: &Self::Challenge,
) -> Result<Self::Response> {
if state.len() != 64 {
return Err(Error::InvalidProof);
}
let mut r_v_bytes = [0u8; 32];
let mut r_r_bytes = [0u8; 32];
r_v_bytes.copy_from_slice(&state[0..32]);
r_r_bytes.copy_from_slice(&state[32..64]);
let r_v_option = Scalar::from_canonical_bytes(r_v_bytes);
let r_r_option = Scalar::from_canonical_bytes(r_r_bytes);
let r_v = if r_v_option.is_some().unwrap_u8() == 1 {
r_v_option.unwrap()
} else {
return Err(Error::InvalidScalar);
};
let r_r = if r_r_option.is_some().unwrap_u8() == 1 {
r_r_option.unwrap()
} else {
return Err(Error::InvalidScalar);
};
let s_v = r_v + challenge.0 * witness.value;
let s_r = r_r + challenge.0 * witness.randomness;
Ok(MultiScalarResponse(vec![s_v, s_r]))
}
fn verifier(
statement: &Self::Statement,
commitment: &Self::Commitment,
challenge: &Self::Challenge,
response: &Self::Response,
) -> Result<()> {
if response.0.len() != 2 {
return Err(Error::InvalidResponse);
}
let s_v = response.0[0];
let s_r = response.0[1];
let lhs = s_v * statement.g + s_r * statement.h;
let rhs = commitment.0 + challenge.0 * statement.commitment;
if lhs == rhs {
Ok(())
} else {
Err(Error::InvalidProof)
}
}
}