Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add frost-client {coordinator,participant} #328

Merged
merged 3 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 33 additions & 34 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion coordinator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ eyre = "0.6.12"
frost-core = { version = "2.0.0-rc.0", features = ["serde"] }
frost-rerandomized = { version = "2.0.0-rc.0", features = ["serde"] }
frost-ed25519 = { version = "2.0.0-rc.0", features = ["serde"] }
reddsa = { git = "https://github.com/ZcashFoundation/reddsa.git", rev = "4d8c4bb337231e6e89117334d7c61dada589a953", features = ["frost", "serde"] }
reddsa = { git = "https://github.com/ZcashFoundation/reddsa.git", rev = "ed49e9ca0699a6450f6d4a9fe62ff168f5ea1ead", features = ["frost", "serde"] }
hex = { version = "0.4", features = ["serde"] }
thiserror = "1.0"
rand = "0.8"
Expand All @@ -25,6 +25,7 @@ reqwest = { version = "0.12.8", features = ["json"] }
server = { path = "../server" }
tokio = { version = "1", features = ["full"] }
message-io = "0.18"
rpassword = "7.3.1"

[features]
default = []
141 changes: 86 additions & 55 deletions coordinator/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,19 @@ pub struct Args {
#[arg(short = 's', long, default_value = "")]
pub signature: String,

/// IP to bind to, if using online comms
/// IP to bind to, if using socket comms.
/// IP to connect to, if using HTTP mode.
#[arg(short, long, default_value = "0.0.0.0")]
pub ip: String,

/// Port to bind to, if using online comms
/// Port to bind to, if using socket comms.
/// Port to connect to, if using HTTP mode.
#[arg(short, long, default_value_t = 2744)]
pub port: u16,
}

#[derive(Clone, Debug)]
pub struct ProcessedArgs<C: Ciphersuite> {
pub ciphersuite: String,

/// CLI mode. If enabled, it will prompt for inputs from stdin
/// and print values to stdout, ignoring other flags.
/// If false, socket communication is enabled.
Expand All @@ -104,6 +104,10 @@ pub struct ProcessedArgs<C: Ciphersuite> {
/// The (actual) password to use in HTTP mode.
pub password: String,

/// The authentication token to use in HTTP mode; if not specified
/// it will login with `password`
pub authentication_token: Option<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.
Expand All @@ -125,10 +129,12 @@ pub struct ProcessedArgs<C: Ciphersuite> {
/// human-readable hex-string is printed to stdout.
pub signature: String,

/// IP to bind to, if using online comms
/// IP to bind to, if using socket comms.
/// IP to connect to, if using HTTP mode.
pub ip: String,

/// Port to bind to, if using online comms
/// Port to bind to, if using socket comms.
/// Port to connect to, if using HTTP mode.
pub port: u16,
}

Expand All @@ -142,7 +148,7 @@ impl<C: Ciphersuite + 'static> ProcessedArgs<C> {
output: &mut dyn Write,
) -> Result<Self, Box<dyn Error>> {
let password = if args.http {
env::var(&args.password).map_err(|_| eyre!("The password argument must specify the name of a environment variable containing the password"))?
read_password(&args.password)?
} else {
String::new()
};
Expand All @@ -168,58 +174,12 @@ impl<C: Ciphersuite + 'static> ProcessedArgs<C> {

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

let messages = if args.message.is_empty() {
writeln!(output, "The message to be signed (hex encoded)")?;
let mut msg = String::new();
input.read_line(&mut msg)?;
vec![hex::decode(msg.trim())?]
} else {
args.message
.iter()
.map(|filename| {
let msg = if filename == "-" || filename.is_empty() {
writeln!(output, "The message to be signed (hex encoded)")?;
let mut msg = String::new();
input.read_line(&mut msg)?;
hex::decode(msg.trim())?
} else {
eprintln!("Reading message from {}...", &filename);
fs::read(filename)?
};
Ok(msg)
})
.collect::<Result<_, Box<dyn Error>>>()?
};
let messages = read_messages(&args.message, output, input)?;

println!("Processing randomizer {:?}", args.randomizer);
let randomizers = if args.ciphersuite == "redpallas" {
if args.randomizer.is_empty() {
Vec::new()
} else {
args.randomizer
.iter()
.map(|filename| {
let randomizer = if filename == "-" || filename.is_empty() {
writeln!(output, "Enter the randomizer (hex string):")?;
let mut randomizer = String::new();
input.read_line(&mut randomizer)?;
let bytes = hex::decode(randomizer.trim())?;
frost_rerandomized::Randomizer::deserialize(&bytes)?
} else {
eprintln!("Reading randomizer from {}...", &filename);
let bytes = fs::read(filename)?;
frost_rerandomized::Randomizer::deserialize(&bytes)?
};
Ok(randomizer)
})
.collect::<Result<_, Box<dyn Error>>>()?
}
} else {
Vec::new()
};
let randomizers = read_randomizers(&args.randomizer, output, input)?;

Ok(ProcessedArgs {
ciphersuite: args.ciphersuite.clone(),
cli: args.cli,
http: args.http,
username: args.username.clone(),
Expand All @@ -232,6 +192,77 @@ impl<C: Ciphersuite + 'static> ProcessedArgs<C> {
signature: args.signature.clone(),
ip: args.ip.clone(),
port: args.port,
authentication_token: None,
})
}
}

pub fn read_password(password_env_name: &str) -> Result<String, Box<dyn Error>> {
if password_env_name.is_empty() {
Ok(
rpassword::prompt_password("Password: ")
.map_err(|_| eyre!("Error reading password"))?,
)
} else {
Ok(env::var(password_env_name).map_err(|_| eyre!("The password argument must specify the name of a environment variable containing the password"))?)
}
}

pub fn read_messages(
message_paths: &[String],
output: &mut dyn Write,
input: &mut dyn BufRead,
) -> Result<Vec<Vec<u8>>, Box<dyn Error>> {
let messages = if message_paths.is_empty() {
writeln!(output, "The message to be signed (hex encoded)")?;
let mut msg = String::new();
input.read_line(&mut msg)?;
vec![hex::decode(msg.trim())?]
} else {
message_paths
.iter()
.map(|filename| {
let msg = if *filename == "-" || filename.is_empty() {
writeln!(output, "The message to be signed (hex encoded)")?;
let mut msg = String::new();
input.read_line(&mut msg)?;
hex::decode(msg.trim())?
} else {
eprintln!("Reading message from {}...", &filename);
fs::read(filename)?
};
Ok(msg)
})
.collect::<Result<_, Box<dyn Error>>>()?
};
Ok(messages)
}

pub fn read_randomizers<C: Ciphersuite + 'static>(
randomizer_paths: &[String],
output: &mut dyn Write,
input: &mut dyn BufRead,
) -> Result<Vec<Randomizer<C>>, Box<dyn Error>> {
let randomizers = if randomizer_paths.is_empty() {
Vec::new()
} else {
randomizer_paths
.iter()
.map(|filename| {
let randomizer = if filename == "-" || filename.is_empty() {
writeln!(output, "Enter the randomizer (hex string):")?;
let mut randomizer = String::new();
input.read_line(&mut randomizer)?;
let bytes = hex::decode(randomizer.trim())?;
frost_rerandomized::Randomizer::deserialize(&bytes)?
} else {
eprintln!("Reading randomizer from {}...", &filename);
let bytes = fs::read(filename)?;
frost_rerandomized::Randomizer::deserialize(&bytes)?
};
Ok(randomizer)
})
.collect::<Result<_, Box<dyn Error>>>()?
};
Ok(randomizers)
}
Loading