diff --git a/CHANGELOG.md b/CHANGELOG.md index 226084b6..d3b9c1d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Security +## Unreleased +### Added + +### Changed + +### Deprecated + +### Removed + +### Fixed +- [\#289](https://github.com/Manta-Network/manta-signer/pull/289) Fix authorization state preventing consecutive transactions + +### Security + ## [1.0.1] 2023-01-24 ### Added - [\#261](https://github.com/Manta-Network/manta-signer/pull/261) Bundle Proving Keys with manta-signer (no download anymore) diff --git a/src/service.rs b/src/service.rs index d51e0942..53b47349 100644 --- a/src/service.rs +++ b/src/service.rs @@ -212,9 +212,11 @@ where .is_ok() { self.authorizer.sleep().await; + println!("Password is ok"); return Ok(()); } } else { + println!("Password is now known, returning auth error"); return Err(Error::AuthorizationError); } delay_password_retry().await; @@ -445,7 +447,6 @@ where #[inline] pub async fn cancel_signing(&mut self) { self.state.lock().currently_signing = false; - // Forcefully sleep because the authorizer gets stuck awake if we exit recovery window self.authorizer.lock().await.authorizer.sleep(); } diff --git a/ui/src-tauri/src/main.rs b/ui/src-tauri/src/main.rs index 6eb75482..f3105272 100644 --- a/ui/src-tauri/src/main.rs +++ b/ui/src-tauri/src/main.rs @@ -267,6 +267,7 @@ impl Authorizer for User { T: Serialize, { APP_STATE.set_authorizing(true); + println!("INFO: Server Awake"); self.emit("authorize", prompt); Box::pin(async move {}) } @@ -274,7 +275,7 @@ impl Authorizer for User { #[inline] fn sleep(&mut self) -> UnitFuture { APP_STATE.set_authorizing(false); - self.emit("abort_auth", &()); + println!("INFO: Server Sleeping"); Box::pin(async move { self.validate_password().await }) } } @@ -358,7 +359,7 @@ async fn set_tray_reset(tray_handle: SystemTrayHandle, reset: bool, show_phrase: "view secret recovery phrase", "View Secret Recovery Phrase", )) - .add_item(CustomMenuItem::new("view zk address", "View ZkAddress")) + .add_item(CustomMenuItem::new("view zk address", "View zkAddress")) .add_item(CustomMenuItem::new("reset", "Delete Account")) .add_item(CustomMenuItem::new("exit", "Quit")) } else if reset { @@ -569,11 +570,10 @@ async fn get_recovery_phrase( server_store: State<'_, ServerStore>, ) -> Result { if let Some(store) = &mut *server_store.lock().await { - let mnemonic = store - .get_stored_mnemonic(Network::Dolphin, &prompt) - .await - .expect("Unable to fetch mnemonic"); - Ok(mnemonic) + match store.get_stored_mnemonic(Network::Dolphin, &prompt).await { + Ok(mnemonic) => Ok(mnemonic), + Err(_) => Err(()), + } } else { Err(()) } @@ -713,11 +713,15 @@ fn main() { "about" => window(app, "about").hide().expect("Unable to hide window."), "main" => { if APP_STATE.get_ready() { - window(app, "main").hide().expect("Unable to hide window."); if APP_STATE.get_authorizing() { + // should not hide from here, let UI handle its authorization aborting and hiding window(app, "main") - .emit_all("abort_auth", "Aborting Authorization") + .emit("abort_auth", "Aborting Authorization") .expect("Failed to abort authorization"); + APP_STATE.set_authorizing(false); + } else { + // hide any non process showing window like show zkAddress + window(app, "main").hide().expect("Unable to hide window."); } } else { app.exit(0); diff --git a/ui/src/App.js b/ui/src/App.js index e0570561..fafdc161 100644 --- a/ui/src/App.js +++ b/ui/src/App.js @@ -158,12 +158,14 @@ function App() { // Case 1: we need authorization for exporting the recovery phrase. if (event.payload === GET_RECOVERY_PHRASE) { + console.log("[INFO]: Viewing secret phrase window"); navigate("/view-secret-phrase"); appWindow.show(); return; } // Case 2: we need authorization for signing a transaction. + console.log("[INFO]: Authorization for transaction"); await checkAndStopExportingPhrase(); let parsedAuthorizationSummary = parseTransactionSummary(event.payload.split(" ")); @@ -175,7 +177,7 @@ function App() { const listenForShowSecretPhraseRequests = async () => { console.log("[INFO]: Setup tray show secret phrase listener."); - listen('show_secret_phrase', (_event) => { + listen('show_secret_phrase', async (_event) => { getSecretRecoveryPhrase(); }) } @@ -207,11 +209,17 @@ function App() { exportingPhraseRef.current = true; } - console.log("[INFO]: Send request to export recovery phrase."); - let phrase = await invoke('get_recovery_phrase', { prompt: GET_RECOVERY_PHRASE }); + try { + console.log("[INFO]: Send request to export recovery phrase."); + let phrase = await invoke('get_recovery_phrase', { prompt: GET_RECOVERY_PHRASE }) - if (phrase) { - setExportedSecretPhrase(phrase); + console.log("[INFO]: Request for recovery phrase passed"); + if (phrase) { + await setExportedSecretPhrase(phrase); + } + } catch(error) { + console.log("[WARNING]: Failed getting mnemonic, either fail or aborted (expected)"); + return; } } diff --git a/ui/src/pages/Authorize.js b/ui/src/pages/Authorize.js index 0bb0e587..626a03d1 100644 --- a/ui/src/pages/Authorize.js +++ b/ui/src/pages/Authorize.js @@ -12,12 +12,13 @@ const Authorize = ({ const [password, setPassword] = useState(''); const [passwordInvalid, setPasswordInvalid] = useState(false); - useEffect(() => { once("abort_auth", async () => { + console.log("[INFO]: Authorization window aborting to cancel function"); await onClickDecline(); }); - }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); const onClickAuthorize = async () => { console.log("[INFO]: Authorizing."); diff --git a/ui/src/pages/ViewPhrase/ViewPhrasePage.js b/ui/src/pages/ViewPhrase/ViewPhrasePage.js index 7223ddad..756e69c4 100644 --- a/ui/src/pages/ViewPhrase/ViewPhrasePage.js +++ b/ui/src/pages/ViewPhrase/ViewPhrasePage.js @@ -13,13 +13,15 @@ const ViewPhrasePage = ({ onClickSubmitPassword, onClickCancel }) => { - + useEffect(() => { once("abort_auth", async () => { + console.log("[INFO]: ViewPhrasePage aborting to cancel function"); await onClickCancel(); }); - }); - + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + return (<>
diff --git a/ui/src/pages/ViewPhrase/ViewSecretPhrase.js b/ui/src/pages/ViewPhrase/ViewSecretPhrase.js index 1089b1a3..2acea4f7 100644 --- a/ui/src/pages/ViewPhrase/ViewSecretPhrase.js +++ b/ui/src/pages/ViewPhrase/ViewSecretPhrase.js @@ -1,4 +1,4 @@ -import { useState } from "react"; +import React, { useState } from 'react'; import ViewPhrasePage from "./ViewPhrasePage"; import ViewPhraseSuccess from "./ViewPhraseSuccess"; @@ -21,6 +21,7 @@ const ViewSecretPhrase = ({ } const onClickCancel = async () => { + console.log("[INFO]: Canceling Phrase Exporting Process"); await stopPasswordPrompt(); endExportPhrase(); }