Skip to content

Commit

Permalink
trusted-dealer: allow reading params from arguments, and writing to f…
Browse files Browse the repository at this point in the history
…iles (#132)
  • Loading branch information
conradoplg authored Jan 31, 2024
1 parent 4925183 commit d0c8949
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 49 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion tests/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,15 @@ async fn trusted_dealer_journey() {

let dealer_input = "3\n5\n\n";

let dealer_config = trusted_dealer_input(&mut dealer_input.as_bytes(), &mut buf).unwrap();
let dealer_config = trusted_dealer_input(
&trusted_dealer::args::Args {
cli: true,
..Default::default()
},
&mut dealer_input.as_bytes(),
&mut buf,
)
.unwrap();

let (shares, pubkeys) =
trusted_dealer_keygen(&dealer_config, IdentifierList::Default, &mut rng).unwrap();
Expand Down
1 change: 1 addition & 0 deletions trusted-dealer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ edition = "2021"
[dependencies]
frost-ed25519 = { version = "1.0.0-rc.0", features = ["serde"] }
reddsa = { git = "https://github.com/ZcashFoundation/reddsa.git", rev = "81c649c412e5b6ba56d491d2857f91fbd28adbc7", features = ["frost"] }
clap = { version = "4.4.7", features = ["derive"] }
thiserror = "1.0"
rand = "0.8"
hex = "0.4"
Expand Down
35 changes: 35 additions & 0 deletions trusted-dealer/src/args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use clap::Parser;

#[derive(Parser, Debug, Default)]
#[command(author, version, about, long_about = None)]
pub struct Args {
/// CLI mode. If enabled, it will prompts for inputs from stdin
/// and print values to stdout, ignoring other flags.
#[arg(short = 'i', long, default_value_t = false)]
pub cli: bool,

/// Where to write the public key package to use. Can be a file path or "-".
/// If "-" is specified, then it will be written to standard output.
#[arg(short = 'P', long, default_value = "public-key-package.json")]
pub public_key_package: String,

/// Template for the key package to be written. If "-" is specified, they will
/// be all written to standard output. Otherwise, they will be written
/// to files using the specified format, replacing "{}" with the index
/// of the participant starting from 1.
#[arg(short = 'k', long, default_value = "key-package-{}.json")]
pub key_package: String,

/// The threshold (minimum number of signers).
#[arg(short = 't', long, default_value_t = 2)]
pub threshold: u16,

/// The total number of participants (maximum number of signers).
#[arg(short = 'n', long, default_value_t = 3)]
pub num_signers: u16,

/// The key to use when splitting into shares, in hex format. If not
/// specified, a random one will be generated.
#[arg(long)]
pub key: Option<String>,
}
6 changes: 4 additions & 2 deletions trusted-dealer/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@ use frost::keys::IdentifierList;
use rand::thread_rng;
use std::io::{BufRead, Write};

use crate::args::Args;
use crate::inputs::{print_values, request_inputs};
use crate::trusted_dealer_keygen::{split_secret, trusted_dealer_keygen};

// Currently this uses the Default Identifiers
pub fn cli(
args: &Args,
input: &mut impl BufRead,
logger: &mut impl Write,
) -> Result<(), Box<dyn std::error::Error>> {
let config = request_inputs(input, logger)?;
let config = request_inputs(args, input, logger)?;

let mut rng = thread_rng();

Expand All @@ -27,7 +29,7 @@ pub fn cli(

let (shares, pubkeys) = keygen?;

print_values(&shares, &pubkeys, logger)?;
print_values(args, &shares, &pubkeys, logger)?;

Ok(())
}
118 changes: 76 additions & 42 deletions trusted-dealer/src/inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ use frost::Error;
use frost::Identifier;
use itertools::Itertools;
use std::collections::BTreeMap;
use std::fs;
use std::io::{BufRead, Write};

use crate::args::Args;

#[derive(Debug, PartialEq, Clone)]
pub struct Config {
pub min_signers: u16,
Expand All @@ -34,41 +37,56 @@ fn validate_inputs(config: &Config) -> Result<(), Error> {
}

pub fn request_inputs(
args: &Args,
input: &mut impl BufRead,
logger: &mut impl Write,
) -> Result<Config, Box<dyn std::error::Error>> {
writeln!(logger, "The minimum number of signers: (2 or more)")?;

let mut min = String::new();
input.read_line(&mut min)?;

let min_signers = min
.trim()
.parse::<u16>()
.map_err(|_| Error::InvalidMinSigners)?;

writeln!(logger, "The maximum number of signers: ")?;

let mut max = String::new();
input.read_line(&mut max)?;
let max_signers = max
.trim()
.parse::<u16>()
.map_err(|_| Error::InvalidMaxSigners)?;

writeln!(
logger,
"Secret key (press enter to randomly generate a fresh one): "
)?;

let mut secret_input = String::new();
input.read_line(&mut secret_input)?;
let secret = hex::decode(secret_input.trim()).map_err(|_| Error::MalformedSigningKey)?;

let config = Config {
min_signers,
max_signers,
secret,
let config = if args.cli {
writeln!(logger, "The minimum number of signers: (2 or more)")?;

let mut min = String::new();
input.read_line(&mut min)?;

let min_signers = min
.trim()
.parse::<u16>()
.map_err(|_| Error::InvalidMinSigners)?;

writeln!(logger, "The maximum number of signers: ")?;

let mut max = String::new();
input.read_line(&mut max)?;
let max_signers = max
.trim()
.parse::<u16>()
.map_err(|_| Error::InvalidMaxSigners)?;

writeln!(
logger,
"Secret key (press enter to randomly generate a fresh one): "
)?;

let mut secret_input = String::new();
input.read_line(&mut secret_input)?;
let secret = hex::decode(secret_input.trim()).map_err(|_| Error::MalformedSigningKey)?;

Config {
min_signers,
max_signers,
secret,
}
} else {
let secret = hex::decode(args.key.clone().unwrap_or("".to_string()))
.map_err(|_| Error::MalformedSigningKey)?;
eprintln!(
"Generating {} shares with threshold {}...",
args.num_signers, args.threshold
);
Config {
min_signers: args.threshold,
max_signers: args.num_signers,
secret,
}
};

validate_inputs(&config)?;
Expand All @@ -77,23 +95,39 @@ pub fn request_inputs(
}

pub fn print_values(
args: &Args,
keys: &BTreeMap<Identifier, SecretShare>,
pubkeys: &PublicKeyPackage,
logger: &mut dyn Write,
) -> Result<(), Box<dyn std::error::Error>> {
writeln!(
logger,
"Public key package:\n{}",
serde_json::to_string(pubkeys).unwrap()
)?;

for (k, v) in keys.iter().sorted_by_key(|x| x.0) {
writeln!(logger, "Participant: {}", hex::encode(k.serialize()))?;
if args.cli {
writeln!(
logger,
"Secret share:\n{}",
serde_json::to_string(v).unwrap()
"Public key package:\n{}",
serde_json::to_string(pubkeys)?
)?;

for (k, v) in keys.iter().sorted_by_key(|x| x.0) {
writeln!(logger, "Participant: {}", hex::encode(k.serialize()))?;
writeln!(
logger,
"Secret share:\n{}",
serde_json::to_string(v).unwrap()
)?;
}
} else {
fs::write(&args.public_key_package, serde_json::to_vec(pubkeys)?)?;
eprintln!("Public key package written to {}", &args.public_key_package);

for (i, (k, v)) in keys.iter().sorted_by_key(|x| x.0).enumerate() {
let path = str::replace(&args.key_package, "{}", format!("{}", i + 1).as_str());
fs::write(&path, serde_json::to_vec(v)?)?;
eprintln!(
"Key package for participant {} written to {}",
hex::encode(k.serialize()),
&path
);
}
}

Ok(())
Expand Down
1 change: 1 addition & 0 deletions trusted-dealer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod args;
pub mod cli;
pub mod inputs;
pub mod trusted_dealer_keygen;
13 changes: 9 additions & 4 deletions trusted-dealer/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
#[cfg(test)]
mod tests;
// TODO: fix and restore tests
// #[cfg(test)]
// mod tests;

use std::io;

use trusted_dealer::cli::cli;
use clap::Parser;

use trusted_dealer::{args::Args, cli::cli};

// TODO: Update to use exit codes
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Args::parse();

let mut reader = Box::new(io::stdin().lock());
let mut logger = io::stdout();
cli(&mut reader, &mut logger)?;
cli(&args, &mut reader, &mut logger)?;

Ok(())
}

0 comments on commit d0c8949

Please sign in to comment.