Skip to content

Commit

Permalink
Add storage abstractions and add server storage hook (#154)
Browse files Browse the repository at this point in the history
* feat: add storage abstractions and add server storage hook
* chore: add CHANGELOG entry
* feat: add optimized README image
* chore: update manta-rs dependencies

Signed-off-by: Brandon H. Gomes <bhgomes@pm.me>
  • Loading branch information
bhgomes committed Jul 29, 2022
1 parent 861563f commit 0e807a0
Show file tree
Hide file tree
Showing 12 changed files with 464 additions and 323 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]
### Added
- [\#154](https://github.com/Manta-Network/manta-signer/pull/154) Add storage abstractions and add server storage hook

### Changed

Expand Down
10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ derivative = { version = "2.2.0", default-features = false, features = ["use_cor
dirs-next = { version = "2.0.0", default-features = false }
futures = { version = "0.3.17", default-features = false, features = ["alloc"] }
http-types = { version = "2.12.0", default-features = false }
manta-accounting = { git = "https://github.com/manta-network/manta-rs", tag = "v0.5.3", default-features = false, features = ["cocoon-fs"] }
manta-crypto = { git = "https://github.com/manta-network/manta-rs", tag = "v0.5.3", default-features = false, features = ["getrandom"] }
manta-parameters = { git = "https://github.com/manta-network/manta-rs", tag = "v0.5.3", default-features = false, features = ["download"] }
manta-pay = { git = "https://github.com/manta-network/manta-rs", tag = "v0.5.3", default-features = false, features = ["bs58", "groth16", "serde", "wallet"] }
manta-util = { git = "https://github.com/manta-network/manta-rs", tag = "v0.5.3", default-features = false }
manta-accounting = { git = "https://github.com/manta-network/manta-rs", tag = "v0.5.4", default-features = false, features = ["cocoon-fs"] }
manta-crypto = { git = "https://github.com/manta-network/manta-rs", tag = "v0.5.4", default-features = false, features = ["getrandom"] }
manta-parameters = { git = "https://github.com/manta-network/manta-rs", tag = "v0.5.4", default-features = false, features = ["download"] }
manta-pay = { git = "https://github.com/manta-network/manta-rs", tag = "v0.5.4", default-features = false, features = ["bs58", "groth16", "serde", "wallet"] }
manta-util = { git = "https://github.com/manta-network/manta-rs", tag = "v0.5.4", default-features = false }
parking_lot = { version = "0.12.1", default-features = false }
password-hash = { version = "0.4.2", default-features = false, features = ["alloc"] }
secrecy = { version = "0.8.0", default-features = false, features = ["alloc"] }
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

`manta-signer` is manta's native client that **turbo charges** zero-knowledge-proof generation.

<img width="655" src="https://user-images.githubusercontent.com/720571/142786609-ce7455e1-dbe7-4a6d-8a78-4aa22984a3d7.png">
<p align="center">
<img width="655" src="./mac-installation.png">
</p>

**Disclaimer: `manta-signer` is experimental software, use it at your own risk.**

Expand Down
7 changes: 5 additions & 2 deletions examples/test_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use manta_crypto::rand::{CryptoRng, OsRng, RngCore, Sample};
use manta_signer::{
config::Config,
secret::{Authorizer, Password, PasswordFuture, SecretString},
service::{self, Error},
service::{Error, Server},
};

/// Mock User
Expand Down Expand Up @@ -58,5 +58,8 @@ async fn main() -> Result<(), Error> {
if let Some(url) = std::env::args().nth(1) {
config.service_url = url;
}
service::start(config, MockUser::new(&mut OsRng)).await
Server::build(config, MockUser::new(&mut OsRng))
.await?
.start()
.await
}
Binary file added mac-installation.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
63 changes: 63 additions & 0 deletions src/http.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2019-2022 Manta Network.
// This file is part of manta-signer.
//
// manta-signer is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// manta-signer is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with manta-signer. If not, see <http://www.gnu.org/licenses/>.

//! Manta Signer HTTP Utilities

use crate::serde::{de::DeserializeOwned, Serialize};
use core::future::Future;

pub use tide::{Body, Error, Request, Response, Server, StatusCode};

/// Generates the JSON body for the output of `f`, returning an HTTP reponse.
#[inline]
pub async fn into_body<R, E, F, Fut>(f: F) -> Result<Response, Error>
where
R: Serialize,
E: Into<Error>,
F: FnOnce() -> Fut,
Fut: Future<Output = Result<R, E>>,
{
Ok(Body::from_json(&f().await.map_err(Into::into)?)?.into())
}

/// Executes `f` on the incoming `request`.
#[inline]
pub async fn execute<S, T, R, E, F, Fut>(mut request: Request<S>, f: F) -> Result<Response, Error>
where
S: Clone,
T: DeserializeOwned,
R: Serialize,
E: Into<Error>,
F: FnOnce(S, T) -> Fut,
Fut: Future<Output = Result<R, E>>,
{
let args = request.body_json::<T>().await?;
into_body(move || async move { f(request.state().clone(), args).await }).await
}

/// Registers a `POST` command with the given `path` and execution `f`.
#[inline]
pub fn register_post<S, T, R, E, F, Fut>(api: &mut Server<S>, path: &'static str, f: F)
where
S: Clone + Send + Sync + 'static,
T: DeserializeOwned + Send + 'static,
R: Serialize + 'static,
E: Into<Error> + 'static,
F: Clone + Send + Sync + 'static + Fn(S, T) -> Fut,
Fut: Future<Output = Result<R, E>> + Send + 'static,
{
api.at(path).post(move |r| execute(r, f.clone()));
}
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@
#![forbid(rustdoc::broken_intra_doc_links)]
#![forbid(missing_docs)]

extern crate alloc;

pub mod config;
pub mod http;
pub mod log;
pub mod parameters;
pub mod secret;
pub mod service;
pub mod storage;

#[doc(inline)]
pub use manta_util::serde;
Expand Down
90 changes: 88 additions & 2 deletions src/secret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use crate::config::Setup;
use futures::future::BoxFuture;
use manta_util::serde::Serialize;
use password_hash::{PasswordHashString, SaltString};
use tokio::sync::mpsc::{channel, Receiver, Sender};

pub use password_hash::{Error as PasswordHashError, PasswordHasher, PasswordVerifier};
pub use secrecy::{ExposeSecret, Secret, SecretString};
Expand Down Expand Up @@ -95,9 +96,9 @@ pub trait Authorizer: 'static + Send {
/// # Implementation Note
///
/// For custom service implementations, this method should be called before any service is run.
/// The [`service::start`] function already calls this method internally.
/// The [`Server::start`] function already calls this method internally.
///
/// [`service::start`]: crate::service::start
/// [`Server::start`]: crate::service::Server::start
#[inline]
fn setup<'s>(&'s mut self, setup: &'s Setup) -> UnitFuture<'s> {
let _ = setup;
Expand Down Expand Up @@ -198,3 +199,88 @@ where
.to_owned()
}
}

/// Password Sender
pub struct PasswordSender {
/// Password Sender
pub password: Sender<Password>,

/// Retry Receiver
pub retry: Receiver<bool>,
}

impl PasswordSender {
/// Builds a new [`PasswordSender`] from `password` and `retry`.
#[inline]
pub fn new(password: Sender<Password>, retry: Receiver<bool>) -> Self {
Self { password, retry }
}

/// Loads the password with `password` waiting for a retry message.
#[inline]
pub async fn load(&mut self, password: SecretString) -> bool {
self.load_exact(password).await;
self.retry
.recv()
.await
.expect("Failed to receive retry message.")
}

/// Loads the password with `password` without requesting a retry message.
#[inline]
pub async fn load_exact(&mut self, password: SecretString) {
let _ = self.password.send(Password::from_known(password)).await;
}

/// Clears the currently stored password.
#[inline]
pub async fn clear(&self) {
let _ = self.password.send(Password::from_unknown()).await;
}
}

/// Password Receiver
pub struct PasswordReceiver {
/// Password Receiver
pub password: Receiver<Password>,

/// Retry Sender
pub retry: Sender<bool>,
}

impl PasswordReceiver {
/// Builds a new [`PasswordReceiver`] from `password` and `retry`.
#[inline]
pub fn new(password: Receiver<Password>, retry: Sender<bool>) -> Self {
Self { password, retry }
}

/// Sends the message `retry` across the retry channel.
#[inline]
pub async fn should_retry(&mut self, retry: bool) {
self.retry
.send(retry)
.await
.expect("Failed to send retry message.");
}

/// Loads the password from the password channel.
#[inline]
pub async fn password(&mut self) -> Password {
self.password
.recv()
.await
.expect("Failed to receive password message.")
}
}

/// Generates a new password-sending channel.
#[inline]
pub fn password_channel() -> (PasswordSender, PasswordReceiver) {
let (password_sender, password_receiver) = channel(1);
let (retry_sender, retry_receiver) = channel(1);
(
PasswordSender::new(password_sender, retry_receiver),
PasswordReceiver::new(password_receiver, retry_sender),
)
}

1 comment on commit 0e807a0

@vercel
Copy link

@vercel vercel bot commented on 0e807a0 Jul 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.