diff --git a/crates/threshold-signature-server/src/helpers/signing.rs b/crates/threshold-signature-server/src/helpers/signing.rs index 29daf9ac5..fc8799687 100644 --- a/crates/threshold-signature-server/src/helpers/signing.rs +++ b/crates/threshold-signature-server/src/helpers/signing.rs @@ -45,6 +45,7 @@ pub async fn do_signing( app_state: &AppState, signing_session_info: SigningSessionInfo, request_limit: u32, + derivation_path: Option, // TODO (Nando): Not a fan of this... ) -> Result { tracing::debug!("Preparing to perform signing"); @@ -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 = user_signature_request .validators_info @@ -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??; diff --git a/crates/threshold-signature-server/src/helpers/substrate.rs b/crates/threshold-signature-server/src/helpers/substrate.rs index 5b036275c..2627ce456 100644 --- a/crates/threshold-signature-server/src/helpers/substrate.rs +++ b/crates/threshold-signature-server/src/helpers/substrate.rs @@ -67,11 +67,24 @@ pub async fn get_registered_details( rpc: &LegacyRpcMethods, verifying_key: Vec, ) -> Result { - 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 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 abc0bec69..7a3db6fed 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 @@ -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 { + pub async fn get_sign_context( + &self, + sign_init: SignInit, + derivation_path: Option, + ) -> Result { 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, AuxInfo, ) = 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)) } diff --git a/crates/threshold-signature-server/src/user/api.rs b/crates/threshold-signature-server/src/user/api.rs index 6e5b4bda7..6e914188e 100644 --- a/crates/threshold-signature-server/src/user/api.rs +++ b/crates/threshold-signature-server/src/user/api.rs @@ -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); @@ -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() { @@ -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(); @@ -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; @@ -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() {