From 8476f5086632514193a1a9c07b21f7da35630666 Mon Sep 17 00:00:00 2001 From: Pedro Fontana Date: Tue, 7 Nov 2023 15:02:25 -0300 Subject: [PATCH] Pedersen hash (#12) --- crates/starknet-types-core/Cargo.toml | 2 + crates/starknet-types-core/README.md | 28 ++++++-- crates/starknet-types-core/src/hash/mod.rs | 5 ++ .../starknet-types-core/src/hash/pedersen.rs | 65 +++++++++++++++++++ crates/starknet-types-core/src/hash/traits.rs | 10 +++ crates/starknet-types-core/src/lib.rs | 3 + 6 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 crates/starknet-types-core/src/hash/mod.rs create mode 100644 crates/starknet-types-core/src/hash/pedersen.rs create mode 100644 crates/starknet-types-core/src/hash/traits.rs diff --git a/crates/starknet-types-core/Cargo.toml b/crates/starknet-types-core/Cargo.toml index 2c6b64b..7b13548 100644 --- a/crates/starknet-types-core/Cargo.toml +++ b/crates/starknet-types-core/Cargo.toml @@ -14,6 +14,7 @@ readme = "README.md" bitvec = { version = "1.0.1", default-features = false } serde = { version = "1.0.163", optional = true, default-features = false } lambdaworks-math = { git = "https://github.com/lambdaclass/lambdaworks.git", rev = "f940e14ed17370d29fe129951448037d11b65ce8", default-features = false} +lambdaworks-crypto = { git = "https://github.com/lambdaclass/lambdaworks.git", rev = "f940e14ed17370d29fe129951448037d11b65ce8", default-features = false, optional = true} arbitrary = { version = "1.3.0", optional = true, default-features = false } @@ -22,6 +23,7 @@ num-traits = { version = "0.2.16", default-features = false } [features] default = ["std", "serde", "curve"] curve = [] +hash = ["dep:lambdaworks-crypto"] std = [] alloc = ["serde?/alloc"] arbitrary = ["std", "dep:arbitrary"] diff --git a/crates/starknet-types-core/README.md b/crates/starknet-types-core/README.md index 6ead45f..b29b2f0 100644 --- a/crates/starknet-types-core/README.md +++ b/crates/starknet-types-core/README.md @@ -6,12 +6,26 @@ Core types representation for Starknet. The `starknet-types-core` crate provides: * The universal `Felt` (Field Element) type for Cairo and STARK proofs. It was created to reduce the fragmentation in the Starknet Rust ecosystem by providing a standardized representation of the `Felt` type. -* The `AffinePoint` and `ProjectivePoint` structs, which represent points on the Stark curve for performing elliptic curve operations. ## Features -- Standardized `Felt` type: Simplify your codebase by using our standardized `Felt` type. -- Optimized for performance: The `Felt` type has been optimized for high-performance applications. +### Always on +- Standardized `Felt` type: Simplify your codebase by using our standardized `Felt` type. Optimized for performance: The `Felt` type has been optimized for high-performance applications. +- No_std support ✅ + +### Serde +- Provides a Serialization and Deserialization implementations for the `Felt` type +- No_std support ✅ + +### Arbitrary +- Provides an Arbitrary implementations for the `Felt` type + +### Curve +- Add the `AffinePoint` and `ProjectivePoint` structs, which represent points on the Stark curve for performing elliptic curve operations. +- No_std support ✅ + +### Hash +- Implements Pedersen hashing for Felts and Felts array ## Examples @@ -29,7 +43,13 @@ Include `starknet-types-core` in your library by adding the following to your `C ```toml [dependencies] -starknet-types-core = { version = "0.0.3", git = "https://github.com/starknet-io/types-rs" } +starknet-types-core = { version = "0.0.3", git = "https://github.com/starknet-io/types-rs", default-features = false, features = [ + "alloc", + "serde", + "arbitrary", + "curve", + "hash", +] } ``` ## Build from source diff --git a/crates/starknet-types-core/src/hash/mod.rs b/crates/starknet-types-core/src/hash/mod.rs new file mode 100644 index 0000000..ed33d07 --- /dev/null +++ b/crates/starknet-types-core/src/hash/mod.rs @@ -0,0 +1,5 @@ +mod pedersen; +mod traits; + +pub use self::pedersen::*; +pub use self::traits::*; diff --git a/crates/starknet-types-core/src/hash/pedersen.rs b/crates/starknet-types-core/src/hash/pedersen.rs new file mode 100644 index 0000000..940ddd0 --- /dev/null +++ b/crates/starknet-types-core/src/hash/pedersen.rs @@ -0,0 +1,65 @@ +use crate::felt::Felt; +use lambdaworks_crypto::hash::pedersen::Pedersen as PedersenLambdaworks; +use lambdaworks_math::field::{ + element::FieldElement, fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, +}; + +use super::traits::StarkHash; + +pub struct Pedersen; + +impl StarkHash for Pedersen { + /// Computes the Pedersen hash of two Felts, as defined + /// in + fn hash(felt_0: &Felt, felt_1: &Felt) -> Felt { + let pedersen = PedersenLambdaworks::default(); + + let hash = pedersen.hash(&felt_0.0, &felt_1.0); + + Felt(hash) + } + + /// Computes the Pedersen hash of an array of Felts, as defined + /// in + fn hash_array(felts: &[Felt]) -> Felt { + let pedersen = PedersenLambdaworks::default(); + let data_len = Felt::from(felts.len()); + let current_hash: FieldElement = felts.iter().fold( + FieldElement::::zero(), + |current_hash, felt| pedersen.hash(¤t_hash, &felt.0), + ); + Felt(pedersen.hash(¤t_hash, &data_len.0)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_pedersen_hash() { + let x = + Felt::from_hex("0x03d937c035c878245caf64531a5756109c53068da139362728feb561405371cb") + .unwrap(); + let y = + Felt::from_hex("0x0208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31a") + .unwrap(); + + assert_eq!( + Pedersen::hash(&x, &y), + Felt::from_hex("0x030e480bed5fe53fa909cc0f8c4d99b8f9f2c016be4c41e13a4848797979c662") + .unwrap() + ); + } + + #[test] + fn test_pedersen_hash_array() { + let a = Felt::from_hex("0xaa").unwrap(); + let b = Felt::from_hex("0xbb").unwrap(); + let c = Felt::from_hex("0xcc").unwrap(); + let expected = + Felt::from_hex("0x10808e8929644950878c4f71326e47c6b584d9cfea2de0415daf8def0f5e89f") + .unwrap(); + assert_eq!(Pedersen::hash_array(&[a, b, c]), expected); + } +} diff --git a/crates/starknet-types-core/src/hash/traits.rs b/crates/starknet-types-core/src/hash/traits.rs new file mode 100644 index 0000000..72036ab --- /dev/null +++ b/crates/starknet-types-core/src/hash/traits.rs @@ -0,0 +1,10 @@ +use crate::felt::Felt; + +pub trait StarkHash { + /// Computes the hash of two Felt + fn hash(felt_0: &Felt, felt_1: &Felt) -> Felt; + + /// Computes the hash of an array of Felts, + /// as defined in + fn hash_array(felts: &[Felt]) -> Felt; +} diff --git a/crates/starknet-types-core/src/lib.rs b/crates/starknet-types-core/src/lib.rs index 18855ad..45bd805 100644 --- a/crates/starknet-types-core/src/lib.rs +++ b/crates/starknet-types-core/src/lib.rs @@ -1,6 +1,9 @@ #![cfg_attr(not(feature = "std"), no_std)] #[cfg(feature = "curve")] pub mod curve; +#[cfg(feature = "hash")] +pub mod hash; + pub mod felt; #[cfg(test)] mod felt_arbitrary;