sigma_protocols/protocols/
pedersen.rs1use curve25519_dalek::ristretto::RistrettoPoint;
7use curve25519_dalek::scalar::Scalar;
8use rand::rngs::OsRng;
9use rand::TryRngCore;
10
11use crate::error::{Error, Result};
12use crate::sigma::{MultiScalarResponse, PointCommitment, ScalarChallenge, SigmaProtocol};
13
14#[derive(Clone, Debug)]
18pub struct PedersenStatement {
19 pub g: RistrettoPoint,
20 pub h: RistrettoPoint,
21 pub commitment: RistrettoPoint,
22}
23
24#[derive(Clone, Debug)]
28pub struct PedersenWitness {
29 pub value: Scalar,
30 pub randomness: Scalar,
31}
32
33pub struct PedersenProof;
37
38impl SigmaProtocol for PedersenProof {
39 type Statement = PedersenStatement;
40 type Witness = PedersenWitness;
41 type Commitment = PointCommitment;
42 type Challenge = ScalarChallenge;
43 type Response = MultiScalarResponse;
44
45 fn prover_commit(
46 statement: &Self::Statement,
47 _witness: &Self::Witness,
48 ) -> (Self::Commitment, Vec<u8>) {
49 let mut r_v_bytes = [0u8; 32];
50 OsRng
51 .try_fill_bytes(&mut r_v_bytes)
52 .expect("Failed to generate random bytes");
53 let r_v = Scalar::from_bytes_mod_order(r_v_bytes);
54 let mut r_r_bytes = [0u8; 32];
55 OsRng
56 .try_fill_bytes(&mut r_r_bytes)
57 .expect("Failed to generate random bytes");
58 let r_r = Scalar::from_bytes_mod_order(r_r_bytes);
59
60 let commitment = r_v * statement.g + r_r * statement.h;
61
62 let mut state = Vec::with_capacity(64);
63 state.extend_from_slice(&r_v.to_bytes());
64 state.extend_from_slice(&r_r.to_bytes());
65
66 (PointCommitment(commitment), state)
67 }
68
69 fn prover_response(
70 _statement: &Self::Statement,
71 witness: &Self::Witness,
72 state: &[u8],
73 challenge: &Self::Challenge,
74 ) -> Result<Self::Response> {
75 if state.len() != 64 {
76 return Err(Error::InvalidProof);
77 }
78
79 let mut r_v_bytes = [0u8; 32];
80 let mut r_r_bytes = [0u8; 32];
81 r_v_bytes.copy_from_slice(&state[0..32]);
82 r_r_bytes.copy_from_slice(&state[32..64]);
83
84 let r_v_option = Scalar::from_canonical_bytes(r_v_bytes);
85 let r_r_option = Scalar::from_canonical_bytes(r_r_bytes);
86
87 let r_v = if r_v_option.is_some().unwrap_u8() == 1 {
88 r_v_option.unwrap()
89 } else {
90 return Err(Error::InvalidScalar);
91 };
92
93 let r_r = if r_r_option.is_some().unwrap_u8() == 1 {
94 r_r_option.unwrap()
95 } else {
96 return Err(Error::InvalidScalar);
97 };
98
99 let s_v = r_v + challenge.0 * witness.value;
100 let s_r = r_r + challenge.0 * witness.randomness;
101
102 Ok(MultiScalarResponse(vec![s_v, s_r]))
103 }
104
105 fn verifier(
106 statement: &Self::Statement,
107 commitment: &Self::Commitment,
108 challenge: &Self::Challenge,
109 response: &Self::Response,
110 ) -> Result<()> {
111 if response.0.len() != 2 {
112 return Err(Error::InvalidResponse);
113 }
114
115 let s_v = response.0[0];
116 let s_r = response.0[1];
117
118 let lhs = s_v * statement.g + s_r * statement.h;
119
120 let rhs = commitment.0 + challenge.0 * statement.commitment;
121
122 if lhs == rhs {
123 Ok(())
124 } else {
125 Err(Error::InvalidProof)
126 }
127 }
128}