From d48f65e388dde809d2f18e0bdb647ad603d01acd Mon Sep 17 00:00:00 2001
From: Benno Zeeman <bzeeman@live.nl>
Date: Tue, 1 Oct 2024 12:51:44 +0200
Subject: [PATCH] refactor(autonomi): pass vault key as parameter

---
 autonomi/src/client/files.rs | 29 ++++++++++++------
 autonomi/src/client/mod.rs   | 10 +-----
 autonomi/src/client/vault.rs | 59 +++++++++++-------------------------
 autonomi/tests/file.rs       | 28 ++++++-----------
 4 files changed, 49 insertions(+), 77 deletions(-)

diff --git a/autonomi/src/client/files.rs b/autonomi/src/client/files.rs
index 524fc6fb7e..e53ab37d32 100644
--- a/autonomi/src/client/files.rs
+++ b/autonomi/src/client/files.rs
@@ -14,6 +14,23 @@ pub struct Root {
     pub map: HashMap<PathBuf, FilePointer>,
 }
 
+impl Root {
+    /// Deserialize from bytes.
+    pub fn from_bytes(data: Bytes) -> Result<Root, rmp_serde::decode::Error> {
+        let root: Root = rmp_serde::from_slice(&data[..])?;
+
+        Ok(root)
+    }
+
+    /// Serialize to bytes.
+    pub fn into_bytes(&self) -> Result<Bytes, rmp_serde::encode::Error> {
+        let root_serialized = rmp_serde::to_vec(&self)?;
+        let root_serialized = Bytes::from(root_serialized);
+
+        Ok(root_serialized)
+    }
+}
+
 /// Structure that describes a file on the network. The actual data is stored in
 /// chunks, to be constructed with the address pointing to the data map.
 ///
@@ -46,13 +63,7 @@ impl Client {
     pub async fn fetch_root(&mut self, address: XorName) -> Result<Root, UploadError> {
         let data = self.get(address).await?;
 
-        Self::deserialize_root(data)
-    }
-
-    pub fn deserialize_root(data: Bytes) -> Result<Root, UploadError> {
-        let root: Root = rmp_serde::from_slice(&data[..]).expect("TODO");
-
-        Ok(root)
+        Ok(Root::from_bytes(data)?)
     }
 
     /// Fetch the file pointed to by the given pointer.
@@ -85,9 +96,9 @@ impl Client {
         }
 
         let root = Root { map };
-        let root_serialized = rmp_serde::to_vec(&root).expect("TODO");
+        let root_serialized = root.into_bytes()?;
 
-        let xor_name = self.put(Bytes::from(root_serialized), wallet).await?;
+        let xor_name = self.put(root_serialized, wallet).await?;
 
         Ok((root, xor_name))
     }
diff --git a/autonomi/src/client/mod.rs b/autonomi/src/client/mod.rs
index 2900ae12b7..e5eb967f03 100644
--- a/autonomi/src/client/mod.rs
+++ b/autonomi/src/client/mod.rs
@@ -9,8 +9,6 @@ pub mod vault;
 
 use std::{collections::HashSet, time::Duration};
 
-#[cfg(feature = "vault")]
-use bls::SecretKey;
 use libp2p::{identity::Keypair, Multiaddr};
 use sn_networking::{multiaddr_is_global, Network, NetworkBuilder, NetworkEvent};
 use sn_protocol::{version::IDENTIFY_PROTOCOL_STR, CLOSE_GROUP_SIZE};
@@ -37,8 +35,6 @@ pub const CONNECT_TIMEOUT_SECS: u64 = 20;
 #[derive(Clone)]
 pub struct Client {
     pub(crate) network: Network,
-    #[cfg(feature = "vault")]
-    pub(crate) vault_secret_key: Option<SecretKey>,
 }
 
 /// Error returned by [`Client::connect`].
