clean up reading, writing and error handling
This commit is contained in:
parent
d9e7df2365
commit
02910565bf
118
dkg/src/cli.rs
118
dkg/src/cli.rs
|
@ -1,35 +1,17 @@
|
||||||
use frost::keys::dkg::{round1, round2};
|
use frost::keys::dkg::{round1, round2};
|
||||||
use frost::{Error, Identifier};
|
use frost::Identifier;
|
||||||
use frost_ed25519 as frost;
|
use frost_ed25519 as frost;
|
||||||
use rand::thread_rng;
|
use rand::thread_rng;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io;
|
use std::io::{BufRead, Write};
|
||||||
|
|
||||||
use crate::inputs::{read_round1_package, read_round2_package, request_inputs};
|
use crate::inputs::{read_round1_package, read_round2_package, request_inputs};
|
||||||
use crate::output::Logger;
|
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
pub fn cli(
|
||||||
pub enum CliError {
|
reader: &mut impl BufRead,
|
||||||
Config,
|
logger: &mut impl Write,
|
||||||
Keygen,
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
}
|
let config = request_inputs(reader, logger)?;
|
||||||
|
|
||||||
pub struct TrustedDealerError {
|
|
||||||
pub frost_error: Error,
|
|
||||||
pub cli_error: CliError,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cli() -> Result<(), TrustedDealerError> {
|
|
||||||
let mut reader = Box::new(io::stdin().lock());
|
|
||||||
let config = request_inputs(&mut reader);
|
|
||||||
if let Err(e) = config {
|
|
||||||
return Err(TrustedDealerError {
|
|
||||||
frost_error: e,
|
|
||||||
cli_error: CliError::Config,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let config = config.unwrap();
|
|
||||||
|
|
||||||
let rng = thread_rng();
|
let rng = thread_rng();
|
||||||
|
|
||||||
|
@ -38,106 +20,80 @@ pub fn cli() -> Result<(), TrustedDealerError> {
|
||||||
config.max_signers,
|
config.max_signers,
|
||||||
config.min_signers,
|
config.min_signers,
|
||||||
rng,
|
rng,
|
||||||
)
|
)?;
|
||||||
.map_err(|e| TrustedDealerError {
|
|
||||||
frost_error: e,
|
|
||||||
cli_error: CliError::Keygen,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let mut console_logger = ConsoleLogger::default();
|
writeln!(logger, "\n=== ROUND 1: SEND PACKAGES ===\n")?;
|
||||||
|
|
||||||
console_logger.log("\n=== ROUND 1: SEND PACKAGES ===\n".to_string());
|
writeln!(
|
||||||
|
logger,
|
||||||
console_logger.log(format!(
|
|
||||||
"Round 1 Package to send to all other participants (your identifier: {}):\n\n{}\n",
|
"Round 1 Package to send to all other participants (your identifier: {}):\n\n{}\n",
|
||||||
serde_json::to_string(&config.identifier).unwrap(),
|
serde_json::to_string(&config.identifier).unwrap(),
|
||||||
serde_json::to_string(&package).unwrap()
|
serde_json::to_string(&package).unwrap()
|
||||||
));
|
)?;
|
||||||
|
|
||||||
console_logger.log("=== ROUND 1: RECEIVE PACKAGES ===\n".to_string());
|
writeln!(logger, "=== ROUND 1: RECEIVE PACKAGES ===\n")?;
|
||||||
|
|
||||||
console_logger.log(format!(
|
writeln!(
|
||||||
|
logger,
|
||||||
"Input Round 1 Packages from the other {} participants.\n",
|
"Input Round 1 Packages from the other {} participants.\n",
|
||||||
config.max_signers - 1,
|
config.max_signers - 1,
|
||||||
));
|
)?;
|
||||||
let mut received_round1_packages: HashMap<Identifier, round1::Package> = HashMap::new();
|
let mut received_round1_packages: HashMap<Identifier, round1::Package> = HashMap::new();
|
||||||
for _ in 0..config.max_signers - 1 {
|
for _ in 0..config.max_signers - 1 {
|
||||||
let (identifier, round1_package) =
|
let (identifier, round1_package) = read_round1_package(reader, logger)?;
|
||||||
read_round1_package(&mut reader).map_err(|e| TrustedDealerError {
|
|
||||||
frost_error: e,
|
|
||||||
cli_error: CliError::Keygen,
|
|
||||||
})?;
|
|
||||||
received_round1_packages.insert(identifier, round1_package);
|
received_round1_packages.insert(identifier, round1_package);
|
||||||
console_logger.log("".to_string());
|
writeln!(logger)?;
|
||||||
}
|
}
|
||||||
let received_round1_packages = received_round1_packages.into_values().collect::<Vec<_>>();
|
let received_round1_packages = received_round1_packages.into_values().collect::<Vec<_>>();
|
||||||
|
|
||||||
let (round2_secret_package, round2_packages) =
|
let (round2_secret_package, round2_packages) =
|
||||||
frost::keys::dkg::part2(secret_package, &received_round1_packages).map_err(|e| {
|
frost::keys::dkg::part2(secret_package, &received_round1_packages)?;
|
||||||
TrustedDealerError {
|
|
||||||
frost_error: e,
|
|
||||||
cli_error: CliError::Keygen,
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
console_logger.log("=== ROUND 2: SEND PACKAGES ===\n".to_string());
|
writeln!(logger, "=== ROUND 2: SEND PACKAGES ===\n")?;
|
||||||
|
|
||||||
for package in round2_packages {
|
for package in round2_packages {
|
||||||
console_logger.log(format!(
|
writeln!(
|
||||||
|
logger,
|
||||||
"Round 2 Package to send to participant {} (your identifier: {}):\n\n{}\n",
|
"Round 2 Package to send to participant {} (your identifier: {}):\n\n{}\n",
|
||||||
serde_json::to_string(package.receiver_identifier()).unwrap(),
|
serde_json::to_string(package.receiver_identifier()).unwrap(),
|
||||||
serde_json::to_string(&config.identifier).unwrap(),
|
serde_json::to_string(&config.identifier).unwrap(),
|
||||||
serde_json::to_string(&package).unwrap()
|
serde_json::to_string(&package).unwrap()
|
||||||
));
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
console_logger.log("=== ROUND 2: RECEIVE PACKAGES ===\n".to_string());
|
writeln!(logger, "=== ROUND 2: RECEIVE PACKAGES ===\n")?;
|
||||||
|
|
||||||
console_logger.log(format!(
|
writeln!(
|
||||||
|
logger,
|
||||||
"Input Round 2 Packages from the other {} participants.\n",
|
"Input Round 2 Packages from the other {} participants.\n",
|
||||||
config.max_signers - 1,
|
config.max_signers - 1,
|
||||||
));
|
)?;
|
||||||
let mut received_round2_packages: HashMap<Identifier, round2::Package> = HashMap::new();
|
let mut received_round2_packages: HashMap<Identifier, round2::Package> = HashMap::new();
|
||||||
for _ in 0..config.max_signers - 1 {
|
for _ in 0..config.max_signers - 1 {
|
||||||
let (identifier, round2_package) =
|
let (identifier, round2_package) = read_round2_package(reader, logger)?;
|
||||||
read_round2_package(&mut reader).map_err(|e| TrustedDealerError {
|
|
||||||
frost_error: e,
|
|
||||||
cli_error: CliError::Keygen,
|
|
||||||
})?;
|
|
||||||
received_round2_packages.insert(identifier, round2_package);
|
received_round2_packages.insert(identifier, round2_package);
|
||||||
console_logger.log("".to_string());
|
writeln!(logger)?;
|
||||||
}
|
}
|
||||||
let received_round2_packages = received_round2_packages.into_values().collect::<Vec<_>>();
|
let received_round2_packages = received_round2_packages.into_values().collect::<Vec<_>>();
|
||||||
|
|
||||||
console_logger.log("=== DKG FINISHED ===".to_string());
|
writeln!(logger, "=== DKG FINISHED ===")?;
|
||||||
|
|
||||||
let (key_package, public_key_package) = frost::keys::dkg::part3(
|
let (key_package, public_key_package) = frost::keys::dkg::part3(
|
||||||
&round2_secret_package,
|
&round2_secret_package,
|
||||||
&received_round1_packages,
|
&received_round1_packages,
|
||||||
&received_round2_packages,
|
&received_round2_packages,
|
||||||
)
|
)?;
|
||||||
.map_err(|e| TrustedDealerError {
|
|
||||||
frost_error: e,
|
|
||||||
cli_error: CliError::Keygen,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
console_logger.log(format!(
|
writeln!(
|
||||||
|
logger,
|
||||||
"Participant key package:\n\n{}\n",
|
"Participant key package:\n\n{}\n",
|
||||||
serde_json::to_string(&key_package).unwrap(),
|
serde_json::to_string(&key_package).unwrap(),
|
||||||
));
|
)?;
|
||||||
console_logger.log(format!(
|
writeln!(
|
||||||
|
logger,
|
||||||
"Partcipant public key package:\n\n{}\n",
|
"Partcipant public key package:\n\n{}\n",
|
||||||
serde_json::to_string(&public_key_package).unwrap(),
|
serde_json::to_string(&public_key_package).unwrap(),
|
||||||
));
|
)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct ConsoleLogger;
|
|
||||||
|
|
||||||
impl Logger for ConsoleLogger {
|
|
||||||
fn log(&mut self, value: String) {
|
|
||||||
println!("{}", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ use frost::{
|
||||||
Error, Identifier,
|
Error, Identifier,
|
||||||
};
|
};
|
||||||
use frost_ed25519 as frost;
|
use frost_ed25519 as frost;
|
||||||
use std::io::BufRead;
|
use std::io::{BufRead, Write};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
@ -12,6 +12,10 @@ 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);
|
||||||
|
@ -28,8 +32,11 @@ fn validate_inputs(config: &Config) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request_inputs(input: &mut impl BufRead) -> Result<Config, Error> {
|
pub fn request_inputs(
|
||||||
println!("The minimum number of signers: (2 or more)");
|
input: &mut impl BufRead,
|
||||||
|
logger: &mut dyn Write,
|
||||||
|
) -> Result<Config, Box<dyn std::error::Error>> {
|
||||||
|
writeln!(logger, "The minimum number of signers: (2 or more)")?;
|
||||||
|
|
||||||
let mut min = String::new();
|
let mut min = String::new();
|
||||||
input.read_line(&mut min).unwrap();
|
input.read_line(&mut min).unwrap();
|
||||||
|
@ -39,7 +46,7 @@ pub fn request_inputs(input: &mut impl BufRead) -> Result<Config, Error> {
|
||||||
.parse::<u16>()
|
.parse::<u16>()
|
||||||
.map_err(|_| Error::InvalidMinSigners)?;
|
.map_err(|_| Error::InvalidMinSigners)?;
|
||||||
|
|
||||||
println!("The maximum number of signers: ");
|
writeln!(logger, "The maximum number of signers: ")?;
|
||||||
|
|
||||||
let mut max = String::new();
|
let mut max = String::new();
|
||||||
input.read_line(&mut max).unwrap();
|
input.read_line(&mut max).unwrap();
|
||||||
|
@ -48,7 +55,10 @@ pub fn request_inputs(input: &mut impl BufRead) -> Result<Config, Error> {
|
||||||
.parse::<u16>()
|
.parse::<u16>()
|
||||||
.map_err(|_| Error::InvalidMaxSigners)?;
|
.map_err(|_| Error::InvalidMaxSigners)?;
|
||||||
|
|
||||||
println!("Your identifier (this should be an integer between 1 and 65535):");
|
writeln!(
|
||||||
|
logger,
|
||||||
|
"Your identifier (this should be an integer between 1 and 65535):"
|
||||||
|
)?;
|
||||||
|
|
||||||
let mut identifier_input = String::new();
|
let mut identifier_input = String::new();
|
||||||
|
|
||||||
|
@ -73,8 +83,9 @@ pub fn request_inputs(input: &mut impl BufRead) -> Result<Config, Error> {
|
||||||
|
|
||||||
pub fn read_round1_package(
|
pub fn read_round1_package(
|
||||||
input: &mut impl BufRead,
|
input: &mut impl BufRead,
|
||||||
) -> Result<(Identifier, round1::Package), Error> {
|
logger: &mut dyn Write,
|
||||||
println!("The sender's identifier (hex string):");
|
) -> Result<(Identifier, round1::Package), Box<dyn std::error::Error>> {
|
||||||
|
writeln!(logger, "The sender's identifier (hex string):")?;
|
||||||
|
|
||||||
let mut identifier_input = String::new();
|
let mut identifier_input = String::new();
|
||||||
input.read_line(&mut identifier_input).unwrap();
|
input.read_line(&mut identifier_input).unwrap();
|
||||||
|
@ -86,7 +97,7 @@ pub fn read_round1_package(
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
println!("Their JSON-encoded Round 1 Package:");
|
writeln!(logger, "Their JSON-encoded Round 1 Package:")?;
|
||||||
|
|
||||||
let mut package_input = String::new();
|
let mut package_input = String::new();
|
||||||
input.read_line(&mut package_input).unwrap();
|
input.read_line(&mut package_input).unwrap();
|
||||||
|
@ -97,8 +108,9 @@ pub fn read_round1_package(
|
||||||
|
|
||||||
pub fn read_round2_package(
|
pub fn read_round2_package(
|
||||||
input: &mut impl BufRead,
|
input: &mut impl BufRead,
|
||||||
) -> Result<(Identifier, round2::Package), Error> {
|
logger: &mut dyn Write,
|
||||||
println!("The participant identifier (this should be an integer between 1 and 65535):");
|
) -> Result<(Identifier, round2::Package), Box<dyn std::error::Error>> {
|
||||||
|
writeln!(logger, "The sender's identifier (hex string):")?;
|
||||||
|
|
||||||
let mut identifier_input = String::new();
|
let mut identifier_input = String::new();
|
||||||
input.read_line(&mut identifier_input).unwrap();
|
input.read_line(&mut identifier_input).unwrap();
|
||||||
|
@ -110,7 +122,7 @@ pub fn read_round2_package(
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
println!("Their JSON-encoded Round 1 Package:");
|
writeln!(logger, "Their JSON-encoded Round 1 Package:")?;
|
||||||
|
|
||||||
let mut package_input = String::new();
|
let mut package_input = String::new();
|
||||||
input.read_line(&mut package_input).unwrap();
|
input.read_line(&mut package_input).unwrap();
|
||||||
|
|
|
@ -6,26 +6,14 @@ mod trusted_dealer_keygen;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use cli::CliError;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use crate::cli::cli;
|
use crate::cli::cli;
|
||||||
|
|
||||||
fn main() -> io::Result<()> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let out = cli();
|
let mut reader = Box::new(io::stdin().lock());
|
||||||
|
let mut logger = io::stdout();
|
||||||
if let Err(e) = out {
|
cli(&mut reader, &mut logger)?;
|
||||||
if e.cli_error == CliError::Config {
|
|
||||||
{
|
|
||||||
eprintln!("Error: {}", e.frost_error);
|
|
||||||
std::process::exit(exitcode::DATAERR)
|
|
||||||
};
|
|
||||||
};
|
|
||||||
if e.cli_error == CliError::Keygen {
|
|
||||||
eprintln!("Error: {}", e.frost_error);
|
|
||||||
std::process::exit(1)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue