1
1
use lambdaworks_math:: {
2
- elliptic_curve:: short_weierstrass:: {
3
- curves:: stark_curve:: StarkCurve , point:: ShortWeierstrassProjectivePoint ,
4
- } ,
2
+ elliptic_curve:: short_weierstrass:: point:: ShortWeierstrassProjectivePoint as Point ,
5
3
field:: {
6
- element:: FieldElement , fields:: fft_friendly:: stark_252_prime_field:: Stark252PrimeField ,
4
+ element:: FieldElement as FE ,
5
+ fields:: fft_friendly:: stark_252_prime_field:: Stark252PrimeField ,
7
6
} ,
8
7
} ;
9
8
10
9
mod constants;
11
10
mod parameters;
12
- use self :: parameters:: PedersenParameters ;
11
+ use parameters:: PedersenParameters ;
12
+ pub use parameters:: PedersenStarkCurve ;
13
13
14
- pub struct Pedersen {
15
- params : PedersenParameters ,
16
- }
14
+ mod private {
15
+ use super :: * ;
17
16
18
- impl Default for Pedersen {
19
- fn default ( ) -> Self {
20
- let pedersen_stark_default_params = PedersenParameters :: default ( ) ;
21
- Self :: new_with_params ( pedersen_stark_default_params)
22
- }
23
- }
17
+ pub trait Sealed { }
24
18
25
- impl Pedersen {
26
- pub fn new_with_params ( params : PedersenParameters ) -> Self {
27
- Self { params }
28
- }
29
-
30
- // Taken from Jonathan Lei's starknet-rs
31
- // https://github.com/xJonathanLEI/starknet-rs/blob/4ab2f36872435ce57b1d8f55856702a6a30f270a/starknet-crypto/src/pedersen_hash.rs
19
+ impl < P : PedersenParameters > Sealed for P { }
20
+ }
32
21
22
+ pub trait Pedersen : PedersenParameters + self :: private:: Sealed {
33
23
/// Implements Starkware version of Pedersen hash of x and y.
34
24
/// Divides each of x and y into 4-bit chunks, and uses lookup tables to accumulate pre-calculated
35
25
/// points corresponding to a given chunk.
36
26
/// Accumulation starts from a "shift_point" whose points are derived from digits of pi.
37
27
/// Pre-calculated points are multiples by powers of 2 of the "shift_point".
38
28
///
39
29
/// Find specification at https://docs.starkware.co/starkex/crypto/pedersen-hash-function.html
40
- pub fn hash (
41
- & self ,
42
- x : & FieldElement < Stark252PrimeField > ,
43
- y : & FieldElement < Stark252PrimeField > ,
44
- ) -> FieldElement < Stark252PrimeField > {
30
+ fn hash ( x : & FE < Self :: F > , y : & FE < Self :: F > ) -> FE < Self :: F > ;
31
+
32
+ /// Performs lookup to find the constant point corresponding to 4-bit chunks of given input.
33
+ /// Keeps adding up those points to the given accumulation point.
34
+ fn lookup_and_accumulate ( acc : & mut Point < Self :: EC > , bits : & [ bool ] , prep : & [ Point < Self :: EC > ] ) ;
35
+ }
36
+
37
+ // FIXME: currently we make some assumptions that apply to `Stark252PrimeField`, so only mark the
38
+ // implementation when that's the field.
39
+ impl < P : PedersenParameters < F = Stark252PrimeField > > Pedersen for P {
40
+ // Taken from Jonathan Lei's starknet-rs
41
+ // https://github.com/xJonathanLEI/starknet-rs/blob/4ab2f36872435ce57b1d8f55856702a6a30f270a/starknet-crypto/src/pedersen_hash.rs
42
+
43
+ fn hash ( x : & FE < Self :: F > , y : & FE < Self :: F > ) -> FE < Self :: F > {
45
44
let x = x. to_bits_le ( ) ;
46
45
let y = y. to_bits_le ( ) ;
47
- let mut acc = self . params . shift_point . clone ( ) ;
46
+ let mut acc = P :: SHIFT_POINT . clone ( ) ;
48
47
49
- self . lookup_and_accumulate ( & mut acc, & x[ ..248 ] , & self . params . points_p1 ) ; // Add a_low * P1
50
- self . lookup_and_accumulate ( & mut acc, & x[ 248 ..252 ] , & self . params . points_p2 ) ; // Add a_high * P2
51
- self . lookup_and_accumulate ( & mut acc, & y[ ..248 ] , & self . params . points_p3 ) ; // Add b_low * P3
52
- self . lookup_and_accumulate ( & mut acc, & y[ 248 ..252 ] , & self . params . points_p4 ) ; // Add b_high * P4
48
+ Self :: lookup_and_accumulate ( & mut acc, & x[ ..248 ] , & P :: POINTS_P1 ) ; // Add a_low * P1
49
+ Self :: lookup_and_accumulate ( & mut acc, & x[ 248 ..252 ] , & P :: POINTS_P2 ) ; // Add a_high * P2
50
+ Self :: lookup_and_accumulate ( & mut acc, & y[ ..248 ] , & P :: POINTS_P3 ) ; // Add b_low * P3
51
+ Self :: lookup_and_accumulate ( & mut acc, & y[ 248 ..252 ] , & P :: POINTS_P4 ) ; // Add b_high * P4
53
52
54
53
* acc. to_affine ( ) . x ( )
55
54
}
56
55
57
- /// Performs lookup to find the constant point corresponding to 4-bit chunks of given input.
58
- /// Keeps adding up those points to the given accumulation point.
59
- fn lookup_and_accumulate (
60
- & self ,
61
- acc : & mut ShortWeierstrassProjectivePoint < StarkCurve > ,
62
- bits : & [ bool ] ,
63
- prep : & [ ShortWeierstrassProjectivePoint < StarkCurve > ] ,
64
- ) {
65
- bits. chunks ( self . params . curve_const_bits )
56
+ fn lookup_and_accumulate ( acc : & mut Point < Self :: EC > , bits : & [ bool ] , prep : & [ Point < Self :: EC > ] ) {
57
+ bits. chunks ( P :: CURVE_CONST_BITS )
66
58
. enumerate ( )
67
59
. for_each ( |( i, v) | {
68
60
let offset = bools_to_usize_le ( v) ;
69
61
if offset > 0 {
70
62
// Table lookup at 'offset-1' in table for chunk 'i'
71
- * acc = acc. operate_with_affine ( & prep[ i * self . params . table_size + offset - 1 ] ) ;
63
+ * acc = acc. operate_with_affine ( & prep[ i * P :: TABLE_SIZE + offset - 1 ] ) ;
72
64
}
73
65
} )
74
66
}
@@ -88,24 +80,23 @@ fn bools_to_usize_le(bools: &[bool]) -> usize {
88
80
#[ cfg( test) ]
89
81
mod tests {
90
82
use super :: * ;
83
+ use crate :: hash:: pedersen:: parameters:: PedersenStarkCurve ;
91
84
92
85
// Test case ported from:
93
86
// https://github.com/starkware-libs/crypto-cpp/blob/95864fbe11d5287e345432dbe1e80dea3c35fc58/src/starkware/crypto/ffi/crypto_lib_test.go
94
87
95
88
#[ test]
96
89
fn test_stark_curve ( ) {
97
- let pedersen = Pedersen :: default ( ) ;
98
-
99
- let x = FieldElement :: < Stark252PrimeField > :: from_hex_unchecked (
90
+ let x = FE :: from_hex_unchecked (
100
91
"03d937c035c878245caf64531a5756109c53068da139362728feb561405371cb" ,
101
92
) ;
102
- let y = FieldElement :: < Stark252PrimeField > :: from_hex_unchecked (
93
+ let y = FE :: from_hex_unchecked (
103
94
"0208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31a" ,
104
95
) ;
105
- let hash = pedersen . hash ( & x, & y) ;
96
+ let hash = PedersenStarkCurve :: hash ( & x, & y) ;
106
97
assert_eq ! (
107
98
hash,
108
- FieldElement :: < Stark252PrimeField > :: from_hex_unchecked(
99
+ FE :: from_hex_unchecked(
109
100
"030e480bed5fe53fa909cc0f8c4d99b8f9f2c016be4c41e13a4848797979c662"
110
101
)
111
102
) ;
0 commit comments