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}