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}