coordinator: use generics
This commit is contained in:
parent
ee7f341910
commit
50c4a21d13
|
@ -402,7 +402,9 @@ dependencies = [
|
|||
"clap",
|
||||
"exitcode",
|
||||
"eyre",
|
||||
"frost-core",
|
||||
"frost-ed25519",
|
||||
"frost-rerandomized",
|
||||
"hex",
|
||||
"itertools 0.13.0",
|
||||
"message-io",
|
||||
|
|
|
@ -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"] }
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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?;
|
||||
|
|
|
@ -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>>;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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{}",
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#[cfg(test)]
|
||||
#![cfg(test)]
|
||||
|
||||
pub struct Helpers {
|
||||
pub participant_id_1: String,
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue