Skip to content
This repository was archived by the owner on Mar 14, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ members = [
"cargo-rcc",
"circuit-examples",
"rcc",
"rcc-lib",
"rcc-halo2",
"rcc-macro",
"rcc-mockbuilder",
Expand All @@ -15,3 +16,8 @@ halo2_proofs = { git = "https://github.com/powdr-org/halo2", branch = "kilic/shu
[patch.crates-io]
halo2_proofs = { git = "https://github.com/powdr-org/halo2", branch = "kilic/shuffle"}

[profile.dev.package."circuit-examples"]
debug = false
debug-assertions = false
overflow-checks = false

1 change: 1 addition & 0 deletions circuit-examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ license = "MIT OR Apache-2.0"

[dependencies]
rcc = { path = "../rcc" }
rcc-lib = { path = "../rcc-lib" }
rcc-macro = { path = "../rcc-macro" }
rcc-mockbuilder = { path = "../rcc-mockbuilder" }
rcc-halo2 = { path = "../rcc-halo2" }
Expand Down
8 changes: 5 additions & 3 deletions circuit-examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ well as a circuit config file `example/halo2_example_config.toml`.
To run mock proof generation with input `999`, run

```
time cargo run --release --example halo2_example_runtime 999
time cargo run --example halo2_example_runtime 999
```

Note that we recommend compiling and running the witness generator in `dev`
mode, as running it in `release` mode could result a 50x slower compilation time.

## Witness generator speed test

An example circuit is given in [`examples/mock_example.rs`](examples/mock_example.rs).
Expand All @@ -37,7 +40,7 @@ This will generate the runtime library file for the circuit in
set to `999`, run

```
time cargo run --release --example mock_example_runtime 999
time cargo run --example mock_example_runtime 999
```

A Circom circuit of equivalent functionality is given in
Expand All @@ -49,4 +52,3 @@ commands inside `example_circom`.
time circom example.circom --wasm
time node example_js/generate_witness.js example_js/example.wasm input.json outputs.wtns
```

14 changes: 4 additions & 10 deletions circuit-examples/examples/halo2_example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,9 @@ fn gen(val: W) -> Vec<(W, W)> {
fn my_circuit() {
let val = input_wire("val");

// let ab = gen(val);
// let c: Vec<W> = ab.iter().map(|(ai, bi)| mul_seq(*ai, *bi)).collect();
// let sum = sum(c);
let ab = gen(val);
let c: Vec<W> = ab.iter().map(|(ai, bi)| mul_seq(*ai, *bi)).collect();
let sum = sum(c);

val.declare_public("val");
// sum.declare_public("sum");

let bits = val.to_bits_be_strict();
for (i, b) in bits.iter().enumerate() {
b.declare_public(format!("{i}").as_str());
}
sum.declare_public("sum");
}
26 changes: 26 additions & 0 deletions circuit-examples/examples/sha256_example.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// use rcc_halo2::builder::{H2Wire as W, *};
use rcc_mockbuilder::mock_builder::{MockWire as W, *};
use rcc::traits::{UInt32, NaiveUInt32, BoolWire};
use rcc_lib::sha256::*;

type U32 = NaiveUInt32<Boolean<W>>;

fn read_u32() -> U32 {
let v: Vec<_> = (0..32).map(|i| {
let w = input_wire(format!("{}-th bit", i).as_str());
builder().assert_bool(w)
}).collect();
U32 { repr: v.try_into().unwrap_or_else(|_| [Boolean::<W>::from_const(0); 32]) }
}

/// This circuit takes input a 4-byte string, interprets it as a U32 and hashes it via SHA256
#[main_component]
fn my_circuit() {
let a = read_u32();

let hash: [U32; 8] = sha256(vec![a; 1]);

for (i, u) in hash.iter().enumerate() {
u.to_dense().declare_public(format!("{i}").as_str());
}
}
55 changes: 55 additions & 0 deletions circuit-examples/examples/sha256_example_runtime.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#![allow(unused_imports)]
#![allow(unused_parens)]
#![allow(non_upper_case_globals)]
#![allow(unused_variables)]
#![allow(unused_mut)]

mod sha256_example_runtime_lib;
use sha256_example_runtime_lib::generate_witnesses;

use ark_bn254::Fr as F;
use rcc_mockbuilder::runtime::{BigUint, PrimeField};

/// Generated via ChatGPT
fn string_to_bool_vector(input: &str) -> Vec<bool> {
// Check if the input string has exactly 4 bytes
if input.len() != 4 {
panic!("Input string must be exactly 4 bytes long");
}

let mut bool_vector = Vec::with_capacity(32); // 4 bytes * 8 bits per byte = 32 bits

for byte in input.bytes() {
// Convert the byte into a u8
let byte_value = byte as u8;

// Iterate through each bit in the byte (from left to right)
for i in (0..8).rev() {
// Check if the i-th bit is set (1) or not (0)
let bit_is_set = (byte_value >> i) & 1 == 1;

// Push the result into the bool vector
bool_vector.push(bit_is_set);
}
}

bool_vector
}

fn main() {
let args: Vec<String> = std::env::args().collect();
let mut inputs = std::collections::HashMap::<String, F>::new();

for (i, b) in string_to_bool_vector(args[1].as_str()).iter().enumerate() {
inputs.insert(format!("{i}-th bit"), F::from(*b));
}

let (witness, public) = generate_witnesses(inputs);

print!("hash: ");
(0..8).for_each(|i| {
let bu: BigUint = public.get(format!("{i}").as_str()).unwrap().into_bigint().into();
print!("{}", bu.to_str_radix(16));
});
println!("");
}
67 changes: 44 additions & 23 deletions rcc-halo2/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#![allow(unused_must_use)]

pub use rcc::{
traits::{AlgBuilder, AlgWire, Boolean, ToBits, ToBitsBuilder},
traits::{AlgBuilder, AlgWire, BoolWire, Boolean, ToBits, ToBitsBuilder},
Builder, WireLike,
};
pub use rcc_macro::{component, component_of, main_component};
Expand Down Expand Up @@ -205,8 +205,8 @@ impl H2Builder {

/// Fill the selector vector until it is of the same length as the witness vector
fn fill_selectors(&mut self) {
let n = self.witness.len() - self.selectors.len();
if n > 0 {
if self.witness.len() > self.selectors.len() {
let n = self.witness.len() - self.selectors.len();
self.selectors.extend((0..n).map(|_| 0))
}
}
Expand Down Expand Up @@ -241,22 +241,6 @@ impl H2Builder {
b
}

/// Add a new wire to the witness column that is constraint to `v`
pub fn new_constant_wire(&mut self, v: F) -> H2Wire {
let constant_index = if self.constants.contains_key(&v) {
*self.constants.get(&v).unwrap()
} else {
let l = self.constants.len();
self.constants.insert(v, l);
l
};
let w = self.new_wire();
let us = format!("{}", v.into_bigint());
self.composer.runtime(quote!( #w = F::from(BigInt!(#us)); ));
self.copys[2].offsets.push((w.row, constant_index));
w
}

/// Compose runtime code that logs the value of a wire
pub fn log(&mut self, wire: H2Wire) {
self.runtime(quote! {
Expand Down Expand Up @@ -430,6 +414,24 @@ impl AlgBuilder for H2Builder {
type Constant = F;
type Bool = Boolean<Self::Wire>;

/// Add a new wire to the witness column that is constraint to `v`
fn new_constant_wire(&mut self, v: F) -> H2Wire {
let constant_index = if self.constants.contains_key(&v) {
*self.constants.get(&v).unwrap()
} else {
let l = self.constants.len();
self.constants.insert(v, l);
l
};
let w = self.new_wire();
let us = format!("{}", v.into_bigint());
self.composer.runtime(quote!( #w = F::from(BigInt!(#us)); ));
self.copys[2].offsets.push((w.row, constant_index));
self.fill_selectors();
w
}


#[component_of(self)]
/// Add gadget
fn add(&mut self, a: H2Wire, b: H2Wire) -> H2Wire {
Expand Down Expand Up @@ -678,12 +680,31 @@ impl ToBitsBuilder for H2Builder {
v
}

fn from_bits_be(&mut self, _: Vec<Self::Bool>) -> Self {
todo!()
fn from_bits_be(&mut self, bits: Vec<Self::Bool>) -> Self::Wire {
let v = self.new_wire();
let num_bits = bits.len();

let mut carry = F::from(1);
let mut pow2 = vec![];
(0..num_bits).for_each(|_| {
pow2.push(self.new_constant_wire(carry));
carry *= F::from(2);
});
pow2.reverse();

for (i, bit) in bits.iter().enumerate() {
let alg_bit = bit.to_alg();
let c = pow2[i];
self.runtime(quote! {
#v = #v + #alg_bit * #c;
});
}
v
}

fn from_bits_le(&mut self, _: Vec<Self::Bool>) -> Self {
todo!()
fn from_bits_le(&mut self, mut bits: Vec<Self::Bool>) -> Self::Wire {
bits.reverse();
self.from_bits_be(bits)
}
}

Expand Down
2 changes: 1 addition & 1 deletion rcc-halo2/src/runtime.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use polyexen::plaf::{ColumnWitness, Witness};

pub use ark_bn254::Fr as F;
pub use ark_ff::{BigInt, BigInteger, Field};
pub use ark_ff::{BigInt, BigInteger, Field, PrimeField};
pub use halo2_proofs::halo2curves::bn256::Fr;
pub use num_bigint::BigUint;

Expand Down
8 changes: 8 additions & 0 deletions rcc-lib/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "rcc-lib"
version = "0.0.1"
edition = "2021"
license = "MIT OR Apache-2.0"

[dependencies]
rcc = { path = "../rcc" }
2 changes: 2 additions & 0 deletions rcc-lib/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod sha256;
pub use sha256::*;
Loading