11use anyhow:: { Context , anyhow} ;
22#[ cfg( feature = "fs" ) ]
33use chrono:: Utc ;
4+ use mithril_common:: messages:: AggregatorCapabilities ;
45use reqwest:: Url ;
56use serde:: { Deserialize , Serialize } ;
67use slog:: { Logger , o} ;
@@ -40,6 +41,20 @@ const fn one_week_in_seconds() -> u32 {
4041 604800
4142}
4243
44+ /// The type of discovery to use to find the aggregator to connect to.
45+ pub enum AggregatorDiscoveryType {
46+ /// Automatically discover the aggregator.
47+ Automatic ,
48+ /// Use a specific URL to connect to the aggregator.
49+ Url ( String ) ,
50+ }
51+
52+ /// The genesis verification key.
53+ pub enum GenesisVerificationKey {
54+ /// The verification key is provided as a JSON Hex-encoded string.
55+ JsonHex ( String ) ,
56+ }
57+
4358/// Options that can be used to configure the client.
4459#[ derive( Debug , Clone , Default , Serialize , Deserialize ) ]
4560pub struct ClientOptions {
@@ -158,8 +173,9 @@ impl Client {
158173
159174/// Builder than can be used to create a [Client] easily or with custom dependencies.
160175pub struct ClientBuilder {
161- aggregator_endpoint : Option < String > ,
162- genesis_verification_key : String ,
176+ aggregator_discovery : AggregatorDiscoveryType ,
177+ aggregator_capabilities : Option < AggregatorCapabilities > ,
178+ genesis_verification_key : Option < GenesisVerificationKey > ,
163179 origin_tag : Option < String > ,
164180 client_type : Option < String > ,
165181 #[ cfg( feature = "fs" ) ]
@@ -180,35 +196,17 @@ impl ClientBuilder {
180196 /// Constructs a new `ClientBuilder` that fetches data from the aggregator at the given
181197 /// endpoint and with the given genesis verification key.
182198 pub fn aggregator ( endpoint : & str , genesis_verification_key : & str ) -> ClientBuilder {
183- Self {
184- aggregator_endpoint : Some ( endpoint. to_string ( ) ) ,
185- genesis_verification_key : genesis_verification_key. to_string ( ) ,
186- origin_tag : None ,
187- client_type : None ,
188- #[ cfg( feature = "fs" ) ]
189- ancillary_verification_key : None ,
190- aggregator_client : None ,
191- certificate_verifier : None ,
192- #[ cfg( feature = "fs" ) ]
193- http_file_downloader : None ,
194- #[ cfg( feature = "unstable" ) ]
195- certificate_verifier_cache : None ,
196- era_fetcher : None ,
197- logger : None ,
198- feedback_receivers : vec ! [ ] ,
199- options : ClientOptions :: default ( ) ,
200- }
199+ Self :: new ( AggregatorDiscoveryType :: Url ( endpoint. to_string ( ) ) ) . with_genesis_verification_key (
200+ GenesisVerificationKey :: JsonHex ( genesis_verification_key. to_string ( ) ) ,
201+ )
201202 }
202203
203204 /// Constructs a new `ClientBuilder` without any dependency set.
204- ///
205- /// Use [ClientBuilder::aggregator] if you don't need to set a custom [AggregatorClient]
206- /// to request data from the aggregator.
207- #[ deprecated( since = "0.12.33" , note = "Will be removed in 0.13.0" ) ]
208- pub fn new ( genesis_verification_key : & str ) -> ClientBuilder {
205+ pub fn new ( aggregator_discovery : AggregatorDiscoveryType ) -> ClientBuilder {
209206 Self {
210- aggregator_endpoint : None ,
211- genesis_verification_key : genesis_verification_key. to_string ( ) ,
207+ aggregator_discovery,
208+ aggregator_capabilities : None ,
209+ genesis_verification_key : None ,
212210 origin_tag : None ,
213211 client_type : None ,
214212 #[ cfg( feature = "fs" ) ]
@@ -226,6 +224,23 @@ impl ClientBuilder {
226224 }
227225 }
228226
227+ /// Sets the genesis verification key to use when verifying certificates.
228+ pub fn with_genesis_verification_key (
229+ mut self ,
230+ genesis_verification_key : GenesisVerificationKey ,
231+ ) -> ClientBuilder {
232+ self . genesis_verification_key = Some ( genesis_verification_key) ;
233+
234+ self
235+ }
236+
237+ /// Sets the aggregator capabilities expected to be matched by the aggregator with which the client will interact.
238+ pub fn with_capabilities ( mut self , capabilities : AggregatorCapabilities ) -> ClientBuilder {
239+ self . aggregator_capabilities = Some ( capabilities) ;
240+
241+ self
242+ }
243+
229244 /// Returns a `Client` that uses the dependencies provided to this `ClientBuilder`.
230245 ///
231246 /// The builder will try to create the missing dependencies using default implementations
@@ -236,6 +251,16 @@ impl ClientBuilder {
236251 . clone ( )
237252 . unwrap_or_else ( || Logger :: root ( slog:: Discard , o ! ( ) ) ) ;
238253
254+ let genesis_verification_key = match self . genesis_verification_key {
255+ Some ( GenesisVerificationKey :: JsonHex ( ref key) ) => key,
256+ None => {
257+ return Err ( anyhow ! (
258+ "The genesis verification key must be provided to build the client with the 'with_genesis_verification_key' function"
259+ )
260+ . into ( ) ) ;
261+ }
262+ } ;
263+
239264 let feedback_sender = FeedbackSender :: new ( & self . feedback_receivers ) ;
240265
241266 let aggregator_client = match self . aggregator_client {
@@ -254,7 +279,7 @@ impl ClientBuilder {
254279 None => Arc :: new (
255280 MithrilCertificateVerifier :: new (
256281 aggregator_client. clone ( ) ,
257- & self . genesis_verification_key ,
282+ genesis_verification_key,
258283 feedback_sender. clone ( ) ,
259284 #[ cfg( feature = "unstable" ) ]
260285 self . certificate_verifier_cache ,
@@ -346,12 +371,14 @@ impl ClientBuilder {
346371 & self ,
347372 logger : Logger ,
348373 ) -> Result < AggregatorHTTPClient , anyhow:: Error > {
349- let endpoint = self
350- . aggregator_endpoint . as_ref ( )
351- . ok_or ( anyhow ! ( "No aggregator endpoint set: \
352- You must either provide an aggregator endpoint or your own AggregatorClient implementation") ) ?;
353- let endpoint_url = Url :: parse ( endpoint) . with_context ( || {
354- format ! ( "Invalid aggregator endpoint, it must be a correctly formed url: '{endpoint}'" )
374+ let aggregator_endpoint = match self . aggregator_discovery {
375+ AggregatorDiscoveryType :: Url ( ref url) => url. clone ( ) ,
376+ AggregatorDiscoveryType :: Automatic => {
377+ todo ! ( "Implement automatic aggregator discovery" )
378+ }
379+ } ;
380+ let endpoint_url = Url :: parse ( & aggregator_endpoint) . with_context ( || {
381+ format ! ( "Invalid aggregator endpoint, it must be a correctly formed url: '{aggregator_endpoint}'" )
355382 } ) ?;
356383
357384 let headers = self . compute_http_headers ( ) ;
0 commit comments