coordinator: use generics

This commit is contained in:
Conrado Gouvea 2024-06-21 18:06:15 -03:00 committed by natalie
parent ee7f341910
commit 50c4a21d13
14 changed files with 199 additions and 167 deletions

2
Cargo.lock generated
View File

@ -402,7 +402,9 @@ dependencies = [
"clap",
"exitcode",
"eyre",
"frost-core",
"frost-ed25519",
"frost-rerandomized",
"hex",
"itertools 0.13.0",
"message-io",

View File

@ -8,6 +8,8 @@ edition = "2021"
[dependencies]
async-trait = "0.1.80"
eyre = "0.6.12"
frost-core = { version = "1.0.0", features = ["serde"] }
frost-rerandomized = { version = "1.0.0", features = ["serde"] }
frost-ed25519 = { version = "1.0.0", features = ["serde"] }
reddsa = { git = "https://github.com/ZcashFoundation/reddsa.git", rev = "81c649c412e5b6ba56d491d2857f91fbd28adbc7", features = ["frost", "serde"] }
hex = { version = "0.4", features = ["serde"] }

View File

@ -3,6 +3,9 @@ use clap::Parser;
#[derive(Parser, Debug, Default)]
#[command(author, version, about, long_about = None)]
pub struct Args {
#[arg(short = 'C', long, default_value = "ed25519")]
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.
@ -32,7 +35,6 @@ pub struct Args {
/// The randomizer to use. Can be a file with the raw randomizer, empty, or
/// "-". If empty, a random one will be generated. If "-" is specified, then
/// it will be read from standard input as a hex string.
#[cfg(feature = "redpallas")]
#[arg(short = 'r', long, default_value = "")]
pub randomizer: String,

View File

@ -1,5 +1,7 @@
use std::io::{BufRead, Write};
use frost_rerandomized::RandomizedCiphersuite;
use crate::args::Args;
use crate::comms::cli::CLIComms;
use crate::comms::http::HTTPComms;
@ -7,20 +9,18 @@ use crate::comms::socket::SocketComms;
use crate::comms::Comms;
use crate::step_1::step_1;
use crate::step_2::step_2;
use crate::step_3::request_randomizer;
use crate::step_3::step_3;
#[cfg(feature = "redpallas")]
use crate::step_3::request_randomizer;
pub async fn cli(
pub async fn cli<C: RandomizedCiphersuite + 'static>(
args: &Args,
reader: &mut impl BufRead,
logger: &mut impl Write,
) -> Result<(), Box<dyn std::error::Error>> {
writeln!(logger, "\n=== STEP 1: CHOOSE PARTICIPANTS ===\n")?;
let mut comms: Box<dyn Comms> = if args.cli {
Box::new(CLIComms {})
let mut comms: Box<dyn Comms<C>> = if args.cli {
Box::new(CLIComms::new())
} else if args.http {
Box::new(HTTPComms::new(args))
} else {
@ -41,8 +41,11 @@ pub async fn cli(
participants_config.commitments.clone(),
)?;
#[cfg(feature = "redpallas")]
let randomizer = request_randomizer(args, reader, logger, &signing_package)?;
let randomizer = if args.ciphersuite == "redpallas" {
Some(request_randomizer(args, reader, logger, &signing_package)?)
} else {
None
};
writeln!(logger, "=== STEP 3: BUILD GROUP SIGNATURE ===\n")?;
@ -53,7 +56,6 @@ pub async fn cli(
logger,
participants_config,
&signing_package,
#[cfg(feature = "redpallas")]
randomizer,
)
.await?;

View File

@ -2,10 +2,7 @@ pub mod cli;
pub mod http;
pub mod socket;
#[cfg(not(feature = "redpallas"))]
use frost_ed25519 as frost;
#[cfg(feature = "redpallas")]
use reddsa::frost::redpallas as frost;
use frost_core::{self as frost, Ciphersuite};
use std::{
collections::BTreeMap,
@ -25,37 +22,35 @@ use frost::{
#[derive(Serialize, Deserialize)]
#[serde(crate = "self::serde")]
#[serde(bound = "C: Ciphersuite")]
#[allow(clippy::large_enum_variant)]
pub enum Message {
pub enum Message<C: Ciphersuite> {
IdentifiedCommitments {
identifier: Identifier,
commitments: SigningCommitments,
identifier: Identifier<C>,
commitments: SigningCommitments<C>,
},
#[cfg(not(feature = "redpallas"))]
SigningPackage(SigningPackage),
#[cfg(feature = "redpallas")]
SigningPackageAndRandomizer {
signing_package: SigningPackage,
randomizer: frost::round2::Randomizer,
signing_package: SigningPackage<C>,
randomizer: Option<frost_rerandomized::Randomizer<C>>,
},
SignatureShare(SignatureShare),
SignatureShare(SignatureShare<C>),
}
#[async_trait(?Send)]
pub trait Comms {
pub trait Comms<C: Ciphersuite> {
async fn get_signing_commitments(
&mut self,
input: &mut dyn BufRead,
output: &mut dyn Write,
pub_key_package: &PublicKeyPackage,
pub_key_package: &PublicKeyPackage<C>,
num_of_participants: u16,
) -> Result<BTreeMap<Identifier, SigningCommitments>, Box<dyn Error>>;
) -> Result<BTreeMap<Identifier<C>, SigningCommitments<C>>, Box<dyn Error>>;
async fn get_signature_shares(
&mut self,
input: &mut dyn BufRead,
output: &mut dyn Write,
signing_package: &SigningPackage,
#[cfg(feature = "redpallas")] randomizer: frost::round2::Randomizer,
) -> Result<BTreeMap<Identifier, SignatureShare>, Box<dyn Error>>;
signing_package: &SigningPackage<C>,
randomizer: Option<frost_rerandomized::Randomizer<C>>,
) -> Result<BTreeMap<Identifier<C>, SignatureShare<C>>, Box<dyn Error>>;
}

View File

@ -1,9 +1,8 @@
//! Command line interface implementation of the Comms trait.
#[cfg(not(feature = "redpallas"))]
use frost_ed25519 as frost;
#[cfg(feature = "redpallas")]
use reddsa::frost::redpallas as frost;
use frost_core as frost;
use frost_core::Ciphersuite;
use eyre::eyre;
@ -18,23 +17,49 @@ use std::{
collections::BTreeMap,
error::Error,
io::{BufRead, Write},
marker::PhantomData,
};
use super::Comms;
pub struct CLIComms {}
pub struct CLIComms<C: Ciphersuite> {
_phantom: PhantomData<C>,
}
impl<C> CLIComms<C>
where
C: Ciphersuite,
{
pub fn new() -> Self {
Self {
_phantom: Default::default(),
}
}
}
impl<C> Default for CLIComms<C>
where
C: Ciphersuite,
{
fn default() -> Self {
Self::new()
}
}
#[async_trait(?Send)]
impl Comms for CLIComms {
impl<C> Comms<C> for CLIComms<C>
where
C: Ciphersuite + 'static,
{
async fn get_signing_commitments(
&mut self,
input: &mut dyn BufRead,
output: &mut dyn Write,
pub_key_package: &PublicKeyPackage,
pub_key_package: &PublicKeyPackage<C>,
num_of_participants: u16,
) -> Result<BTreeMap<Identifier, SigningCommitments>, Box<dyn Error>> {
) -> Result<BTreeMap<Identifier<C>, SigningCommitments<C>>, Box<dyn Error>> {
let mut participants_list = Vec::new();
let mut commitments_list: BTreeMap<Identifier, SigningCommitments> = BTreeMap::new();
let mut commitments_list: BTreeMap<Identifier<C>, SigningCommitments<C>> = BTreeMap::new();
for i in 1..=num_of_participants {
writeln!(output, "Identifier for participant {:?} (hex encoded): ", i)?;
@ -60,10 +85,13 @@ impl Comms for CLIComms {
&mut self,
input: &mut dyn BufRead,
output: &mut dyn Write,
signing_package: &SigningPackage,
#[cfg(feature = "redpallas")] _randomizer: frost::round2::Randomizer,
) -> Result<BTreeMap<Identifier, SignatureShare>, Box<dyn Error>> {
let mut signatures_list: BTreeMap<Identifier, SignatureShare> = BTreeMap::new();
signing_package: &SigningPackage<C>,
randomizer: Option<frost_rerandomized::Randomizer<C>>,
) -> Result<BTreeMap<Identifier<C>, SignatureShare<C>>, Box<dyn Error>> {
if randomizer.is_some() {
panic!("rerandomized not supported");
}
let mut signatures_list: BTreeMap<Identifier<C>, SignatureShare<C>> = BTreeMap::new();
for p in signing_package.signing_commitments().keys() {
writeln!(
output,
@ -80,20 +108,22 @@ impl Comms for CLIComms {
}
}
pub fn read_identifier(input: &mut dyn BufRead) -> Result<Identifier, Box<dyn Error>> {
pub fn read_identifier<C: Ciphersuite + 'static>(
input: &mut dyn BufRead,
) -> Result<Identifier<C>, Box<dyn Error>> {
let mut identifier_input = String::new();
input.read_line(&mut identifier_input)?;
let bytes = hex::decode(identifier_input.trim())?;
let serialization = bytes.try_into().map_err(|_| eyre!("Invalid Identifier"))?;
let identifier = Identifier::deserialize(&serialization)?;
let identifier = Identifier::<C>::deserialize(&serialization)?;
Ok(identifier)
}
pub fn validate(
id: Identifier,
key_package: &PublicKeyPackage,
id_list: &[Identifier],
) -> Result<(), frost::Error> {
pub fn validate<C: Ciphersuite>(
id: Identifier<C>,
key_package: &PublicKeyPackage<C>,
id_list: &[Identifier<C>],
) -> Result<(), frost::Error<C>> {
if !key_package.verifying_shares().contains_key(&id) {
return Err(frost::Error::MalformedIdentifier);
}; // TODO: Error is actually that the identifier does not exist

View File

@ -2,10 +2,9 @@
use async_trait::async_trait;
#[cfg(not(feature = "redpallas"))]
use frost_ed25519 as frost;
#[cfg(feature = "redpallas")]
use reddsa::frost::redpallas as frost;
use frost_core as frost;
use frost_core::Ciphersuite;
use eyre::eyre;
use server::Uuid;
@ -19,38 +18,41 @@ use std::{
collections::BTreeMap,
error::Error,
io::{BufRead, Write},
marker::PhantomData,
time::Duration,
};
use super::Comms;
use crate::args::Args;
pub struct HTTPComms {
pub struct HTTPComms<C: Ciphersuite> {
client: reqwest::Client,
host_port: String,
session_id: Option<Uuid>,
_phantom: PhantomData<C>,
}
impl HTTPComms {
impl<C: Ciphersuite> HTTPComms<C> {
pub fn new(args: &Args) -> Self {
let client = reqwest::Client::new();
Self {
client,
host_port: format!("http://{}:{}", args.ip, args.port),
session_id: None,
_phantom: Default::default(),
}
}
}
#[async_trait(?Send)]
impl Comms for HTTPComms {
impl<C: Ciphersuite + 'static> Comms<C> for HTTPComms<C> {
async fn get_signing_commitments(
&mut self,
_input: &mut dyn BufRead,
_output: &mut dyn Write,
_pub_key_package: &PublicKeyPackage,
_pub_key_package: &PublicKeyPackage<C>,
num_signers: u16,
) -> Result<BTreeMap<Identifier, SigningCommitments>, Box<dyn Error>> {
) -> Result<BTreeMap<Identifier<C>, SigningCommitments<C>>, Box<dyn Error>> {
let r = self
.client
.post(format!("{}/create_new_session", self.host_port))
@ -103,9 +105,9 @@ impl Comms for HTTPComms {
&mut self,
_input: &mut dyn BufRead,
_output: &mut dyn Write,
signing_package: &SigningPackage,
#[cfg(feature = "redpallas")] randomizer: frost::round2::Randomizer,
) -> Result<BTreeMap<Identifier, SignatureShare>, Box<dyn Error>> {
signing_package: &SigningPackage<C>,
randomizer: Option<frost_rerandomized::Randomizer<C>>,
) -> Result<BTreeMap<Identifier<C>, SignatureShare<C>>, Box<dyn Error>> {
// Send SigningPackage to all participants
eprintln!("Sending SigningPackage to participants...");
@ -116,10 +118,7 @@ impl Comms for HTTPComms {
aux_msg: Default::default(),
session_id: self.session_id.unwrap(),
signing_package: vec![signing_package.try_into()?],
#[cfg(feature = "redpallas")]
randomizer: vec![randomizer.into()],
#[cfg(not(feature = "redpallas"))]
randomizer: vec![],
randomizer: randomizer.map(|r| vec![r.into()]).unwrap_or_default(),
})
.send()
.await?

View File

@ -1,10 +1,10 @@
//! Socket implementation of the Comms trait, using message-io.
use async_trait::async_trait;
#[cfg(not(feature = "redpallas"))]
use frost_ed25519 as frost;
#[cfg(feature = "redpallas")]
use reddsa::frost::redpallas as frost;
use frost_core as frost;
use frost_core::Ciphersuite;
use eyre::eyre;
use message_io::{
@ -22,18 +22,20 @@ use std::{
collections::BTreeMap,
error::Error,
io::{BufRead, Write},
marker::PhantomData,
};
use super::{Comms, Message};
use crate::args::Args;
pub struct SocketComms {
pub struct SocketComms<C: Ciphersuite> {
input_rx: Receiver<(Endpoint, Vec<u8>)>,
endpoints: BTreeMap<Identifier, Endpoint>,
endpoints: BTreeMap<Identifier<C>, Endpoint>,
handler: NodeHandler<()>,
_phantom: PhantomData<C>,
}
impl SocketComms {
impl<C: Ciphersuite> SocketComms<C> {
pub fn new(args: &Args) -> Self {
let (handler, listener) = node::split::<()>();
let addr = format!("{}:{}", args.ip, args.port);
@ -48,6 +50,7 @@ impl SocketComms {
input_rx: rx,
endpoints: BTreeMap::new(),
handler,
_phantom: Default::default(),
};
// TODO: save handle
@ -71,14 +74,14 @@ impl SocketComms {
}
#[async_trait(?Send)]
impl Comms for SocketComms {
impl<C: Ciphersuite> Comms<C> for SocketComms<C> {
async fn get_signing_commitments(
&mut self,
_input: &mut dyn BufRead,
_output: &mut dyn Write,
_pub_key_package: &PublicKeyPackage,
_pub_key_package: &PublicKeyPackage<C>,
num_of_participants: u16,
) -> Result<BTreeMap<Identifier, SigningCommitments>, Box<dyn Error>> {
) -> Result<BTreeMap<Identifier<C>, SigningCommitments<C>>, Box<dyn Error>> {
self.endpoints = BTreeMap::new();
let mut signing_commitments = BTreeMap::new();
eprintln!("Waiting for participants to send their commitments...");
@ -88,7 +91,7 @@ impl Comms for SocketComms {
.recv()
.await
.ok_or(eyre!("Did not receive all commitments"))?;
let message: Message = serde_json::from_slice(&data)?;
let message: Message<C> = serde_json::from_slice(&data)?;
if let Message::IdentifiedCommitments {
identifier,
commitments,
@ -107,15 +110,12 @@ impl Comms for SocketComms {
&mut self,
_input: &mut dyn BufRead,
_output: &mut dyn Write,
signing_package: &SigningPackage,
#[cfg(feature = "redpallas")] randomizer: frost::round2::Randomizer,
) -> Result<BTreeMap<Identifier, SignatureShare>, Box<dyn Error>> {
signing_package: &SigningPackage<C>,
randomizer: Option<frost_rerandomized::Randomizer<C>>,
) -> Result<BTreeMap<Identifier<C>, SignatureShare<C>>, Box<dyn Error>> {
// Send SigningPackage to all participants
eprintln!("Sending SigningPackage to participants...");
#[cfg(not(feature = "redpallas"))]
let data = serde_json::to_vec(&Message::SigningPackage(signing_package.clone()))?;
#[cfg(feature = "redpallas")]
let data = serde_json::to_vec(&Message::SigningPackageAndRandomizer {
signing_package: signing_package.clone(),
randomizer,
@ -138,7 +138,7 @@ impl Comms for SocketComms {
.recv()
.await
.ok_or(eyre!("Did not receive all commitments"))?;
let message: Message = serde_json::from_slice(&data)?;
let message: Message<C> = serde_json::from_slice(&data)?;
if let Message::SignatureShare(signature_share) = message {
let identifier = self
.endpoints

View File

@ -1,4 +1,3 @@
#[cfg(all(test, not(feature = "redpallas")))]
mod tests;
use std::io;
@ -13,7 +12,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut reader = Box::new(io::stdin().lock());
let mut logger = io::stdout();
let r = cli(&args, &mut reader, &mut logger).await;
let r = if args.ciphersuite == "ed25519" {
cli::<frost_ed25519::Ed25519Sha512>(&args, &mut reader, &mut logger).await
} else if args.ciphersuite == "redpallas" {
cli::<reddsa::frost::redpallas::PallasBlake2b512>(&args, &mut reader, &mut logger).await
} else {
panic!("invalid ciphersuite");
};
// Force process to exit; since socket comms spawn a thread, it will keep
// running forever. Ideally we should join() the thread but this works for

View File

@ -1,7 +1,4 @@
#[cfg(not(feature = "redpallas"))]
use frost_ed25519 as frost;
#[cfg(feature = "redpallas")]
use reddsa::frost::redpallas as frost;
use frost_core::{self as frost, Ciphersuite};
use frost::{keys::PublicKeyPackage, round1::SigningCommitments, Identifier};
@ -13,18 +10,18 @@ use std::{
use crate::{args::Args, comms::Comms, input::read_from_file_or_stdin};
#[derive(PartialEq, Debug)]
pub struct ParticipantsConfig {
pub commitments: BTreeMap<Identifier, SigningCommitments>,
pub pub_key_package: PublicKeyPackage,
pub struct ParticipantsConfig<C: Ciphersuite> {
pub commitments: BTreeMap<Identifier<C>, SigningCommitments<C>>,
pub pub_key_package: PublicKeyPackage<C>,
}
// TODO: needs to include the coordinator's keys!
pub async fn step_1(
pub async fn step_1<C: Ciphersuite>(
args: &Args,
comms: &mut dyn Comms,
comms: &mut dyn Comms<C>,
reader: &mut dyn BufRead,
logger: &mut dyn Write,
) -> Result<ParticipantsConfig, Box<dyn std::error::Error>> {
) -> Result<ParticipantsConfig<C>, Box<dyn std::error::Error>> {
let participants = read_commitments(args, comms, reader, logger).await?;
print_participants(logger, &participants.commitments);
Ok(participants)
@ -36,12 +33,12 @@ pub async fn step_1(
// 1. public key package
// 2. number of participants
// 3. identifiers for all participants
async fn read_commitments(
async fn read_commitments<C: Ciphersuite>(
args: &Args,
comms: &mut dyn Comms,
comms: &mut dyn Comms<C>,
input: &mut dyn BufRead,
logger: &mut dyn Write,
) -> Result<ParticipantsConfig, Box<dyn std::error::Error>> {
) -> Result<ParticipantsConfig<C>, Box<dyn std::error::Error>> {
let out = read_from_file_or_stdin(
input,
logger,
@ -49,7 +46,7 @@ async fn read_commitments(
&args.public_key_package,
)?;
let pub_key_package: PublicKeyPackage = serde_json::from_str(&out)?;
let pub_key_package: PublicKeyPackage<C> = serde_json::from_str(&out)?;
let num_of_participants = if args.num_signers == 0 {
writeln!(logger, "The number of participants: ")?;
@ -71,9 +68,9 @@ async fn read_commitments(
})
}
pub fn print_participants(
pub fn print_participants<C: Ciphersuite>(
logger: &mut dyn Write,
participants: &BTreeMap<Identifier, SigningCommitments>,
participants: &BTreeMap<Identifier<C>, SigningCommitments<C>>,
) {
writeln!(logger, "Selected participants: ",).unwrap();
@ -82,15 +79,14 @@ pub fn print_participants(
}
}
#[cfg(all(test, not(feature = "redpallas")))]
#[cfg(test)]
mod tests {
use std::collections::BTreeMap;
use frost::{
use frost_ed25519::{
keys::{PublicKeyPackage, VerifyingShare},
Error, Identifier, VerifyingKey,
};
use frost_ed25519 as frost;
use hex::FromHex;
use crate::comms::cli::validate;

View File

@ -1,7 +1,4 @@
#[cfg(not(feature = "redpallas"))]
use frost_ed25519 as frost;
#[cfg(feature = "redpallas")]
use reddsa::frost::redpallas as frost;
use frost_core::{self as frost, Ciphersuite};
use frost::{round1::SigningCommitments, Identifier, SigningPackage};
@ -14,17 +11,17 @@ use std::{
use crate::args::Args;
#[derive(Debug, PartialEq, Clone)]
pub struct CommitmentsConfig {
pub struct CommitmentsConfig<C: Ciphersuite> {
pub message: Vec<u8>,
pub signer_commitments: BTreeMap<Identifier, SigningCommitments>,
pub signer_commitments: BTreeMap<Identifier<C>, SigningCommitments<C>>,
}
pub fn step_2(
pub fn step_2<C: Ciphersuite>(
args: &Args,
input: &mut impl BufRead,
logger: &mut dyn Write,
commitments: BTreeMap<Identifier, SigningCommitments>,
) -> Result<SigningPackage, Box<dyn std::error::Error>> {
commitments: BTreeMap<Identifier<C>, SigningCommitments<C>>,
) -> Result<SigningPackage<C>, Box<dyn std::error::Error>> {
let signing_package = request_message(args, input, logger, commitments)?;
print_signing_package(logger, &signing_package);
Ok(signing_package)
@ -32,12 +29,12 @@ pub fn step_2(
// Input required:
// 1. message
fn request_message(
fn request_message<C: Ciphersuite>(
args: &Args,
input: &mut impl BufRead,
logger: &mut dyn Write,
commitments: BTreeMap<Identifier, SigningCommitments>,
) -> Result<SigningPackage, Box<dyn std::error::Error>> {
commitments: BTreeMap<Identifier<C>, SigningCommitments<C>>,
) -> Result<SigningPackage<C>, Box<dyn std::error::Error>> {
let message = if args.message.is_empty() {
writeln!(logger, "The message to be signed (hex encoded)")?;
@ -55,7 +52,10 @@ fn request_message(
Ok(signing_package)
}
fn print_signing_package(logger: &mut dyn Write, signing_package: &SigningPackage) {
fn print_signing_package<C: Ciphersuite>(
logger: &mut dyn Write,
signing_package: &SigningPackage<C>,
) {
writeln!(
logger,
"Signing Package:\n{}",

View File

@ -1,9 +1,7 @@
#[cfg(not(feature = "redpallas"))]
use frost_ed25519 as frost;
#[cfg(feature = "redpallas")]
use reddsa::frost::redpallas as frost;
use frost_core::{self as frost, Ciphersuite};
use frost::{Signature, SigningPackage};
use frost_rerandomized::RandomizedCiphersuite;
use std::{
fs,
@ -12,16 +10,15 @@ use std::{
use crate::{args::Args, comms::Comms, step_1::ParticipantsConfig};
#[cfg(feature = "redpallas")]
pub fn request_randomizer(
pub fn request_randomizer<C: RandomizedCiphersuite + 'static>(
args: &Args,
input: &mut impl BufRead,
logger: &mut dyn Write,
signing_package: &SigningPackage,
) -> Result<frost::round2::Randomizer, Box<dyn std::error::Error>> {
signing_package: &SigningPackage<C>,
) -> Result<frost_rerandomized::Randomizer<C>, Box<dyn std::error::Error>> {
if args.randomizer.is_empty() {
let rng = rand::thread_rng();
return Ok(frost::round2::Randomizer::new(rng, signing_package)?);
return Ok(frost_rerandomized::Randomizer::new(rng, signing_package)?);
};
let randomizer = if args.randomizer == "-" {
writeln!(logger, "Enter the randomizer (hex string):")?;
@ -35,29 +32,28 @@ pub fn request_randomizer(
fs::read(&args.randomizer)?
};
Ok(frost::round2::Randomizer::deserialize(
Ok(frost_rerandomized::Randomizer::deserialize(
&randomizer
.try_into()
.map_err(|_| frost::Error::MalformedIdentifier)?,
.map_err(|_| frost::Error::<C>::MalformedIdentifier)?,
)?)
}
pub async fn step_3(
pub async fn step_3<C: Ciphersuite>(
args: &Args,
comms: &mut dyn Comms,
comms: &mut dyn Comms<C>,
input: &mut dyn BufRead,
logger: &mut dyn Write,
participants: ParticipantsConfig,
signing_package: &SigningPackage,
#[cfg(feature = "redpallas")] randomizer: frost::round2::Randomizer,
) -> Result<Signature, Box<dyn std::error::Error>> {
participants: ParticipantsConfig<C>,
signing_package: &SigningPackage<C>,
randomizer: Option<frost_rerandomized::Randomizer<C>>,
) -> Result<Signature<C>, Box<dyn std::error::Error>> {
let group_signature = request_inputs_signature_shares(
comms,
input,
logger,
participants,
signing_package,
#[cfg(feature = "redpallas")]
randomizer,
)
.await?;
@ -68,46 +64,47 @@ pub async fn step_3(
// Input required:
// 1. number of signers (TODO: maybe pass this in?)
// 2. signatures for all signers
async fn request_inputs_signature_shares(
comms: &mut dyn Comms,
async fn request_inputs_signature_shares<C: Ciphersuite>(
comms: &mut dyn Comms<C>,
input: &mut dyn BufRead,
logger: &mut dyn Write,
participants: ParticipantsConfig,
signing_package: &SigningPackage,
#[cfg(feature = "redpallas")] randomizer: frost::round2::Randomizer,
) -> Result<Signature, Box<dyn std::error::Error>> {
participants: ParticipantsConfig<C>,
signing_package: &SigningPackage<C>,
randomizer: Option<frost_rerandomized::Randomizer<C>>,
) -> Result<Signature<C>, Box<dyn std::error::Error>> {
let signatures_list = comms
.get_signature_shares(
input,
logger,
signing_package,
#[cfg(feature = "redpallas")]
randomizer,
)
.get_signature_shares(input, logger, signing_package, randomizer)
.await?;
#[cfg(feature = "redpallas")]
let randomizer_params = frost::RandomizedParams::from_randomizer(
participants.pub_key_package.verifying_key(),
randomizer,
);
let group_signature = if let Some(randomizer) = randomizer {
let randomizer_params = frost_rerandomized::RandomizedParams::<C>::from_randomizer(
participants.pub_key_package.verifying_key(),
randomizer,
);
let group_signature = frost::aggregate(
signing_package,
&signatures_list,
&participants.pub_key_package,
#[cfg(feature = "redpallas")]
&randomizer_params,
)
.unwrap();
frost_rerandomized::aggregate(
signing_package,
&signatures_list,
&participants.pub_key_package,
&randomizer_params,
)
.unwrap()
} else {
frost::aggregate::<C>(
signing_package,
&signatures_list,
&participants.pub_key_package,
)
.unwrap()
};
Ok(group_signature)
}
fn print_signature(
fn print_signature<C: Ciphersuite>(
args: &Args,
logger: &mut dyn Write,
group_signature: Signature,
group_signature: Signature<C>,
) -> Result<(), Box<dyn std::error::Error>> {
if args.signature.is_empty() {
writeln!(

View File

@ -1,4 +1,4 @@
#[cfg(test)]
#![cfg(test)]
pub struct Helpers {
pub participant_id_1: String,

View File

@ -1,4 +1,5 @@
#[cfg(test)]
#![cfg(test)]
use coordinator::{
args::Args,
comms::cli::CLIComms,
@ -96,7 +97,7 @@ async fn check_step_1() {
..
} = get_helpers();
let mut comms = CLIComms {};
let mut comms = CLIComms::new();
let args = Args::default();
let mut buf = BufWriter::new(Vec::new());
@ -201,7 +202,7 @@ async fn check_step_3() {
..
} = get_helpers();
let mut comms = CLIComms {};
let mut comms = CLIComms::new();
let mut buf = BufWriter::new(Vec::new());
let args = Args::default();
@ -235,6 +236,7 @@ async fn check_step_3() {
&mut buf,
participants_config,
&signing_package,
None,
)
.await
.unwrap();