Skip to content

Commit dfb2927

Browse files
committed
Codec: more appropriate and explicit name for the API to provide a deterministic challenge for the Fiat-Shamir transform
1 parent 18e8db6 commit dfb2927

File tree

13 files changed

+91
-90
lines changed

13 files changed

+91
-90
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "sigma-rs"
33
version = "0.1.0"
44
authors = [
5-
"nougzarm <[email protected]>",
5+
"Nugzari Uzoevi <[email protected]>",
66
"Michele Orrù <[email protected]>",
77
"Lénaïck Gouriou <[email protected]>"
88
]

src/transcript/keccak_transcript.rs renamed to src/codec/keccak_codec.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::transcript::r#trait::{DuplexSpongeInterface, TranscriptCodec};
1+
use crate::codec::r#trait::{DuplexSpongeInterface, Codec};
22
use crate::GroupSerialisation;
33
use ff::PrimeField;
44
use group::{Group, GroupEncoding};
@@ -160,7 +160,7 @@ where
160160
_marker: core::marker::PhantomData<G>,
161161
}
162162

163-
impl<G, H> TranscriptCodec<G> for ByteSchnorrCodec<G, H>
163+
impl<G, H> Codec<G> for ByteSchnorrCodec<G, H>
164164
where
165165
G: Group + GroupEncoding + GroupSerialisation,
166166
H: DuplexSpongeInterface,

src/codec/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
pub mod keccak_codec;
2+
pub mod shake_codec;
3+
pub mod r#trait;
4+
5+
pub use keccak_codec::{ByteSchnorrCodec, KeccakDuplexSponge};
6+
pub use r#trait::Codec;
7+
pub use shake_codec::ShakeCodec;

src/transcript/shake_transcript.rs renamed to src/codec/shake_codec.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
//! Implementation of a Fiat-Shamir transcript codec using SHAKE128 (Keccak)
1+
//! Implementation of a Fiat-Shamir codec using SHAKE128
22
//!
3-
//! This module defines `KeccakTranscript`, a concrete implementation of the `TranscriptCodec`
3+
//! This module defines `ShakeCodec`, a concrete implementation of the `Codec`
44
//! trait. It uses the SHAKE128 extendable output function (XOF) from the Keccak family
55
//! to generate Fiat-Shamir challenges for Sigma protocols.
66
//!
7-
//! It allows commitments (group elements) to be absorbed into a transcript,
7+
//! It allows commitments (group elements) to be absorbed into a codec,
88
//! and produces scalar challenges by squeezing bytes from the hash state.
99
//!
1010
//! # Usage
11-
//! - The prover and verifier absorb the same messages into identical `KeccakTranscript` instances.
12-
//! - The prover and the verifier then squeeze the hash to generate a challenge scalar for the protocol. The verifier can check that the prover used the challenge output by the transcript because he owns an identical transcript.
11+
//! - The prover and verifier absorb the same messages into identical `ShakeCodec` instances.
12+
//! - The prover and the verifier then squeeze the hash to generate a challenge scalar for the protocol. The verifier can check that the prover used the challenge output by the codec because he owns an identical codec.
1313
1414
use ff::PrimeField;
1515
use group::{Group, GroupEncoding};
@@ -18,28 +18,28 @@ use sha3::{
1818
Shake128,
1919
};
2020

21-
use crate::transcript::r#trait::TranscriptCodec;
21+
use crate::codec::r#trait::Codec;
2222

