From ed47af18f9109f4da4b47dd3ed6af0e6e0cb6fda Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 18 Jul 2024 14:58:30 -0400 Subject: [PATCH] Bump Synedrion to latest `master` (#946) * Bump `synedrion` to latest `HEAD` * Replace `MappedResult` with `ProtocolResult` This was removed in: https://github.com/entropyxyz/synedrion/pull/124 * Replace `CombinedMessage` with `MessageBundle` This was removed in https://github.com/entropyxyz/synedrion/pull/128. * Add identifier generic to Error and Result types From here: https://github.com/entropyxyz/synedrion/commit/80482c5b65515b54b3b9c4de0bd184931dc8f92a * Use Synedrion's new `SessionId` type Introduced in https://github.com/entropyxyz/synedrion/pull/128. * Replace `Vec<_>` with `BTreeSet<_>` This was introduced in https://github.com/entropyxyz/synedrion/pull/124. * Remove borrow when making sessions * Use new `ThresholdKeyShare` API Old one was removed inhttps://github.com/entropyxyz/synedrion/pull/124. * Use `BTreeSet` in `entropy-tss` crate * Get `create_test_keyshares` compiling * Use my Synedrion branch with `serde` support * Iterator should actually exclude Charlie * Fix protocol test compilation * Stop using my branch and point to `master` instead * Remove `TODO` --- Cargo.lock | 17 ++++- crates/client/Cargo.toml | 2 +- crates/kvdb/Cargo.toml | 2 +- crates/protocol/Cargo.toml | 2 +- crates/protocol/src/errors.rs | 40 +++++----- crates/protocol/src/execute_protocol.rs | 76 ++++++++++++------- crates/protocol/src/protocol_message.rs | 8 +- crates/protocol/tests/protocol.rs | 36 +++++---- crates/testing-utils/Cargo.toml | 2 +- .../src/create_test_keyshares.rs | 67 +++++++++------- crates/threshold-signature-server/Cargo.toml | 2 +- .../signing_client/protocol_execution/mod.rs | 4 +- scripts/create-test-keyshares/Cargo.toml | 5 +- 13 files changed, 162 insertions(+), 101 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f9f528f8a..3c10b442e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4050,6 +4050,16 @@ dependencies = [ "serde", ] +[[package]] +name = "hashing-serializer" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66c9b1a5e47c3bf40ae0f5705e84daa4cd6d8a74b2bdba43c06eb01dbc236f6e" +dependencies = [ + "digest 0.10.7", + "serde", +] + [[package]] name = "hashlink" version = "0.8.4" @@ -11276,6 +11286,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" dependencies = [ + "serde", "zeroize", ] @@ -13906,22 +13917,24 @@ checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" [[package]] name = "synedrion" version = "0.1.0" -source = "git+https://github.com/entropyxyz/synedrion?rev=25373111cbb01e1a25d8a5c5bb8f4652c725b3f1#25373111cbb01e1a25d8a5c5bb8f4652c725b3f1" +source = "git+https://github.com/entropyxyz/synedrion?rev=3be1339c21384a8e60a1534f1d3bfdd022662e63#3be1339c21384a8e60a1534f1d3bfdd022662e63" dependencies = [ "base64 0.21.7", "bincode", - "cfg-if", "crypto-bigint", "crypto-primes", "digest 0.10.7", "displaydoc", + "hashing-serializer", "hex", "k256", "rand_core 0.6.4", + "secrecy", "serde", "sha2 0.10.8", "sha3", "signature", + "zeroize", ] [[package]] diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index e97cc92c3..4546a1614 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -27,7 +27,7 @@ x25519-dalek ={ version="2.0.1", features=["static_secrets"], optional=true } entropy-protocol={ version="0.2.0", path="../protocol", optional=true, default-features=false } reqwest ={ version="0.12.5", features=["json", "stream"], optional=true } base64 ={ version="0.22.0", optional=true } -synedrion ={ git="https://github.com/entropyxyz/synedrion", rev="25373111cbb01e1a25d8a5c5bb8f4652c725b3f1", optional=true } +synedrion ={ git="https://github.com/entropyxyz/synedrion", rev="3be1339c21384a8e60a1534f1d3bfdd022662e63", optional=true } hex ={ version="0.4.3", optional=true } anyhow ="1.0.86" diff --git a/crates/kvdb/Cargo.toml b/crates/kvdb/Cargo.toml index 1ff338aac..809e78c53 100644 --- a/crates/kvdb/Cargo.toml +++ b/crates/kvdb/Cargo.toml @@ -23,7 +23,7 @@ zeroize ={ version="1.8", features=["zeroize_derive"], default-features= rpassword ={ version="7.3.1", default-features=false } scrypt ={ version="0.11.0", default-features=false, features=["std"] } chacha20poly1305={ version="0.9", features=["alloc"], default-features=false } -synedrion ={ git="https://github.com/entropyxyz/synedrion", rev="25373111cbb01e1a25d8a5c5bb8f4652c725b3f1" } +synedrion ={ git="https://github.com/entropyxyz/synedrion", rev="3be1339c21384a8e60a1534f1d3bfdd022662e63" } # Async tokio ={ version="1.38", features=["macros", "sync", "fs", "rt-multi-thread", "io-util"] } diff --git a/crates/protocol/Cargo.toml b/crates/protocol/Cargo.toml index deeffb8b3..c15544516 100644 --- a/crates/protocol/Cargo.toml +++ b/crates/protocol/Cargo.toml @@ -11,7 +11,7 @@ edition ='2021' [dependencies] async-trait ="0.1.81" entropy-shared ={ version="0.2.0", path="../shared", default-features=false } -synedrion ={ git="https://github.com/entropyxyz/synedrion", rev="25373111cbb01e1a25d8a5c5bb8f4652c725b3f1" } +synedrion ={ git="https://github.com/entropyxyz/synedrion", rev="3be1339c21384a8e60a1534f1d3bfdd022662e63" } serde ={ version="1.0", features=["derive"], default-features=false } subxt ={ version="0.35.3", default-features=false } sp-core ={ version="31.0.0", default-features=false, features=["full_crypto", "serde"] } diff --git a/crates/protocol/src/errors.rs b/crates/protocol/src/errors.rs index a1e42905a..b76ec1d59 100644 --- a/crates/protocol/src/errors.rs +++ b/crates/protocol/src/errors.rs @@ -15,14 +15,14 @@ use synedrion::{ sessions, AuxGenResult, InteractiveSigningResult, KeyInitResult, KeyResharingResult, - MappedResult, + ProtocolResult, }; use thiserror::Error; use crate::{protocol_message::ProtocolMessage, KeyParams, PartyId}; #[derive(Debug, Error)] -pub enum GenericProtocolError> { +pub enum GenericProtocolError { #[error("Synedrion session error {0}")] Joined(Box>), #[error("Incoming message stream error: {0}")] @@ -33,28 +33,28 @@ pub enum GenericProtocolError> { Mpsc(#[from] tokio::sync::mpsc::error::SendError), } -impl> From for GenericProtocolError { +impl From for GenericProtocolError { fn from(err: sessions::LocalError) -> Self { Self::Joined(Box::new(sessions::Error::Local(err))) } } -impl> From> - for GenericProtocolError -{ +impl From> for GenericProtocolError { fn from(err: sessions::RemoteError) -> Self { Self::Joined(Box::new(sessions::Error::Remote(err))) } } -impl> From> for GenericProtocolError { +impl From> for GenericProtocolError { fn from(err: sessions::Error) -> Self { Self::Joined(Box::new(err)) } } -impl From>> for ProtocolExecutionErr { - fn from(err: GenericProtocolError>) -> Self { +impl From>> + for ProtocolExecutionErr +{ + fn from(err: GenericProtocolError>) -> Self { tracing::error!("{:?}", err); match err { GenericProtocolError::Joined(err) => ProtocolExecutionErr::SigningProtocolError(err), @@ -65,8 +65,8 @@ impl From>> for Protoco } } -impl From>> for ProtocolExecutionErr { - fn from(err: GenericProtocolError>) -> Self { +impl From>> for ProtocolExecutionErr { + fn from(err: GenericProtocolError>) -> Self { tracing::error!("{:?}", err); match err { GenericProtocolError::Joined(err) => ProtocolExecutionErr::KeyInitProtocolError(err), @@ -77,8 +77,8 @@ impl From>> for ProtocolExecutionE } } -impl From>> for ProtocolExecutionErr { - fn from(err: GenericProtocolError>) -> Self { +impl From>> for ProtocolExecutionErr { + fn from(err: GenericProtocolError>) -> Self { tracing::error!("{:?}", err); match err { GenericProtocolError::Joined(err) => ProtocolExecutionErr::KeyReshareProtocolError(err), @@ -89,8 +89,8 @@ impl From>> for ProtocolExecu } } -impl From>> for ProtocolExecutionErr { - fn from(err: GenericProtocolError>) -> Self { +impl From>> for ProtocolExecutionErr { + fn from(err: GenericProtocolError>) -> Self { tracing::error!("{:?}", err); match err { GenericProtocolError::Joined(err) => ProtocolExecutionErr::AuxGenProtocolError(err), @@ -109,13 +109,15 @@ pub enum ProtocolExecutionErr { #[error("Synedrion session creation error: {0}")] SessionCreation(sessions::LocalError), #[error("Synedrion signing session error")] - SigningProtocolError(Box, PartyId>>), + SigningProtocolError( + Box, PartyId>>, + ), #[error("Synedrion key init session error")] - KeyInitProtocolError(Box, PartyId>>), + KeyInitProtocolError(Box, PartyId>>), #[error("Synedrion key reshare session error")] - KeyReshareProtocolError(Box, PartyId>>), + KeyReshareProtocolError(Box, PartyId>>), #[error("Synedrion aux generation session error")] - AuxGenProtocolError(Box, PartyId>>), + AuxGenProtocolError(Box, PartyId>>), #[error("Broadcast error: {0}")] Broadcast(#[from] Box>), #[error("Mpsc send error: {0}")] diff --git a/crates/protocol/src/execute_protocol.rs b/crates/protocol/src/execute_protocol.rs index a03f7c262..f45ac0f8c 100644 --- a/crates/protocol/src/execute_protocol.rs +++ b/crates/protocol/src/execute_protocol.rs @@ -25,7 +25,7 @@ use synedrion::{ k256::EncodedPoint, make_aux_gen_session, make_interactive_signing_session, make_key_init_session, make_key_resharing_session, - sessions::{FinalizeOutcome, Session}, + sessions::{FinalizeOutcome, Session, SessionId as SynedrionSessionId}, signature::{self, hazmat::RandomizedPrehashSigner}, AuxInfo, KeyResharingInputs, KeyShare, NewHolder, OldHolder, PrehashedMessage, RecoverableSignature, ThresholdKeyShare, @@ -39,6 +39,8 @@ use crate::{ DkgSubsession, KeyParams, KeyShareWithAuxInfo, PartyId, SessionId, }; +use std::collections::BTreeSet; + pub type ChannelIn = mpsc::Receiver; pub type ChannelOut = Broadcaster; @@ -67,11 +69,11 @@ impl RandomizedPrehashSigner for PairWrapper { } } -async fn execute_protocol_generic>( +async fn execute_protocol_generic( mut chans: Channels, session: Session, session_id_hash: [u8; 32], -) -> Result<(Res::MappedSuccess, mpsc::Receiver), GenericProtocolError> { +) -> Result<(Res::Success, mpsc::Receiver), GenericProtocolError> { let tx = &chans.0; let rx = &mut chans.1; @@ -112,7 +114,7 @@ async fn execute_protocol_generic>( )) })?; - if let ProtocolMessagePayload::CombinedMessage(payload) = message.payload.clone() { + if let ProtocolMessagePayload::MessageBundle(payload) = message.payload.clone() { if message.session_id_hash == session_id_hash { break (message.from, *payload); } else { @@ -170,7 +172,8 @@ pub async fn execute_signing_protocol( tracing::debug!("Executing signing protocol"); tracing::trace!("Using key share with verifying key {:?}", &key_share.verifying_key()); - let party_ids: Vec = threshold_accounts.iter().cloned().map(PartyId::new).collect(); + let party_ids: BTreeSet = + threshold_accounts.iter().cloned().map(PartyId::new).collect(); let pair = PairWrapper(threshold_pair.clone()); @@ -178,7 +181,7 @@ pub async fn execute_signing_protocol( let session = make_interactive_signing_session( &mut OsRng, - &session_id_hash, + SynedrionSessionId::from_seed(session_id_hash.as_slice()), pair, &party_ids, key_share, @@ -206,24 +209,26 @@ pub async fn execute_dkg( tracing::debug!("Executing DKG"); let broadcaster = chans.0.clone(); - let mut party_ids: Vec = + let party_ids: BTreeSet = threshold_accounts.iter().cloned().map(PartyId::new).collect(); - party_ids.sort(); let pair = PairWrapper(threshold_pair.clone()); let my_party_id = PartyId::new(AccountId32(threshold_pair.public().0)); let session_id_hash = session_id.blake2(Some(DkgSubsession::KeyInit))?; - let (mut key_init_parties, includes_me) = + let (key_init_parties, includes_me) = get_key_init_parties(&my_party_id, threshold, &party_ids, &session_id_hash)?; - key_init_parties.sort(); let (verifying_key, old_holder, chans) = if includes_me { // First run the key init session. - let session = - make_key_init_session(&mut OsRng, &session_id_hash, pair.clone(), &key_init_parties) - .map_err(ProtocolExecutionErr::SessionCreation)?; + let session = make_key_init_session( + &mut OsRng, + SynedrionSessionId::from_seed(session_id_hash.as_slice()), + pair.clone(), + &key_init_parties, + ) + .map_err(ProtocolExecutionErr::SessionCreation)?; let (init_keyshare, rx) = execute_protocol_generic(chans, session, session_id_hash).await?; @@ -248,7 +253,7 @@ pub async fn execute_dkg( } ( verifying_key, - Some(OldHolder { key_share: init_keyshare.to_threshold_key_share() }), + Some(OldHolder { key_share: ThresholdKeyShare::from_key_share(&init_keyshare) }), chans, ) } else { @@ -289,9 +294,14 @@ pub async fn execute_dkg( }; let session_id_hash = session_id.blake2(Some(DkgSubsession::Reshare))?; - let session = - make_key_resharing_session(&mut OsRng, &session_id_hash, pair.clone(), &party_ids, &inputs) - .map_err(ProtocolExecutionErr::SessionCreation)?; + let session = make_key_resharing_session( + &mut OsRng, + SynedrionSessionId::from_seed(session_id_hash.as_slice()), + pair.clone(), + &party_ids, + inputs, + ) + .map_err(ProtocolExecutionErr::SessionCreation)?; let (new_key_share_option, rx) = execute_protocol_generic(chans, session, session_id_hash).await?; let new_key_share = @@ -303,8 +313,13 @@ pub async fn execute_dkg( // Now run the aux gen protocol to get AuxInfo let session_id_hash = session_id.blake2(Some(DkgSubsession::AuxGen))?; - let session = make_aux_gen_session(&mut OsRng, &session_id_hash, pair, &party_ids) - .map_err(ProtocolExecutionErr::SessionCreation)?; + let session = make_aux_gen_session( + &mut OsRng, + SynedrionSessionId::from_seed(session_id_hash.as_slice()), + pair, + &party_ids, + ) + .map_err(ProtocolExecutionErr::SessionCreation)?; let aux_info = execute_protocol_generic(chans, session, session_id_hash).await?.0; tracing::info!("Finished aux gen protocol"); @@ -327,7 +342,8 @@ pub async fn execute_proactive_refresh( tracing::debug!("Executing proactive refresh"); tracing::debug!("Signing with {:?}", &threshold_pair.public()); - let party_ids: Vec = threshold_accounts.iter().cloned().map(PartyId::new).collect(); + let party_ids: BTreeSet = + threshold_accounts.iter().cloned().map(PartyId::new).collect(); let pair = PairWrapper(threshold_pair.clone()); let verifying_key = old_key.verifying_key(); @@ -344,9 +360,14 @@ pub async fn execute_proactive_refresh( new_holders: party_ids.clone(), new_threshold: threshold, }; - let session = - make_key_resharing_session(&mut OsRng, &session_id_hash, pair, &party_ids, &inputs) - .map_err(ProtocolExecutionErr::SessionCreation)?; + let session = make_key_resharing_session( + &mut OsRng, + SynedrionSessionId::from_seed(session_id_hash.as_slice()), + pair, + &party_ids, + inputs, + ) + .map_err(ProtocolExecutionErr::SessionCreation)?; let new_key_share = execute_protocol_generic(chans, session, session_id_hash).await?.0; @@ -357,10 +378,11 @@ pub async fn execute_proactive_refresh( fn get_key_init_parties( my_party_id: &PartyId, threshold: usize, - validators: &[PartyId], + validators: &BTreeSet, session_id_hash: &[u8], -) -> Result<(Vec, bool), ProtocolExecutionErr> { - let mut parties = vec![]; +) -> Result<(BTreeSet, bool), ProtocolExecutionErr> { + let validators = validators.iter().cloned().collect::>(); + let mut parties = BTreeSet::new(); let mut includes_self = false; let number = BigUint::from_bytes_be(session_id_hash); let start_index_big = &number % validators.len(); @@ -372,7 +394,7 @@ fn get_key_init_parties( if member == my_party_id { includes_self = true; } - parties.push(member.clone()); + parties.insert(member.clone()); } Ok((parties, includes_self)) diff --git a/crates/protocol/src/protocol_message.rs b/crates/protocol/src/protocol_message.rs index 18b83d686..b197aaac6 100644 --- a/crates/protocol/src/protocol_message.rs +++ b/crates/protocol/src/protocol_message.rs @@ -17,7 +17,7 @@ use std::str; use serde::{Deserialize, Serialize}; use sp_core::sr25519; -use synedrion::sessions::CombinedMessage; +use synedrion::sessions::MessageBundle; use crate::{protocol_transport::errors::ProtocolMessageErr, PartyId}; @@ -41,7 +41,7 @@ pub struct ProtocolMessage { #[derive(Debug, Clone, Serialize, Deserialize)] pub enum ProtocolMessagePayload { /// The signed protocol message - CombinedMessage(Box>), + MessageBundle(Box>), /// A verifying key for parties who were not present in the key init session VerifyingKey(Vec), } @@ -59,13 +59,13 @@ impl ProtocolMessage { pub(crate) fn new( from: &PartyId, to: &PartyId, - payload: CombinedMessage, + payload: MessageBundle, session_id_hash: [u8; 32], ) -> Self { Self { from: from.clone(), to: to.clone(), - payload: ProtocolMessagePayload::CombinedMessage(Box::new(payload)), + payload: ProtocolMessagePayload::MessageBundle(Box::new(payload)), session_id_hash, } } diff --git a/crates/protocol/tests/protocol.rs b/crates/protocol/tests/protocol.rs index 36365c2d5..79aef51ee 100644 --- a/crates/protocol/tests/protocol.rs +++ b/crates/protocol/tests/protocol.rs @@ -31,6 +31,8 @@ use x25519_dalek::StaticSecret; mod helpers; use helpers::{server, ProtocolOutput}; +use std::collections::BTreeSet; + #[test] #[serial] fn sign_protocol_with_time_logged() { @@ -73,16 +75,15 @@ async fn test_sign_with_parties(num_parties: usize) { let (pairs, ids) = get_keypairs_and_ids(num_parties); let keyshares = KeyShare::::new_centralized(&mut OsRng, &ids, None); let aux_infos = AuxInfo::::new_centralized(&mut OsRng, &ids); - let verifying_key = keyshares[0].verifying_key(); + let verifying_key = keyshares[&PartyId::from(pairs[0].public())].verifying_key(); let parties: Vec<_> = pairs .iter() - .enumerate() - .map(|(i, pair)| ValidatorSecretInfo { + .map(|pair| ValidatorSecretInfo { pair: pair.clone(), - keyshare: Some(keyshares[i].clone()), + keyshare: Some(keyshares[&PartyId::from(pair.public())].clone()), threshold_keyshare: None, - aux_info: Some(aux_infos[i].clone()), + aux_info: Some(aux_infos[&PartyId::from(pair.public())].clone()), }) .collect(); let message_hash = [0u8; 32]; @@ -110,7 +111,7 @@ async fn test_sign_with_parties(num_parties: usize) { async fn test_refresh_with_parties(num_parties: usize) { let (pairs, ids) = get_keypairs_and_ids(num_parties); let keyshares = KeyShare::::new_centralized(&mut OsRng, &ids, None); - let verifying_key = keyshares[0].verifying_key(); + let verifying_key = keyshares[&PartyId::from(pairs[0].public())].verifying_key(); let session_id = SessionId::ProactiveRefresh { verifying_key: verifying_key.to_encoded_point(true).as_bytes().to_vec(), @@ -119,11 +120,12 @@ async fn test_refresh_with_parties(num_parties: usize) { let parties: Vec<_> = pairs .iter() - .enumerate() - .map(|(i, pair)| ValidatorSecretInfo { + .map(|pair| ValidatorSecretInfo { pair: pair.clone(), keyshare: None, - threshold_keyshare: Some(keyshares[i].to_threshold_key_share()), + threshold_keyshare: Some(ThresholdKeyShare::from_key_share( + &keyshares[&PartyId::from(pair.public())], + )), aux_info: None, }) .collect(); @@ -159,7 +161,13 @@ async fn test_dkg_and_sign_with_parties(num_parties: usize) { pairs.iter().map(|pair| ValidatorSecretInfo::pair_only(pair.clone())).collect(); let session_id = SessionId::Dkg { user: AccountId32([0; 32]), block_number: 0 }; let outputs = test_protocol_with_parties(dkg_parties, session_id, threshold).await; - let signing_committee = &ids[..threshold]; + + let signing_committee = (0..threshold) + .into_iter() + .map(|i| pairs[i].clone()) + .map(|pair| ids.get(&PartyId::from(pair.public())).unwrap()) + .cloned() + .collect::>(); let parties: Vec = outputs .clone() @@ -329,9 +337,11 @@ fn get_tokio_runtime(num_cpus: usize) -> Runtime { } /// Generate keypair and make PartyId from public key -fn get_keypairs_and_ids(num_parties: usize) -> (Vec, Vec) { +fn get_keypairs_and_ids(num_parties: usize) -> (Vec, BTreeSet) { let pairs = (0..num_parties).map(|_| sr25519::Pair::generate().0).collect::>(); - let ids = - pairs.iter().map(|pair| PartyId::new(AccountId32(pair.public().0))).collect::>(); + let ids = pairs + .iter() + .map(|pair| PartyId::new(AccountId32(pair.public().0))) + .collect::>(); (pairs, ids) } diff --git a/crates/testing-utils/Cargo.toml b/crates/testing-utils/Cargo.toml index e5d009528..94062fff7 100644 --- a/crates/testing-utils/Cargo.toml +++ b/crates/testing-utils/Cargo.toml @@ -22,7 +22,7 @@ entropy-shared ={ version="0.2.0", path="../shared" } entropy-kvdb ={ version="0.2.0", path="../kvdb", default-features=false } entropy-tss ={ version="0.2.0", path="../threshold-signature-server" } entropy-protocol ={ version="0.2.0", path="../protocol" } -synedrion ={ git="https://github.com/entropyxyz/synedrion", rev="25373111cbb01e1a25d8a5c5bb8f4652c725b3f1" } +synedrion ={ git="https://github.com/entropyxyz/synedrion", rev="3be1339c21384a8e60a1534f1d3bfdd022662e63" } hex ="0.4.3" rand_core ="0.6.4" rand ="0.8.5" diff --git a/crates/testing-utils/src/create_test_keyshares.rs b/crates/testing-utils/src/create_test_keyshares.rs index 663363764..09e3456aa 100644 --- a/crates/testing-utils/src/create_test_keyshares.rs +++ b/crates/testing-utils/src/create_test_keyshares.rs @@ -18,13 +18,14 @@ use entropy_protocol::{execute_protocol::PairWrapper, PartyId}; use rand_core::OsRng; use sp_core::{sr25519, Pair}; -use subxt::utils::AccountId32; use synedrion::{ - ecdsa::SigningKey, make_key_resharing_session, AuxInfo, KeyResharingInputs, KeyShare, - NewHolder, OldHolder, SchemeParams, ThresholdKeyShare, + ecdsa::SigningKey, make_key_resharing_session, sessions::SessionId, AuxInfo, + KeyResharingInputs, KeyShare, NewHolder, OldHolder, SchemeParams, ThresholdKeyShare, }; use synedrion_test_environment::run_nodes; +use std::collections::BTreeSet; + /// Given a secp256k1 secret key and 3 signing keypairs for the TSS parties, generate a set of /// threshold keyshares with auxiliary info pub async fn create_test_keyshares( @@ -37,34 +38,44 @@ where Params: SchemeParams, { let signing_key = SigningKey::from_bytes(&(distributed_secret_key_bytes).into()).unwrap(); - let signers = vec![alice, bob, charlie.clone()]; - let shared_randomness = b"12345"; + let signers = vec![alice.clone(), bob, charlie.clone()]; + let session_id = SessionId::from_seed(b"12345".as_slice()); let all_parties = - signers.iter().map(|pair| PartyId::new(AccountId32(pair.public().0))).collect::>(); + signers.iter().map(|pair| PartyId::from(pair.public())).collect::>(); - let old_holders = all_parties.clone().into_iter().take(2).collect::>(); + let old_holders = all_parties.clone().into_iter().take(2).collect::>(); let keyshares = KeyShare::::new_centralized(&mut OsRng, &old_holders, Some(&signing_key)); let aux_infos = AuxInfo::::new_centralized(&mut OsRng, &all_parties); - let new_holder = - NewHolder { verifying_key: keyshares[0].verifying_key(), old_threshold: 2, old_holders }; + let alice_id = PartyId::from(alice.public()); + let new_holder = NewHolder { + verifying_key: keyshares[&alice_id].verifying_key(), + old_threshold: 2, + old_holders, + }; - let mut sessions = (0..2) - .map(|idx| { + let mut sessions = signers + .iter() + .filter(|&pair| pair.public() != charlie.public()) + .map(|pair| { let inputs = KeyResharingInputs { - old_holder: Some(OldHolder { key_share: keyshares[idx].to_threshold_key_share() }), + old_holder: Some(OldHolder { + key_share: ThresholdKeyShare::from_key_share( + &keyshares[&PartyId::from(pair.public())], + ), + }), new_holder: Some(new_holder.clone()), new_holders: all_parties.clone(), new_threshold: 2, }; make_key_resharing_session( &mut OsRng, - shared_randomness, - PairWrapper(signers[idx].clone()), + session_id, + PairWrapper(pair.clone()), &all_parties, - &inputs, + inputs, ) .unwrap() }) @@ -79,10 +90,10 @@ where }; make_key_resharing_session( &mut OsRng, - shared_randomness, + session_id, PairWrapper(charlie), &all_parties, - &inputs, + inputs, ) .unwrap() }; @@ -92,8 +103,8 @@ where let new_t_key_shares = run_nodes(sessions).await; let mut output = Vec::new(); - for i in 0..3 { - output.push((new_t_key_shares[i].clone().unwrap(), aux_infos[i].clone())); + for (i, party_id) in signers.iter().map(|pair| PartyId::from(pair.public())).enumerate() { + output.push((new_t_key_shares[i].clone().unwrap(), aux_infos[&party_id].clone())); } output } @@ -106,24 +117,24 @@ mod synedrion_test_environment { use rand_core::OsRng; use sp_core::sr25519; use std::collections::BTreeMap; - use synedrion::{CombinedMessage, FinalizeOutcome, MappedResult, Session}; + use synedrion::{FinalizeOutcome, MessageBundle, ProtocolResult, Session}; use tokio::{ sync::mpsc, time::{sleep, Duration}, }; - type MessageOut = (PartyId, PartyId, CombinedMessage); - type MessageIn = (PartyId, CombinedMessage); + type MessageOut = (PartyId, PartyId, MessageBundle); + type MessageIn = (PartyId, MessageBundle); fn key_to_str(key: &PartyId) -> String { key.to_string() } /// Run a generic synedrion session - async fn run_session>( + async fn run_session( tx: mpsc::Sender, rx: mpsc::Receiver, session: Session, - ) -> Res::MappedSuccess { + ) -> Res::Success { let mut rx = rx; let mut session = session; @@ -239,10 +250,10 @@ mod synedrion_test_environment { pub async fn run_nodes( sessions: Vec>, - ) -> Vec + ) -> Vec where - Res: MappedResult + Send + 'static, - Res::MappedSuccess: Send + 'static, + Res: ProtocolResult + Send + 'static, + Res::Success: Send + 'static, { let num_parties = sessions.len(); @@ -257,7 +268,7 @@ mod synedrion_test_environment { let dispatcher_task = message_dispatcher(tx_map, dispatcher_rx); let dispatcher = tokio::spawn(dispatcher_task); - let handles: Vec> = rxs + let handles: Vec> = rxs .into_iter() .zip(sessions.into_iter()) .map(|(rx, session)| { diff --git a/crates/threshold-signature-server/Cargo.toml b/crates/threshold-signature-server/Cargo.toml index 40911ba78..af88f910f 100644 --- a/crates/threshold-signature-server/Cargo.toml +++ b/crates/threshold-signature-server/Cargo.toml @@ -21,7 +21,7 @@ zeroize ="1.8.1" hex ="0.4.3" reqwest-eventsource="0.6" serde_derive ="1.0.147" -synedrion ={ git="https://github.com/entropyxyz/synedrion", rev="25373111cbb01e1a25d8a5c5bb8f4652c725b3f1" } +synedrion ={ git="https://github.com/entropyxyz/synedrion", rev="3be1339c21384a8e60a1534f1d3bfdd022662e63" } strum ="0.26.2" backoff ={ version="0.4.0", features=["tokio"] } diff --git a/crates/threshold-signature-server/src/signing_client/protocol_execution/mod.rs b/crates/threshold-signature-server/src/signing_client/protocol_execution/mod.rs index 1cefdb6cc..abc0bec69 100644 --- a/crates/threshold-signature-server/src/signing_client/protocol_execution/mod.rs +++ b/crates/threshold-signature-server/src/signing_client/protocol_execution/mod.rs @@ -33,6 +33,8 @@ use crate::{ signing_client::{ListenerState, ProtocolErr}, }; +use std::collections::BTreeSet; + /// Thin wrapper around [ListenerState], manages execution of a signing party. #[derive(Clone)] pub struct ThresholdSigningService<'a> { @@ -98,7 +100,7 @@ impl<'a> ThresholdSigningService<'a> { return Err(ProtocolErr::BadSessionId); }; - let parties: Vec = + let parties: BTreeSet = threshold_accounts.iter().map(|t| PartyId::new(t.clone())).collect(); let rsig = execute_signing_protocol( diff --git a/scripts/create-test-keyshares/Cargo.toml b/scripts/create-test-keyshares/Cargo.toml index 77dcc7348..5ce936758 100644 --- a/scripts/create-test-keyshares/Cargo.toml +++ b/scripts/create-test-keyshares/Cargo.toml @@ -13,8 +13,9 @@ entropy-testing-utils={ version="0.2.0-rc.1", path="../../crates/testing-utils" tokio ={ version="1.38", features=["macros", "fs", "rt-multi-thread", "io-util", "process"] } entropy-shared ={ version="0.2.0-rc.1", path="../../crates/shared" } entropy-kvdb ={ version="0.2.0-rc.1", path="../../crates/kvdb", default-features=false } -# Unreleased version of synedrion - this was head of master at the point of beginning to add t of n -synedrion={ git="https://github.com/entropyxyz/synedrion", rev="25373111cbb01e1a25d8a5c5bb8f4652c725b3f1" } + +# Unreleased version of Synedrion with support for child key derivations. +synedrion={ git="https://github.com/entropyxyz/synedrion", rev="3be1339c21384a8e60a1534f1d3bfdd022662e63" } entropy-tss={ version="0.2.0-rc.1", path="../../crates/threshold-signature-server", features=[ "test_helpers", ] }