diff --git a/CHANGELOG.md b/CHANGELOG.md index fc13c3f4..3a041986 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Added ### Changed +- [\#343](https://github.com/Manta-Network/manta-signer/pull/343) Adds ability to load mnemonic from old state version. - [\#338](https://github.com/Manta-Network/manta-signer/pull/338) Change start button to continue in View zkAddress. - [\#332](https://github.com/Manta-Network/manta-signer/pull/332) Add sink account validation diff --git a/Cargo.lock b/Cargo.lock index 9db95b1c..2b058547 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -687,6 +687,15 @@ version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bip0039" version = "0.10.1" @@ -2728,6 +2737,17 @@ dependencies = [ "libc", ] +[[package]] +name = "manta-accounting" +version = "0.5.10" +source = "git+https://github.com/manta-network/manta-rs?tag=v0.5.10#86b4630b02ec211c4cce8628d771e2c26f18a814" +dependencies = [ + "derivative", + "derive_more", + "manta-crypto 0.5.10", + "manta-util 0.5.10", +] + [[package]] name = "manta-accounting" version = "0.5.12" @@ -2737,8 +2757,34 @@ dependencies = [ "cocoon", "derivative", "derive_more", - "manta-crypto", - "manta-util", + "manta-crypto 0.5.12", + "manta-util 0.5.12", +] + +[[package]] +name = "manta-crypto" +version = "0.5.10" +source = "git+https://github.com/manta-network/manta-rs?tag=v0.5.10#86b4630b02ec211c4cce8628d771e2c26f18a814" +dependencies = [ + "ark-bls12-381", + "ark-bn254", + "ark-ec", + "ark-ed-on-bls12-381", + "ark-ed-on-bn254", + "ark-ff", + "ark-groth16", + "ark-r1cs-std", + "ark-relations", + "ark-serialize", + "ark-snark", + "ark-std", + "derivative", + "ed25519-dalek", + "manta-util 0.5.10", + "num-integer", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_core 0.6.4", ] [[package]] @@ -2760,13 +2806,25 @@ dependencies = [ "ark-std", "derivative", "ed25519-dalek", - "manta-util", + "manta-util 0.5.12", "num-integer", "rand 0.8.5", "rand_chacha 0.3.1", "rand_core 0.6.4", ] +[[package]] +name = "manta-parameters" +version = "0.5.10" +source = "git+https://github.com/manta-network/manta-rs?tag=v0.5.10#86b4630b02ec211c4cce8628d771e2c26f18a814" +dependencies = [ + "anyhow", + "blake3", + "gitignore", + "hex", + "walkdir", +] + [[package]] name = "manta-parameters" version = "0.5.12" @@ -2780,6 +2838,24 @@ dependencies = [ "walkdir", ] +[[package]] +name = "manta-pay" +version = "0.5.10" +source = "git+https://github.com/manta-network/manta-rs?tag=v0.5.10#86b4630b02ec211c4cce8628d771e2c26f18a814" +dependencies = [ + "aes-gcm 0.9.4", + "bip0039", + "bip32", + "blake2 0.10.6", + "bs58", + "derivative", + "manta-accounting 0.5.10", + "manta-crypto 0.5.10", + "manta-parameters 0.5.10", + "manta-util 0.5.10", + "num-bigint", +] + [[package]] name = "manta-pay" version = "0.5.12" @@ -2791,10 +2867,10 @@ dependencies = [ "blake2 0.10.6", "bs58", "derivative", - "manta-accounting", - "manta-crypto", - "manta-parameters", - "manta-util", + "manta-accounting 0.5.12", + "manta-crypto 0.5.12", + "manta-parameters 0.5.12", + "manta-util 0.5.12", "num-bigint", ] @@ -2804,16 +2880,18 @@ version = "1.1.1" dependencies = [ "argon2", "async-std", + "bincode", "chrono", "derivative", "dirs-next", "futures", "http-types", - "manta-accounting", - "manta-crypto", - "manta-parameters", - "manta-pay", - "manta-util", + "manta-accounting 0.5.12", + "manta-crypto 0.5.12", + "manta-parameters 0.5.12", + "manta-pay 0.5.10", + "manta-pay 0.5.12", + "manta-util 0.5.12", "parking_lot", "password-hash", "reqwest", @@ -2834,6 +2912,16 @@ dependencies = [ "tauri-build", ] +[[package]] +name = "manta-util" +version = "0.5.10" +source = "git+https://github.com/manta-network/manta-rs?tag=v0.5.10#86b4630b02ec211c4cce8628d771e2c26f18a814" +dependencies = [ + "crossbeam-channel", + "serde", + "serde_with", +] + [[package]] name = "manta-util" version = "0.5.12" diff --git a/Cargo.toml b/Cargo.toml index 67a2694b..7427a7f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ disable-restart = [] [dependencies] argon2 = { version = "0.4.1", default-features = false, features = ["alloc", "password-hash"] } async-std = { version = "1.11.0", default-features = false, features = ["attributes", "tokio1"] } +bincode = "1.3.3" chrono = { version = "0.4.19", default-features = false, features = ["clock"] } derivative = { version = "2.2.0", default-features = false, features = ["use_core"] } dirs-next = { version = "2.0.0", default-features = false } @@ -50,6 +51,7 @@ manta-pay = { git = "https://github.com/manta-network/manta-rs", tag = "v0.5.12" manta-util = { git = "https://github.com/manta-network/manta-rs", tag = "v0.5.12", default-features = false } parking_lot = { version = "0.12.1", default-features = false } password-hash = { version = "0.4.2", default-features = false, features = ["alloc"] } +previous-state-manta-pay = { package = "manta-pay", git = "https://github.com/manta-network/manta-rs", tag = "v0.5.10", default-features = false, features = ["bs58", "groth16", "serde", "wallet", "std", "parameters"] } reqwest = { version = "0.11.14", default-features = false, features = ["json"] } secrecy = { version = "0.8.0", default-features = false, features = ["alloc"] } serde_json = { version = "1.0.91", default-features = false } diff --git a/src/service.rs b/src/service.rs index a95a2875..11716925 100644 --- a/src/service.rs +++ b/src/service.rs @@ -44,6 +44,10 @@ use manta_pay::{ AssetMetadata, TokenType, }, }; + +/// previous version of manta-pay state. Should use versioning system for SignerState +use previous_state_manta_pay::signer::base::SignerState as OldSignerState; + use manta_util::{from_variant, serde::Serialize}; use parking_lot::Mutex; use std::{ @@ -436,7 +440,7 @@ where }; let existing_signer = Signer::from_parts( parameters.clone(), - Self::load_state(existing_state_path, password_hash) + Self::load_state(existing_state_path, password_hash, ¶meters) .await .expect("Unable to get dolphin state")?, ); @@ -474,7 +478,7 @@ where .expect("Unable to recreate signer instance from existing mnemonic."); Ok(Some(state)) } else { - Self::load_state(data_path, password_hash).await + Self::load_state(data_path, password_hash, parameters).await } } @@ -557,17 +561,51 @@ where async fn load_state( data_path: &Path, password_hash: &PasswordHash, + parameters: &SignerParameters, ) -> Result> { info!("loading signer state from disk")?; - let data_path = data_path.to_owned(); + let data_path_buf = data_path.to_owned(); + let password_hash_bytes = password_hash.as_bytes(); + + let state_result = task::spawn_blocking(move || { + File::load::<_, SignerState>(&data_path_buf, &password_hash_bytes) + }) + .await?; + + if let Ok(correct_state) = state_result { + Ok(Some(correct_state)) + } else { + // fallback to try from old state version + Self::new_state_from_old_state(data_path, password_hash, parameters).await + } + } + + /// Attempts to create new signer state from the old signer state version + #[inline] + async fn new_state_from_old_state( + data_path: &Path, + password_hash: &PasswordHash, + parameters: &SignerParameters, + ) -> Result> { + info!("loading mnemonic from old state")?; + let data_path_buf = data_path.to_owned(); let password_hash_bytes = password_hash.as_bytes(); if let Ok(state) = task::spawn_blocking(move || { - File::load::<_, SignerState>(&data_path, &password_hash_bytes) + File::load::<_, OldSignerState>(&data_path_buf, &password_hash_bytes) }) .await? { - Ok(Some(state)) + let mnemonic = state.accounts().keys().expose_mnemonic().clone(); + + let encoded: Vec = bincode::serialize(&mnemonic).expect("encoding mnenomic failed"); + let new_mnemonic: Mnemonic = + bincode::deserialize(&encoded[..]).expect("decoding mnenomic failed"); + + let new_state = + Self::create_state(data_path, password_hash, new_mnemonic, parameters).await?; + + Ok(Some(new_state)) } else { Ok(None) }