Skip to content

Commit

Permalink
Add socket comms for Participant demo (#131)
Browse files Browse the repository at this point in the history
* Add CLI comms to participant demo (#92)

* Update Coordinator unit tests after comms changes (#92)

* Update integration tests with participant cli comms (#92)

* Add socket comms to Participant demo (#92)

Remove group signature verification from participant demo

* Update participant cli test (#92)

* fix redpallas compile issue

* Update participant/src/args.rs

---------

Co-authored-by: Conrado Gouvea <[email protected]>
Co-authored-by: Conrado Gouvea <[email protected]>
  • Loading branch information
3 people authored Jan 30, 2024
1 parent e9269f2 commit 4925183
Show file tree
Hide file tree
Showing 24 changed files with 579 additions and 178 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions coordinator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ message-io = "0.18"

[features]
redpallas = []
sockets = []
default = []
9 changes: 8 additions & 1 deletion coordinator/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
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::step_1::step_1;
use crate::step_2::step_2;
use crate::step_3::step_3;
Expand All @@ -16,16 +19,20 @@ pub async fn cli(
) -> Result<(), Box<dyn std::error::Error>> {
writeln!(logger, "\n=== STEP 1: CHOOSE PARTICIPANTS ===\n")?;

#[cfg(not(feature = "sockets"))]
let mut comms = CLIComms {};

#[cfg(feature = "sockets")]
let mut comms = SocketComms::new(&args);

let participants_config = step_1(args, &mut comms, reader, logger).await?;

writeln!(
logger,
"=== STEP 2: CHOOSE MESSAGE AND GENERATE COMMITMENT PACKAGE ===\n"
)?;

let signing_package = step_2(reader, logger, participants_config.commitments.clone())?;
let signing_package = step_2(reader, logger, participants_config.commitments.clone()).await?;

#[cfg(feature = "redpallas")]
let randomizer = request_randomizer(reader, logger)?;
Expand Down
11 changes: 6 additions & 5 deletions coordinator/src/comms/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ impl SocketComms {
pub fn new(args: &Args) -> Self {
let (handler, listener) = node::split::<()>();
let addr = format!("{}:{}", args.ip, args.port);
let (tx, rx) = mpsc::channel(100);
let (tx, rx) = mpsc::channel(2000);

handler
let _ = handler
.network()
.listen(Transport::FramedTcp, addr)
.unwrap();
.map_err(|e| println!("{}", e));

let socket_comm = Self {
input_rx: rx,
Expand All @@ -62,8 +62,9 @@ impl SocketComms {
NetEvent::Accepted(_endpoint, _listener) => println!("Client connected"), // Tcp or Ws
NetEvent::Message(endpoint, data) => {
println!("Received: {}", String::from_utf8_lossy(data));
// TODO: handle error
let _ = input_tx.try_send((endpoint, data.to_vec()));
let _ = input_tx
.try_send((endpoint, data.to_vec()))
.map_err(|e| println!("{}", e));
}
NetEvent::Disconnected(_endpoint) => println!("Client disconnected"), //Tcp or Ws
});
Expand Down
2 changes: 1 addition & 1 deletion coordinator/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
};

/// Read the contents of a file or from a stdin.
/// If `object_name` is "-" or a file that does not exist, then it reads from
/// If `file_path` is "-" or a file that does not exist, then it reads from
/// stdin.
/// `object_name` is used for printing prompts and it should describe what
/// is being read.
Expand Down
3 changes: 3 additions & 0 deletions coordinator/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#[cfg(all(test, not(feature = "redpallas")))]
mod tests;

use std::io;

use clap::Parser;
Expand Down
2 changes: 1 addition & 1 deletion coordinator/src/step_2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub struct CommitmentsConfig {
pub signer_commitments: BTreeMap<Identifier, SigningCommitments>,
}

pub fn step_2(
pub async fn step_2(
input: &mut impl BufRead,
logger: &mut dyn Write,
commitments: BTreeMap<Identifier, SigningCommitments>,
Expand Down
1 change: 1 addition & 0 deletions coordinator/src/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// mod steps;
107 changes: 60 additions & 47 deletions coordinator/src/tests/steps.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
#[cfg(test)]
use coordinator::{
args::Args,
comms::cli::CLIComms,
step_1::{step_1, ParticipantsConfig},
step_2::step_2,
step_3::step_3,
};
use frost::{
keys::{PublicKeyPackage, VerifyingShare},
round1::{NonceCommitment, SigningCommitments},
Identifier, SigningPackage, VerifyingKey,
};
use frost_ed25519 as frost;
use hex::FromHex;
use std::{collections::BTreeMap, io::BufWriter};

// Test values from https://github.com/ZcashFoundation/frost/blob/main/frost-ed25519/tests/helpers/vectors.json

const PUBLIC_KEY_1: &str = "fc2c9b8e335c132d9ebe0403c9317aac480bbbf8cbdb1bc3730bb68eb60dadf9";
Expand All @@ -10,7 +27,7 @@ fn build_pub_key_package() -> PublicKeyPackage {
let id_2 = Identifier::try_from(2).unwrap();
let id_3 = Identifier::try_from(3).unwrap();

let mut signer_pubkeys = HashMap::new();
let mut signer_pubkeys = BTreeMap::new();
signer_pubkeys.insert(
id_1,
VerifyingShare::deserialize(<[u8; 32]>::from_hex(PUBLIC_KEY_1).unwrap()).unwrap(),
Expand All @@ -24,12 +41,13 @@ fn build_pub_key_package() -> PublicKeyPackage {
VerifyingShare::deserialize(<[u8; 32]>::from_hex(PUBLIC_KEY_3).unwrap()).unwrap(),
);

let group_public = VerifyingKey::from_hex(GROUP_PUBLIC_KEY).unwrap();
let group_public =
VerifyingKey::deserialize(<[u8; 32]>::from_hex(GROUP_PUBLIC_KEY).unwrap()).unwrap();

PublicKeyPackage::new(signer_pubkeys, group_public)
}

fn build_signing_package() -> SigningPackage {
fn build_signing_commitments() -> BTreeMap<Identifier, SigningCommitments> {
let id_1 = Identifier::try_from(1).unwrap();
let id_3 = Identifier::try_from(3).unwrap();

Expand All @@ -55,15 +73,19 @@ fn build_signing_package() -> SigningPackage {
signing_commitments.insert(id_1, signer_commitments_1);
signing_commitments.insert(id_3, signer_commitments_3);

SigningPackage::new(signing_commitments, b"test")
signing_commitments

// SigningPackage::new(signing_commitments, b"test")
}

// Input required:
// 1. public key package
// 2. number of signers
// 3. identifiers for all signers
#[test]
fn check_step_1() {
#[tokio::test]
async fn check_step_1() {
let mut comms = CLIComms {};
let args = Args::default();
let mut buf = BufWriter::new(Vec::new());

let id_1 = Identifier::try_from(1).unwrap();
Expand All @@ -87,16 +109,6 @@ fn check_step_1() {

// --

let expected_participants_config = ParticipantsConfig {
participants: vec![id_1, id_3],
pub_key_package: build_pub_key_package(),
};

let participants_config = step_1(&mut valid_input, &mut buf);

assert!(participants_config.is_ok());
assert!(participants_config.unwrap() == expected_participants_config);

let expected = "Paste the JSON public key package: \nThe number of participants: \nIdentifier for participant 1 (hex encoded): \nIdentifier for participant 2 (hex encoded): \nSelected participants: \n\"0100000000000000000000000000000000000000000000000000000000000000\"\n\"0300000000000000000000000000000000000000000000000000000000000000\"\n";

let (_, res) = &buf.into_parts();
Expand All @@ -109,16 +121,18 @@ fn check_step_1() {
// 1. message
// 2. number of signers
// 3. commitments for all signers
#[test]
fn check_step_2() {
#[tokio::test]
async fn check_step_2() {
let mut comms = CLIComms {};
let args = Args::default();
let mut buf = BufWriter::new(Vec::new());

// -- INPUTS --

let message = "74657374";

let commitments_input_1 = "{\"hiding\":\"5078f5c6d679654bb88a8887242d49cc21a553ed26caed4d52570c6656fb9b92\", \"binding\":\"936b660d3008d8298b0a7220a327a0813ffedd9d07604bdc73d7cffef63c0da0\", \"ciphersuite\":\"FROST(Ed25519, SHA-512)\" }";
let commitments_input_3 = "{\"hiding\":\"91c2469b501fe5af8493f9ae77c8f57999460af317f2d9f2d4378ae0e665860e\", \"binding\":\"c225618accff2266a45d87dc3219b04c774ca26c8629c4fa483e7e87da820007\",\"ciphersuite\":\"FROST(Ed25519, SHA-512)\"}";
let commitments_input_1 = "{\"header\":{\"version\":0,\"ciphersuite\":\"FROST-ED25519-SHA512-v1\"},\"identifier\":\"0100000000000000000000000000000000000000000000000000000000000000\",\"signing_share\":\"4ca8a14c31582e92770b23d8b4e5f253d94cbbdc34332cbbb9972f7d0a16a106\",\"commitment\":[\"c0b1eb84bc74624e9196a4ae01d7b784133dd714943001524e33f62ac09fe6df\",\"a4ed252f52e34077e990f70a743a261ff74cbda88173269cc1feeb0616af734b\",\"0fe7ced03a6d5cc4286d050f20fea6dbc14f412a430fc21f92ee2861011fb93c\"]}";
let commitments_input_3 = "{\"header\":{\"version\":0,\"ciphersuite\":\"FROST-ED25519-SHA512-v1\"},\"identifier\":\"0300000000000000000000000000000000000000000000000000000000000000\",\"signing_share\":\"4ca8a14c31582e92770b23d8b4e5f253d94cbbdc34332cbbb9972f7d0a16a106\",\"commitment\":[\"c0b1eb84bc74624e9196a4ae01d7b784133dd714943001524e33f62ac09fe6df\",\"a4ed252f52e34077e990f70a743a261ff74cbda88173269cc1feeb0616af734b\",\"0fe7ced03a6d5cc4286d050f20fea6dbc14f412a430fc21f92ee2861011fb93c\"]}";

let input = format!(
"{}\n{}\n{}\n",
Expand All @@ -131,15 +145,25 @@ fn check_step_2() {

let id_1 = Identifier::try_from(1).unwrap();
let id_3 = Identifier::try_from(3).unwrap();
let participants = vec![id_1, id_3];

let expected_signing_package = build_signing_package();
let signing_commitments = build_signing_commitments();

let expected_signing_package = SigningPackage::new(signing_commitments.clone(), b"test");

let signing_package = step_2(&mut valid_input, &mut buf, participants);
let signing_package = step_2(&mut valid_input, &mut buf, signing_commitments.clone());

assert!(signing_package.is_ok());
assert!(signing_package.unwrap() == expected_signing_package);

let expected_participants_config = ParticipantsConfig {
commitments: signing_commitments.clone(),
pub_key_package: build_pub_key_package(),
};

let participants_config = step_1(&args, &mut comms, &mut valid_input, &mut buf);

assert!(participants_config.await.unwrap() == expected_participants_config);

let expected = "The message to be signed (hex encoded)\nPlease enter JSON encoded commitments for participant 0100000000000000000000000000000000000000000000000000000000000000:\nPlease enter JSON encoded commitments for participant 0300000000000000000000000000000000000000000000000000000000000000:\nSigning Package:\n{\"signing_commitments\":{\"0100000000000000000000000000000000000000000000000000000000000000\":{\"hiding\":\"5078f5c6d679654bb88a8887242d49cc21a553ed26caed4d52570c6656fb9b92\",\"binding\":\"936b660d3008d8298b0a7220a327a0813ffedd9d07604bdc73d7cffef63c0da0\",\"ciphersuite\":\"FROST(Ed25519, SHA-512)\"},\"0300000000000000000000000000000000000000000000000000000000000000\":{\"hiding\":\"91c2469b501fe5af8493f9ae77c8f57999460af317f2d9f2d4378ae0e665860e\",\"binding\":\"c225618accff2266a45d87dc3219b04c774ca26c8629c4fa483e7e87da820007\",\"ciphersuite\":\"FROST(Ed25519, SHA-512)\"}},\"message\":\"74657374\",\"ciphersuite\":\"FROST(Ed25519, SHA-512)\"}\n";

let (_, res) = &buf.into_parts();
Expand All @@ -148,28 +172,13 @@ fn check_step_2() {
assert_eq!(expected, actual)
}

use crate::{
step_1::{step_1, ParticipantsConfig},
step_2::step_2,
step_3::step_3,
};
use frost::{
keys::{PublicKeyPackage, VerifyingShare},
round1::{NonceCommitment, SigningCommitments},
Identifier, SigningPackage, VerifyingKey,
};
use frost_ed25519 as frost;
use hex::FromHex;
use std::{
collections::{BTreeMap, HashMap},
io::BufWriter,
};

// // Input required:
// // 1. number of signers (TODO: maybe pass this in?)
// // 2. signatures for all signers
#[test]
fn check_step_3() {
#[tokio::test]
async fn check_step_3() {
let mut comms = CLIComms {};
let args = Args::default();
let mut buf = BufWriter::new(Vec::new());

let id_1 = Identifier::try_from(1).unwrap();
Expand All @@ -180,7 +189,7 @@ fn check_step_3() {
const GROUP_PUBLIC_KEY: &str =
"15d21ccd7ee42959562fc8aa63224c8851fb3ec85a3faf66040d380fb9738673";

let mut signer_pubkeys = HashMap::new();
let mut signer_pubkeys = BTreeMap::new();
signer_pubkeys.insert(
id_1,
VerifyingShare::deserialize(<[u8; 32]>::from_hex(PUBLIC_KEY_1).unwrap()).unwrap(),
Expand All @@ -190,7 +199,8 @@ fn check_step_3() {
VerifyingShare::deserialize(<[u8; 32]>::from_hex(PUBLIC_KEY_3).unwrap()).unwrap(),
);

let group_public = VerifyingKey::from_hex(GROUP_PUBLIC_KEY).unwrap();
let group_public =
VerifyingKey::deserialize(<[u8; 32]>::from_hex(GROUP_PUBLIC_KEY).unwrap()).unwrap();

let signature_1 = "{\"share\":\"b97409beff18861f0959530db091a64b812e3fefaa87e1e3d2c039f11d96cc09\",\"ciphersuite\":\"FROST(Ed25519, SHA-512)\"}";
let signature_3 = "{\"share\":\"9816a14e7cdecfcb240976f564cf98c5640e596b6ddf270379efbef4e9f7db0b\",\"ciphersuite\":\"FROST(Ed25519, SHA-512)\"}";
Expand All @@ -199,17 +209,20 @@ fn check_step_3() {

let mut valid_input = input.as_bytes();

let commitments = build_signing_commitments();

let participants_config = ParticipantsConfig {
participants: vec![id_1, id_3],
commitments: commitments.clone(),
pub_key_package: PublicKeyPackage::new(signer_pubkeys, group_public),
};
let signing_package = build_signing_package();
let signing_package = SigningPackage::new(commitments, b"test");

step_3(
&mut comms,
&mut valid_input,
&mut buf,
participants_config,
signing_package,
&signing_package,
);

let expected = "Please enter JSON encoded signature shares for participant 0100000000000000000000000000000000000000000000000000000000000000:\nPlease enter JSON encoded signature shares for participant 0300000000000000000000000000000000000000000000000000000000000000:\nGroup signature: \"72c948a63797c693e8e978fdb703a1f5a7590472a539da13b71dd6c2b8c1b2a664b7b4af6194439357c5d15f366760fce53c985a186709e74bb0f8e5078ea805\"\n";
Expand Down
4 changes: 4 additions & 0 deletions participant/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ rand = "0.8"
eyre = "0.6.11"
exitcode = "1.1.2"
serde_json = "1.0"
clap = { version = "4.4.7", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
message-io = "0.18"

[features]
redpallas = []
sockets = []
default = []
19 changes: 19 additions & 0 deletions participant/src/args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use clap::Parser;

#[derive(Parser, Debug, Default)]
#[command(author, version, about, long_about = None)]
pub struct Args {
/// 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.
#[arg(short = 'k', long, default_value = "key-package-1.json")]
pub key_package: String,

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

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

0 comments on commit 4925183

Please sign in to comment.