codegen.rs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. //! A module for generating the code that uses the `sigma-proofs` crate API.
  2. //!
  3. //! If that crate gets its own macro interface, it can use this module
  4. //! directly.
  5. use super::combiners::StatementTree;
  6. use super::types::{expr_type_tokens_id_closure, AExprType, VarDict};
  7. use proc_macro2::TokenStream;
  8. use quote::{format_ident, quote, ToTokens};
  9. use std::collections::HashSet;
  10. use syn::{Expr, Ident};
  11. /// Names and types of fields that might end up in a generated struct
  12. #[derive(Clone)]
  13. pub enum StructField {
  14. Scalar(Ident),
  15. VecScalar(Ident),
  16. Point(Ident),
  17. VecPoint(Ident),
  18. }
  19. impl StructField {
  20. /// Extract the [`struct@Ident`] from the [`StructField`]
  21. pub fn ident(&self) -> Ident {
  22. match self {
  23. Self::Scalar(id) | Self::VecScalar(id) | Self::Point(id) | Self::VecPoint(id) => {
  24. id.clone()
  25. }
  26. }
  27. }
  28. }
  29. /// A list of StructField items
  30. #[derive(Default)]
  31. pub struct StructFieldList {
  32. pub fields: Vec<StructField>,
  33. }
  34. impl StructFieldList {
  35. pub fn push_scalar(&mut self, s: &Ident) {
  36. self.fields.push(StructField::Scalar(s.clone()));
  37. }
  38. pub fn push_vecscalar(&mut self, s: &Ident) {
  39. self.fields.push(StructField::VecScalar(s.clone()));
  40. }
  41. pub fn push_point(&mut self, s: &Ident) {
  42. self.fields.push(StructField::Point(s.clone()));
  43. }
  44. pub fn push_vecpoint(&mut self, s: &Ident) {
  45. self.fields.push(StructField::VecPoint(s.clone()));
  46. }
  47. pub fn push_vars(&mut self, vars: &VarDict, for_instance: bool) {
  48. for (id, ti) in vars.iter() {
  49. match ti {
  50. AExprType::Scalar { is_pub, is_vec, .. } => {
  51. if *is_pub == for_instance {
  52. if *is_vec {
  53. self.push_vecscalar(&format_ident!("{}", id))
  54. } else {
  55. self.push_scalar(&format_ident!("{}", id))
  56. }
  57. }
  58. }
  59. AExprType::Point { is_vec, .. } => {
  60. if for_instance {
  61. if *is_vec {
  62. self.push_vecpoint(&format_ident!("{}", id))
  63. } else {
  64. self.push_point(&format_ident!("{}", id))
  65. }
  66. }
  67. }
  68. }
  69. }
  70. }
  71. #[cfg(feature = "dump")]
  72. /// Output a ToTokens of code to dump the contents of the fields to
  73. /// the `std::fmt::Formatter` with the given `fmt_id`
  74. pub fn dump(&self, fmt_id: &Ident) -> impl ToTokens {
  75. // Sort the field ids
  76. let mut fields = self.fields.clone();
  77. fields.sort_by_key(|f| f.ident());
  78. let dump_chunks = fields.iter().map(|f| match f {
  79. // It's not a big deal if writes fail here, so we use "ok()"
  80. // to ignore the `Result`
  81. StructField::Scalar(id) => quote! {
  82. write!(#fmt_id, " {}: ", stringify!(#id)).ok();
  83. Instance::dump_scalar(&self.#id, #fmt_id);
  84. write!(#fmt_id, ",\n").ok();
  85. },
  86. StructField::VecScalar(id) => quote! {
  87. write!(#fmt_id, " {}: [\n", stringify!(#id)).ok();
  88. for s in self.#id.iter() {
  89. write!(#fmt_id, " ").ok();
  90. Instance::dump_scalar(s, #fmt_id);
  91. write!(#fmt_id, ",\n").ok();
  92. }
  93. write!(#fmt_id, " ],\n").ok();
  94. },
  95. StructField::Point(id) => quote! {
  96. write!(#fmt_id, " {}: ", stringify!(#id)).ok();
  97. Instance::dump_point(&self.#id, #fmt_id);
  98. write!(#fmt_id, ",\n").ok();
  99. },
  100. StructField::VecPoint(id) => quote! {
  101. write!(#fmt_id, " {}: [\n", stringify!(#id)).ok();
  102. for p in self.#id.iter() {
  103. write!(#fmt_id, " ").ok();
  104. Instance::dump_point(p, #fmt_id);
  105. write!(#fmt_id, ",\n").ok();
  106. }
  107. write!(#fmt_id, " ],\n").ok();
  108. },
  109. });
  110. quote! { #(#dump_chunks)* }
  111. }
  112. /// Output a ToTokens of the fields as they would appear in a struct
  113. /// definition
  114. pub fn field_decls(&self) -> impl ToTokens {
  115. let decls = self.fields.iter().map(|f| match f {
  116. StructField::Scalar(id) => quote! {
  117. pub #id: Scalar,
  118. },
  119. StructField::VecScalar(id) => quote! {
  120. pub #id: Vec<Scalar>,
  121. },
  122. StructField::Point(id) => quote! {
  123. pub #id: Point,
  124. },
  125. StructField::VecPoint(id) => quote! {
  126. pub #id: Vec<Point>,
  127. },
  128. });
  129. quote! { #(#decls)* }
  130. }
  131. /// Output a ToTokens of the list of fields
  132. pub fn field_list(&self) -> impl ToTokens {
  133. let field_ids = self.fields.iter().map(|f| match f {
  134. StructField::Scalar(id) => quote! {
  135. #id,
  136. },
  137. StructField::VecScalar(id) => quote! {
  138. #id,
  139. },
  140. StructField::Point(id) => quote! {
  141. #id,
  142. },
  143. StructField::VecPoint(id) => quote! {
  144. #id,
  145. },
  146. });
  147. quote! { #(#field_ids)* }
  148. }
  149. }
  150. /// The main struct to handle code generation using the `sigma-proofs` API.
  151. pub struct CodeGen<'a> {
  152. proto_name: Ident,
  153. group_name: Ident,
  154. vars: &'a VarDict,
  155. unique_prefix: String,
  156. statements: &'a mut StatementTree,
  157. }
  158. impl<'a> CodeGen<'a> {
  159. /// Find a prefix that does not appear at the beginning of any
  160. /// variable name in `vars`
  161. fn unique_prefix(vars: &VarDict) -> String {
  162. 'outer: for tag in 0usize.. {
  163. let try_prefix = if tag == 0 {
  164. "sigma__".to_string()
  165. } else {
  166. format!("sigma{}__", tag)
  167. };
  168. for v in vars.keys() {
  169. if v.starts_with(&try_prefix) {
  170. continue 'outer;
  171. }
  172. }
  173. return try_prefix;
  174. }
  175. // The compiler complains if this isn't here, but it will only
  176. // get hit if vars contains at least usize::MAX entries, which
  177. // isn't going to happen.
  178. String::new()
  179. }
  180. pub fn new(
  181. proto_name: Ident,
  182. group_name: Ident,
  183. vars: &'a VarDict,
  184. statements: &'a mut StatementTree,
  185. ) -> Self {
  186. Self {
  187. proto_name,
  188. group_name,
  189. vars,
  190. unique_prefix: Self::unique_prefix(vars),
  191. statements,
  192. }
  193. }
  194. /// Generate the code for the `protocol` and `protocol_witness`
  195. /// functions that create the `ComposedInstance` and `ComposedWitness`
  196. /// structs, respectively, given a slice of [`Expr`]s that will be
  197. /// bundled into a single `LinearRelation`. The instance code evaluates
  198. /// to `Result<ComposedInstance<Point>, InvalidInstance>`; the witness
  199. /// code evaluates to `Result<ComposedWitness<Point>, InvalidWitness>`.
  200. fn linear_relation_codegen(&self, exprs: &[&Expr]) -> (TokenStream, TokenStream) {
  201. let instance_var = format_ident!("{}instance", self.unique_prefix);
  202. let lr_var = format_ident!("{}lr", self.unique_prefix);
  203. let mut allocated_vars: HashSet<Ident> = HashSet::new();
  204. let mut param_vec_code = quote! {};
  205. let mut witness_vec_code = quote! {};
  206. let mut witness_code = quote! {};
  207. let mut scalar_allocs = quote! {};
  208. let mut element_allocs = quote! {};
  209. let mut eq_code = quote! {};
  210. let mut element_assigns = quote! {};
  211. for (i, expr) in exprs.iter().enumerate() {
  212. let eq_id = format_ident!("{}eq{}", self.unique_prefix, i + 1);
  213. let vec_index_var = format_ident!("{}i", self.unique_prefix);
  214. let vec_len_var = format_ident!("{}veclen{}", self.unique_prefix, i + 1);
  215. // Record any vector variables we encountered in this
  216. // expression
  217. let mut vec_param_vars: HashSet<Ident> = HashSet::new();
  218. let mut vec_witness_vars: HashSet<Ident> = HashSet::new();
  219. // Ensure the `Expr` is of a type we recognize. In
  220. // particular, it must be an assignment (left = right) where
  221. // the expression on the left is an arithmetic expression
  222. // that evaluates to a public Point, and the expression on
  223. // the right is an arithmetic expression that evaluates to a
  224. // Point. It is allowed for neither or both Points to be
  225. // vector variables.
  226. let Expr::Assign(syn::ExprAssign { left, right, .. }) = expr else {
  227. let expr_str = quote! { #expr }.to_string();
  228. panic!("Unrecognized expression: {expr_str}");
  229. };
  230. let (left_type, left_tokens) =
  231. expr_type_tokens_id_closure(self.vars, left, &mut |id, id_type| match id_type {
  232. AExprType::Scalar { is_pub: false, .. } => {
  233. panic!("Left side of = contains a private Scalar");
  234. }
  235. AExprType::Scalar {
  236. is_vec: false,
  237. is_pub: true,
  238. ..
  239. }
  240. | AExprType::Point { is_vec: false, .. } => Ok(quote! {#instance_var.#id}),
  241. AExprType::Scalar {
  242. is_vec: true,
  243. is_pub: true,
  244. ..
  245. }
  246. | AExprType::Point { is_vec: true, .. } => {
  247. vec_param_vars.insert(id.clone());
  248. Ok(quote! {#instance_var.#id})
  249. }
  250. })
  251. .unwrap();
  252. let AExprType::Point {
  253. is_pub: true,
  254. is_vec: left_is_vec,
  255. } = left_type
  256. else {
  257. let expr_str = quote! { #expr }.to_string();
  258. panic!("Left side of = does not evaluate to a public point: {expr_str}");
  259. };
  260. let Ok((right_type, right_tokens)) =
  261. expr_type_tokens_id_closure(self.vars, right, &mut |id, id_type| match id_type {
  262. AExprType::Scalar {
  263. is_vec: false,
  264. is_pub: false,
  265. ..
  266. } => {
  267. if allocated_vars.insert(id.clone()) {
  268. scalar_allocs = quote! {
  269. #scalar_allocs
  270. let #id = #lr_var.allocate_scalar();
  271. };
  272. witness_code = quote! {
  273. #witness_code
  274. witnessvec.push(witness.#id);
  275. };
  276. }
  277. Ok(quote! {#id})
  278. }
  279. AExprType::Scalar {
  280. is_vec: false,
  281. is_pub: true,
  282. ..
  283. } => Ok(quote! {#instance_var.#id}),
  284. AExprType::Scalar {
  285. is_vec: true,
  286. is_pub: false,
  287. ..
  288. } => {
  289. vec_witness_vars.insert(id.clone());
  290. if allocated_vars.insert(id.clone()) {
  291. scalar_allocs = quote! {
  292. #scalar_allocs
  293. let #id = (0..#vec_len_var)
  294. .map(|i| #lr_var.allocate_scalar())
  295. .collect::<Vec<_>>();
  296. };
  297. witness_code = quote! {
  298. #witness_code
  299. witnessvec.extend(witness.#id.clone());
  300. };
  301. }
  302. Ok(quote! { #id })
  303. }
  304. AExprType::Scalar {
  305. is_vec: true,
  306. is_pub: true,
  307. ..
  308. } => {
  309. vec_param_vars.insert(id.clone());
  310. Ok(quote! {#instance_var.#id})
  311. }
  312. AExprType::Point { is_vec: false, .. } => {
  313. if allocated_vars.insert(id.clone()) {
  314. // sigma-proofs reserves element indices for the
  315. // identity and the canonical group generator.
  316. // Reuse them whenever a declared point has one of
  317. // those values; otherwise keep the point as an
  318. // ordinary instance element.
  319. element_allocs = quote! {
  320. #element_allocs
  321. let #id = if #instance_var.#id
  322. == <Point as group::Group>::identity()
  323. {
  324. #lr_var.identity()
  325. } else if #instance_var.#id
  326. == <Point as group::Group>::generator()
  327. {
  328. #lr_var.generator()
  329. } else {
  330. #lr_var.allocate_element_with(#instance_var.#id)
  331. };
  332. };
  333. }
  334. Ok(quote! {#id})
  335. }
  336. AExprType::Point { is_vec: true, .. } => {
  337. vec_param_vars.insert(id.clone());
  338. if allocated_vars.insert(id.clone()) {
  339. element_allocs = quote! {
  340. #element_allocs
  341. let #id = (0..#vec_len_var)
  342. .map(|#vec_index_var| #lr_var.allocate_element())
  343. .collect::<Vec<_>>();
  344. };
  345. element_assigns = quote! {
  346. #element_assigns
  347. for #vec_index_var in 0..#vec_len_var {
  348. #lr_var.set_element(
  349. #id[#vec_index_var],
  350. #instance_var.#id[#vec_index_var],
  351. );
  352. }
  353. };
  354. }
  355. Ok(quote! { #id })
  356. }
  357. })
  358. else {
  359. let expr_str = quote! { #expr }.to_string();
  360. panic!("Right side of = is not a valid arithmetic expression: {expr_str}");
  361. };
  362. let AExprType::Point {
  363. is_vec: right_is_vec,
  364. ..
  365. } = right_type
  366. else {
  367. let expr_str = quote! { #expr }.to_string();
  368. panic!("Right side of = does not evaluate to a Point: {expr_str}");
  369. };
  370. if left_is_vec != right_is_vec {
  371. let expr_str = quote! { #expr }.to_string();
  372. panic!("Only one side of = is a vector expression: {expr_str}");
  373. }
  374. let vec_param_varvec = Vec::from_iter(vec_param_vars);
  375. let vec_witness_varvec = Vec::from_iter(vec_witness_vars);
  376. if !vec_param_varvec.is_empty() {
  377. let firstvar = &vec_param_varvec[0];
  378. param_vec_code = quote! {
  379. #param_vec_code
  380. let #vec_len_var = #instance_var.#firstvar.len();
  381. };
  382. for thisvar in vec_param_varvec.iter().skip(1) {
  383. param_vec_code = quote! {
  384. #param_vec_code
  385. if #vec_len_var != #instance_var.#thisvar.len() {
  386. return Err(InvalidInstance::new(format!(
  387. "Instance variables {} and {} must have the same length",
  388. stringify!(#firstvar),
  389. stringify!(#thisvar),
  390. )));
  391. }
  392. };
  393. }
  394. if !vec_witness_varvec.is_empty() {
  395. witness_vec_code = quote! {
  396. #witness_vec_code
  397. let #vec_len_var = instance.#firstvar.len();
  398. };
  399. }
  400. for witvar in vec_witness_varvec {
  401. witness_vec_code = quote! {
  402. #witness_vec_code
  403. if #vec_len_var != witness.#witvar.len() {
  404. eprintln!(
  405. "Instance variables {} and {} must have the same length",
  406. stringify!(#firstvar),
  407. stringify!(#witvar),
  408. );
  409. return Err(InvalidWitness);
  410. }
  411. }
  412. }
  413. };
  414. if right_is_vec {
  415. eq_code = quote! {
  416. #eq_code
  417. let #eq_id = (#right_tokens)
  418. .iter()
  419. .cloned()
  420. .map(|lr| #lr_var.allocate_eq(lr))
  421. .collect::<Vec<_>>();
  422. };
  423. element_assigns = quote! {
  424. #element_assigns
  425. (#left_tokens)
  426. .iter()
  427. .zip(#eq_id.iter())
  428. .for_each(|(l,eq)| #lr_var.set_element(*eq, *l));
  429. };
  430. } else {
  431. eq_code = quote! {
  432. #eq_code
  433. let #eq_id = #lr_var.allocate_eq(#right_tokens);
  434. };
  435. element_assigns = quote! {
  436. #element_assigns
  437. #lr_var.set_element(#eq_id, #left_tokens);
  438. }
  439. }
  440. }
  441. (
  442. quote! {
  443. {
  444. let mut #lr_var = LinearRelation::<Point>::new();
  445. #param_vec_code
  446. #scalar_allocs
  447. #element_allocs
  448. #eq_code
  449. #element_assigns
  450. ComposedInstance::try_from(#lr_var)
  451. }
  452. },
  453. quote! {
  454. {
  455. #witness_vec_code
  456. let mut witnessvec = Vec::new();
  457. #witness_code
  458. Result::<_, InvalidWitness>::Ok(ComposedWitness::Simple(witnessvec))
  459. }
  460. },
  461. )
  462. }
  463. /// Generate the code for the `protocol` and `protocol_witness`
  464. /// functions that create the `ComposedInstance` and `ComposedWitness`
  465. /// structs, respectively, given a [`StatementTree`] describing the
  466. /// statements to be proven. The output components are the code for
  467. /// the `protocol` and `protocol_witness` functions, respectively.
  468. /// The instance code evaluates to
  469. /// `Result<ComposedInstance<Point>, InvalidInstance>`; the witness code
  470. /// evaluates to `Result<ComposedWitness<Point>, InvalidWitness>`.
  471. fn instance_witness_codegen(&self, statement: &StatementTree) -> (TokenStream, TokenStream) {
  472. match statement {
  473. // The StatementTree has no statements (it's just the single
  474. // leaf "true")
  475. StatementTree::Leaf(_) if statement.is_leaf_true() => (
  476. quote! {
  477. ComposedInstance::try_from(LinearRelation::<Point>::new())
  478. },
  479. quote! {
  480. Result::<_, InvalidWitness>::Ok(ComposedWitness::Simple(vec![]))
  481. },
  482. ),
  483. // The StatementTree is a single statement. Generate a
  484. // single LinearRelation from it.
  485. StatementTree::Leaf(leafexpr) => {
  486. self.linear_relation_codegen(std::slice::from_ref(&leafexpr))
  487. }
  488. // The StatementTree is an And. Separate out the leaf
  489. // statements, and generate a single LinearRelation from
  490. // them. Then if there are non-leaf nodes as well, And them
  491. // together.
  492. StatementTree::And(stvec) => {
  493. let mut leaves: Vec<&Expr> = Vec::new();
  494. let mut others: Vec<&StatementTree> = Vec::new();
  495. for st in stvec {
  496. match st {
  497. StatementTree::Leaf(le) => leaves.push(le),
  498. _ => others.push(st),
  499. }
  500. }
  501. let (instance_code, witness_code) = self.linear_relation_codegen(&leaves);
  502. if others.is_empty() {
  503. (instance_code, witness_code)
  504. } else {
  505. let (other_instances, other_witnesses): (Vec<TokenStream>, Vec<TokenStream>) =
  506. others
  507. .iter()
  508. .map(|st| self.instance_witness_codegen(st))
  509. .unzip();
  510. (
  511. quote! {
  512. ComposedInstance::and([
  513. #instance_code?,
  514. #(#other_instances?,)*
  515. ])
  516. },
  517. quote! {
  518. Result::<_, InvalidWitness>::Ok(ComposedWitness::and([
  519. #witness_code?,
  520. #(#other_witnesses?,)*
  521. ]))
  522. },
  523. )
  524. }
  525. }
  526. StatementTree::Or(stvec) => {
  527. let (instances, witnesses): (Vec<TokenStream>, Vec<TokenStream>) = stvec
  528. .iter()
  529. .map(|st| self.instance_witness_codegen(st))
  530. .unzip();
  531. (
  532. quote! {
  533. ComposedInstance::or([
  534. #(#instances?,)*
  535. ])
  536. },
  537. quote! {
  538. Result::<_, InvalidWitness>::Ok(ComposedWitness::or([
  539. #(#witnesses?,)*
  540. ]))
  541. },
  542. )
  543. }
  544. StatementTree::Thresh(thresh, stvec) => {
  545. let (instances, witnesses): (Vec<TokenStream>, Vec<TokenStream>) = stvec
  546. .iter()
  547. .map(|st| self.instance_witness_codegen(st))
  548. .unzip();
  549. (
  550. quote! {
  551. ComposedInstance::threshold(#thresh, [
  552. #(#instances?,)*
  553. ])
  554. },
  555. quote! {
  556. Result::<_, InvalidWitness>::Ok(ComposedWitness::threshold([
  557. #(#witnesses?,)*
  558. ]))
  559. },
  560. )
  561. }
  562. }
  563. }
  564. /// Generate the code that uses the `sigma-proofs` API to prove and
  565. /// verify the statements in the [`CodeGen`].
  566. ///
  567. /// `emit_prover` and `emit_verifier` are as in
  568. /// [`sigma_compiler_core`](super::super::sigma_compiler_core).
  569. pub fn generate(&mut self, emit_prover: bool, emit_verifier: bool) -> TokenStream {
  570. let proto_name = &self.proto_name;
  571. let group_name = &self.group_name;
  572. let group_types = quote! {
  573. use super::group;
  574. pub type Scalar = <super::#group_name as group::Group>::Scalar;
  575. pub type Point = super::#group_name;
  576. };
  577. // Flatten nested "And"s into single "And"s
  578. self.statements.flatten_ands();
  579. let mut pub_instance_fields = StructFieldList::default();
  580. pub_instance_fields.push_vars(self.vars, true);
  581. // Generate the public instance struct definition
  582. let instance_def = {
  583. let decls = pub_instance_fields.field_decls();
  584. #[cfg(feature = "dump")]
  585. let dump_impl = {
  586. let dump_chunks = pub_instance_fields.dump(&format_ident!("fmt"));
  587. quote! {
  588. impl Instance {
  589. fn dump_scalar(s: &Scalar, fmt: &mut std::fmt::Formatter<'_>) {
  590. let bytes: &[u8] = &s.to_repr();
  591. for b in bytes.iter().rev() {
  592. // It's not a big deal if writes fail
  593. // here, so we use "ok()" to ignore the
  594. // `Result`
  595. write!(fmt, "{:02x}", b).ok();
  596. }
  597. }
  598. fn dump_point(p: &Point, fmt: &mut std::fmt::Formatter<'_>) {
  599. let bytes: &[u8] = &p.to_bytes();
  600. for b in bytes.iter().rev() {
  601. // It's not a big deal if writes fail
  602. // here, so we use "ok()" to ignore the
  603. // `Result`
  604. write!(fmt, "{:02x}", b).ok();
  605. }
  606. }
  607. }
  608. impl std::fmt::Debug for Instance {
  609. fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  610. #dump_chunks
  611. Ok(())
  612. }
  613. }
  614. }
  615. };
  616. #[cfg(not(feature = "dump"))]
  617. let dump_impl = {
  618. quote! {}
  619. };
  620. quote! {
  621. #[derive(Clone)]
  622. pub struct Instance {
  623. #decls
  624. }
  625. #dump_impl
  626. }
  627. };
  628. let mut witness_fields = StructFieldList::default();
  629. witness_fields.push_vars(self.vars, false);
  630. // Generate the witness struct definition
  631. let witness_def = if emit_prover {
  632. let decls = witness_fields.field_decls();
  633. quote! {
  634. #[derive(Clone)]
  635. pub struct Witness {
  636. #decls
  637. }
  638. }
  639. } else {
  640. quote! {}
  641. };
  642. let (instance_code, witness_code) = self.instance_witness_codegen(self.statements);
  643. // Generate the function that creates the sigma-proofs ComposedInstance
  644. let instance_func = {
  645. let instance_var = format_ident!("{}instance", self.unique_prefix);
  646. quote! {
  647. fn protocol(
  648. #instance_var: &Instance,
  649. ) -> Result<ComposedInstance<Point>, InvalidInstance> {
  650. #instance_code
  651. }
  652. }
  653. };
  654. // Generate the function that creates the sigma-proofs ComposedWitness
  655. let witness_func = if emit_prover {
  656. quote! {
  657. fn protocol_witness(
  658. instance: &Instance,
  659. witness: &Witness,
  660. ) -> Result<ComposedWitness<Point>, InvalidWitness> {
  661. #witness_code
  662. }
  663. }
  664. } else {
  665. quote! {}
  666. };
  667. // Generate the prove function
  668. let prove_func = if emit_prover {
  669. let instance_var = format_ident!("{}instance", self.unique_prefix);
  670. let witness_var = format_ident!("{}witness", self.unique_prefix);
  671. let session_id_var = format_ident!("{}session_id", self.unique_prefix);
  672. let composed_instance_var = format_ident!("{}composed_instance", self.unique_prefix);
  673. let composed_witness_var = format_ident!("{}composed_witness", self.unique_prefix);
  674. quote! {
  675. pub fn prove(
  676. #instance_var: &Instance,
  677. #witness_var: &Witness,
  678. #session_id_var: &[u8],
  679. ) -> Result<Vec<u8>, InvalidWitness> {
  680. let #composed_instance_var = protocol(#instance_var)?;
  681. let #composed_witness_var = protocol_witness(#instance_var, #witness_var)?;
  682. sigma_proofs::prove_compact(
  683. #session_id_var, &#composed_instance_var, &#composed_witness_var,
  684. )
  685. }
  686. }
  687. } else {
  688. quote! {}
  689. };
  690. // Generate the verify function
  691. let verify_func = if emit_verifier {
  692. let instance_var = format_ident!("{}instance", self.unique_prefix);
  693. let proof_var = format_ident!("{}proof", self.unique_prefix);
  694. let session_id_var = format_ident!("{}session_id", self.unique_prefix);
  695. let composed_instance_var = format_ident!("{}composed_instance", self.unique_prefix);
  696. quote! {
  697. pub fn verify(
  698. #instance_var: &Instance,
  699. #proof_var: &[u8],
  700. #session_id_var: &[u8],
  701. ) -> Result<(), VerificationError> {
  702. let #composed_instance_var = protocol(#instance_var)?;
  703. sigma_proofs::verify_compact(#session_id_var, &#composed_instance_var, #proof_var)
  704. }
  705. }
  706. } else {
  707. quote! {}
  708. };
  709. // Output the generated module for this protocol
  710. let dump_use = if cfg!(feature = "dump") {
  711. quote! {
  712. use group::GroupEncoding;
  713. }
  714. } else {
  715. quote! {}
  716. };
  717. quote! {
  718. #[allow(non_snake_case)]
  719. pub mod #proto_name {
  720. use super::sigma_compiler;
  721. use sigma_compiler::sigma_proofs;
  722. use sigma_compiler::group::ff::PrimeField;
  723. use sigma_compiler::subtle::CtOption;
  724. use sigma_compiler::vecutils::*;
  725. use sigma_proofs::{
  726. composition::{ComposedInstance, ComposedWitness},
  727. errors::{InvalidInstance, InvalidWitness, VerificationError},
  728. LinearRelation,
  729. };
  730. use std::ops::Neg;
  731. #dump_use
  732. #group_types
  733. #instance_def
  734. #witness_def
  735. #instance_func
  736. #witness_func
  737. #prove_func
  738. #verify_func
  739. }
  740. }
  741. }
  742. }