Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ group = "0.13"
rand = "0.8.5"
rand_core = "0.6.4"
lazy_static = "1.4.0"
spongefish = { git = "https://github.com/arkworks-rs/spongefish", branch = "mu/refactor", features = ["curve25519-dalek"] }
merlin = { version = "3", default-features = false }
sigma-proof-compiler-derive = { version = "0.1.0", path = "sigma-proof-compiler-derive" }
thiserror = "2.0.17"
Expand Down
14 changes: 9 additions & 5 deletions sigma-proof-compiler-derive/src/sym_instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,14 @@ pub fn derive_sym_instance_impl(input: TokenStream) -> TokenStream {
// Generate get_field_names() method body
let get_field_names_body = match &data.fields {
Fields::Named(fields) => {
let field_names: Vec<String> = fields.named.iter().map(|field| {
let field_name = field.ident.as_ref().unwrap();
field_name.to_string()
}).collect();
let field_names: Vec<String> = fields
.named
.iter()
.map(|field| {
let field_name = field.ident.as_ref().unwrap();
field_name.to_string()
})
.collect();

let name_literals = field_names.iter().map(|n| quote! { #n });
quote! {
Expand Down Expand Up @@ -428,4 +432,4 @@ pub fn derive_sym_instance_impl(input: TokenStream) -> TokenStream {
panic!("SymInstance derive macro does not support unions");
}
}
}
}
44 changes: 19 additions & 25 deletions src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ use crate::{
absorb::{SymInstance, SymWitness},
equations::{SymPoint, SymScalar},
errors::{SigmaProofError, SigmaProofResult},
transcript::ProofTranscript,
};
use curve25519_dalek::{constants::RISTRETTO_BASEPOINT_POINT, RistrettoPoint, Scalar};
use spongefish::{ProverState, VerifierState};

const PROTOCOL_ID: [u8; 32] = [0u8; 32];
const SESSION_ID: [u8; 32] = [0u8; 32];

/// Escape a variable name for LaTeX and wrap in texttt
fn latex_var(name: &str) -> String {
Expand Down Expand Up @@ -149,38 +152,34 @@ pub trait SigmaProof {

fn prove(witness: &Self::WITNESS, instance: &Self::INSTANCE) -> SigmaProofResult<Vec<u8>> {
// init transcript
let mut transcript = ProofTranscript::new_prover(Self::LABEL);
let mut prover_state = ProverState::new_std(PROTOCOL_ID, SESSION_ID);

// absorb instance, not f(instance)
for point in instance.points() {
transcript.common_absorb_point(b"", &point.evaluate()?);
prover_state.public_message(&point.evaluate()?);
}
for scalar in instance.scalars() {
transcript.common_absorb_scalar(b"", &scalar.evaluate()?);
prover_state.public_message(&scalar.evaluate()?);
}

// round 1
let rng = &mut rand::rngs::OsRng;
let alphas = Self::WITNESS::rand(rng);
let commited_alphas = Self::psi(&alphas, instance);
for point in &commited_alphas {
transcript.prover_absorb_point(b"r", &point.evaluate()?);
prover_state.prover_message(&point.evaluate()?);
}

// round 2
let e = transcript.challenge(b"e");
let e = prover_state.verifier_message::<Scalar>();

// round 3
for z_i in witness
.values()?
.into_iter()
.zip(alphas.values()?)
.map(|(s, a)| s * e + a)
{
transcript.prover_absorb_scalar(b"z", &z_i);
for (s, a) in witness.values()?.into_iter().zip(alphas.values()?) {
let z_i = s * e + a;
prover_state.prover_message(&z_i);
}

Ok(transcript.finalize())
Ok(prover_state.narg_string().to_vec())
}

fn verify(instance: &Self::INSTANCE, proof: &[u8]) -> Result<(), SigmaProofError> {
Expand All @@ -190,7 +189,7 @@ pub trait SigmaProof {
}

// init transcript
let mut transcript = ProofTranscript::new_verifier(Self::LABEL, proof);
let mut verifier_state = VerifierState::new_std(PROTOCOL_ID, SESSION_ID, proof);

// evaluate f(instance)
let big_x_points: Vec<_> = Self::f(instance)
Expand All @@ -200,25 +199,20 @@ pub trait SigmaProof {

// absorb instance, not f(instance)
for point in instance.points() {
transcript.common_absorb_point(b"", &point.evaluate()?);
verifier_state.public_message(&point.evaluate()?);
}
for scalar in instance.scalars() {
transcript.common_absorb_scalar(b"", &scalar.evaluate()?);
verifier_state.public_message(&scalar.evaluate()?);
}

// -> A
let big_a = transcript
.verifier_receive_points(b"r", big_x_points.len())
.ok_or(SigmaProofError::TranscriptError)?;
let big_a = verifier_state.prover_messages_vec(big_x_points.len())?;

// <- challenge
let e = transcript.challenge(b"e");
let e = verifier_state.verifier_message::<Scalar>();

// -> sigma
let sigmas = transcript
.verifier_receives_all_scalars(b"z")
.ok_or(SigmaProofError::TranscriptError)?;
println!("sigmas received: {}", sigmas.len());
let sigmas = verifier_state.prover_messages_vec(Self::WITNESS::num_scalars())?;
let sigmas_as_input = Self::WITNESS::from_values(&sigmas)?;

let psi_output = Self::psi(&sigmas_as_input, instance);
Expand Down
105 changes: 8 additions & 97 deletions src/transcript.rs
Original file line number Diff line number Diff line change
@@ -1,99 +1,10 @@
use curve25519_dalek::{
ristretto::{CompressedRistretto, RistrettoPoint},
scalar::Scalar,
};
use std::io::{Read, Write};

pub(crate) struct ProofTranscript {
state: merlin::Transcript,
proof: std::io::Cursor<Vec<u8>>,
is_prover: bool,
}

impl ProofTranscript {
pub(crate) fn new_prover(label: &'static [u8]) -> Self {
Self {
state: merlin::Transcript::new(label),
proof: std::io::Cursor::new(Vec::new()),
is_prover: true,
}
}

pub(crate) fn new_verifier(label: &'static [u8], proof: &[u8]) -> Self {
Self {
state: merlin::Transcript::new(label),
proof: std::io::Cursor::new(proof.to_vec()),
is_prover: false,
}
}

pub(crate) fn common_absorb_scalar(&mut self, label: &'static [u8], scalar: &Scalar) {
self.state.append_message(label, scalar.as_bytes());
}

pub(crate) fn common_absorb_point(&mut self, label: &'static [u8], point: &RistrettoPoint) {
self.state
.append_message(label, point.compress().as_bytes());
}

pub(crate) fn prover_absorb_scalar(&mut self, label: &'static [u8], scalar: &Scalar) {
assert!(self.is_prover);
self.common_absorb_scalar(label, scalar);
self.proof.write_all(scalar.as_bytes()).unwrap();
}

pub(crate) fn verifier_receives_all_scalars(
&mut self,
label: &'static [u8],
) -> Option<Vec<Scalar>> {
assert!(!self.is_prover);
let mut scalars = Vec::new();
loop {
let mut buf = [0u8; 32];
match self.proof.read_exact(&mut buf) {
Ok(()) => {
let scalar = Scalar::from_canonical_bytes(buf).into_option()?;
self.common_absorb_scalar(label, &scalar);
scalars.push(scalar);
}
Err(_) => break,
}
}
Some(scalars)
}

pub(crate) fn prover_absorb_point(&mut self, label: &'static [u8], point: &RistrettoPoint) {
assert!(self.is_prover);
self.common_absorb_point(label, &point);
self.proof.write_all(point.compress().as_bytes()).unwrap();
}

pub(crate) fn verifier_receive_points(
&mut self,
label: &'static [u8],
count: usize,
) -> Option<Vec<RistrettoPoint>> {
assert!(!self.is_prover);
let mut points = Vec::with_capacity(count);
for _ in 0..count {
let mut buf = [0u8; 32];
if self.proof.read_exact(&mut buf).is_err() {
return None;
}
let point = CompressedRistretto(buf).decompress()?;
self.common_absorb_point(label, &point); // TODO: we recompress here :/
points.push(point);
}
Some(points)
}

pub(crate) fn challenge(&mut self, label: &'static [u8]) -> Scalar {
let mut buf = [0u8; 64];
self.state.challenge_bytes(label, &mut buf);
Scalar::from_bytes_mod_order_wide(&buf)
}

pub(crate) fn finalize(self) -> Vec<u8> {
self.proof.into_inner()
use crate::errors::SigmaProofError;

/// Spongefish opts for a minimal error.
/// Informative errors about instance decoding, deserialziation might leak information outside
/// Instance processing errors also happen at a different step
impl From<spongefish::VerificationError> for SigmaProofError {
fn from(_value: spongefish::VerificationError) -> Self {
SigmaProofError::TranscriptError
}
}