sigma_rs/traits.rs
1//! Generic interface for 3-message Sigma protocols.
2//!
3//! This module defines the [`SigmaProtocol`] and [`SigmaProtocolSimulator`] traits,
4//! used to describe interactive zero-knowledge proofs of knowledge,
5//! such as Schnorr proofs, that follow the 3-message Sigma protocol structure.
6
7use crate::errors::Error;
8use rand::{CryptoRng, Rng};
9
10/// A trait defining the behavior of a generic Sigma protocol.
11///
12/// A Sigma protocol is a 3-message proof protocol where a prover can convince
13/// a verifier of knowledge of a witness for a given public statement
14/// without revealing the witness.
15///
16/// ## Associated Types
17/// - `Commitment`: The prover's initial commitment.
18/// - `ProverState`: The prover's internal state needed to compute a response.
19/// - `Response`: The prover's response to a verifier's challenge.
20/// - `Witness`: The prover's secret knowledge.
21/// - `Challenge`: The verifier's challenge value.
22///
23/// ## Minimal Implementation
24/// Types implementing [`SigmaProtocol`] must define:
25/// - `prover_commit` — Generates a commitment and internal state.
26/// - `prover_response` — Computes a response to a challenge.
27/// - `verifier` — Verifies a full transcript `(commitment, challenge, response)`.
28///
29/// ## Serialization
30/// Implementors must also provide methods for serialization and deserialization
31/// of each component of the proof.
32/// Required methods:
33/// - `serialize_commitment` / `deserialize_commitment`
34/// - `serialize_challenge` / `deserialize_challenge`
35/// - `serialize_response` / `deserialize_response`
36///
37/// These functions should encode/decode each component into/from a compact binary format.
38///
39/// ## Identification
40/// To allow transcript hash binding and protocol distinction,
41/// implementors must provide:
42/// - `protocol_identifier` — A fixed byte identifier of the protocol.
43/// - `instance_label` — A label specific to the instance being proven.
44pub trait SigmaProtocol {
45 type Commitment;
46 type ProverState;
47 type Response;
48 type Witness;
49 type Challenge;
50
51 /// First step of the protocol. Given the witness and RNG, this generates:
52 /// - A public commitment to send to the verifier.
53 /// - The internal state to use when computing the response.
54 fn prover_commit(
55 &self,
56 witness: &Self::Witness,
57 rng: &mut (impl Rng + CryptoRng),
58 ) -> Result<(Self::Commitment, Self::ProverState), Error>;
59
60 /// Computes the prover's response to a challenge based on the prover state.
61 fn prover_response(
62 &self,
63 state: Self::ProverState,
64 challenge: &Self::Challenge,
65 ) -> Result<Self::Response, Error>;
66
67 /// Final step of the protocol: checks that the commitment, challenge, and response form a valid transcript.
68 ///
69 /// Returns:
70 /// - `Ok(())` if the transcript is valid.
71 /// - `Err(())` otherwise.
72 fn verifier(
73 &self,
74 commitment: &Self::Commitment,
75 challenge: &Self::Challenge,
76 response: &Self::Response,
77 ) -> Result<(), Error>;
78
79 /// Serializes a commitment to bytes.
80 fn serialize_commitment(&self, commitment: &Self::Commitment) -> Vec<u8>;
81
82 /// Serializes a challenge to bytes.
83 fn serialize_challenge(&self, challenge: &Self::Challenge) -> Vec<u8>;
84
85 /// Serializes a response to bytes.
86 fn serialize_response(&self, response: &Self::Response) -> Vec<u8>;
87
88 /// Deserializes a commitment from bytes.
89 fn deserialize_commitment(&self, data: &[u8]) -> Result<Self::Commitment, Error>;
90
91 /// Deserializes a challenge from bytes.
92 fn deserialize_challenge(&self, data: &[u8]) -> Result<Self::Challenge, Error>;
93
94 /// Deserializes a response from bytes.
95 fn deserialize_response(&self, data: &[u8]) -> Result<Self::Response, Error>;
96
97 fn protocol_identifier(&self) -> impl AsRef<[u8]>;
98
99 fn instance_label(&self) -> impl AsRef<[u8]>;
100}
101
102type Transcript<P> = (
103 <P as SigmaProtocol>::Commitment,
104 <P as SigmaProtocol>::Challenge,
105 <P as SigmaProtocol>::Response,
106);
107
108/// A trait defining the behavior of a Sigma protocol for which simulation of transcripts is necessary.
109///
110/// Every Sigma protocol can be simulated, but in practice, this is primarily used
111/// for proving security properties (zero-knowledge, soundness, etc.).
112///
113/// Some protocols (e.g. OR compositions) require simulation capabilities during actual proof generation.
114///
115/// ## Minimal Implementation
116/// Types implementing [`SigmaProtocolSimulator`] must define:
117/// - `simulate_proof`
118/// - `simulate_transcript`
119#[allow(clippy::type_complexity)]
120pub trait SigmaProtocolSimulator: SigmaProtocol {
121 /// Generates a random response (e.g. for simulation or OR composition).
122 ///
123 /// Typically used to simulate a proof without a witness.
124 fn simulate_response<R: Rng + CryptoRng>(&self, rng: &mut R) -> Self::Response;
125
126 /// Simulates a commitment for which ('commitment', 'challenge', 'response') is a valid transcript.
127 ///
128 /// This function allows to omit commitment in compact proofs of the type ('challenge', 'response').
129 fn simulate_commitment(
130 &self,
131 challenge: &Self::Challenge,
132 response: &Self::Response,
133 ) -> Result<Self::Commitment, Error>;
134
135 /// Generates a full simulated proof transcript (commitment, challenge, response)
136 /// without requiring knowledge of a witness.
137 fn simulate_transcript<R: Rng + CryptoRng>(
138 &self,
139 rng: &mut R,
140 ) -> Result<Transcript<Self>, Error>;
141}