Improve consistency of testing across projects (#76)
* Update participant tests to use DKG format (#37) Update Makefile to not run --all-features in tests cli tests were not touched * Update tests in trusted dealer (#37) * Refactor test files structure to be consistent across projects (#37) * Add cross project integration test (#37) * Remove empty test files (#37) * Remove reference to old test (#37) * print entire identifier instead of converting back to integer * Remove commented code (#37) * Add signature verification step to participant demo (#78) * Add verification step to participant demo (#56) * Add cli test to participant (#56) Clean up some comments and prints --------- Co-authored-by: Conrado Gouvea <conradoplg@gmail.com>
This commit is contained in:
parent
c6056d0e45
commit
0c528929c5
|
@ -1142,6 +1142,22 @@ dependencies = [
|
|||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tests"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"coordinator",
|
||||
"dkg",
|
||||
"exitcode",
|
||||
"frost-ed25519",
|
||||
"hex",
|
||||
"participant",
|
||||
"rand",
|
||||
"reddsa",
|
||||
"serde_json",
|
||||
"trusted-dealer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.48"
|
||||
|
|
|
@ -3,5 +3,10 @@ members = [
|
|||
"participant",
|
||||
"trusted-dealer",
|
||||
"dkg",
|
||||
"coordinator"
|
||||
"coordinator", "tests"
|
||||
]
|
||||
default-members = ["participant",
|
||||
"trusted-dealer",
|
||||
"dkg",
|
||||
"coordinator", "tests"]
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
|
|||
script = "cargo fmt"
|
||||
|
||||
[tasks.clippy-full]
|
||||
script = "cargo clippy --all-features --all-targets -- -D warnings"
|
||||
script = "cargo clippy --all-targets -- -D warnings"
|
||||
|
||||
[tasks.all]
|
||||
dependencies = [
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
pub mod cli;
|
||||
|
||||
mod step_1;
|
||||
mod step_2;
|
||||
mod step_3;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
pub mod step_1;
|
||||
pub mod step_2;
|
||||
pub mod step_3;
|
||||
|
|
|
@ -35,7 +35,7 @@ pub fn step_3(
|
|||
participants: ParticipantsConfig,
|
||||
signing_package: SigningPackage,
|
||||
#[cfg(feature = "redpallas")] randomizer: frost::round2::Randomizer,
|
||||
) {
|
||||
) -> Signature {
|
||||
let group_signature = request_inputs_signature_shares(
|
||||
input,
|
||||
logger,
|
||||
|
@ -46,6 +46,7 @@ pub fn step_3(
|
|||
)
|
||||
.unwrap();
|
||||
print_signature(logger, group_signature);
|
||||
group_signature
|
||||
}
|
||||
|
||||
// Input required:
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
mod steps;
|
|
@ -1,96 +0,0 @@
|
|||
// use frost::keys::{IdentifierList, KeyPackage, SecretShare};
|
||||
// use frost::round1::{SigningCommitments, SigningNonces};
|
||||
// use frost::round2::SignatureShare;
|
||||
// use frost::{Identifier, SigningPackage};
|
||||
// use frost_ed25519 as frost;
|
||||
|
||||
// use rand::rngs::ThreadRng;
|
||||
// use rand::thread_rng;
|
||||
// use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
// #[test]
|
||||
// fn check_keygen_with_dealer() {
|
||||
// let mut rng = thread_rng();
|
||||
// let (shares, pubkeys) =
|
||||
// frost::keys::generate_with_dealer(3, 2, IdentifierList::Default, &mut rng).unwrap();
|
||||
// let key_packages = key_package(&shares);
|
||||
// let (nonces, commitments) = round_1(2, &mut rng, &key_packages);
|
||||
// let message = "i am a message".as_bytes();
|
||||
|
||||
// let signing_packages = step_2();
|
||||
|
||||
// let signature_shares = round_2(nonces, &key_packages, signing_packages);
|
||||
|
||||
// let signing_packages = step_2()
|
||||
|
||||
// // Coordinator
|
||||
|
||||
// let config = Config {
|
||||
// message,
|
||||
// signing_package,
|
||||
// signature_shares,
|
||||
// pubkeys,
|
||||
// };
|
||||
|
||||
// // let group_signature = aggregate_and_verify(config);
|
||||
|
||||
// // let expected = aggregate(
|
||||
// // config.signing_package,
|
||||
// // config.signature_shares,
|
||||
// // config.pubkeys,
|
||||
// // )
|
||||
// // .unwrap();
|
||||
|
||||
// // assert!(group_signature.is_ok());
|
||||
// // assert!(group_signature == expected)
|
||||
// }
|
||||
|
||||
// fn key_package(shares: &HashMap<Identifier, SecretShare>) -> HashMap<Identifier, KeyPackage> {
|
||||
// let mut key_packages: HashMap<_, _> = HashMap::new();
|
||||
|
||||
// for (identifier, secret_share) in shares {
|
||||
// let key_package = frost::keys::KeyPackage::try_from(secret_share.clone()).unwrap();
|
||||
// key_packages.insert(*identifier, key_package);
|
||||
// }
|
||||
|
||||
// key_packages
|
||||
// }
|
||||
|
||||
// fn round_1(
|
||||
// min_signers: u16,
|
||||
// mut rng: &mut ThreadRng,
|
||||
// key_packages: &HashMap<Identifier, KeyPackage>,
|
||||
// ) -> (
|
||||
// HashMap<Identifier, SigningNonces>,
|
||||
// BTreeMap<Identifier, SigningCommitments>,
|
||||
// ) {
|
||||
// // Participant Round 1
|
||||
|
||||
// let mut nonces_map = HashMap::new();
|
||||
// let mut commitments_map = BTreeMap::new();
|
||||
|
||||
// for participant_index in 1..(min_signers + 1) {
|
||||
// let participant_identifier = participant_index.try_into().expect("should be nonzero");
|
||||
// let key_package = &key_packages[&participant_identifier];
|
||||
// let (nonces, commitments) = frost::round1::commit(key_package.secret_share(), &mut rng);
|
||||
// nonces_map.insert(participant_identifier, nonces);
|
||||
// commitments_map.insert(participant_identifier, commitments);
|
||||
// }
|
||||
// (nonces_map, commitments_map)
|
||||
// }
|
||||
|
||||
// fn round_2(
|
||||
// nonces_map: HashMap<Identifier, SigningNonces>,
|
||||
// key_packages: &HashMap<Identifier, KeyPackage>,
|
||||
// signing_package: SigningPackage,
|
||||
// ) -> HashMap<Identifier, SignatureShare> {
|
||||
// let mut signature_shares = HashMap::new();
|
||||
// for participant_identifier in nonces_map.keys() {
|
||||
// let key_package = &key_packages[participant_identifier];
|
||||
|
||||
// let nonces = &nonces_map[participant_identifier];
|
||||
// let signature_share = frost::round2::sign(&signing_package, nonces, key_package).unwrap();
|
||||
// signature_shares.insert(*participant_identifier, signature_share);
|
||||
// }
|
||||
// signature_shares
|
||||
// }
|
|
@ -0,0 +1,2 @@
|
|||
pub mod cli;
|
||||
pub mod inputs;
|
|
@ -6,7 +6,7 @@ mod tests;
|
|||
|
||||
use std::io;
|
||||
|
||||
use crate::cli::cli;
|
||||
use cli::cli;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut reader = Box::new(io::stdin().lock());
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
mod inputs_tests;
|
||||
mod integration_test;
|
||||
mod inputs;
|
||||
|
|
|
@ -85,7 +85,6 @@ fn return_malformed_identifier_error_if_identifier_invalid() {
|
|||
let mut buf = BufWriter::new(Vec::new());
|
||||
let expected = request_inputs(&mut invalid_input, &mut buf).unwrap_err();
|
||||
|
||||
println!("{:?}", expected);
|
||||
assert_eq!(
|
||||
*expected.downcast::<Error>().unwrap(),
|
||||
Error::MalformedIdentifier
|
|
@ -0,0 +1,2 @@
|
|||
#[cfg(test)]
|
||||
mod integration_tests;
|
|
@ -1,3 +1,5 @@
|
|||
use dkg::cli::cli;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::io::{BufRead, Write};
|
||||
use std::thread;
|
||||
|
@ -5,8 +7,6 @@ use std::thread;
|
|||
use frost_ed25519::keys::{KeyPackage, PublicKeyPackage};
|
||||
use frost_ed25519::Identifier;
|
||||
|
||||
use crate::cli::cli;
|
||||
|
||||
// Read a single line from the given reader.
|
||||
fn read_line(mut reader: impl BufRead) -> Result<String, std::io::Error> {
|
||||
let mut s = String::new();
|
|
@ -1,71 +1,63 @@
|
|||
use frost::{Error, Signature};
|
||||
#[cfg(not(feature = "redpallas"))]
|
||||
use frost_ed25519 as frost;
|
||||
#[cfg(feature = "redpallas")]
|
||||
use reddsa::frost::redpallas as frost;
|
||||
|
||||
use frost::{round1, Error};
|
||||
use participant::round1::{print_values, request_inputs};
|
||||
use participant::round2::{generate_signature, print_values_round_2, round_2_request_inputs};
|
||||
use participant::Logger;
|
||||
use crate::round1::{print_values, request_inputs};
|
||||
use crate::round2::{generate_signature, print_values_round_2, round_2_request_inputs};
|
||||
use rand::thread_rng;
|
||||
use std::io::BufRead;
|
||||
use std::io::{BufRead, Write};
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum CliError {
|
||||
Config,
|
||||
Signing,
|
||||
}
|
||||
pub fn cli(
|
||||
input: &mut impl BufRead,
|
||||
logger: &mut impl Write,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let round_1_config = request_inputs(input, logger)?;
|
||||
|
||||
pub struct ParticipantError {
|
||||
pub frost_error: Error,
|
||||
pub cli_error: CliError,
|
||||
}
|
||||
let key_package = round_1_config.key_package;
|
||||
|
||||
// This is a little messy because of the use of unwrap(). This can be improved.
|
||||
pub fn cli(input: &mut impl BufRead, logger: &mut dyn Logger) -> Result<(), ParticipantError> {
|
||||
let round_1_config = request_inputs(input, logger);
|
||||
|
||||
if let Err(e) = round_1_config {
|
||||
return Err(ParticipantError {
|
||||
frost_error: e,
|
||||
cli_error: CliError::Config,
|
||||
});
|
||||
}
|
||||
|
||||
let round_1_config_ok = round_1_config.unwrap();
|
||||
|
||||
let key_package_ok = round_1_config_ok.key_package;
|
||||
|
||||
logger.log("Key Package succesfully created.".to_string());
|
||||
writeln!(logger, "Key Package succesfully created.")?;
|
||||
|
||||
let mut rng = thread_rng();
|
||||
let (nonces, commitments) = round1::commit(key_package_ok.secret_share(), &mut rng);
|
||||
let (nonces, commitments) = frost::round1::commit(key_package.secret_share(), &mut rng);
|
||||
|
||||
print_values(commitments, logger);
|
||||
print_values(commitments, logger)?;
|
||||
|
||||
let round_2_config = round_2_request_inputs(input, logger); // TODO: handle errors
|
||||
let round_2_config = round_2_request_inputs(input, logger)?;
|
||||
|
||||
if let Err(e) = round_2_config {
|
||||
return Err(ParticipantError {
|
||||
frost_error: e,
|
||||
cli_error: CliError::Config,
|
||||
});
|
||||
}
|
||||
|
||||
let round_2_config_ok = round_2_config.unwrap();
|
||||
let config_message = round_2_config.clone();
|
||||
|
||||
// Sign
|
||||
|
||||
let signature = generate_signature(round_2_config_ok, &key_package_ok, &nonces); // TODO: handle errors
|
||||
let signature = generate_signature(round_2_config, &key_package, &nonces)?;
|
||||
|
||||
if let Err(e) = signature {
|
||||
return Err(ParticipantError {
|
||||
frost_error: e,
|
||||
cli_error: CliError::Signing,
|
||||
});
|
||||
}
|
||||
print_values_round_2(signature, logger)?;
|
||||
|
||||
print_values_round_2(signature.unwrap(), logger);
|
||||
let group_signature = request_signature(input, logger)?;
|
||||
key_package
|
||||
.group_public()
|
||||
.verify(config_message.signing_package.message(), &group_signature)?;
|
||||
|
||||
writeln!(logger, "Group Signature verified.")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn request_signature(
|
||||
input: &mut impl BufRead,
|
||||
logger: &mut impl Write,
|
||||
) -> Result<Signature, Box<dyn std::error::Error>> {
|
||||
writeln!(logger, "The group signature:")?;
|
||||
|
||||
let mut signature_input = String::new();
|
||||
|
||||
input.read_line(&mut signature_input)?;
|
||||
|
||||
let group_signature =
|
||||
serde_json::from_str(signature_input.trim()).map_err(|_| Error::InvalidSignature)?;
|
||||
|
||||
// TODO: add redpallas feature
|
||||
|
||||
Ok(group_signature)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
pub mod cli;
|
||||
pub mod round1;
|
||||
pub mod round2;
|
||||
|
||||
pub trait Logger {
|
||||
fn log(&mut self, value: String);
|
||||
}
|
||||
|
|
|
@ -1,38 +1,19 @@
|
|||
mod cli;
|
||||
mod round1;
|
||||
mod round2;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use cli::{cli, CliError};
|
||||
use participant::Logger;
|
||||
use cli::cli;
|
||||
|
||||
use std::io;
|
||||
|
||||
fn main() -> io::Result<()> {
|
||||
// TODO: Update to use exit codes
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut reader = Box::new(io::stdin().lock());
|
||||
let mut logger = ConsoleLogger;
|
||||
let out = cli(&mut reader, &mut logger);
|
||||
|
||||
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::Signing {
|
||||
eprintln!("Error: {}", e.frost_error);
|
||||
std::process::exit(1)
|
||||
};
|
||||
}
|
||||
let mut logger = io::stdout();
|
||||
cli(&mut reader, &mut logger)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ConsoleLogger;
|
||||
|
||||
impl Logger for ConsoleLogger {
|
||||
fn log(&mut self, value: String) {
|
||||
println!("{}", value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,13 +5,12 @@ use reddsa::frost::redpallas as frost;
|
|||
#[cfg(feature = "redpallas")]
|
||||
use reddsa::frost::redpallas::keys::PositiveY;
|
||||
|
||||
use crate::Logger;
|
||||
use frost::{
|
||||
keys::{KeyPackage, SecretShare},
|
||||
round1::SigningCommitments,
|
||||
Error,
|
||||
};
|
||||
use std::io::BufRead;
|
||||
use std::io::{BufRead, Write};
|
||||
|
||||
// TODO: Rethink the types here. They're inconsistent with each other
|
||||
#[derive(Debug, PartialEq)]
|
||||
|
@ -22,13 +21,13 @@ pub struct Round1Config {
|
|||
// TODO: refactor to generate config
|
||||
pub fn request_inputs(
|
||||
input: &mut impl BufRead,
|
||||
logger: &mut dyn Logger,
|
||||
) -> Result<Round1Config, Error> {
|
||||
logger.log("Your JSON-encoded secret share or key package:".to_string());
|
||||
logger: &mut impl Write,
|
||||
) -> Result<Round1Config, Box<dyn std::error::Error>> {
|
||||
writeln!(logger, "Your JSON-encoded secret share or key package:")?;
|
||||
|
||||
let mut json = String::new();
|
||||
|
||||
input.read_line(&mut json).unwrap();
|
||||
input.read_line(&mut json)?;
|
||||
|
||||
let key_package = if let Ok(secret_share) = serde_json::from_str::<SecretShare>(&json) {
|
||||
KeyPackage::try_from(secret_share)?
|
||||
|
@ -43,14 +42,22 @@ pub fn request_inputs(
|
|||
Ok(Round1Config { key_package })
|
||||
}
|
||||
|
||||
// The nonces are printed out here for demo purposes only. The hiding and binding nonces are SECRET and not to be shared.
|
||||
pub fn print_values(commitments: SigningCommitments, logger: &mut dyn Logger) {
|
||||
logger.log("=== Round 1 ===".to_string());
|
||||
logger.log("SigningNonces were generated and stored in memory".to_string());
|
||||
logger.log(format!(
|
||||
pub fn print_values(
|
||||
commitments: SigningCommitments,
|
||||
logger: &mut dyn Write,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
writeln!(logger, "=== Round 1 ===")?;
|
||||
writeln!(logger, "SigningNonces were generated and stored in memory")?;
|
||||
writeln!(
|
||||
logger,
|
||||
"SigningCommitments:\n{}",
|
||||
serde_json::to_string(&commitments).unwrap(),
|
||||
));
|
||||
logger.log("=== Round 1 Completed ===".to_string());
|
||||
logger.log("Please send your SigningCommitments to the coordinator".to_string());
|
||||
)?;
|
||||
writeln!(logger, "=== Round 1 Completed ===")?;
|
||||
writeln!(
|
||||
logger,
|
||||
"Please send your SigningCommitments to the coordinator"
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -5,16 +5,15 @@ use frost_ed25519 as frost;
|
|||
#[cfg(feature = "redpallas")]
|
||||
use reddsa::frost::redpallas as frost;
|
||||
|
||||
use crate::Logger;
|
||||
use frost::{
|
||||
keys::KeyPackage,
|
||||
round1::SigningNonces,
|
||||
round2::{self, SignatureShare},
|
||||
Error, SigningPackage,
|
||||
};
|
||||
use std::io::BufRead;
|
||||
use std::io::{BufRead, Write};
|
||||
|
||||
// #[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Round2Config {
|
||||
pub signing_package: SigningPackage,
|
||||
#[cfg(feature = "redpallas")]
|
||||
|
@ -25,15 +24,15 @@ pub struct Round2Config {
|
|||
// TODO: handle errors
|
||||
pub fn round_2_request_inputs(
|
||||
input: &mut impl BufRead,
|
||||
logger: &mut dyn Logger,
|
||||
) -> Result<Round2Config, Error> {
|
||||
logger.log("=== Round 2 ===".to_string());
|
||||
logger: &mut dyn Write,
|
||||
) -> Result<Round2Config, Box<dyn std::error::Error>> {
|
||||
writeln!(logger, "=== Round 2 ===")?;
|
||||
|
||||
logger.log("Enter the JSON-encoded SigningPackage:".to_string());
|
||||
writeln!(logger, "Enter the JSON-encoded SigningPackage:")?;
|
||||
|
||||
let mut signing_package_json = String::new();
|
||||
|
||||
input.read_line(&mut signing_package_json).unwrap();
|
||||
input.read_line(&mut signing_package_json)?;
|
||||
|
||||
// TODO: change to return a generic Error and use a better error
|
||||
let signing_package: SigningPackage = serde_json::from_str(signing_package_json.trim())
|
||||
|
@ -41,7 +40,7 @@ pub fn round_2_request_inputs(
|
|||
|
||||
#[cfg(feature = "redpallas")]
|
||||
{
|
||||
logger.log("Enter the randomizer (hex string):".to_string());
|
||||
writeln!(logger, "Enter the randomizer (hex string):")?;
|
||||
|
||||
let mut json = String::new();
|
||||
|
||||
|
@ -81,11 +80,17 @@ pub fn generate_signature(
|
|||
Ok(signature)
|
||||
}
|
||||
|
||||
pub fn print_values_round_2(signature: SignatureShare, logger: &mut dyn Logger) {
|
||||
logger.log("Please send the following to the Coordinator".to_string());
|
||||
logger.log(format!(
|
||||
pub fn print_values_round_2(
|
||||
signature: SignatureShare,
|
||||
logger: &mut dyn Write,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
writeln!(logger, "Please send the following to the Coordinator")?;
|
||||
writeln!(
|
||||
logger,
|
||||
"SignatureShare:\n{}",
|
||||
serde_json::to_string(&signature).unwrap()
|
||||
));
|
||||
logger.log("=== End of Round 2 ===".to_string());
|
||||
)?;
|
||||
writeln!(logger, "=== End of Round 2 ===")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,103 +1,21 @@
|
|||
// use crate::cli::cli;
|
||||
// use frost::{keys::SigningShare, round1};
|
||||
// use frost_ed25519 as frost;
|
||||
// use hex::FromHex;
|
||||
// use participant::Logger;
|
||||
// use rand::thread_rng;
|
||||
use std::io::BufWriter;
|
||||
|
||||
// pub struct TestLogger(Vec<String>);
|
||||
use crate::cli::cli;
|
||||
|
||||
// impl Logger for TestLogger {
|
||||
// fn log(&mut self, value: String) {
|
||||
// self.0.push(value);
|
||||
// }
|
||||
// }
|
||||
#[test]
|
||||
fn check_cli() {
|
||||
let key_package = r#"{"identifier":"0100000000000000000000000000000000000000000000000000000000000000","value":"ee4a66fec3ced53cac04b0abc309bb57f03f8d7dede033e4ae7b6ef57630120f","commitment":["21446705fa7da298998a567a3c2fdd7274903a886dcde9a77f615d915feb6764","56ce223ffbde8ce5971be587cbb0b8b31aa2bc220a6803b9ce73c63f9f432514","6dcc10da9443ef2c9bbd5fc6a9c3bcd4c5ede8048cc0b1342b091fd1ff6dc53c"],"ciphersuite":"FROST(Ed25519, SHA-512)"}"#;
|
||||
|
||||
// #[test]
|
||||
// fn check_cli() {
|
||||
// // Round 1 inputs
|
||||
// let identifier = "1";
|
||||
// let pub_key = "470f53fb724502bf5b851471e9f8317616fcc7be9405ccff3347c232a3052ce7";
|
||||
// let group_pub_key = "42ae1baa1bce5a38c130e60aade154ec8775076e729881aba66dabd0c0ac6332";
|
||||
// let signing_share = "1edfa2ebd280cba9a72f0bc027d21c30078c11f92e0c908addb958062c1ac900";
|
||||
// let vss_commitment = "0342ae1baa1bce5a38c130e60aade154ec8775076e729881aba66dabd0c0ac6332393a813a6b47782f0fbe653593cbb7b0e0e13f01b54b801144545cb774c0fe5683d8bee3cd63b10523ccace10044869c56bce8a6061950f9aebd7f2e36249571";
|
||||
let signing_package = r#"{"signing_commitments":{"0100000000000000000000000000000000000000000000000000000000000000":{"hiding":"710a280fcedbcbe626fff055f682e4a525c31f157dd6071ef2c04ea0ecbe8de9","binding":"6dc707cdf26a589b3e2de4f6bae09b94d5d3bb939937b52bc6b16bdecd0b041f","ciphersuite":"FROST(Ed25519, SHA-512)"},"0200000000000000000000000000000000000000000000000000000000000000":{"hiding":"777f011bf695e27ce62474747a9c110cc3b827268047913a21030c3eba0e1eed","binding":"67f051035284cd619f0e7fc583eb3cb0c88d993aad621c856edc0f995f4588b2","ciphersuite":"FROST(Ed25519, SHA-512)"},"0300000000000000000000000000000000000000000000000000000000000000":{"hiding":"c052599bb7a52911b6b58e7c20747f12d45d23aab4aec98aaecdc7909dc6aff3","binding":"b3fbefc67070b1b56203ef875a2c7caf24802dbc943bdc62decac33287b63b23","ciphersuite":"FROST(Ed25519, SHA-512)"}},"message":"74657374","ciphersuite":"FROST(Ed25519, SHA-512)"}"#;
|
||||
let group_signature = "\"daae8e867c1c3000687a819262099c44e4799853729d87738b4811637a659f3075829c4ee6c5f6767e11b937e18dce20886b0d3f015caaf4ccdb76d4d185910c\"";
|
||||
|
||||
// // Round 2 inputs
|
||||
// let min_signers = "3";
|
||||
// const MESSAGE: &str = "15d21ccd7ee42959562fc8aa63224c8851fb3ec85a3faf66040d380fb9738673";
|
||||
// const IDENTIFIER_2: &str = "2";
|
||||
// const HIDING_COMMITMENT_2: &str =
|
||||
// "30f3f03bd739024dc5b1e9d422745a7f32b0971d5cef302106b30bd9f5642d70";
|
||||
// const BINDING_COMMITMENT_2: &str =
|
||||
// "a7ccae3750846fbd7d132efec85e96236a711b2097a6f03b1afa04f6029458cc";
|
||||
// const IDENTIFIER_3: &str = "3";
|
||||
// const HIDING_COMMITMENT_3: &str =
|
||||
// "d31bd81ce216b1c83912803a574a0285796275cb8b14f6dc92c8b09a6951f0a2";
|
||||
// const BINDING_COMMITMENT_3: &str =
|
||||
// "e1c863cfd08df775b6747ef2456e9bf9a03cc281a479a95261dc39137fcf0967";
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
|
||||
// let input = format!(
|
||||
// "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n",
|
||||
// identifier,
|
||||
// pub_key,
|
||||
// group_pub_key,
|
||||
// signing_share,
|
||||
// vss_commitment,
|
||||
// min_signers,
|
||||
// MESSAGE,
|
||||
// IDENTIFIER_2,
|
||||
// HIDING_COMMITMENT_2,
|
||||
// BINDING_COMMITMENT_2,
|
||||
// IDENTIFIER_3,
|
||||
// HIDING_COMMITMENT_3,
|
||||
// BINDING_COMMITMENT_3
|
||||
// );
|
||||
// let mut reader = input.as_bytes();
|
||||
// let mut test_logger = TestLogger(Vec::new());
|
||||
// let _out = cli(&mut reader, &mut test_logger);
|
||||
let input = format!(
|
||||
"{}\n{}\n{}\n",
|
||||
key_package, signing_package, group_signature
|
||||
);
|
||||
|
||||
// let mut rng = thread_rng();
|
||||
|
||||
// // We aren't testing randomness so this needs to be generated in the tests. TODO: mock the round1::commit function. To be improved in a later issue.
|
||||
// let (nonces, commitments) =
|
||||
// round1::commit(&SigningShare::from_hex(signing_share).unwrap(), &mut rng);
|
||||
|
||||
// let _hiding_nonce = hex::encode(nonces.hiding().serialize());
|
||||
// let _binding_nonce = hex::encode(nonces.binding().serialize());
|
||||
// let _hiding_commitment = hex::encode(commitments.hiding().serialize());
|
||||
// let _binding_commitment = hex::encode(commitments.binding().serialize());
|
||||
|
||||
// // let signature_share = hex::encode(sig_share.to_bytes());
|
||||
|
||||
// let log = [
|
||||
// "Your identifier (this should be an integer between 1 and 65535):",
|
||||
// "Your public key:",
|
||||
// "The group public key:",
|
||||
// "Your secret share:",
|
||||
// "Your verifiable secret sharing commitment:",
|
||||
// "Key Package succesfully created.",
|
||||
// "=== Round 1 ===",
|
||||
// "Hiding nonce: {}",
|
||||
// "Binding nonce: {}",
|
||||
// "Hiding commitment: {}",
|
||||
// "Binding commitment: {}",
|
||||
// "=== Round 1 Completed ===",
|
||||
// "Please send your Hiding and Binding Commitments to the coordinator",
|
||||
// "=== Round 2 ===",
|
||||
// "Number of signers:",
|
||||
// "Enter the message to sign (received from the coordinator):",
|
||||
// "Identifier:",
|
||||
// "Hiding commitment 2:",
|
||||
// "Binding commitment 2:",
|
||||
// "Identifier:",
|
||||
// "Hiding commitment 3:",
|
||||
// "Binding commitment 3:",
|
||||
// // "Signature share: {}", // TODO: this tests the signature share value returned is correct. The calculation is done in lib.rs tests.
|
||||
// // "=== Round 2 Completed ==="
|
||||
// ]
|
||||
// .to_vec();
|
||||
|
||||
// assert_eq!(test_logger.0[0..7], log[0..7]);
|
||||
// assert_eq!(test_logger.0[12..22], log[12..22]);
|
||||
// // TODO: test nonce and commitment values
|
||||
// }
|
||||
let signature = cli(&mut input.as_bytes(), &mut buf);
|
||||
assert!(signature.is_ok());
|
||||
}
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
use std::io::BufWriter;
|
||||
|
||||
#[cfg(test)]
|
||||
use frost::Identifier;
|
||||
use frost::{
|
||||
keys::{KeyPackage, SigningShare, VerifyingShare},
|
||||
round1, VerifyingKey,
|
||||
round1, Error, VerifyingKey,
|
||||
};
|
||||
use frost_ed25519 as frost;
|
||||
use hex::FromHex;
|
||||
use participant::round1::{print_values, request_inputs, Round1Config};
|
||||
|
||||
use participant::Logger;
|
||||
use rand::thread_rng;
|
||||
|
||||
const PUBLIC_KEY: &str = "adf6ab1f882d04988eadfaa52fb175bf37b6247785d7380fde3fb9d68032470d";
|
||||
|
@ -16,14 +17,6 @@ const GROUP_PUBLIC_KEY: &str = "087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34f
|
|||
const SIGNING_SHARE: &str = "ceed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104";
|
||||
const SECRET_SHARE_JSON: &str = r#"{"identifier":"0100000000000000000000000000000000000000000000000000000000000000","value":"ceed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104","commitment":["087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e","926d5910e146dccb9148ca39dc7607f4f7123ff1c0ffaf109add1d165c568bf2", "291bb78d7e4ef124f5aa6a36cbcf8c276e70fbb4e208212e916d762fc42c1bbc"],"ciphersuite":"FROST(Ed25519, SHA-512)"}"#;
|
||||
|
||||
pub struct TestLogger(Vec<String>);
|
||||
|
||||
impl Logger for TestLogger {
|
||||
fn log(&mut self, value: String) {
|
||||
self.0.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
fn build_key_package() -> KeyPackage {
|
||||
KeyPackage::new(
|
||||
Identifier::try_from(1).unwrap(),
|
||||
|
@ -39,81 +32,90 @@ fn check_valid_round_1_inputs() {
|
|||
key_package: build_key_package(),
|
||||
};
|
||||
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
|
||||
let input = SECRET_SHARE_JSON;
|
||||
let mut valid_input = input.as_bytes();
|
||||
|
||||
let expected = request_inputs(&mut valid_input, &mut test_logger).unwrap();
|
||||
let expected = request_inputs(&mut valid_input, &mut buf).unwrap();
|
||||
|
||||
assert_eq!(expected, config);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_0_input_for_identifier() {
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
|
||||
let input = r#"{"identifier":"0000000000000000000000000000000000000000000000000000000000000000","value":"ceed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104","commitment":["087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e","291bb78d7e4ef124f5aa6a36cbcf8c276e70fbb4e208212e916d762fc42c1bbc"],"ciphersuite":"FROST(Ed25519, SHA-512)"}"#;
|
||||
let mut invalid_input = input.as_bytes();
|
||||
|
||||
let expected = request_inputs(&mut invalid_input, &mut test_logger);
|
||||
// let expected = request_inputs(&mut invalid_input, &mut buf).unwrap_err();
|
||||
|
||||
assert!(expected.is_err());
|
||||
let expected = request_inputs(&mut invalid_input, &mut buf).unwrap_err();
|
||||
|
||||
assert_eq!(
|
||||
*expected.downcast::<Error>().unwrap(),
|
||||
Error::InvalidSecretShare
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_invalid_length_signing_share() {
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
|
||||
let input = r#"{"identifier":"0100000000000000000000000000000000000000000000000000000000000000","value":"ed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104","commitment":["087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e","291bb78d7e4ef124f5aa6a36cbcf8c276e70fbb4e208212e916d762fc42c1bbc"],"ciphersuite":"FROST(Ed25519, SHA-512)"}"#;
|
||||
|
||||
let mut invalid_input = input.as_bytes();
|
||||
|
||||
let expected = request_inputs(&mut invalid_input, &mut test_logger);
|
||||
let expected = request_inputs(&mut invalid_input, &mut buf).unwrap_err();
|
||||
|
||||
assert!(expected.is_err());
|
||||
assert_eq!(
|
||||
*expected.downcast::<Error>().unwrap(),
|
||||
Error::InvalidSecretShare
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_invalid_round_1_inputs() {
|
||||
let input = r#"{"value":"ceed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104","commitment":["087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e","926d5910e146dccb9148ca39dc7607f4f7123ff1c0ffaf109add1d165c568bf2", "291bb78d7e4ef124f5aa6a36cbcf8c276e70fbb4e208212e916d762fc42c1bbc"],"ciphersuite":"FROST(Ed25519, SHA-512)"}"#;
|
||||
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
|
||||
let mut valid_input = input.as_bytes();
|
||||
|
||||
let expected = request_inputs(&mut valid_input, &mut test_logger);
|
||||
assert!(expected.is_err());
|
||||
let expected = request_inputs(&mut valid_input, &mut buf).unwrap_err();
|
||||
assert_eq!(
|
||||
*expected.downcast::<Error>().unwrap(),
|
||||
Error::InvalidSecretShare
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: Handle this error differently
|
||||
#[test]
|
||||
fn check_invalid_length_vss_commitment() {
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
|
||||
let input = r#"{"identifier":"0100000000000000000000000000000000000000000000000000000000000000","value":"ceed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104","commitment":["7e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e","291bb78d7e4ef124f5aa6a36cbcf8c276e70fbb4e208212e916d762fc42c1bbc"],"ciphersuite":"FROST(Ed25519, SHA-512)"}"#;
|
||||
|
||||
let mut invalid_input = input.as_bytes();
|
||||
|
||||
let expected = request_inputs(&mut invalid_input, &mut test_logger);
|
||||
let expected = request_inputs(&mut invalid_input, &mut buf);
|
||||
assert!(expected.is_err())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_print_values() {
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
let signing_share =
|
||||
SigningShare::deserialize(<[u8; 32]>::from_hex(SIGNING_SHARE).unwrap()).unwrap();
|
||||
let mut rng = thread_rng();
|
||||
let (_nonces, commitments) = round1::commit(&signing_share, &mut rng);
|
||||
|
||||
print_values(commitments, &mut test_logger); // TODO: Run test without random
|
||||
print_values(commitments, &mut buf).unwrap(); // TODO: Run test without random
|
||||
|
||||
let log = [
|
||||
"=== Round 1 ===",
|
||||
"SigningNonces were generated and stored in memory",
|
||||
&format!("SigningCommitments:\n{{\"hiding\":\"{}\",\"binding\":\"{}\",\"ciphersuite\":\"FROST(Ed25519, SHA-512)\"}}", &hex::encode(commitments.hiding().serialize()), &hex::encode(commitments.binding().serialize())),
|
||||
"=== Round 1 Completed ===",
|
||||
"Please send your SigningCommitments to the coordinator"];
|
||||
assert_eq!(test_logger.0, log)
|
||||
let out = String::from_utf8(buf.into_inner().unwrap()).unwrap();
|
||||
|
||||
let log = format!("=== Round 1 ===\nSigningNonces were generated and stored in memory\nSigningCommitments:\n{{\"hiding\":\"{}\",\"binding\":\"{}\",\"ciphersuite\":\"FROST(Ed25519, SHA-512)\"}}\n=== Round 1 Completed ===\nPlease send your SigningCommitments to the coordinator\n", &hex::encode(commitments.hiding().serialize()), &hex::encode(commitments.binding().serialize()));
|
||||
|
||||
assert_eq!(out, log)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::{collections::BTreeMap, io::BufWriter};
|
||||
|
||||
#[cfg(test)]
|
||||
use frost::Identifier;
|
||||
|
@ -12,17 +12,8 @@ use frost_ed25519 as frost;
|
|||
use hex::FromHex;
|
||||
use participant::round2::print_values_round_2;
|
||||
use participant::round2::{generate_signature, round_2_request_inputs, Round2Config};
|
||||
use participant::Logger;
|
||||
use rand::thread_rng;
|
||||
|
||||
pub struct TestLogger(Vec<String>);
|
||||
|
||||
impl Logger for TestLogger {
|
||||
fn log(&mut self, value: String) {
|
||||
self.0.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
const PUBLIC_KEY: &str = "adf6ab1f882d04988eadfaa52fb175bf37b6247785d7380fde3fb9d68032470d";
|
||||
const GROUP_PUBLIC_KEY: &str = "087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e";
|
||||
const SIGNING_SHARE: &str = "ceed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104";
|
||||
|
@ -68,14 +59,12 @@ fn check_valid_round_2_inputs() {
|
|||
signing_package: SigningPackage::new(signer_commitments, &message),
|
||||
};
|
||||
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
|
||||
let input = format!("{}\n", signing_package);
|
||||
let mut valid_input = input.as_bytes();
|
||||
|
||||
println!("After valid input");
|
||||
|
||||
let round_2_config = round_2_request_inputs(&mut valid_input, &mut test_logger);
|
||||
let round_2_config = round_2_request_inputs(&mut valid_input, &mut buf);
|
||||
|
||||
assert!(round_2_config.is_ok());
|
||||
assert_eq!(
|
||||
|
@ -129,19 +118,20 @@ fn check_sign() {
|
|||
|
||||
#[test]
|
||||
fn check_print_values_round_2() {
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
|
||||
const SIGNATURE_SHARE: &str =
|
||||
"44055c54d0604cbd006f0d1713a22474d7735c5e8816b1878f62ca94bf105900";
|
||||
let signature_response =
|
||||
SignatureShare::deserialize(<[u8; 32]>::from_hex(SIGNATURE_SHARE).unwrap()).unwrap();
|
||||
|
||||
print_values_round_2(signature_response, &mut test_logger);
|
||||
print_values_round_2(signature_response, &mut buf).unwrap();
|
||||
|
||||
let log = [
|
||||
"Please send the following to the Coordinator",
|
||||
"SignatureShare:\n{\"share\":\"44055c54d0604cbd006f0d1713a22474d7735c5e8816b1878f62ca94bf105900\",\"ciphersuite\":\"FROST(Ed25519, SHA-512)\"}",
|
||||
"=== End of Round 2 ==="];
|
||||
let log = "Please send the following to the Coordinator\n".to_owned() +
|
||||
"SignatureShare:\n{\"share\":\"44055c54d0604cbd006f0d1713a22474d7735c5e8816b1878f62ca94bf105900\",\"ciphersuite\":\"FROST(Ed25519, SHA-512)\"}\n" +
|
||||
"=== End of Round 2 ===\n";
|
||||
|
||||
assert_eq!(test_logger.0, log);
|
||||
let out = String::from_utf8(buf.into_inner().unwrap()).unwrap();
|
||||
|
||||
assert_eq!(out, log);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
[package]
|
||||
name = "tests"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
frost-ed25519 = { version = "0.6.0", features = ["serde"] }
|
||||
reddsa = { git = "https://github.com/ZcashFoundation/reddsa.git", rev = "8534e283acf0015cc2450e2a6b49685a3bb3145d", features = ["frost"] }
|
||||
hex = "0.4"
|
||||
rand = "0.8"
|
||||
exitcode = "1.1.2"
|
||||
serde_json = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
frost-ed25519 = { version = "0.6.0", features = ["serde"] }
|
||||
dkg = { path = "../dkg"}
|
||||
trusted-dealer = { path = "../trusted-dealer"}
|
||||
participant = { path = "../participant"}
|
||||
coordinator = { path = "../coordinator"}
|
||||
rand = "0.8"
|
|
@ -0,0 +1,150 @@
|
|||
use frost_ed25519 as frost;
|
||||
|
||||
use frost::keys::IdentifierList;
|
||||
use frost::Identifier;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::HashMap;
|
||||
use std::io::BufWriter;
|
||||
|
||||
use rand::thread_rng;
|
||||
|
||||
use trusted_dealer::inputs::request_inputs as trusted_dealer_input;
|
||||
use trusted_dealer::trusted_dealer_keygen::trusted_dealer_keygen;
|
||||
|
||||
use participant::round2::round_2_request_inputs as participant_input_round_2;
|
||||
use participant::{
|
||||
round1::request_inputs as participant_input_round_1, round2::generate_signature,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn trusted_dealer_journey() {
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
let mut rng = thread_rng();
|
||||
|
||||
// Trusted dealer
|
||||
|
||||
let dealer_input = "3\n5\n\n";
|
||||
|
||||
let dealer_config = trusted_dealer_input(&mut dealer_input.as_bytes(), &mut buf).unwrap();
|
||||
|
||||
let (shares, pubkeys) =
|
||||
trusted_dealer_keygen(&dealer_config, IdentifierList::Default, &mut rng).unwrap();
|
||||
|
||||
// Coordinator step 1
|
||||
|
||||
let num_of_participants = 3;
|
||||
|
||||
let id_input_1 = "0100000000000000000000000000000000000000000000000000000000000000";
|
||||
let id_input_2 = "0200000000000000000000000000000000000000000000000000000000000000";
|
||||
let id_input_3 = "0300000000000000000000000000000000000000000000000000000000000000";
|
||||
|
||||
let participant_id_1 = Identifier::try_from(1).unwrap();
|
||||
let participant_id_2 = Identifier::try_from(2).unwrap();
|
||||
let participant_id_3 = Identifier::try_from(3).unwrap();
|
||||
|
||||
let step_1_input = format!(
|
||||
"{}\n{}\n{}\n{}\n{}\n",
|
||||
serde_json::to_string(&pubkeys).unwrap(),
|
||||
num_of_participants,
|
||||
id_input_1,
|
||||
id_input_2,
|
||||
id_input_3
|
||||
);
|
||||
|
||||
let participants_config =
|
||||
coordinator::step_1::step_1(&mut step_1_input.as_bytes(), &mut buf).unwrap();
|
||||
|
||||
// Participants round 1
|
||||
|
||||
let mut key_packages: HashMap<_, _> = HashMap::new();
|
||||
|
||||
for (identifier, secret_share) in shares {
|
||||
let key_package = frost::keys::KeyPackage::try_from(secret_share).unwrap();
|
||||
key_packages.insert(identifier, key_package);
|
||||
}
|
||||
|
||||
let mut nonces_map = HashMap::new();
|
||||
let mut commitments_map = BTreeMap::new();
|
||||
|
||||
for participant_index in 1..=3 {
|
||||
let participant_identifier = Identifier::try_from(participant_index).unwrap();
|
||||
|
||||
let share = key_packages[&participant_identifier].secret_share();
|
||||
|
||||
let round_1_input = format!(
|
||||
"{}\n",
|
||||
&serde_json::to_string(&key_packages[&participant_identifier]).unwrap()
|
||||
);
|
||||
let round_1_config =
|
||||
participant_input_round_1(&mut round_1_input.as_bytes(), &mut buf).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
round_1_config.key_package,
|
||||
key_packages[&participant_identifier]
|
||||
);
|
||||
|
||||
let (nonces, commitments) = frost::round1::commit(share, &mut rng);
|
||||
|
||||
nonces_map.insert(participant_identifier, nonces);
|
||||
commitments_map.insert(participant_identifier, commitments);
|
||||
}
|
||||
|
||||
// Coordinator step 2
|
||||
|
||||
let mut signature_shares = HashMap::new();
|
||||
let message = "74657374";
|
||||
|
||||
let step_2_input = format!(
|
||||
"{}\n{}\n{}\n{}\n",
|
||||
message,
|
||||
serde_json::to_string(&commitments_map[&participant_id_1]).unwrap(),
|
||||
serde_json::to_string(&commitments_map[&participant_id_2]).unwrap(),
|
||||
serde_json::to_string(&commitments_map[&participant_id_3]).unwrap()
|
||||
);
|
||||
|
||||
let signing_package = coordinator::step_2::step_2(
|
||||
&mut step_2_input.as_bytes(),
|
||||
&mut buf,
|
||||
vec![participant_id_1, participant_id_2, participant_id_3],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Participants round 2
|
||||
|
||||
for participant_identifier in nonces_map.keys() {
|
||||
let round_2_input = format!("{}\n", serde_json::to_string(&signing_package).unwrap());
|
||||
let round_2_config =
|
||||
participant_input_round_2(&mut round_2_input.as_bytes(), &mut buf).unwrap();
|
||||
let signature = generate_signature(
|
||||
round_2_config,
|
||||
&key_packages[participant_identifier],
|
||||
&nonces_map[participant_identifier],
|
||||
)
|
||||
.unwrap();
|
||||
signature_shares.insert(*participant_identifier, signature);
|
||||
}
|
||||
|
||||
// coordinator step 3
|
||||
|
||||
let step_3_input = format!(
|
||||
"{}\n{}\n{}\n",
|
||||
serde_json::to_string(&signature_shares[&participant_id_1]).unwrap(),
|
||||
serde_json::to_string(&signature_shares[&participant_id_2]).unwrap(),
|
||||
serde_json::to_string(&signature_shares[&participant_id_3]).unwrap()
|
||||
);
|
||||
let group_signature = coordinator::step_3::step_3(
|
||||
&mut step_3_input.as_bytes(),
|
||||
&mut buf,
|
||||
participants_config,
|
||||
signing_package,
|
||||
);
|
||||
|
||||
// verify
|
||||
|
||||
let is_signature_valid = pubkeys
|
||||
.group_public()
|
||||
.verify("test".as_bytes(), &group_signature)
|
||||
.is_ok();
|
||||
assert!(is_signature_valid);
|
||||
}
|
|
@ -4,37 +4,18 @@ use frost_ed25519 as frost;
|
|||
use reddsa::frost::redpallas as frost;
|
||||
|
||||
use frost::keys::IdentifierList;
|
||||
use frost::Error;
|
||||
use rand::thread_rng;
|
||||
use std::io;
|
||||
use std::io::{BufRead, Write};
|
||||
|
||||
use crate::inputs::request_inputs;
|
||||
use crate::output::{print_values, Logger};
|
||||
use crate::inputs::{print_values, request_inputs};
|
||||
use crate::trusted_dealer_keygen::{split_secret, trusted_dealer_keygen};
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum CliError {
|
||||
Config,
|
||||
Keygen,
|
||||
}
|
||||
|
||||
pub struct TrustedDealerError {
|
||||
pub frost_error: Error,
|
||||
pub cli_error: CliError,
|
||||
}
|
||||
|
||||
// Currently this defaults to the Default value for Identifiers
|
||||
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();
|
||||
// Currently this uses the Default Identifiers
|
||||
pub fn cli(
|
||||
input: &mut impl BufRead,
|
||||
logger: &mut impl Write,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let config = request_inputs(input, logger)?;
|
||||
|
||||
let mut rng = thread_rng();
|
||||
|
||||
|
@ -44,27 +25,9 @@ pub fn cli() -> Result<(), TrustedDealerError> {
|
|||
split_secret(&config, IdentifierList::Default, &mut rng)
|
||||
};
|
||||
|
||||
if let Err(e) = keygen {
|
||||
return Err(TrustedDealerError {
|
||||
frost_error: e,
|
||||
cli_error: CliError::Keygen,
|
||||
});
|
||||
}
|
||||
let (shares, pubkeys) = keygen?;
|
||||
|
||||
let (shares, pubkeys) = keygen.unwrap();
|
||||
|
||||
let mut console_logger = ConsoleLogger;
|
||||
|
||||
print_values(&shares, &pubkeys, &mut console_logger);
|
||||
print_values(&shares, &pubkeys, logger)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ConsoleLogger;
|
||||
|
||||
impl Logger for ConsoleLogger {
|
||||
fn log(&mut self, value: String) {
|
||||
println!("{}", value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,12 @@ use frost_ed25519 as frost;
|
|||
#[cfg(feature = "redpallas")]
|
||||
use reddsa::frost::redpallas as frost;
|
||||
|
||||
use frost::keys::{PublicKeyPackage, SecretShare};
|
||||
use frost::Error;
|
||||
use std::io::BufRead;
|
||||
use frost::Identifier;
|
||||
use itertools::Itertools;
|
||||
use std::collections::HashMap;
|
||||
use std::io::{BufRead, Write};
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Config {
|
||||
|
@ -29,30 +33,36 @@ fn validate_inputs(config: &Config) -> Result<(), Error> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn request_inputs(input: &mut impl BufRead) -> Result<Config, Error> {
|
||||
println!("The minimum number of signers: (2 or more)");
|
||||
pub fn request_inputs(
|
||||
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).unwrap();
|
||||
input.read_line(&mut min)?;
|
||||
|
||||
let min_signers = min
|
||||
.trim()
|
||||
.parse::<u16>()
|
||||
.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();
|
||||
input.read_line(&mut max)?;
|
||||
let max_signers = max
|
||||
.trim()
|
||||
.parse::<u16>()
|
||||
.map_err(|_| Error::InvalidMaxSigners)?;
|
||||
|
||||
println!("Secret key (press enter to randomly generate a fresh one): ");
|
||||
writeln!(
|
||||
logger,
|
||||
"Secret key (press enter to randomly generate a fresh one): "
|
||||
)?;
|
||||
|
||||
let mut secret_input = String::new();
|
||||
input.read_line(&mut secret_input).unwrap();
|
||||
input.read_line(&mut secret_input)?;
|
||||
let secret = hex::decode(secret_input.trim()).map_err(|_| Error::MalformedSigningKey)?;
|
||||
|
||||
let config = Config {
|
||||
|
@ -65,3 +75,31 @@ pub fn request_inputs(input: &mut impl BufRead) -> Result<Config, Error> {
|
|||
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
pub fn print_values(
|
||||
keys: &HashMap<Identifier, SecretShare>,
|
||||
pubkeys: &PublicKeyPackage,
|
||||
logger: &mut dyn Write,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
#[cfg(feature = "redpallas")]
|
||||
let pubkeys = pubkeys.clone().into_positive_y();
|
||||
#[cfg(feature = "redpallas")]
|
||||
let pubkeys = &pubkeys;
|
||||
|
||||
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()))?;
|
||||
writeln!(
|
||||
logger,
|
||||
"Secret share:\n{}",
|
||||
serde_json::to_string(v).unwrap()
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
pub mod cli;
|
||||
pub mod inputs;
|
||||
pub mod trusted_dealer_keygen;
|
|
@ -1,31 +1,15 @@
|
|||
mod cli;
|
||||
mod inputs;
|
||||
mod output;
|
||||
mod trusted_dealer_keygen;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use cli::CliError;
|
||||
use std::io;
|
||||
|
||||
use crate::cli::cli;
|
||||
use trusted_dealer::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)
|
||||
};
|
||||
}
|
||||
// TODO: Update to use exit codes
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut reader = Box::new(io::stdin().lock());
|
||||
let mut logger = io::stdout();
|
||||
cli(&mut reader, &mut logger)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
#[cfg(not(feature = "redpallas"))]
|
||||
use frost_ed25519 as frost;
|
||||
#[cfg(feature = "redpallas")]
|
||||
use reddsa::frost::redpallas as frost;
|
||||
#[cfg(feature = "redpallas")]
|
||||
use reddsa::frost::redpallas::keys::PositiveY;
|
||||
|
||||
use frost::keys::{PublicKeyPackage, SecretShare};
|
||||
use frost::Identifier;
|
||||
use itertools::Itertools;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub trait Logger {
|
||||
fn log(&mut self, value: String);
|
||||
}
|
||||
|
||||
fn get_identifier_value(i: Identifier) -> String {
|
||||
let s = i.serialize();
|
||||
let le_bytes: [u8; 2] = [s[0], s[1]];
|
||||
u16::from_le_bytes(le_bytes).to_string()
|
||||
}
|
||||
|
||||
pub fn print_values(
|
||||
keys: &HashMap<Identifier, SecretShare>,
|
||||
pubkeys: &PublicKeyPackage,
|
||||
logger: &mut dyn Logger,
|
||||
) {
|
||||
#[cfg(feature = "redpallas")]
|
||||
let pubkeys = pubkeys.clone().into_positive_y();
|
||||
#[cfg(feature = "redpallas")]
|
||||
let pubkeys = &pubkeys;
|
||||
|
||||
logger.log(format!(
|
||||
"Public key package:\n{}",
|
||||
serde_json::to_string(pubkeys).unwrap()
|
||||
));
|
||||
|
||||
println!("---");
|
||||
|
||||
for (k, v) in keys.iter().sorted_by_key(|x| x.0) {
|
||||
logger.log(format!("Participant: {}", get_identifier_value(*k)));
|
||||
logger.log(format!(
|
||||
"Secret share:\n{}",
|
||||
serde_json::to_string(v).unwrap()
|
||||
));
|
||||
println!("---")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::output::get_identifier_value;
|
||||
use frost::Identifier;
|
||||
use frost_ed25519 as frost;
|
||||
|
||||
#[test]
|
||||
fn check_get_identifier_value() {
|
||||
let min = "1";
|
||||
let identifier_min = Identifier::try_from(1).unwrap();
|
||||
|
||||
assert!(get_identifier_value(identifier_min) == min);
|
||||
|
||||
let max = "65535";
|
||||
let identifier_max = Identifier::try_from(65535).unwrap();
|
||||
|
||||
assert!(get_identifier_value(identifier_max) == max);
|
||||
}
|
||||
}
|
|
@ -1,3 +1,2 @@
|
|||
mod inputs_tests;
|
||||
mod integration_test;
|
||||
mod output_tests;
|
||||
mod inputs;
|
||||
mod print_values;
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
use std::io::BufWriter;
|
||||
|
||||
use frost::Error;
|
||||
use frost_ed25519 as frost;
|
||||
use trusted_dealer::inputs::{request_inputs, Config};
|
||||
|
||||
#[test]
|
||||
fn check_valid_input_for_signers() {
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
let config = Config {
|
||||
min_signers: 2,
|
||||
max_signers: 3,
|
||||
secret: Vec::new(),
|
||||
};
|
||||
|
||||
let mut valid_input = "2\n3\n\n".as_bytes();
|
||||
let expected = request_inputs(&mut valid_input, &mut buf).unwrap();
|
||||
|
||||
assert_eq!(expected, config);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_error_if_min_participant_greater_than_max_participant() {
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
let mut invalid_input = "4\n3\n\n".as_bytes();
|
||||
let expected = request_inputs(&mut invalid_input, &mut buf).unwrap_err();
|
||||
|
||||
assert_eq!(
|
||||
*expected.downcast::<Error>().unwrap(),
|
||||
Error::InvalidMinSigners
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_error_if_min_participant_is_less_than_2() {
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
let mut invalid_input = "1\n3\n\n".as_bytes();
|
||||
let expected = request_inputs(&mut invalid_input, &mut buf).unwrap_err();
|
||||
|
||||
assert_eq!(
|
||||
*expected.downcast::<Error>().unwrap(),
|
||||
Error::InvalidMinSigners
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_error_if_max_participant_is_less_than_2() {
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
let mut invalid_input = "2\n1\n\n".as_bytes();
|
||||
let expected = request_inputs(&mut invalid_input, &mut buf).unwrap_err();
|
||||
|
||||
assert_eq!(
|
||||
*expected.downcast::<Error>().unwrap(),
|
||||
Error::InvalidMaxSigners
|
||||
);
|
||||
}
|
||||
|
||||
// Testing inclusion of secret input
|
||||
|
||||
#[test]
|
||||
fn check_valid_input_with_secret() {
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
let mut valid_input =
|
||||
"3\n6\n7b1c33d3f5291d85de664833beb1ad469f7fb6025a0ec78b3a790c6e13a98304\n".as_bytes();
|
||||
let config = request_inputs(&mut valid_input, &mut buf).unwrap();
|
||||
|
||||
let secret: Vec<u8> = vec![
|
||||
123, 28, 51, 211, 245, 41, 29, 133, 222, 102, 72, 51, 190, 177, 173, 70, 159, 127, 182, 2,
|
||||
90, 14, 199, 139, 58, 121, 12, 110, 19, 169, 131, 4,
|
||||
];
|
||||
let expected = Config {
|
||||
min_signers: 3,
|
||||
max_signers: 6,
|
||||
secret,
|
||||
};
|
||||
|
||||
assert_eq!(expected, config)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_error_if_invalid_min_signers_input() {
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
let mut invalid_input = "hello\n6\n\n".as_bytes();
|
||||
let expected = request_inputs(&mut invalid_input, &mut buf).unwrap_err();
|
||||
|
||||
assert_eq!(
|
||||
*expected.downcast::<Error>().unwrap(),
|
||||
Error::InvalidMinSigners
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_error_if_invalid_max_signers_input() {
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
let mut invalid_input = "4\nworld\n\n".as_bytes();
|
||||
let expected = request_inputs(&mut invalid_input, &mut buf).unwrap_err();
|
||||
|
||||
assert_eq!(
|
||||
*expected.downcast::<Error>().unwrap(),
|
||||
Error::InvalidMaxSigners
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_malformed_signing_key_error_if_secret_is_invalid() {
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
let mut secret_input = "4\n6\nasecret\n".as_bytes();
|
||||
let expected = request_inputs(&mut secret_input, &mut buf).unwrap_err();
|
||||
|
||||
assert_eq!(
|
||||
*expected.downcast::<Error>().unwrap(),
|
||||
Error::MalformedSigningKey
|
||||
);
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
use crate::inputs::{request_inputs, Config};
|
||||
use frost::Error;
|
||||
use frost_ed25519 as frost;
|
||||
|
||||
#[test]
|
||||
fn check_valid_input_for_signers() {
|
||||
let config = Config {
|
||||
min_signers: 2,
|
||||
max_signers: 3,
|
||||
secret: Vec::new(),
|
||||
};
|
||||
|
||||
let mut valid_input = "2\n3\n\n".as_bytes();
|
||||
let expected = request_inputs(&mut valid_input);
|
||||
|
||||
assert_eq!(expected, Ok(config));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_error_if_min_participant_greater_than_max_participant() {
|
||||
let mut invalid_input = "4\n3\n\n".as_bytes();
|
||||
let expected = request_inputs(&mut invalid_input);
|
||||
|
||||
assert_eq!(expected, Err(Error::InvalidMinSigners));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_error_if_min_participant_is_less_than_2() {
|
||||
let mut invalid_input = "1\n3\n\n".as_bytes();
|
||||
let expected = request_inputs(&mut invalid_input);
|
||||
|
||||
assert_eq!(expected, Err(Error::InvalidMinSigners));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_error_if_max_participant_is_less_than_2() {
|
||||
let mut invalid_input = "2\n1\n\n".as_bytes();
|
||||
let expected = request_inputs(&mut invalid_input);
|
||||
|
||||
assert_eq!(expected, Err(Error::InvalidMaxSigners));
|
||||
}
|
||||
|
||||
// Testing inclusion of secret input
|
||||
|
||||
#[test]
|
||||
fn check_valid_input_with_secret() {
|
||||
let mut valid_input =
|
||||
"3\n6\n7b1c33d3f5291d85de664833beb1ad469f7fb6025a0ec78b3a790c6e13a98304\n".as_bytes();
|
||||
let config = request_inputs(&mut valid_input).unwrap();
|
||||
|
||||
let secret: Vec<u8> = vec![
|
||||
123, 28, 51, 211, 245, 41, 29, 133, 222, 102, 72, 51, 190, 177, 173, 70, 159, 127, 182, 2,
|
||||
90, 14, 199, 139, 58, 121, 12, 110, 19, 169, 131, 4,
|
||||
];
|
||||
let expected = Config {
|
||||
min_signers: 3,
|
||||
max_signers: 6,
|
||||
secret,
|
||||
};
|
||||
|
||||
assert_eq!(expected, config)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_error_if_invalid_min_signers_input() {
|
||||
let mut invalid_input = "hello\n6\n\n".as_bytes();
|
||||
let expected = request_inputs(&mut invalid_input);
|
||||
|
||||
assert_eq!(expected, Err(Error::InvalidMinSigners))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_error_if_invalid_max_signers_input() {
|
||||
let mut invalid_input = "4\nworld\n\n".as_bytes();
|
||||
let expected = request_inputs(&mut invalid_input);
|
||||
|
||||
assert_eq!(expected, Err(Error::InvalidMaxSigners))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_malformed_signing_key_error_if_secret_is_invalid() {
|
||||
let mut secret_input = "4\n6\nasecret\n".as_bytes();
|
||||
let expected = request_inputs(&mut secret_input);
|
||||
|
||||
assert_eq!(expected, Err(Error::MalformedSigningKey))
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
use frost::keys::IdentifierList;
|
||||
use frost_ed25519 as frost;
|
||||
use rand::thread_rng;
|
||||
|
||||
use crate::inputs::Config;
|
||||
use crate::output::{print_values, Logger};
|
||||
use crate::trusted_dealer_keygen::{split_secret, trusted_dealer_keygen};
|
||||
|
||||
struct TestLogger(Vec<String>);
|
||||
|
||||
impl Logger for TestLogger {
|
||||
fn log(&mut self, value: String) {
|
||||
self.0.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_output_without_secret() {
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
let mut rng = thread_rng();
|
||||
let config = Config {
|
||||
min_signers: 2,
|
||||
max_signers: 3,
|
||||
secret: Vec::new(),
|
||||
};
|
||||
let (shares, pubkeys) =
|
||||
trusted_dealer_keygen(&config, IdentifierList::Default, &mut rng).unwrap();
|
||||
|
||||
print_values(&shares, &pubkeys, &mut test_logger); // TODO: do we need shares here?
|
||||
|
||||
let public_key_package = serde_json::to_string(&pubkeys).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
test_logger.0[0],
|
||||
format!("Public key package:\n{}", public_key_package)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_output_with_secret() {
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
let mut rng = thread_rng();
|
||||
let secret: Vec<u8> = vec![
|
||||
123, 28, 51, 211, 245, 41, 29, 133, 222, 102, 72, 51, 190, 177, 173, 70, 159, 127, 182, 2,
|
||||
90, 14, 199, 139, 58, 121, 12, 110, 19, 169, 131, 4,
|
||||
];
|
||||
let config = Config {
|
||||
min_signers: 2,
|
||||
max_signers: 3,
|
||||
secret,
|
||||
};
|
||||
let (shares, pubkeys) = split_secret(&config, IdentifierList::Default, &mut rng).unwrap();
|
||||
|
||||
print_values(&shares, &pubkeys, &mut test_logger);
|
||||
|
||||
let public_key_package = serde_json::to_string(&pubkeys).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
test_logger.0[0],
|
||||
format!("Public key package:\n{}", public_key_package)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_output_with_large_num_of_signers() {
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
let mut rng = thread_rng();
|
||||
let config = Config {
|
||||
min_signers: 10,
|
||||
max_signers: 20,
|
||||
secret: Vec::new(),
|
||||
};
|
||||
let (shares, pubkeys) =
|
||||
trusted_dealer_keygen(&config, IdentifierList::Default, &mut rng).unwrap();
|
||||
|
||||
print_values(&shares, &pubkeys, &mut test_logger);
|
||||
|
||||
let public_key_package = serde_json::to_string(&pubkeys).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
test_logger.0[0],
|
||||
format!("Public key package:\n{}", public_key_package)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_output_with_secret_with_large_num_of_signers() {
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
let mut rng = thread_rng();
|
||||
let secret: Vec<u8> = vec![
|
||||
123, 28, 51, 211, 245, 41, 29, 133, 222, 102, 72, 51, 190, 177, 173, 70, 159, 127, 182, 2,
|
||||
90, 14, 199, 139, 58, 121, 12, 110, 19, 169, 131, 4,
|
||||
];
|
||||
let config = Config {
|
||||
min_signers: 10,
|
||||
max_signers: 20,
|
||||
secret,
|
||||
};
|
||||
let (shares, pubkeys) = split_secret(&config, IdentifierList::Default, &mut rng).unwrap();
|
||||
|
||||
print_values(&shares, &pubkeys, &mut test_logger);
|
||||
|
||||
let public_key_package = serde_json::to_string(&pubkeys).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
test_logger.0[0],
|
||||
format!("Public key package:\n{}", public_key_package)
|
||||
);
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
use frost::keys::{IdentifierList, PublicKeyPackage, SecretShare};
|
||||
use frost::Identifier;
|
||||
use frost_ed25519 as frost;
|
||||
use itertools::Itertools;
|
||||
use rand::thread_rng;
|
||||
use std::collections::HashMap;
|
||||
use std::io::BufWriter;
|
||||
|
||||
use trusted_dealer::inputs::print_values;
|
||||
use trusted_dealer::inputs::Config;
|
||||
use trusted_dealer::trusted_dealer_keygen::{split_secret, trusted_dealer_keygen};
|
||||
|
||||
fn build_output(shares: HashMap<Identifier, SecretShare>, pubkeys: PublicKeyPackage) -> String {
|
||||
let pub_key_package = format!(
|
||||
"Public key package:\n{}",
|
||||
serde_json::to_string(&pubkeys).unwrap()
|
||||
);
|
||||
|
||||
let mut out = pub_key_package;
|
||||
|
||||
for (k, v) in shares.iter().sorted_by_key(|x| x.0) {
|
||||
out = out
|
||||
+ &format!("\nParticipant: {}", hex::encode(k.serialize()))
|
||||
+ &format!("\nSecret share:\n{}", serde_json::to_string(v).unwrap())
|
||||
}
|
||||
|
||||
out + "\n"
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_output_without_secret() {
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
let mut rng = thread_rng();
|
||||
let config = Config {
|
||||
min_signers: 2,
|
||||
max_signers: 3,
|
||||
secret: Vec::new(),
|
||||
};
|
||||
let identifiers = IdentifierList::Default;
|
||||
let (shares, pubkeys) = trusted_dealer_keygen(&config, identifiers, &mut rng).unwrap();
|
||||
|
||||
print_values(&shares, &pubkeys, &mut buf).unwrap(); // TODO: do we need shares here?
|
||||
|
||||
let out = String::from_utf8(buf.into_inner().unwrap()).unwrap();
|
||||
|
||||
assert_eq!(out, build_output(shares, pubkeys));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_output_with_secret() {
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
let mut rng = thread_rng();
|
||||
let secret: Vec<u8> = vec![
|
||||
123, 28, 51, 211, 245, 41, 29, 133, 222, 102, 72, 51, 190, 177, 173, 70, 159, 127, 182, 2,
|
||||
90, 14, 199, 139, 58, 121, 12, 110, 19, 169, 131, 4,
|
||||
];
|
||||
let config = Config {
|
||||
min_signers: 2,
|
||||
max_signers: 3,
|
||||
secret,
|
||||
};
|
||||
let (shares, pubkeys) = split_secret(&config, IdentifierList::Default, &mut rng).unwrap();
|
||||
|
||||
print_values(&shares, &pubkeys, &mut buf).unwrap();
|
||||
|
||||
let out = String::from_utf8(buf.into_inner().unwrap()).unwrap();
|
||||
|
||||
assert_eq!(out, build_output(shares, pubkeys));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_output_with_large_num_of_signers() {
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
let mut rng = thread_rng();
|
||||
let config = Config {
|
||||
min_signers: 10,
|
||||
max_signers: 20,
|
||||
secret: Vec::new(),
|
||||
};
|
||||
let (shares, pubkeys) =
|
||||
trusted_dealer_keygen(&config, IdentifierList::Default, &mut rng).unwrap();
|
||||
|
||||
print_values(&shares, &pubkeys, &mut buf).unwrap();
|
||||
|
||||
let out = String::from_utf8(buf.into_inner().unwrap()).unwrap();
|
||||
|
||||
assert_eq!(out, build_output(shares, pubkeys));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_output_with_secret_with_large_num_of_signers() {
|
||||
let mut buf = BufWriter::new(Vec::new());
|
||||
let mut rng = thread_rng();
|
||||
let secret: Vec<u8> = vec![
|
||||
123, 28, 51, 211, 245, 41, 29, 133, 222, 102, 72, 51, 190, 177, 173, 70, 159, 127, 182, 2,
|
||||
90, 14, 199, 139, 58, 121, 12, 110, 19, 169, 131, 4,
|
||||
];
|
||||
let config = Config {
|
||||
min_signers: 10,
|
||||
max_signers: 20,
|
||||
secret,
|
||||
};
|
||||
let (shares, pubkeys) = split_secret(&config, IdentifierList::Default, &mut rng).unwrap();
|
||||
|
||||
print_values(&shares, &pubkeys, &mut buf).unwrap();
|
||||
|
||||
let out = String::from_utf8(buf.into_inner().unwrap()).unwrap();
|
||||
|
||||
assert_eq!(out, build_output(shares, pubkeys));
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
pub mod signature_gen;
|
|
@ -1,13 +1,14 @@
|
|||
use crate::inputs::Config;
|
||||
use crate::tests::integration_test::signature_gen::{key_package, round_1, round_2};
|
||||
use crate::trusted_dealer_keygen::split_secret;
|
||||
mod helpers;
|
||||
|
||||
use frost::aggregate;
|
||||
use frost::keys::IdentifierList;
|
||||
use frost_ed25519 as frost;
|
||||
use helpers::signature_gen::{key_package, round_1, round_2};
|
||||
use rand::thread_rng;
|
||||
use trusted_dealer::inputs::Config;
|
||||
use trusted_dealer::trusted_dealer_keygen::split_secret;
|
||||
|
||||
use crate::trusted_dealer_keygen::trusted_dealer_keygen;
|
||||
mod signature_gen;
|
||||
use trusted_dealer::trusted_dealer_keygen::trusted_dealer_keygen;
|
||||
|
||||
#[test]
|
||||
fn check_keygen_with_dealer() {
|
Loading…
Reference in New Issue