1- //! Configuration for the HTTP proving service.
1+ //! Configuration for the proving service.
22
33use std:: net:: { IpAddr , Ipv4Addr } ;
44use std:: path:: PathBuf ;
@@ -21,27 +21,54 @@ const DEFAULT_PORT: u16 = 3000;
2121const DEFAULT_MAX_CONCURRENT_REQUESTS : usize = 2 ;
2222const DEFAULT_MAX_CONNECTIONS : u32 = 10 ;
2323
24- /// Configuration for the HTTP proving service.
24+ /// Transport mode for the JSON-RPC server.
25+ #[ derive( Clone , Debug ) ]
26+ pub enum TransportMode {
27+ Http ,
28+ Https { tls_cert_file : PathBuf , tls_key_file : PathBuf } ,
29+ }
30+
31+ impl TransportMode {
32+ /// Constructs a `TransportMode` from optional cert and key paths.
33+ ///
34+ /// Returns `Http` when both are `None`, `Https` when both are `Some`, or an error when only
35+ /// one is provided.
36+ pub fn new (
37+ tls_cert_file : Option < PathBuf > ,
38+ tls_key_file : Option < PathBuf > ,
39+ ) -> Result < Self , ConfigError > {
40+ match ( tls_cert_file, tls_key_file) {
41+ ( None , None ) => Ok ( Self :: Http ) ,
42+ ( Some ( tls_cert_file) , Some ( tls_key_file) ) => {
43+ Ok ( Self :: Https { tls_cert_file, tls_key_file } )
44+ }
45+ ( Some ( _) , None ) => Err ( ConfigError :: IncompleteTlsConfig (
46+ "tls_cert_file is set but tls_key_file is missing" . to_string ( ) ,
47+ ) ) ,
48+ ( None , Some ( _) ) => Err ( ConfigError :: IncompleteTlsConfig (
49+ "tls_key_file is set but tls_cert_file is missing" . to_string ( ) ,
50+ ) ) ,
51+ }
52+ }
53+ }
54+
55+ /// Raw configuration as deserialized from JSON. TLS fields are optional and validated after CLI
56+ /// overrides are applied.
2557#[ derive( Clone , Debug , Deserialize , Serialize ) ]
2658#[ serde( default ) ]
27- pub struct ServiceConfig {
28- /// Configuration for the prover.
59+ struct RawServiceConfig {
2960 #[ serde( flatten) ]
30- pub prover_config : ProverConfig ,
31- /// IP address to bind the server to.
32- pub ip : IpAddr ,
33- /// Port to bind the server to.
34- pub port : u16 ,
35- /// Maximum number of concurrent proving requests.
36- pub max_concurrent_requests : usize ,
37- /// Maximum number of simultaneous JSON-RPC connections (safety net).
38- pub max_connections : u32 ,
39- /// List of allowed web origins (domains) that may call this HTTP service from a browser
40- /// (CORS). Examples: `http://localhost:5173`, `https://app.example.com`, or `*` to allow any origin.
41- pub cors_allow_origin : Vec < String > ,
61+ prover_config : ProverConfig ,
62+ ip : IpAddr ,
63+ port : u16 ,
64+ max_concurrent_requests : usize ,
65+ max_connections : u32 ,
66+ cors_allow_origin : Vec < String > ,
67+ tls_cert_file : Option < PathBuf > ,
68+ tls_key_file : Option < PathBuf > ,
4269}
4370
44- impl Default for ServiceConfig {
71+ impl Default for RawServiceConfig {
4572 fn default ( ) -> Self {
4673 Self {
4774 prover_config : ProverConfig :: default ( ) ,
@@ -50,10 +77,33 @@ impl Default for ServiceConfig {
5077 max_concurrent_requests : DEFAULT_MAX_CONCURRENT_REQUESTS ,
5178 max_connections : DEFAULT_MAX_CONNECTIONS ,
5279 cors_allow_origin : Vec :: new ( ) ,
80+ tls_cert_file : None ,
81+ tls_key_file : None ,
5382 }
5483 }
5584}
5685
86+ /// Configuration for the proving service.
87+ #[ derive( Clone , Debug ) ]
88+ pub struct ServiceConfig {
89+ /// Configuration for the prover.
90+ pub prover_config : ProverConfig ,
91+ /// IP address to bind the server to.
92+ pub ip : IpAddr ,
93+ /// Port to bind the server to.
94+ pub port : u16 ,
95+ /// Maximum number of concurrent proving requests.
96+ pub max_concurrent_requests : usize ,
97+ /// Maximum number of simultaneous JSON-RPC connections (safety net).
98+ pub max_connections : u32 ,
99+ /// List of allowed web origins (domains) that may call this HTTP service from a browser
100+ /// (CORS). Examples: `http://localhost:5173`, `https://app.example.com`, or `*` to allow any
101+ /// origin.
102+ pub cors_allow_origin : Vec < String > ,
103+ /// Transport mode (HTTP or HTTPS with TLS).
104+ pub transport : TransportMode ,
105+ }
106+
57107impl ServiceConfig {
58108 /// Creates a ServiceConfig from CLI arguments.
59109 pub fn from_args ( args : CliArgs ) -> Result < Self , ConfigError > {
@@ -65,15 +115,15 @@ impl ServiceConfig {
65115 e
66116 ) )
67117 } ) ?;
68- serde_json:: from_str ( & contents) . map_err ( |e| {
118+ serde_json:: from_str :: < RawServiceConfig > ( & contents) . map_err ( |e| {
69119 ConfigError :: ConfigFileError ( format ! (
70120 "Failed to parse config file {}: {}" ,
71121 config_file. display( ) ,
72122 e
73123 ) )
74124 } ) ?
75125 } else {
76- ServiceConfig :: default ( )
126+ RawServiceConfig :: default ( )
77127 } ;
78128
79129 // Override with CLI arguments if provided.
@@ -126,6 +176,24 @@ impl ServiceConfig {
126176 config. max_connections = max;
127177 }
128178 }
179+ if let Some ( tls_cert_file) = args. tls_cert_file {
180+ if Some ( & tls_cert_file) != config. tls_cert_file . as_ref ( ) {
181+ info ! (
182+ "CLI override: tls_cert_file: {:?} -> {:?}" ,
183+ config. tls_cert_file, tls_cert_file
184+ ) ;
185+ config. tls_cert_file = Some ( tls_cert_file) ;
186+ }
187+ }
188+ if let Some ( tls_key_file) = args. tls_key_file {
189+ if Some ( & tls_key_file) != config. tls_key_file . as_ref ( ) {
190+ info ! (
191+ "CLI override: tls_key_file: {:?} -> {:?}" ,
192+ config. tls_key_file, tls_key_file
193+ ) ;
194+ config. tls_key_file = Some ( tls_key_file) ;
195+ }
196+ }
129197
130198 if args. no_cors && !args. cors_allow_origin . is_empty ( ) {
131199 return Err ( ConfigError :: InvalidArgument (
@@ -194,19 +262,28 @@ impl ServiceConfig {
194262 "max_connections must be at least 1" . to_string ( ) ,
195263 ) ) ;
196264 }
197- config. cors_allow_origin = normalize_cors_allow_origins ( config. cors_allow_origin ) ?;
198- if config. cors_allow_origin == [ "*" ] {
265+ let transport = TransportMode :: new ( config. tls_cert_file , config. tls_key_file ) ?;
266+ let cors_allow_origin = normalize_cors_allow_origins ( config. cors_allow_origin ) ?;
267+ if cors_allow_origin == [ "*" ] {
199268 info ! ( "CORS allow-origin configured as wildcard '*'." ) ;
200269 }
201270
202- Ok ( config)
271+ Ok ( ServiceConfig {
272+ prover_config : config. prover_config ,
273+ ip : config. ip ,
274+ port : config. port ,
275+ max_concurrent_requests : config. max_concurrent_requests ,
276+ max_connections : config. max_connections ,
277+ cors_allow_origin,
278+ transport,
279+ } )
203280 }
204281}
205282
206283/// CLI arguments for the proving service.
207284#[ derive( Parser , Debug ) ]
208285#[ command( name = "starknet-os-runner" ) ]
209- #[ command( about = "HTTP service for generating Starknet OS proofs" , long_about = None ) ]
286+ #[ command( about = "HTTP/HTTPS service for generating Starknet OS proofs" , long_about = None ) ]
210287pub struct CliArgs {
211288 /// Path to JSON configuration file.
212289 #[ arg( long, value_name = "FILE" ) ]
@@ -236,6 +313,14 @@ pub struct CliArgs {
236313 #[ arg( long, value_name = "N" ) ]
237314 pub max_connections : Option < u32 > ,
238315
316+ /// Path to TLS certificate chain PEM file. Requires --tls-key-file.
317+ #[ arg( long, value_name = "FILE" ) ]
318+ pub tls_cert_file : Option < PathBuf > ,
319+
320+ /// Path to TLS private key PEM file. Requires --tls-cert-file.
321+ #[ arg( long, value_name = "FILE" ) ]
322+ pub tls_key_file : Option < PathBuf > ,
323+
239324 /// Override STRK fee token address (hex, e.g. for custom environments that share a chain ID).
240325 #[ arg( long, value_name = "ADDRESS" ) ]
241326 pub strk_fee_token_address : Option < String > ,
@@ -279,4 +364,6 @@ pub enum ConfigError {
279364 InvalidArgument ( String ) ,
280365 #[ error( "Missing required field: {0}" ) ]
281366 MissingRequiredField ( String ) ,
367+ #[ error( "Incomplete TLS configuration: {0}" ) ]
368+ IncompleteTlsConfig ( String ) ,
282369}
0 commit comments