Skip to content

Commit 05a151b

Browse files
committed
Update Client implementation #147
* Add new Verifier dependency * Add missing tests for restore snapshot * Cleaned client code for more readability
1 parent 16cc2ee commit 05a151b

File tree

3 files changed

+188
-65
lines changed

3 files changed

+188
-65
lines changed

mithril-network/mithril-client/src/client.rs

Lines changed: 176 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,76 @@
11
use log::debug;
2+
use mithril_aggregator::fake_data;
3+
use std::str;
24

35
use crate::aggregator::AggregatorHandler;
46
use crate::entities::*;
57
use crate::errors;
8+
use crate::verifier::Verifier;
9+
10+
/// AggregatorHandlerWrapper wraps an AggregatorHandler
11+
pub type AggregatorHandlerWrapper = Box<dyn AggregatorHandler>;
12+
13+
/// VerifierWrapper wraps a Verifier
14+
pub type VerifierWrapper = Box<dyn Verifier>;
615

716
/// Mithril client wrapper
8-
pub struct Client<R>
9-
where
10-
R: AggregatorHandler,
11-
{
17+
pub struct Client {
1218
pub network: String,
13-
pub aggregator_handler: Option<Box<R>>,
19+
pub aggregator_handler: Option<AggregatorHandlerWrapper>,
20+
pub verifier: Option<VerifierWrapper>,
1421
}
1522

16-
impl<R> Client<R>
17-
where
18-
R: AggregatorHandler,
19-
{
23+
impl Client {
2024
/// Client factory
2125
pub fn new(network: String) -> Self {
2226
Self {
2327
network,
2428
aggregator_handler: None,
29+
verifier: None,
2530
}
2631
}
2732

2833
/// With AggregatorHandler
29-
pub fn with_aggregator_handler(&mut self, aggregator_handler: R) -> &mut Self {
30-
self.aggregator_handler = Some(Box::new(aggregator_handler));
34+
pub fn with_aggregator_handler(
35+
&mut self,
36+
aggregator_handler: AggregatorHandlerWrapper,
37+
) -> &mut Self {
38+
self.aggregator_handler = Some(aggregator_handler);
39+
self
40+
}
41+
42+
/// With Verifier
43+
pub fn with_verifier(&mut self, verifier: VerifierWrapper) -> &mut Self {
44+
self.verifier = Some(verifier);
3145
self
3246
}
33-
}
3447

35-
impl<R> Client<R>
36-
where
37-
R: AggregatorHandler,
38-
{
3948
/// List snapshots
4049
pub async fn list_snapshots(&self) -> Result<Vec<SnapshotListItem>, String> {
4150
debug!("List snapshots");
42-
match &self.aggregator_handler {
43-
Some(aggregator_handler) => match aggregator_handler.list_snapshots().await {
44-
Ok(snapshots) => Ok(snapshots
45-
.iter()
46-
.map(|snapshot| convert_to_list_item(snapshot, self.network.clone()))
47-
.collect::<Vec<SnapshotListItem>>()),
48-
Err(err) => Err(err),
49-
},
50-
None => Err(errors::MISSING_AGGREGATOR_HANDLER.to_string()),
51-
}
51+
let aggregator_handler = &self
52+
.aggregator_handler
53+
.as_ref()
54+
.ok_or_else(|| errors::MISSING_AGGREGATOR_HANDLER.to_string())?;
55+
Ok(aggregator_handler
56+
.list_snapshots()
57+
.await?
58+
.iter()
59+
.map(|snapshot| convert_to_list_item(snapshot, self.network.clone()))
60+
.collect::<Vec<SnapshotListItem>>())
5261
}
5362

5463
/// Show a snapshot
5564
pub async fn show_snapshot(&self, digest: &str) -> Result<Vec<SnapshotFieldItem>, String> {
5665
debug!("Show snapshot {}", digest);
57-
match &self.aggregator_handler {
58-
Some(aggregator_handler) => match aggregator_handler.get_snapshot_details(digest).await
59-
{
60-
Ok(snapshot) => Ok(convert_to_field_items(&snapshot, self.network.clone())),
61-
Err(err) => Err(err),
62-
},
63-
None => Err(errors::MISSING_AGGREGATOR_HANDLER.to_string()),
64-
}
66+
let aggregator_handler = &self
67+
.aggregator_handler
68+
.as_ref()
69+
.ok_or_else(|| errors::MISSING_AGGREGATOR_HANDLER.to_string())?;
70+
Ok(convert_to_field_items(
71+
&aggregator_handler.get_snapshot_details(digest).await?,
72+
self.network.clone(),
73+
))
6574
}
6675

6776
/// Download a snapshot by digest
@@ -71,36 +80,46 @@ where
7180
location_index: isize,
7281
) -> Result<(String, String), String> {
7382
debug!("Download snapshot {}", digest);
74-
match &self.aggregator_handler {
75-
Some(aggregator_handler) => match aggregator_handler.get_snapshot_details(digest).await
76-
{
77-
Ok(snapshot) => {
78-
let from = snapshot
79-
.locations
80-
.get((location_index - 1) as usize)
81-
.unwrap()
82-
.to_owned();
83-
match aggregator_handler.download_snapshot(digest, &from).await {
84-
Ok(to) => Ok((from, to)),
85-
Err(err) => Err(err),
86-
}
87-
}
88-
Err(err) => Err(err),
89-
},
90-
None => Err(errors::MISSING_AGGREGATOR_HANDLER.to_string()),
83+
let aggregator_handler = &self
84+
.aggregator_handler
85+
.as_ref()
86+
.ok_or_else(|| errors::MISSING_AGGREGATOR_HANDLER.to_string())?;
87+
let snapshot = aggregator_handler.get_snapshot_details(digest).await?;
88+
let from = snapshot
89+
.locations
90+
.get((location_index - 1) as usize)
91+
.unwrap()
92+
.to_owned();
93+
match aggregator_handler.download_snapshot(digest, &from).await {
94+
Ok(to) => Ok((from, to)),
95+
Err(err) => Err(err),
9196
}
9297
}
9398

9499
/// Restore a snapshot by hash
95100
pub async fn restore_snapshot(&self, digest: &str) -> Result<String, String> {
96101
debug!("Restore snapshot {}", digest);
97-
match &self.aggregator_handler {
98-
Some(aggregator_handler) => match aggregator_handler.unpack_snapshot(digest).await {
99-
Ok(to) => Ok(to),
100-
Err(err) => Err(err),
101-
},
102-
None => Err(errors::MISSING_AGGREGATOR_HANDLER.to_string()),
103-
}
102+
let aggregator_handler = &self
103+
.aggregator_handler
104+
.as_ref()
105+
.ok_or_else(|| errors::MISSING_AGGREGATOR_HANDLER.to_string())?;
106+
let verifier = &self
107+
.verifier
108+
.as_ref()
109+
.ok_or_else(|| errors::MISSING_VERIFIER.to_string())?;
110+
let fake_digest = fake_data::digest();
111+
debug!("Fake digest {:?}", fake_digest);
112+
let certificate_hash = str::from_utf8(&fake_digest).unwrap();
113+
let certificate_details = aggregator_handler
114+
.get_certificate_details(certificate_hash)
115+
.await?;
116+
verifier.verify_multi_signature(
117+
&digest.as_bytes().to_vec(),
118+
certificate_details.multisignature.as_ref(),
119+
&certificate_details.participants,
120+
&certificate_details.protocol_parameters,
121+
)?;
122+
aggregator_handler.unpack_snapshot(digest).await
104123
}
105124
}
106125

@@ -143,6 +162,7 @@ mod tests {
143162
use super::*;
144163

145164
use crate::aggregator::MockAggregatorHandler;
165+
use crate::verifier::MockVerifier;
146166
use mithril_aggregator::fake_data;
147167

148168
#[tokio::test]
@@ -155,7 +175,7 @@ mod tests {
155175
.return_const(Ok(fake_snapshots.clone()))
156176
.once();
157177
let mut client = Client::new(network.clone());
158-
client.with_aggregator_handler(mock_aggregator_handler);
178+
client.with_aggregator_handler(Box::new(mock_aggregator_handler));
159179
let snapshot_list_items = client.list_snapshots().await;
160180
snapshot_list_items.as_ref().expect("unexpected error");
161181
let snapshot_list_items_expected = fake_snapshots
@@ -173,7 +193,7 @@ mod tests {
173193
.return_const(Err("error occurred".to_string()))
174194
.once();
175195
let mut client = Client::new("testnet".to_string());
176-
client.with_aggregator_handler(mock_aggregator_handler);
196+
client.with_aggregator_handler(Box::new(mock_aggregator_handler));
177197
let snapshot_list_items = client.list_snapshots().await;
178198
assert!(
179199
snapshot_list_items.is_err(),
@@ -191,7 +211,7 @@ mod tests {
191211
.return_const(Ok(fake_snapshot.clone()))
192212
.once();
193213
let mut client = Client::new("testnet".to_string());
194-
client.with_aggregator_handler(mock_aggregator_handler);
214+
client.with_aggregator_handler(Box::new(mock_aggregator_handler));
195215
let snapshot_item = client.show_snapshot(digest).await;
196216
snapshot_item.as_ref().expect("unexpected error");
197217
let snapshot_item_expected = convert_to_field_items(&fake_snapshot, "testnet".to_string());
@@ -207,8 +227,102 @@ mod tests {
207227
.return_const(Err("error occurred".to_string()))
208228
.once();
209229
let mut client = Client::new("testnet".to_string());
210-
client.with_aggregator_handler(mock_aggregator_handler);
230+
client.with_aggregator_handler(Box::new(mock_aggregator_handler));
211231
let snapshot_item = client.show_snapshot(digest).await;
212232
assert!(snapshot_item.is_err(), "an error should have occurred");
213233
}
234+
235+
#[tokio::test]
236+
async fn test_restore_snapshot_ok() {
237+
let certificate_hash = "certhash123";
238+
let fake_certificate = fake_data::certificate(certificate_hash.to_string());
239+
let mut mock_aggregator_handler = MockAggregatorHandler::new();
240+
let mut mock_verifier = MockVerifier::new();
241+
mock_aggregator_handler
242+
.expect_get_certificate_details()
243+
.return_const(Ok(fake_certificate.clone()))
244+
.once();
245+
mock_aggregator_handler
246+
.expect_unpack_snapshot()
247+
.return_const(Ok("".to_string()))
248+
.once();
249+
mock_verifier
250+
.expect_verify_multi_signature()
251+
.return_const(Ok(()))
252+
.once();
253+
let mut client = Client::new("testnet".to_string());
254+
client
255+
.with_aggregator_handler(Box::new(mock_aggregator_handler))
256+
.with_verifier(Box::new(mock_verifier));
257+
let restore = client.restore_snapshot(certificate_hash).await;
258+
restore.expect("unexpected error");
259+
}
260+
261+
#[tokio::test]
262+
async fn test_restore_snapshot_ko_get_certificate_details() {
263+
let certificate_hash = "certhash123";
264+
let mut mock_aggregator_handler = MockAggregatorHandler::new();
265+
let mut mock_verifier = MockVerifier::new();
266+
mock_aggregator_handler
267+
.expect_get_certificate_details()
268+
.return_const(Err("an error".to_string()))
269+
.once();
270+
mock_aggregator_handler.expect_unpack_snapshot().never();
271+
mock_verifier.expect_verify_multi_signature().never();
272+
let mut client = Client::new("testnet".to_string());
273+
client
274+
.with_aggregator_handler(Box::new(mock_aggregator_handler))
275+
.with_verifier(Box::new(mock_verifier));
276+
let restore = client.restore_snapshot(certificate_hash).await;
277+
assert!(restore.is_err(), "an error should have occurred");
278+
}
279+
280+
#[tokio::test]
281+
async fn test_restore_snapshot_ko_verify_multi_signature() {
282+
let certificate_hash = "certhash123";
283+
let fake_certificate = fake_data::certificate(certificate_hash.to_string());
284+
let mut mock_aggregator_handler = MockAggregatorHandler::new();
285+
let mut mock_verifier = MockVerifier::new();
286+
mock_aggregator_handler
287+
.expect_get_certificate_details()
288+
.return_const(Ok(fake_certificate.clone()))
289+
.once();
290+
mock_aggregator_handler.expect_unpack_snapshot().never();
291+
mock_verifier
292+
.expect_verify_multi_signature()
293+
.return_const(Err("an error".to_string()))
294+
.once();
295+
let mut client = Client::new("testnet".to_string());
296+
client
297+
.with_aggregator_handler(Box::new(mock_aggregator_handler))
298+
.with_verifier(Box::new(mock_verifier));
299+
let restore = client.restore_snapshot(certificate_hash).await;
300+
assert!(restore.is_err(), "an error should have occurred");
301+
}
302+
303+
#[tokio::test]
304+
async fn test_restore_unpack_snapshot() {
305+
let certificate_hash = "certhash123";
306+
let fake_certificate = fake_data::certificate(certificate_hash.to_string());
307+
let mut mock_aggregator_handler = MockAggregatorHandler::new();
308+
let mut mock_verifier = MockVerifier::new();
309+
mock_aggregator_handler
310+
.expect_get_certificate_details()
311+
.return_const(Ok(fake_certificate.clone()))
312+
.once();
313+
mock_aggregator_handler
314+
.expect_unpack_snapshot()
315+
.return_const(Err("an error".to_string()))
316+
.once();
317+
mock_verifier
318+
.expect_verify_multi_signature()
319+
.return_const(Ok(()))
320+
.once();
321+
let mut client = Client::new("testnet".to_string());
322+
client
323+
.with_aggregator_handler(Box::new(mock_aggregator_handler))
324+
.with_verifier(Box::new(mock_verifier));
325+
let restore = client.restore_snapshot(certificate_hash).await;
326+
assert!(restore.is_err(), "an error should have occurred");
327+
}
214328
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
pub const MISSING_AGGREGATOR_HANDLER: &str = "missing aggregator handler";
2+
3+
pub const MISSING_VERIFIER: &str = "missing verifier";

mithril-network/mithril-client/src/main.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod aggregator_fake;
55
mod client;
66
mod entities;
77
mod errors;
8+
mod verifier;
89

910
use clap::{Parser, Subcommand};
1011
use clap_verbosity_flag::{InfoLevel, Verbosity};
@@ -15,6 +16,7 @@ use std::env;
1516
use crate::aggregator::*;
1617
use crate::client::Client;
1718
use crate::entities::Config;
19+
use crate::verifier::*;
1820

1921
/// CLI args
2022
#[derive(Parser)]
@@ -94,12 +96,17 @@ async fn main() {
9496
debug!("{:?}", config);
9597

9698
// Init dependencies
97-
let aggregator_handler =
98-
AggregatorHTTPClient::new(config.network.clone(), config.aggregator_endpoint.clone());
99+
let aggregator_handler = Box::new(AggregatorHTTPClient::new(
100+
config.network.clone(),
101+
config.aggregator_endpoint.clone(),
102+
));
103+
let verifier = Box::new(VerifierImpl::new());
99104

100105
// Init client
101106
let mut client = Client::new(config.network.clone());
102-
client.with_aggregator_handler(aggregator_handler);
107+
client
108+
.with_aggregator_handler(aggregator_handler)
109+
.with_verifier(verifier);
103110

104111
// Execute commands
105112
match &args.command {

0 commit comments

Comments
 (0)