diff --git a/hash/plonky2/src/arithmetic/binary_arithmetic.rs b/hash/plonky2/src/arithmetic/binary_arithmetic.rs new file mode 100644 index 0000000..ffdde19 --- /dev/null +++ b/hash/plonky2/src/arithmetic/binary_arithmetic.rs @@ -0,0 +1,30 @@ +use plonky2::hash::hash_types::RichField; +use plonky2::field::extension::Extendable; +use plonky2::plonk::circuit_builder::CircuitBuilder; +use plonky2::iop::target::BoolTarget; + +pub trait CircuitBuilderBoolTarget, const D: usize> { + fn and(&mut self, a: BoolTarget, b: BoolTarget) -> BoolTarget; + fn or(&mut self, a: BoolTarget, b: BoolTarget) -> BoolTarget; + fn xor(&mut self, a: BoolTarget, b: BoolTarget) -> BoolTarget; + +} + +impl, const D: usize> CircuitBuilderBoolTarget + for CircuitBuilder{ + fn xor(&mut self, a: BoolTarget, b: BoolTarget) -> BoolTarget { + + // a ^ b := (a - b)^2 + let s = self.sub(a.target, b.target); + BoolTarget::new_unsafe(self.mul(s, s)) + + } + + fn and(&mut self, a: BoolTarget, b: BoolTarget) -> BoolTarget { + self.and(a, b) + } + + fn or(&mut self, a: BoolTarget, b: BoolTarget) -> BoolTarget { + self.or(a, b) + } + } \ No newline at end of file diff --git a/hash/plonky2/src/arithmetic/u32_arithmetic.rs b/hash/plonky2/src/arithmetic/u32_arithmetic.rs new file mode 100644 index 0000000..08ba34b --- /dev/null +++ b/hash/plonky2/src/arithmetic/u32_arithmetic.rs @@ -0,0 +1,80 @@ +use plonky2::iop::target::{BoolTarget, Target}; +use plonky2::hash::hash_types::RichField; +use plonky2::field::extension::Extendable; +use plonky2::plonk::circuit_builder::CircuitBuilder; + +use super::binary_arithmetic::CircuitBuilderBoolTarget; +#[derive(Clone, Copy, Debug)] +pub struct U32Target(pub Target); + +pub trait CircuitBuilderU32, const D: usize> { + fn or_u32(&mut self, a: U32Target, b: U32Target) -> U32Target; + fn and_u32(&mut self, a: U32Target, b: U32Target) -> U32Target; + fn xor_u32(&mut self, a: U32Target, b: U32Target) -> U32Target; + + fn from_u32(&mut self, a: U32Target) -> Vec; + fn to_u32(&mut self, a: Vec) -> U32Target; + +} + +impl, const D: usize> CircuitBuilderU32 + for CircuitBuilder{ + + fn from_u32(&mut self, a: U32Target) -> Vec { + + let mut res = Vec::new(); + let bit_targets = self.split_le_base::<2>(a.0, 32); + + for i in (0..32).rev() { + res.push(BoolTarget::new_unsafe(bit_targets[i])); + } + res + } + + fn to_u32(&mut self, a: Vec) -> U32Target { + let bit_len = a.len(); + assert_eq!(bit_len, 32); + U32Target(self.le_sum(a[0..32].iter().rev())) + } + + + fn or_u32(&mut self, a: U32Target, b: U32Target) -> U32Target { + let binary_target_a = self.from_u32(a); + let binary_target_b = self.from_u32(b); + + let mut res = Vec::::new(); + for i in 0..32 { + + let r = self.or(binary_target_a[i], binary_target_b[i]); + res.push(r); + } + self.to_u32(res) + } + + fn and_u32(&mut self, a: U32Target, b: U32Target) -> U32Target { + let binary_target_a = self.from_u32(a); + let binary_target_b = self.from_u32(b); + + let mut res = Vec::::new(); + for i in 0..32 { + + let r = self.and(binary_target_a[i], binary_target_b[i]); + res.push(r); + } + self.to_u32(res) + + } + + fn xor_u32(&mut self, a: U32Target, b: U32Target) -> U32Target { + let binary_target_a = self.from_u32(a); + let binary_target_b = self.from_u32(b); + + let mut res = Vec::::new(); + for i in 0..32 { + + let r = self.xor(binary_target_a[i], binary_target_b[i]); + res.push(r); + } + self.to_u32(res) + } + } \ No newline at end of file diff --git a/hash/plonky2/src/arithmetic/u64_arithmetic.rs b/hash/plonky2/src/arithmetic/u64_arithmetic.rs new file mode 100644 index 0000000..abd711d --- /dev/null +++ b/hash/plonky2/src/arithmetic/u64_arithmetic.rs @@ -0,0 +1,32 @@ +use plonky2::hash::hash_types::RichField; +use plonky2::field::extension::Extendable; +use plonky2::plonk::circuit_builder::CircuitBuilder; +use super::u32_arithmetic::CircuitBuilderU32; +use super::u32_arithmetic::U32Target; +#[derive(Clone, Copy, Debug)] +pub struct U64Target(pub [U32Target;2]); + +pub trait CircuitBuilderU64, const D: usize> { + fn and(&mut self, a: U64Target, b: U64Target) -> U64Target; + fn xor(&mut self, a: U64Target, b: U64Target) -> U64Target; +} + +impl, const D: usize> CircuitBuilderU64 + for CircuitBuilder{ + fn xor(&mut self, a: U64Target, b: U64Target) -> U64Target { + let mut result = Vec::new(); + for i in 0..2 { + result.push(self.xor_u32(a.0[i], b.0[i])); + } + U64Target([result[0], result[1]]) + } + + fn and(&mut self, a: U64Target, b: U64Target) -> U64Target { + let mut result = Vec::new(); + + for i in 0..2 { + result.push(self.and_u32(a.0[i], b.0[i])); + } + U64Target([result[0], result[1]]) + } +} \ No newline at end of file diff --git a/hash/plonky2/src/bench/keccak.rs b/hash/plonky2/src/bench/keccak.rs index 2dc4d14..e64b0b9 100644 --- a/hash/plonky2/src/bench/keccak.rs +++ b/hash/plonky2/src/bench/keccak.rs @@ -56,87 +56,87 @@ pub fn keccak_bench(_size: usize) { //---------------------------------------------------------- -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; -const KECCAK_ROUNDS: usize = 24; +// 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; +// 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, -]; +// 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, +// ]; -fn initialize_state() -> [u64; KECCAK_LANES] { - [0; KECCAK_LANES] -} -pub struct U64Target([U32Target;2]); +// fn initialize_state() -> [u64; KECCAK_LANES] { +// [0; KECCAK_LANES] +// } +// pub struct U64Target([U32Target;2]); -// copied from sha256 circuit -// TODO: move to some common place -pub fn u32_to_bits_target, const D: usize, const B: usize>( - builder: &mut CircuitBuilder, - a: &U32Target, -) -> Vec { - let mut res = Vec::new(); - let bit_targets = builder.split_le_base::(a.0, 32); - for i in (0..32).rev() { - res.push(BoolTarget::new_unsafe(bit_targets[i])); - } - res -} +// // copied from sha256 circuit +// // TODO: move to some common place +// pub fn u32_to_bits_target, const D: usize, const B: usize>( +// builder: &mut CircuitBuilder, +// a: &U32Target, +// ) -> Vec { +// let mut res = Vec::new(); +// let bit_targets = builder.split_le_base::(a.0, 32); +// for i in (0..32).rev() { +// res.push(BoolTarget::new_unsafe(bit_targets[i])); +// } +// res +// } -// copied from sha256 circuit -// TODO: move to some common place -pub fn bits_to_u32_target, const D: usize>( - builder: &mut CircuitBuilder, - bits_target: Vec, -) -> U32Target { - let bit_len = bits_target.len(); - assert_eq!(bit_len, 32); - U32Target(builder.le_sum(bits_target[0..32].iter().rev())) -} +// // copied from sha256 circuit +// // TODO: move to some common place +// pub fn bits_to_u32_target, const D: usize>( +// builder: &mut CircuitBuilder, +// bits_target: Vec, +// ) -> U32Target { +// let bit_len = bits_target.len(); +// assert_eq!(bit_len, 32); +// U32Target(builder.le_sum(bits_target[0..32].iter().rev())) +// } -//TODO: not tested -pub fn xor_u64, const D: usize>( - builder: &mut CircuitBuilder, - x: U64Target, - y: U64Target, -) -> U64Target { - let xor_x0_y0 = xor_u32(builder, x.0[0], y.0[0]); - let xor_x1_y1 = xor_u32(builder, x.0[1], y.0[1]); +// //TODO: not tested +// pub fn xor_u64, const D: usize>( +// builder: &mut CircuitBuilder, +// x: U64Target, +// y: U64Target, +// ) -> U64Target { +// let xor_x0_y0 = xor_u32(builder, x.0[0], y.0[0]); +// let xor_x1_y1 = xor_u32(builder, x.0[1], y.0[1]); - U64Target([xor_x0_y0,xor_x1_y1]) +// U64Target([xor_x0_y0,xor_x1_y1]) -} +// } -pub fn xor_u32, const D: usize>( - builder: &mut CircuitBuilder, - x: U32Target, - y: U32Target, -) -> U32Target { +// pub fn xor_u32, const D: usize>( +// builder: &mut CircuitBuilder, +// x: U32Target, +// y: U32Target, +// ) -> U32Target { - let bits_target_x = u32_to_bits_target::(builder, &x); - let bits_target_y = u32_to_bits_target::(builder, &y); +// let bits_target_x = u32_to_bits_target::(builder, &x); +// let bits_target_y = u32_to_bits_target::(builder, &y); - assert_eq!(bits_target_x.len(), bits_target_y.len()); +// assert_eq!(bits_target_x.len(), bits_target_y.len()); - let mut xor_result_final = Vec::::new(); - for i in 0..bits_target_x.len() { - let a_plus_b = builder.add(bits_target_x.get(i).unwrap().target, bits_target_y.get(i).unwrap().target); - let ab = builder.mul(bits_target_x.get(i).unwrap().target, bits_target_y.get(i).unwrap().target); - let two_ab = builder.mul_const(F::from_canonical_u64(2), ab); - let xor_result = builder.sub(a_plus_b, two_ab); - xor_result_final.push(BoolTarget::new_unsafe(xor_result)); - } - let result = bits_to_u32_target(builder, xor_result_final); - result +// let mut xor_result_final = Vec::::new(); +// for i in 0..bits_target_x.len() { +// let a_plus_b = builder.add(bits_target_x.get(i).unwrap().target, bits_target_y.get(i).unwrap().target); +// let ab = builder.mul(bits_target_x.get(i).unwrap().target, bits_target_y.get(i).unwrap().target); +// let two_ab = builder.mul_const(F::from_canonical_u64(2), ab); +// let xor_result = builder.sub(a_plus_b, two_ab); +// xor_result_final.push(BoolTarget::new_unsafe(xor_result)); +// } +// let result = bits_to_u32_target(builder, xor_result_final); +// result -} +// } // Theta // pub fn theta, const D: usize>( diff --git a/hash/plonky2/src/main.rs b/hash/plonky2/src/main.rs index 0eaa9fb..a87e42b 100644 --- a/hash/plonky2/src/main.rs +++ b/hash/plonky2/src/main.rs @@ -15,6 +15,12 @@ mod bench{ } } +mod arithmetic { + pub mod binary_arithmetic; + pub mod u32_arithmetic; + pub mod u64_arithmetic; +} + use bench::poseidon::poseidon_bench; use bench::keccak::keccak_bench; use bench::sha256::sha::sha256_bench;