* Add http option for Participant (#123) * Fix redpallas tests for participant phase 2 (#123) * Update participant/src/comms/http.rs * Remove unnecessary session id for participant round 2 (#123) * Fix clippy error (#123) --------- Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
This commit is contained in:
parent
fb6e8f5e9f
commit
06c0c2453d
|
@ -1378,7 +1378,9 @@ dependencies = [
|
||||||
"message-io",
|
"message-io",
|
||||||
"rand",
|
"rand",
|
||||||
"reddsa",
|
"reddsa",
|
||||||
|
"reqwest",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"server",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2074,6 +2076,7 @@ dependencies = [
|
||||||
"rand",
|
"rand",
|
||||||
"reddsa",
|
"reddsa",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"server",
|
||||||
"tokio",
|
"tokio",
|
||||||
"trusted-dealer",
|
"trusted-dealer",
|
||||||
]
|
]
|
||||||
|
|
|
@ -19,10 +19,6 @@ pub struct Config {
|
||||||
pub identifier: Identifier,
|
pub identifier: Identifier,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Logger {
|
|
||||||
fn log(&mut self, value: String);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validate_inputs(config: &Config) -> Result<(), Error> {
|
fn validate_inputs(config: &Config) -> Result<(), Error> {
|
||||||
if config.min_signers < 2 {
|
if config.min_signers < 2 {
|
||||||
return Err(Error::InvalidMinSigners);
|
return Err(Error::InvalidMinSigners);
|
||||||
|
|
|
@ -17,6 +17,8 @@ serde_json = "1.0"
|
||||||
clap = { version = "4.5.4", features = ["derive"] }
|
clap = { version = "4.5.4", features = ["derive"] }
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
message-io = "0.18"
|
message-io = "0.18"
|
||||||
|
reqwest = { version = "0.11.23", features = ["json"] }
|
||||||
|
server = { path = "../server" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
redpallas = []
|
redpallas = []
|
||||||
|
|
|
@ -9,6 +9,11 @@ pub struct Args {
|
||||||
#[arg(long, default_value_t = false)]
|
#[arg(long, default_value_t = false)]
|
||||||
pub cli: bool,
|
pub cli: bool,
|
||||||
|
|
||||||
|
/// HTTP mode. If enabled, it will use HTTP communication with a
|
||||||
|
/// FROST server.
|
||||||
|
#[arg(long, default_value_t = false)]
|
||||||
|
pub http: bool,
|
||||||
|
|
||||||
/// Public key package to use. Can be a file with a JSON-encoded
|
/// 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,
|
/// package, or "". If the file does not exist or if "" is specified,
|
||||||
/// then it will be read from standard input.
|
/// then it will be read from standard input.
|
||||||
|
@ -22,4 +27,8 @@ pub struct Args {
|
||||||
/// Port to connect to, if using online comms
|
/// Port to connect to, if using online comms
|
||||||
#[arg(short, long, default_value_t = 2744)]
|
#[arg(short, long, default_value_t = 2744)]
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
|
|
||||||
|
/// Optional Session ID
|
||||||
|
#[arg(short, long, default_value = "")]
|
||||||
|
pub session_id: String,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::args::Args;
|
use crate::args::Args;
|
||||||
|
|
||||||
use crate::comms::cli::CLIComms;
|
use crate::comms::cli::CLIComms;
|
||||||
|
use crate::comms::http::HTTPComms;
|
||||||
use crate::comms::socket::SocketComms;
|
use crate::comms::socket::SocketComms;
|
||||||
|
|
||||||
use crate::comms::Comms;
|
use crate::comms::Comms;
|
||||||
|
@ -17,6 +18,8 @@ pub async fn cli(
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut comms: Box<dyn Comms> = if args.cli {
|
let mut comms: Box<dyn Comms> = if args.cli {
|
||||||
Box::new(CLIComms {})
|
Box::new(CLIComms {})
|
||||||
|
} else if args.http {
|
||||||
|
Box::new(HTTPComms::new(args))
|
||||||
} else {
|
} else {
|
||||||
Box::new(SocketComms::new(args))
|
Box::new(SocketComms::new(args))
|
||||||
};
|
};
|
||||||
|
@ -45,7 +48,9 @@ pub async fn cli(
|
||||||
.await?;
|
.await?;
|
||||||
let signature = generate_signature(round_2_config, &key_package, &nonces)?;
|
let signature = generate_signature(round_2_config, &key_package, &nonces)?;
|
||||||
|
|
||||||
comms.send_signature_share(signature).await?;
|
comms
|
||||||
|
.send_signature_share(*key_package.identifier(), signature)
|
||||||
|
.await?;
|
||||||
|
|
||||||
print_values_round_2(signature, logger)?;
|
print_values_round_2(signature, logger)?;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod cli;
|
pub mod cli;
|
||||||
|
pub mod http;
|
||||||
pub mod socket;
|
pub mod socket;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
@ -55,6 +56,7 @@ pub trait Comms {
|
||||||
|
|
||||||
async fn send_signature_share(
|
async fn send_signature_share(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
identifier: Identifier,
|
||||||
signature_share: SignatureShare,
|
signature_share: SignatureShare,
|
||||||
) -> Result<(), Box<dyn Error>>;
|
) -> Result<(), Box<dyn Error>>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@ impl Comms for CLIComms {
|
||||||
|
|
||||||
async fn send_signature_share(
|
async fn send_signature_share(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
_identifier: Identifier,
|
||||||
_signature_share: SignatureShare,
|
_signature_share: SignatureShare,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) -> Result<(), Box<dyn Error>> {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
//! HTTP implementation of the Comms trait.
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
|
#[cfg(not(feature = "redpallas"))]
|
||||||
|
use frost_ed25519 as frost;
|
||||||
|
#[cfg(feature = "redpallas")]
|
||||||
|
use reddsa::frost::redpallas as frost;
|
||||||
|
|
||||||
|
use eyre::eyre;
|
||||||
|
|
||||||
|
use frost::{round1::SigningCommitments, round2::SignatureShare, Identifier};
|
||||||
|
|
||||||
|
use super::{Comms, GenericSigningPackage};
|
||||||
|
|
||||||
|
use std::io::{BufRead, Write};
|
||||||
|
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use crate::args::Args;
|
||||||
|
|
||||||
|
pub struct HTTPComms {
|
||||||
|
client: reqwest::Client,
|
||||||
|
host_port: String,
|
||||||
|
session_id: Uuid,
|
||||||
|
}
|
||||||
|
|
||||||
|
use server::Uuid;
|
||||||
|
|
||||||
|
// TODO: Improve error handling for invalid session id
|
||||||
|
impl HTTPComms {
|
||||||
|
pub fn new(args: &Args) -> Self {
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
Self {
|
||||||
|
client,
|
||||||
|
host_port: format!("http://{}:{}", args.ip, args.port),
|
||||||
|
session_id: Uuid::parse_str(&args.session_id).expect("invalid session id"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait(?Send)]
|
||||||
|
impl Comms for HTTPComms {
|
||||||
|
async fn get_signing_package(
|
||||||
|
&mut self,
|
||||||
|
_input: &mut dyn BufRead,
|
||||||
|
_output: &mut dyn Write,
|
||||||
|
commitments: SigningCommitments,
|
||||||
|
identifier: Identifier,
|
||||||
|
) -> Result<GenericSigningPackage, Box<dyn Error>> {
|
||||||
|
// Send Commitments to Server
|
||||||
|
self.client
|
||||||
|
.post(format!("{}/send_commitments", self.host_port))
|
||||||
|
.json(&server::SendCommitmentsArgs {
|
||||||
|
session_id: self.session_id,
|
||||||
|
identifier,
|
||||||
|
commitments: vec![commitments],
|
||||||
|
})
|
||||||
|
.send()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
eprint!("Waiting for coordinator to send signing package...");
|
||||||
|
|
||||||
|
// Receive SigningPackage from Coordinator
|
||||||
|
|
||||||
|
let r = loop {
|
||||||
|
let r = self
|
||||||
|
.client
|
||||||
|
.post(format!("{}/get_signing_package", self.host_port))
|
||||||
|
.json(&server::GetSigningPackageArgs {
|
||||||
|
session_id: self.session_id,
|
||||||
|
})
|
||||||
|
.send()
|
||||||
|
.await?;
|
||||||
|
if r.status() != 200 {
|
||||||
|
tokio::time::sleep(Duration::from_secs(2)).await;
|
||||||
|
eprint!(".");
|
||||||
|
} else {
|
||||||
|
eprintln!("\nSigning package received");
|
||||||
|
break r.json::<server::GetSigningPackageOutput>().await?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "redpallas")]
|
||||||
|
let signing_package = (
|
||||||
|
r.signing_package
|
||||||
|
.first()
|
||||||
|
.ok_or(eyre!("missing signing package"))
|
||||||
|
.cloned()?,
|
||||||
|
r.randomizer
|
||||||
|
.first()
|
||||||
|
.ok_or(eyre!("missing randomizer"))
|
||||||
|
.cloned()?,
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "redpallas"))]
|
||||||
|
let signing_package = r
|
||||||
|
.signing_package
|
||||||
|
.first()
|
||||||
|
.ok_or(eyre!("missing signing package"))
|
||||||
|
.cloned()?;
|
||||||
|
|
||||||
|
Ok(signing_package)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn send_signature_share(
|
||||||
|
&mut self,
|
||||||
|
identifier: Identifier,
|
||||||
|
signature_share: SignatureShare,
|
||||||
|
) -> Result<(), Box<dyn Error>> {
|
||||||
|
// Send signature share to Coordinator
|
||||||
|
|
||||||
|
eprintln!("Sending signature share to coordinator...");
|
||||||
|
|
||||||
|
let _r = self
|
||||||
|
.client
|
||||||
|
.post(format!("{}/send_signature_share", self.host_port))
|
||||||
|
.json(&server::SendSignatureShareArgs {
|
||||||
|
identifier,
|
||||||
|
session_id: self.session_id,
|
||||||
|
signature_share: vec![signature_share],
|
||||||
|
})
|
||||||
|
.send()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -117,6 +117,7 @@ impl Comms for SocketComms {
|
||||||
|
|
||||||
async fn send_signature_share(
|
async fn send_signature_share(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
_identifier: Identifier,
|
||||||
signature_share: SignatureShare,
|
signature_share: SignatureShare,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) -> Result<(), Box<dyn Error>> {
|
||||||
// Send signature shares to Coordinator
|
// Send signature shares to Coordinator
|
||||||
|
|
|
@ -42,8 +42,9 @@ async fn check_valid_round_1_inputs() {
|
||||||
key_package: "-".to_string(),
|
key_package: "-".to_string(),
|
||||||
ip: "0.0.0.0".to_string(),
|
ip: "0.0.0.0".to_string(),
|
||||||
port: 80,
|
port: 80,
|
||||||
|
session_id: "session-id".to_string(),
|
||||||
|
http: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let input = SECRET_SHARE_JSON;
|
let input = SECRET_SHARE_JSON;
|
||||||
let mut valid_input = input.as_bytes();
|
let mut valid_input = input.as_bytes();
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
use frost::Identifier;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
pub use uuid::Uuid;
|
pub use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -75,8 +76,8 @@ pub struct GetSigningPackageOutput {
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct SendSignatureShareArgs {
|
pub struct SendSignatureShareArgs {
|
||||||
|
pub identifier: Identifier,
|
||||||
pub session_id: Uuid,
|
pub session_id: Uuid,
|
||||||
pub identifier: frost::Identifier,
|
|
||||||
pub signature_share: Vec<frost::round2::SignatureShare>,
|
pub signature_share: Vec<frost::round2::SignatureShare>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -176,8 +176,8 @@ async fn test_main_router() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let res = server
|
let res = server
|
||||||
.post("/send_signature_share")
|
.post("/send_signature_share")
|
||||||
.json(&server::SendSignatureShareArgs {
|
.json(&server::SendSignatureShareArgs {
|
||||||
session_id,
|
|
||||||
identifier: *identifier,
|
identifier: *identifier,
|
||||||
|
session_id,
|
||||||
signature_share,
|
signature_share,
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
|
@ -18,6 +18,7 @@ dkg = { path = "../dkg"}
|
||||||
trusted-dealer = { path = "../trusted-dealer"}
|
trusted-dealer = { path = "../trusted-dealer"}
|
||||||
participant = { path = "../participant"}
|
participant = { path = "../participant"}
|
||||||
coordinator = { path = "../coordinator"}
|
coordinator = { path = "../coordinator"}
|
||||||
|
server = { path = "../server"}
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|
Loading…
Reference in New Issue