23-
/// A Fiat-Shamir transcript over a group `G`, using SHAKE128 (Keccak).
23+
/// A Fiat-Shamir codec over a group `G`, using SHAKE128.
2424
///
2525
/// This struct manages the state of the hash function and produces
2626
/// deterministic, random-looking scalars for use in Sigma protocols.
2727
///
28-
/// The transcript is initialized with a domain separator and absorbs serialized
28+
/// The codec is initialized with a domain separator and absorbs serialized
2929
/// group elements. It outputs challenges compatible with the group’s scalar field.
30-
pub struct ShakeTranscript<G: Group> {
30+
pub struct ShakeCodec<G: Group> {
3131
/// Internal SHAKE128 hasher state.
3232
hasher: Shake128,
33-
/// Marker to bind this transcript to a specific group `G`.
33+
/// Marker to bind this codec to a specific group `G`.
3434
_marker: core::marker::PhantomData<G>,
3535
}
3636

37-
impl<G> TranscriptCodec<G> for ShakeTranscript<G>
37+
impl<G> Codec<G> for ShakeCodec<G>
3838
where
3939
G: Group + GroupEncoding,
4040
G::Scalar: PrimeField,
4141
{
42-
/// Initializes the transcript with a domain separation label, to avoid cross-protocol collisions.
42+
/// Initializes the codec with a domain separation label, to avoid cross-protocol collisions.
4343
fn new(domain_sep: &[u8]) -> Self {
4444
let mut hasher = Shake128::default();
4545
hasher.update(domain_sep);
@@ -49,15 +49,15 @@ where
4949
}
5050
}
5151

52-
/// Absorbs a slice of group elements into the transcript. Each element is serialized and fed into the hasher.
52+
/// Absorbs a slice of group elements into the codec. Each element is serialized and fed into the hasher.
5353
fn prover_message(&mut self, elems: &[G]) -> &mut Self {
5454
for elem in elems {
5555
self.hasher.update(elem.to_bytes().as_ref());
5656
}
5757
self
5858
}
5959

60-
/// Produce a random-looking challenge scalar from the transcript.
60+
/// Produce a random-looking challenge scalar from the codec.
6161
///
6262
/// The method reads from the finalized SHAKE128 state until it finds
6363
/// a valid scalar (i.e., one within the field).

src/codec/trait.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//! Codec Trait
2+
//!
3+
//! This module defines the `Codec` trait, a generic interface to manage codecs of a protocol execution.
4+
5+
use group::Group;
6+
7+
pub trait DuplexSpongeInterface {
8+
fn new(iv: &[u8]) -> Self;
9+
10+
fn absorb(&mut self, input: &[u8]);
11+
12+
fn squeeze(&mut self, length: usize) -> Vec<u8>;
13+
}
14+
15+
/// A trait defining the behavior of a domain-separated codec hashing, which is typically used for Sigma Protocols.
16+
///
17+
/// A domain-separated hashing codec is a codec, identified by a domain, which is incremented with successive messages ("absorb"). The codec can then output a bit stream of any length, which is typically used to generate a challenge unique to the given codec ("squeeze"). (See Sponge Construction).
18+
///
19+
/// The output is deterministic for a given set of input. Thus, both Prover and Verifier can generate the codec on their sides and ensure the same inputs have been used in both side of the protocol.
20+
///
21+
/// ## Minimal Implementation
22+
/// Types implementing `Codec` must define:
23+
/// - `new`
24+
/// - `prover_message`
25+
/// - `verifier_challenge`
26+
pub trait Codec<G: Group> {
27+
/// Generates an empty codec that can be identified by a domain separator.
28+
fn new(domain_sep: &[u8]) -> Self;
29+
30+
/// Absorbs a list of group elements (e.g., commitments) into the codec.
31+
fn prover_message(&mut self, elems: &[G]) -> &mut Self
32+
where
33+
Self: Sized;
34+
35+
/// Produces a scalar that can be used as a challenge from the codec.
36+
fn verifier_challenge(&mut self) -> G::Scalar;
37+
}

src/fiat_shamir.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
//! Fiat-Shamir transformation for Sigma protocols.
22
//!
33
//! This module defines `NISigmaProtocol`, a generic non-interactive Sigma protocol wrapper,
4-
//! based on applying the Fiat-Shamir heuristic using a transcript codec.
4+
//! based on applying the Fiat-Shamir heuristic using a codec.
55
//!
66
//! It transforms an interactive Sigma protocol into a non-interactive one,
77
//! by deriving challenges deterministically from previous protocol messages
8-
//! via a cryptographic sponge function (transcript).
8+
//! via a cryptographic sponge function (Codec).
99
//!
1010
//! # Usage
1111
//! This struct is generic over:
1212
//! - `P`: the underlying Sigma protocol (`SigmaProtocol` trait).
13-
//! - `C`: the transcript codec (`TranscriptCodec` trait).
13+
//! - `C`: the codec (`Codec` trait).
1414
//! - `G`: the group used for commitments and operations (`Group` trait).
1515
1616
use crate::{
17-
transcript::TranscriptCodec,
17+
codec::Codec,
1818
SigmaProtocol,
1919
ProofError
2020
};
@@ -25,24 +25,24 @@ use rand::{CryptoRng, RngCore};
2525
/// A Fiat-Shamir transformation of a Sigma protocol into a non-interactive proof.
2626
///
2727
/// `NISigmaProtocol` wraps an interactive Sigma protocol `P`
28-
/// and a hash-based transcript `C`, to produce non-interactive proofs.
28+
/// and a hash-based codec `C`, to produce non-interactive proofs.
2929
///
30-
/// It manages the domain separation, transcript reset,
30+
/// It manages the domain separation, codec reset,
3131
/// proof generation, and proof verification.
3232
///
3333
/// # Type Parameters
3434
/// - `P`: the Sigma protocol implementation.
35-
/// - `C`: the transcript codec used for Fiat-Shamir.
35+
/// - `C`: the codec used for Fiat-Shamir.
3636
/// - `G`: the group on which the protocol operates.
3737
pub struct NISigmaProtocol<P, C, G>
3838
where
3939
G: Group,
4040
P: SigmaProtocol<Commitment = Vec<G>, Challenge = <G as Group>::Scalar>,
41-
C: TranscriptCodec<G>,
41+
C: Codec<G>,
4242
{
4343
/// Domain separation string for the Fiat-Shamir transform.
4444
domain_sep: Vec<u8>,
45-
/// Current transcript state.
45+
/// Current codec state.
4646
hash_state: C,
4747
/// Underlying Sigma protocol.
4848
sigmap: P,
@@ -52,7 +52,7 @@ impl<P, C, G> NISigmaProtocol<P, C, G>
5252
where
5353
G: Group,
5454
P: SigmaProtocol<Commitment = Vec<G>, Challenge = <G as Group>::Scalar>,
55-
C: TranscriptCodec<G>,
55+
C: Codec<G>,
5656
{
5757
/// Creates a new non-interactive Sigma protocol, identified by a domain separator (usually fixed per protocol instantiation), and an initialized Sigma protocol instance.
5858
pub fn new(iv: &[u8], instance: P) -> Self {

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@ pub use proof_composition::*;
2828
pub use schnorr_proof::*;
2929
pub use r#trait::*;
3030

31-
pub mod transcript;
31+
pub mod codec;
3232
pub mod old;

src/transcript/mod.rs

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/transcript/trait.rs

Lines changed: 0 additions & 36 deletions
This file was deleted.

tests/interactive_codec.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
use curve25519_dalek::ristretto::RistrettoPoint;
22
use rand::rngs::OsRng;
33

4-
use sigma_rs::transcript::{
5-
r#trait::TranscriptCodec, shake_transcript::ShakeTranscript,
4+
use sigma_rs::codec::{
5+
r#trait::Codec, shake_codec::ShakeCodec,
66
};
77

8-
pub type KeccakTranscriptRistretto = ShakeTranscript<curve25519_dalek::ristretto::RistrettoPoint>;
8+
pub type ShakeCodecRistretto = ShakeCodec<curve25519_dalek::ristretto::RistrettoPoint>;
99

1010
#[allow(non_snake_case)]
1111
#[test]
12-
fn keccak_transcript_ristretto() {
12+
fn shake_codec_ristretto() {
1313
// Type alias to mirror the Sage naming
14-
type Transcript = KeccakTranscriptRistretto;
14+
type Codec = ShakeCodecRistretto;
1515

1616
// Generate some commitments
1717
let G = RistrettoPoint::random(&mut OsRng);
1818
let H = RistrettoPoint::random(&mut OsRng);
1919

20-
let domain_sep = b"test-keccak-ristretto";
20+
let domain_sep = b"test-shake-ristretto";
2121

22-
// Initialize transcript
23-
let mut binding = Transcript::new(domain_sep);
24-
let transcript = binding.prover_message(&[G, H]);
22+
// Initialize codec
23+
let mut binding = Codec::new(domain_sep);
24+
let codec = binding.prover_message(&[G, H]);
2525

2626
// Derive challenge
27-
let challenge = transcript.verifier_challenge();
27+
let challenge = codec.verifier_challenge();
2828

2929
// Output result
3030
println!("Challenge: {:?}", challenge);

0 commit comments

Comments
 (0)