Skip to content

Commit

Permalink
feat: export circom verifier
Browse files Browse the repository at this point in the history
  • Loading branch information
eigmax committed Mar 30, 2024
1 parent ac23f38 commit 8b68283
Show file tree
Hide file tree
Showing 15 changed files with 102 additions and 31 deletions.
3 changes: 0 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,3 @@ members = [
"dsl_compile"
, "fields", "recursion"]
resolver = "2"
[patch."https://github.com/privacy-scaling-explorations/halo2"]

halo2_proofs = { git = "https://github.com/georgwiese/halo2", branch = "make-emit-public-v0.3.0", features = ["circuit-params"] }
1 change: 1 addition & 0 deletions dsl_compile/src/input_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::errors::{bail, DslError, Result};
use ansi_term::Colour;
use std::path::{Path, PathBuf};

#[allow(dead_code)]
pub struct Input {
pub input_program: PathBuf,
pub out_r1cs: PathBuf,
Expand Down
5 changes: 2 additions & 3 deletions recursion/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,9 @@ starky = { path = "../starky", default-features = false }
plonky = { path = "../plonky", default-features = false }
algebraic = { path = "../algebraic", default-features = false }

powdr = { git = "https://github.com/powdr-labs/powdr.git", rev = "450e3f1" }
powdr = { git = "https://github.com/powdr-labs/powdr.git", rev = "450e3f1" }
powdr-ast = { git = "https://github.com/powdr-labs/powdr.git", rev = "450e3f1" }
powdr-pil-analyzer = { git = "https://github.com/powdr-labs/powdr.git", rev = "450e3f1" }

powdr-pil-analyzer = { git = "https://github.com/powdr-labs/powdr.git", rev = "450e3f1" }

[dev-dependencies]
env_logger = "0.10"
Expand Down
9 changes: 5 additions & 4 deletions recursion/src/pilcom.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
//! Poring from https://github.com/powdr-labs/powdr.git.
use std::rc::Rc;
mod export;
mod expression_counter;

pub use export::export;

use powdr::number::GoldilocksField;
use starky::types::PIL;
use std::path::Path;

pub fn compile_pil_from_str(pil_str: &str) -> PIL {
let analyze = powdr_pil_analyzer::analyze_string::<GoldilocksField>(pil_str);

export::export(&analyze)
export(Rc::new(analyze))
}
pub fn compile_pil_from_path(pil_path: &str) -> PIL {
let analyze = powdr_pil_analyzer::analyze_file::<GoldilocksField>(Path::new(pil_path));

export::export(&analyze)
export(Rc::new(analyze))
}

#[cfg(test)]
Expand Down
4 changes: 2 additions & 2 deletions recursion/src/pilcom/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ struct Exporter<'a, T> {
number_q: u64,
}

