Skip to content

Commit

Permalink
Run the aux gen protocol when resharing to a new signing committee (#977
Browse files Browse the repository at this point in the history
)

* Rename subsession enum

* Fix updating keyshare on proactive refresh

* Add aux gen to reshare process

* Check that both aux info and keyshare changes following reshare in test

* Testing-utils should load entropy-tss with the test_helpers feature present

* Changelog

* Tidy

* Add TODO

* Taplo

* Rm entry from changelog

* Comment following review
  • Loading branch information
ameba23 authored Aug 7, 2024
1 parent 7454094 commit f54a54f
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 26 deletions.
8 changes: 4 additions & 4 deletions crates/protocol/src/execute_protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use crate::{
errors::{GenericProtocolError, ProtocolExecutionErr},
protocol_message::{ProtocolMessage, ProtocolMessagePayload},
protocol_transport::Broadcaster,
DkgSubsession, KeyParams, KeyShareWithAuxInfo, PartyId, SessionId,
KeyParams, KeyShareWithAuxInfo, PartyId, SessionId, Subsession,
};

use std::collections::BTreeSet;
Expand Down Expand Up @@ -217,7 +217,7 @@ pub async fn execute_dkg(

let my_party_id = PartyId::new(AccountId32(threshold_pair.public().0));

let session_id_hash = session_id.blake2(Some(DkgSubsession::KeyInit))?;
let session_id_hash = session_id.blake2(Some(Subsession::KeyInit))?;
let (key_init_parties, includes_me) =
get_key_init_parties(&my_party_id, threshold, &party_ids, &session_id_hash)?;

Expand Down Expand Up @@ -293,7 +293,7 @@ pub async fn execute_dkg(
new_threshold: threshold,
};

let session_id_hash = session_id.blake2(Some(DkgSubsession::Reshare))?;
let session_id_hash = session_id.blake2(Some(Subsession::Reshare))?;
let session = make_key_resharing_session(
&mut OsRng,
SynedrionSessionId::from_seed(session_id_hash.as_slice()),
Expand All @@ -312,7 +312,7 @@ pub async fn execute_dkg(
let chans = Channels(broadcaster.clone(), rx);

// Now run the aux gen protocol to get AuxInfo
let session_id_hash = session_id.blake2(Some(DkgSubsession::AuxGen))?;
let session_id_hash = session_id.blake2(Some(Subsession::AuxGen))?;
let session = make_aux_gen_session(
&mut OsRng,
SynedrionSessionId::from_seed(session_id_hash.as_slice()),
Expand Down
6 changes: 3 additions & 3 deletions crates/protocol/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ impl SessionId {
/// Optionally with some extra data used to identify a sub-session
pub fn blake2(
&self,
sub_session: Option<DkgSubsession>,
sub_session: Option<Subsession>,
) -> Result<[u8; 32], ProtocolExecutionErr> {
let mut hasher = Blake2s256::new();
hasher.update(bincode::serialize(self)?);
Expand All @@ -214,9 +214,9 @@ impl SessionId {
}
}

/// A sub-protocol of the DKG protocol
/// A sub-protocol of the DKG or reshare protocols
#[derive(Debug)]
pub enum DkgSubsession {
pub enum Subsession {
/// The synedrion key init protocol
KeyInit,
/// The synedrion reshare protocol
Expand Down
2 changes: 1 addition & 1 deletion crates/testing-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ tokio ={ version="1.39", features=["macros", "fs", "rt-multi-thread"
axum ={ version="0.7.5" }
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-tss ={ version="0.2.0", path="../threshold-signature-server", features=["test_helpers"] }
entropy-protocol ={ version="0.2.0", path="../protocol" }
synedrion ={ git="https://github.com/entropyxyz/synedrion", rev="3be1339c21384a8e60a1534f1d3bfdd022662e63" }
hex ="0.4.3"
Expand Down
16 changes: 14 additions & 2 deletions crates/threshold-signature-server/src/signing_client/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use axum::{
use blake2::{Blake2s256, Digest};
use entropy_protocol::{
execute_protocol::{execute_proactive_refresh, Channels},
KeyParams, Listener, PartyId, SessionId, ValidatorInfo,
KeyParams, KeyShareWithAuxInfo, Listener, PartyId, SessionId, ValidatorInfo,
};
use parity_scale_codec::Encode;

Expand Down Expand Up @@ -112,7 +112,19 @@ pub async fn proactive_refresh(
ocw_data.block_number,
)
.await?;
let serialized_key_share = key_serialize(&new_key_share)

// Get aux info from existing entry
let aux_info = {
let existing_entry = app_state.kv_store.kv().get(&key).await?;
let (_old_key_share, aux_info): KeyShareWithAuxInfo = deserialize(&existing_entry)
.ok_or_else(|| {
ProtocolErr::Deserialization("Failed to load KeyShare".into())
})?;
aux_info
};

// Since this is a refresh with the parties not changing, store the old aux_info
let serialized_key_share = key_serialize(&(new_key_share, aux_info))
.map_err(|_| ProtocolErr::KvSerialize("Kv Serialize Error".to_string()))?;

app_state.kv_store.kv().delete(&key).await?;
Expand Down
43 changes: 32 additions & 11 deletions crates/threshold-signature-server/src/validator/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use crate::{
};
use axum::{body::Bytes, extract::State, http::StatusCode};
use entropy_kvdb::kv_manager::{helpers::serialize as key_serialize, KvManager};
use entropy_protocol::Subsession;
pub use entropy_protocol::{
decode_verifying_key,
errors::ProtocolExecutionErr,
Expand All @@ -45,8 +46,8 @@ use subxt::{
OnlineClient,
};
use synedrion::{
make_key_resharing_session, sessions::SessionId as SynedrionSessionId, KeyResharingInputs,
NewHolder, OldHolder,
make_aux_gen_session, make_key_resharing_session, sessions::SessionId as SynedrionSessionId,
AuxInfo, KeyResharingInputs, NewHolder, OldHolder,
};
use tokio::time::timeout;

Expand Down Expand Up @@ -150,7 +151,7 @@ pub async fn new_reshare(

let session_id = SessionId::Reshare { verifying_key, block_number: data.block_number };
let account_id = AccountId32(signer.signer().public().0);
let session_id_hash = session_id.blake2(None)?;
let session_id_hash = session_id.blake2(Some(Subsession::Reshare))?;
let pair = PairWrapper(signer.signer().clone());

let mut converted_validator_info = vec![];
Expand Down Expand Up @@ -183,27 +184,47 @@ pub async fn new_reshare(
)
.await?;

let channels = {
let (channels, broadcaster) = {
let ready = timeout(Duration::from_secs(SETUP_TIMEOUT_SECONDS), rx_ready).await?;
let broadcast_out = ready??;
Channels(broadcast_out, rx_from_others)
(Channels(broadcast_out.clone(), rx_from_others), broadcast_out)
};

let session = make_key_resharing_session(
&mut OsRng,
SynedrionSessionId::from_seed(session_id_hash.as_slice()),
pair,
pair.clone(),
&party_ids,
inputs,
)
.map_err(ProtocolExecutionErr::SessionCreation)?;

let new_key_share = execute_protocol_generic(channels, session, session_id_hash)
let (new_key_share_option, rx) = execute_protocol_generic(channels, session, session_id_hash)
.await
.map_err(|_| ValidatorErr::ProtocolError("Error executing protocol".to_string()))?
.0
.ok_or(ValidatorErr::NoOutputFromReshareProtocol)?;
let serialized_key_share = key_serialize(&new_key_share)
.map_err(|_| ValidatorErr::ProtocolError("Error executing protocol".to_string()))?;

let new_key_share = new_key_share_option.ok_or(ValidatorErr::NoOutputFromReshareProtocol)?;

// Setup channels for the next session
let channels = Channels(broadcaster, rx);

// Now run an aux gen session
let session_id_hash = session_id.blake2(Some(Subsession::AuxGen))?;
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: AuxInfo<KeyParams, PartyId> =
execute_protocol_generic(channels, session, session_id_hash)
.await
.map_err(|_| ValidatorErr::ProtocolError("Error executing protocol".to_string()))?
.0;

let serialized_key_share = key_serialize(&(new_key_share, aux_info))
.map_err(|_| ProtocolErr::KvSerialize("Kv Serialize Error".to_string()))?;
let network_parent_key = hex::encode(NETWORK_PARENT_KEY);
// TODO: should this be a two step process? see # https://github.com/entropyxyz/entropy-core/issues/968
Expand Down
24 changes: 19 additions & 5 deletions crates/threshold-signature-server/src/validator/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ use crate::{
},
validator::{api::validate_new_reshare, errors::ValidatorErr},
};
use entropy_kvdb::clean_tests;
use entropy_kvdb::{
clean_tests,
kv_manager::helpers::{deserialize, serialize},
};
use entropy_protocol::KeyShareWithAuxInfo;
use entropy_shared::{
OcwMessageReshare, EVE_VERIFYING_KEY, MIN_BALANCE, NETWORK_PARENT_KEY,
TEST_RESHARE_BLOCK_NUMBER,
Expand Down Expand Up @@ -92,12 +96,22 @@ async fn test_reshare() {
for response_result in response_results {
assert_eq!(response_result.unwrap().text().await.unwrap(), "");
}

for i in 0..validator_ports.len() {
assert_ne!(
key_shares_before[i],
unsafe_get(&client, hex::encode(NETWORK_PARENT_KEY), validator_ports[i]).await
);
let (key_share_before, aux_info_before): KeyShareWithAuxInfo =
deserialize(&key_shares_before[i]).unwrap();

let key_share_and_aux_data_after =
unsafe_get(&client, hex::encode(NETWORK_PARENT_KEY), validator_ports[i]).await;
let (key_share_after, aux_info_after): KeyShareWithAuxInfo =
deserialize(&key_share_and_aux_data_after).unwrap();

// Check key share has changed
assert_ne!(serialize(&key_share_before).unwrap(), serialize(&key_share_after).unwrap());
// Check aux info has changed
assert_ne!(serialize(&aux_info_before).unwrap(), serialize(&aux_info_after).unwrap());
}
// TODO #981 - test signing a message with the new keyshare set
clean_tests();
}

Expand Down

0 comments on commit f54a54f

Please sign in to comment.