filecoin_hashers/
sha256.rs1use std::fmt::{self, Debug, Formatter};
2use std::hash::Hasher as StdHasher;
3use std::panic::panic_any;
4
5use anyhow::ensure;
6use bellperson::{
7 gadgets::{boolean::Boolean, multipack, num::AllocatedNum, sha256::sha256 as sha256_circuit},
8 ConstraintSystem, SynthesisError,
9};
10use blstrs::Scalar as Fr;
11use ff::{Field, PrimeField};
12use merkletree::{
13 hash::{Algorithm, Hashable},
14 merkle::Element,
15};
16use rand::RngCore;
17use serde::{Deserialize, Serialize};
18use sha2::{Digest, Sha256};
19
20use crate::types::{Domain, HashFunction, Hasher};
21
22#[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
23pub struct Sha256Hasher {}
24
25impl Hasher for Sha256Hasher {
26 type Domain = Sha256Domain;
27 type Function = Sha256Function;
28
29 fn name() -> String {
30 "sha256_hasher".into()
31 }
32}
33
34#[derive(Default, Clone, Debug)]
35pub struct Sha256Function(Sha256);
36
37impl StdHasher for Sha256Function {
38 #[inline]
39 fn write(&mut self, msg: &[u8]) {
40 self.0.update(msg)
41 }
42
43 #[inline]
44 fn finish(&self) -> u64 {
45 unreachable!("unused by Function -- should never be called")
46 }
47}
48
49#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize, Hash)]
50pub struct Sha256Domain(pub [u8; 32]);
51
52impl Debug for Sha256Domain {
53 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
54 write!(f, "Sha256Domain({})", hex::encode(self.0))
55 }
56}
57
58impl AsRef<Sha256Domain> for Sha256Domain {
59 fn as_ref(&self) -> &Self {
60 self
61 }
62}
63
64impl Sha256Domain {
65 fn trim_to_fr32(&mut self) {
66 self.0[31] &= 0b0011_1111;
68 }
69}
70
71impl AsRef<[u8]> for Sha256Domain {
72 fn as_ref(&self) -> &[u8] {
73 &self.0[..]
74 }
75}
76
77impl Hashable<Sha256Function> for Sha256Domain {
78 fn hash(&self, state: &mut Sha256Function) {
79 state.write(self.as_ref())
80 }
81}
82
83impl From<Fr> for Sha256Domain {
84 fn from(val: Fr) -> Self {
85 Sha256Domain(val.to_repr())
86 }
87}
88
89impl From<Sha256Domain> for Fr {
90 fn from(val: Sha256Domain) -> Self {
91 Fr::from_repr_vartime(val.0).expect("from_repr failure")
92 }
93}
94
95impl Domain for Sha256Domain {
96 fn into_bytes(&self) -> Vec<u8> {
97 self.0.to_vec()
98 }
99
100 fn try_from_bytes(raw: &[u8]) -> anyhow::Result<Self> {
101 ensure!(
102 raw.len() == Sha256Domain::byte_len(),
103 "invalid number of bytes"
104 );
105
106 let mut res = Sha256Domain::default();
107 res.0.copy_from_slice(&raw[0..Sha256Domain::byte_len()]);
108 Ok(res)
109 }
110
111 fn write_bytes(&self, dest: &mut [u8]) -> anyhow::Result<()> {
112 ensure!(
113 dest.len() >= Sha256Domain::byte_len(),
114 "invalid number of bytes"
115 );
116
117 dest[0..Sha256Domain::byte_len()].copy_from_slice(&self.0[..]);
118 Ok(())
119 }
120
121 fn random<R: RngCore>(rng: &mut R) -> Self {
122 Fr::random(rng).into()
124 }
125}
126
127impl Element for Sha256Domain {
128 fn byte_len() -> usize {
129 32
130 }
131
132 fn from_slice(bytes: &[u8]) -> Self {
133 match Sha256Domain::try_from_bytes(bytes) {
134 Ok(res) => res,
135 Err(err) => panic_any(err),
136 }
137 }
138
139 fn copy_to_slice(&self, bytes: &mut [u8]) {
140 bytes.copy_from_slice(&self.0);
141 }
142}
143
144impl HashFunction<Sha256Domain> for Sha256Function {
145 fn hash(data: &[u8]) -> Sha256Domain {
146 let hashed = Sha256::digest(data);
147 let mut res = Sha256Domain::default();
148 res.0.copy_from_slice(&hashed[..]);
149 res.trim_to_fr32();
150 res
151 }
152
153 fn hash2(a: &Sha256Domain, b: &Sha256Domain) -> Sha256Domain {
154 let hashed = Sha256::new().chain_update(a).chain_update(b).finalize();
155 let mut res = Sha256Domain::default();
156 res.0.copy_from_slice(&hashed[..]);
157 res.trim_to_fr32();
158 res
159 }
160
161 fn hash_multi_leaf_circuit<Arity, CS: ConstraintSystem<Fr>>(
162 mut cs: CS,
163 leaves: &[AllocatedNum<Fr>],
164 _height: usize,
165 ) -> Result<AllocatedNum<Fr>, SynthesisError> {
166 let mut bits = Vec::with_capacity(leaves.len() * Fr::CAPACITY as usize);
167 for (i, leaf) in leaves.iter().enumerate() {
168 let mut padded = leaf.to_bits_le(cs.namespace(|| format!("{}_num_into_bits", i)))?;
169 while padded.len() % 8 != 0 {
170 padded.push(Boolean::Constant(false));
171 }
172
173 bits.extend(
174 padded
175 .chunks_exact(8)
176 .flat_map(|chunk| chunk.iter().rev())
177 .cloned(),
178 );
179 }
180 Self::hash_circuit(cs, &bits)
181 }
182
183 fn hash_leaf_bits_circuit<CS: ConstraintSystem<Fr>>(
184 cs: CS,
185 left: &[Boolean],
186 right: &[Boolean],
187 _height: usize,
188 ) -> Result<AllocatedNum<Fr>, SynthesisError> {
189 let mut preimage: Vec<Boolean> = vec![];
190
191 let mut left_padded = left.to_vec();
192 while !left_padded.len().is_multiple_of(8) {
193 left_padded.push(Boolean::Constant(false));
194 }
195
196 preimage.extend(
197 left_padded
198 .chunks_exact(8)
199 .flat_map(|chunk| chunk.iter().rev())
200 .cloned(),
201 );
202
203 let mut right_padded = right.to_vec();
204 while !right_padded.len().is_multiple_of(8) {
205 right_padded.push(Boolean::Constant(false));
206 }
207
208 preimage.extend(
209 right_padded
210 .chunks_exact(8)
211 .flat_map(|chunk| chunk.iter().rev())
212 .cloned(),
213 );
214
215 Self::hash_circuit(cs, &preimage[..])
216 }
217
218 fn hash_circuit<CS: ConstraintSystem<Fr>>(
219 mut cs: CS,
220 bits: &[Boolean],
221 ) -> Result<AllocatedNum<Fr>, SynthesisError> {
222 let be_bits = sha256_circuit(cs.namespace(|| "hash"), bits)?;
223 let le_bits = be_bits
224 .chunks(8)
225 .flat_map(|chunk| chunk.iter().rev())
226 .take(Fr::CAPACITY as usize)
227 .cloned()
228 .collect::<Vec<_>>();
229 multipack::pack_bits(cs.namespace(|| "pack_le"), &le_bits)
230 }
231
232 fn hash2_circuit<CS>(
233 mut cs: CS,
234 a_num: &AllocatedNum<Fr>,
235 b_num: &AllocatedNum<Fr>,
236 ) -> Result<AllocatedNum<Fr>, SynthesisError>
237 where
238 CS: ConstraintSystem<Fr>,
239 {
240 let a = a_num.to_bits_le(cs.namespace(|| "a_bits"))?;
242 let b = b_num.to_bits_le(cs.namespace(|| "b_bits"))?;
243
244 let mut preimage: Vec<Boolean> = vec![];
245
246 let mut a_padded = a.to_vec();
247 while a_padded.len() % 8 != 0 {
248 a_padded.push(Boolean::Constant(false));
249 }
250
251 preimage.extend(
252 a_padded
253 .chunks_exact(8)
254 .flat_map(|chunk| chunk.iter().rev())
255 .cloned(),
256 );
257
258 let mut b_padded = b.to_vec();
259 while b_padded.len() % 8 != 0 {
260 b_padded.push(Boolean::Constant(false));
261 }
262
263 preimage.extend(
264 b_padded
265 .chunks_exact(8)
266 .flat_map(|chunk| chunk.iter().rev())
267 .cloned(),
268 );
269
270 Self::hash_circuit(cs, &preimage[..])
271 }
272}
273
274impl Algorithm<Sha256Domain> for Sha256Function {
275 #[inline]
276 fn hash(&mut self) -> Sha256Domain {
277 let mut h = [0u8; 32];
278 h.copy_from_slice(self.0.clone().finalize().as_ref());
279 let mut dd = Sha256Domain::from(h);
280 dd.trim_to_fr32();
281 dd
282 }
283
284 #[inline]
285 fn reset(&mut self) {
286 self.0.reset();
287 }
288
289 fn leaf(&mut self, leaf: Sha256Domain) -> Sha256Domain {
290 leaf
291 }
292
293 fn node(&mut self, left: Sha256Domain, right: Sha256Domain, _height: usize) -> Sha256Domain {
294 left.hash(self);
295 right.hash(self);
296 self.hash()
297 }
298
299 fn multi_node(&mut self, parts: &[Sha256Domain], _height: usize) -> Sha256Domain {
300 for part in parts {
301 part.hash(self)
302 }
303 self.hash()
304 }
305}
306
307impl From<[u8; 32]> for Sha256Domain {
308 #[inline]
309 fn from(val: [u8; 32]) -> Self {
310 Sha256Domain(val)
311 }
312}
313
314impl From<Sha256Domain> for [u8; 32] {
315 #[inline]
316 fn from(val: Sha256Domain) -> Self {
317 val.0
318 }
319}