Hello World using powdr as a library

Besides the CLI, powdr can also be used as a Rust library. The powdr crate exposes internal crates and data structures needed to compile code, generate witnesses, and compute proofs.

Add powdr to your crate's dependencies:

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

The following Rust code has the same workflow as our previous "Hello World" example. The full project can be found here, and as an example in the powdr crate. To run the example in the powdr repository, run:

cargo run --example powdr_crate_usage

You can also enable logs to know what is happening internally:

RUST_LOG=info cargo run --example powdr_crate_usage
use powdr_test::halo2_pipeline;

fn main() {
    env_logger::init();

    halo2_pipeline(
        "test_data/asm/book/hello_world.asm",
        vec![0.into()],
        vec![],
        8,
    );
}
use powdr::backend::BackendType;
use powdr::number::buffered_write_file;
use powdr::Bn254Field;
use powdr::Pipeline;

use std::path::Path;

pub fn halo2_pipeline(
    pil: &str,
    prover_inputs: Vec<Bn254Field>,
    publics: Vec<Bn254Field>,
    setup_size: u64,
) {
    // Straightforward case
    let _proof = Pipeline::<Bn254Field>::default()
        .from_file(pil.into())
        .with_prover_inputs(prover_inputs.clone())
        .with_backend(BackendType::Halo2, None)
        .compute_proof()
        .unwrap();

    // Step-by-step case

    // First we create the universal setup of size 8
    buffered_write_file(Path::new("params.bin"), |writer| {
        BackendType::Halo2
            .factory::<Bn254Field>()
            .generate_setup(setup_size, writer)
            .unwrap()
    })
    .unwrap();

    // Configure a pipeline
    let mut pipeline = Pipeline::<Bn254Field>::default()
        .from_file(pil.into())
        .with_prover_inputs(prover_inputs)
        .with_backend(BackendType::Halo2, None)
        .with_setup_file(Some("params.bin".into()));

    // Create the verification key
    buffered_write_file(Path::new("vkey.bin"), |w| {
        pipeline.export_verification_key(w).unwrap()
    })
    .unwrap();

    // Add the verification key to a fresh pipeline and create a proof
    let mut pipeline_fresh = pipeline.clone().with_vkey_file(Some("vkey.bin".into()));

    let proof = pipeline_fresh.compute_proof().unwrap();

    // Create yet another fresh pipeline only for proof verification
    let mut pipeline = pipeline
        .with_backend(BackendType::Halo2, None)
        .with_setup_file(Some("params.bin".into()))
        .with_vkey_file(Some("vkey.bin".into()));

    // Verify a proof created by a different Pipeline
    pipeline.verify(proof, &[publics]).unwrap();
}