diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index f60e2130..70186cf0 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -27,7 +27,7 @@ jobs: with: persist-credentials: false - - uses: dtolnay/rust-toolchain@nightly + - uses: dtolnay/rust-toolchain@stable with: components: llvm-tools-preview diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e7d80a8b..3fc078e1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,16 +10,13 @@ on: jobs: - # We're using nightly for the async traits. - # TODO: Revert back to stable when that is stabilized. - test_ed25519: name: Test with ed25519 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4.1.1 - - uses: dtolnay/rust-toolchain@nightly + - uses: dtolnay/rust-toolchain@stable - run: cargo test test_redpallas: @@ -28,7 +25,7 @@ jobs: steps: - uses: actions/checkout@v4.1.1 - - uses: dtolnay/rust-toolchain@nightly + - uses: dtolnay/rust-toolchain@stable - run: cargo test --features redpallas clippy: @@ -39,7 +36,7 @@ jobs: - uses: actions/checkout@v4.1.1 with: persist-credentials: false - - uses: dtolnay/rust-toolchain@nightly + - uses: dtolnay/rust-toolchain@stable with: components: rustfmt, clippy - name: Run clippy manually without annotations @@ -53,7 +50,7 @@ jobs: - uses: actions/checkout@v4.1.1 with: persist-credentials: false - - uses: dtolnay/rust-toolchain@nightly + - uses: dtolnay/rust-toolchain@stable with: components: rustfmt - uses: Swatinem/rust-cache@v2 diff --git a/Cargo.lock b/Cargo.lock index ff8c9ffb..41cabf23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,6 +77,17 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "async-trait" +version = "0.1.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "atomic-polyfill" version = "0.1.11" @@ -257,6 +268,7 @@ checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" name = "coordinator" version = "0.1.0" dependencies = [ + "async-trait", "clap", "exitcode", "eyre", @@ -819,6 +831,7 @@ dependencies = [ name = "participant" version = "0.1.0" dependencies = [ + "async-trait", "clap", "exitcode", "eyre", diff --git a/coordinator/Cargo.toml b/coordinator/Cargo.toml index cab26c0e..fe0e25a2 100644 --- a/coordinator/Cargo.toml +++ b/coordinator/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +async-trait = "0.1.77" eyre = "0.6.12" frost-ed25519 = { version = "1.0.0-rc.0", features = ["serde"] } reddsa = { git = "https://github.com/ZcashFoundation/reddsa.git", rev = "81c649c412e5b6ba56d491d2857f91fbd28adbc7", features = ["frost", "serde"] } @@ -21,5 +22,4 @@ message-io = "0.18" [features] redpallas = [] -sockets = [] default = [] diff --git a/coordinator/src/args.rs b/coordinator/src/args.rs index 915c666e..2d4f5e46 100644 --- a/coordinator/src/args.rs +++ b/coordinator/src/args.rs @@ -3,6 +3,12 @@ use clap::Parser; #[derive(Parser, Debug, Default)] #[command(author, version, about, long_about = None)] pub struct Args { + /// 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. + #[arg(long, default_value_t = false)] + pub cli: bool, + /// The number of participants. If 0, will prompt for a value. #[arg(short = 'n', long, default_value_t = 0)] pub num_signers: u16, diff --git a/coordinator/src/cli.rs b/coordinator/src/cli.rs index da3d5b82..b7c44b74 100644 --- a/coordinator/src/cli.rs +++ b/coordinator/src/cli.rs @@ -1,10 +1,9 @@ use std::io::{BufRead, Write}; use crate::args::Args; -#[cfg(not(feature = "sockets"))] use crate::comms::cli::CLIComms; -#[cfg(feature = "sockets")] 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::step_3; @@ -19,13 +18,13 @@ pub async fn cli( ) -> Result<(), Box> { writeln!(logger, "\n=== STEP 1: CHOOSE PARTICIPANTS ===\n")?; - #[cfg(not(feature = "sockets"))] - let mut comms = CLIComms {}; + let mut comms: Box = if args.cli { + Box::new(CLIComms {}) + } else { + Box::new(SocketComms::new(args)) + }; - #[cfg(feature = "sockets")] - let mut comms = SocketComms::new(&args); - - let participants_config = step_1(args, &mut comms, reader, logger).await?; + let participants_config = step_1(args, &mut *comms, reader, logger).await?; writeln!( logger, @@ -47,7 +46,7 @@ pub async fn cli( step_3( args, - &mut comms, + &mut *comms, reader, logger, participants_config, diff --git a/coordinator/src/comms.rs b/coordinator/src/comms.rs index f29bd128..a22a1363 100644 --- a/coordinator/src/comms.rs +++ b/coordinator/src/comms.rs @@ -6,6 +6,14 @@ use frost_ed25519 as frost; #[cfg(feature = "redpallas")] use reddsa::frost::redpallas as frost; +use std::{ + collections::BTreeMap, + error::Error, + io::{BufRead, Write}, +}; + +use async_trait::async_trait; + use frost::{ keys::PublicKeyPackage, round1::SigningCommitments, @@ -14,12 +22,6 @@ use frost::{ Identifier, SigningPackage, }; -use std::{ - collections::BTreeMap, - error::Error, - io::{BufRead, Write}, -}; - #[derive(Serialize, Deserialize)] #[serde(crate = "self::serde")] #[allow(clippy::large_enum_variant)] @@ -32,7 +34,7 @@ pub enum Message { SignatureShare(SignatureShare), } -#[allow(async_fn_in_trait)] +#[async_trait(?Send)] pub trait Comms { async fn get_signing_commitments( &mut self, diff --git a/coordinator/src/comms/cli.rs b/coordinator/src/comms/cli.rs index 7f95199e..fb75b6b4 100644 --- a/coordinator/src/comms/cli.rs +++ b/coordinator/src/comms/cli.rs @@ -7,6 +7,8 @@ use reddsa::frost::redpallas as frost; use eyre::eyre; +use async_trait::async_trait; + use frost::{ keys::PublicKeyPackage, round1::SigningCommitments, round2::SignatureShare, Identifier, SigningPackage, @@ -22,6 +24,7 @@ use super::Comms; pub struct CLIComms {} +#[async_trait(?Send)] impl Comms for CLIComms { async fn get_signing_commitments( &mut self, diff --git a/coordinator/src/comms/socket.rs b/coordinator/src/comms/socket.rs index 0a8de3ba..d45dd902 100644 --- a/coordinator/src/comms/socket.rs +++ b/coordinator/src/comms/socket.rs @@ -1,5 +1,6 @@ //! 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")] @@ -71,6 +72,7 @@ impl SocketComms { } } +#[async_trait(?Send)] impl Comms for SocketComms { async fn get_signing_commitments( &mut self, diff --git a/coordinator/src/step_1.rs b/coordinator/src/step_1.rs index d85e6d91..594fc591 100755 --- a/coordinator/src/step_1.rs +++ b/coordinator/src/step_1.rs @@ -21,7 +21,7 @@ pub struct ParticipantsConfig { // TODO: needs to include the coordinator's keys! pub async fn step_1( args: &Args, - comms: &mut impl Comms, + comms: &mut dyn Comms, reader: &mut dyn BufRead, logger: &mut dyn Write, ) -> Result> { @@ -38,7 +38,7 @@ pub async fn step_1( // 3. identifiers for all participants async fn read_commitments( args: &Args, - comms: &mut impl Comms, + comms: &mut dyn Comms, input: &mut dyn BufRead, logger: &mut dyn Write, ) -> Result> { @@ -50,7 +50,7 @@ async fn read_commitments( )?; let pub_key_package: PublicKeyPackage = serde_json::from_str(&pub_key_package)?; - let num_of_participants = if args.num_signers == 0 { + let num_of_participants = if args.cli && args.num_signers == 0 { writeln!(logger, "The number of participants: ")?; let mut participants = String::new(); diff --git a/coordinator/src/step_2.rs b/coordinator/src/step_2.rs index 221e229f..593a3c38 100644 --- a/coordinator/src/step_2.rs +++ b/coordinator/src/step_2.rs @@ -38,7 +38,7 @@ fn request_message( logger: &mut dyn Write, commitments: BTreeMap, ) -> Result> { - let message = if args.message == "-" { + let message = if args.cli && args.message == "-" { writeln!(logger, "The message to be signed (hex encoded)")?; let mut msg = String::new(); diff --git a/coordinator/src/step_3.rs b/coordinator/src/step_3.rs index 315ac359..9a5f0adf 100644 --- a/coordinator/src/step_3.rs +++ b/coordinator/src/step_3.rs @@ -31,7 +31,7 @@ pub fn request_randomizer( pub async fn step_3( args: &Args, - comms: &mut impl Comms, + comms: &mut dyn Comms, input: &mut dyn BufRead, logger: &mut dyn Write, participants: ParticipantsConfig, @@ -56,7 +56,7 @@ pub async fn step_3( // 1. number of signers (TODO: maybe pass this in?) // 2. signatures for all signers async fn request_inputs_signature_shares( - comms: &mut impl Comms, + comms: &mut dyn Comms, input: &mut dyn BufRead, logger: &mut dyn Write, participants: ParticipantsConfig, diff --git a/participant/Cargo.toml b/participant/Cargo.toml index f18d2b37..4a549ee8 100644 --- a/participant/Cargo.toml +++ b/participant/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +async-trait = "0.1.77" frost-ed25519 = { version = "1.0.0-rc.0", features = ["serde"] } reddsa = { git = "https://github.com/ZcashFoundation/reddsa.git", rev = "81c649c412e5b6ba56d491d2857f91fbd28adbc7", features = ["frost"] } hex = "0.4" @@ -19,5 +20,4 @@ message-io = "0.18" [features] redpallas = [] -sockets = [] default = [] diff --git a/participant/src/args.rs b/participant/src/args.rs index 9fe46428..8b00a184 100644 --- a/participant/src/args.rs +++ b/participant/src/args.rs @@ -3,6 +3,12 @@ use clap::Parser; #[derive(Parser, Debug, Default)] #[command(author, version, about, long_about = None)] pub struct Args { + /// 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. + #[arg(long, default_value_t = false)] + pub cli: bool, + /// Public key package to use. Can be a file with a JSON-encoded /// package, or "-". If the file does not exist or if "-" is specified, /// then it will be read from standard input. diff --git a/participant/src/cli.rs b/participant/src/cli.rs index 3e1cac25..e7e68054 100644 --- a/participant/src/cli.rs +++ b/participant/src/cli.rs @@ -1,8 +1,6 @@ use crate::args::Args; -#[cfg(not(feature = "sockets"))] use crate::comms::cli::CLIComms; -#[cfg(feature = "sockets")] use crate::comms::socket::SocketComms; use crate::comms::Comms; @@ -17,11 +15,11 @@ pub async fn cli( input: &mut impl BufRead, logger: &mut impl Write, ) -> Result<(), Box> { - #[cfg(not(feature = "sockets"))] - let mut comms = CLIComms {}; - - #[cfg(feature = "sockets")] - let mut comms = SocketComms::new(&args); + let mut comms: Box = if args.cli { + Box::new(CLIComms {}) + } else { + Box::new(SocketComms::new(args)) + }; // Round 1 @@ -38,7 +36,7 @@ pub async fn cli( // Round 2 - Sign let round_2_config = round_2_request_inputs( - &mut comms, + &mut *comms, input, logger, commitments, diff --git a/participant/src/comms.rs b/participant/src/comms.rs index 0be67631..a21e3b2b 100644 --- a/participant/src/comms.rs +++ b/participant/src/comms.rs @@ -1,6 +1,8 @@ pub mod cli; pub mod socket; +use async_trait::async_trait; + #[cfg(not(feature = "redpallas"))] use frost_ed25519 as frost; #[cfg(feature = "redpallas")] @@ -30,7 +32,7 @@ pub enum Message { SignatureShare(SignatureShare), } -#[allow(async_fn_in_trait)] +#[async_trait(?Send)] pub trait Comms { async fn get_signing_package( &mut self, diff --git a/participant/src/comms/cli.rs b/participant/src/comms/cli.rs index 783b4b7c..b6aa4bf4 100644 --- a/participant/src/comms/cli.rs +++ b/participant/src/comms/cli.rs @@ -1,5 +1,6 @@ //! Command line interface implementation of the Comms trait. +use async_trait::async_trait; #[cfg(not(feature = "redpallas"))] use frost_ed25519 as frost; #[cfg(feature = "redpallas")] @@ -22,6 +23,7 @@ use crate::comms::Comms; pub struct CLIComms {} +#[async_trait(?Send)] impl Comms for CLIComms { async fn get_signing_package( &mut self, diff --git a/participant/src/comms/socket.rs b/participant/src/comms/socket.rs index e78305af..4601d667 100644 --- a/participant/src/comms/socket.rs +++ b/participant/src/comms/socket.rs @@ -1,5 +1,6 @@ //! 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")] @@ -74,6 +75,7 @@ impl SocketComms { } } +#[async_trait(?Send)] impl Comms for SocketComms { async fn get_signing_package( &mut self, diff --git a/participant/src/round2.rs b/participant/src/round2.rs index eba6f092..9a008a5a 100644 --- a/participant/src/round2.rs +++ b/participant/src/round2.rs @@ -24,7 +24,7 @@ pub struct Round2Config { // TODO: refactor to generate config // TODO: handle errors pub async fn round_2_request_inputs( - comms: &mut impl Comms, + comms: &mut dyn Comms, input: &mut impl BufRead, logger: &mut dyn Write, commitments: SigningCommitments, diff --git a/participant/src/tests/round1.rs b/participant/src/tests/round1.rs index bec33470..7fddae5f 100644 --- a/participant/src/tests/round1.rs +++ b/participant/src/tests/round1.rs @@ -38,6 +38,7 @@ async fn check_valid_round_1_inputs() { let mut buf = BufWriter::new(Vec::new()); let args = Args { + cli: true, key_package: "-".to_string(), ip: "0.0.0.0".to_string(), port: 80, diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 5d56faf9..292fe499 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "nightly" +channel = "stable" diff --git a/tests/tests/integration_tests.rs b/tests/tests/integration_tests.rs index ea59b509..01ed3220 100644 --- a/tests/tests/integration_tests.rs +++ b/tests/tests/integration_tests.rs @@ -31,6 +31,7 @@ async fn trusted_dealer_journey() { let mut rng = thread_rng(); let coordinator_args = CoordinatorArgs { + cli: true, public_key_package: "-".to_string(), signature: "-".to_string(), message: "-".to_string(), diff --git a/trusted-dealer/src/args.rs b/trusted-dealer/src/args.rs index 24718b63..a7f77dc1 100644 --- a/trusted-dealer/src/args.rs +++ b/trusted-dealer/src/args.rs @@ -3,9 +3,10 @@ use clap::Parser; #[derive(Parser, Debug, Default)] #[command(author, version, about, long_about = None)] pub struct Args { - /// CLI mode. If enabled, it will prompts for inputs from stdin + /// CLI mode. If enabled, it will prompt for inputs from stdin /// and print values to stdout, ignoring other flags. - #[arg(short = 'i', long, default_value_t = false)] + /// If false, socket communication is enabled. + #[arg(long, default_value_t = false)] pub cli: bool, /// Where to write the public key package to use. Can be a file path or "-".