From 0362e07a09a8cf2943c546b0d5cb4c0df6edc6bc Mon Sep 17 00:00:00 2001 From: Conrado Gouvea Date: Thu, 15 Feb 2024 18:55:08 -0300 Subject: [PATCH] change create_new_session to not require specific signers --- server/src/functions.rs | 18 +++++++++--------- server/src/state.rs | 7 ++++++- server/src/types.rs | 4 ++-- server/tests/integration_tests.rs | 27 +++++++-------------------- 4 files changed, 24 insertions(+), 32 deletions(-) diff --git a/server/src/functions.rs b/server/src/functions.rs index ba3de4c9..9659d9a7 100644 --- a/server/src/functions.rs +++ b/server/src/functions.rs @@ -25,7 +25,7 @@ pub(crate) async fn create_new_session( // Create new session object. let id = Uuid::new_v4(); let session = Session { - identifiers: args.identifiers.iter().cloned().collect(), + num_signers: args.num_signers, message_count: args.message_count, state: SessionState::WaitingForCommitments { commitments: Default::default(), @@ -50,7 +50,7 @@ pub(crate) async fn get_session_info( ))?; Ok(Json(GetSessionInfoOutput { - identifiers: session.identifiers.iter().copied().collect(), + num_signers: session.num_signers, message_count: session.message_count, })) } @@ -74,9 +74,6 @@ pub(crate) async fn send_commitments( match &mut session.state { SessionState::WaitingForCommitments { commitments } => { - if !session.identifiers.contains(&args.identifier) { - return Err(AppError(StatusCode::NOT_FOUND, eyre!("invalid identifier"))); - } if args.commitments.len() != session.message_count as usize { return Err(AppError( StatusCode::INTERNAL_SERVER_ERROR, @@ -89,7 +86,7 @@ pub(crate) async fn send_commitments( // poor networking connectivity leading to retries) commitments.insert(args.identifier, args.commitments); // If complete, advance to next state - if commitments.keys().cloned().collect::>() == session.identifiers { + if commitments.len() == session.num_signers as usize { session.state = SessionState::CommitmentsReady { commitments: commitments.clone(), } @@ -154,7 +151,7 @@ pub(crate) async fn send_signing_package( ))?; match &mut session.state { - SessionState::CommitmentsReady { .. } => { + SessionState::CommitmentsReady { commitments } => { if args.signing_package.len() != session.message_count as usize || args.randomizer.len() != session.message_count as usize { @@ -164,6 +161,7 @@ pub(crate) async fn send_signing_package( )); } session.state = SessionState::WaitingForSignatureShares { + identifiers: commitments.keys().cloned().collect(), signing_package: args.signing_package, signature_shares: Default::default(), randomizer: args.randomizer, @@ -194,6 +192,7 @@ pub(crate) async fn get_signing_package( match &session.state { SessionState::WaitingForSignatureShares { + identifiers: _, signing_package, signature_shares: _, randomizer, @@ -228,12 +227,13 @@ pub(crate) async fn send_signature_share( match &mut session.state { SessionState::WaitingForSignatureShares { + identifiers, signing_package: _, signature_shares, randomizer: _, aux_msg: _, } => { - if !session.identifiers.contains(&args.identifier) { + if !identifiers.contains(&args.identifier) { return Err(AppError(StatusCode::NOT_FOUND, eyre!("invalid identifier"))); } if args.signature_share.len() != session.message_count as usize { @@ -247,7 +247,7 @@ pub(crate) async fn send_signature_share( // poor networking connectivity leading to retries) signature_shares.insert(args.identifier, args.signature_share); // If complete, advance to next state - if signature_shares.keys().cloned().collect::>() == session.identifiers { + if signature_shares.keys().cloned().collect::>() == *identifiers { session.state = SessionState::SignatureSharesReady { signature_shares: signature_shares.clone(), }; diff --git a/server/src/state.rs b/server/src/state.rs index 8e89050d..1440b82a 100644 --- a/server/src/state.rs +++ b/server/src/state.rs @@ -24,6 +24,9 @@ pub enum SessionState { /// SigningPackage ready to be fetched by participants. Waiting for /// participants to send their signature shares. WaitingForSignatureShares { + /// Identifiers of the participants that sent commitments in the + /// previous state. + identifiers: BTreeSet, /// SigningPackage sent by the coordinator to be sent to participants, /// for each message being signed. signing_package: Vec, @@ -56,8 +59,10 @@ impl Default for SessionState { /// A particular signing session. pub struct Session { + /// The number of signers in the session. + pub(crate) num_signers: u16, /// The set of identifiers for the session. - pub(crate) identifiers: BTreeSet, + // pub(crate) identifiers: BTreeSet, /// The number of messages being simultaneously signed. pub(crate) message_count: u8, /// The session state. diff --git a/server/src/types.rs b/server/src/types.rs index d89e30d4..20664631 100644 --- a/server/src/types.rs +++ b/server/src/types.rs @@ -7,7 +7,7 @@ use reddsa::frost::redpallas as frost; #[derive(Serialize, Deserialize)] pub struct CreateNewSessionArgs { - pub identifiers: Vec, + pub num_signers: u16, pub message_count: u8, } @@ -23,7 +23,7 @@ pub struct GetSessionInfoArgs { #[derive(Serialize, Deserialize)] pub struct GetSessionInfoOutput { - pub identifiers: Vec, + pub num_signers: u16, pub message_count: u8, } diff --git a/server/tests/integration_tests.rs b/server/tests/integration_tests.rs index ddbeed0a..48121ed3 100644 --- a/server/tests/integration_tests.rs +++ b/server/tests/integration_tests.rs @@ -38,7 +38,7 @@ async fn test_main_router() -> Result<(), Box> { let res = server .post("/create_new_session") .json(&server::CreateNewSessionArgs { - identifiers: key_packages.keys().copied().collect::>(), + num_signers: 2, message_count: 2, }) .await; @@ -51,7 +51,7 @@ async fn test_main_router() -> Result<(), Box> { // Map to store the SigningNonces (for each message, for each participant) let mut nonces_map = BTreeMap::<_, _>::new(); - for (identifier, key_package) in key_packages.iter() { + for (identifier, key_package) in key_packages.iter().take(2) { // As participant `identifier` // Get the number of messages (the participants wouldn't know without @@ -85,7 +85,9 @@ async fn test_main_router() -> Result<(), Box> { commitments: commitments_vec, }) .await; - res.assert_status_ok(); + if res.status_code() != 200 { + panic!("status code: {}; error: {}", res.status_code(), res.text()); + } } // As the coordinator, get the commitments @@ -127,7 +129,7 @@ async fn test_main_router() -> Result<(), Box> { // As each participant, get SigningPackages and generate the SignatureShares // for each. - for (identifier, key_package) in key_packages.iter() { + for (identifier, key_package) in key_packages.iter().take(2) { // As participant `identifier` // Get SigningPackages @@ -201,21 +203,6 @@ async fn test_main_router() -> Result<(), Box> { /// A better example on how to write client code. #[tokio::test] async fn test_http() -> Result<(), Box> { - // Create test values - let mut rng = thread_rng(); - let (shares, _pubkeys) = - frost::keys::generate_with_dealer(3, 2, frost::keys::IdentifierList::Default, &mut rng) - .unwrap(); - let key_packages: BTreeMap<_, _> = shares - .iter() - .map(|(identifier, secret_share)| { - ( - *identifier, - frost::keys::KeyPackage::try_from(secret_share.clone()).unwrap(), - ) - }) - .collect(); - // Spawn server for testing tokio::spawn(async move { server::run(&Args { @@ -235,7 +222,7 @@ async fn test_http() -> Result<(), Box> { let r = client .post("http://127.0.0.1:2744/create_new_session") .json(&server::CreateNewSessionArgs { - identifiers: key_packages.keys().copied().collect::>(), + num_signers: 2, message_count: 1, }) .send()