1+ use std:: sync:: OnceLock ;
2+
13use ark_ff:: { One , SquareRootField , Zero } ;
24
35use ledger:: { proofs:: transaction:: legacy_input:: to_bits, ToInputs } ;
@@ -18,6 +20,26 @@ pub struct VrfMessage {
1820 delegator_index : u64 ,
1921}
2022
23+ struct CachedFields {
24+ two : BaseField ,
25+ three : BaseField ,
26+ five : BaseField ,
27+ projection_point_z : BaseField ,
28+ // Add other fields here that might benefit from caching
29+ }
30+
31+ static CACHED_FIELDS : OnceLock < CachedFields > = OnceLock :: new ( ) ;
32+
33+ #[ inline( always) ]
34+ fn get_y ( x : BaseField , five : BaseField ) -> Option < BaseField > {
35+ let mut res = x;
36+ res *= & x; // x^2
37+ res += BaseField :: zero ( ) ; // x^2 + A x
38+ res *= & x; // x^3 + A x
39+ res += five; // x^3 + A x + B
40+ res. sqrt ( )
41+ }
42+
2143impl VrfMessage {
2244 pub fn new ( global_slot : u32 , epoch_seed : EpochSeed , delegator_index : u64 ) -> Self {
2345 Self {
@@ -32,27 +54,38 @@ impl VrfMessage {
3254 }
3355
3456 pub fn to_group ( & self ) -> VrfResult < CurvePoint > {
35- // helpers
36- let two = BaseField :: one ( ) + BaseField :: one ( ) ;
37- let three = two + BaseField :: one ( ) ;
38-
39- // params, according to ocaml
40- let mut projection_point_z_bytes =
41- hex:: decode ( "1AF731EC3CA2D77CC5D13EDC8C9A0A77978CB5F4FBFCC470B5983F5B6336DB69" ) ?;
42- projection_point_z_bytes. reverse ( ) ;
43- let projection_point_z = BaseField :: from_bytes ( & projection_point_z_bytes) ?;
57+ let cached = CACHED_FIELDS . get_or_init ( || {
58+ let one = BaseField :: one ( ) ;
59+ let two = one + one;
60+ let three = two + one;
61+ let five = three + two;
62+
63+ let projection_point_z_bytes =
64+ hex:: decode ( "1AF731EC3CA2D77CC5D13EDC8C9A0A77978CB5F4FBFCC470B5983F5B6336DB69" )
65+ . expect ( "Failed to decode hex string" ) ;
66+ let projection_point_z = BaseField :: from_bytes ( & projection_point_z_bytes)
67+ . expect ( "Failed to convert bytes to BaseField" ) ;
68+
69+ CachedFields {
70+ two,
71+ three,
72+ five,
73+ projection_point_z,
74+ }
75+ } ) ;
76+
4477 let projection_point_y = BaseField :: one ( ) ;
45- let conic_c = three;
78+ let conic_c = cached . three ;
4679 let u_over_2 = BaseField :: one ( ) ;
47- let u = two;
80+ let u = cached . two ;
4881
4982 let t = self . hash ( ) ;
5083
5184 // field to conic
5285 let ct = conic_c * t;
53- let s =
54- two * ( ( ct * projection_point_y ) + projection_point_z ) / ( ( ct * t) + BaseField :: one ( ) ) ;
55- let conic_z = projection_point_z - s;
86+ let s = cached . two * ( ( ct * projection_point_y ) + cached . projection_point_z )
87+ / ( ( ct * t) + BaseField :: one ( ) ) ;
88+ let conic_z = cached . projection_point_z - s;
5689 let conic_y = projection_point_y - ( s * t) ;
5790
5891 // conic to s
@@ -64,22 +97,8 @@ impl VrfMessage {
6497 let x2 = -( u + v) ;
6598 let x3 = u + ( y * y) ;
6699
67- let get_y = |x : BaseField | -> Option < BaseField > {
68- let five = BaseField :: one ( )
69- + BaseField :: one ( )
70- + BaseField :: one ( )
71- + BaseField :: one ( )
72- + BaseField :: one ( ) ;
73- let mut res = x;
74- res *= & x; // x^2
75- res += BaseField :: zero ( ) ; // x^2 + A x
76- res *= & x; // x^3 + A x
77- res += five; // x^3 + A x + B
78- res. sqrt ( )
79- } ;
80-
81100 for x in [ x1, x2, x3] {
82- if let Some ( y) = get_y ( x) {
101+ if let Some ( y) = get_y ( x, cached . five ) {
83102 return Ok ( CurvePoint :: new ( x, y, false ) ) ;
84103 }
85104 }
0 commit comments