hash_uncompressed.rs
1 // Copyright (c) 2019-2025 Alpha-Delta Network Inc. 2 // This file is part of the deltavm library. 3 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at: 7 8 // http://www.apache.org/licenses/LICENSE-2.0 9 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 use super::*; 17 18 impl<E: Environment, const NUM_WINDOWS: u8, const WINDOW_SIZE: u8> HashUncompressed 19 for BHP<E, NUM_WINDOWS, WINDOW_SIZE> 20 { 21 type Input = bool; 22 type Output = Group<E>; 23 24 /// Returns the BHP hash of the given input as an affine group element. 25 /// 26 /// This uncompressed variant of the BHP hash function is provided to support 27 /// the BHP commitment scheme, as it is typically not used by applications. 28 fn hash_uncompressed(&self, input: &[Self::Input]) -> Result<Self::Output> { 29 // The number of hasher bits to fit. 30 let num_hasher_bits = NUM_WINDOWS as usize * WINDOW_SIZE as usize * BHP_CHUNK_SIZE; 31 // The number of data bits in the output. 32 let num_data_bits = Field::<E>::size_in_data_bits(); 33 // The maximum number of input bits per iteration. 34 let max_input_bits_per_iteration = num_hasher_bits - num_data_bits; 35 36 debug_assert!(num_data_bits < num_hasher_bits); 37 debug_assert_eq!(num_data_bits - 64, self.domain.len()); 38 39 // Initialize a variable to store the hash from the current iteration. 40 let mut digest = Group::<E>::zero(); 41 42 // Prepare a reusable vector for the preimage. 43 let mut preimage = Vec::with_capacity(num_hasher_bits); 44 45 // Compute the hash of the input. 46 for (i, input_bits) in input.chunks(max_input_bits_per_iteration).enumerate() { 47 // Determine if this is the first iteration. 48 match i == 0 { 49 // Construct the first iteration as: [ 0...0 || DOMAIN || LENGTH(INPUT) || INPUT[0..BLOCK_SIZE] ]. 50 true => { 51 // Initialize a vector for the hash preimage. 52 preimage.extend(&self.domain); 53 (input.len() as u64).write_bits_le(&mut preimage); 54 preimage.extend(input_bits); 55 } 56 // Construct the subsequent iterations as: [ PREVIOUS_HASH[0..DATA_BITS] || INPUT[I * BLOCK_SIZE..(I + 1) * BLOCK_SIZE] ]. 57 false => { 58 // Initialize a vector for the hash preimage. 59 digest.to_x_coordinate().write_bits_le(&mut preimage); 60 preimage.truncate(num_data_bits); 61 preimage.extend(input_bits); 62 } 63 } 64 // Hash the preimage for this iteration. 65 digest = self.hasher.hash_uncompressed(&preimage)?; 66 preimage.clear(); 67 } 68 69 Ok(digest) 70 } 71 } 72 73 #[cfg(test)] 74 mod tests { 75 use super::*; 76 use deltavm_console_types::environment::Console; 77 78 type CurrentEnvironment = Console; 79 80 const ITERATIONS: u64 = 1000; 81 82 #[test] 83 fn test_bhp256_input_size() -> Result<()> { 84 let bhp = BHP256::<CurrentEnvironment>::setup("BHPTest")?; 85 86 let mut rng = TestRng::default(); 87 88 for i in 0..ITERATIONS { 89 let input = (0..bhp.window_size() as u64 + i).map(|_| bool::rand(&mut rng)).collect::<Vec<_>>(); 90 bhp.hash_uncompressed(&input)?; 91 } 92 Ok(()) 93 } 94 95 #[test] 96 fn test_bhp512_input_size() -> Result<()> { 97 let bhp = BHP512::<CurrentEnvironment>::setup("BHPTest")?; 98 99 let mut rng = TestRng::default(); 100 101 for i in 0..ITERATIONS { 102 let input = (0..bhp.window_size() as u64 + i).map(|_| bool::rand(&mut rng)).collect::<Vec<_>>(); 103 bhp.hash_uncompressed(&input)?; 104 } 105 Ok(()) 106 } 107 108 #[test] 109 fn test_bhp768_input_size() -> Result<()> { 110 let bhp = BHP768::<CurrentEnvironment>::setup("BHPTest")?; 111 112 let mut rng = TestRng::default(); 113 114 for i in 0..ITERATIONS { 115 let input = (0..bhp.window_size() as u64 + i).map(|_| bool::rand(&mut rng)).collect::<Vec<_>>(); 116 bhp.hash_uncompressed(&input)?; 117 } 118 Ok(()) 119 } 120 121 #[test] 122 fn test_bhp1024_input_size() -> Result<()> { 123 let bhp = BHP1024::<CurrentEnvironment>::setup("BHPTest")?; 124 125 let mut rng = TestRng::default(); 126 127 for i in 0..ITERATIONS { 128 let input = (0..bhp.window_size() as u64 + i).map(|_| bool::rand(&mut rng)).collect::<Vec<_>>(); 129 bhp.hash_uncompressed(&input)?; 130 } 131 Ok(()) 132 } 133 }