@@ -11,7 +11,7 @@ use tracing::{debug, instrument};
1111use crate :: state:: { OPRFInstance , OPRFState } ;
1212use ppoprf:: ppoprf;
1313
14- /// Request format for the randomness endpoint
14+ /// Request structure for the randomness endpoint
1515#[ derive( Deserialize , Debug ) ]
1616pub struct RandomnessRequest {
1717 /// Array of points to evaluate
@@ -21,7 +21,7 @@ pub struct RandomnessRequest {
2121 epoch : Option < u8 > ,
2222}
2323
24- /// Response format for the randomness endpoint
24+ /// Response structure for the randomness endpoint
2525#[ derive( Serialize , Debug ) ]
2626pub struct RandomnessResponse {
2727 /// Resulting points from the OPRF valuation
@@ -32,26 +32,34 @@ pub struct RandomnessResponse {
3232 epoch : u8 ,
3333}
3434
35- /// Response format for the info endpoint
35+ /// Response structure for the info endpoint
3636/// Rename fields to match the earlier golang implementation.
3737#[ derive( Serialize , Debug ) ]
38+ #[ serde( rename_all = "camelCase" ) ]
3839pub struct InfoResponse {
3940 /// ServerPublicKey used to verify zero-knowledge proof
40- #[ serde( rename = "publicKey" ) ]
4141 public_key : String ,
4242 /// Currently active randomness epoch
43- #[ serde( rename = "currentEpoch" ) ]
4443 current_epoch : u8 ,
4544 /// Timestamp of the next epoch rotation
4645 /// This should be a string in RFC 3339 format,
4746 /// e.g. 2023-03-14T16:33:05Z.
48- #[ serde( rename = "nextEpochTime" ) ]
4947 next_epoch_time : Option < String > ,
5048 /// Maximum number of points accepted in a single request
51- #[ serde( rename = "maxPoints" ) ]
5249 max_points : usize ,
5350}
5451
52+ /// Response structure for the "list instances" endpoint.
53+ #[ derive( Serialize , Debug ) ]
54+ #[ serde( rename_all = "camelCase" ) ]
55+ pub struct ListInstancesResponse {
56+ /// A list of available instances on the server.
57+ instances : Vec < String > ,
58+ /// The default instance on this server.
59+ /// A requests made to /info and /randomness will utilize this instance.
60+ default_instance : String ,
61+ }
62+
5563/// Response returned to report error conditions
5664#[ derive( Serialize , Debug ) ]
5765struct ErrorResponse {
@@ -112,14 +120,14 @@ impl axum::response::IntoResponse for Error {
112120
113121type Result < T > = std:: result:: Result < T , Error > ;
114122
115- fn get_server_from_state (
116- state : & OPRFState ,
117- instance_name : String ,
118- ) -> Result < RwLockReadGuard < ' _ , OPRFInstance > > {
123+ fn get_server_from_state < ' a > (
124+ state : & ' a OPRFState ,
125+ instance_name : & ' a str ,
126+ ) -> Result < RwLockReadGuard < ' a , OPRFInstance > > {
119127 Ok ( state
120128 . instances
121- . get ( & instance_name)
122- . ok_or ( Error :: InstanceNotFound ( instance_name) ) ?
129+ . get ( instance_name)
130+ . ok_or_else ( || Error :: InstanceNotFound ( instance_name. to_string ( ) ) ) ?
123131 . read ( ) ?)
124132}
125133
@@ -131,7 +139,7 @@ async fn randomness(
131139 request : RandomnessRequest ,
132140) -> Result < Json < RandomnessResponse > > {
133141 debug ! ( "recv: {request:?}" ) ;
134- let state = get_server_from_state ( & state, instance_name) ?;
142+ let state = get_server_from_state ( & state, & instance_name) ?;
135143 let epoch = request. epoch . unwrap_or ( state. epoch ) ;
136144 if epoch != state. epoch {
137145 return Err ( Error :: BadEpoch ( epoch) ) ;
@@ -180,7 +188,7 @@ pub async fn specific_instance_randomness(
180188#[ instrument( skip( state) ) ]
181189async fn info ( state : OPRFState , instance_name : String ) -> Result < Json < InfoResponse > > {
182190 debug ! ( "recv: info request" ) ;
183- let state = get_server_from_state ( & state, instance_name) ?;
191+ let state = get_server_from_state ( & state, & instance_name) ?;
184192 let public_key = state. server . get_public_key ( ) . serialize_to_bincode ( ) ?;
185193 let public_key = BASE64 . encode ( public_key) ;
186194 let response = InfoResponse {
@@ -206,3 +214,11 @@ pub async fn specific_instance_info(
206214) -> Result < Json < InfoResponse > > {
207215 info ( state, instance_name) . await
208216}
217+
218+ // Lists all available instances, as well as the default instance
219+ pub async fn list_instances ( State ( state) : State < OPRFState > ) -> Result < Json < ListInstancesResponse > > {
220+ Ok ( Json ( ListInstancesResponse {
221+ instances : state. instances . keys ( ) . cloned ( ) . collect ( ) ,
222+ default_instance : state. default_instance . clone ( ) ,
223+ } ) )
224+ }
0 commit comments