pub fn export<T: FieldElement>(analyzed: &Analyzed<T>) -> PIL {
let mut exporter = Exporter::new(analyzed);
pub fn export<T: FieldElement>(analyzed: std::rc::Rc<Analyzed<T>>) -> PIL {
let mut exporter = Exporter::new(&analyzed);
let mut publics = Vec::new();
let mut pol_identities = Vec::new();
let mut plookup_identities = Vec::new();
Expand Down
4 changes: 2 additions & 2 deletions starkjs/fibonacci/fibonacci.pil
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ namespace Fibonacci(%N);
pol constant L1, LLAST;
pol commit l1,l2;

pol l2c = l2;
//pol l2c = l2;

public in1 = l2c(0);
public in1 = l2(0);
public in2 = l1(0);
public out = l1(%N-1);

Expand Down
3 changes: 3 additions & 0 deletions zkvm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ itertools = "0.12.0"
log = "0.4.0"

powdr = { git = "https://github.com/powdr-labs/powdr", rev = "450e3f1" }
starky = { path = "../starky" }
recursion = { path = "../recursion" }

hex = "0.4.3"
thiserror = "1.0"
serde_json = "1.0.108"
anyhow = "1.0.79"
tempfile = "3"

[dev-dependencies]
env_logger = "0.10"
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 2 additions & 1 deletion zkvm/vm/evm/src/lib.rs → zkvm/program/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use alloc::string::String;
use alloc::string::ToString;

use k256::ecdsa::SigningKey;
const TEST_CHANNEL: u32 = 1;

/// Recover the address from a private key (SigningKey).
pub fn recover_address(private_key: &[u8]) -> Option<Address> {
Expand All @@ -28,7 +29,7 @@ pub fn recover_address(private_key: &[u8]) -> Option<Address> {

#[no_mangle]
fn main() {
let suite_json: String = get_data_serde(666);
let suite_json: String = get_data_serde(TEST_CHANNEL);
print!("suite_json: {suite_json}\n");
let suite = read_suite(&suite_json);

Expand Down
3 changes: 1 addition & 2 deletions zkvm/vm/lr/Cargo.toml → zkvm/program/lr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
powdr-riscv-runtime = { git = "https://github.com/eigmax/powdr", branch = "main" }

powdr-riscv-runtime = { git = "https://github.com/powdr-labs/powdr", rev = "450e3f1" }

[workspace]
File renamed without changes.
File renamed without changes.
98 changes: 84 additions & 14 deletions zkvm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
use anyhow::Result;
use powdr::backend::BackendType;
use powdr::number::{FieldElement, GoldilocksField};
use powdr::riscv::continuations::{
bootloader::default_input, rust_continuations, rust_continuations_dry_run,
};
use powdr::number::{DegreeType, FieldElement, GoldilocksField};
use powdr::riscv::continuations::{rust_continuations, rust_continuations_dry_run};
use powdr::riscv::{compile_rust, CoProcessors};
use powdr::Pipeline;
use recursion::pilcom::export as pil_export;
use starky::{
merklehash::MerkleTreeGL,
pil2circom,
stark_setup::StarkSetup,
types::{StarkStruct, Step},
};
use std::fs;
use std::path::Path;
use std::time::Instant;

Expand All @@ -25,18 +31,71 @@ fn generate_witness_and_prove<F: FieldElement>(

pipeline = pipeline.with_backend(BackendType::EStark);
pipeline.compute_proof().unwrap();

let duration = start.elapsed();
log::debug!("Proving took: {:?}", duration);
Ok(())
}

fn generate_verifier<F: FieldElement, W: std::io::Write>(
mut pipeline: Pipeline<F>,
mut writer: W,
) -> Result<()> {
// TODO: don't write it to disk, we should discuss with powdr-labs to provide a function for
//pipeline to return the vk directly.
let mut tf = tempfile::tempfile().unwrap();
pipeline.export_verification_key(&mut tf).unwrap();
let mut setup: StarkSetup<MerkleTreeGL> = serde_json::from_reader(tf).unwrap();

let pil = pipeline.optimized_pil().unwrap();

let degree = pil.degree();
assert!(degree > 1);
let n_bits = (DegreeType::BITS - (degree - 1).leading_zeros()) as usize;
let n_bits_ext = n_bits + 1;

let steps = (2..=n_bits_ext)
.rev()
.step_by(4)
.map(|b| Step { nBits: b })
.collect();

let params = StarkStruct {
nBits: n_bits,
nBitsExt: n_bits_ext,
nQueries: 2,
verificationHashType: "GL".to_owned(),
steps,
};

// generate circom
let opt = pil2circom::StarkOption {
enable_input: false,
verkey_input: false,
skip_main: true,
agg_stage: false,
};
if !setup.starkinfo.qs.is_empty() {
let pil_json = pil_export::<F>(pil);
let str_ver = pil2circom::pil2circom(
&pil_json,
&setup.const_root,
&params,
&mut setup.starkinfo,
&mut setup.program,
&opt,
)
.unwrap();
writer.write_fmt(format_args!("{}", str_ver))?;
}
Ok(())
}

pub fn zkvm_evm_execute_and_prove(task: &str, suite_json: String, output_path: &str) -> Result<()> {
log::debug!("Compiling Rust...");
let force_overwrite = true;
let with_bootloader = true;
let (asm_file_path, asm_contents) = compile_rust::<GoldilocksField>(
&format!("vm/{task}"),
&format!("program/{task}"),
Path::new(output_path),
force_overwrite,
&CoProcessors::base().with_poseidon(),
Expand All @@ -59,6 +118,7 @@ pub fn zkvm_evm_execute_and_prove(task: &str, suite_json: String, output_path: &
let duration = start.elapsed();
log::debug!("Computing fixed columns took: {:?}", duration);

/*
log::debug!("Running powdr-riscv executor in fast mode...");
let start = Instant::now();
Expand All @@ -69,10 +129,10 @@ pub fn zkvm_evm_execute_and_prove(task: &str, suite_json: String, output_path: &
&default_input(&[]),
powdr::riscv_executor::ExecMode::Fast,
);

let duration = start.elapsed();
log::debug!("Fast executor took: {:?}", duration);
log::debug!("Trace length: {}", trace.len);
*/

log::debug!("Running powdr-riscv executor in trace mode for continuations...");
let start = Instant::now();
Expand Down Expand Up @@ -119,6 +179,7 @@ pub fn zkvm_evm_generate_chunks(

log::debug!("Running powdr-riscv executor in fast mode...");

/*
let (trace, _mem) = powdr::riscv_executor::execute::<GoldilocksField>(
&asm_contents,
powdr::riscv_executor::MemoryState::new(),
Expand All @@ -128,7 +189,7 @@ pub fn zkvm_evm_generate_chunks(
);
log::debug!("Trace length: {}", trace.len);

*/
log::debug!("Running powdr-riscv executor in trace mode for continuations...");
let start = Instant::now();

Expand Down Expand Up @@ -158,12 +219,25 @@ pub fn zkvm_evm_prove_only(
.with_output(output_path.into(), true)
.from_asm_file(asm_file_path.clone())
.with_prover_inputs(Default::default())
.with_existing_proof_file(Some(Path::new(output_path).to_path_buf()))
.add_data(TEST_CHANNEL, suite_json);

log::debug!("Running witness generation and proof computation...");
let start = Instant::now();

rust_continuation(pipeline, generate_witness_and_prove, bootloader_input, i).unwrap();
//TODO: if we clone it, we lost the information gained from this function
rust_continuation(
pipeline.clone(),
generate_witness_and_prove,
bootloader_input,
i,
)
.unwrap();

let verifer_file = Path::new(output_path).join(format!("{}_chunk_{}.circom", task, i));
let f = fs::File::open(verifer_file)?;
log::debug!("Running circom verifier generation...");
generate_verifier(pipeline, f).unwrap();

let duration = start.elapsed();
log::debug!(
Expand Down Expand Up @@ -204,10 +278,6 @@ mod tests {
use num_traits::identities::Zero;
use std::io::{Read, Write};

use std::fs;

//use revm::primitives::address;

// RUST_MIN_STACK=2073741821 RUST_LOG=debug proxychains nohup cargo test --release test_zkvm_evm_prove -- --nocapture &
#[test]
#[ignore]
Expand Down Expand Up @@ -241,7 +311,7 @@ mod tests {

let output_path = "/tmp/test_lr";
let task = "lr";
let workspace = format!("vm/{}", task);
let workspace = format!("program/{}", task);
let bootloader_inputs =
zkvm_evm_generate_chunks(workspace.as_str(), &suite_json, output_path).unwrap();
// save the chunks
Expand Down

0 comments on commit 8b68283

Please sign in to comment.