use super::*;
impl<E: Environment, const NUM_BITS: u8> Hash for Pedersen<E, NUM_BITS> {
type Input = Boolean<E>;
type Output = Field<E>;
fn hash(&self, input: &[Self::Input]) -> Self::Output {
self.hash_uncompressed(input).to_x_coordinate()
}
}
impl<E: Environment, const NUM_BITS: u8> Metrics<dyn Hash<Input = Boolean<E>, Output = Field<E>>>
for Pedersen<E, NUM_BITS>
{
type Case = Vec<Mode>;
#[inline]
fn count(case: &Self::Case) -> Count {
count!(Pedersen<E, NUM_BITS>, HashUncompressed<Input = Boolean<E>, Output = Group<E>>, case)
}
}
impl<E: Environment, const NUM_BITS: u8> OutputMode<dyn Hash<Input = Boolean<E>, Output = Field<E>>>
for Pedersen<E, NUM_BITS>
{
type Case = Vec<Mode>;
#[inline]
fn output_mode(parameter: &Self::Case) -> Mode {
output_mode!(Pedersen<E, NUM_BITS>, HashUncompressed<Input = Boolean<E>, Output = Group<E>>, parameter)
}
}
#[cfg(all(test, console))]
mod tests {
use super::*;
use snarkvm_circuit_types::environment::Circuit;
use snarkvm_utilities::{TestRng, Uniform};
const ITERATIONS: u64 = 10;
const MESSAGE: &str = "PedersenCircuit0";
const NUM_BITS_MULTIPLIER: u8 = 8;
fn check_hash<const NUM_BITS: u8>(mode: Mode, rng: &mut TestRng) {
use console::Hash as H;
let native = console::Pedersen::<<Circuit as Environment>::Network, NUM_BITS>::setup(MESSAGE);
let circuit = Pedersen::<Circuit, NUM_BITS>::constant(native.clone());
for i in 0..ITERATIONS {
let input = (0..NUM_BITS).map(|_| bool::rand(rng)).collect::<Vec<bool>>();
let expected = native.hash(&input).expect("Failed to hash native input");
let circuit_input: Vec<Boolean<_>> = Inject::new(mode, input);
Circuit::scope(format!("Pedersen {mode} {i}"), || {
let candidate = circuit.hash(&circuit_input);
assert_eq!(expected, candidate.eject_value());
let modes = circuit_input.iter().map(|b| b.eject_mode()).collect::<Vec<_>>();
assert_count!(
Pedersen<Circuit, NUM_BITS>,
HashUncompressed<Input = Boolean<Circuit>, Output = Group<Circuit>>,
&modes
);
assert_output_mode!(
Pedersen<Circuit, NUM_BITS>,
HashUncompressed<Input = Boolean<Circuit>, Output = Group<Circuit>>,
&modes,
candidate
);
});
}
}
#[test]
fn test_hash_constant() {
let mut rng = TestRng::default();
check_hash::<NUM_BITS_MULTIPLIER>(Mode::Constant, &mut rng);
check_hash::<{ 2 * NUM_BITS_MULTIPLIER }>(Mode::Constant, &mut rng);
check_hash::<{ 3 * NUM_BITS_MULTIPLIER }>(Mode::Constant, &mut rng);
check_hash::<{ 4 * NUM_BITS_MULTIPLIER }>(Mode::Constant, &mut rng);
check_hash::<{ 5 * NUM_BITS_MULTIPLIER }>(Mode::Constant, &mut rng);
}
#[test]
fn test_hash_public() {
let mut rng = TestRng::default();
check_hash::<NUM_BITS_MULTIPLIER>(Mode::Public, &mut rng);
check_hash::<{ 2 * NUM_BITS_MULTIPLIER }>(Mode::Public, &mut rng);
check_hash::<{ 3 * NUM_BITS_MULTIPLIER }>(Mode::Public, &mut rng);
check_hash::<{ 4 * NUM_BITS_MULTIPLIER }>(Mode::Public, &mut rng);
check_hash::<{ 5 * NUM_BITS_MULTIPLIER }>(Mode::Public, &mut rng);
}
#[test]
fn test_hash_private() {
let mut rng = TestRng::default();
check_hash::<NUM_BITS_MULTIPLIER>(Mode::Private, &mut rng);
check_hash::<{ 2 * NUM_BITS_MULTIPLIER }>(Mode::Private, &mut rng);
check_hash::<{ 3 * NUM_BITS_MULTIPLIER }>(Mode::Private, &mut rng);
check_hash::<{ 4 * NUM_BITS_MULTIPLIER }>(Mode::Private, &mut rng);
check_hash::<{ 5 * NUM_BITS_MULTIPLIER }>(Mode::Private, &mut rng);
}
}