Skip to content

Commit 857d931

Browse files
committed
feat(client): implement basic aggregator discoverer
1 parent 4681baa commit 857d931

File tree

3 files changed

+37
-9
lines changed

3 files changed

+37
-9
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mithril-client/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ flate2 = { version = "1.1.4", optional = true }
5959
flume = { version = "0.11.1", optional = true }
6060
futures = "0.3.31"
6161
mithril-common = { path = "../mithril-common", version = ">=0.6", default-features = false }
62+
mithril-aggregator-discovery = { path = "../internal/mithril-aggregator-discovery" }
6263
reqwest = { workspace = true, default-features = false, features = [
6364
"charset",
6465
"http2",

mithril-client/src/client.rs

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use anyhow::{Context, anyhow};
22
#[cfg(feature = "fs")]
33
use chrono::Utc;
4+
use mithril_aggregator_discovery::{
5+
AggregatorDiscoverer, HttpConfigAggregatorDiscoverer, MithrilNetwork,
6+
};
47
use mithril_common::messages::AggregatorCapabilities;
58
use reqwest::Url;
69
use serde::{Deserialize, Serialize};
@@ -44,7 +47,7 @@ const fn one_week_in_seconds() -> u32 {
4447
/// The type of discovery to use to find the aggregator to connect to.
4548
pub enum AggregatorDiscoveryType {
4649
/// Automatically discover the aggregator.
47-
Automatic,
50+
Automatic(MithrilNetwork),
4851
/// Use a specific URL to connect to the aggregator.
4952
Url(String),
5053
}
@@ -175,6 +178,7 @@ impl Client {
175178
pub struct ClientBuilder {
176179
aggregator_discovery: AggregatorDiscoveryType,
177180
aggregator_capabilities: Option<AggregatorCapabilities>,
181+
aggregator_discoverer: Option<Arc<dyn AggregatorDiscoverer>>,
178182
genesis_verification_key: Option<GenesisVerificationKey>,
179183
origin_tag: Option<String>,
180184
client_type: Option<String>,
@@ -196,16 +200,19 @@ impl ClientBuilder {
196200
/// Constructs a new `ClientBuilder` that fetches data from the aggregator at the given
197201
/// endpoint and with the given genesis verification key.
198202
pub fn aggregator(endpoint: &str, genesis_verification_key: &str) -> ClientBuilder {
199-
Self::new(AggregatorDiscoveryType::Url(endpoint.to_string())).with_genesis_verification_key(
200-
GenesisVerificationKey::JsonHex(genesis_verification_key.to_string()),
201-
)
203+
Self::new(AggregatorDiscoveryType::Url(endpoint.to_string()))
204+
.with_genesis_verification_key(GenesisVerificationKey::JsonHex(
205+
genesis_verification_key.to_string(),
206+
))
207+
.with_aggregator_discoverer(Arc::new(HttpConfigAggregatorDiscoverer::default()))
202208
}
203209

204210
/// Constructs a new `ClientBuilder` without any dependency set.
205211
pub fn new(aggregator_discovery: AggregatorDiscoveryType) -> ClientBuilder {
206212
Self {
207213
aggregator_discovery,
208214
aggregator_capabilities: None,
215+
aggregator_discoverer: None,
209216
genesis_verification_key: None,
210217
origin_tag: None,
211218
client_type: None,
@@ -241,6 +248,16 @@ impl ClientBuilder {
241248
self
242249
}
243250

251+
/// Sets the aggregator discoverer to use to find the aggregator endpoint when in automatic discovery.
252+
pub fn with_aggregator_discoverer(
253+
mut self,
254+
discoverer: Arc<dyn AggregatorDiscoverer>,
255+
) -> ClientBuilder {
256+
self.aggregator_discoverer = Some(discoverer);
257+
258+
self
259+
}
260+
244261
/// Returns a `Client` that uses the dependencies provided to this `ClientBuilder`.
245262
///
246263
/// The builder will try to create the missing dependencies using default implementations
@@ -264,7 +281,7 @@ impl ClientBuilder {
264281
let feedback_sender = FeedbackSender::new(&self.feedback_receivers);
265282

266283
let aggregator_client = match self.aggregator_client {
267-
None => Arc::new(self.build_aggregator_client(logger.clone())?),
284+
None => Arc::new(self.build_aggregator_client(logger.clone()).await?),
268285
Some(client) => client,
269286
};
270287

@@ -367,15 +384,24 @@ impl ClientBuilder {
367384
})
368385
}
369386

370-
fn build_aggregator_client(
387+
async fn build_aggregator_client(
371388
&self,
372389
logger: Logger,
373390
) -> Result<AggregatorHTTPClient, anyhow::Error> {
374391
let aggregator_endpoint = match self.aggregator_discovery {
375392
AggregatorDiscoveryType::Url(ref url) => url.clone(),
376-
AggregatorDiscoveryType::Automatic => {
377-
todo!("Implement automatic aggregator discovery")
378-
}
393+
AggregatorDiscoveryType::Automatic(ref network) => match &self.aggregator_discoverer {
394+
Some(discoverer) => discoverer
395+
.get_available_aggregators(network.to_owned())
396+
.await
397+
.with_context(|| "Discovering aggregator endpoint failed")?
398+
.next()
399+
.unwrap()
400+
.into(),
401+
None => {
402+
return Err(anyhow!("The aggregator discoverer must be provided to build the client with automatic discovery using the 'with_aggregator_discoverer' function").into());
403+
}
404+
},
379405
};
380406
let endpoint_url = Url::parse(&aggregator_endpoint).with_context(|| {
381407
format!("Invalid aggregator endpoint, it must be a correctly formed url: '{aggregator_endpoint}'")

0 commit comments

Comments
 (0)