openzeppelin_crypto/pedersen/instance/
starknet.rs

1//! This module contains the Pedersen Hash function parameters for
2//! [Starknet instance].
3//!
4//! [Starknet instance]: <https://docs.starkware.co/starkex/crypto/pedersen-hash-function.html>
5
6use crate::{
7    arithmetic::uint::U256,
8    curve::sw::{instance::starknet::StarknetCurveConfig, Affine},
9    fp_from_num, from_hex,
10    pedersen::params::PedersenParams,
11};
12
13#[derive(Clone, Default, PartialEq, Eq)]
14/// Pedersen Hash parameters for Starknet.
15pub struct StarknetPedersenParams;
16
17impl PedersenParams<StarknetCurveConfig> for StarknetPedersenParams {
18    type AffineRepr = Affine<StarknetCurveConfig>;
19
20    /// Low part bits.
21    const LOW_PART_BITS: u32 = 248;
22    /// Low part mask. (2**248 - 1)
23    const LOW_PART_MASK: U256 = from_hex!(
24        "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
25    );
26    const N_ELEMENT_BITS_HASH: usize = 252;
27    const P_0: Affine<StarknetCurveConfig> = Affine::new_unchecked(
28			fp_from_num!("2089986280348253421170679821480865132823066470938446095505822317253594081284"),
29			fp_from_num!("1713931329540660377023406109199410414810705867260802078187082345529207694986")
30		);
31    const P_1: Affine<StarknetCurveConfig> =
32		Affine::new_unchecked(
33            fp_from_num!("996781205833008774514500082376783249102396023663454813447423147977397232763"),
34            fp_from_num!("1668503676786377725805489344771023921079126552019160156920634619255970485781")
35        );
36    const P_2: Affine<StarknetCurveConfig> =
37        Affine::new_unchecked(
38            fp_from_num!("2251563274489750535117886426533222435294046428347329203627021249169616184184"),
39            fp_from_num!("1798716007562728905295480679789526322175868328062420237419143593021674992973")
40        );
41    const P_3: Affine<StarknetCurveConfig> =
42		Affine::new_unchecked(
43            fp_from_num!("2138414695194151160943305727036575959195309218611738193261179310511854807447"),
44            fp_from_num!("113410276730064486255102093846540133784865286929052426931474106396135072156")
45        );
46    const P_4:  Affine<StarknetCurveConfig> =
47		Affine::new_unchecked(
48            fp_from_num!("2379962749567351885752724891227938183011949129833673362440656643086021394946"),
49            fp_from_num!("776496453633298175483985398648758586525933812536653089401905292063708816422")
50        );
51}
52
53#[cfg(test)]
54mod tests {
55
56    use super::*;
57    use crate::{
58        curve::sw::instance::starknet::{Fq, StarknetCurveConfig},
59        fp_from_hex,
60        pedersen::Pedersen,
61    };
62
63    #[test]
64    fn correct_bits_hash_length() {
65        assert_eq!(StarknetPedersenParams::N_ELEMENT_BITS_HASH, 252);
66    }
67
68    #[test]
69    fn correct_shift_point() {
70        assert_eq!(StarknetPedersenParams::P_0, Affine::new_unchecked(
71            fp_from_num!("2089986280348253421170679821480865132823066470938446095505822317253594081284"),
72            fp_from_num!("1713931329540660377023406109199410414810705867260802078187082345529207694986")
73        ));
74    }
75
76    #[derive(Debug)]
77    struct StarknetTestCase {
78        x: Fq,
79        y: Fq,
80        expected: Option<Fq>,
81    }
82
83    #[test]
84    fn smoke() {
85        // Based on <https://github.com/starkware-libs/starkware-crypto-utils/blob/master/test/config/signature_test_data.json>.
86        let test_cases = vec![
87                StarknetTestCase {
88                    x: fp_from_hex!("3d937c035c878245caf64531a5756109c53068da139362728feb561405371cb"),
89                    y: fp_from_hex!("208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31a"),
90                    expected: Some(fp_from_hex!("30e480bed5fe53fa909cc0f8c4d99b8f9f2c016be4c41e13a4848797979c662"))
91                },
92                StarknetTestCase {
93                    x: fp_from_hex!("58f580910a6ca59b28927c08fe6c43e2e303ca384badc365795fc645d479d45"),
94                    y: fp_from_hex!("78734f65a067be9bdb39de18434d71e79f7b6466a4b66bbd979ab9e7515fe0b"),
95                    expected: Some(fp_from_hex!("68cc0b76cddd1dd4ed2301ada9b7c872b23875d5ff837b3a87993e0d9996b87")),
96                },
97            ];
98        for test_case in test_cases {
99            let pedersen =
100                Pedersen::<StarknetPedersenParams, StarknetCurveConfig>::new();
101
102            assert_eq!(
103                pedersen.hash(test_case.x, test_case.y),
104                test_case.expected,
105                "Failed for input x: {:?}, y: {:?}",
106                test_case.x,
107                test_case.y
108            );
109        }
110    }
111
112    #[test]
113    #[cfg(feature = "ruint")]
114    fn hash() {
115        // Check no panics.
116        proptest::proptest!(|(input1: alloy_primitives::U256, input2: alloy_primitives::U256)| {
117            let pedersen =
118                Pedersen::<StarknetPedersenParams, StarknetCurveConfig>::new();
119            let hash = pedersen.hash(U256::from(input1), U256::from(input2));
120            assert!(hash.is_some());
121        });
122    }
123}