From b83f29cca285bece39e8c1db4a77cf3de6add543 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 5 Nov 2021 15:22:52 +0100 Subject: [PATCH] Comments and cleaning --- src/hash/hash_types.rs | 54 +++++++++++++- src/hash/hashing.rs | 1 + src/plonk/config.rs | 161 +++++++++++++++++------------------------ 3 files changed, 119 insertions(+), 97 deletions(-) diff --git a/src/hash/hash_types.rs b/src/hash/hash_types.rs index e0f95c88..378431fc 100644 --- a/src/hash/hash_types.rs +++ b/src/hash/hash_types.rs @@ -1,10 +1,12 @@ use std::convert::TryInto; use rand::Rng; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, PrimeField, RichField}; use crate::iop::target::Target; +use crate::util::ceil_div_usize; +use crate::util::serialization::Buffer; /// Represents a ~256 bit hash output. #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] @@ -121,3 +123,51 @@ impl HashOutTarget { #[derive(Clone, Debug)] pub struct MerkleCapTarget(pub Vec); + +/// Hash consisting of a byte array. +#[derive(Eq, PartialEq, Copy, Clone, Debug)] +pub struct BytesHash(pub [u8; N]); +impl Serialize for BytesHash { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + todo!() + } +} +impl<'de, const N: usize> Deserialize<'de> for BytesHash { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + todo!() + } +} + +impl From> for BytesHash { + fn from(v: Vec) -> Self { + Self(v.try_into().unwrap()) + } +} + +impl From> for Vec { + fn from(hash: BytesHash) -> Self { + hash.0.to_vec() + } +} + +impl From> for u64 { + fn from(hash: BytesHash) -> Self { + u64::from_le_bytes(hash.0[..8].try_into().unwrap()) + } +} + +impl From> for Vec { + fn from(hash: BytesHash) -> Self { + let n = hash.0.len(); + let mut v = hash.0.to_vec(); + v.resize(ceil_div_usize(n, 8) * 8, 0); + let mut buffer = Buffer::new(v); + buffer.read_field_vec(buffer.len() / 8).unwrap() + } +} diff --git a/src/hash/hashing.rs b/src/hash/hashing.rs index 309182dc..3a5cc48d 100644 --- a/src/hash/hashing.rs +++ b/src/hash/hashing.rs @@ -93,6 +93,7 @@ pub fn compress>(x: HashOut, y: HashOut } } +/// Permutation that can be used in the sponge construction for an algebraic hash. pub trait PlonkyPermutation { fn permute(input: [F; SPONGE_WIDTH]) -> [F; SPONGE_WIDTH]; } diff --git a/src/plonk/config.rs b/src/plonk/config.rs index 1eec858d..771a3ce7 100644 --- a/src/plonk/config.rs +++ b/src/plonk/config.rs @@ -10,7 +10,7 @@ use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::field_types::RichField; use crate::field::goldilocks_field::GoldilocksField; use crate::gates::poseidon::PoseidonGate; -use crate::hash::hash_types::HashOut; +use crate::hash::hash_types::{BytesHash, HashOut}; use crate::hash::hashing::{ compress, hash_n_to_hash, PlonkyPermutation, PoseidonPermutation, SPONGE_WIDTH, }; @@ -19,6 +19,7 @@ use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::ceil_div_usize; use crate::util::serialization::Buffer; +/// Trait for hash functions. pub trait Hasher: Sized + Clone + Debug + Eq + PartialEq { /// Size of `Hash` in bytes. const HASH_SIZE: usize; @@ -40,6 +41,25 @@ pub trait Hasher: Sized + Clone + Debug + Eq + PartialEq { fn two_to_one(left: Self::Hash, right: Self::Hash) -> Self::Hash; } +/// Trait for algebraic hash functions, built from a permutation using the sponge construction. +pub trait AlgebraicHasher: Hasher> { + // TODO: Adding a `const WIDTH: usize` here yields a compiler error down the line. + // Maybe try again in a while. + + /// Permutation used in the sponge construction. + type Permutation: PlonkyPermutation; + /// Circuit to conditionally swap two chunks of the inputs (useful in verifying Merkle proofs), + /// then apply the permutation. + fn permute_swapped( + inputs: [Target; SPONGE_WIDTH], + swap: BoolTarget, + builder: &mut CircuitBuilder, + ) -> [Target; SPONGE_WIDTH] + where + F: Extendable; +} + +/// Poseidon hash function. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct PoseidonHash; impl Hasher for PoseidonHash { @@ -139,53 +159,7 @@ impl AlgebraicHasher for PoseidonHash { // } // } -pub trait AlgebraicHasher: Hasher> { - // TODO: Adding a `const WIDTH: usize` here yields a compiler error down the line. - // Maybe try again in a while. - type Permutation: PlonkyPermutation; - fn permute_swapped( - inputs: [Target; SPONGE_WIDTH], - swap: BoolTarget, - builder: &mut CircuitBuilder, - ) -> [Target; SPONGE_WIDTH] - where - F: Extendable; -} - -pub trait GenericConfig: - Debug + Clone + Sync + Sized + Send + Eq + PartialEq -{ - type F: RichField + Extendable; - type FE: FieldExtension; - type Hasher: Hasher; - type InnerHasher: AlgebraicHasher; -} - -pub trait AlgebraicConfig: - Debug + Clone + Sync + Sized + Send + Eq + PartialEq -{ - type F: RichField + Extendable; - type FE: FieldExtension; - type Hasher: AlgebraicHasher; - type InnerHasher: AlgebraicHasher; -} - -impl, const D: usize> GenericConfig for A { - type F = >::F; - type FE = >::FE; - type Hasher = >::Hasher; - type InnerHasher = >::InnerHasher; -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct PoseidonGoldilocksConfig; -impl AlgebraicConfig<2> for PoseidonGoldilocksConfig { - type F = GoldilocksField; - type FE = QuadraticExtension; - type Hasher = PoseidonHash; - type InnerHasher = PoseidonHash; -} - +/// Keccak hash function. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct KeccakHash; impl Hasher for KeccakHash { @@ -210,6 +184,50 @@ impl Hasher for KeccakHash { } } +/// Generic configuration trait. +pub trait GenericConfig: + Debug + Clone + Sync + Sized + Send + Eq + PartialEq +{ + /// Main field. + type F: RichField + Extendable; + /// Field extension of degree 4 of the main field. + type FE: FieldExtension; + /// Hash function used for building Merkle trees. + type Hasher: Hasher; + /// Algebraic hash function used for the challenger and hashing public inputs. + type InnerHasher: AlgebraicHasher; +} + +/// Configuration trait for "algebraic" configurations, i.e., those using an algebraic hash function +/// in Merkle trees. +/// Same as `GenericConfig` trait but with `InnerHasher: AlgebraicHasher`. +pub trait AlgebraicConfig: + Debug + Clone + Sync + Sized + Send + Eq + PartialEq +{ + type F: RichField + Extendable; + type FE: FieldExtension; + type Hasher: AlgebraicHasher; + type InnerHasher: AlgebraicHasher; +} + +impl, const D: usize> GenericConfig for A { + type F = >::F; + type FE = >::FE; + type Hasher = >::Hasher; + type InnerHasher = >::InnerHasher; +} + +/// Configuration using Poseidon over the Goldilocks field. +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct PoseidonGoldilocksConfig; +impl AlgebraicConfig<2> for PoseidonGoldilocksConfig { + type F = GoldilocksField; + type FE = QuadraticExtension; + type Hasher = PoseidonHash; + type InnerHasher = PoseidonHash; +} + +/// Configuration using truncated Keccak over the Goldilocks field. #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub struct KeccakGoldilocksConfig; impl GenericConfig<2> for KeccakGoldilocksConfig { @@ -218,50 +236,3 @@ impl GenericConfig<2> for KeccakGoldilocksConfig { type Hasher = KeccakHash<25>; type InnerHasher = PoseidonHash; } - -#[derive(Eq, PartialEq, Copy, Clone, Debug)] -pub struct BytesHash([u8; N]); -impl Serialize for BytesHash { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - todo!() - } -} -impl<'de, const N: usize> Deserialize<'de> for BytesHash { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - todo!() - } -} - -impl From> for BytesHash { - fn from(v: Vec) -> Self { - Self(v.try_into().unwrap()) - } -} - -impl From> for Vec { - fn from(hash: BytesHash) -> Self { - hash.0.to_vec() - } -} - -impl From> for u64 { - fn from(hash: BytesHash) -> Self { - u64::from_le_bytes(hash.0[..8].try_into().unwrap()) - } -} - -impl From> for Vec { - fn from(hash: BytesHash) -> Self { - let n = hash.0.len(); - let mut v = hash.0.to_vec(); - v.resize(ceil_div_usize(n, 8) * 8, 0); - let mut buffer = Buffer::new(v); - buffer.read_field_vec(buffer.len() / 8).unwrap() - } -}