commit_uncompressed.rs
1 // Copyright (c) 2019-2025 Alpha-Delta Network Inc. 2 // This file is part of the alphavm 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> CommitUncompressed 19 for BHP<E, NUM_WINDOWS, WINDOW_SIZE> 20 { 21 type Input = Boolean<E>; 22 type Output = Group<E>; 23 type Randomizer = Scalar<E>; 24 25 /// Returns the BHP commitment of the given input and randomizer as an affine group element. 26 fn commit_uncompressed(&self, input: &[Self::Input], randomizer: &Self::Randomizer) -> Self::Output { 27 let hash = self.hash_uncompressed(input); 28 29 // Compute h^r. 30 randomizer 31 .to_bits_le() 32 .iter() 33 .zip_eq(self.hasher.random_base()) 34 .map(|(bit, power)| Group::ternary(bit, power, &Group::zero())) 35 .fold(hash, |acc, x| acc + x) 36 } 37 } 38 39 #[cfg(test)] 40 mod tests { 41 use super::*; 42 use alphavm_circuit_types::environment::Circuit; 43 use alphavm_curves::{AffineCurve, ProjectiveCurve}; 44 use alphavm_utilities::{TestRng, Uniform}; 45 46 use anyhow::Result; 47 48 const ITERATIONS: u64 = 100; 49 const DOMAIN: &str = "BHPCircuit0"; 50 51 fn check_commit_uncompressed<const NUM_WINDOWS: u8, const WINDOW_SIZE: u8>( 52 mode: Mode, 53 num_constants: u64, 54 num_public: u64, 55 num_private: u64, 56 num_constraints: u64, 57 ) -> Result<()> { 58 use console::CommitUncompressed as C; 59 60 // Initialize BHP. 61 let native = console::BHP::<<Circuit as Environment>::Network, NUM_WINDOWS, WINDOW_SIZE>::setup(DOMAIN)?; 62 let circuit = BHP::<Circuit, NUM_WINDOWS, WINDOW_SIZE>::new(Mode::Constant, native.clone()); 63 // Determine the number of inputs. 64 let num_input_bits = NUM_WINDOWS as usize * WINDOW_SIZE as usize * BHP_CHUNK_SIZE; 65 66 let mut rng = TestRng::default(); 67 68 for i in 0..ITERATIONS { 69 // Sample a random input. 70 let input = (0..num_input_bits).map(|_| bool::rand(&mut rng)).collect::<Vec<bool>>(); 71 // Sample a randomizer. 72 let randomizer = Uniform::rand(&mut rng); 73 // Compute the expected commitment. 74 let expected = native.commit_uncompressed(&input, &randomizer).expect("Failed to commit native input"); 75 // Prepare the circuit input. 76 let circuit_input: Vec<Boolean<_>> = Inject::new(mode, input); 77 // Prepare the circuit randomizer. 78 let circuit_randomizer: Scalar<_> = Inject::new(mode, randomizer); 79 80 Circuit::scope(format!("BHP {mode} {i}"), || { 81 // Perform the hash operation. 82 let candidate = circuit.commit_uncompressed(&circuit_input, &circuit_randomizer); 83 assert_scope!(<=num_constants, num_public, num_private, num_constraints); 84 assert_eq!(expected, candidate.eject_value()); 85 assert!(candidate.eject_value().to_affine().is_on_curve()); 86 assert!(candidate.eject_value().to_affine().is_in_correct_subgroup_assuming_on_curve()); 87 }); 88 Circuit::reset(); 89 } 90 Ok(()) 91 } 92 93 #[test] 94 fn test_commit_uncompressed_constant() -> Result<()> { 95 check_commit_uncompressed::<32, 48>(Mode::Constant, 8200, 0, 0, 0) 96 } 97 98 #[test] 99 fn test_commit_uncompressed_public() -> Result<()> { 100 check_commit_uncompressed::<32, 48>(Mode::Public, 1044, 0, 10781, 10785) 101 } 102 103 #[test] 104 fn test_commit_uncompressed_private() -> Result<()> { 105 check_commit_uncompressed::<32, 48>(Mode::Private, 1044, 0, 10781, 10785) 106 } 107 }