Skip to content

Commit

Permalink
v0.4.7 - Stark Pedersen Rework
Browse files Browse the repository at this point in the history
  • Loading branch information
beeinger committed Sep 11, 2024
1 parent df118be commit 195cdac
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 36 deletions.
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "accumulators"
version = "0.4.6"
version = "0.4.7"
edition = "2021"
license-file = "LICENSE"
description = "Complete package of multiple Accumulators with Stores and hashing functions (Hashers)"
Expand All @@ -24,7 +24,6 @@ hex = "0.4.3" # Hex encoding
tiny-keccak = "2.0.2" # Keccak hashing
starknet = "0.6.0" # StarkNet pedersen
starknet-crypto = "0.6.0" # StarkNet poseidon
primitive-types = "0.10" # U256 primitive type in pedersen
uuid = { version = "1.4.1", features = ["v4"] } # UUID
parking_lot = "0.12.1" # Sync mutex
num-bigint = "0.4.4" # Bigints in hashers (TODO: double check if needed)
Expand Down
5 changes: 3 additions & 2 deletions src/hasher/core.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use starknet::core::types::FromStrError;
use std::{fmt::Debug, str::FromStr};
use strum_macros::EnumIter;
use thiserror::Error;
Expand All @@ -16,10 +17,10 @@ pub enum HasherError {
},
#[error("Invalid elements length for hashing function")]
InvalidElementsLength,
#[error("Fail to convert to U256")]
U256ConversionError,
#[error("Fail to decode hex")]
HexDecodeError(#[from] hex::FromHexError),
#[error("Fail to convert to felt")]
FeltConversionError(#[from] FromStrError),
}

/// A trait for hash functions
Expand Down
105 changes: 73 additions & 32 deletions src/hasher/hashers/stark_pedersen.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use primitive_types::U256;
use starknet::core::{crypto::pedersen_hash, types::FieldElement};

use crate::hasher::{byte_size, HasherError, HashingFunction};
Expand All @@ -17,43 +16,18 @@ impl Hasher for StarkPedersenHasher {
HashingFunction::Pedersen
}

/// Hashes a data which is a vector of strings
///
/// NOTE: data should be of size 2
fn hash(&self, data: Vec<String>) -> Result<String, HasherError> {
if data.len() != 2 {
if data.len() < 2 {
return Err(HasherError::InvalidElementsLength);
}

for element in &data {
self.is_element_size_valid(element)?;
let mut elements = data.into_iter();
let mut hash = elements.next().unwrap();
for element in elements {
hash = self.internal_hash(vec![hash, element])?;
}

let mut clean_data = Vec::with_capacity(data.len());
for s in data.iter() {
let number_str = if let Some(stripped) = s.strip_prefix("0x") {
U256::from_str_radix(stripped, 16)
} else {
U256::from_str_radix(s, 16)
};

match number_str {
Ok(number) => clean_data.push(number.to_string()),
Err(_) => return Err(HasherError::U256ConversionError),
}
}

let result = pedersen_hash(
&FieldElement::from_dec_str(&clean_data[0]).unwrap_or_default(),
&FieldElement::from_dec_str(&clean_data[1]).unwrap_or_default(),
)
.to_string();

let computed_result =
U256::from_dec_str(result.trim()).map_err(|_| HasherError::U256ConversionError)?;
let padded_hex_str = format!("0x{:064x}", computed_result);

Ok(padded_hex_str)
Ok(hash)
}

fn is_element_size_valid(&self, element: &str) -> Result<bool, HasherError> {
Expand Down Expand Up @@ -83,6 +57,28 @@ impl Hasher for StarkPedersenHasher {
}

impl StarkPedersenHasher {
/// Hashes a data which is a vector of hex strings
///
/// NOTE: data should be of size 2
fn internal_hash(&self, data: Vec<String>) -> Result<String, HasherError> {
if data.len() != 2 {
return Err(HasherError::InvalidElementsLength);
}

for element in &data {
self.is_element_size_valid(element)?;
}

let result = pedersen_hash(
&FieldElement::from_hex_be(&data[0])?,
&FieldElement::from_hex_be(&data[1])?,
)
.to_bytes_be();

let padded_hex_str = format!("0x{:0>64}", hex::encode(result));
Ok(padded_hex_str)
}

pub fn new() -> Self {
Self {
block_size_bits: 252,
Expand All @@ -95,3 +91,48 @@ impl Default for StarkPedersenHasher {
Self::new()
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_stark_pedersen_hasher_cairo_playground_reference_1() {
let hasher = StarkPedersenHasher::new();
let data = vec![
// 314
"0x13a".to_string(),
// 159
"0x9f".to_string(),
];
let hash = hasher.hash(data).unwrap();
assert_eq!(
hash,
// 307958720726328212653290369969069617958360335228383070119367204176047090109
"0x00ae4c67cf8deb4f68f6bad0ce61be81097cf082b4bfa83c637af99a978fa9bd",
"Hashes do not match"
);
}

#[test]
fn test_stark_pedersen_hasher_cairo_playground_reference_2() {
let hasher = StarkPedersenHasher::new();
let data = vec![
// 314
"0x13a".to_string(),
// 159
"0x9f".to_string(),
// 265
"0x109".to_string(),
// 358
"0x166".to_string(),
];
let hash = hasher.hash(data).unwrap();
assert_eq!(
hash,
// 1828757374677754028678056220799392919487521050857166686061558043629802016816
"0x040b0a3d05cf798d507d2b4b2725bb28b00d16c0ceefa2222aa04cc88518d030",
"Hashes do not match"
);
}
}

0 comments on commit 195cdac

Please sign in to comment.