Skip to content

Commit

Permalink
Split registration flow based on existence of derivation path
Browse files Browse the repository at this point in the history
  • Loading branch information
HCastano committed Aug 7, 2024
1 parent bbb7b4d commit 1a4a39c
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 25 deletions.
6 changes: 4 additions & 2 deletions crates/threshold-signature-server/src/helpers/signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ pub async fn do_signing(
app_state: &AppState,
signing_session_info: SigningSessionInfo,
request_limit: u32,
derivation_path: Option<String>, // TODO (Nando): Not a fan of this...
) -> Result<RecoverableSignature, ProtocolErr> {
tracing::debug!("Preparing to perform signing");

Expand All @@ -60,8 +61,8 @@ pub async fn do_signing(

let account_id = AccountId32(signer.public().0);

// set up context for signing protocol execution
let sign_context = signing_service.get_sign_context(info.clone()).await?;
// Set up context for signing protocol execution
let sign_context = signing_service.get_sign_context(info.clone(), derivation_path).await?;

let tss_accounts: Vec<AccountId32> = user_signature_request
.validators_info
Expand Down Expand Up @@ -89,6 +90,7 @@ pub async fn do_signing(
&x25519_secret_key,
)
.await?;

let channels = {
let ready = timeout(Duration::from_secs(SETUP_TIMEOUT_SECONDS), rx_ready).await?;
let broadcast_out = ready??;
Expand Down
23 changes: 18 additions & 5 deletions crates/threshold-signature-server/src/helpers/substrate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,24 @@ pub async fn get_registered_details(
rpc: &LegacyRpcMethods<EntropyConfig>,
verifying_key: Vec<u8>,
) -> Result<RegisteredInfo, UserErr> {
let registered_info_query = entropy::storage().registry().registered(BoundedVec(verifying_key));
let result = query_chain(api, rpc, registered_info_query, None)
.await?
.ok_or_else(|| UserErr::ChainFetch("Not Registering error: Register Onchain first"))?;
Ok(result)
let registered_info_query =
entropy::storage().registry().registered(BoundedVec(verifying_key.clone()));
let registered_result = query_chain(api, rpc, registered_info_query, None).await?;

let registration_info = if let Some(old_registration_info) = registered_result {
old_registration_info
} else {
// We failed with the old registration path, let's try the new one
let registered_info_query =
entropy::storage().registry().registered_on_chain(BoundedVec(verifying_key));
let new_registration_info = query_chain(api, rpc, registered_info_query, None)
.await?
.ok_or_else(|| UserErr::ChainFetch("Not Registering error: Register Onchain first"))?;

new_registration_info
};

Ok(registration_info)
}

/// Takes Stash keys and returns validator info from chain
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,35 @@ impl<'a> ThresholdSigningService<'a> {
fields(sign_init),
level = tracing::Level::DEBUG
)]
pub async fn get_sign_context(&self, sign_init: SignInit) -> Result<SignContext, ProtocolErr> {
pub async fn get_sign_context(
&self,
sign_init: SignInit,
derivation_path: Option<String>,
) -> Result<SignContext, ProtocolErr> {
tracing::debug!("Getting signing context");
let key_share_and_aux_info_vec = self
.kv_manager
.kv()
.get(&hex::encode(sign_init.signing_session_info.signature_verifying_key.clone()))
.await?;

let verifying_key = if derivation_path.is_some() {
entropy_shared::NETWORK_PARENT_KEY.as_bytes().to_vec()
} else {
sign_init.signing_session_info.signature_verifying_key.clone()
};

let key_share_and_aux_info_vec =
self.kv_manager.kv().get(&hex::encode(verifying_key)).await?;

let (key_share, aux_info): (
ThresholdKeyShare<KeyParams, PartyId>,
AuxInfo<KeyParams, PartyId>,
) = entropy_kvdb::kv_manager::helpers::deserialize(&key_share_and_aux_info_vec)
.ok_or_else(|| ProtocolErr::Deserialization("Failed to load KeyShare".into()))?;

let key_share = if let Some(path) = derivation_path {
let path = path.parse().expect("TODO");
key_share.derive_bip32(&path).expect("TODO")
} else {
key_share
};

Ok(SignContext::new(sign_init, key_share, aux_info))
}

Expand Down
43 changes: 31 additions & 12 deletions crates/threshold-signature-server/src/user/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ pub async fn sign_tx(
.number;

check_stale(user_sig_req.block_number, block_number).await?;

// Probably impossible but block signing from parent key anyways
if string_verifying_key == hex::encode(NETWORK_PARENT_KEY) {
return Err(UserErr::NoSigningFromParentKey);
Expand All @@ -159,7 +160,9 @@ pub async fn sign_tx(
if user_details.programs_data.0.is_empty() {
return Err(UserErr::NoProgramPointerDefined());
}
// handle aux data padding, if it is not explicit by client for ease send through None, error if incorrect length

// handle aux data padding, if it is not explicit by client for ease send through None, error
// if incorrect length
let auxilary_data_vec;
if let Some(auxilary_data) = user_sig_req.clone().auxilary_data {
if auxilary_data.len() < user_details.programs_data.0.len() {
Expand All @@ -170,6 +173,7 @@ pub async fn sign_tx(
} else {
auxilary_data_vec = vec![None; user_details.programs_data.0.len()];
}

// gets fuel from chain
let max_instructions_per_programs_query =
entropy::storage().parameters().max_instructions_per_programs();
Expand All @@ -186,7 +190,9 @@ pub async fn sign_tx(
runtime.evaluate(&program, &signature_request, Some(&program_info.program_config), None)?;
}

// TODO (Nando): Internal algo needs to be changed here
let signers = get_signers_from_chain(&api, &rpc).await?;

// Use the validator info from chain as we can be sure it is in the correct order and the
// details are correct
user_sig_req.validators_info = signers;
Expand All @@ -207,22 +213,35 @@ pub async fn sign_tx(
request_author,
};

let _has_key = check_for_key(&string_verifying_key, &app_state.kv_store).await?;
// In the new registration flow we don't store the verifying key in the KVDB, so we only do this
// check if we're using the old registration flow
if user_details.derivation_path.is_none() {
let _has_key = check_for_key(&string_verifying_key, &app_state.kv_store).await?;
}

// TODO (Nando): We're hardcoding this for now since we know the path used on-chain
let derivation_path = user_details.derivation_path.map(|count| format!("m/0/{}", count));

let (mut response_tx, response_rx) = mpsc::channel(1);

// Do the signing protocol in another task, so we can already respond
tokio::spawn(async move {
let signing_protocol_output =
do_signing(&rpc, user_sig_req, &app_state, signing_session_id, request_limit)
.await
.map(|signature| {
(
BASE64_STANDARD.encode(signature.to_rsv_bytes()),
signer.signer().sign(&signature.to_rsv_bytes()),
)
})
.map_err(|error| error.to_string());
let signing_protocol_output = do_signing(
&rpc,
user_sig_req,
&app_state,
signing_session_id,
request_limit,
derivation_path,
)
.await
.map(|signature| {
(
BASE64_STANDARD.encode(signature.to_rsv_bytes()),
signer.signer().sign(&signature.to_rsv_bytes()),
)
})
.map_err(|error| error.to_string());

// This response chunk is sent later with the result of the signing protocol
if response_tx.try_send(serde_json::to_string(&signing_protocol_output)).is_err() {
Expand Down

0 comments on commit 1a4a39c

Please sign in to comment.