From 2ad12d596eb81c091c8c56098354d3c8bbec6da1 Mon Sep 17 00:00:00 2001 From: Benno Zeeman Date: Fri, 18 Oct 2024 17:22:05 +0200 Subject: [PATCH 1/4] feat(autonomi): expose user data in wasm --- autonomi/src/client/vault_user_data.rs | 25 ++++++++++ autonomi/src/client/wasm.rs | 63 ++++++++++++++++++++++++-- autonomi/tests-js/index.js | 17 +++++-- 3 files changed, 98 insertions(+), 7 deletions(-) diff --git a/autonomi/src/client/vault_user_data.rs b/autonomi/src/client/vault_user_data.rs index 779cf023d9..a45a2adaea 100644 --- a/autonomi/src/client/vault_user_data.rs +++ b/autonomi/src/client/vault_user_data.rs @@ -65,6 +65,31 @@ impl UserData { Self::default() } + /// Add an archive. Returning true if the archive was newly added. + pub fn add_file_archive(&mut self, archive: ArchiveAddr) -> bool { + self.file_archives.insert(archive) + } + + /// Add a name for an archive. Returning the old archive if it existed. + pub fn add_file_archive_name( + &mut self, + archive: ArchiveAddr, + name: String, + ) -> Option { + self.file_archive_names.insert(name, archive) + } + + /// Remove an archive. Returning true if the archive was removed. + pub fn remove_file_archive(&mut self, archive: ArchiveAddr) -> bool { + // TODO: Should we also remove the name? + self.file_archives.remove(&archive) + } + + /// Remove a archive name. Returning the archive if it existed. + pub fn remove_file_archive_name(&mut self, name: String) -> Option { + self.file_archive_names.remove(&name) + } + /// To bytes pub fn to_bytes(&self) -> Result { let bytes = rmp_serde::to_vec(&self)?; diff --git a/autonomi/src/client/wasm.rs b/autonomi/src/client/wasm.rs index 56ebca582e..6ac80e2558 100644 --- a/autonomi/src/client/wasm.rs +++ b/autonomi/src/client/wasm.rs @@ -4,9 +4,6 @@ use wasm_bindgen::prelude::*; use super::address::{addr_to_str, str_to_addr}; use super::vault_user_data::UserData; -#[wasm_bindgen(js_name = UserData)] -pub struct JsUserData(UserData); - #[wasm_bindgen(js_name = Client)] pub struct JsClient(super::Client); @@ -141,6 +138,66 @@ mod vault { use super::*; use bls::SecretKey; + #[wasm_bindgen(js_name = UserData)] + pub struct JsUserData(UserData); + + #[wasm_bindgen(js_class = UserData)] + impl JsUserData { + #[wasm_bindgen(constructor)] + pub fn new() -> Self { + Self(UserData::new()) + } + + #[wasm_bindgen(js_name = addArchive)] + pub fn add_archive( + &mut self, + archive: String, + name: Option, + ) -> Result<(), JsError> { + let archive = str_to_addr(&archive)?; + + // TODO: Log when archive already exists? + self.0.add_file_archive(archive); + + if let Some(name) = name { + if let Some(old_archive) = self.0.add_file_archive_name(archive, name.clone()) { + tracing::warn!( + "Overwriting archive stored as '{name}': {old_archive} -> {archive}" + ); + } + } + + Ok(()) + } + + #[wasm_bindgen(js_name = removeArchive)] + pub fn remove_archive(&mut self, archive: String) -> Result<(), JsError> { + let archive = str_to_addr(&archive)?; + self.0.remove_file_archive(archive); + + Ok(()) + } + + #[wasm_bindgen(js_name = removeArchiveName)] + pub fn remove_archive_name(&mut self, name: String) -> Result<(), JsError> { + let _archive_name = self.0.remove_file_archive_name(name); + + Ok(()) + } + + #[wasm_bindgen(js_name = archives)] + pub fn archives(&self) -> Result { + let archives = serde_wasm_bindgen::to_value(&self.0.file_archives)?; + Ok(archives) + } + + #[wasm_bindgen(js_name = archiveNames)] + pub fn archive_names(&self) -> Result { + let archives = serde_wasm_bindgen::to_value(&self.0.file_archive_names)?; + Ok(archives) + } + } + #[wasm_bindgen(js_class = Client)] impl JsClient { #[wasm_bindgen(js_name = getUserDataFromVault)] diff --git a/autonomi/tests-js/index.js b/autonomi/tests-js/index.js index a44ae3892c..75b3b76312 100644 --- a/autonomi/tests-js/index.js +++ b/autonomi/tests-js/index.js @@ -53,13 +53,22 @@ describe('autonomi', function () { assert.deepEqual(archive, archiveFetched); }); - it('writes bytes to vault and fetches it', async () => { + it('writes archive to vault and fetches it', async () => { + const addr = "0000000000000000000000000000000000000000000000000000000000000000"; // Dummy data address const data = randomData(32); const secretKey = atnm.genSecretKey(); - await client.writeBytesToVault(data, wallet, secretKey); - const dataFetched = await client.fetchAndDecryptVault(secretKey); + const archive = new atnm.Archive(); + archive.addNewFile('foo', addr); + const archiveAddr = await client.archivePut(archive, wallet); + + const userData = new atnm.UserData(); + userData.addArchive(archiveAddr, 'foo'); + + await client.putUserDataToVault(data, wallet, secretKey); + const userDataFetched = await client.put_user_data_to_vault(secretKey); - assert.deepEqual(data, dataFetched); + assert.deepEqual(userDataFetched.archives(), userData.archives()); + assert.deepEqual(userDataFetched.archiveNames(), userData.archiveNames()); }); }); From 6c32173ab41d669781db6b672b72fb1db7f5d6a2 Mon Sep 17 00:00:00 2001 From: Benno Zeeman Date: Mon, 21 Oct 2024 13:13:35 +0200 Subject: [PATCH 2/4] refactor(autonomi): move `new` to top of impl And move conversion to/from bytes to the bottom --- autonomi/src/client/archive.rs | 42 +++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/autonomi/src/client/archive.rs b/autonomi/src/client/archive.rs index 17055e0682..aa5301cfeb 100644 --- a/autonomi/src/client/archive.rs +++ b/autonomi/src/client/archive.rs @@ -68,19 +68,12 @@ impl Default for Metadata { } impl Archive { - /// Deserialize from bytes. - pub fn from_bytes(data: Bytes) -> Result { - let root: Archive = rmp_serde::from_slice(&data[..])?; - - Ok(root) - } - - /// Serialize to bytes. - pub fn into_bytes(&self) -> Result { - let root_serialized = rmp_serde::to_vec(&self)?; - let root_serialized = Bytes::from(root_serialized); - - Ok(root_serialized) + /// Create a new emtpy local archive + /// Note that this does not upload the archive to the network + pub fn new() -> Self { + Self { + map: HashMap::new(), + } } /// Rename a file in an archive @@ -99,14 +92,6 @@ impl Archive { Ok(()) } - /// Create a new emtpy local archive - /// Note that this does not upload the archive to the network - pub fn new() -> Self { - Self { - map: HashMap::new(), - } - } - /// Add a file to a local archive /// Note that this does not upload the archive to the network pub fn add_file(&mut self, path: PathBuf, data_addr: DataAddr, meta: Metadata) { @@ -144,6 +129,21 @@ impl Archive { pub fn map(&self) -> &HashMap { &self.map } + + /// Deserialize from bytes. + pub fn from_bytes(data: Bytes) -> Result { + let root: Archive = rmp_serde::from_slice(&data[..])?; + + Ok(root) + } + + /// Serialize to bytes. + pub fn into_bytes(&self) -> Result { + let root_serialized = rmp_serde::to_vec(&self)?; + let root_serialized = Bytes::from(root_serialized); + + Ok(root_serialized) + } } impl Client { From dc2ae9750656be1a6ba62f62375823b624df7db0 Mon Sep 17 00:00:00 2001 From: Benno Zeeman Date: Mon, 21 Oct 2024 16:01:06 +0200 Subject: [PATCH 3/4] refactor(autonomi): user data refactor --- autonomi/src/client/vault_user_data.rs | 30 +++++------- autonomi/src/client/wasm.rs | 63 ++++++++++---------------- autonomi/tests-js/index.js | 11 ++--- 3 files changed, 39 insertions(+), 65 deletions(-) diff --git a/autonomi/src/client/vault_user_data.rs b/autonomi/src/client/vault_user_data.rs index a45a2adaea..6533c738dc 100644 --- a/autonomi/src/client/vault_user_data.rs +++ b/autonomi/src/client/vault_user_data.rs @@ -37,13 +37,11 @@ pub struct UserData { pub register_sk: Option, /// Owned register addresses pub registers: HashSet, - /// Owned file archive addresses - pub file_archives: HashSet, + /// Owned file archive addresses, along with an optional name for that archive + pub file_archives: HashMap>, /// Owner register names, providing it is optional pub register_names: HashMap, - /// Owned file archive addresses along with a name for that archive providing it is optional - pub file_archive_names: HashMap, } /// Errors that can occur during the get operation. @@ -65,31 +63,25 @@ impl UserData { Self::default() } - /// Add an archive. Returning true if the archive was newly added. - pub fn add_file_archive(&mut self, archive: ArchiveAddr) -> bool { - self.file_archives.insert(archive) + /// Add an archive. Returning `Some` (with the optional old name) if the archive was already in the set. + pub fn add_file_archive(&mut self, archive: ArchiveAddr) -> Option> { + self.file_archives.insert(archive, None) } - /// Add a name for an archive. Returning the old archive if it existed. - pub fn add_file_archive_name( + /// Add an archive. Returning `Some` (with the optional old name) if the archive was already in the set. + pub fn add_file_archive_with_name( &mut self, archive: ArchiveAddr, name: String, - ) -> Option { - self.file_archive_names.insert(name, archive) + ) -> Option> { + self.file_archives.insert(archive, Some(name)) } - /// Remove an archive. Returning true if the archive was removed. - pub fn remove_file_archive(&mut self, archive: ArchiveAddr) -> bool { - // TODO: Should we also remove the name? + /// Remove an archive. Returning `Some` (with the optional old name) if the archive was in the set. + pub fn remove_file_archive(&mut self, archive: ArchiveAddr) -> Option> { self.file_archives.remove(&archive) } - /// Remove a archive name. Returning the archive if it existed. - pub fn remove_file_archive_name(&mut self, name: String) -> Option { - self.file_archive_names.remove(&name) - } - /// To bytes pub fn to_bytes(&self) -> Result { let bytes = rmp_serde::to_vec(&self)?; diff --git a/autonomi/src/client/wasm.rs b/autonomi/src/client/wasm.rs index 6ac80e2558..bae5cc8eba 100644 --- a/autonomi/src/client/wasm.rs +++ b/autonomi/src/client/wasm.rs @@ -148,54 +148,40 @@ mod vault { Self(UserData::new()) } - #[wasm_bindgen(js_name = addArchive)] - pub fn add_archive( + #[wasm_bindgen(js_name = addFileArchive)] + pub fn add_file_archive( &mut self, archive: String, name: Option, ) -> Result<(), JsError> { let archive = str_to_addr(&archive)?; - // TODO: Log when archive already exists? - self.0.add_file_archive(archive); + let old_name = if let Some(ref name) = name { + self.0.add_file_archive_with_name(archive, name.clone()) + } else { + self.0.add_file_archive(archive) + }; - if let Some(name) = name { - if let Some(old_archive) = self.0.add_file_archive_name(archive, name.clone()) { - tracing::warn!( - "Overwriting archive stored as '{name}': {old_archive} -> {archive}" - ); - } + if let Some(old_name) = old_name { + tracing::warn!("Overwriting archive (`{archive}`): `{old_name:?}` -> `{name:?}`"); } Ok(()) } - #[wasm_bindgen(js_name = removeArchive)] - pub fn remove_archive(&mut self, archive: String) -> Result<(), JsError> { + #[wasm_bindgen(js_name = removeFileArchive)] + pub fn remove_file_archive(&mut self, archive: String) -> Result<(), JsError> { let archive = str_to_addr(&archive)?; self.0.remove_file_archive(archive); Ok(()) } - #[wasm_bindgen(js_name = removeArchiveName)] - pub fn remove_archive_name(&mut self, name: String) -> Result<(), JsError> { - let _archive_name = self.0.remove_file_archive_name(name); - - Ok(()) - } - - #[wasm_bindgen(js_name = archives)] - pub fn archives(&self) -> Result { + #[wasm_bindgen(js_name = fileArchives)] + pub fn file_archives(&self) -> Result { let archives = serde_wasm_bindgen::to_value(&self.0.file_archives)?; Ok(archives) } - - #[wasm_bindgen(js_name = archiveNames)] - pub fn archive_names(&self) -> Result { - let archives = serde_wasm_bindgen::to_value(&self.0.file_archive_names)?; - Ok(archives) - } } #[wasm_bindgen(js_class = Client)] @@ -203,12 +189,9 @@ mod vault { #[wasm_bindgen(js_name = getUserDataFromVault)] pub async fn get_user_data_from_vault( &self, - secret_key: Vec, + secret_key: &SecretKeyJs, ) -> Result { - let secret_key: [u8; 32] = secret_key[..].try_into()?; - let secret_key = SecretKey::from_bytes(secret_key)?; - - let user_data = self.0.get_user_data_from_vault(&secret_key).await?; + let user_data = self.0.get_user_data_from_vault(&secret_key.0).await?; Ok(JsUserData(user_data)) } @@ -216,15 +199,12 @@ mod vault { #[wasm_bindgen(js_name = putUserDataToVault)] pub async fn put_user_data_to_vault( &self, - user_data: JsUserData, + user_data: &JsUserData, wallet: &JsWallet, - secret_key: Vec, + secret_key: &SecretKeyJs, ) -> Result<(), JsError> { - let secret_key: [u8; 32] = secret_key[..].try_into()?; - let secret_key = SecretKey::from_bytes(secret_key)?; - self.0 - .put_user_data_to_vault(&secret_key, &wallet.0, user_data.0) + .put_user_data_to_vault(&secret_key.0, &wallet.0, user_data.0.clone()) .await?; Ok(()) @@ -232,10 +212,13 @@ mod vault { } } +#[wasm_bindgen(js_name = SecretKey)] +pub struct SecretKeyJs(bls::SecretKey); + #[wasm_bindgen(js_name = genSecretKey)] -pub fn gen_secret_key() -> Vec { +pub fn gen_secret_key() -> SecretKeyJs { let secret_key = bls::SecretKey::random(); - secret_key.to_bytes().to_vec() + SecretKeyJs(secret_key) } #[wasm_bindgen(js_name = Wallet)] diff --git a/autonomi/tests-js/index.js b/autonomi/tests-js/index.js index 75b3b76312..1dd1dffac0 100644 --- a/autonomi/tests-js/index.js +++ b/autonomi/tests-js/index.js @@ -63,12 +63,11 @@ describe('autonomi', function () { const archiveAddr = await client.archivePut(archive, wallet); const userData = new atnm.UserData(); - userData.addArchive(archiveAddr, 'foo'); + userData.addFileArchive(archiveAddr, 'foo'); - await client.putUserDataToVault(data, wallet, secretKey); - const userDataFetched = await client.put_user_data_to_vault(secretKey); - - assert.deepEqual(userDataFetched.archives(), userData.archives()); - assert.deepEqual(userDataFetched.archiveNames(), userData.archiveNames()); + await client.putUserDataToVault(userData, wallet, secretKey); + const userDataFetched = await client.getUserDataFromVault(secretKey); + + assert.deepEqual(userDataFetched.fileArchives(), userData.fileArchives()); }); }); From 284608d887d06625e487834f4749eccf586a7cc7 Mon Sep 17 00:00:00 2001 From: Benno Zeeman Date: Tue, 22 Oct 2024 08:54:40 +0200 Subject: [PATCH 4/4] refactor(autonomi): use empty string as default --- autonomi/src/client/vault_user_data.rs | 28 +++++++++++--------------- autonomi/src/client/wasm.rs | 4 +++- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/autonomi/src/client/vault_user_data.rs b/autonomi/src/client/vault_user_data.rs index 6533c738dc..e40e73e260 100644 --- a/autonomi/src/client/vault_user_data.rs +++ b/autonomi/src/client/vault_user_data.rs @@ -7,7 +7,6 @@ // permissions and limitations relating to use of the SAFE Network Software. use std::collections::HashMap; -use std::collections::HashSet; use super::archive::ArchiveAddr; use super::data::GetError; @@ -35,13 +34,10 @@ pub static USER_DATA_VAULT_CONTENT_IDENTIFIER: LazyLock = pub struct UserData { /// The register secret key hex encoded pub register_sk: Option, - /// Owned register addresses - pub registers: HashSet, - /// Owned file archive addresses, along with an optional name for that archive - pub file_archives: HashMap>, - - /// Owner register names, providing it is optional - pub register_names: HashMap, + /// Owned register addresses, along with their names (can be empty) + pub registers: HashMap, + /// Owned file archive addresses, along with their names (can be empty) + pub file_archives: HashMap, } /// Errors that can occur during the get operation. @@ -63,22 +59,22 @@ impl UserData { Self::default() } - /// Add an archive. Returning `Some` (with the optional old name) if the archive was already in the set. - pub fn add_file_archive(&mut self, archive: ArchiveAddr) -> Option> { - self.file_archives.insert(archive, None) + /// Add an archive. Returning `Option::Some` with the old name if the archive was already in the set. + pub fn add_file_archive(&mut self, archive: ArchiveAddr) -> Option { + self.file_archives.insert(archive, "".into()) } - /// Add an archive. Returning `Some` (with the optional old name) if the archive was already in the set. + /// Add an archive. Returning `Option::Some` with the old name if the archive was already in the set. pub fn add_file_archive_with_name( &mut self, archive: ArchiveAddr, name: String, - ) -> Option> { - self.file_archives.insert(archive, Some(name)) + ) -> Option { + self.file_archives.insert(archive, name) } - /// Remove an archive. Returning `Some` (with the optional old name) if the archive was in the set. - pub fn remove_file_archive(&mut self, archive: ArchiveAddr) -> Option> { + /// Remove an archive. Returning `Option::Some` with the old name if the archive was already in the set. + pub fn remove_file_archive(&mut self, archive: ArchiveAddr) -> Option { self.file_archives.remove(&archive) } diff --git a/autonomi/src/client/wasm.rs b/autonomi/src/client/wasm.rs index bae5cc8eba..d4dd7cf674 100644 --- a/autonomi/src/client/wasm.rs +++ b/autonomi/src/client/wasm.rs @@ -163,7 +163,9 @@ mod vault { }; if let Some(old_name) = old_name { - tracing::warn!("Overwriting archive (`{archive}`): `{old_name:?}` -> `{name:?}`"); + tracing::warn!( + "Changing name of archive `{archive}` from `{old_name:?}` to `{name:?}`" + ); } Ok(())