Comments and cleaning

This commit is contained in:
wborgeaud 2021-11-05 15:22:52 +01:00
parent d4c8caa208
commit b83f29cca2
3 changed files with 119 additions and 97 deletions

View File

@ -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<HashOutTarget>);
/// Hash consisting of a byte array.
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub struct BytesHash<const N: usize>(pub [u8; N]);
impl<const N: usize> Serialize for BytesHash<N> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
todo!()
}
}
impl<'de, const N: usize> Deserialize<'de> for BytesHash<N> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
todo!()
}
}
impl<const N: usize> From<Vec<u8>> for BytesHash<N> {
fn from(v: Vec<u8>) -> Self {
Self(v.try_into().unwrap())
}
}
impl<const N: usize> From<BytesHash<N>> for Vec<u8> {
fn from(hash: BytesHash<N>) -> Self {
hash.0.to_vec()
}
}
impl<const N: usize> From<BytesHash<N>> for u64 {
fn from(hash: BytesHash<N>) -> Self {
u64::from_le_bytes(hash.0[..8].try_into().unwrap())
}
}
impl<F: RichField, const N: usize> From<BytesHash<N>> for Vec<F> {
fn from(hash: BytesHash<N>) -> 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()
}
}

View File

@ -93,6 +93,7 @@ pub fn compress<F: RichField, P: PlonkyPermutation<F>>(x: HashOut<F>, y: HashOut
}
}
/// Permutation that can be used in the sponge construction for an algebraic hash.
pub trait PlonkyPermutation<F: RichField> {
fn permute(input: [F; SPONGE_WIDTH]) -> [F; SPONGE_WIDTH];
}

View File

@ -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<F: RichField>: Sized + Clone + Debug + Eq + PartialEq {
/// Size of `Hash` in bytes.
const HASH_SIZE: usize;
@ -40,6 +41,25 @@ pub trait Hasher<F: RichField>: 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<F: RichField>: Hasher<F, Hash = HashOut<F>> {
// 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<F>;
/// Circuit to conditionally swap two chunks of the inputs (useful in verifying Merkle proofs),
/// then apply the permutation.
fn permute_swapped<const D: usize>(
inputs: [Target; SPONGE_WIDTH],
swap: BoolTarget,
builder: &mut CircuitBuilder<F, D>,
) -> [Target; SPONGE_WIDTH]
where
F: Extendable<D>;
}
/// Poseidon hash function.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct PoseidonHash;
impl<F: RichField> Hasher<F> for PoseidonHash {
@ -139,53 +159,7 @@ impl<F: RichField> AlgebraicHasher<F> for PoseidonHash {
// }
// }
pub trait AlgebraicHasher<F: RichField>: Hasher<F, Hash = HashOut<F>> {
// TODO: Adding a `const WIDTH: usize` here yields a compiler error down the line.
// Maybe try again in a while.
type Permutation: PlonkyPermutation<F>;
fn permute_swapped<const D: usize>(
inputs: [Target; SPONGE_WIDTH],
swap: BoolTarget,
builder: &mut CircuitBuilder<F, D>,
) -> [Target; SPONGE_WIDTH]
where
F: Extendable<D>;
}
pub trait GenericConfig<const D: usize>:
Debug + Clone + Sync + Sized + Send + Eq + PartialEq
{
type F: RichField + Extendable<D, Extension = Self::FE>;
type FE: FieldExtension<D, BaseField = Self::F>;
type Hasher: Hasher<Self::F>;
type InnerHasher: AlgebraicHasher<Self::F>;
}
pub trait AlgebraicConfig<const D: usize>:
Debug + Clone + Sync + Sized + Send + Eq + PartialEq
{
type F: RichField + Extendable<D, Extension = Self::FE>;
type FE: FieldExtension<D, BaseField = Self::F>;
type Hasher: AlgebraicHasher<Self::F>;
type InnerHasher: AlgebraicHasher<Self::F>;
}
impl<A: AlgebraicConfig<D>, const D: usize> GenericConfig<D> for A {
type F = <Self as AlgebraicConfig<D>>::F;
type FE = <Self as AlgebraicConfig<D>>::FE;
type Hasher = <Self as AlgebraicConfig<D>>::Hasher;
type InnerHasher = <Self as AlgebraicConfig<D>>::InnerHasher;
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct PoseidonGoldilocksConfig;
impl AlgebraicConfig<2> for PoseidonGoldilocksConfig {
type F = GoldilocksField;
type FE = QuadraticExtension<Self::F>;
type Hasher = PoseidonHash;
type InnerHasher = PoseidonHash;
}
/// Keccak hash function.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct KeccakHash<const N: usize>;
impl<F: RichField, const N: usize> Hasher<F> for KeccakHash<N> {
@ -210,6 +184,50 @@ impl<F: RichField, const N: usize> Hasher<F> for KeccakHash<N> {
}
}
/// Generic configuration trait.
pub trait GenericConfig<const D: usize>:
Debug + Clone + Sync + Sized + Send + Eq + PartialEq
{
/// Main field.
type F: RichField + Extendable<D, Extension = Self::FE>;
/// Field extension of degree 4 of the main field.
type FE: FieldExtension<D, BaseField = Self::F>;
/// Hash function used for building Merkle trees.
type Hasher: Hasher<Self::F>;
/// Algebraic hash function used for the challenger and hashing public inputs.
type InnerHasher: AlgebraicHasher<Self::F>;
}
/// Configuration trait for "algebraic" configurations, i.e., those using an algebraic hash function
/// in Merkle trees.
/// Same as `GenericConfig` trait but with `InnerHasher: AlgebraicHasher<F>`.
pub trait AlgebraicConfig<const D: usize>:
Debug + Clone + Sync + Sized + Send + Eq + PartialEq
{
type F: RichField + Extendable<D, Extension = Self::FE>;
type FE: FieldExtension<D, BaseField = Self::F>;
type Hasher: AlgebraicHasher<Self::F>;
type InnerHasher: AlgebraicHasher<Self::F>;
}
impl<A: AlgebraicConfig<D>, const D: usize> GenericConfig<D> for A {
type F = <Self as AlgebraicConfig<D>>::F;
type FE = <Self as AlgebraicConfig<D>>::FE;
type Hasher = <Self as AlgebraicConfig<D>>::Hasher;
type InnerHasher = <Self as AlgebraicConfig<D>>::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<Self::F>;
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<const N: usize>([u8; N]);
impl<const N: usize> Serialize for BytesHash<N> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
todo!()
}
}
impl<'de, const N: usize> Deserialize<'de> for BytesHash<N> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
todo!()
}
}
impl<const N: usize> From<Vec<u8>> for BytesHash<N> {
fn from(v: Vec<u8>) -> Self {
Self(v.try_into().unwrap())
}
}
impl<const N: usize> From<BytesHash<N>> for Vec<u8> {
fn from(hash: BytesHash<N>) -> Self {
hash.0.to_vec()
}
}
impl<const N: usize> From<BytesHash<N>> for u64 {
fn from(hash: BytesHash<N>) -> Self {
u64::from_le_bytes(hash.0[..8].try_into().unwrap())
}
}
impl<F: RichField, const N: usize> From<BytesHash<N>> for Vec<F> {
fn from(hash: BytesHash<N>) -> 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()
}
}