Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trusted Setup client binaries #257

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
- [\#257](https://github.com/Manta-Network/manta-rs/pull/257) Add client binaries for the trusted setup
- [\#238](https://github.com/Manta-Network/manta-rs/pull/238) Add trusted setup ceremony primitives for server and client
- [\#237](https://github.com/Manta-Network/manta-rs/pull/237) Public input fuzzing tests for transfer protocol
- [\#215](https://github.com/Manta-Network/manta-rs/pull/215) Add windowed multiplication algorithm for groups
Expand Down
14 changes: 14 additions & 0 deletions manta-crypto/src/arkworks/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,17 @@ where
let bytes: Vec<u8> = Deserialize::deserialize(deserializer)?;
CanonicalDeserialize::deserialize(bytes.as_slice()).map_err(de::Error::custom)
}

/// Deserializes data of type `T` using the [`CanonicalDeserialize`] format with `D` as the
/// [`Deserializer`] without checking for correctness.
#[cfg(feature = "serde")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
#[inline]
pub fn canonical_deserialize_unchecked<'de, D, T>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
T: CanonicalDeserialize,
{
let bytes: Vec<u8> = Deserialize::deserialize(deserializer)?;
CanonicalDeserialize::deserialize_unchecked(bytes.as_slice()).map_err(de::Error::custom)
}
6 changes: 6 additions & 0 deletions manta-trusted-setup/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ is-it-maintained-issue-resolution = { repository = "Manta-Network/manta-rs" }
is-it-maintained-open-issues = { repository = "Manta-Network/manta-rs" }
maintenance = { status = "actively-developed" }

[[bin]]
name = "groth16_phase2_client"
required-features = ["bincode", "clap", "csv", "ppot", "tokio"]

[features]
# Bincode for Message Signing
bincode = ["dep:bincode", "serde"]
Expand Down Expand Up @@ -58,6 +62,7 @@ ark-std = { version = "0.3.0", default-features = false }
bincode = { version = "1.3.3", optional = true, default-features = false }
blake2 = { version = "0.10.4", default-features = false }
bs58 = { version = "0.4", default-features = false, features = ["alloc"] }
clap = { version = "3.2.22", optional = true, default-features = false, features = ["color", "derive", "std", "suggestions", "unicode", "wrap_help"] }
colored = { version = "2.0.0", default-features = false }
console = { version = "0.15.1", default-features = false }
csv = { version = "1.1.6", optional = true, default-features = false }
Expand All @@ -67,6 +72,7 @@ manta-crypto = { path = "../manta-crypto", default-features = false, features =
manta-util = { path = "../manta-util", default-features = false, features = ["reqwest"] }
parking_lot = { version = "0.12.1", default-features = false }
tiny-bip39 = { version = "1.0.0", default-features = false }
tokio = { version = "1.21.1", optional = true, default-features = false, features = ["rt-multi-thread"] }

[dev-dependencies]
ark-snark = { version = "0.3.0", default-features = false }
Expand Down
99 changes: 99 additions & 0 deletions manta-trusted-setup/src/bin/groth16_phase2_client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright 2019-2022 Manta Network.
// This file is part of manta-rs.
//
// manta-rs 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-rs 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-rs. If not, see <http://www.gnu.org/licenses/>.

//! Trusted Setup Ceremony Client

extern crate alloc;

use clap::{Parser, Subcommand};
use dialoguer::{theme::ColorfulTheme, Input};
use manta_trusted_setup::groth16::ceremony::{
config::ppot::{client_contribute, exit_on_error, get_client_keys, register, Config},
CeremonyError,
};

/// Welcome Message
pub const TITLE: &str = r"
__ __ _ _______ _ _ _____ _
| \/ | | | |__ __| | | | | / ____| | |
| \ / | __ _ _ __ | |_ __ _ | |_ __ _ _ ___| |_ ___ __| | | (___ ___| |_ _ _ _ __
| |\/| |/ _` | '_ \| __/ _` | | | '__| | | / __| __/ _ \/ _` | \___ \ / _ | __| | | | '_ \
| | | | (_| | | | | || (_| | | | | | |_| \__ | || __| (_| | ____) | __| |_| |_| | |_) |
|_| |_|\__,_|_| |_|\__\__,_| |_|_| \__,_|___/\__\___|\__,_| |_____/ \___|\__|\__,_| .__/
| |
|_|
";

/// Command
#[derive(Debug, Subcommand)]
pub enum Command {
/// Register for the Trusted Setup Ceremony
Register,

/// Runs the Trusted Setup Ceremony as a Contributor
Contribute,
}

/// Command Line Arguments
#[derive(Debug, Parser)]
pub struct Arguments {
/// Command
#[clap(subcommand)]
command: Command,
}

impl Arguments {
/// Takes command line arguments and executes the corresponding operations.
#[inline]
pub fn run(self) -> Result<(), CeremonyError<Config>> {
println!("{}", TITLE);
match self.command {
Command::Register => {
let twitter_account = Input::with_theme(&ColorfulTheme::default())
.with_prompt("Your twitter account")
.interact_text()
.expect("");
let email = Input::with_theme(&ColorfulTheme::default())
.with_prompt("Your email")
.interact_text()
.expect("");
register(twitter_account, email);
Ok(())
}
Command::Contribute => {
let (sk, pk) = match get_client_keys() {
Ok(keys) => keys,
Err(e) => panic!("Error while extracting the client keys: {}", e),
};
match tokio::runtime::Builder::new_multi_thread()
.worker_threads(4)
.enable_io()
.enable_time()
.build()
{
Ok(runtime) => {
runtime.block_on(async { client_contribute::<Config>(sk, pk).await })
}
Err(e) => panic!("I/O Error while setting up the tokio Runtime: {:?}", e),
}
}
}
}
}

fn main() {
exit_on_error(Arguments::parse().run());
}
72 changes: 50 additions & 22 deletions manta-trusted-setup/src/groth16/ceremony/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,21 @@ use crate::{
ceremony::signature::{SignedMessage, Signer},
groth16::{
ceremony::{
message::{ContributeRequest, QueryRequest, QueryResponse},
message::{ContributeRequest, ContributeResponse, QueryRequest, QueryResponse},
Ceremony, CeremonyError, Metadata, Round, UnexpectedError,
},
mpc,
},
};
use alloc::vec::Vec;
use console::Term;
use manta_crypto::rand::OsRng;
use manta_util::{
http::reqwest::{self, IntoUrl, KnownUrlClient},
ops::ControlFlow,
serde::{de::DeserializeOwned, Serialize},
};
use tokio::time::{sleep, Duration};

/// Converts the [`reqwest`] error `err` into a [`CeremonyError`] depending on whether it comes from
/// a timeout or other network error.
Expand All @@ -47,16 +50,19 @@ where
}
}

/// Client Update States
/// Client Continuation States
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Update {
pub enum Continue {
/// Position Updated
Position(u64),

/// Timeout
Timeout,
}

/// Client Update States
pub type Update<C> = ControlFlow<ContributeResponse<C>, Continue>;

/// Client
pub struct Client<C>
where
Expand Down Expand Up @@ -130,10 +136,28 @@ where
C::Identifier: Serialize,
C::Nonce: DeserializeOwned,
{
let (metadata, nonce) = client
let mut client_data = client
.post("start", &identifier)
.await
.map_err(into_ceremony_error)?;
.map_err(into_ceremony_error);
let term = Term::stdout();
let mut counter = 0u8;
println!("Connecting to server for Metadata");
while let Err(CeremonyError::NotRegistered) = client_data {
if counter >= 60 {
panic!("This is taking longer than expected, please try again later.");
}
term.clear_last_lines(1)
.expect("Clear last lines should succeed.");
println!("Waiting for server registry update. Please make sure you are registered.");
sleep(Duration::from_millis(10000)).await;
client_data = client
.post("start", &identifier)
.await
.map_err(into_ceremony_error);
counter += 1;
}
let (metadata, nonce) = client_data?;
Ok(Self::new_unchecked(
Signer::new(nonce, signing_key, identifier),
client,
Expand Down Expand Up @@ -172,12 +196,13 @@ where
&mut self,
hasher: &C::Hasher,
mut round: Round<C>,
) -> Result<(), CeremonyError<C>>
) -> Result<ContributeResponse<C>, CeremonyError<C>>
where
C::Identifier: Serialize,
C::Nonce: Serialize,
C::Signature: Serialize,
ContributeRequest<C>: Serialize,
ContributeResponse<C>: DeserializeOwned,
{
let mut rng = OsRng;
let mut proof = Vec::new();
Expand All @@ -193,59 +218,62 @@ where
proof,
})?;
self.client
.post("update", &signed_message)
.post("contribute", &signed_message)
.await
.map_err(into_ceremony_error)
}

/// Tries to contribute to the ceremony if at the front of the queue. This method returns an
/// optional [`Update`] if the status of the unfinalized participant has changed. If the result
/// is `Ok(None)` then the ceremony contribution was successful.
/// [`Update`] if the status of the unfinalized participant has changed. If the result
/// is `Ok(Response::Break)` then the ceremony contribution was successful and the success
/// response is returned
#[inline]
pub async fn try_contribute(&mut self) -> Result<Option<Update>, CeremonyError<C>>
pub async fn try_contribute(&mut self) -> Result<Update<C>, CeremonyError<C>>
where
C::Identifier: Serialize,
C::Nonce: Serialize,
C::Signature: Serialize,
ContributeRequest<C>: Serialize,
QueryResponse<C>: DeserializeOwned,
ContributeRequest<C>: Serialize,
ContributeResponse<C>: DeserializeOwned,
{
let state = match self.query().await {
Ok(QueryResponse::State(state)) => state,
Ok(QueryResponse::QueuePosition(position)) => {
return Ok(Some(Update::Position(position)))
return Ok(Update::Continue(Continue::Position(position)))
}
Err(CeremonyError::Timeout) => return Ok(Some(Update::Timeout)),
Err(CeremonyError::Timeout) => return Ok(Update::Continue(Continue::Timeout)),
Err(err) => return Err(err),
};
match self.contribute(&C::Hasher::default(), state).await {
Ok(_) => Ok(None),
Ok(response) => Ok(Update::Break(response)),
Err(CeremonyError::Timeout) | Err(CeremonyError::NotYourTurn) => {
Ok(Some(Update::Timeout))
Ok(Update::Continue(Continue::Timeout))
}
Err(err) => Err(err),
}
}
}

/// Runs the contribution protocol for `signing_key`, `identifier`, and `server_url`, using
/// `process_update` as the callback for processing [`Update`] messages from the client.
/// `process_continuation` as the callback for processing [`Continue`] messages from the client.
#[inline]
pub async fn contribute<C, U, F>(
signing_key: C::SigningKey,
identifier: C::Identifier,
server_url: U,
mut process_update: F,
) -> Result<(), CeremonyError<C>>
mut process_continuation: F,
) -> Result<ContributeResponse<C>, CeremonyError<C>>
where
C: Ceremony,
C::Identifier: Serialize,
C::Nonce: DeserializeOwned + Serialize,
C::Signature: Serialize,
ContributeRequest<C>: Serialize,
QueryResponse<C>: DeserializeOwned,
ContributeRequest<C>: Serialize,
ContributeResponse<C>: DeserializeOwned,
U: IntoUrl,
F: FnMut(Update),
F: FnMut(&Metadata, Continue),
{
let mut client = Client::build(
signing_key,
Expand All @@ -255,8 +283,8 @@ where
.await?;
loop {
match client.try_contribute().await {
Ok(Some(update)) => process_update(update),
Ok(None) => return Ok(()),
Ok(Update::Continue(update)) => process_continuation(&client.metadata, update),
Ok(Update::Break(response)) => return Ok(response),
Err(CeremonyError::InvalidSignature { expected_nonce }) => {
client.update_nonce(expected_nonce)?;
}
Expand Down
4 changes: 2 additions & 2 deletions manta-trusted-setup/src/groth16/ceremony/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@

//! Groth16 Trusted Setup Ceremony Configurations

#[cfg(feature = "csv")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "csv")))]
#[cfg(all(feature = "csv", feature = "ppot"))]
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "csv", feature = "ppot"))))]
pub mod ppot;
Loading