From 0579e3ff1c6cdba6ae58b8b07037c2e7dabb11c2 Mon Sep 17 00:00:00 2001 From: Alexander Cyon Date: Fri, 19 Jan 2024 14:11:08 +0100 Subject: [PATCH] WIP display/debug and Wallet Account tests --- .../bip39/bip39_passphrase.rs | 31 +++++++++++------- .../bip39/mnemonic.rs | 29 +++++++++++++---- .../derivation/mnemonic_with_passphrase.rs | 32 +++++++++++++++---- .../secure_storage/wallet_client_storage.rs | 8 ++++- profile/src/wallet/wallet_accounts.rs | 9 +++++- .../wallet_kit_common/types/logged_result.rs | 1 + 6 files changed, 83 insertions(+), 27 deletions(-) diff --git a/profile/src/hierarchical_deterministic/bip39/bip39_passphrase.rs b/profile/src/hierarchical_deterministic/bip39/bip39_passphrase.rs index db462aca..21082127 100644 --- a/profile/src/hierarchical_deterministic/bip39/bip39_passphrase.rs +++ b/profile/src/hierarchical_deterministic/bip39/bip39_passphrase.rs @@ -9,17 +9,23 @@ use crate::prelude::*; )] #[serde(transparent)] #[display("")] -#[debug("{:?}", self.non_sensitive())] +#[debug("{:?}", self.partially_obfuscated_string())] pub struct BIP39Passphrase(pub String); -impl SafeToLog for BIP39Passphrase { - /// Logs the word count and FactorSourceID o - fn non_sensitive(&self) -> impl std::fmt::Debug { +impl BIP39Passphrase { + pub fn partially_obfuscated_string(&self) -> String { if self.0.is_empty() { "" } else { "" } + .to_string() + } +} +impl SafeToLog for BIP39Passphrase { + /// Logs the word count and FactorSourceID o + fn non_sensitive(&self) -> impl std::fmt::Debug { + self.partially_obfuscated_string() } } @@ -71,20 +77,23 @@ mod tests { } #[test] - fn display() { + fn debug() { assert_eq!( - format!("{}", BIP39Passphrase::new("so secret")), - "" + format!("{:?}", BIP39Passphrase::new("so secret")), + format!("{:?}", "") + ); + assert_eq!( + format!("{:?}", BIP39Passphrase::default()), + format!("{:?}", "") ); - assert_eq!(format!("{}", BIP39Passphrase::default()), ""); } #[test] - fn debug() { + fn display() { assert_eq!( - format!("{:?}", BIP39Passphrase::new("so secret")), + format!("{}", BIP39Passphrase::new("so secret")), "" ); - assert_eq!(format!("{:?}", BIP39Passphrase::default()), ""); + assert_eq!(format!("{}", BIP39Passphrase::default()), ""); } } diff --git a/profile/src/hierarchical_deterministic/bip39/mnemonic.rs b/profile/src/hierarchical_deterministic/bip39/mnemonic.rs index d10b1140..f71dcf56 100644 --- a/profile/src/hierarchical_deterministic/bip39/mnemonic.rs +++ b/profile/src/hierarchical_deterministic/bip39/mnemonic.rs @@ -5,23 +5,29 @@ use crate::prelude::*; PartialEq, Eq, Hash, - SerializeDisplay, DeserializeFromStr, derive_more::Display, derive_more::Debug, uniffi::Record, )] -#[display("OBFUSCATED")] -#[debug("{:?}", self.non_sensitive())] +#[display("{}", self.to_obfuscated_string())] +#[debug("{:?}", self.partially_obfuscated_string())] pub struct Mnemonic { pub words: Vec, pub word_count: BIP39WordCount, pub language: BIP39Language, } -impl SafeToLog for Mnemonic { - /// Logs the word count and FactorSourceID o - fn non_sensitive(&self) -> impl std::fmt::Debug { +impl Serialize for Mnemonic { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.phrase().serialize(serializer) + } +} +impl Mnemonic { + pub fn partially_obfuscated_string(&self) -> String { format!( "{} ({}...{})", self.word_count, @@ -30,6 +36,12 @@ impl SafeToLog for Mnemonic { ) } } +impl SafeToLog for Mnemonic { + /// Logs the word count and FactorSourceID o + fn non_sensitive(&self) -> impl std::fmt::Debug { + self.partially_obfuscated_string() + } +} /// Returns the words of a mnemonic as a String joined by spaces, e.g. "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong" #[uniffi::export] @@ -129,7 +141,10 @@ mod tests { #[test] fn debug() { let mnemonic = Mnemonic::placeholder(); - assert_eq!(format!("{:?}", mnemonic), "24 words (bright...mandate)") + assert_eq!( + format!("{:?}", mnemonic), + format!("{:?}", "24 words (bright...mandate)") + ); } #[test] diff --git a/profile/src/hierarchical_deterministic/derivation/mnemonic_with_passphrase.rs b/profile/src/hierarchical_deterministic/derivation/mnemonic_with_passphrase.rs index 22f75307..8dfe9c01 100644 --- a/profile/src/hierarchical_deterministic/derivation/mnemonic_with_passphrase.rs +++ b/profile/src/hierarchical_deterministic/derivation/mnemonic_with_passphrase.rs @@ -15,20 +15,25 @@ use crate::prelude::*; )] #[serde(rename_all = "camelCase")] #[display("")] -#[debug("{:?}", self.non_sensitive())] +#[debug("{:?}", self.partially_obfuscated_string())] pub struct MnemonicWithPassphrase { pub mnemonic: Mnemonic, pub passphrase: BIP39Passphrase, } +impl MnemonicWithPassphrase { + pub fn partially_obfuscated_string(&self) -> String { + format!( + "{} + {}", + self.mnemonic.partially_obfuscated_string(), + self.passphrase.partially_obfuscated_string() + ) + } +} impl SafeToLog for MnemonicWithPassphrase { /// Logs the word count and FactorSourceID o fn non_sensitive(&self) -> impl std::fmt::Debug { - format!( - "{:?} + {:?}", - self.mnemonic.non_sensitive(), - self.passphrase.non_sensitive() - ) + self.partially_obfuscated_string() } } @@ -152,11 +157,24 @@ mod tests { MnemonicWithPassphrase::placeholder_other() ); } + #[test] fn display() { assert_eq!( format!("{}", MnemonicWithPassphrase::placeholder()), - "" + "" + ); + } + + #[test] + fn debug() { + assert_eq!( + format!("{:?}", MnemonicWithPassphrase::placeholder()), + format!("{:?}", "24 words (bright...mandate) + ") + ); + assert_eq!( + format!("{:?}", MnemonicWithPassphrase::placeholder_other()), + format!("{:?}", "12 words (zoo...wrong) + ") ); } diff --git a/profile/src/wallet/secure_storage/wallet_client_storage.rs b/profile/src/wallet/secure_storage/wallet_client_storage.rs index cc86cfd7..1601dce4 100644 --- a/profile/src/wallet/secure_storage/wallet_client_storage.rs +++ b/profile/src/wallet/secure_storage/wallet_client_storage.rs @@ -53,9 +53,15 @@ impl WalletClientStorage { self.interface.load_data(key).and_then(|o| match o { None => Ok(None), Some(j) => serde_json::from_slice(j.as_slice()).map_err(|_| { + let type_name = std::any::type_name::().to_string(); + error!( + "Failed to deserialize json to type: {}\nJSON (utf8):\n{:?}", + &type_name, + String::from_utf8(j.clone()) + ); CommonError::FailedToDeserializeJSONToValue { json_byte_count: j.len(), - type_name: std::any::type_name::().to_string(), + type_name, } }), }) diff --git a/profile/src/wallet/wallet_accounts.rs b/profile/src/wallet/wallet_accounts.rs index 1f299df3..25f6e7c1 100644 --- a/profile/src/wallet/wallet_accounts.rs +++ b/profile/src/wallet/wallet_accounts.rs @@ -356,7 +356,14 @@ mod tests { fn load_private_device_factor_source_by_id() { let profile = Profile::placeholder(); let private = PrivateHierarchicalDeterministicFactorSource::placeholder(); - let (wallet, _) = Wallet::ephemeral(profile.clone()); + let (wallet, storage) = Wallet::ephemeral(profile.clone()); + + let data = serde_json::to_vec(&private.mnemonic_with_passphrase).unwrap(); + let key = SecureStorageKey::DeviceFactorSourceMnemonic { + factor_source_id: private.clone().factor_source.id.clone(), + }; + assert!(storage.save_data(key.clone(), data.clone()).is_ok()); + assert_eq!( wallet.load_private_device_factor_source_by_id(&private.factor_source.id.clone()), Ok(private.clone()) diff --git a/profile/src/wallet_kit_common/types/logged_result.rs b/profile/src/wallet_kit_common/types/logged_result.rs index 00db6a1d..147e5577 100644 --- a/profile/src/wallet_kit_common/types/logged_result.rs +++ b/profile/src/wallet_kit_common/types/logged_result.rs @@ -20,5 +20,6 @@ impl LoggedResult for Result { F: FnOnce(&T) -> String, { self.inspect(|x| log::log!(level, "{}", format(&x))) + .inspect_err(|e| error!("Err: {}", e)) } }