sigma_protocols/protocols/
pedersen.rs

1//! Pedersen commitment opening proof.
2//!
3//! Proves knowledge of the opening (value and randomness) of a Pedersen commitment.
4//! Specifically, proves knowledge of (v, r) such that C = v * G + r * H.
5
6use curve25519_dalek::ristretto::RistrettoPoint;
7use curve25519_dalek::scalar::Scalar;
8
9use crate::error::{Error, Result};
10use crate::sigma::{MultiScalarResponse, PointCommitment, ScalarChallenge, SigmaProtocol};
11use crate::utils::{random_scalar, scalar_from_state};
12
13/// Public statement for Pedersen commitment proof.
14///
15/// Contains the two base points and the commitment.
16#[derive(Clone, Debug)]
17pub struct PedersenStatement {
18    pub g: RistrettoPoint,
19    pub h: RistrettoPoint,
20    pub commitment: RistrettoPoint,
21}
22
23/// Private witness for Pedersen commitment proof.
24///
25/// Contains the committed value and the randomness used.
26#[derive(Clone, Debug)]
27pub struct PedersenWitness {
28    pub value: Scalar,
29    pub randomness: Scalar,
30}
31
32/// Pedersen commitment opening proof implementation.
33///
34/// Proves knowledge of (v, r) such that C = v * G + r * H.
35pub struct PedersenProof;
36
37impl SigmaProtocol for PedersenProof {
38    type Statement = PedersenStatement;
39    type Witness = PedersenWitness;
40    type Commitment = PointCommitment;
41    type Challenge = ScalarChallenge;
42    type Response = MultiScalarResponse;
43
44    fn prover_commit(
45        statement: &Self::Statement,
46        _witness: &Self::Witness,
47    ) -> (Self::Commitment, Vec<u8>) {
48        let r_v = random_scalar();
49        let r_r = random_scalar();
50        let commitment = r_v * statement.g + r_r * statement.h;
51
52        let mut state = Vec::with_capacity(64);
53        state.extend_from_slice(&r_v.to_bytes());
54        state.extend_from_slice(&r_r.to_bytes());
55
56        (PointCommitment(commitment), state)
57    }
58
59    fn prover_response(
60        _statement: &Self::Statement,
61        witness: &Self::Witness,
62        state: &[u8],
63        challenge: &Self::Challenge,
64    ) -> Result<Self::Response> {
65        if state.len() != 64 {
66            return Err(Error::InvalidProof);
67        }
68
69        let r_v = scalar_from_state(&state[0..32])?;
70        let r_r = scalar_from_state(&state[32..64])?;
71
72        let s_v = r_v + challenge.0 * witness.value;
73        let s_r = r_r + challenge.0 * witness.randomness;
74
75        Ok(MultiScalarResponse(vec![s_v, s_r]))
76    }
77
78    fn verifier(
79        statement: &Self::Statement,
80        commitment: &Self::Commitment,
81        challenge: &Self::Challenge,
82        response: &Self::Response,
83    ) -> Result<()> {
84        if response.0.len() != 2 {
85            return Err(Error::InvalidResponse);
86        }
87
88        let s_v = response.0[0];
89        let s_r = response.0[1];
90
91        let lhs = s_v * statement.g + s_r * statement.h;
92
93        let rhs = commitment.0 + challenge.0 * statement.commitment;
94
95        if lhs == rhs {
96            Ok(())
97        } else {
98            Err(Error::InvalidProof)
99        }
100    }
101}