Skip to content

Commit

Permalink
addint support to coordinator and participant
Browse files Browse the repository at this point in the history
  • Loading branch information
conradoplg committed Jul 8, 2024
1 parent 35ddb27 commit faa1c30
Show file tree
Hide file tree
Showing 15 changed files with 280 additions and 67 deletions.
15 changes: 15 additions & 0 deletions coordinator/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@ pub struct Args {
#[arg(long, default_value_t = false)]
pub http: bool,

/// The username to use in HTTP mode.
#[arg(short = 'u', long, default_value = "")]
pub username: String,

/// The password to use in HTTP mode. If specified, it will be read from the
/// environment variable with the given name.
#[arg(short = 'w', long, default_value = "")]
pub password: String,

/// The comma-separated usernames of the signers to use in HTTP mode.
/// If HTTP mode is enabled and this is empty, then the session ID
/// will be printed and will have to be shared manually.
#[arg(short = 'S', long, value_delimiter = ',')]
pub signers: Vec<String>,

/// The number of participants. If 0, will prompt for a value.
#[arg(short = 'n', long, default_value_t = 0)]
pub num_signers: u16,
Expand Down
2 changes: 1 addition & 1 deletion coordinator/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub async fn cli<C: RandomizedCiphersuite + 'static>(
let mut comms: Box<dyn Comms<C>> = if args.cli {
Box::new(CLIComms::new())
} else if args.http {
Box::new(HTTPComms::new(args))
Box::new(HTTPComms::new(args)?)
} else {
Box::new(SocketComms::new(args))
};
Expand Down
63 changes: 55 additions & 8 deletions coordinator/src/comms/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use frost::{

use std::{
collections::BTreeMap,
env,
error::Error,
io::{BufRead, Write},
marker::PhantomData,
Expand All @@ -30,18 +31,27 @@ pub struct HTTPComms<C: Ciphersuite> {
client: reqwest::Client,
host_port: String,
session_id: Option<Uuid>,
username: String,
password: String,
access_token: String,
signers: Vec<String>,
_phantom: PhantomData<C>,
}

impl<C: Ciphersuite> HTTPComms<C> {
pub fn new(args: &Args) -> Self {
pub fn new(args: &Args) -> Result<Self, Box<dyn Error>> {
let client = reqwest::Client::new();
Self {
let password = env::var(&args.password).map_err(|_| eyre!("The password argument must specify the name of a environment variable containing the password"))?;
Ok(Self {
client,
host_port: format!("http://{}:{}", args.ip, args.port),
session_id: None,
username: args.username.clone(),
password,
access_token: String::new(),
signers: args.signers.clone(),
_phantom: Default::default(),
}
})
}
}

Expand All @@ -54,11 +64,26 @@ impl<C: Ciphersuite + 'static> Comms<C> for HTTPComms<C> {
_pub_key_package: &PublicKeyPackage<C>,
num_signers: u16,
) -> Result<BTreeMap<Identifier<C>, SigningCommitments<C>>, Box<dyn Error>> {
self.access_token = self
.client
.post(format!("{}/login", self.host_port))
.json(&server::LoginArgs {
username: self.username.clone(),
password: self.password.clone(),
})
.send()
.await?
.json::<server::LoginOutput>()
.await?
.access_token
.to_string();

let r = self
.client
.post(format!("{}/create_new_session", self.host_port))
.bearer_auth(&self.access_token)
.json(&server::CreateNewSessionArgs {
usernames: vec![],
usernames: self.signers.clone(),
num_signers,
message_count: 1,
})
Expand All @@ -67,17 +92,20 @@ impl<C: Ciphersuite + 'static> Comms<C> for HTTPComms<C> {
.json::<server::CreateNewSessionOutput>()
.await?;

eprintln!(
"Send the following session ID to participants: {}",
r.session_id
);
if self.signers.is_empty() {
eprintln!(
"Send the following session ID to participants: {}",
r.session_id
);
}
self.session_id = Some(r.session_id);
eprint!("Waiting for participants to send their commitments...");

let r = loop {
let r = self
.client
.post(format!("{}/get_commitments", self.host_port))
.bearer_auth(&self.access_token)
.json(&server::GetCommitmentsArgs {
session_id: r.session_id,
})
Expand Down Expand Up @@ -116,6 +144,7 @@ impl<C: Ciphersuite + 'static> Comms<C> for HTTPComms<C> {
let _r = self
.client
.post(format!("{}/send_signing_package", self.host_port))
.bearer_auth(&self.access_token)
.json(&server::SendSigningPackageArgs {
aux_msg: Default::default(),
session_id: self.session_id.unwrap(),
Expand All @@ -133,6 +162,7 @@ impl<C: Ciphersuite + 'static> Comms<C> for HTTPComms<C> {
let r = self
.client
.post(format!("{}/get_signature_shares", self.host_port))
.bearer_auth(&self.access_token)
.json(&server::GetSignatureSharesArgs {
session_id: self.session_id.unwrap(),
})
Expand All @@ -147,6 +177,23 @@ impl<C: Ciphersuite + 'static> Comms<C> for HTTPComms<C> {
};
eprintln!();

let _r = self
.client
.post(format!("{}/close_session", self.host_port))
.bearer_auth(&self.access_token)
.json(&server::CloseSessionArgs {
session_id: self.session_id.unwrap(),
})
.send()
.await?;

let _r = self
.client
.post(format!("{}/logout", self.host_port))
.bearer_auth(&self.access_token)
.send()
.await?;

let signature_shares = r
.signature_shares
.first()
Expand Down
4 changes: 3 additions & 1 deletion coordinator/src/step_1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ async fn read_commitments<C: Ciphersuite>(

let pub_key_package: PublicKeyPackage<C> = serde_json::from_str(&out)?;

let num_of_participants = if args.num_signers == 0 {
let num_of_participants = if !args.signers.is_empty() {
args.signers.len() as u16
} else if args.num_signers == 0 {
writeln!(logger, "The number of participants: ")?;

let mut participants = String::new();
Expand Down
9 changes: 9 additions & 0 deletions participant/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ pub struct Args {
#[arg(long, default_value_t = false)]
pub http: bool,

/// The username to use in HTTP mode.
#[arg(short = 'u', long, default_value = "")]
pub username: String,

/// The password to use in HTTP mode. If specified, it will be read from the
/// environment variable with the given name.
#[arg(short = 'w', long, default_value = "")]
pub password: String,

/// Public key package to use. Can be a file with a JSON-encoded
/// package, or "". If the file does not exist or if "" is specified,
/// then it will be read from standard input.
Expand Down
2 changes: 1 addition & 1 deletion participant/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub async fn cli<C: RandomizedCiphersuite + 'static>(
let mut comms: Box<dyn Comms<C>> = if args.cli {
Box::new(CLIComms::new())
} else if args.http {
Box::new(HTTPComms::new(args))
Box::new(HTTPComms::new(args)?)
} else {
Box::new(SocketComms::new(args))
};
Expand Down
72 changes: 62 additions & 10 deletions participant/src/comms/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use frost::{round1::SigningCommitments, round2::SignatureShare, Identifier};

use super::Comms;

use std::env;
use std::io::{BufRead, Write};

use std::error::Error;
Expand All @@ -22,7 +23,10 @@ use crate::args::Args;
pub struct HTTPComms<C: Ciphersuite> {
client: reqwest::Client,
host_port: String,
session_id: Uuid,
session_id: Option<Uuid>,
username: String,
password: String,
access_token: String,
_phantom: PhantomData<C>,
}

Expand All @@ -33,14 +37,18 @@ impl<C> HTTPComms<C>
where
C: Ciphersuite,
{
pub fn new(args: &Args) -> Self {
pub fn new(args: &Args) -> Result<Self, Box<dyn Error>> {
let client = reqwest::Client::new();
Self {
let password = env::var(&args.password).map_err(|_| eyre!("The password argument must specify the name of a environment variable containing the password"))?;
Ok(Self {
client,
host_port: format!("http://{}:{}", args.ip, args.port),
session_id: Uuid::parse_str(&args.session_id).expect("invalid session id"),
session_id: Uuid::parse_str(&args.session_id).ok(),
username: args.username.clone(),
password,
access_token: String::new(),
_phantom: Default::default(),
}
})
}
}

Expand All @@ -63,11 +71,48 @@ where
),
Box<dyn Error>,
> {
self.access_token = self
.client
.post(format!("{}/login", self.host_port))
.json(&server::LoginArgs {
username: self.username.clone(),
password: self.password.clone(),
})
.send()
.await?
.json::<server::LoginOutput>()
.await?
.access_token
.to_string();

let session_id = match self.session_id {
Some(s) => s,
None => {
// Get session ID from server
let r = self
.client
.post(format!("{}/list_sessions", self.host_port))
.bearer_auth(&self.access_token)
.send()
.await?
.json::<server::ListSessionsOutput>()
.await?;
if r.session_ids.len() > 1 {
return Err(eyre!("user has more than one FROST session active, which is still not supported by this tool").into());
} else if r.session_ids.is_empty() {
return Err(eyre!("User has no current session actives. The Coordinator should either specify your username, or manually share the session ID which you can specify with --session_id").into());
}
r.session_ids[0]
}
};
self.session_id = Some(session_id);

// Send Commitments to Server
self.client
.post(format!("{}/send_commitments", self.host_port))
.bearer_auth(&self.access_token)
.json(&server::SendCommitmentsArgs {
session_id: self.session_id,
session_id,
identifier: identifier.into(),
commitments: vec![(&commitments).try_into()?],
})
Expand All @@ -82,9 +127,8 @@ where
let r = self
.client
.post(format!("{}/get_signing_package", self.host_port))
.json(&server::GetSigningPackageArgs {
session_id: self.session_id,
})
.bearer_auth(&self.access_token)
.json(&server::GetSigningPackageArgs { session_id })
.send()
.await?;
if r.status() != 200 {
Expand Down Expand Up @@ -126,14 +170,22 @@ where
let _r = self
.client
.post(format!("{}/send_signature_share", self.host_port))
.bearer_auth(&self.access_token)
.json(&server::SendSignatureShareArgs {
identifier: identifier.into(),
session_id: self.session_id,
session_id: self.session_id.unwrap(),
signature_share: vec![signature_share.into()],
})
.send()
.await?;

let _r = self
.client
.post(format!("{}/logout", self.host_port))
.bearer_auth(&self.access_token)
.send()
.await?;

Ok(())
}
}
2 changes: 2 additions & 0 deletions participant/src/tests/round1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ async fn check_valid_round_1_inputs() {
port: 80,
session_id: "session-id".to_string(),
http: false,
username: "".to_string(),
password: "".to_string(),
};
let input = SECRET_SHARE_JSON;
let mut valid_input = input.as_bytes();
Expand Down
3 changes: 2 additions & 1 deletion server/migrations/20240627222152_init.down.sql
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
-- Add down migration script here
drop table if exists users;
drop table if exists users;
drop table if exists access_tokens;
11 changes: 9 additions & 2 deletions server/migrations/20240627222152_init.up.sql
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ create table if not exists users
id integer primary key not null,
username text not null unique,
password text not null,
pubkey blob not null,
access_token blob null
pubkey blob not null
);

create table if not exists access_tokens
(
id integer primary key not null,
user_id integer not null,
access_token blob not null,
foreign key(user_id) references users(id) on delete cascade
);
Loading

0 comments on commit faa1c30

Please sign in to comment.