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}