risc0_zkp/core/hash/
mod.rs

1// Copyright 2024 RISC Zero, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Traits to configure which cryptographic primitives the ZKP uses
16
17pub mod blake2b;
18pub mod poseidon2;
19#[cfg(feature = "prove")]
20pub mod poseidon_254;
21pub mod sha;
22
23use alloc::{boxed::Box, rc::Rc, string::String};
24
25use risc0_core::field::{baby_bear::BabyBear, Field};
26
27use super::digest::Digest;
28
29/// A trait that sets the hashes and encodings used by the ZKP.
30pub trait HashFn<F: Field>: Send + Sync {
31    /// Generate a hash from a pair of [Digest].
32    fn hash_pair(&self, a: &Digest, b: &Digest) -> Box<Digest>;
33
34    /// Generate a hash from a slice of field elements.  This may be unpadded so
35    /// this is only safe to used when the size is known.
36    fn hash_elem_slice(&self, slice: &[F::Elem]) -> Box<Digest>;
37
38    /// Generate a hash from a slice of extension field element.  This may be
39    /// unpadded so this is only safe to used when the size is known.
40    fn hash_ext_elem_slice(&self, slice: &[F::ExtElem]) -> Box<Digest>;
41}
42
43/// A trait that sets the PRNG used by Fiat-Shamir.  We allow specialization at
44/// this level rather than at RngCore because some hashes such as Poseidon have
45/// elements distributed uniformly over the field natively.
46pub trait Rng<F: Field> {
47    /// Mix in randomness from a Fiat-Shamir commitment.
48    fn mix(&mut self, val: &Digest);
49
50    /// Get a cryptographically uniform set of bits, as the low order bits of a
51    /// u32
52    fn random_bits(&mut self, bits: usize) -> u32;
53
54    /// Get a cryptographically uniform field element
55    fn random_elem(&mut self) -> F::Elem;
56
57    /// Get a cryptographically uniform extension field element
58    fn random_ext_elem(&mut self) -> F::ExtElem;
59}
60
61/// Responsible for constructing new Rngs.
62pub trait RngFactory<F: Field> {
63    /// Construct a new Rng
64    fn new_rng(&self) -> Box<dyn Rng<F>>;
65}
66
67/// Make it easy compute both hash related traits from a single source
68pub struct HashSuite<F: Field> {
69    /// The name of this HashSuite.
70    pub name: String,
71
72    /// Define the hash used by the HashSuite
73    pub hashfn: Rc<dyn HashFn<F>>,
74
75    /// Define an RNG factory
76    pub rng: Rc<dyn RngFactory<F>>,
77}
78
79impl<F: Field> Clone for HashSuite<F> {
80    fn clone(&self) -> Self {
81        Self {
82            name: self.name.clone(),
83            hashfn: self.hashfn.clone(),
84            rng: self.rng.clone(),
85        }
86    }
87}
88
89/// Construct a supported hash function given its name. Returns None is the name does not
90/// correspond to a supported hash function.
91pub fn hash_suite_from_name(name: impl AsRef<str>) -> Option<HashSuite<BabyBear>> {
92    match name.as_ref() {
93        "sha-256" => Some(sha::Sha256HashSuite::new_suite()),
94        "poseidon2" => Some(poseidon2::Poseidon2HashSuite::new_suite()),
95        "blake2b" => Some(blake2b::Blake2bCpuHashSuite::new_suite()),
96        #[cfg(feature = "prove")]
97        "poseidon_254" => Some(poseidon_254::Poseidon254HashSuite::new_suite()),
98        _ => None,
99    }
100}