Skip to content

Commit

Permalink
proactive refresh (#413)
Browse files Browse the repository at this point in the history
* proactive refresh

* spec out proactive refresh endpoint

* testing framework

* store fake key

* add send key

* setup websockets

* update synedrion

* working

* errors

* more negative tests
  • Loading branch information
JesseAbram authored Oct 9, 2023
1 parent 9ac98b5 commit 48259be
Show file tree
Hide file tree
Showing 19 changed files with 507 additions and 146 deletions.
110 changes: 7 additions & 103 deletions Cargo.lock

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

6 changes: 3 additions & 3 deletions crypto/kvdb/src/kv_manager/value.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::{convert::TryFrom, path::PathBuf};

use entropy_protocol::{KeyParams, PartyId};
use entropy_protocol::PartyId;
use serde::{Deserialize, Serialize};
use synedrion::KeyShare;
use synedrion::{KeyShare, ProductionParams};
use tracing::{info, span, Level, Span};
use zeroize::Zeroize;

Expand All @@ -24,7 +24,7 @@ pub struct Entropy(pub Vec<u8>);
pub struct PartyInfo {
// TODO: in the future this will probably be a mapping {party_id: [share_id, share_id, ...]}
pub party_ids: Vec<PartyId>,
pub share: KeyShare<KeyParams>,
pub share: KeyShare<ProductionParams>,
}

/// Kv manager for grpc services
Expand Down
92 changes: 90 additions & 2 deletions crypto/protocol/src/execute_protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use subxt::utils::AccountId32;
use subxt_signer::sr25519;
use synedrion::{
sessions::{
make_interactive_signing_session, make_keygen_and_aux_session, FinalizeOutcome,
PrehashedMessage, ToSend,
make_interactive_signing_session, make_key_refresh_session, make_keygen_and_aux_session,
FinalizeOutcome, PrehashedMessage, ToSend,
},
signature::{
self,
Expand Down Expand Up @@ -245,3 +245,91 @@ pub async fn execute_dkg(
}
}
}

/// Execute proactive refresh.
#[instrument(skip(chans, threshold_signer))]
pub async fn execute_proactive_refresh(
mut chans: Channels,
threshold_signer: &sr25519::Keypair,
threshold_accounts: Vec<AccountId32>,
my_idx: &u8,
old_key: KeyShare<KeyParams>,
) -> Result<KeyShare<KeyParams>, ProtocolExecutionErr> {
let party_ids: Vec<PartyId> =
threshold_accounts.clone().into_iter().map(PartyId::new).collect();
let my_id = PartyId::new(threshold_accounts[*my_idx as usize].clone());
let id_to_index = party_ids
.iter()
.enumerate()
.map(|(idx, id)| (id, PartyIdx::from_usize(idx)))
.collect::<HashMap<_, _>>();

let tx = &chans.0;
let rx = &mut chans.1;

let signer = SignerWrapper(threshold_signer.clone());
// TODO (#376): while `Public::from_raw` happens to work here, it is not the correct way.
// We should have `Public` objects at this point, not `AccountId32`.
let verifiers = threshold_accounts
.into_iter()
.map(|acc| VerifierWrapper(sr25519::PublicKey(acc.0)))
.collect::<Vec<_>>();

// TODO (#375): this should come from whoever initiates the signing process,
// (or as some deterministic function, e.g. the hash of the last block mined)
// and be the same for all participants.
let shared_randomness = b"123456";

let mut sending = make_key_refresh_session(
&mut OsRng,
shared_randomness,
signer,
&verifiers,
PartyIdx::from_usize(*my_idx as usize),
)
.map_err(ProtocolExecutionErr::SessionCreationError)?;
let key_change = loop {
let (mut receiving, to_send) =
sending.start_receiving(&mut OsRng).map_err(ProtocolExecutionErr::SynedrionSession)?;

match to_send {
ToSend::Broadcast(message) => {
tx.send(ProtocolMessage::new_bcast(&my_id, message))?;
},
ToSend::Direct(msgs) =>
for (id_to, message) in msgs.into_iter() {
tx.send(ProtocolMessage::new_p2p(
&my_id,
&party_ids[id_to.as_usize()],
message,
))?;
},
};

while receiving.has_cached_messages() {
receiving.receive_cached_message().map_err(ProtocolExecutionErr::SynedrionSession)?;
}

while !receiving.can_finalize() {
let signing_message = rx.recv().await.ok_or_else(|| {
ProtocolExecutionErr::IncomingStream(format!("{:?}", receiving.current_stage()))
})?;

// TODO: we shouldn't send broadcasts to ourselves in the first place.
if signing_message.from == my_id {
continue;
}
let from_idx = id_to_index[&signing_message.from];
receiving
.receive(from_idx, signing_message.payload)
.map_err(ProtocolExecutionErr::SynedrionSession)?;
}

match receiving.finalize(&mut OsRng).map_err(ProtocolExecutionErr::SynedrionSession)? {
FinalizeOutcome::Result(res) => break res,
FinalizeOutcome::AnotherRound(new_sending) => sending = new_sending,
}
};

Ok(old_key.update(key_change))
}
Binary file modified crypto/server/entropy_metadata.scale
Binary file not shown.
8 changes: 3 additions & 5 deletions crypto/server/src/helpers/signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,11 @@ pub async fn do_signing(
let info =
SignInit::new(message.clone(), sig_hash.clone(), tx_id.clone(), user_address.clone())?;
let signing_service = ThresholdSigningService::new(state, kv_manager);
let signer =
get_signer(kv_manager).await.map_err(|_| ProtocolErr::UserError("Error getting Signer"))?;
let signer = get_signer(kv_manager).await.map_err(|e| ProtocolErr::UserError(e.to_string()))?;

let x25519_secret_key = derive_static_secret(signer.signer());
let subxt_signer = get_subxt_signer(kv_manager)
.await
.map_err(|_| ProtocolErr::UserError("Error getting Signer"))?;
let subxt_signer =
get_subxt_signer(kv_manager).await.map_err(|e| ProtocolErr::UserError(e.to_string()))?;

let account_id = AccountId32(subxt_signer.public_key().0);

Expand Down
15 changes: 15 additions & 0 deletions crypto/server/src/helpers/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use entropy_protocol::{
KeyParams, ValidatorInfo,
};
use entropy_shared::{KeyVisibility, SETUP_TIMEOUT_SECONDS};
use parity_scale_codec::Encode;
use sp_core::crypto::AccountId32;
use subxt::{
ext::sp_core::{sr25519, Bytes},
Expand Down Expand Up @@ -134,3 +135,17 @@ pub async fn send_key(
}
Ok(())
}

/// Checks if a validator is in the current selected registration committee
pub fn check_in_registration_group(
validators_info: &[entropy_shared::ValidatorInfo],
validator_address: &SubxtAccountId32,
) -> Result<(), UserErr> {
let is_proper_signer = validators_info
.iter()
.any(|validator_info| validator_info.tss_account == validator_address.encode());
if !is_proper_signer {
return Err(UserErr::InvalidSigner("Invalid Signer in Signing group"));
}
Ok(())
}
5 changes: 3 additions & 2 deletions crypto/server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ async fn main() {
}
// TODO: find a proper batch size
let batch_size = 10;
let key_amount = 10_000;
let signer = get_signer(&kv_store).await.expect("Issue acquiring threshold signer key");
let has_fee_balance = check_balance_for_fees(&api, signer.account_id(), MIN_BALANCE)
.await
Expand All @@ -199,15 +200,14 @@ async fn main() {
let ip_address =
String::from_utf8(key_server_info.endpoint).expect("failed to parse IP address.");
let recip_key = x25519_dalek::PublicKey::from(key_server_info.x25519_public_key);
let all_keys = get_all_keys(&api, batch_size).await.expect("failed to get all keys.");
let all_keys = get_all_keys(&api, key_amount).await.expect("failed to get all keys.");
let _ = get_and_store_values(
all_keys, &kv_store, ip_address, batch_size, args.dev, &recip_key, &signer,
)
.await;
tell_chain_syncing_is_done(&api, &signer).await.expect("failed to finish chain sync.");
}

// TODO: unhardcode endpoint
let addr = SocketAddr::from_str(&args.threshold_url).expect("failed to parse threshold url.");
tracing::info!("listening on {}", addr);
axum::Server::bind(&addr)
Expand All @@ -221,6 +221,7 @@ pub fn app(app_state: AppState) -> Router {
.route("/user/sign_tx", post(sign_tx))
.route("/user/new", post(new_user))
.route("/user/receive_key", post(receive_key))
.route("/signer/proactive_refresh", post(proactive_refresh))
.route("/validator/sync_kvdb", post(sync_kvdb))
.route("/healthz", get(healthz))
.route("/ws", get(ws_handler));
Expand Down
Loading

0 comments on commit 48259be

Please sign in to comment.