mirror of
https://github.com/logos-storage/zk-benchmarks.git
synced 2026-08-10 00:23:12 +00:00
plonky2 circuit for keccak256. code taken from https://github.com/qope/plonky2-keccak256/tree/main
This commit is contained in:
parent
5e7d6fd8c8
commit
1199701caa
@ -13,6 +13,8 @@ plonky2 = "0.2.2"
|
|||||||
rand = "0.8.3"
|
rand = "0.8.3"
|
||||||
anyhow = "1.0.79"
|
anyhow = "1.0.79"
|
||||||
sha2 = "0.10"
|
sha2 = "0.10"
|
||||||
|
tiny-keccak={version="2.0.2", features=["keccak"]}
|
||||||
|
hex="0.4.3"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,7 @@ pub trait CircuitBuilderU64<F: RichField + Extendable<D>, const D: usize> {
|
|||||||
fn zero_u64(&mut self) -> U64Target;
|
fn zero_u64(&mut self) -> U64Target;
|
||||||
|
|
||||||
fn not_u64(&mut self, a: U64Target) -> U64Target;
|
fn not_u64(&mut self, a: U64Target) -> U64Target;
|
||||||
|
fn add_virtual_u64_target(&mut self) -> U64Target;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilderU64<F, D>
|
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilderU64<F, D>
|
||||||
@ -57,4 +58,8 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilderU64<F, D>
|
|||||||
fn not_u64(&mut self, a: U64Target) -> U64Target {
|
fn not_u64(&mut self, a: U64Target) -> U64Target {
|
||||||
U64Target([self.not_u32(a.0[0]), self.not_u32(a.0[1])])
|
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())])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -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<F: RichField + Extendable<D>, const D: usize>(
|
|
||||||
builder: &mut CircuitBuilder<F, D>,
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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<F: RichField + Extendable<D>, const D: usize>(
|
|
||||||
builder: &mut CircuitBuilder<F, D>,
|
|
||||||
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])) ;
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -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<F: RichField + Extendable<D>, const D: usize>(
|
|
||||||
builder: &mut CircuitBuilder<F, D>,
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@ -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<F: RichField + Extendable<D>, const D: usize>(
|
|
||||||
builder: &mut CircuitBuilder<F, D>,
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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<F: RichField + Extendable<D>, const D: usize>(
|
|
||||||
builder: &mut CircuitBuilder<F, D>,
|
|
||||||
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<F: RichField + Extendable<D>, const D: usize>(
|
|
||||||
builder: &mut CircuitBuilder<F, D>,
|
|
||||||
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::<F, D>::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::<PoseidonGoldilocksConfig>();
|
|
||||||
|
|
||||||
// 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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -14,11 +14,6 @@ mod bench{
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub mod keccak256{
|
pub mod keccak256{
|
||||||
pub mod theta;
|
|
||||||
pub mod rho;
|
|
||||||
pub mod pi;
|
|
||||||
pub mod iota;
|
|
||||||
pub mod chi;
|
|
||||||
pub mod keccak;
|
pub mod keccak;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user