mirror of
https://github.com/logos-storage/zk-benchmarks.git
synced 2026-01-05 07:13:08 +00:00
code cleaning and fixing random bytes generation for sha256
This commit is contained in:
parent
1199701caa
commit
bbea51f947
@ -3,30 +3,76 @@ use plonky2::field::extension::Extendable;
|
||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
use plonky2::iop::target::BoolTarget;
|
||||
|
||||
//TODO: remove the dead codes later
|
||||
#[allow(dead_code)]
|
||||
pub trait CircuitBuilderBoolTarget<F: RichField + Extendable<D>, 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;
|
||||
pub fn xor_circuit<F, const D: usize>(
|
||||
a: BoolTarget,
|
||||
b: BoolTarget,
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
) -> BoolTarget
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
{
|
||||
|
||||
// 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);
|
||||
|
||||
BoolTarget::new_unsafe(a_plus_b_minus_2ab)
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilderBoolTarget<F, D>
|
||||
for CircuitBuilder<F, D>{
|
||||
fn xor(&mut self, a: BoolTarget, b: BoolTarget) -> BoolTarget {
|
||||
pub fn xor_const_circuit<F, const D: usize>(
|
||||
a: BoolTarget,
|
||||
b: bool,
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
) -> BoolTarget
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
{
|
||||
// b = 0 => xor(a, b) = a
|
||||
// b = 1 => xor(a, b) = 1 - a = not(a)
|
||||
if b {
|
||||
builder.not(a)
|
||||
} else {
|
||||
a
|
||||
}
|
||||
}
|
||||
|
||||
// a ^ b := (a - b)^2
|
||||
let s = self.sub(a.target, b.target);
|
||||
BoolTarget::new_unsafe(self.mul(s, s))
|
||||
// reffered to https://github.com/polymerdao/plonky2-sha256
|
||||
/// 0 -> [0, 1, 2, ..., 63]
|
||||
/// 1 -> [63, 0, 1, ..., 62]
|
||||
/// 63 -> [1, 2, ..., 63, 0]
|
||||
pub fn rotate_u64(y: usize) -> Vec<usize> {
|
||||
let mut res = Vec::new();
|
||||
for i in 64 - y..64 {
|
||||
res.push(i);
|
||||
}
|
||||
for i in 0..64 - y {
|
||||
res.push(i);
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
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
|
||||
}
|
||||
|
||||
// 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)
|
||||
// }
|
||||
}
|
||||
pub fn u64_to_bits(num: u64) -> Vec<bool> {
|
||||
let mut result = Vec::with_capacity(64);
|
||||
let mut n = num;
|
||||
for _ in 0..64 {
|
||||
result.push(n & 1 == 1);
|
||||
n >>= 1;
|
||||
}
|
||||
result
|
||||
}
|
||||
@ -3,97 +3,59 @@ use plonky2::hash::hash_types::RichField;
|
||||
use plonky2::field::extension::Extendable;
|
||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
use plonky2_u32::gadgets::arithmetic_u32::U32Target;
|
||||
use super::binary_arithmetic::CircuitBuilderBoolTarget;
|
||||
use plonky2_u32::gadgets::arithmetic_u32::CircuitBuilderU32;
|
||||
|
||||
//TODO: remove the dead codes later
|
||||
#[allow(dead_code)]
|
||||
pub trait CircuitBuilderU32M<F: RichField + Extendable<D>, 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 rotate_left_u32(&mut self, a: U32Target, n: u8) -> U32Target;
|
||||
|
||||
fn from_u32(&mut self, a: U32Target) -> Vec<BoolTarget>;
|
||||
fn to_u32(&mut self, a: Vec<BoolTarget>) -> U32Target;
|
||||
|
||||
// not := 0xFFFFFFFF - x
|
||||
fn not_u32(&mut self, a: U32Target) -> U32Target;
|
||||
|
||||
pub fn add_u32<F: RichField + Extendable<D>, const D: usize>(
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
a: &U32Target,
|
||||
b: &U32Target,
|
||||
) -> U32Target {
|
||||
let (res, _carry) = builder.add_u32(*a, *b);
|
||||
res
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilderU32M<F, D>
|
||||
for CircuitBuilder<F, D>{
|
||||
pub fn u32_to_bits_target<F: RichField + Extendable<D>, const D: usize, const B: usize>(
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
a: &U32Target,
|
||||
) -> Vec<BoolTarget> {
|
||||
let mut res = Vec::new();
|
||||
let bit_targets = builder.split_le_base::<B>(a.0, 32);
|
||||
for i in (0..32).rev() {
|
||||
res.push(BoolTarget::new_unsafe(bit_targets[i]));
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn from_u32(&mut self, a: U32Target) -> Vec<BoolTarget> {
|
||||
pub fn bits_to_u32_target<F: RichField + Extendable<D>, const D: usize>(
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
bits_target: Vec<BoolTarget>,
|
||||
) -> U32Target {
|
||||
let bit_len = bits_target.len();
|
||||
assert_eq!(bit_len, 32);
|
||||
U32Target(builder.le_sum(bits_target[0..32].iter().rev()))
|
||||
}
|
||||
|
||||
let mut res = Vec::new();
|
||||
let bit_targets = self.split_le_base::<2>(a.0, 32);
|
||||
// x>>y
|
||||
// Assume: 0 at index 32
|
||||
pub fn shift32(y: usize) -> Vec<usize> {
|
||||
let mut res = Vec::new();
|
||||
for _ in 32 - y..32 {
|
||||
res.push(32);
|
||||
}
|
||||
for i in 0..32 - y {
|
||||
res.push(i);
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
for i in (0..32).rev() {
|
||||
res.push(BoolTarget::new_unsafe(bit_targets[i]));
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn to_u32(&mut self, a: Vec<BoolTarget>) -> 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::<BoolTarget>::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::<BoolTarget>::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::<BoolTarget>::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)
|
||||
}
|
||||
|
||||
// fn rotate_left_u32(&mut self, a: U32Target, n: u8) -> U32Target {
|
||||
// let two_power_n = self.constant_u32(0x1 << n);
|
||||
// let (lo, hi) = self.mul_u32(a, two_power_n);
|
||||
// self.add_u32(lo, hi).0
|
||||
// }
|
||||
|
||||
// not := 0xFFFFFFFF - x
|
||||
fn not_u32(&mut self, a: U32Target) -> U32Target {
|
||||
let zero = self.zero_u32();
|
||||
let ff = self.constant_u32(0xFFFFFFFF);
|
||||
self.sub_u32(ff, a, zero).0
|
||||
}
|
||||
|
||||
}
|
||||
// define ROTATE(x, y) (((x)>>(y)) | ((x)<<(32-(y))))
|
||||
pub fn rotate32(y: usize) -> Vec<usize> {
|
||||
let mut res = Vec::new();
|
||||
for i in 32 - y..32 {
|
||||
res.push(i);
|
||||
}
|
||||
for i in 0..32 - y {
|
||||
res.push(i);
|
||||
}
|
||||
res
|
||||
}
|
||||
@ -1,65 +1,152 @@
|
||||
use plonky2::hash::hash_types::RichField;
|
||||
use plonky2::field::extension::Extendable;
|
||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
use plonky2_u32::gadgets::arithmetic_u32::U32Target;
|
||||
use super::u32_arithmetic::CircuitBuilderU32M;
|
||||
use plonky2_u32::gadgets::arithmetic_u32::CircuitBuilderU32;
|
||||
use std::marker::PhantomData;
|
||||
use plonky2::iop::target::BoolTarget;
|
||||
use plonky2::iop::witness::PartialWitness;
|
||||
use plonky2::iop::witness::WitnessWrite;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct U64Target(pub [U32Target;2]);
|
||||
use crate::arithmetic::binary_arithmetic::{rotate_u64,xor_const_circuit,u64_to_bits,xor_circuit};
|
||||
|
||||
//TODO: remove the dead codes later
|
||||
#[allow(dead_code)]
|
||||
pub trait CircuitBuilderU64<F: RichField + Extendable<D>, const D: usize> {
|
||||
fn and_u64(&mut self, a: U64Target, b: U64Target) -> U64Target;
|
||||
fn xor_u64(&mut self, a: U64Target, b: U64Target) -> U64Target;
|
||||
fn rotate_left_u64(&mut self, a: U64Target, n: u8) -> U64Target;
|
||||
|
||||
fn zero_u64(&mut self) -> U64Target;
|
||||
|
||||
fn not_u64(&mut self, a: U64Target) -> U64Target;
|
||||
fn add_virtual_u64_target(&mut self) -> U64Target;
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct U64Target<F, const D: usize> {
|
||||
pub bits: Vec<BoolTarget>,
|
||||
_phantom: PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilderU64<F, D>
|
||||
for CircuitBuilder<F, D>{
|
||||
fn xor_u64(&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]));
|
||||
impl<F, const D: usize> U64Target<F, D>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
{
|
||||
pub fn new(builder: &mut CircuitBuilder<F, D>) -> Self {
|
||||
let mut result = vec![];
|
||||
for _ in 0..64 {
|
||||
result.push(builder.add_virtual_bool_target_safe());
|
||||
}
|
||||
U64Target([result[0], result[1]])
|
||||
}
|
||||
|
||||
fn and_u64(&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]));
|
||||
Self {
|
||||
bits: result,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
U64Target([result[0], result[1]])
|
||||
}
|
||||
|
||||
fn rotate_left_u64(&mut self, a: U64Target, n: u8) -> U64Target {
|
||||
let (lo, hi) = if n < 32 { (a.0[0], a.0[1]) } else { (a.0[1], a.0[0]) };
|
||||
|
||||
let two_power_x = self.constant_u32(0x1 << (n % 32));
|
||||
let (lo0, hi0) = self.mul_u32(lo, two_power_x);
|
||||
let (lo1, hi1) = self.mul_add_u32(hi, two_power_x, hi0);
|
||||
|
||||
U64Target([self.add_u32(lo0, hi1).0, lo1])
|
||||
pub fn from(bits: Vec<BoolTarget>) -> Self {
|
||||
assert_eq!(bits.len(), 64);
|
||||
Self {
|
||||
bits,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn zero_u64(&mut self) -> U64Target {
|
||||
let zero_u32 = self.zero_u32();
|
||||
U64Target([zero_u32,zero_u32])
|
||||
pub fn set_witness(&self, bits: Vec<bool>, pw: &mut PartialWitness<F>) {
|
||||
for i in 0..64 {
|
||||
pw.set_bool_target(self.bits[i], bits[i]);
|
||||
}
|
||||
}
|
||||
|
||||
fn not_u64(&mut self, a: U64Target) -> U64Target {
|
||||
U64Target([self.not_u32(a.0[0]), self.not_u32(a.0[1])])
|
||||
pub fn constant(x: u64, builder: &mut CircuitBuilder<F, D>) -> 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,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_virtual_u64_target(&mut self) -> U64Target {
|
||||
U64Target([U32Target(self.add_virtual_target()),U32Target(self.add_virtual_target())])
|
||||
pub fn connect(&self, other: &Self, builder: &mut CircuitBuilder<F, D>) {
|
||||
for i in 0..64 {
|
||||
builder.connect(self.bits[i].target, other.bits[i].target);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_bits(&self, builder: &mut CircuitBuilder<F, D>) -> Vec<BoolTarget> {
|
||||
let output = Self::new(builder);
|
||||
self.connect(&output, builder);
|
||||
output.bits
|
||||
}
|
||||
|
||||
pub fn xor(&self, other: &Self, builder: &mut CircuitBuilder<F, D>) -> 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<F, D>) -> 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<F, D>) -> 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<F, D>) -> 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<F, D>) -> 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -20,227 +20,8 @@ use plonky2::plonk::circuit_data::CircuitConfig;
|
||||
use plonky2::plonk::config::PoseidonGoldilocksConfig;
|
||||
use anyhow::Result;
|
||||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct U64Target<F, const D: usize> {
|
||||
pub bits: Vec<BoolTarget>,
|
||||
_phantom: PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<F, const D: usize> U64Target<F, D>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
{
|
||||
pub fn new(builder: &mut CircuitBuilder<F, D>) -> Self {
|
||||
let mut result = vec![];
|
||||
for _ in 0..64 {
|
||||
result.push(builder.add_virtual_bool_target_safe());
|
||||
}
|
||||
Self {
|
||||
bits: result,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from(bits: Vec<BoolTarget>) -> Self {
|
||||
assert_eq!(bits.len(), 64);
|
||||
Self {
|
||||
bits,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_witness(&self, bits: Vec<bool>, pw: &mut PartialWitness<F>) {
|
||||
for i in 0..64 {
|
||||
pw.set_bool_target(self.bits[i], bits[i]);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn constant(x: u64, builder: &mut CircuitBuilder<F, D>) -> 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<F, D>) {
|
||||
for i in 0..64 {
|
||||
builder.connect(self.bits[i].target, other.bits[i].target);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_bits(&self, builder: &mut CircuitBuilder<F, D>) -> Vec<BoolTarget> {
|
||||
let output = Self::new(builder);
|
||||
self.connect(&output, builder);
|
||||
output.bits
|
||||
}
|
||||
|
||||
pub fn xor(&self, other: &Self, builder: &mut CircuitBuilder<F, D>) -> 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<F, D>) -> 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<F, D>) -> 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<F, D>) -> 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<F, D>) -> 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn xor_circuit<F, const D: usize>(
|
||||
a: BoolTarget,
|
||||
b: BoolTarget,
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
) -> BoolTarget
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
{
|
||||
// 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);
|
||||
|
||||
BoolTarget::new_unsafe(a_plus_b_minus_2ab)
|
||||
}
|
||||
|
||||
pub fn xor_const_circuit<F, const D: usize>(
|
||||
a: BoolTarget,
|
||||
b: bool,
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
) -> BoolTarget
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
{
|
||||
// b = 0 => xor(a, b) = a
|
||||
// b = 1 => xor(a, b) = 1 - a = not(a)
|
||||
if b {
|
||||
builder.not(a)
|
||||
} else {
|
||||
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<usize> {
|
||||
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<bool> {
|
||||
let mut result = Vec::with_capacity(64);
|
||||
let mut n = num;
|
||||
for _ in 0..64 {
|
||||
result.push(n & 1 == 1);
|
||||
n >>= 1;
|
||||
}
|
||||
result
|
||||
}
|
||||
use crate::arithmetic::binary_arithmetic::xor_circuit;
|
||||
use crate::arithmetic::u64_arithmetic::U64Target;
|
||||
|
||||
pub const ROUND_CONSTANTS: [u64; 24] = [
|
||||
1u64,
|
||||
|
||||
@ -40,7 +40,7 @@ pub fn poseidon_bench(depth: usize) -> Result<()> {
|
||||
let hash = builder.hash_or_noop::<PoseidonHash>(initial.clone());
|
||||
|
||||
// Public inputs are the initial value (provided below) and the result (which is generated).
|
||||
builder.register_public_inputs(initial.clone().as_slice());
|
||||
// builder.register_public_inputs(initial.clone().as_slice());
|
||||
builder.register_public_input(hash.elements[0]);
|
||||
builder.register_public_input(hash.elements[1]);
|
||||
builder.register_public_input(hash.elements[2]);
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
// use plonky2::{hash::hash_types::HashOutTarget, iop::target::Target, iop::target::BoolTarget};
|
||||
use plonky2::iop::target::BoolTarget;
|
||||
|
||||
use plonky2::hash::hash_types::RichField;
|
||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
// use plonky2_field::extension;
|
||||
use plonky2::field::extension::Extendable;
|
||||
use plonky2_u32::gadgets::arithmetic_u32::U32Target;
|
||||
use super::sigma::bits_to_u32_target;
|
||||
use super::sigma::u32_to_bits_target;
|
||||
use crate::arithmetic::u32_arithmetic::{bits_to_u32_target, u32_to_bits_target};
|
||||
|
||||
|
||||
pub fn ch<F: RichField + Extendable<D>, const D: usize>(
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
|
||||
@ -4,8 +4,7 @@ use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
use plonky2::field::extension::Extendable;
|
||||
use plonky2_u32::gadgets::arithmetic_u32::U32Target;
|
||||
|
||||
use super::sigma::u32_to_bits_target;
|
||||
use super::sigma::bits_to_u32_target;
|
||||
use crate::arithmetic::u32_arithmetic::{bits_to_u32_target, u32_to_bits_target};
|
||||
|
||||
pub fn maj<F: RichField + Extendable<D>, const D: usize>(
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
// define ROTATE(x, y) (((x)>>(y)) | ((x)<<(32-(y))))
|
||||
pub fn rotate32(y: usize) -> Vec<usize> {
|
||||
let mut res = Vec::new();
|
||||
for i in 32 - y..32 {
|
||||
res.push(i);
|
||||
}
|
||||
for i in 0..32 - y {
|
||||
res.push(i);
|
||||
}
|
||||
res
|
||||
}
|
||||
@ -1,3 +1,5 @@
|
||||
// code is taken from https://github.com/polymerdao/plonky2-sha256
|
||||
|
||||
use plonky2::iop::target::BoolTarget;
|
||||
use plonky2::hash::hash_types::RichField;
|
||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
@ -16,15 +18,8 @@ use super::sigma::sigma1;
|
||||
use super::maj::maj;
|
||||
use super::constants::*;
|
||||
use super::ch::ch;
|
||||
|
||||
fn add_u32<F: RichField + Extendable<D>, const D: usize>(
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
a: &U32Target,
|
||||
b: &U32Target,
|
||||
) -> U32Target {
|
||||
let (res, _carry) = builder.add_u32(*a, *b);
|
||||
res
|
||||
}
|
||||
use crate::arithmetic::u32_arithmetic::add_u32;
|
||||
use rand::Rng;
|
||||
|
||||
pub struct Sha256Targets {
|
||||
pub message: Vec<BoolTarget>,
|
||||
@ -179,19 +174,18 @@ pub fn make_circuits<F: RichField + Extendable<D>, const D: usize>(
|
||||
}
|
||||
|
||||
|
||||
fn generate_random_bytes() -> Vec<u8> {
|
||||
const MSG_SIZE: usize = 64;
|
||||
let mut msg = vec![0; MSG_SIZE as usize];
|
||||
for i in 0..MSG_SIZE - 1 {
|
||||
msg[i] = i as u8;
|
||||
}
|
||||
fn generate_random_bytes(size: usize) -> Vec<u8> {
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut bytes = vec![0u8; size];
|
||||
rng.fill(&mut bytes[..]);
|
||||
|
||||
msg
|
||||
bytes
|
||||
|
||||
}
|
||||
|
||||
pub fn sha256_bench() -> Result<()> {
|
||||
let msg = generate_random_bytes();
|
||||
pub fn sha256_bench(size: usize) -> Result<()> {
|
||||
let msg = generate_random_bytes(size);
|
||||
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(msg.clone());
|
||||
@ -221,7 +215,7 @@ pub fn sha256_bench() -> Result<()> {
|
||||
}
|
||||
|
||||
println!(
|
||||
"Constructing inner proof with {} gates",
|
||||
"number of gates: {}",
|
||||
builder.num_gates()
|
||||
);
|
||||
let data = builder.build::<C>();
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
// x>>y
|
||||
// Assume: 0 at index 32
|
||||
pub fn shift32(y: usize) -> Vec<usize> {
|
||||
let mut res = Vec::new();
|
||||
for _ in 32 - y..32 {
|
||||
res.push(32);
|
||||
}
|
||||
for i in 0..32 - y {
|
||||
res.push(i);
|
||||
}
|
||||
res
|
||||
}
|
||||
@ -1,36 +1,12 @@
|
||||
// use plonky2::{hash::hash_types::HashOutTarget, iop::target::Target, iop::target::BoolTarget};
|
||||
use plonky2::iop::target::BoolTarget;
|
||||
|
||||
use plonky2::hash::hash_types::RichField;
|
||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
// use plonky2_field::extension;
|
||||
use plonky2::field::extension::Extendable;
|
||||
use plonky2_u32::gadgets::arithmetic_u32::U32Target;
|
||||
use super::shift::shift32;
|
||||
use super::rotate::rotate32;
|
||||
use crate::arithmetic::u32_arithmetic::{rotate32, shift32};
|
||||
use crate::arithmetic::u32_arithmetic::u32_to_bits_target;
|
||||
use crate::arithmetic::u32_arithmetic::bits_to_u32_target;
|
||||
use super::xor3::xor3;
|
||||
|
||||
pub fn u32_to_bits_target<F: RichField + Extendable<D>, const D: usize, const B: usize>(
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
a: &U32Target,
|
||||
) -> Vec<BoolTarget> {
|
||||
let mut res = Vec::new();
|
||||
let bit_targets = builder.split_le_base::<B>(a.0, 32);
|
||||
for i in (0..32).rev() {
|
||||
res.push(BoolTarget::new_unsafe(bit_targets[i]));
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
pub fn bits_to_u32_target<F: RichField + Extendable<D>, const D: usize>(
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
bits_target: Vec<BoolTarget>,
|
||||
) -> U32Target {
|
||||
let bit_len = bits_target.len();
|
||||
assert_eq!(bit_len, 32);
|
||||
U32Target(builder.le_sum(bits_target[0..32].iter().rev()))
|
||||
}
|
||||
|
||||
pub fn sigma0<F: RichField + Extendable<D>, const D: usize>(
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
a: &U32Target,
|
||||
|
||||
@ -3,8 +3,6 @@ mod bench{
|
||||
pub mod poseidon;
|
||||
pub mod sha256{
|
||||
pub mod constants;
|
||||
pub mod shift;
|
||||
pub mod rotate;
|
||||
pub mod sigma;
|
||||
pub mod sha;
|
||||
pub mod xor3;
|
||||
@ -56,7 +54,7 @@ fn main() {
|
||||
|
||||
"sha256" => {
|
||||
println!("Running sha256: ");
|
||||
let _ = sha256_bench();
|
||||
let _ = sha256_bench(size);
|
||||
}
|
||||
|
||||
_ => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user