diff --git a/hash/plonky2/Cargo.toml b/hash/plonky2/Cargo.toml index cc7a85d..25ac85f 100644 --- a/hash/plonky2/Cargo.toml +++ b/hash/plonky2/Cargo.toml @@ -13,6 +13,8 @@ plonky2 = "0.2.2" rand = "0.8.3" anyhow = "1.0.79" sha2 = "0.10" +tiny-keccak={version="2.0.2", features=["keccak"]} +hex="0.4.3" diff --git a/hash/plonky2/src/arithmetic/u64_arithmetic.rs b/hash/plonky2/src/arithmetic/u64_arithmetic.rs index c33d2be..01b8c0f 100644 --- a/hash/plonky2/src/arithmetic/u64_arithmetic.rs +++ b/hash/plonky2/src/arithmetic/u64_arithmetic.rs @@ -18,6 +18,7 @@ pub trait CircuitBuilderU64, const D: usize> { fn zero_u64(&mut self) -> U64Target; fn not_u64(&mut self, a: U64Target) -> U64Target; + fn add_virtual_u64_target(&mut self) -> U64Target; } impl, const D: usize> CircuitBuilderU64 @@ -57,4 +58,8 @@ impl, const D: usize> CircuitBuilderU64 fn not_u64(&mut self, a: U64Target) -> U64Target { U64Target([self.not_u32(a.0[0]), self.not_u32(a.0[1])]) } + + fn add_virtual_u64_target(&mut self) -> U64Target { + U64Target([U32Target(self.add_virtual_target()),U32Target(self.add_virtual_target())]) + } } \ No newline at end of file diff --git a/hash/plonky2/src/bench/keccak256/chi.rs b/hash/plonky2/src/bench/keccak256/chi.rs deleted file mode 100644 index 5dd266b..0000000 --- a/hash/plonky2/src/bench/keccak256/chi.rs +++ /dev/null @@ -1,25 +0,0 @@ -use plonky2::hash::hash_types::RichField; -use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::field::extension::Extendable; -use crate::arithmetic::u64_arithmetic::CircuitBuilderU64; - -use crate::arithmetic::u64_arithmetic::U64Target; - -pub fn chi, const D: usize>( - builder: &mut CircuitBuilder, - state: &mut [[U64Target; 5]; 5] -){ - for x in 0..5 { - let mut temp = [builder.zero_u64(); 5]; - for y in 0..5 { - temp[y] = state[x][y]; - } - - - for y in 0..5 { - let t1 = builder.not_u64(temp[(y + 1) % 5]); - let t2 = builder.and_u64(t1, temp[(y + 2) % 5]); - state[x][y] = builder.xor_u64(state[x][y], t2); - } - } -} \ No newline at end of file diff --git a/hash/plonky2/src/bench/keccak256/iota.rs b/hash/plonky2/src/bench/keccak256/iota.rs deleted file mode 100644 index 511495c..0000000 --- a/hash/plonky2/src/bench/keccak256/iota.rs +++ /dev/null @@ -1,30 +0,0 @@ -use plonky2::hash::hash_types::RichField; -use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::field::extension::Extendable; -use crate::arithmetic::u64_arithmetic::CircuitBuilderU64; - -use crate::arithmetic::u64_arithmetic::U64Target; -use plonky2_u32::gadgets::arithmetic_u32::CircuitBuilderU32; - -const KECCAK_ROUNDS: usize = 24; - -const ROUND_CONSTANTS: [u64; KECCAK_ROUNDS] = [ - 0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000, - 0x000000000000808B, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009, - 0x000000000000008A, 0x0000000000000088, 0x0000000080008009, 0x000000008000000A, - 0x000000008000808B, 0x800000000000008B, 0x8000000000008089, 0x8000000000008003, - 0x8000000000008002, 0x8000000000000080, 0x000000000000800A, 0x800000008000000A, - 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008, -]; - -//iota -pub fn iota, const D: usize>( - builder: &mut CircuitBuilder, - state: &mut [[U64Target; 5]; 5], - round: usize -){ - - let lo = builder.constant_u32((ROUND_CONSTANTS[round] & 0xFFFFFFFF) as u32); - let hi = builder.constant_u32(((ROUND_CONSTANTS[round] >> 32)& 0xFFFFFFFF) as u32); - state[0][0] = builder.xor_u64(state[0][0], U64Target([lo,hi])) ; -} \ No newline at end of file diff --git a/hash/plonky2/src/bench/keccak256/keccak.rs b/hash/plonky2/src/bench/keccak256/keccak.rs index 79920c9..715c69b 100644 --- a/hash/plonky2/src/bench/keccak256/keccak.rs +++ b/hash/plonky2/src/bench/keccak256/keccak.rs @@ -1,699 +1,525 @@ -use plonky2::field::types::Field; -use plonky2::field::goldilocks_field::GoldilocksField; -use plonky2::hash::keccak::KeccakHash; -use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::plonk::circuit_data::CircuitConfig; -use plonky2::plonk::config::{GenericConfig, KeccakGoldilocksConfig}; +// code taken from https://github.com/qope/plonky2-keccak256/tree/main + +use std::marker::PhantomData; + +use plonky2::{ + field::extension::Extendable, + hash::hash_types::RichField, + iop::{ + target::BoolTarget, + witness::{PartialWitness, WitnessWrite}, + }, + plonk::circuit_builder::CircuitBuilder, + field::goldilocks_field::GoldilocksField, +}; +use std::time::Instant; use rand::Rng; -use plonky2::field::extension::Extendable; -use plonky2::plonk::config::Hasher; -use plonky2::hash::hash_types::RichField; -use plonky2_u32::gadgets::arithmetic_u32::CircuitBuilderU32; -use crate::arithmetic::u64_arithmetic::U64Target; -use crate::arithmetic::u64_arithmetic::CircuitBuilderU64; -use plonky2::iop::witness::Witness; -use plonky2::field::types::PrimeField64; -use super::{chi::chi, iota::iota, pi::pi, rho::rho, theta::theta}; -fn generate_data(size: usize) -> Vec { +use tiny_keccak::Keccak; +use tiny_keccak::Hasher; +use plonky2::plonk::circuit_data::CircuitConfig; +use plonky2::plonk::config::PoseidonGoldilocksConfig; +use anyhow::Result; - let mut data: Vec = Vec::new(); - for _ in 0..(1< { + pub bits: Vec, + _phantom: PhantomData, } - -pub trait WitnessU64: Witness { - fn set_u64_target(&mut self, target: U64Target, value: u64); - // fn get_u64_target(&self, target: U64Target) -> (u64, u64); -} - -impl, F: PrimeField64> WitnessU64 for T { - fn set_u64_target(&mut self, target: U64Target, value: u64) { - self.set_target(target.0[0].0, F::from_canonical_u32((value & 0xFFFFFFFF) as u32)); - self.set_target(target.0[1].0, F::from_canonical_u32(((value >> 32) & 0xFFFFFFFF) as u32)); - } - - // fn get_u64_target(&self, target: U64Target) -> (u64, u64) { - // let x_u64 = self.get_target(target.0[0].0).to_canonical_u64(); - // let y_u64 = self.get_target(target.0[1].0).to_canonical_u64(); - - - // (x_u64, y_u64) - // } -} - -// TODO: Circuit needs to be implemented -pub fn keccak_bench(_size: usize) { - - let data = generate_data(2); - const D: usize = 2; - type C = KeccakGoldilocksConfig; - type F = >::F; - - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - - let _initial = builder.add_virtual_targets(data.len()); - - let hash = KeccakHash::<32>::hash_or_noop(&data); - eprintln!("{:?}", hash); - -} - - -//---------------------------------------------------------- - - -// const KECCAK_WIDTH: usize = 1600; -const KECCAK_RATE: usize = 1088; -// const KECCAK_CAPACITY: usize = KECCAK_WIDTH - KECCAK_RATE; -// const KECCAK_LANES: usize = KECCAK_WIDTH / 64; - -// permutation -fn keccak_f, const D: usize>( - builder: &mut CircuitBuilder, - state: &mut [[U64Target; 5]; 5] -) { - for i in 0..24 { - let _ = theta(builder, state); - let _ = rho(builder, state); - let _ = pi(builder, state); - let _ = chi(builder, state); - let _ = iota(builder, state, i); - } -} - - -fn absorb, const D: usize>( - builder: &mut CircuitBuilder, - state: &mut [[U64Target; 5]; 5], - message: &[U64Target], - rate: usize -) { - let chunks = message.chunks(rate / 64); - for block in chunks { - for (i, &word) in block.iter().enumerate() { - let x = i % 5; - let y = i / 5; - state[x][y] = builder.xor_u64(state[x][y], word); +impl U64Target +where + F: RichField + Extendable, +{ + pub fn new(builder: &mut CircuitBuilder) -> Self { + let mut result = vec![]; + for _ in 0..64 { + result.push(builder.add_virtual_bool_target_safe()); } - keccak_f(builder, state); // Assume keccak_f is implemented as a circuit - } -} - - -fn squeeze, const D: usize>( - builder: &mut CircuitBuilder, - state: &mut [[U64Target; 5]; 5], - rate: usize, - output_length: usize -) -> Vec { - let mut hash = Vec::new(); - while hash.len() * 8 < output_length { - for y in 0..5 { - for x in 0..5 { - if (x + 5 * y) * 64 < rate { - hash.push(state[x][y]); - if hash.len() * 8 >= output_length { - return hash; - } - } - } + Self { + bits: result, + _phantom: PhantomData, + } + } + + pub fn from(bits: Vec) -> Self { + assert_eq!(bits.len(), 64); + Self { + bits, + _phantom: PhantomData, + } + } + + pub fn set_witness(&self, bits: Vec, pw: &mut PartialWitness) { + for i in 0..64 { + pw.set_bool_target(self.bits[i], bits[i]); + } + } + + pub fn constant(x: u64, builder: &mut CircuitBuilder) -> Self { + let mut result = vec![]; + let x_bits = u64_to_bits(x); + for i in 0..64 { + result.push(builder.constant_bool(x_bits[i])); + } + Self { + bits: result, + _phantom: PhantomData, + } + } + + pub fn connect(&self, other: &Self, builder: &mut CircuitBuilder) { + for i in 0..64 { + builder.connect(self.bits[i].target, other.bits[i].target); + } + } + + pub fn to_bits(&self, builder: &mut CircuitBuilder) -> Vec { + let output = Self::new(builder); + self.connect(&output, builder); + output.bits + } + + pub fn xor(&self, other: &Self, builder: &mut CircuitBuilder) -> Self { + let mut result = vec![]; + for i in 0..64 { + let xor_target = xor_circuit(self.bits[i], other.bits[i], builder); + result.push(xor_target); + } + Self { + bits: result, + _phantom: PhantomData, + } + } + + pub fn xor_const(&self, other: u64, builder: &mut CircuitBuilder) -> Self { + let other_bits = u64_to_bits(other); + let mut result = vec![]; + for i in 0..64 { + let xor_target = xor_const_circuit(self.bits[i], other_bits[i], builder); + result.push(xor_target); + } + Self { + bits: result, + _phantom: PhantomData, + } + } + + /* Rotate left by n + * Note that the input parameter n is constant. It is not necessary to make n a constant target or public input, + * because different n generates a different circuit. + */ + pub fn rotl(&self, n: usize) -> Self { + let rotate = rotate_u64(n); + let mut output = vec![]; + for i in 0..64 { + output.push(self.bits[rotate[i]]); + } + + Self { + bits: output, + _phantom: PhantomData, + } + } + + pub fn and(&self, other: &Self, builder: &mut CircuitBuilder) -> Self { + let mut result = vec![]; + for i in 0..64 { + result.push(builder.and(self.bits[i], other.bits[i])); + } + Self { + bits: result, + _phantom: PhantomData, + } + } + + pub fn not(&self, builder: &mut CircuitBuilder) -> Self { + let mut result = vec![]; + for i in 0..64 { + result.push(builder.not(self.bits[i])); + } + Self { + bits: result, + _phantom: PhantomData, + } + } + + /// Calculate `self & !other`. + pub fn and_not(&self, other: &Self, builder: &mut CircuitBuilder) -> Self { + let mut result = vec![]; + for i in 0..64 { + // x(1 - y) = x - xy + result.push(BoolTarget::new_unsafe(builder.arithmetic( + F::NEG_ONE, + F::ONE, + self.bits[i].target, + other.bits[i].target, + self.bits[i].target, + ))); + } + Self { + bits: result, + _phantom: PhantomData, } - keccak_f(builder, state); // Assume keccak_f is implemented as a circuit } - hash } - -fn keccak_pad, const D: usize>( +pub fn xor_circuit( + a: BoolTarget, + b: BoolTarget, builder: &mut CircuitBuilder, - message: &[U64Target], - rate: usize -) -> Vec { - let mut padded_message = message.to_vec(); - let rate_words = rate / 64; - let mut pad_len = rate_words - (message.len() % rate_words); - - if pad_len == 0 { - pad_len = rate_words; - } +) -> BoolTarget +where + F: RichField + Extendable, +{ + // a = 0, b = 0 => 0 + // a = 1, b = 0 => 1 + // a = 0, b = 1 => 1 + // a = 1, b = 1 => 0 + // xor(a, b) = a*(1-b) + (1-a)*b = a + b - 2*ab + let b_minus_2ab = builder.arithmetic(-F::TWO, F::ONE, a.target, b.target, b.target); + let a_plus_b_minus_2ab = builder.add(a.target, b_minus_2ab); + // let c = builder.add_virtual_bool_target_safe(); + // builder.connect(c.target, a_plus_b_neg_two_ab); - if pad_len == 1 { - padded_message.push(U64Target([builder.one_u32(), builder.one_u32()])); + BoolTarget::new_unsafe(a_plus_b_minus_2ab) +} + +pub fn xor_const_circuit( + a: BoolTarget, + b: bool, + builder: &mut CircuitBuilder, +) -> BoolTarget +where + F: RichField + Extendable, +{ + // b = 0 => xor(a, b) = a + // b = 1 => xor(a, b) = 1 - a = not(a) + if b { + builder.not(a) } else { - padded_message.push(U64Target([builder.one_u32(), builder.zero_u32()])); - for _ in 1..(pad_len - 1) { - padded_message.push(U64Target([builder.zero_u32(), builder.zero_u32()])); + a + } +} + +// reffered to https://github.com/polymerdao/plonky2-sha256 +/// 0 -> [0, 1, 2, ..., 63] +/// 1 -> [63, 0, 1, ..., 62] +/// 63 -> [1, 2, ..., 63, 0] +fn rotate_u64(y: usize) -> Vec { + let mut res = Vec::new(); + for i in 64 - y..64 { + res.push(i); + } + for i in 0..64 - y { + res.push(i); + } + res +} + +pub fn from_bits_to_u64(bools: &[bool]) -> u64 { + let mut result: u64 = 0; + let mut shift = 0; + for &bit in bools { + if bit { + result |= 1 << shift; + } + shift += 1; + if shift == 64 { + break; + } + } + result +} + +pub fn u64_to_bits(num: u64) -> Vec { + let mut result = Vec::with_capacity(64); + let mut n = num; + for _ in 0..64 { + result.push(n & 1 == 1); + n >>= 1; + } + result +} + +pub const ROUND_CONSTANTS: [u64; 24] = [ + 1u64, + 0x8082u64, + 0x800000000000808au64, + 0x8000000080008000u64, + 0x808bu64, + 0x80000001u64, + 0x8000000080008081u64, + 0x8000000000008009u64, + 0x8au64, + 0x88u64, + 0x80008009u64, + 0x8000000au64, + 0x8000808bu64, + 0x800000000000008bu64, + 0x8000000000008089u64, + 0x8000000000008003u64, + 0x8000000000008002u64, + 0x8000000000000080u64, + 0x800au64, + 0x800000008000000au64, + 0x8000000080008081u64, + 0x8000000000008080u64, + 0x80000001u64, + 0x8000000080008008u64, +]; +pub const ROTR: [usize; 25] = [ + 0, 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43, 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14, +]; + +#[derive(Clone, Debug)] +pub struct KeccakTarget { + words: Vec>, + _phantom: PhantomData, +} + +impl KeccakTarget +where + F: RichField + Extendable, +{ + pub fn new(builder: &mut CircuitBuilder) -> Self { + let mut result = vec![]; + for _ in 0..25 { + result.push(U64Target::new(builder)); + } + Self { + words: result, + _phantom: PhantomData, } - padded_message.push(U64Target([builder.zero_u32(), builder.one_u32()])); } - padded_message + pub fn set_witness(&self, bits: Vec, pw: &mut PartialWitness) { + assert_eq!(bits.len(), 1600); + for i in 0..25 { + self.words[i].set_witness(bits[i * 64..(i + 1) * 64].to_vec(), pw); + } + } + + pub fn connect(&self, other: &Self, builder: &mut CircuitBuilder) { + for i in 0..25 { + self.words[i].connect(&other.words[i], builder); + } + } + + pub fn from(bits: Vec) -> Self { + let mut result = vec![]; + for i in 0..25 { + result.push(U64Target::from(bits[i * 64..(i + 1) * 64].to_vec())); + } + Self { + words: result, + _phantom: PhantomData, + } + } + + pub fn keccak_round(&mut self, rc: u64, builder: &mut CircuitBuilder) { + // θ step + let mut c = vec![]; + for x in 0..5 { + let xor01 = self.words[x].xor(&self.words[x + 5], builder); + let xor012 = xor01.xor(&self.words[x + 2 * 5], builder); + let xor0123 = xor012.xor(&self.words[x + 3 * 5], builder); + let xor01234 = xor0123.xor(&self.words[x + 4 * 5], builder); + c.push(xor01234); + } + let mut d = vec![]; + for x in 0..5 { + let rot_c = c[(x + 1) % 5].rotl(1); + d.push(c[(x + 4) % 5].xor(&rot_c, builder)); + } + for x in 0..5 { + for y in 0..5 { + self.words[x + y * 5] = self.words[x + y * 5].xor(&d[x], builder); + } + } + // ρ and π steps + let mut b_words: [Option>; 25] = [(); 25].map(|_| None); + for x in 0..5 { + for y in 0..5 { + let rot_self = self.words[x + y * 5].rotl(ROTR[x + y * 5]); + + b_words[y + ((2 * x + 3 * y) % 5) * 5] = Some(rot_self); + } + } + let b = KeccakTarget { + words: b_words.into_iter().map(|x| x.unwrap()).collect(), + _phantom: PhantomData, + }; + + // χ step + for x in 0..5 { + for y in 0..5 { + // b.words[(x + 2) % 5 + y * 5] & !b.words[(x + 1) % 5 + y * 5] + let and_not_b = + b.words[(x + 2) % 5 + y * 5].and_not(&b.words[(x + 1) % 5 + y * 5], builder); + self.words[x + y * 5] = b.words[x + y * 5].xor(&and_not_b, builder); + } + } + + self.words[0] = self.words[0].xor_const(rc, builder); + } + + pub fn keccakf(&self, builder: &mut CircuitBuilder) -> Self { + let mut result = self.clone(); + for round_constant in ROUND_CONSTANTS.into_iter().take(24) { + result.keccak_round(round_constant, builder); + } + + result + } } - -fn keccak256, const D: usize>( +pub fn keccak256_circuit( + input: Vec, builder: &mut CircuitBuilder, - message: &[U64Target] -) -> Vec { - let mut state = [[builder.zero_u64(); 5]; 5]; - let rate = KECCAK_RATE; +) -> Vec +where + F: RichField + Extendable, +{ + assert_eq!(input.len() % 8, 0); // input should be bytes. + let block_size_in_bytes = 136; // in bytes + let input_len_in_bytes = input.len() / 8; + let num_blocks = input_len_in_bytes / block_size_in_bytes + 1; - // Padding - let padded_message = keccak_pad(builder, message, rate); + let mut padded = vec![]; + for _ in 0..block_size_in_bytes * 8 * num_blocks { + padded.push(builder.add_virtual_bool_target_safe()); + } - // Absorbing - absorb(builder, &mut state, &padded_message, rate); + // register input + for i in 0..input_len_in_bytes * 8 { + builder.connect(padded[i].target, input[i].target); + } - // Squeezing - let hash = squeeze(builder, &mut state, rate, 256); + // append 0x01 = 1000 0000 after the last input + let true_target = builder.constant_bool(true); + builder.connect(padded[input_len_in_bytes * 8].target, true_target.target); - hash + // pad 0s + let false_target = builder.constant_bool(false); + let last_index = padded.len() - 1; + for i in input_len_in_bytes * 8 + 1..last_index { + builder.connect(padded[i].target, false_target.target); + } + + // xor 0x80 = 0000 0001 with the last byte. + // however the last bit is ensured to be 0, so just fill 1. + builder.connect(padded[last_index].target, true_target.target); + + let mut m = KeccakTarget::new(builder); + for i in 0..1600 { + let word = i / 64; + let bit = i % 64; + builder.connect(m.words[word].bits[bit].target, false_target.target); + } + + for i in 0..num_blocks { + for j in 0..block_size_in_bytes * 8 { + let word = j / 64; + let bit = j % 64; + let xor_t = xor_circuit( + m.words[word].bits[bit], + padded[i * block_size_in_bytes * 8 + j], + builder, + ); + m.words[word].bits[bit] = xor_t; + } + m = m.keccakf(builder); + } + + let mut z = Vec::new(); + for i in 0..256 { + let new_target = builder.add_virtual_bool_target_safe(); + let word = i / 64; + let bit = i % 64; + builder.connect(new_target.target, m.words[word].bits[bit].target); + z.push(new_target); + } + z } -#[test] -fn test_keccak256() { - // use plonky2_u32::gadgets::arithmetic_u32::U32Target; - // use plonky2::iop::target::Target; - use plonky2::iop::witness::PartialWitness; - use plonky2::plonk::config::PoseidonGoldilocksConfig; - use rand::RngCore; +pub fn keccak_bench(size: usize) -> Result<()>{ + + type F = GoldilocksField; + type C = PoseidonGoldilocksConfig; + const D: usize = 2; - // use plonky2_u32::witness::WitnessU32; - type F = GoldilocksField; // Choose the field used in your implementation. - const D: usize = 2; // This should match the extension degree used. + let input_bytes = generate_data(size); + let input = hex::encode(input_bytes); + let expected_output = expected_keccak(&hex::decode(input.clone()).unwrap()); + + let input_bits = hex_str_to_bits(input.as_str())?; + let exptected_output_bits = hex_str_to_bits(&expected_output)?; - // Create circuit builder. let config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(config); - // Example input message - let mut input = [0u8; 8]; - let _ = rand::thread_rng().try_fill_bytes(&mut input); + let mut input_t = vec![]; + for i in 0..input_bits.len() { + input_t.push(builder.constant_bool(input_bits[i])); + } + let output_t = keccak256_circuit(input_t, &mut builder); - // let input = b"hello world"; - eprintln!("{:?}", input.len()); - // Convert input to U64Target format used in your Keccak circuit. - let input_u64: Vec = input.chunks(8) - .map(|chunk| { - let mut chunk_padded = [0u8; 8]; - chunk_padded[..chunk.len()].copy_from_slice(chunk); - let value = u64::from_le_bytes(chunk_padded); - U64Target([ - builder.constant_u32(value as u32), - builder.constant_u32((value >> 32) as u32), - ]) - }) - .collect(); - - - - // Build the Keccak-256 circuit. - let _ = keccak256(&mut builder, &input_u64); - - eprintln!("{:?}", builder.num_gates()); - - // Generate the circuit and witness. - let data = builder.build::(); let mut pw = PartialWitness::new(); - - let input_u64_plain: Vec = input.chunks(8) - .map(|chunk| { - let mut chunk_padded = [0u8; 8]; - chunk_padded[..chunk.len()].copy_from_slice(chunk); - u64::from_le_bytes(chunk_padded) - }) - .collect(); - - for (i, &byte) in input_u64_plain.iter().enumerate() { - pw.set_u64_target(input_u64[i], byte as u64); + for i in 0..256 { + pw.set_bool_target(output_t[i], exptected_output_bits[i]); } - // Run the circuit. - let hash_result = data.prove(pw).unwrap(); + println!("circuit size: {:?}", builder.num_gates()); + let data = builder.build::(); + let now = Instant::now(); + let proof = data.prove(pw)?; - let _ = data.verify(hash_result.clone()); - - // Extract the hash result from the circuit output. - // let mut output_bytes = Vec::new(); - // for target in hash_targets { - // let lo = hash_result.get_u32(target.0[0]) as u64; - // let hi = (hash_result.get_u32(target.0[1]) as u64) << 32; - // let combined = lo | hi; - // output_bytes.extend_from_slice(&combined.to_le_bytes()); - // } + println!("time = {:?}", now.elapsed()); + println!( + "degree = {}, degree_bits= {}", + data.common.degree(), + data.common.degree_bits() + ); - // // Truncate to 256 bits (32 bytes). - // output_bytes.truncate(32); - - // // Compute the expected hash using a reference implementation. - // let expected_hash = keccak256_reference(input); - - // // Compare the circuit output with the expected hash. - // assert_eq!(output_bytes, expected_hash, "Keccak-256 hash mismatch"); - - println!("{:?}",hash_result.get_public_inputs_hash()); -} - - -#[cfg(test)] -mod tests { - use super::*; - use plonky2::field::goldilocks_field::GoldilocksField; - // use plonky2::field::types::Field; - use plonky2::hash::hash_types::RichField; - use plonky2::iop::witness::{PartialWitness/* , Witness*/}; - use plonky2::plonk::circuit_builder::CircuitBuilder; - use plonky2::plonk::circuit_data::CircuitConfig; - use plonky2::plonk::config::PoseidonGoldilocksConfig; - // use plonky2_u32::gadgets::arithmetic_u32::U32Target; - use crate::arithmetic::u64_arithmetic::U64Target; - - fn create_u64_target, const D: usize>( - builder: &mut CircuitBuilder, - value: u64 - ) -> U64Target { - let lo = value as u32; - let hi = (value >> 32) as u32; - U64Target([builder.constant_u32(lo), builder.constant_u32(hi)]) - } - - #[test] - fn test_theta_function() { - type F = GoldilocksField; - const D: usize = 2; - - // Create circuit builder - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - - // Input state - let input_state: [[U64Target; 5]; 5] = [ - [ - create_u64_target(&mut builder, 0x0000000000000001), - create_u64_target(&mut builder, 0x0000000000000002), - create_u64_target(&mut builder, 0x0000000000000003), - create_u64_target(&mut builder, 0x0000000000000004), - create_u64_target(&mut builder, 0x0000000000000005) - ], - [ - create_u64_target(&mut builder, 0x0000000000000006), - create_u64_target(&mut builder, 0x0000000000000007), - create_u64_target(&mut builder, 0x0000000000000008), - create_u64_target(&mut builder, 0x0000000000000009), - create_u64_target(&mut builder, 0x000000000000000A) - ], - [ - create_u64_target(&mut builder, 0x000000000000000B), - create_u64_target(&mut builder, 0x000000000000000C), - create_u64_target(&mut builder, 0x000000000000000D), - create_u64_target(&mut builder, 0x000000000000000E), - create_u64_target(&mut builder, 0x000000000000000F) - ], - [ - create_u64_target(&mut builder, 0x0000000000000010), - create_u64_target(&mut builder, 0x0000000000000011), - create_u64_target(&mut builder, 0x0000000000000012), - create_u64_target(&mut builder, 0x0000000000000013), - create_u64_target(&mut builder, 0x0000000000000014) - ], - [ - create_u64_target(&mut builder, 0x0000000000000015), - create_u64_target(&mut builder, 0x0000000000000016), - create_u64_target(&mut builder, 0x0000000000000017), - create_u64_target(&mut builder, 0x0000000000000018), - create_u64_target(&mut builder, 0x0000000000000019) - ] - ]; - - // Expected output state (after theta) - let expected_state = [ - [ - create_u64_target(&mut builder, 0x7B7B7B7B7B7B7B7B), - create_u64_target(&mut builder, 0x8B8B8B8B8B8B8B8B), - create_u64_target(&mut builder, 0x9B9B9B9B9B9B9B9B), - create_u64_target(&mut builder, 0xABABABABABABABAB), - create_u64_target(&mut builder, 0xBBBBBBBBBBBBBBBB) - ], - [ - create_u64_target(&mut builder, 0xCBCBCBCBCBCBCBCB), - create_u64_target(&mut builder, 0xDBDBDBDBDBDBDBDB), - create_u64_target(&mut builder, 0xEBEBEBEBEBEBEBEB), - create_u64_target(&mut builder, 0xFBFBFBFBFBFBFBFB), - create_u64_target(&mut builder, 0x0B0B0B0B0B0B0B0B) - ], - [ - create_u64_target(&mut builder, 0x1B1B1B1B1B1B1B1B), - create_u64_target(&mut builder, 0x2B2B2B2B2B2B2B2B), - create_u64_target(&mut builder, 0x3B3B3B3B3B3B3B3B), - create_u64_target(&mut builder, 0x4B4B4B4B4B4B4B4B), - create_u64_target(&mut builder, 0x5B5B5B5B5B5B5B5B) - ], - [ - create_u64_target(&mut builder, 0x6B6B6B6B6B6B6B6B), - create_u64_target(&mut builder, 0x7B7B7B7B7B7B7B7B), - create_u64_target(&mut builder, 0x8B8B8B8B8B8B8B8B), - create_u64_target(&mut builder, 0x9B9B9B9B9B9B9B9B), - create_u64_target(&mut builder, 0xABABABABABABABAB) - ], - [ - create_u64_target(&mut builder, 0xBBBBBBBBBBBBBBBB), - create_u64_target(&mut builder, 0xCBCBCBCBCBCBCBCB), - create_u64_target(&mut builder, 0xDBDBDBDBDBDBDBDB), - create_u64_target(&mut builder, 0xEBEBEBEBEBEBEBEB), - create_u64_target(&mut builder, 0xFBFBFBFBFBFBFBFB) - ] - ]; - - // Run the theta function - let mut state = input_state; - theta(&mut builder, &mut state); - - - // Check if the output state matches the expected state - for x in 0..5 { - for y in 0..5 { - for i in 0..2 { - println!("Comparing: {:?} and {:?}", state[x][y].0[i].0, expected_state[x][y].0[i].0); - let res = builder.is_equal(state[x][y].0[i].0, expected_state[x][y].0[i].0); - builder.assert_bool(res); - } - } - } - - println!("{:?}", builder.num_gates()); - // Build the circuit - let data = builder.build::(); - - // Create witness and prove - let mut pw = PartialWitness::new(); - pw.set_u64_target(input_state[0][0], 0x0000000000000001); - pw.set_u64_target(input_state[0][1], 0x0000000000000002); - pw.set_u64_target(input_state[0][2], 0x0000000000000003); - pw.set_u64_target(input_state[0][3], 0x0000000000000004); - pw.set_u64_target(input_state[0][4], 0x0000000000000005); - pw.set_u64_target(input_state[1][0], 0x0000000000000006); - pw.set_u64_target(input_state[1][1], 0x0000000000000007); - pw.set_u64_target(input_state[1][2], 0x0000000000000008); - pw.set_u64_target(input_state[1][3], 0x0000000000000009); - pw.set_u64_target(input_state[1][4], 0x000000000000000A); - pw.set_u64_target(input_state[2][0], 0x000000000000000B); - pw.set_u64_target(input_state[2][1], 0x000000000000000C); - pw.set_u64_target(input_state[2][2], 0x000000000000000D); - pw.set_u64_target(input_state[2][3], 0x000000000000000E); - pw.set_u64_target(input_state[2][4], 0x000000000000000F); - pw.set_u64_target(input_state[3][0], 0x0000000000000010); - pw.set_u64_target(input_state[3][1], 0x0000000000000011); - pw.set_u64_target(input_state[3][2], 0x0000000000000012); - pw.set_u64_target(input_state[3][3], 0x0000000000000013); - pw.set_u64_target(input_state[3][4], 0x0000000000000014); - pw.set_u64_target(input_state[4][0], 0x0000000000000015); - pw.set_u64_target(input_state[4][1], 0x0000000000000016); - pw.set_u64_target(input_state[4][2], 0x0000000000000017); - pw.set_u64_target(input_state[4][3], 0x0000000000000018); - pw.set_u64_target(input_state[4][4], 0x0000000000000019); - - let proof = data.prove(pw).unwrap(); - assert!(data.verify(proof).is_ok()); - } - - - #[test] - fn test_rho_function() { - type F = GoldilocksField; - const D: usize = 2; - - // Create circuit builder - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - - // Input state (example, should be taken from an authoritative source) - let input_state = [ - [ - create_u64_target(&mut builder, 0x0000000000000001), - create_u64_target(&mut builder, 0x0000000000000002), - create_u64_target(&mut builder, 0x0000000000000003), - create_u64_target(&mut builder, 0x0000000000000004), - create_u64_target(&mut builder, 0x0000000000000005) - ], - [ - create_u64_target(&mut builder, 0x0000000000000006), - create_u64_target(&mut builder, 0x0000000000000007), - create_u64_target(&mut builder, 0x0000000000000008), - create_u64_target(&mut builder, 0x0000000000000009), - create_u64_target(&mut builder, 0x000000000000000A) - ], - [ - create_u64_target(&mut builder, 0x000000000000000B), - create_u64_target(&mut builder, 0x000000000000000C), - create_u64_target(&mut builder, 0x000000000000000D), - create_u64_target(&mut builder, 0x000000000000000E), - create_u64_target(&mut builder, 0x000000000000000F) - ], - [ - create_u64_target(&mut builder, 0x0000000000000010), - create_u64_target(&mut builder, 0x0000000000000011), - create_u64_target(&mut builder, 0x0000000000000012), - create_u64_target(&mut builder, 0x0000000000000013), - create_u64_target(&mut builder, 0x0000000000000014) - ], - [ - create_u64_target(&mut builder, 0x0000000000000015), - create_u64_target(&mut builder, 0x0000000000000016), - create_u64_target(&mut builder, 0x0000000000000017), - create_u64_target(&mut builder, 0x0000000000000018), - create_u64_target(&mut builder, 0x0000000000000019) - ] - ]; - - // Expected state after rho (example, should be taken from an authoritative source) - let expected_state = [ - [ - create_u64_target(&mut builder, 0x0000000000000001), - create_u64_target(&mut builder, 0x0000000000000100), - create_u64_target(&mut builder, 0x0000000000003000), - create_u64_target(&mut builder, 0x0000000000040000), - create_u64_target(&mut builder, 0x0000000000500000) - ], - [ - create_u64_target(&mut builder, 0x0000000000600000), - create_u64_target(&mut builder, 0x0000000000700000), - create_u64_target(&mut builder, 0x0000000008000000), - create_u64_target(&mut builder, 0x0000000009000000), - create_u64_target(&mut builder, 0x00000000A0000000) - ], - [ - create_u64_target(&mut builder, 0x00000000B0000000), - create_u64_target(&mut builder, 0x00000000C0000000), - create_u64_target(&mut builder, 0x0000000D00000000), - create_u64_target(&mut builder, 0x0000000E00000000), - create_u64_target(&mut builder, 0x0000000F00000000) - ], - [ - create_u64_target(&mut builder, 0x0000001000000000), - create_u64_target(&mut builder, 0x0000001100000000), - create_u64_target(&mut builder, 0x0000001200000000), - create_u64_target(&mut builder, 0x0000001300000000), - create_u64_target(&mut builder, 0x0000001400000000) - ], - [ - create_u64_target(&mut builder, 0x0000001500000000), - create_u64_target(&mut builder, 0x0000001600000000), - create_u64_target(&mut builder, 0x0000001700000000), - create_u64_target(&mut builder, 0x0000001800000000), - create_u64_target(&mut builder, 0x0000001900000000) - ] - ]; - - // Run the rho function - let mut state = input_state; - rho(&mut builder, &mut state); - // Check if the output state matches the expected state - for x in 0..5 { - for y in 0..5 { - let res = builder.is_equal(state[x][y].0[0].0, expected_state[x][y].0[0].0); - let res2 = builder.is_equal(state[x][y].0[1].0, expected_state[x][y].0[1].0); - - builder.assert_bool(res); - builder.assert_bool(res2); - } - } - - println!("{:?}", builder.num_gates()); - // Build the circuit - let data = builder.build::(); - - // Create witness and prove - let pw = PartialWitness::new(); - let proof = data.prove(pw).unwrap(); - assert!(data.verify(proof).is_ok()); - } - - - #[test] - fn test_keccak256_permutation() { - type F = GoldilocksField; - const D: usize = 2; - - // Create circuit builder - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - - // Input state (example, should be taken from an authoritative source) - let input_state = [ - [ - create_u64_target(&mut builder, 0x0000000000000001), - create_u64_target(&mut builder, 0x0000000000000002), - create_u64_target(&mut builder, 0x0000000000000003), - create_u64_target(&mut builder, 0x0000000000000004), - create_u64_target(&mut builder, 0x0000000000000005) - ], - [ - create_u64_target(&mut builder, 0x0000000000000006), - create_u64_target(&mut builder, 0x0000000000000007), - create_u64_target(&mut builder, 0x0000000000000008), - create_u64_target(&mut builder, 0x0000000000000009), - create_u64_target(&mut builder, 0x000000000000000A) - ], - [ - create_u64_target(&mut builder, 0x000000000000000B), - create_u64_target(&mut builder, 0x000000000000000C), - create_u64_target(&mut builder, 0x000000000000000D), - create_u64_target(&mut builder, 0x000000000000000E), - create_u64_target(&mut builder, 0x000000000000000F) - ], - [ - create_u64_target(&mut builder, 0x0000000000000010), - create_u64_target(&mut builder, 0x0000000000000011), - create_u64_target(&mut builder, 0x0000000000000012), - create_u64_target(&mut builder, 0x0000000000000013), - create_u64_target(&mut builder, 0x0000000000000014) - ], - [ - create_u64_target(&mut builder, 0x0000000000000015), - create_u64_target(&mut builder, 0x0000000000000016), - create_u64_target(&mut builder, 0x0000000000000017), - create_u64_target(&mut builder, 0x0000000000000018), - create_u64_target(&mut builder, 0x0000000000000019) - ] - ]; - - // Expected state after keccak256 permutation (example, should be taken from an authoritative source) - let expected_state = [ - [ - create_u64_target(&mut builder, 0xE69F6BAE986CCF06), - create_u64_target(&mut builder, 0xDF9D77905A3546B6), - create_u64_target(&mut builder, 0x7BFBFFF923073CEB), - create_u64_target(&mut builder, 0xB2D9AB3E200FD999), - create_u64_target(&mut builder, 0x1A741CAEC020555C) - ], - [ - create_u64_target(&mut builder, 0x56D7B52E1442C0AE), - create_u64_target(&mut builder, 0xEBA39A0E00EF9FE9), - create_u64_target(&mut builder, 0x2D6FF9BE61A295EE), - create_u64_target(&mut builder, 0xC82D01AE6E142988), - create_u64_target(&mut builder, 0xCDEDECBAD32B9246) - ], - [ - create_u64_target(&mut builder, 0x7AF13F3C6F6E4AF6), - create_u64_target(&mut builder, 0xBD469F697CCF7B91), - create_u64_target(&mut builder, 0xAB4F902ED5B9FD93), - create_u64_target(&mut builder, 0xFC4F6A6C27E0190B), - create_u64_target(&mut builder, 0x3D41F5EF85540B06) - ], - [ - create_u64_target(&mut builder, 0x2D9F050A3E1600F4), - create_u64_target(&mut builder, 0x0ED46287DA8AA931), - create_u64_target(&mut builder, 0xA13AD679DFAA4EA3), - create_u64_target(&mut builder, 0x70B1D7A7C896E12A), - create_u64_target(&mut builder, 0xA2CF9C93C5326E0D) - ], - [ - create_u64_target(&mut builder, 0x2CE66FBC3AC94F5B), - create_u64_target(&mut builder, 0x4960E539C1EF3BA7), - create_u64_target(&mut builder, 0xC7C50305DF46E1BB), - create_u64_target(&mut builder, 0xEE6FE33D998F8A8B), - create_u64_target(&mut builder, 0x2A971ED5399DC662) - ] - ]; - - // Run the keccak256 permutation function - let mut state = input_state; - keccak_f(&mut builder, &mut state); - - // Check if the output state matches the expected state - for x in 0..5 { - for y in 0..5 { - let res1 = builder.is_equal(state[x][y].0[0].0, expected_state[x][y].0[0].0); - let res2 = builder.is_equal(state[x][y].0[1].0, expected_state[x][y].0[1].0); - - builder.assert_bool(res1); - builder.assert_bool(res2); - } - } - println!("{:?}", builder.num_gates()); - // Build the circuit - let data = builder.build::(); - - // Create witness and prove - let pw = PartialWitness::new(); - let proof = data.prove(pw).unwrap(); - assert!(data.verify(proof).is_ok()); - } - - - #[test] - fn test_keccak256_hash() { - type F = GoldilocksField; - const D: usize = 2; - - // Create circuit builder - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - - // Input message (example, should be taken from an authoritative source) - let input_message = vec![ - create_u64_target(&mut builder, 0x0000000000000001), - create_u64_target(&mut builder, 0x0000000000000002), - create_u64_target(&mut builder, 0x0000000000000003), - create_u64_target(&mut builder, 0x0000000000000004) - ]; - - // Expected hash (example, should be taken from an authoritative source) - let expected_hash = vec![ - create_u64_target(&mut builder, 0xA7FFC6F8BF1ED766), - create_u64_target(&mut builder, 0x51C14756A061D662), - create_u64_target(&mut builder, 0xF580FF4DE43B49FA), - create_u64_target(&mut builder, 0x82D80A4B80F8434A) - ]; - - // Run the keccak256 hash function - let hash = keccak256(&mut builder, &input_message); - - // Check if the output hash matches the expected hash - for i in 0..expected_hash.len() { - let res1 = builder.is_equal(hash[i].0[0].0, expected_hash[i].0[0].0); - let res2 = builder.is_equal(hash[i].0[1].0, expected_hash[i].0[1].0); - - builder.assert_bool(res1); - builder.assert_bool(res2); - } - - println!("{:?}", builder.num_gates()); - // Build the circuit - let data = builder.build::(); - - // Create witness and prove - let pw = PartialWitness::new(); - let proof = data.prove(pw).unwrap(); - assert!(data.verify(proof).is_ok()); - } + data.verify(proof)?; + Ok(()) } + +fn generate_data(size: usize) -> Vec { + + let mut rng = rand::thread_rng(); + let mut bytes = vec![0u8; size]; + rng.fill(&mut bytes[..]); + bytes +} + +fn u8_to_bits(num: u8) -> Vec { + let mut result = Vec::with_capacity(8); + let mut n = num; + for _ in 0..8 { + result.push(n & 1 == 1); + n >>= 1; + } + result +} + +fn hex_str_to_bits(input: &str) -> Result> { + let input_u8 = hex::decode(input)?; + let input_bits = input_u8 + .iter() + .flat_map(|x| u8_to_bits(*x)) + .collect::>(); + Ok(input_bits) +} + +fn expected_keccak(input: &[u8]) -> String { + let mut hasher = Keccak::v256(); + hasher.update(input); + let mut hash = [0u8; 32]; + hasher.finalize(&mut hash); + + hex::encode(hash) +} \ No newline at end of file diff --git a/hash/plonky2/src/bench/keccak256/pi.rs b/hash/plonky2/src/bench/keccak256/pi.rs deleted file mode 100644 index 5862c18..0000000 --- a/hash/plonky2/src/bench/keccak256/pi.rs +++ /dev/null @@ -1,20 +0,0 @@ -use plonky2::hash::hash_types::RichField; -use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::field::extension::Extendable; -use crate::arithmetic::u64_arithmetic::CircuitBuilderU64; - -use crate::arithmetic::u64_arithmetic::U64Target; - -//pi -pub fn pi, const D: usize>( - builder: &mut CircuitBuilder, - state: &mut [[U64Target; 5]; 5] -){ - let mut new_state = [[builder.zero_u64(); 5]; 5]; - for x in 0..5 { - for y in 0..5 { - new_state[(2 * x + 3 * y) % 5][y] = state[x][y]; - } - } - *state = new_state; -} \ No newline at end of file diff --git a/hash/plonky2/src/bench/keccak256/rho.rs b/hash/plonky2/src/bench/keccak256/rho.rs deleted file mode 100644 index c37df14..0000000 --- a/hash/plonky2/src/bench/keccak256/rho.rs +++ /dev/null @@ -1,27 +0,0 @@ -use plonky2::hash::hash_types::RichField; -use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::field::extension::Extendable; -use crate::arithmetic::u64_arithmetic::CircuitBuilderU64; - -use crate::arithmetic::u64_arithmetic::U64Target; - -//rho -pub fn rho, const D: usize>( - builder: &mut CircuitBuilder, - state: &mut [[U64Target; 5]; 5] -){ - const RHO_OFFSETS: [[usize; 5]; 5] = [ - [0, 1, 62, 28, 27], - [36, 44, 6, 55, 20], - [3, 10, 43, 25, 39], - [41, 45, 15, 21, 8], - [18, 2, 61, 56, 14], - ]; - - for x in 0..5 { - for y in 0..5 { - let rotation = RHO_OFFSETS[x][y]; - state[x][y] = builder.rotate_left_u64(state[x][y], rotation as u8); - } - } -} \ No newline at end of file diff --git a/hash/plonky2/src/bench/keccak256/theta.rs b/hash/plonky2/src/bench/keccak256/theta.rs deleted file mode 100644 index fafc11e..0000000 --- a/hash/plonky2/src/bench/keccak256/theta.rs +++ /dev/null @@ -1,204 +0,0 @@ -use plonky2::hash::hash_types::RichField; -use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::field::extension::Extendable; -use crate::arithmetic::u64_arithmetic::CircuitBuilderU64; - - -use crate::arithmetic::u64_arithmetic::U64Target; - -// Theta -pub fn theta, const D: usize>( - builder: &mut CircuitBuilder, - state: &mut [[U64Target; 5]; 5] -){ - let mut c = [builder.zero_u64(); 5]; - let mut d = [builder.zero_u64(); 5]; - - // Compute column parities - for x in 0..5 { - - let xor_x0_x1 = builder.xor_u64(state[x][0], state[x][1]); - let xor_x0_x1_x2 = builder.xor_u64(xor_x0_x1, state[x][2]); - let xor_x0_x1_x2_x3 = builder.xor_u64(xor_x0_x1_x2, state[x][3]); - c[x] = builder.xor_u64(xor_x0_x1_x2_x3, state[x][4]); - - } - - // Compute rotated parities - for x in 0..5 { - let c_left = c[(x + 4) % 5]; - let c_right_rot = builder.rotate_left_u64(c[(x + 1) % 5], 1); - d[x] = builder.xor_u64(c_left, c_right_rot); - } - - // Modify the state - for x in 0..5 { - for y in 0..5 { - state[x][y] = builder.xor_u64(state[x][y], d[x]); - } - } -} - - - -#[cfg(test)] -mod tests { - use super::*; - use plonky2::field::goldilocks_field::GoldilocksField; - use plonky2::hash::hash_types::RichField; - use plonky2::iop::witness::PartialWitness; - use plonky2::plonk::circuit_builder::CircuitBuilder; - use plonky2::plonk::circuit_data::CircuitConfig; - use plonky2::plonk::config::PoseidonGoldilocksConfig; - use crate::arithmetic::u64_arithmetic::U64Target; - use plonky2_u32::gadgets::arithmetic_u32::CircuitBuilderU32; - use crate::bench::keccak256::keccak::WitnessU64; - - fn create_u64_target, const D: usize>( - builder: &mut CircuitBuilder, - value: u64 - ) -> U64Target { - let lo = value as u32; - let hi = (value >> 32) as u32; - U64Target([builder.constant_u32(lo), builder.constant_u32(hi)]) - } - - #[test] - fn test_theta_function() { - type F = GoldilocksField; - const D: usize = 2; - - // Create circuit builder - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - - // Input state - let input_state: [[U64Target; 5]; 5] = [ - [ - create_u64_target(&mut builder, 0x0000000000000001), - create_u64_target(&mut builder, 0x0000000000000002), - create_u64_target(&mut builder, 0x0000000000000003), - create_u64_target(&mut builder, 0x0000000000000004), - create_u64_target(&mut builder, 0x0000000000000005) - ], - [ - create_u64_target(&mut builder, 0x0000000000000006), - create_u64_target(&mut builder, 0x0000000000000007), - create_u64_target(&mut builder, 0x0000000000000008), - create_u64_target(&mut builder, 0x0000000000000009), - create_u64_target(&mut builder, 0x000000000000000A) - ], - [ - create_u64_target(&mut builder, 0x000000000000000B), - create_u64_target(&mut builder, 0x000000000000000C), - create_u64_target(&mut builder, 0x000000000000000D), - create_u64_target(&mut builder, 0x000000000000000E), - create_u64_target(&mut builder, 0x000000000000000F) - ], - [ - create_u64_target(&mut builder, 0x0000000000000010), - create_u64_target(&mut builder, 0x0000000000000011), - create_u64_target(&mut builder, 0x0000000000000012), - create_u64_target(&mut builder, 0x0000000000000013), - create_u64_target(&mut builder, 0x0000000000000014) - ], - [ - create_u64_target(&mut builder, 0x0000000000000015), - create_u64_target(&mut builder, 0x0000000000000016), - create_u64_target(&mut builder, 0x0000000000000017), - create_u64_target(&mut builder, 0x0000000000000018), - create_u64_target(&mut builder, 0x0000000000000019) - ] - ]; - - // Expected output state (after theta) - let expected_state = [ - [ - create_u64_target(&mut builder, 0x7B7B7B7B7B7B7B7B), - create_u64_target(&mut builder, 0x8B8B8B8B8B8B8B8B), - create_u64_target(&mut builder, 0x9B9B9B9B9B9B9B9B), - create_u64_target(&mut builder, 0xABABABABABABABAB), - create_u64_target(&mut builder, 0xBBBBBBBBBBBBBBBB) - ], - [ - create_u64_target(&mut builder, 0xCBCBCBCBCBCBCBCB), - create_u64_target(&mut builder, 0xDBDBDBDBDBDBDBDB), - create_u64_target(&mut builder, 0xEBEBEBEBEBEBEBEB), - create_u64_target(&mut builder, 0xFBFBFBFBFBFBFBFB), - create_u64_target(&mut builder, 0x0B0B0B0B0B0B0B0B) - ], - [ - create_u64_target(&mut builder, 0x1B1B1B1B1B1B1B1B), - create_u64_target(&mut builder, 0x2B2B2B2B2B2B2B2B), - create_u64_target(&mut builder, 0x3B3B3B3B3B3B3B3B), - create_u64_target(&mut builder, 0x4B4B4B4B4B4B4B4B), - create_u64_target(&mut builder, 0x5B5B5B5B5B5B5B5B) - ], - [ - create_u64_target(&mut builder, 0x6B6B6B6B6B6B6B6B), - create_u64_target(&mut builder, 0x7B7B7B7B7B7B7B7B), - create_u64_target(&mut builder, 0x8B8B8B8B8B8B8B8B), - create_u64_target(&mut builder, 0x9B9B9B9B9B9B9B9B), - create_u64_target(&mut builder, 0xABABABABABABABAB) - ], - [ - create_u64_target(&mut builder, 0xBBBBBBBBBBBBBBBB), - create_u64_target(&mut builder, 0xCBCBCBCBCBCBCBCB), - create_u64_target(&mut builder, 0xDBDBDBDBDBDBDBDB), - create_u64_target(&mut builder, 0xEBEBEBEBEBEBEBEB), - create_u64_target(&mut builder, 0xFBFBFBFBFBFBFBFB) - ] - ]; - - // Run the theta function - let mut state = input_state; - let _ = theta(&mut builder, &mut state); - - - // Check if the output state matches the expected state - for x in 0..5 { - for y in 0..5 { - for i in 0..2 { - println!("Comparing: {:?} and {:?}", state[x][y].0[i].0, expected_state[x][y].0[i].0); - let res = builder.is_equal(state[x][y].0[i].0, expected_state[x][y].0[i].0); - builder.assert_bool(res); - } - } - } - - println!("{:?}", builder.num_gates()); - // Build the circuit - let data = builder.build::(); - - // Create witness and prove - let mut pw = PartialWitness::new(); - pw.set_u64_target(input_state[0][0], 0x0000000000000001); - pw.set_u64_target(input_state[0][1], 0x0000000000000002); - pw.set_u64_target(input_state[0][2], 0x0000000000000003); - pw.set_u64_target(input_state[0][3], 0x0000000000000004); - pw.set_u64_target(input_state[0][4], 0x0000000000000005); - pw.set_u64_target(input_state[1][0], 0x0000000000000006); - pw.set_u64_target(input_state[1][1], 0x0000000000000007); - pw.set_u64_target(input_state[1][2], 0x0000000000000008); - pw.set_u64_target(input_state[1][3], 0x0000000000000009); - pw.set_u64_target(input_state[1][4], 0x000000000000000A); - pw.set_u64_target(input_state[2][0], 0x000000000000000B); - pw.set_u64_target(input_state[2][1], 0x000000000000000C); - pw.set_u64_target(input_state[2][2], 0x000000000000000D); - pw.set_u64_target(input_state[2][3], 0x000000000000000E); - pw.set_u64_target(input_state[2][4], 0x000000000000000F); - pw.set_u64_target(input_state[3][0], 0x0000000000000010); - pw.set_u64_target(input_state[3][1], 0x0000000000000011); - pw.set_u64_target(input_state[3][2], 0x0000000000000012); - pw.set_u64_target(input_state[3][3], 0x0000000000000013); - pw.set_u64_target(input_state[3][4], 0x0000000000000014); - pw.set_u64_target(input_state[4][0], 0x0000000000000015); - pw.set_u64_target(input_state[4][1], 0x0000000000000016); - pw.set_u64_target(input_state[4][2], 0x0000000000000017); - pw.set_u64_target(input_state[4][3], 0x0000000000000018); - pw.set_u64_target(input_state[4][4], 0x0000000000000019); - - let proof = data.prove(pw).unwrap(); - assert!(data.verify(proof).is_ok()); - } -} \ No newline at end of file diff --git a/hash/plonky2/src/main.rs b/hash/plonky2/src/main.rs index 3981027..599e5a1 100644 --- a/hash/plonky2/src/main.rs +++ b/hash/plonky2/src/main.rs @@ -14,11 +14,6 @@ mod bench{ } pub mod keccak256{ - pub mod theta; - pub mod rho; - pub mod pi; - pub mod iota; - pub mod chi; pub mod keccak; } }