|
@@ -0,0 +1,491 @@
|
|
|
|
+//! Sigma-RS specific code generation module.
|
|
|
|
+//!
|
|
|
|
+//! This module contains the sigma-rs implementation that was in the feature/sigma-rs branch.
|
|
|
|
+
|
|
|
|
+use super::syntax::*;
|
|
|
|
+use proc_macro2::TokenStream;
|
|
|
|
+use quote::{quote, ToTokens};
|
|
|
|
+use std::collections::HashMap;
|
|
|
|
+use syn::visit_mut::{self, VisitMut};
|
|
|
|
+use syn::{parse_quote, Expr, Ident, Token};
|
|
|
|
+use syn::{ExprBinary, BinOp, ExprPath};
|
|
|
|
+use syn::Result;
|
|
|
|
+
|
|
|
|
+// Names and types of fields that might end up in a generated struct
|
|
|
|
+enum StructField {
|
|
|
|
+ Scalar(Ident),
|
|
|
|
+ VecScalar(Ident),
|
|
|
|
+ Point(Ident),
|
|
|
|
+ VecPoint(Ident),
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// A list of StructField items
|
|
|
|
+#[derive(Default)]
|
|
|
|
+struct StructFieldList {
|
|
|
|
+ fields: Vec<StructField>,
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl StructFieldList {
|
|
|
|
+ pub fn push_scalar(&mut self, s: &Ident) {
|
|
|
|
+ self.fields.push(StructField::Scalar(s.clone()));
|
|
|
|
+ }
|
|
|
|
+ pub fn push_vecscalar(&mut self, s: &Ident) {
|
|
|
|
+ self.fields.push(StructField::VecScalar(s.clone()));
|
|
|
|
+ }
|
|
|
|
+ pub fn push_point(&mut self, s: &Ident) {
|
|
|
|
+ self.fields.push(StructField::Point(s.clone()));
|
|
|
|
+ }
|
|
|
|
+ pub fn push_vecpoint(&mut self, s: &Ident) {
|
|
|
|
+ self.fields.push(StructField::VecPoint(s.clone()));
|
|
|
|
+ }
|
|
|
|
+ pub fn push_vars(&mut self, vardict: &TaggedVarDict, is_pub: bool) {
|
|
|
|
+ let mut entries: Vec<_> = vardict.iter().collect();
|
|
|
|
+ entries.sort_by_key(|(k, _)| (*k).clone());
|
|
|
|
+ for (_, ti) in entries {
|
|
|
|
+ match ti {
|
|
|
|
+ TaggedIdent::Scalar(st) => {
|
|
|
|
+ if st.is_pub == is_pub {
|
|
|
|
+ if st.is_vec {
|
|
|
|
+ self.push_vecscalar(&st.id)
|
|
|
|
+ } else {
|
|
|
|
+ self.push_scalar(&st.id)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ TaggedIdent::Point(pt) => {
|
|
|
|
+ if is_pub {
|
|
|
|
+ if pt.is_vec {
|
|
|
|
+ self.push_vecpoint(&pt.id)
|
|
|
|
+ } else {
|
|
|
|
+ self.push_point(&pt.id)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /// Output a ToTokens of the fields as they would appear in a struct
|
|
|
|
+ /// definition
|
|
|
|
+ pub fn field_decls(&self) -> impl ToTokens {
|
|
|
|
+ let decls = self.fields.iter().map(|f| match f {
|
|
|
|
+ StructField::Scalar(id) => quote! {
|
|
|
|
+ pub #id: Scalar,
|
|
|
|
+ },
|
|
|
|
+ StructField::VecScalar(id) => quote! {
|
|
|
|
+ pub #id: Vec<Scalar>,
|
|
|
|
+ },
|
|
|
|
+ StructField::Point(id) => quote! {
|
|
|
|
+ pub #id: Point,
|
|
|
|
+ },
|
|
|
|
+ StructField::VecPoint(id) => quote! {
|
|
|
|
+ pub #id: Vec<Point>,
|
|
|
|
+ },
|
|
|
|
+ });
|
|
|
|
+ quote! { #(#decls)* }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// An implementation of the
|
|
|
|
+/// [`VisitMut`](https://docs.rs/syn/latest/syn/visit_mut/trait.VisitMut.html)
|
|
|
|
+/// trait that massages the provided statements.
|
|
|
|
+///
|
|
|
|
+/// This massaging currently consists of:
|
|
|
|
+/// - Changing equality from = to ==
|
|
|
|
+/// - Changing any identifier `id` to either `params.id` or
|
|
|
|
+/// `witness.id` depending on whether it is public or private
|
|
|
|
+struct StatementFixup {
|
|
|
|
+ idmap: HashMap<String, Expr>,
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl StatementFixup {
|
|
|
|
+ pub fn new(spec: &SigmaCompSpec) -> Self {
|
|
|
|
+ let mut idmap: HashMap<String, Expr> = HashMap::new();
|
|
|
|
+
|
|
|
|
+ // For each public identifier id (Points, or Scalars marked
|
|
|
|
+ // "pub"), add to the map "id" -> params.id. For each private
|
|
|
|
+ // identifier (Scalars not marked "pub"), add to the map "id" ->
|
|
|
|
+ // witness.id.
|
|
|
|
+ for (id, is_pub) in spec.vars.values().map(|ti| match ti {
|
|
|
|
+ TaggedIdent::Scalar(st) => (&st.id, st.is_pub),
|
|
|
|
+ TaggedIdent::Point(pt) => (&pt.id, true),
|
|
|
|
+ }) {
|
|
|
|
+ let idexpr: Expr = if is_pub {
|
|
|
|
+ parse_quote! { params.#id }
|
|
|
|
+ } else {
|
|
|
|
+ parse_quote! { witness.#id }
|
|
|
|
+ };
|
|
|
|
+ idmap.insert(id.to_string(), idexpr);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Self { idmap }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl VisitMut for StatementFixup {
|
|
|
|
+ fn visit_expr_mut(&mut self, node: &mut Expr) {
|
|
|
|
+ if let Expr::Assign(assn) = node {
|
|
|
|
+ *node = Expr::Binary(syn::ExprBinary {
|
|
|
|
+ attrs: assn.attrs.clone(),
|
|
|
|
+ left: assn.left.clone(),
|
|
|
|
+ op: syn::BinOp::Eq(Token),
|
|
|
|
+ right: assn.right.clone(),
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ if let Expr::Path(expath) = node {
|
|
|
|
+ if let Some(id) = expath.path.get_ident() {
|
|
|
|
+ if let Some(expr) = self.idmap.get(&id.to_string()) {
|
|
|
|
+ *node = expr.clone();
|
|
|
|
+ // Don't recurse
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // Unless we bailed out above, continue with the default
|
|
|
|
+ // traversal
|
|
|
|
+ visit_mut::visit_expr_mut(self, node);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// Tries to extract an identifier from an expression of type `Expr`
|
|
|
|
+fn expr_to_ident(expr: &Expr) -> Option<&Ident> {
|
|
|
|
+ if let Expr::Path(ExprPath { path, .. }) = expr {
|
|
|
|
+ if path.segments.len() == 1 {
|
|
|
|
+ return Some(&path.segments[0].ident);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ None
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// Analyzes an expression `Expr` representing a sum (x * Q + y * H + ...)
|
|
|
|
+/// and returns a vector of couples `(base_point_ident, scalar_ident)`
|
|
|
|
+fn extract_terms(expr: &Expr) -> Result<Vec<(Ident, Ident)>> {
|
|
|
|
+ let mut terms = Vec::new();
|
|
|
|
+
|
|
|
|
+ match expr {
|
|
|
|
+ Expr::Binary(ExprBinary { op: BinOp::Add(_), left, right, .. }) => {
|
|
|
|
+ terms.extend(extract_terms(left)?);
|
|
|
|
+ terms.extend(extract_terms(right)?);
|
|
|
|
+ }
|
|
|
|
+ Expr::Binary(ExprBinary { op: BinOp::Mul(_), left, right, .. }) => {
|
|
|
|
+ let (scalar, point) = match (expr_to_ident(left), expr_to_ident(right)) {
|
|
|
|
+ (Some(a), Some(b)) => {
|
|
|
|
+ (a.clone(), b.clone())
|
|
|
|
+ }
|
|
|
|
+ _ => {
|
|
|
|
+ return Err(syn::Error::new_spanned(expr, "Expected product of two identifiers like `x * Q`"));
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ terms.push((point, scalar));
|
|
|
|
+ }
|
|
|
|
+ _ => {
|
|
|
|
+ return Err(syn::Error::new_spanned(expr, "Expected addition or multiplication expression"));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Ok(terms)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// Extracts a linear combination from an expression of the form `lhs = x * Q + y * H + ...`
|
|
|
|
+pub fn extract_linear_combination(expr: &Expr) -> Result<(Ident, Vec<(Ident, Ident)>)> {
|
|
|
|
+ if let Expr::Assign(assign) = expr {
|
|
|
|
+ let lhs_ident = expr_to_ident(&assign.left)
|
|
|
|
+ .ok_or_else(|| syn::Error::new_spanned(&assign.left, "Expected left-hand side to be a single identifier"))?
|
|
|
|
+ .clone();
|
|
|
|
+
|
|
|
|
+ let terms = extract_terms(&assign.right)?;
|
|
|
|
+ Ok((lhs_ident, terms))
|
|
|
|
+ } else {
|
|
|
|
+ Err(syn::Error::new_spanned(expr, "Expected an assignment expression like `A = x * G + y * H`"))
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// Generate the sigma-rs implementation code (from feature/sigma-rs branch)
|
|
|
|
+pub fn sigma_compiler_core_sigmars(
|
|
|
|
+ spec: &mut SigmaCompSpec,
|
|
|
|
+ emit_prover: bool,
|
|
|
|
+ emit_verifier: bool,
|
|
|
|
+) -> TokenStream {
|
|
|
|
+ let proto_name = &spec.proto_name;
|
|
|
|
+ let group_name = &spec.group_name;
|
|
|
|
+
|
|
|
|
+ // Save a copy of the input TaggedVarDict, because the Params and
|
|
|
|
+ // Witness structs will be built from that TaggedVarDict, not the
|
|
|
|
+ // one modified by apply_substitutions below.
|
|
|
|
+ let input_vars = spec.vars.clone();
|
|
|
|
+
|
|
|
|
+ // Apply any substitution transformations
|
|
|
|
+ // Note: We create a dummy CodeGen since sigma-rs implementation doesn't use it
|
|
|
|
+ let mut dummy_codegen = crate::codegen::CodeGen::new(spec);
|
|
|
|
+ crate::transform::apply_substitutions(&mut dummy_codegen, &mut spec.statements, &mut spec.vars).unwrap();
|
|
|
|
+
|
|
|
|
+ let group_types = quote! {
|
|
|
|
+ pub type Scalar = <super::#group_name as super::Group>::Scalar;
|
|
|
|
+ pub type Point = super::#group_name;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ // Generate the public params struct definition
|
|
|
|
+ let params_def = {
|
|
|
|
+ let mut pub_params_fields = StructFieldList::default();
|
|
|
|
+ pub_params_fields.push_vars(&input_vars, true);
|
|
|
|
+
|
|
|
|
+ let decls = pub_params_fields.field_decls();
|
|
|
|
+
|
|
|
|
+ let new_args = pub_params_fields.fields.iter().map(|f| match f {
|
|
|
|
+ StructField::Scalar(id) => quote! { #id: Scalar },
|
|
|
|
+ StructField::VecScalar(id) => quote! { #id: Vec<Scalar> },
|
|
|
|
+ StructField::Point(id) => quote! { #id: Point },
|
|
|
|
+ StructField::VecPoint(id) => quote! { #id: Vec<Point> },
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // Allowance of the secret scalars of LinearRelation (see sigma-rs::linear_relation)
|
|
|
|
+ let scalar_allocs = {
|
|
|
|
+ let mut sec_params_fields = StructFieldList::default();
|
|
|
|
+ sec_params_fields.push_vars(&input_vars, false);
|
|
|
|
+ sec_params_fields.fields.iter().map(|f|
|
|
|
|
+ match f {
|
|
|
|
+ StructField::Scalar(id) => quote! {
|
|
|
|
+ let scalar_var = protocol.sigmap.0.allocate_scalar();
|
|
|
|
+ scalar_bindings.push((::syn::parse_str::<::syn::Ident>(stringify!(#id)).unwrap(), None, scalar_var));
|
|
|
|
+ },
|
|
|
|
+ _ => quote! {},
|
|
|
|
+ }
|
|
|
|
+ ).collect::<Vec<_>>()
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ // Allowance of (public) group elements of the LinearRelation (see sigma-rs::linear_relation)
|
|
|
|
+ let point_allocs = {
|
|
|
|
+ pub_params_fields.fields.iter().map(|f| {
|
|
|
|
+ if let StructField::Point(id) = f {
|
|
|
|
+ quote! {
|
|
|
|
+ let point_var = protocol.sigmap.0.allocate_element();
|
|
|
|
+ protocol.sigmap.0.assign_elements([(point_var, #id.clone())]);
|
|
|
|
+ point_bindings.push((::syn::parse_str::<::syn::Ident>(stringify!(#id)).unwrap(), None, point_var));
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ quote! {}
|
|
|
|
+ }
|
|
|
|
+ }).collect::<Vec<_>>()
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ // Allowance of LinearRelation constraints for the construction of induced sigma protocol
|
|
|
|
+ let statements_alloc = {
|
|
|
|
+ spec.statements.clone().leaves_mut().iter().map(|f| {
|
|
|
|
+ let (lhs, terms) = extract_linear_combination(f).unwrap();
|
|
|
|
+
|
|
|
|
+ let pairs = terms.iter().map(|(point, scalar)| {
|
|
|
|
+ quote! {
|
|
|
|
+ {
|
|
|
|
+ let scalar_var = scalar_bindings
|
|
|
|
+ .iter()
|
|
|
|
+ .find(|(id, _, _)| id == &::syn::parse_str::<::syn::Ident>(stringify!(#scalar)).unwrap())
|
|
|
|
+ .expect(&format!("Missing scalar binding for {}", stringify!(#scalar)))
|
|
|
|
+ .2;
|
|
|
|
+
|
|
|
|
+ let point_var = point_bindings
|
|
|
|
+ .iter()
|
|
|
|
+ .find(|(id, _, _)| id == &::syn::parse_str::<::syn::Ident>(stringify!(#point)).unwrap())
|
|
|
|
+ .expect(&format!("Missing point binding for {}", stringify!(#point)))
|
|
|
|
+ .2;
|
|
|
|
+
|
|
|
|
+ (scalar_var, point_var)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ quote! {
|
|
|
|
+ {
|
|
|
|
+ let lhs = point_bindings
|
|
|
|
+ .iter()
|
|
|
|
+ .find(|(id, _, _)| id == &::syn::parse_str::<::syn::Ident>(stringify!(#lhs)).unwrap())
|
|
|
|
+ .expect(&format!("Missing point binding for {}", stringify!(#lhs)))
|
|
|
|
+ .2;
|
|
|
|
+
|
|
|
|
+ let rhs = vec![#(#pairs),*];
|
|
|
|
+ protocol.sigmap.0.constrain(lhs, rhs)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }).collect::<Vec<_>>()
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ let dump_impl = if cfg!(feature = "dump") {
|
|
|
|
+ let dump_chunks = pub_params_fields.fields.iter().map(|f| match f {
|
|
|
|
+ StructField::Scalar(id) => quote! {
|
|
|
|
+ print!(" {}: ", stringify!(#id));
|
|
|
|
+ Params::dump_scalar(&self.#id);
|
|
|
|
+ println!("");
|
|
|
|
+ },
|
|
|
|
+ StructField::VecScalar(id) => quote! {
|
|
|
|
+ print!(" {}: [", stringify!(#id));
|
|
|
|
+ for s in self.#id.iter() {
|
|
|
|
+ print!(" ");
|
|
|
|
+ Params::dump_scalar(s);
|
|
|
|
+ println!(",");
|
|
|
|
+ }
|
|
|
|
+ println!(" ]");
|
|
|
|
+ },
|
|
|
|
+ StructField::Point(id) => quote! {
|
|
|
|
+ print!(" {}: ", stringify!(#id));
|
|
|
|
+ Params::dump_point(&self.#id);
|
|
|
|
+ println!("");
|
|
|
|
+ },
|
|
|
|
+ StructField::VecPoint(id) => quote! {
|
|
|
|
+ print!(" {}: [", stringify!(#id));
|
|
|
|
+ for p in self.#id.iter() {
|
|
|
|
+ print!(" ");
|
|
|
|
+ Params::dump_point(p);
|
|
|
|
+ println!(",");
|
|
|
|
+ }
|
|
|
|
+ println!(" ]");
|
|
|
|
+ },
|
|
|
|
+ });
|
|
|
|
+ quote! {
|
|
|
|
+ impl Params {
|
|
|
|
+ fn dump_scalar(s: &Scalar) {
|
|
|
|
+ let bytes: &[u8] = &s.to_repr();
|
|
|
|
+ print!("{:02x?}", bytes);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn dump_point(p: &Point) {
|
|
|
|
+ let bytes: &[u8] = &p.to_bytes();
|
|
|
|
+ print!("{:02x?}", bytes);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn dump(&self) {
|
|
|
|
+ println!("params: {:?}", self);
|
|
|
|
+ #(#dump_chunks)*
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ quote! {
|
|
|
|
+ impl Protocol {
|
|
|
|
+ pub fn new(#(#new_args),*) -> Self {
|
|
|
|
+ let mut scalar_bindings: Vec<(::syn::Ident, Option<usize>, ScalarVar)> = Vec::new();
|
|
|
|
+ let mut point_bindings: Vec<(::syn::Ident, Option<usize>, GroupVar)> = Vec::new();
|
|
|
|
+ let mut protocol = NISigma::new(b"hello world", SchnorrProtocol(LinearRelation::new()));
|
|
|
|
+ #(#scalar_allocs)*
|
|
|
|
+ #(#point_allocs)*
|
|
|
|
+ #(#statements_alloc)*
|
|
|
|
+
|
|
|
|
+ Protocol { protocol, scalar_bindings, point_bindings }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ quote! {
|
|
|
|
+ pub struct Params {
|
|
|
|
+ #decls
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub struct Protocol {
|
|
|
|
+ pub protocol: NISigmaProtocol<SchnorrProtocol<super::#group_name>, ShakeCodec<super::#group_name>>,
|
|
|
|
+ pub scalar_bindings: Vec<(::syn::Ident, Option<usize>, ScalarVar)>,
|
|
|
|
+ pub point_bindings: Vec<(::syn::Ident, Option<usize>, GroupVar)>
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ #dump_impl
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ // Generate the witness struct definition
|
|
|
|
+ let witness_def = if emit_prover {
|
|
|
|
+ let mut _witness_fields = StructFieldList::default();
|
|
|
|
+ _witness_fields.push_vars(&input_vars, false);
|
|
|
|
+
|
|
|
|
+ // For the case where the struct witness supports the field system
|
|
|
|
+ // let decls = witness_fields.field_decls();
|
|
|
|
+ quote! {
|
|
|
|
+ pub struct Witness (pub Vec<<super::#group_name as super::Group>::Scalar>);
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ quote! {}
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ // Generate the prove function
|
|
|
|
+ let prove_func = if emit_prover {
|
|
|
|
+ let dumper = if cfg!(feature = "dump") {
|
|
|
|
+ quote! {
|
|
|
|
+ println!("prover params = {{");
|
|
|
|
+ params.dump();
|
|
|
|
+ println!("}}");
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ quote! {
|
|
|
|
+ let mut rng = OsRng;
|
|
|
|
+ let result = protocol.protocol.prove_batchable(&witness.0, &mut rng).is_ok();
|
|
|
|
+ match result {
|
|
|
|
+ true => Ok(protocol.protocol.prove_batchable(&witness.0, &mut rng).unwrap()),
|
|
|
|
+ false => Err(())
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ quote! {
|
|
|
|
+ pub fn prove(protocol: &Protocol, witness: &Witness) -> Result<Vec<u8>,()> {
|
|
|
|
+ #dumper
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ quote! {}
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ // Generate the verify function
|
|
|
|
+ let verify_func = if emit_verifier {
|
|
|
|
+ let dumper = if cfg!(feature = "dump") {
|
|
|
|
+ quote! {
|
|
|
|
+ println!("verifier params = {{");
|
|
|
|
+ params.dump();
|
|
|
|
+ println!("}}");
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ quote! {
|
|
|
|
+ let result = protocol.protocol.verify_batchable(proof).is_ok();
|
|
|
|
+ match result {
|
|
|
|
+ true => Ok(()),
|
|
|
|
+ false => Err(())
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ quote! {
|
|
|
|
+ pub fn verify(protocol: &Protocol, proof: &[u8]) -> Result<(),()> {
|
|
|
|
+ #dumper
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ quote! {}
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ // Output the generated module for this protocol
|
|
|
|
+ let dump_use = if cfg!(feature = "dump") {
|
|
|
|
+ quote! {
|
|
|
|
+ use ff::PrimeField;
|
|
|
|
+ use group::GroupEncoding;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ quote! {
|
|
|
|
+ use sigma_rs::schnorr_protocol::SchnorrProtocol;
|
|
|
|
+ use sigma_rs::linear_relation::{LinearCombination, LinearRelation};
|
|
|
|
+ use sigma_rs::linear_relation::{GroupVar, ScalarVar};
|
|
|
|
+ use sigma_rs::fiat_shamir::NISigmaProtocol;
|
|
|
|
+ use sigma_rs::codec::ShakeCodec;
|
|
|
|
+ use syn::Ident;
|
|
|
|
+ use std::collections::HashMap;
|
|
|
|
+ use rand::rngs::OsRng;
|
|
|
|
+
|
|
|
|
+ type NISigma = NISigmaProtocol<SchnorrProtocol<super::#group_name>, ShakeCodec<super::#group_name>>;
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ quote! {
|
|
|
|
+ #[allow(non_snake_case)]
|
|
|
|
+ pub mod #proto_name {
|
|
|
|
+ #dump_use
|
|
|
|
+
|
|
|
|
+ #group_types
|
|
|
|
+ #params_def
|
|
|
|
+ #witness_def
|
|
|
|
+
|
|
|
|
+ #prove_func
|
|
|
|
+ #verify_func
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|