Skip to main content

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