diff --git a/dkg/src/cli.rs b/dkg/src/cli.rs index ff7715e..c383bd0 100644 --- a/dkg/src/cli.rs +++ b/dkg/src/cli.rs @@ -1,35 +1,17 @@ use frost::keys::dkg::{round1, round2}; -use frost::{Error, Identifier}; +use frost::Identifier; use frost_ed25519 as frost; use rand::thread_rng; 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::output::Logger; -#[derive(PartialEq)] -pub enum CliError { - Config, - Keygen, -} - -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(); +pub fn cli( + reader: &mut impl BufRead, + logger: &mut impl Write, +) -> Result<(), Box> { + let config = request_inputs(reader, logger)?; let rng = thread_rng(); @@ -38,106 +20,80 @@ pub fn cli() -> Result<(), TrustedDealerError> { config.max_signers, config.min_signers, 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()); - - console_logger.log(format!( + writeln!( + logger, "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(&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", config.max_signers - 1, - )); + )?; let mut received_round1_packages: HashMap = HashMap::new(); for _ in 0..config.max_signers - 1 { - let (identifier, round1_package) = - read_round1_package(&mut reader).map_err(|e| TrustedDealerError { - frost_error: e, - cli_error: CliError::Keygen, - })?; + let (identifier, round1_package) = read_round1_package(reader, logger)?; received_round1_packages.insert(identifier, round1_package); - console_logger.log("".to_string()); + writeln!(logger)?; } let received_round1_packages = received_round1_packages.into_values().collect::>(); let (round2_secret_package, round2_packages) = - frost::keys::dkg::part2(secret_package, &received_round1_packages).map_err(|e| { - TrustedDealerError { - frost_error: e, - cli_error: CliError::Keygen, - } - })?; + frost::keys::dkg::part2(secret_package, &received_round1_packages)?; - console_logger.log("=== ROUND 2: SEND PACKAGES ===\n".to_string()); + writeln!(logger, "=== ROUND 2: SEND PACKAGES ===\n")?; for package in round2_packages { - console_logger.log(format!( + writeln!( + logger, "Round 2 Package to send to participant {} (your identifier: {}):\n\n{}\n", serde_json::to_string(package.receiver_identifier()).unwrap(), serde_json::to_string(&config.identifier).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", config.max_signers - 1, - )); + )?; let mut received_round2_packages: HashMap = HashMap::new(); for _ in 0..config.max_signers - 1 { - let (identifier, round2_package) = - read_round2_package(&mut reader).map_err(|e| TrustedDealerError { - frost_error: e, - cli_error: CliError::Keygen, - })?; + let (identifier, round2_package) = read_round2_package(reader, logger)?; received_round2_packages.insert(identifier, round2_package); - console_logger.log("".to_string()); + writeln!(logger)?; } let received_round2_packages = received_round2_packages.into_values().collect::>(); - console_logger.log("=== DKG FINISHED ===".to_string()); + writeln!(logger, "=== DKG FINISHED ===")?; let (key_package, public_key_package) = frost::keys::dkg::part3( &round2_secret_package, &received_round1_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", serde_json::to_string(&key_package).unwrap(), - )); - console_logger.log(format!( + )?; + writeln!( + logger, "Partcipant public key package:\n\n{}\n", serde_json::to_string(&public_key_package).unwrap(), - )); + )?; Ok(()) } - -#[derive(Default)] -pub struct ConsoleLogger; - -impl Logger for ConsoleLogger { - fn log(&mut self, value: String) { - println!("{}", value); - } -} diff --git a/dkg/src/inputs.rs b/dkg/src/inputs.rs index fa62b10..94dbb71 100755 --- a/dkg/src/inputs.rs +++ b/dkg/src/inputs.rs @@ -3,7 +3,7 @@ use frost::{ Error, Identifier, }; use frost_ed25519 as frost; -use std::io::BufRead; +use std::io::{BufRead, Write}; #[derive(Debug, PartialEq, Clone)] pub struct Config { @@ -12,6 +12,10 @@ pub struct Config { pub identifier: Identifier, } +pub trait Logger { + fn log(&mut self, value: String); +} + fn validate_inputs(config: &Config) -> Result<(), Error> { if config.min_signers < 2 { return Err(Error::InvalidMinSigners); @@ -28,8 +32,11 @@ fn validate_inputs(config: &Config) -> Result<(), Error> { Ok(()) } -pub fn request_inputs(input: &mut impl BufRead) -> Result { - println!("The minimum number of signers: (2 or more)"); +pub fn request_inputs( + input: &mut impl BufRead, + logger: &mut dyn Write, +) -> Result> { + writeln!(logger, "The minimum number of signers: (2 or more)")?; let mut min = String::new(); input.read_line(&mut min).unwrap(); @@ -39,7 +46,7 @@ pub fn request_inputs(input: &mut impl BufRead) -> Result { .parse::() .map_err(|_| Error::InvalidMinSigners)?; - println!("The maximum number of signers: "); + writeln!(logger, "The maximum number of signers: ")?; let mut max = String::new(); input.read_line(&mut max).unwrap(); @@ -48,7 +55,10 @@ pub fn request_inputs(input: &mut impl BufRead) -> Result { .parse::() .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(); @@ -73,8 +83,9 @@ pub fn request_inputs(input: &mut impl BufRead) -> Result { pub fn read_round1_package( input: &mut impl BufRead, -) -> Result<(Identifier, round1::Package), Error> { - println!("The sender's identifier (hex string):"); + logger: &mut dyn Write, +) -> Result<(Identifier, round1::Package), Box> { + writeln!(logger, "The sender's identifier (hex string):")?; let mut identifier_input = String::new(); input.read_line(&mut identifier_input).unwrap(); @@ -86,7 +97,7 @@ pub fn read_round1_package( ) .unwrap(); - println!("Their JSON-encoded Round 1 Package:"); + writeln!(logger, "Their JSON-encoded Round 1 Package:")?; let mut package_input = String::new(); input.read_line(&mut package_input).unwrap(); @@ -97,8 +108,9 @@ pub fn read_round1_package( pub fn read_round2_package( input: &mut impl BufRead, -) -> Result<(Identifier, round2::Package), Error> { - println!("The participant identifier (this should be an integer between 1 and 65535):"); + logger: &mut dyn Write, +) -> Result<(Identifier, round2::Package), Box> { + writeln!(logger, "The sender's identifier (hex string):")?; let mut identifier_input = String::new(); input.read_line(&mut identifier_input).unwrap(); @@ -110,7 +122,7 @@ pub fn read_round2_package( ) .unwrap(); - println!("Their JSON-encoded Round 1 Package:"); + writeln!(logger, "Their JSON-encoded Round 1 Package:")?; let mut package_input = String::new(); input.read_line(&mut package_input).unwrap(); diff --git a/dkg/src/main.rs b/dkg/src/main.rs index 8b2165d..ba8f844 100755 --- a/dkg/src/main.rs +++ b/dkg/src/main.rs @@ -6,26 +6,14 @@ mod trusted_dealer_keygen; #[cfg(test)] mod tests; -use cli::CliError; use std::io; use crate::cli::cli; -fn main() -> io::Result<()> { - let out = cli(); - - if let Err(e) = out { - 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) - }; - } +fn main() -> Result<(), Box> { + let mut reader = Box::new(io::stdin().lock()); + let mut logger = io::stdout(); + cli(&mut reader, &mut logger)?; Ok(()) }