@@ -88,11 +84,7 @@ impl Client {
 
         receiver.await.expect("sender should not close")?;
 
-        Ok(Self {
-            network,
-            #[cfg(feature = "vault")]
-            vault_secret_key: None,
-        })
+        Ok(Self { network })
     }
 }
 
diff --git a/autonomi/src/client/vault.rs b/autonomi/src/client/vault.rs
index 527ca2b9b7..afe38c0825 100644
--- a/autonomi/src/client/vault.rs
+++ b/autonomi/src/client/vault.rs
@@ -17,8 +17,6 @@ use tracing::info;
 pub enum VaultError {
     #[error("Could not generate Vault secret key from entropy: {0:?}")]
     Bls(#[from] bls::Error),
-    #[error("No Vault has been defined. Use `client.with_vault_entropy` to define one.")]
-    NoVaultPacketDefined,
     #[error("Scratchpad found at {0:?} was not a valid record.")]
     CouldNotDeserializeVaultScratchPad(ScratchpadAddress),
     #[error("Protocol: {0}")]
@@ -28,37 +26,22 @@ pub enum VaultError {
 }
 
 impl Client {
-    /// Add a vault secret key to the client
-    ///
-    /// The secret key is derived from the supplied entropy bytes.
-    pub fn with_vault_entropy(mut self, bytes: Bytes) -> Result<Self, VaultError> {
-        // simple hash as XORNAME_LEN == SK_LENs
-        let xorname = xor_name::XorName::from_content(&bytes);
-        // before generating the sk from these bytes.
-        self.vault_secret_key = Some(SecretKey::from_bytes(xorname.0)?);
-
-        Ok(self)
-    }
-
     /// Retrieves and returns a decrypted vault if one exists.
-    pub async fn fetch_and_decrypt_vault(&self) -> Result<Option<Bytes>, VaultError> {
-        let Some(vault_secret_key) = self.vault_secret_key.as_ref() else {
-            return Err(VaultError::NoVaultPacketDefined);
-        };
-
-        let pad = self.get_vault_from_network().await?;
+    pub async fn fetch_and_decrypt_vault(
+        &self,
+        secret_key: &SecretKey,
+    ) -> Result<Option<Bytes>, VaultError> {
+        let pad = self.get_vault_from_network(secret_key).await?;
 
-        Ok(pad.decrypt_data(vault_secret_key)?)
+        Ok(pad.decrypt_data(secret_key)?)
     }
 
     /// Gets the vault Scratchpad from a provided client public key
-    async fn get_vault_from_network(&self) -> Result<Scratchpad, VaultError> {
-        // let vault = self.vault.as_ref()?;
-        let Some(vault_secret_key) = self.vault_secret_key.as_ref() else {
-            return Err(VaultError::NoVaultPacketDefined);
-        };
-
-        let client_pk = vault_secret_key.public_key();
+    async fn get_vault_from_network(
+        &self,
+        secret_key: &SecretKey,
+    ) -> Result<Scratchpad, VaultError> {
+        let client_pk = secret_key.public_key();
 
         let scratch_address = ScratchpadAddress::new(client_pk);
         let network_address = NetworkAddress::from_scratchpad_address(scratch_address);
@@ -85,23 +68,17 @@ impl Client {
 
     /// Put data into the client's VaultPacket
     ///
-    /// Returns Ok(None) early if no vault packet is defined.
-    ///
     /// Pays for a new VaultPacket if none yet created for the client. Returns the current version
     /// of the data on success.
-    pub async fn write_bytes_to_vault_if_defined(
+    pub async fn write_bytes_to_vault(
         &mut self,
         data: Bytes,
         wallet: &mut Wallet,
-    ) -> Result<Option<u64>, PutError> {
-        // Exit early if no vault packet defined
-        let Some(client_sk) = self.vault_secret_key.as_ref() else {
-            return Ok(None);
-        };
-
-        let client_pk = client_sk.public_key();
+        secret_key: &SecretKey,
+    ) -> Result<u64, PutError> {
+        let client_pk = secret_key.public_key();
 
-        let pad_res = self.get_vault_from_network().await;
+        let pad_res = self.get_vault_from_network(secret_key).await;
         let mut is_new = true;
 
         let mut scratch = if let Ok(existing_data) = pad_res {
@@ -119,7 +96,7 @@ impl Client {
             Scratchpad::new(client_pk)
         };
 
-        let next_count = scratch.update_and_sign(data, client_sk);
+        let next_count = scratch.update_and_sign(data, secret_key);
         let scratch_address = scratch.network_address();
         let scratch_key = scratch_address.to_record_key();
 
@@ -172,6 +149,6 @@ impl Client {
 
         self.network.put_record(record, &put_cfg).await?;
 
-        Ok(Some(next_count))
+        Ok(next_count)
     }
 }
diff --git a/autonomi/tests/file.rs b/autonomi/tests/file.rs
index 952f859631..0ecb19d292 100644
--- a/autonomi/tests/file.rs
+++ b/autonomi/tests/file.rs
@@ -2,10 +2,6 @@ mod common;
 
 use crate::common::{evm_network_from_env, evm_wallet_from_env_or_default};
 use autonomi::Client;
-#[cfg(feature = "vault")]
-use bytes::Bytes;
-#[cfg(feature = "vault")]
-use eyre::bail;
 use std::time::Duration;
 use tokio::time::sleep;
 
@@ -18,9 +14,6 @@ async fn file() -> Result<(), Box<dyn std::error::Error>> {
     let mut client = Client::connect(&[]).await.unwrap();
     let wallet = evm_wallet_from_env_or_default(network);
 
-    // let data = common::gen_random_data(1024 * 1024 * 1000);
-    // let user_key = common::gen_random_data(32);
-
     let (root, addr) = client
         .upload_from_dir("tests/file/test_dir".into(), &wallet)
         .await?;
@@ -44,11 +37,9 @@ async fn file_into_vault() -> eyre::Result<()> {
 
     let network = evm_network_from_env();
 
-    let mut client = Client::connect(&[])
-        .await?
-        .with_vault_entropy(Bytes::from("at least 32 bytes of entropy here"))?;
-
-    let wallet = evm_wallet_from_env_or_default(network);
+    let mut client = Client::connect(&[]).await?;
+    let mut wallet = evm_wallet_from_env_or_default(network);
+    let client_sk = bls::SecretKey::random();
 
     let (root, addr) = client
         .upload_from_dir("tests/file/test_dir".into(), &wallet)
@@ -56,6 +47,9 @@ async fn file_into_vault() -> eyre::Result<()> {
     sleep(Duration::from_secs(2)).await;
 
     let root_fetched = client.fetch_root(addr).await?;
+    client
+        .write_bytes_to_vault(root.into_bytes()?, &mut wallet, &client_sk)
+        .await?;
 
     assert_eq!(
         root.map, root_fetched.map,
@@ -63,19 +57,17 @@ async fn file_into_vault() -> eyre::Result<()> {
     );
 
     // now assert over the stored account packet
-    let new_client = Client::connect(&[])
-        .await?
-        .with_vault_entropy(Bytes::from("at least 32 bytes of entropy here"))?;
+    let new_client = Client::connect(&[]).await?;
 
-    if let Some(ap) = new_client.fetch_and_decrypt_vault().await? {
-        let ap_root_fetched = Client::deserialize_root(ap)?;
+    if let Some(ap) = new_client.fetch_and_decrypt_vault(&client_sk).await? {
+        let ap_root_fetched = autonomi::client::files::Root::from_bytes(ap)?;
 
         assert_eq!(
             root.map, ap_root_fetched.map,
             "root fetched should match root put"
         );
     } else {
-        bail!("No account packet found");
+        eyre::bail!("No account packet found");
     }
 
     Ok(())