Skip to content

Commit

Permalink
rusk-abi: Generate the BlsScalar hash without truncation
Browse files Browse the repository at this point in the history
  • Loading branch information
moCello committed Jul 9, 2024
1 parent 2133332 commit 5e18126
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 29 deletions.
53 changes: 29 additions & 24 deletions rusk-abi/src/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
// Copyright (c) DUSK NETWORK. All rights reserved.

use blake2b_simd::{Params, State};
use dusk_bytes::Serializable;
use execution_core::BlsScalar;

/// Hashes scalars and arbitrary slices of bytes using Blake2b-256, returning
/// a valid [`BlsScalar`].
/// Hashes scalars and arbitrary slices of bytes using Blake2b, returning a
/// valid [`BlsScalar`]. Using the `Hasher` yields the same result as when using
/// `BlsScalar::hash_to_scalar`.
///
/// The hashing cannot be proved inside a circuit, if that is desired, use
/// This hash cannot be proven inside a circuit, if that is desired, use
/// `poseidon_hash` instead.
pub struct Hasher {
state: State,
Expand All @@ -20,7 +20,7 @@ pub struct Hasher {
impl Default for Hasher {
fn default() -> Self {
Hasher {
state: Params::new().hash_length(BlsScalar::SIZE).to_state(),
state: Params::new().hash_length(64).to_state(),
}
}
}
Expand All @@ -43,32 +43,37 @@ impl Hasher {
hasher
}

/// Get the output of the hasher.
pub fn output(self) -> [u8; BlsScalar::SIZE] {
let hasher = self;
let mut buf = [0u8; BlsScalar::SIZE];
buf.copy_from_slice(hasher.state.finalize().as_ref());

// This is a workaround for the fact that `Blake2b` does not support
// bitlengths that are not a multiple of 8.
// We're going to zero out the last nibble of the hash to ensure
// that the result can fit in a `BlsScalar`.
buf[BlsScalar::SIZE - 1] &= 0xf;

buf
}

/// Retrieve result and consume hasher instance.
pub fn finalize(self) -> BlsScalar {
BlsScalar::from_bytes(&self.output()).expect(
"Conversion to BlsScalar should never fail after truncation",
)
BlsScalar::from_bytes_wide(self.state.finalize().as_array())
}

/// Compute hash of arbitrary data into a valid [`BlsScalar`].
/// Compute hash of arbitrary data into a valid [`BlsScalar`]. This
/// equivalent to using `BlsScalar::hash_to_scalar`.
pub fn digest(data: impl AsRef<[u8]>) -> BlsScalar {
let mut hasher = Hasher::new();
hasher.update(data.as_ref());
hasher.finalize()
}
}

#[cfg(test)]
mod tests {
use super::*;
use rand_core::{OsRng, RngCore};

#[test]
fn test_hash() {
let mut input = [0u8; 100000];
OsRng.fill_bytes(&mut input[..]);

let mut hasher = Hasher::new();
for input_chunk in input.chunks(100) {
hasher.update(input_chunk);
}
let hash = hasher.finalize();

assert_eq!(hash, BlsScalar::hash_to_scalar(&input));
assert_eq!(hash, Hasher::digest(&input));
}
}
4 changes: 1 addition & 3 deletions rusk-abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,7 @@ const fn reserved(b: u8) -> ContractId {
/// Generate a [`ContractId`] address from the given slice of bytes, that is
/// also a valid [`BlsScalar`]
pub fn gen_contract_id(bytes: &[u8]) -> ContractId {
let mut hasher = Hasher::new();
hasher.update(bytes);
ContractId::from_bytes(hasher.output())
ContractId::from_bytes(Hasher::digest(bytes).into())
}

/// Converts a `ContractId` to a `BlsScalar`
Expand Down
4 changes: 2 additions & 2 deletions rusk-abi/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ fn hash_host() {
}

assert_eq!(
"0x0e17c56704c3ec2523d206e2e06e08b336e0079bb4c4c5b850d496125f73cdb9",
"0x58c751eca2d6a41227e0c52ef579f4688d698b3447a8bcc27fb2831e11d3239e",
format!("{:?}", Hasher::digest(input))
);
}
Expand Down Expand Up @@ -99,7 +99,7 @@ fn hash() {
.data;

assert_eq!(
"0x0e17c56704c3ec2523d206e2e06e08b336e0079bb4c4c5b850d496125f73cdb9",
"0x58c751eca2d6a41227e0c52ef579f4688d698b3447a8bcc27fb2831e11d3239e",
format!("{scalar:?}")
);
}
Expand Down

0 comments on commit 5e18126

Please sign in to comment.