use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::scalar::Scalar;
use crate::error::{Error, Result};
use crate::sigma::{MultiScalarResponse, PointCommitment, ScalarChallenge, SigmaProtocol};
use crate::utils::{random_scalar, scalar_from_state};
#[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 r_v = random_scalar();
let r_r = random_scalar();
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 r_v = scalar_from_state(&state[0..32])?;
let r_r = scalar_from_state(&state[32..64])?;
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)
}
}
}