arnaucube
arnaucube/ethdos-foldPublic Self-hosted repository
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}