Skip to content

Commit 15e2f11

Browse files
committed
refactor(client): prepare client builder for aggregator discovery
1 parent 17a7f7b commit 15e2f11

File tree

1 file changed

+61
-34
lines changed

1 file changed

+61
-34
lines changed

mithril-client/src/client.rs

Lines changed: 61 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use anyhow::{Context, anyhow};
22
#[cfg(feature = "fs")]
33
use chrono::Utc;
4+
use mithril_common::messages::AggregatorCapabilities;
45
use reqwest::Url;
56
use serde::{Deserialize, Serialize};
67
use 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)]
4560
pub struct ClientOptions {
@@ -158,8 +173,9 @@ impl Client {
158173

159174
/// Builder than can be used to create a [Client] easily or with custom dependencies.
160175
pub 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

Comments
 (0)