ethdos-fold/src/lib.rs
src/lib.rsRaw
1//! This file contains the WASM bindings.
2//!
3#![allow(non_snake_case)]
4#![allow(dead_code)]
5#![allow(non_camel_case_types)]
6#![allow(clippy::upper_case_acronyms)]
7
8use ark_bn254::{Fr, G1Projective as G1};
9use ark_ec::AffineRepr;
10use ark_grumpkin::Projective as G2;
11use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
12use ark_std::Zero;
13use base64::{engine::general_purpose::STANDARD as b64, Engine as _};
14use rand::rngs::OsRng;
15
16use arkeddsa::ed_on_bn254_twist::{constraints::EdwardsVar, EdwardsProjective};
17
18use folding_schemes::{
19 commitment::pedersen::Pedersen,
20 folding::nova::{Nova, PreprocessorParam},
21 frontend::FCircuit,
22 transcript::poseidon::poseidon_canonical_config,
23 FoldingScheme,
24};
25
26use crate::fcircuit::EthDosCircuit;
27use crate::signature::{gen_signatures, SigPk};
28use crate::utils::{dbg, elapsed, get_time};
29
30mod fcircuit;
31mod fold_ethdos;
32mod signature;
33mod utils;
34
35use wasm_bindgen::prelude::*;
36
37// define type aliases for the FCircuit (FC) and the FoldingScheme (FS), to avoid writting the
38// whole type each time.
39type FC = EthDosCircuit<Fr, EdwardsProjective, EdwardsVar>;
40type FS = Nova<G1, G2, FC, Pedersen<G1>, Pedersen<G2>, false>;
41
42#[wasm_bindgen]
43extern "C" {
44 fn alert(s: &str);
45}
46
47#[wasm_bindgen]
48pub fn gen_params() -> Vec<String> {
49 let mut rng = OsRng;
50 let poseidon_config = poseidon_canonical_config::<Fr>();
51
52 let f_circuit = FC::new(poseidon_config.clone()).unwrap();
53
54 let nova_preprocess_params = PreprocessorParam::new(poseidon_config.clone(), f_circuit.clone());
55 let start = get_time();
56 let nova_params = FS::preprocess(&mut rng, &nova_preprocess_params).unwrap();
57 dbg(format!("Nova params generated: {:?}ms", elapsed(start)));
58
59 // serialize
60 let start = get_time();
61 let mut prover_params_serialized = vec![];
62 nova_params
63 .0
64 .serialize_compressed(&mut prover_params_serialized)
65 .unwrap();
66 dbg(format!(
67 "Nova prover params serialized: {:?}ms",
68 elapsed(start)
69 ));
70
71 let start = get_time();
72 let mut verifier_params_serialized = vec![];
73 nova_params
74 .1
75 .serialize_compressed(&mut verifier_params_serialized)
76 .unwrap();
77 dbg(format!(
78 "Nova prover params serialized: {:?}ms",
79 elapsed(start)
80 ));
81
82 dbg(format!(
83 "prover_params size: {} mb",
84 prover_params_serialized.len() / (1024 * 1024)
85 ));
86 dbg(format!(
87 "verifier_params size: {} mb",
88 verifier_params_serialized.len() / (1024 * 1024)
89 ));
90
91 vec![
92 b64.encode(&prover_params_serialized),
93 b64.encode(&prover_params_serialized),
94 ]
95}
96
97#[wasm_bindgen]
98pub fn gen_sigs(n_steps: usize) -> Vec<String> {
99 let mut rng = OsRng;
100 let poseidon_config = poseidon_canonical_config::<Fr>();
101
102 let sigs: Vec<SigPk<EdwardsProjective>> = gen_signatures(&mut rng, &poseidon_config, n_steps);
103 let b: Vec<Vec<u8>> = sigs.iter().map(|&s| s.to_bytes()).collect();
104 b.iter().map(|s| b64.encode(s)).collect::<Vec<String>>()
105}
106
107#[wasm_bindgen]
108pub fn fold_sigs(params: Vec<String>, sigs_pks: Vec<String>) -> String {
109 dbg("starting fold_sigs (rust)".to_string());
110
111 let poseidon_config = poseidon_canonical_config::<Fr>();
112
113 // parse sigs_pks
114 let b: Vec<Vec<u8>> = sigs_pks.iter().map(|s| b64.decode(s).unwrap()).collect();
115 let pks_sigs: Vec<SigPk<EdwardsProjective>> =
116 b.iter().map(|s| SigPk::from_bytes(s.clone())).collect();
117
118 // parse params
119 let start = get_time();
120 let pp = FS::pp_deserialize_with_mode(
121 &mut b64.decode(params[0].clone()).unwrap().as_slice(),
122 ark_serialize::Compress::Yes,
123 ark_serialize::Validate::Yes,
124 poseidon_config.clone(), // fcircuit_params
125 )
126 .unwrap();
127 let vp = FS::vp_deserialize_with_mode(
128 &mut b64.decode(params[1].clone()).unwrap().as_slice(),
129 ark_serialize::Compress::Yes,
130 ark_serialize::Validate::Yes,
131 poseidon_config.clone(), // fcircuit_params
132 )
133 .unwrap();
134 let fs_params = (pp, vp);
135 dbg(format!(
136 "params (prover & verifier) deserialization: {:?}ms",
137 elapsed(start)
138 ));
139
140 // set the initial state
141 let xy = pks_sigs[0].pk.0.xy().unwrap();
142 let pk0 = vec![xy.0, xy.1];
143 let z_0: Vec<Fr> = [pk0.clone(), pk0, vec![Fr::zero()]].concat();
144
145 type FC = EthDosCircuit<Fr, EdwardsProjective, EdwardsVar>;
146 let f_circuit = FC::new(poseidon_config.clone()).unwrap();
147
148 // initialize the folding scheme engine, in our case we use Nova
149 let mut nova = FS::init(&fs_params, f_circuit, z_0.clone()).unwrap();
150 let rng = OsRng;
151 let n_steps = sigs_pks.len();
152
153 let start_full = get_time();
154 #[allow(clippy::needless_range_loop)]
155 for i in 0..n_steps {
156 let start = get_time();
157 nova.prove_step(rng, pks_sigs[i], None).unwrap();
158 dbg(format!(
159 "Nova::prove_step {}: {:?}ms",
160 nova.i,
161 elapsed(start)
162 ));
163 }
164 dbg(format!(
165 "Nova's all {} steps time: {:?}ms",
166 n_steps,
167 elapsed(start_full)
168 ));
169
170 let ivc_proof = nova.ivc_proof();
171 let mut ivc_proof_bytes = vec![];
172 ivc_proof
173 .serialize_compressed(&mut ivc_proof_bytes)
174 .unwrap();
175 dbg(format!(
176 "ivc_proof size: {} mb",
177 ivc_proof_bytes.len() / (1024 * 1024)
178 ));
179
180 b64.encode(ivc_proof_bytes)
181}
182
183#[wasm_bindgen]
184pub fn verify_proof(verifier_params: String, ivc_proof: String) -> String {
185 let poseidon_config = poseidon_canonical_config::<Fr>();
186
187 let vp = FS::vp_deserialize_with_mode(
188 &mut b64.decode(verifier_params.clone()).unwrap().as_slice(),
189 ark_serialize::Compress::Yes,
190 ark_serialize::Validate::Yes,
191 poseidon_config.clone(), // fcircuit_params
192 )
193 .unwrap();
194 // let proof =
195 // FS::IVCProof::deserialize_compressed(b64.decode(ivc_proof).unwrap().as_slice()).unwrap();
196 let proof = <Nova<G1, G2, FC, Pedersen<G1>, Pedersen<G2>, false> as FoldingScheme<
197 G1,
198 G2,
199 FC,
200 >>::IVCProof::deserialize_compressed(b64.decode(ivc_proof).unwrap().as_slice())
201 .unwrap();
202
203 FS::verify(
204 vp, // Nova's verifier params
205 proof,
206 )
207 .unwrap();
208 "verified".to_string()
209}