1313// ! * x = 0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca
1414// ! * y = 0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f
1515
16- use crate :: ec :: {self, EcPoint , EcPointTrait , EcStateTrait };
16+ use crate :: ec :: {self, EcPointTrait , EcStateTrait };
1717use crate :: math;
1818#[allow(unused_imports)]
1919use crate :: option :: OptionTrait ;
@@ -160,15 +160,8 @@ pub fn check_ecdsa_signature(
160160pub fn recover_public_key (
161161 message_hash : felt252 , signature_r : felt252 , signature_s : felt252 , y_parity : bool ,
162162) -> Option <felt252 > {
163- let mut signature_r_point = EcPointTrait :: new_from_x (signature_r )? ;
164- let y : u256 = signature_r_point . try_into ()? . y (). into ();
165- // If the actual parity of the actual y is different than requested, flip the parity.
166- if (y . low & 1 == 1 ) != y_parity {
167- signature_r_point = - signature_r_point ;
168- }
169-
170- // Retrieve the generator point.
171- let gen_point = EcPointTrait :: new (ec :: stark_curve :: GEN_X , ec :: stark_curve :: GEN_Y )? ;
163+ let r_point = EcPointTrait :: new_nz_from_x (signature_r )? ;
164+ let gen_point = EcPointTrait :: new_nz (ec :: stark_curve :: GEN_X , ec :: stark_curve :: GEN_Y )? ;
172165
173166 // a Valid signature should satisfy:
174167 // zG + rQ = sR.
@@ -184,13 +177,23 @@ pub fn recover_public_key(
184177 // Q.x = ((s/r)R - (z/r)G).x.
185178 let r_nz : u256 = signature_r . into ();
186179 let r_nz = r_nz . try_into ()? ;
187- const ORD_U256 : u256 = ec :: stark_curve :: ORDER . into ();
180+ use ec :: stark_curve :: ORDER as ORD ;
181+ const ORD_U256 : u256 = ORD . into ();
188182 const ORD_NZ : NonZero <u256 > = ORD_U256 . try_into (). unwrap ();
189183 let r_inv = math :: u256_inv_mod (r_nz , ORD_NZ )? . into ();
190184 let s_div_r : felt252 = math :: u256_mul_mod_n (signature_s . into (), r_inv , ORD_NZ ). try_into ()? ;
191185 let z_div_r : felt252 = math :: u256_mul_mod_n (message_hash . into (), r_inv , ORD_NZ ). try_into ()? ;
192- let s_div_rR: EcPoint = signature_r_point . mul (s_div_r );
193- let z_div_rG: EcPoint = gen_point . mul (z_div_r );
194-
195- Some ((s_div_rR - z_div_rG). try_into ()? . x ())
186+ let mut state = EcStateTrait :: init ();
187+ let ord = ORD ;
188+ state . add_mul (ord - z_div_r , gen_point );
189+ // Checking if the actual parity of the point's y is different than the requested, and if so,
190+ // flipping the multiplier instead of negating the point to match the requested parity.
191+ let y : u256 = r_point . y (). into ();
192+ let r_multiplier = if (y . low & 1 != 0 ) ^ y_parity {
193+ ord - s_div_r
194+ } else {
195+ s_div_r
196+ };
197+ state . add_mul (r_multiplier , r_point );
198+ Some (state . finalize_nz ()? . x ())
196199}
0 commit comments