Skip to content
This repository has been archived by the owner on Aug 30, 2022. It is now read-only.

Commit

Permalink
add documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert-Steiner committed Aug 26, 2020
1 parent 70dde9c commit 53a1e81
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 19 deletions.
4 changes: 2 additions & 2 deletions rust/examples/mobile-client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ fn main() -> Result<(), ()> {
// perform the participant task (this function should be triggered regularly on the phone while the
// app is active or in a background task)
fn perform_task(url: &str, bytes: &[u8], model: Model) -> Vec<u8> {
let mut client = MobileClient::deserialize(url, bytes).unwrap();
let mut client = MobileClient::restore(url, bytes).unwrap();
client.set_local_model(model);
client = match client.perform_task() {
client = match client.try_to_proceed() {
Ok(client) => client,
Err((client, _)) => client,
};
Expand Down
10 changes: 0 additions & 10 deletions rust/xaynet-client/src/mobile_client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,16 +252,6 @@ impl ClientState<Sum2> {
}
}

pub async fn get_global_model<T: ApiClient>(api: &mut T) -> Option<Model> {
if let Ok(model) = api.get_model().await {
debug!("fetched global model");
model
} else {
debug!("global model not ready yet");
None
}
}

#[derive(From, Serialize, Deserialize)]
pub enum ClientStateMachine {
Awaiting(ClientState<Awaiting>),
Expand Down
62 changes: 55 additions & 7 deletions rust/xaynet-client/src/mobile_client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ pub mod client;
pub mod participant;

use crate::{
api::HttpApiClient,
api::{ApiClient, HttpApiClient, HttpApiClientError},
mobile_client::{
client::{get_global_model, ClientStateMachine, LocalModel},
client::{ClientStateMachine, LocalModel},
participant::ParticipantSettings,
},
};
Expand All @@ -27,6 +27,9 @@ pub enum MobileClientError {
#[error("failed to initialize runtime: {0}")]
/// Failed to initialize runtime.
Runtime(#[from] std::io::Error),
#[error("failed to request API: {0}")]
/// Failed to request API.
Api(#[from] HttpApiClientError),
}

pub struct MobileClient {
Expand All @@ -36,6 +39,14 @@ pub struct MobileClient {
}

impl MobileClient {
/// Initializes a fresh client. This method only needs to called once.
///
/// To serialize and restore a client, please use the [`MobileClient::serialize`] and
/// [`MobileClient::restore`]
///
/// # Errors
///
/// Fails if the crypto module cannot be initialized.
pub fn init(
url: &str,
participant_settings: ParticipantSettings,
Expand All @@ -50,7 +61,13 @@ impl MobileClient {
Ok(Self::new(url, client_state))
}

pub fn deserialize(url: &str, bytes: &[u8]) -> Result<Self, MobileClientError> {
/// Restores a client from its serialized state.
///
/// # Errors
///
/// Fails if the serialized state is corrupted and the client cannot be restored
/// or if the crypto module cannot be initialized.
pub fn restore(url: &str, bytes: &[u8]) -> Result<Self, MobileClientError> {
let client_state: ClientStateMachine = bincode::deserialize(bytes)?;
Ok(Self::new(url, client_state))
}
Expand All @@ -65,6 +82,13 @@ impl MobileClient {
}
}

/// Serializes the current state of the client.
///
/// # Note
///
/// The serialized state is **not encrypted** and contains sensitive data such as the
/// participant's private key. Therefore, the user of the [`MobileClient`] **must** ensure
/// that the serialized state is stored in a safe place.
pub fn serialize(&self) -> Vec<u8> {
// Safe to unwrap:
//
Expand All @@ -79,13 +103,27 @@ impl MobileClient {
bincode::serialize(&self.client_state).unwrap()
}

/// Fetches and returns the latest global model from the coordinator.
/// Returns `None` if no global model is available.
///
/// # Errors
///
/// Fails if the runtime cannot be initialized or if an API request has failed.
pub fn get_global_model(&mut self) -> Result<Option<Model>, MobileClientError> {
let global_model =
Self::runtime()?.block_on(async { get_global_model(&mut self.api).await });
Ok(global_model)
Self::runtime()?
.block_on(async { self.api.get_model().await })
.map_err(|err| err.into())
}

pub fn perform_task(self) -> Result<Self, (Self, MobileClientError)> {
/// Tries to proceed with the current client task.
/// This will consume the current state of the client and produces a new one.
///
/// # Errors
///
/// Fails if the runtime cannot be initialized.
/// In this case the state of the client remains unchanged and is returned
/// together with the error.
pub fn try_to_proceed(self) -> Result<Self, (Self, MobileClientError)> {
let mut runtime = match Self::runtime() {
Ok(runtime) => runtime,
// We don't want to loose the current client because of a runtime error.
Expand All @@ -109,10 +147,20 @@ impl MobileClient {
})
}

/// Sets the local model.
///
/// The local model is only sent if the client has been selected as an update client.
/// If the client is an update client and no local model is available, the client remains
/// in this state until a local model has been set or a new round has been started by the
/// coordinator.
pub fn set_local_model(&mut self, model: Model) {
self.local_model.set_local_model(model);
}

/// Creates a new participant secret key.
///
/// The secret key is part of the [`ParticipantSettings`] which are required for the first
/// initialization of the client.
pub fn create_participant_secret_key() -> SecretSigningKey {
let SigningKeyPair { secret, .. } = SigningKeyPair::generate();
secret
Expand Down
Empty file removed rust/xaynet-client/src/mod.rs
Empty file.

0 comments on commit 53a1e81

Please sign in to comment.