From f7b0acaaacf06353aae0232ed0cf814dd229d361 Mon Sep 17 00:00:00 2001 From: ehsan shariati Date: Tue, 13 Dec 2022 14:38:20 -0500 Subject: [PATCH 1/6] Added suport for external wnfs_key --- .../androidTest/java/land/fx/app/WNFSTest.kt | 14 +++ dep/wnfs/src/private/privateref.rs | 6 +- dep/wnfsutils/Cargo.toml | 3 +- dep/wnfsutils/src/private_forest.rs | 87 +++++++++++++++++-- lib/src/main/java/land/fx/wnfslib/Fs.java | 12 ++- wnfslib/src/lib.rs | 21 ++++- 6 files changed, 126 insertions(+), 17 deletions(-) diff --git a/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt b/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt index b57e0b2..9271428 100644 --- a/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt +++ b/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt @@ -126,5 +126,19 @@ class WNFSTest { assert(content contentEquals "Hello, World!".toByteArray()) Log.d("AppMock", "readFile. content="+content.toString()) + Log.d("AppMock", "All tests before reload passed") + + Log.d("AppMock", "wnfs12 Testing reload with cid="+config.cid+" & wnfsKey="+wnfsKey.toString()) + //Testing reload Directory + var private_ref_reload: String = getPrivateRef(client, wnfsKey) + Log.d("AppMock", "wnfs12 original PrivateRef. private_ref="+config.private_ref) + Log.d("AppMock", "wnfs12 getPrivateRef. private_ref="+private_ref_reload) + assertNotNull("private_ref should not be null", private_ref_reload) + assert(private_ref_reload.toByteArray() contentEquals config.private_ref.toByteArray()) + + val content_reloaded = readFile(client, config.cid, private_ref_reload, "root/test.txt") + assert(content_reloaded contentEquals "Hello, World!".toByteArray()) + Log.d("AppMock", "readFile. content_reloaded="+content_reloaded.toString()) + } } diff --git a/dep/wnfs/src/private/privateref.rs b/dep/wnfs/src/private/privateref.rs index b1f6a3f..2336e76 100644 --- a/dep/wnfs/src/private/privateref.rs +++ b/dep/wnfs/src/private/privateref.rs @@ -12,11 +12,11 @@ use serde::{de::Error as DeError, ser::Error as SerError, Deserialize, Serialize #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct PrivateRef { /// Sha3-256 hash of saturated namefilter. - pub(crate) saturated_name_hash: HashOutput, + pub saturated_name_hash: HashOutput, /// Sha3-256 hash of the ratchet key. - pub(crate) content_key: ContentKey, + pub content_key: ContentKey, /// Skip-ratchet-derived key. - pub(crate) revision_key: RevisionKey, + pub revision_key: RevisionKey, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/dep/wnfsutils/Cargo.toml b/dep/wnfsutils/Cargo.toml index bf03845..56bc9b9 100644 --- a/dep/wnfsutils/Cargo.toml +++ b/dep/wnfsutils/Cargo.toml @@ -19,4 +19,5 @@ serde = "1.0.149" serde_json = "1.0.89" anyhow = "1.0.66" async-trait = "0.1.58" -log = "0.4.14" \ No newline at end of file +log = "0.4.14" +sha3 = "0.10" \ No newline at end of file diff --git a/dep/wnfsutils/src/private_forest.rs b/dep/wnfsutils/src/private_forest.rs index 655d041..e7e7a38 100644 --- a/dep/wnfsutils/src/private_forest.rs +++ b/dep/wnfsutils/src/private_forest.rs @@ -10,12 +10,13 @@ use std::{ io::{Read, Write} }; use wnfs::{ - dagcbor, - private::{PrivateForest, PrivateRef}, + dagcbor, Hasher, utils, + private::{PrivateForest, PrivateRef, PrivateNode, Key}, BlockStore, Namefilter, PrivateDirectory, PrivateOpResult, Metadata, }; use anyhow::Result; use log::{trace, Level}; +use sha3::Sha3_256; use crate::blockstore::FFIFriendlyBlockStore; @@ -70,6 +71,9 @@ impl<'a> PrivateDirectoryHelper<'a> { } pub async fn get_root_dir(&mut self, forest: Rc, private_ref: PrivateRef) -> Result> { + //trace!("\r\n wnfs13 revision_key = {:?}", private_ref.revision_key.0.as_bytes()); + //trace!("\r\n wnfs13 saturated_name_hash = {:?}", private_ref.saturated_name_hash); + //trace!("\r\n wnfs13 content_key = {:?}", private_ref.content_key.0.as_bytes()); // Fetch and decrypt root directory from the private forest using provided private ref. forest .get(&private_ref, PrivateForest::resolve_lowest, &mut self.store) @@ -77,20 +81,77 @@ impl<'a> PrivateDirectoryHelper<'a> { .unwrap().unwrap().as_dir() } - pub async fn init(&mut self, forest: Rc) -> (Cid, PrivateRef) { + pub async fn get_private_ref(&mut self, wnfs_key: Vec) -> PrivateRef { + let ratchet_seed: [u8; 32] = Sha3_256::hash(&wnfs_key); + let inumber: [u8; 32] = Sha3_256::hash(&ratchet_seed); + let private_ref = PrivateRef::with_seed(Namefilter::default(), ratchet_seed, inumber); + trace!("\r\n wnfs13 get_private_ref.content_key {:?}", private_ref.content_key.0.as_bytes()); + trace!("\r\n wnfs13 get_private_ref.saturated_name_hash {:?}", private_ref.saturated_name_hash); + trace!("\r\n wnfs13 get_private_ref.revision_key {:?}", private_ref.revision_key.0.as_bytes()); + + private_ref + + } + + pub async fn init(&mut self, forest: Rc, wnfs_key: Vec) -> (Cid, PrivateRef) { + let ratchet_seed: [u8; 32]; + let inumber: [u8; 32]; + if wnfs_key.is_empty() { + let wnfs_random_key = Key::new(utils::get_random_bytes::<32>(&mut self.rng)); + ratchet_seed = Sha3_256::hash(&wnfs_random_key.as_bytes()); + inumber = utils::get_random_bytes::<32>(&mut self.rng); // Needs to be random + }else { + ratchet_seed = Sha3_256::hash(&wnfs_key); + inumber = Sha3_256::hash(&ratchet_seed); + } + // Create a new directory. - let dir = Rc::new(PrivateDirectory::new( + /*let dir = Rc::new(PrivateDirectory::with_seed( + Namefilter::default(), + Utc::now(), + ratchet_seed, + inumber + ));*/ + let dir = PrivateNode::from(PrivateDirectory::with_seed( Namefilter::default(), Utc::now(), - &mut self.rng, + ratchet_seed, + inumber, )); + let header = dir.get_header(); + + trace!("\r\n wnfs13 header revision_key = {:?}", header.get_private_ref().revision_key.0.as_bytes()); + trace!("\r\n wnfs13 header saturated_name_hash = {:?}", header.get_private_ref().saturated_name_hash); + trace!("\r\n wnfs13 header content_key = {:?}", header.get_private_ref().content_key.0.as_bytes()); + + let forest = forest + .put( + header.get_saturated_name(), + &header.get_private_ref(), + &dir, + &mut self.store, + &mut self.rng, + ) + .await + .unwrap(); + + trace!("\r\n wnfs13 init1 revision_key = {:?}", dir.as_dir().unwrap().header.get_private_ref().revision_key.0.as_bytes()); + trace!("\r\n wnfs13 init1 saturated_name_hash = {:?}", dir.as_dir().unwrap().header.get_private_ref().saturated_name_hash); + trace!("\r\n wnfs13 init1 content_key = {:?}", dir.as_dir().unwrap().header.get_private_ref().content_key.0.as_bytes()); let PrivateOpResult { root_dir, forest, .. } = dir + .as_dir() + .unwrap() .mkdir(&["root".into()], true, Utc::now(), forest, &mut self.store,&mut self.rng) .await .unwrap(); + let init_private_ref = root_dir.header.get_private_ref(); - (self.update_forest(forest).await.unwrap(), root_dir.header.get_private_ref()) + trace!("\r\n wnfs13 init2 revision_key = {:?}", init_private_ref.revision_key.0.as_bytes()); + trace!("\r\n wnfs13 init2 saturated_name_hash = {:?}", init_private_ref.saturated_name_hash); + trace!("\r\n wnfs13 init2 content_key = {:?}", init_private_ref.content_key.0.as_bytes()); + + (self.update_forest(forest).await.unwrap(), init_private_ref) } fn get_file_as_byte_vec(&mut self, filename: &String) -> Vec { @@ -199,6 +260,13 @@ impl<'a> PrivateDirectoryHelper<'a> { return runtime.block_on(self.load_forest(forest_cid)); } + pub fn synced_get_private_ref(&mut self, wnfs_key: Vec) -> PrivateRef + { + let runtime = + tokio::runtime::Runtime::new().expect("Unable to create a runtime"); + return runtime.block_on(self.get_private_ref(wnfs_key)); + } + pub fn synced_get_root_dir(&mut self, forest: Rc, private_ref: PrivateRef) -> Result, anyhow::Error> { @@ -207,11 +275,11 @@ impl<'a> PrivateDirectoryHelper<'a> { return runtime.block_on(self.get_root_dir(forest, private_ref)); } - pub fn synced_init(&mut self, forest: Rc) -> (Cid, PrivateRef) + pub fn synced_init(&mut self, forest: Rc, wnfs_key: Vec) -> (Cid, PrivateRef) { let runtime = tokio::runtime::Runtime::new().expect("Unable to create a runtime"); - return runtime.block_on(self.init(forest)); + return runtime.block_on(self.init(forest, wnfs_key)); } pub fn synced_write_file_from_path(&mut self, forest: Rc, root_dir: Rc, path_segments: &[String], filename: &String) -> (Cid, PrivateRef) @@ -288,13 +356,14 @@ mod private_tests { #[async_std::test] async fn iboverall() { + let empty_key: Vec = vec![0; 32]; let store = KVBlockStore::new(String::from("./tmp/test2"), IpldCodec::DagCbor); let blockstore = FFIFriendlyBlockStore::new(Box::new(store)); let helper = &mut PrivateDirectoryHelper::new(blockstore); let forest_cid = helper.create_private_forest().await.unwrap(); println!("cid: {:?}", forest_cid); let forest = helper.load_forest(forest_cid).await.unwrap(); - let (forest_cid, private_ref) = helper.init(forest).await; + let (forest_cid, private_ref) = helper.init(forest, empty_key).await; let forest = helper.load_forest(forest_cid).await.unwrap(); let root_dir = helper.get_root_dir(forest.to_owned(), private_ref.to_owned()).await.unwrap(); let (new_cid, _) = helper.write_file(forest.to_owned(), root_dir.to_owned(), &["root".into(), "hello".into(), "world.txt".into()], b"hello, world!".to_vec()).await; diff --git a/lib/src/main/java/land/fx/wnfslib/Fs.java b/lib/src/main/java/land/fx/wnfslib/Fs.java index 1ef97f5..d9bbdc6 100644 --- a/lib/src/main/java/land/fx/wnfslib/Fs.java +++ b/lib/src/main/java/land/fx/wnfslib/Fs.java @@ -6,7 +6,9 @@ public final class Fs { private static native String createPrivateForestNative(Datastore datastore); - private static native Config createRootDirNative(Datastore datastore, String cid); + private static native String getPrivateRefNative(Datastore datastore, byte[] wnfsKey); + + private static native Config createRootDirNative(Datastore datastore, String cid, byte[] wnfsKey); private static native Config writeFileFromPathNative(Datastore datastore, String cid, String privateRef, String path, String filename); @@ -26,8 +28,12 @@ public static String createPrivateForest(Datastore datastore) { return createPrivateForestNative(datastore); } - public static Config createRootDir(Datastore datastore, String cid) { - return createRootDirNative(datastore, cid); + public static String getPrivateRef(Datastore datastore, byte[] wnfsKey) { + return getPrivateRefNative(datastore, wnfsKey); + } + + public static Config createRootDir(Datastore datastore, String cid, byte[] wnfsKey) { + return createRootDirNative(datastore, cid, wnfsKey); } public static Config writeFileFromPath(Datastore datastore, String cid, String privateRef, String path, String filename) { diff --git a/wnfslib/src/lib.rs b/wnfslib/src/lib.rs index d243dfc..b1c3037 100644 --- a/wnfslib/src/lib.rs +++ b/wnfslib/src/lib.rs @@ -126,12 +126,30 @@ pub mod android { serialize_cid(env, helper.synced_create_private_forest().unwrap()).into_inner() } + #[no_mangle] + pub extern "C" fn Java_land_fx_wnfslib_Fs_getPrivateRefNative( + env: JNIEnv, + _: JClass, + jni_fula_client: JObject, + jni_wnfs_key: jbyteArray, + ) -> jstring { + trace!("**********************getPrivateRefNative started**************"); + let store = JNIStore::new(env, jni_fula_client); + let block_store = FFIFriendlyBlockStore::new(Box::new(store)); + let helper = &mut PrivateDirectoryHelper::new(block_store); + let wnfs_key: Vec = jbyte_array_to_vec(env, jni_wnfs_key); + let private_ref = helper.synced_get_private_ref(wnfs_key); + trace!("**********************getPrivateRefNative finished**************"); + serialize_private_ref(env, private_ref).into_inner() + } + #[no_mangle] pub extern "C" fn Java_land_fx_wnfslib_Fs_createRootDirNative( env: JNIEnv, _: JClass, jni_fula_client: JObject, jni_cid: JString, + jni_wnfs_key: jbyteArray, ) -> jobject { trace!("**********************createRootDirNative started**************"); let store = JNIStore::new(env, jni_fula_client); @@ -140,7 +158,8 @@ pub mod android { let forest_cid = deserialize_cid(env, jni_cid); trace!("cid: {}", forest_cid); let forest = helper.synced_load_forest(forest_cid).unwrap(); - let (cid, private_ref) = helper.synced_init(forest); + let wnfs_key: Vec = jbyte_array_to_vec(env, jni_wnfs_key); + let (cid, private_ref) = helper.synced_init(forest, wnfs_key); trace!("pref: {:?}", private_ref); trace!("**********************createRootDirNative finished**************"); serialize_config(env, cid, private_ref) From f3fcb547a05e22f48033a1aaa1cbd95717095960 Mon Sep 17 00:00:00 2001 From: ehsan shariati Date: Tue, 13 Dec 2022 14:40:40 -0500 Subject: [PATCH 2/6] Update WNFSTest.kt --- appmock/src/androidTest/java/land/fx/app/WNFSTest.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt b/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt index 9271428..d32d18b 100644 --- a/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt +++ b/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt @@ -12,6 +12,8 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import java.io.File +import java.nio.charset.StandardCharsets +import java.security.MessageDigest @RunWith(AndroidJUnit4::class) @@ -48,6 +50,10 @@ class WNFSTest { val fulaClient = Fulamobile.newClient(configExt) val client = ConvertFulaClient(fulaClient) Log.d("AppMock", "client created with id="+fulaClient.id()) + + val keyPhrase = ("test").toByteArray(StandardCharsets.UTF_8) + val digest: MessageDigest = MessageDigest.getInstance("SHA-256"); + val wnfsKey: ByteArray = digest.digest(keyPhrase); /* val sampleData = arrayOf(36, 212, 208, 119, 240, 231, 139, 103, 180, 43, 238, 192, 90, 25, 53, 111, 134, 254, 216, 237, 50, 10, 16, 85, 157, 154, 111, 204, 182, 200, 71, 44, 39, 18, 115, 1, 24, 175, 92, 3, 132, 226, 156, 7, 131, 220, 159, 77, 240, 190, 224, 11, 55, 203, 198, 194, 76, 39, 150, 181, 23, 232, 32, 23, 249, 162, 213, 93, 225, 191, 100, 168, 161, 234, 48, 232, 219, 38, 31, 230, 114, 53, 35, 10, 222, 212, 16, 92, 83, 157, 235, 202, 189, 48, 192, 165, 58, 70, 32, 142, 227, 151, 23, 175, 124, 41, 127, 145, 31, 167, 182, 205, 132, 151, 129, 58, 65, 136, 26, 32, 35, 221, 75, 76, 165, 128, 82, 219, 155, 216, 167, 219, 253, 155, 46, 130, 88, 44, 7, 143, 32, 111, 191, 238, 87, 40, 146, 46, 247, 135, 181, 29, 13, 38, 183, 251, 99, 190, 100, 234, 182, 121, 109, 253, 45, 54, 250, 94, 251, 158, 158, 144, 198, 253, 37, 111, 22, 87, 6, 166, 119, 123, 89, 230, 64, 90, 244, 205, 249, 168, 110, 51, 118, 60, 226, 102, 120, 129, 65, 3, 170, 172, 45, 119, 120, 62, 111, 55, 21, 91, 86, 53, 184, 253, 59, 41, 0, 90, 145, 41, 230, 109, 108, 46, 118, 225, 176, 221, 98, 221, 53, 92, 119, 254, 57, 163, 120, 179, 160, 74, 203, 104, 35, 188, 96, 153, 178, 122, 214, 30, 254, 19, 6, 33, 183, 14, 223, 7, 161, 171, 245, 21, 214, 1, 60, 79, 54, 202, 67, 145, 12, 240, 60, 210, 115, 217, 171, 175, 135, 33, 24, 138, 181, 63, 44, 4, 105, 76, 54, 230, 217, 81, 141, 209, 196, 129, 236, 18, 155, 246, 6, 138, 239, 8, 170, 10, 50, 233, 104, 50, 233, 58, 140, 16, 16, 213, 238, 95, 239, 227, 2, 108, 0, 215, 14, 84, 86, 82, 241, 50, 174, 1, 72, 132, 150, 3, 56, 177, 156, 254, 189, 7, 177, 2, 207, 107, 243, 234, 64, 42, 74, 245, 230, 240, 116, 193, 222, 29, 187, 239, 240, 185, 49, 27, 132, 169, 121, 86, 186, 10, 226, 150, 237, 154, 75, 173, 198, 20, 213, 215, 11, 29, 251, 140, 81, 249, 225, 148, 169, 197, 201, 180, 206, 252, 219, 130, 224, 152, 60, 252, 121, 236, 214, 107, 15, 172, 104, 17, 64, 99, 57, 253, 251, 114, 64, 196, 184, 36, 181, 208, 181, 80, 19, 143, 75, 250, 0, 55, 211, 135, 59, 126, 151, 11, 149, 59, 8, 248, 156, 45, 244, 62, 26, 53, 136, 197, 203, 99, 122, 225, 67, 116, 165, 254, 172, 29, 170, 116, 59, 214, 47, 213, 45, 60, 226, 209, 229, 98, 4, 37, 33, 156, 140, 243, 176, 23, 31, 149, 102, 89, 118, 126, 6, 66, 185, 188, 187, 241, 183, 187, 234, 132, 137, 28, 30, 1, 104, 151, 64, 238, 220, 139, 144, 22, 87, 215, 13, 90, 156, 79, 71, 39, 41, 123, 114, 128, 5, 223, 97, 14, 47, 3, 178, 15, 102, 52, 98, 127, 226, 163, 70, 237, 241, 83, 90, 172, 178, 66, 241, 123, 213, 104, 242, 47, 47, 2, 198, 194, 150, 123, 181, 86, 50, 86, 190, 48, 15, 60, 188, 77, 135, 1, 118, 134, 47, 230, 103, 16, 230, 120, 255, 85, 86, 101, 236, 35, 127, 147, 234, 226, 93, 174, 200, 185, 45, 36, 117, 13, 253, 151, 232, 80, 106, 5, 46, 167, 123, 234, 218, 182, 66, 183, 0, 120, 107, 251, 116, 80, 79, 212, 142, 160, 8, 217, 149, 161, 238, 219, 141, 127, 87, 180, 192, 40, 154, 31, 164, 184, 117, 158, 167, 210, 119, 219, 238, 166, 234, 84, 239, 128, 143, 140, 171, 171, 181, 108, 96, 215, 125, 161, 92, 179, 48, 222, 115, 25, 29, 27, 68, 240, 139, 149, 10, 215, 14, 185, 219, 10, 236, 112, 128, 68, 226, 17, 45, 100, 135, 232, 222, 36, 193, 233, 4, 51, 222, 61, 103, 108, 229, 177, 177, 205, 86, 82, 95, 185, 248, 115, 1, 215, 197, 123, 9, 155, 152, 37, 233, 212, 150, 163, 33, 188, 4, 99, 84, 45, 5, 199, 65, 188, 226, 87, 165, 35, 108, 180, 135, 159, 55, 242, 22, 21, 234, 194, 225, 246, 193, 218, 246, 2, 224, 2, 103, 50, 121, 105, 113, 159, 5, 238, 40, 223, 184, 61, 79, 215, 118, 216, 154, 112, 39, 27, 56, 233, 80, 218, 40, 204, 213, 14, 171, 220, 12, 62, 142, 213, 118, 23, 102, 122, 148, 194, 168, 62, 183, 250, 232, 134, 84, 49, 149, 102, 141, 144, 42, 134, 211, 44, 185, 136, 186, 172, 146, 215, 197, 76, 125, 172, 114, 115, 126, 42, 66, 1, 224, 222, 59, 49, 58, 22, 49, 132, 27, 1, 79, 158, 82, 20, 57, 120, 130, 114, 55, 141, 237, 39, 249, 6, 161, 98, 14, 151, 149, 243, 150, 179, 238, 232, 207, 214, 98, 179, 114, 22, 130, 72, 229, 17, 180, 156, 211, 211, 190, 244, 10, 20, 182, 30, 87, 18, 164, 101, 102, 28, 31, 236, 142, 239, 183, 25, 234, 166, 8, 230, 42, 94, 239, 73, 138, 186, 28, 88, 111, 233, 105, 66, 176, 88, 245, 249, 156, 41, 226, 44, 24, 114, 244, 193, 25, 182, 38, 155, 28, 24, 237, 62, 251, 254, 153, 2, 31, 244, 206, 230, 83, 122, 13, 77, 140, 27, 200, 247, 19, 24, 241, 169, 44, 252, 64, 106, 139, 131, 208, 42, 129, 249, 179, 134, 244, 225, 107, 219, 68, 126, 105, 179, 242, 140, 198, 77, 2, 255, 163, 222, 190, 2, 198, 200, 130, 245, 125, 238, 226, 149, 130, 106, 109, 176, 145, 18, 233, 156, 148, 174, 251, 224, 181, 68, 34, 94, 243, 1, 150, 98, 96, 63, 157, 128, 49, 230, 250, 97, 131, 48, 74, 125, 228, 88, 4, 213, 127, 201, 60, 17, 41, 246, 140, 35, 11, 172, 36, 118, 238, 162, 17, 22, 189, 188, 102, 83, 67, 242, 215, 78, 231, 232, 246, 202, 52, 49, 87, 119, 28, 14, 225, 28, 86, 45, 73, 190, 128, 196, 255, 106, 196, 63, 107, 122, 7, 14, 254, 7, 255, 245, 71, 193, 241, 138, 93, 74, 177, 165, 25, 8, 67, 3, 45, 113, 182, 203, 89, 179, 173, 156, 156, 248, 64, 233, 194, 67, 214, 62, 211, 236, 90, 183, 203, 183, 2, 95, 172, 84, 143, 26, 223, 48, 208, 151, 152, 110, 132, 88, 246, 62, 118, 95, 116, 116, 6, 228, 92, 6, 199, 70, 202, 147, 160, 177, 33, 30, 227, 107, 78, 45, 44, 99, 172, 69, 182, 189, 173, 160, 25, 98, 62, 177, 73, 83, 140, 196, 9, 174, 197, 71, 235, 128, 60, 148, 175, 30, 162, 180, 44, 165, 247, 65, 87, 169, 71, 178, 237, 25, 72, 191, 239, 222, 128, 184, 32, 214, 160, 95, 96, 85, 58, 110, 118, 179, 133, 110, 134, 29, 111, 199, 220, 90, 12, 83, 9, 12, 106, 124, 51, 149, 172, 146, 145, 32, 244, 15, 53, 218, 6, 117, 38, 4, 186, 43, 235, 202, 162, 134, 62, 44, 14, 31, 8, 49, 101, 169, 32, 101, 242, 58, 38, 34, 250, 65, 211, 46, 235, 12, 143, 76, 245, 89, 69, 193, 210, 99, 30, 57, 43, 227, 154, 248, 108, 187, 152, 7, 91, 122, 148, 211, 182, 147, 162, 117, 66, 126, 108, 144, 229, 101, 224, 188, 45, 174, 48, 21, 224, 10, 0, 36, 98, 243, 214, 186, 101, 71, 53, 46, 106, 95, 157, 179, 77, 192, 20, 74, 159, 223, 158, 185, 23) From 34a9371859d055b1fabdf99dcadd7e3a98928f9e Mon Sep 17 00:00:00 2001 From: ehsan shariati Date: Tue, 13 Dec 2022 14:41:25 -0500 Subject: [PATCH 3/6] Update WNFSTest.kt --- appmock/src/androidTest/java/land/fx/app/WNFSTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt b/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt index d32d18b..11909e1 100644 --- a/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt +++ b/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt @@ -75,7 +75,7 @@ class WNFSTest { println(privateForest) - var config = createRootDir(client, privateForest) + var config = createRootDir(client, privateForest, wnfsKey) Log.d("AppMock", "config crecreateRootDirated. cid="+config.cid+" & private_ref="+config.private_ref) assertNotNull("cid should not be null", config.cid) assertNotNull("private_ref should not be null", config.private_ref) From c9cd20a2103685baa923fe94ea26375eb90fc988 Mon Sep 17 00:00:00 2001 From: ehsan shariati Date: Tue, 13 Dec 2022 18:54:10 -0500 Subject: [PATCH 4/6] Corrected the issue with updating forest --- .../androidTest/java/land/fx/app/WNFSTest.kt | 10 ++-- dep/wnfsutils/src/private_forest.rs | 54 ++++++++++--------- 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt b/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt index 11909e1..4876036 100644 --- a/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt +++ b/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt @@ -140,11 +140,11 @@ class WNFSTest { Log.d("AppMock", "wnfs12 original PrivateRef. private_ref="+config.private_ref) Log.d("AppMock", "wnfs12 getPrivateRef. private_ref="+private_ref_reload) assertNotNull("private_ref should not be null", private_ref_reload) - assert(private_ref_reload.toByteArray() contentEquals config.private_ref.toByteArray()) - - val content_reloaded = readFile(client, config.cid, private_ref_reload, "root/test.txt") - assert(content_reloaded contentEquals "Hello, World!".toByteArray()) - Log.d("AppMock", "readFile. content_reloaded="+content_reloaded.toString()) +/* + val fileNames_reloaded = ls(client, config.cid, private_ref_reload, "root") + Log.d("AppMock", "ls. fileNames_reloaded="+fileNames_reloaded) + assertEquals(fileNames_reloaded, "test.txt\ntest1")*/ + } } diff --git a/dep/wnfsutils/src/private_forest.rs b/dep/wnfsutils/src/private_forest.rs index e7e7a38..e80dfd6 100644 --- a/dep/wnfsutils/src/private_forest.rs +++ b/dep/wnfsutils/src/private_forest.rs @@ -78,7 +78,9 @@ impl<'a> PrivateDirectoryHelper<'a> { forest .get(&private_ref, PrivateForest::resolve_lowest, &mut self.store) .await - .unwrap().unwrap().as_dir() + .unwrap() + .unwrap() + .as_dir() } pub async fn get_private_ref(&mut self, wnfs_key: Vec) -> PrivateRef { @@ -112,34 +114,35 @@ impl<'a> PrivateDirectoryHelper<'a> { ratchet_seed, inumber ));*/ - let dir = PrivateNode::from(PrivateDirectory::with_seed( - Namefilter::default(), - Utc::now(), - ratchet_seed, - inumber, + let root_dir = Rc::new(PrivateDirectory::with_seed( + Namefilter::default(), + Utc::now(), + ratchet_seed, + inumber, )); - let header = dir.get_header(); - trace!("\r\n wnfs13 header revision_key = {:?}", header.get_private_ref().revision_key.0.as_bytes()); - trace!("\r\n wnfs13 header saturated_name_hash = {:?}", header.get_private_ref().saturated_name_hash); - trace!("\r\n wnfs13 header content_key = {:?}", header.get_private_ref().content_key.0.as_bytes()); - - let forest = forest - .put( - header.get_saturated_name(), - &header.get_private_ref(), - &dir, - &mut self.store, - &mut self.rng, - ) + let private_ref = root_dir.header.get_private_ref(); + let name = root_dir.header.get_saturated_name(); + + let forest = forest + .put( + name, + &private_ref, + &PrivateNode::Dir(Rc::clone(&root_dir)), + &mut self.store, + &mut self.rng, + ) .await .unwrap(); + + let init_private_ref = root_dir.header.get_private_ref(); - trace!("\r\n wnfs13 init1 revision_key = {:?}", dir.as_dir().unwrap().header.get_private_ref().revision_key.0.as_bytes()); - trace!("\r\n wnfs13 init1 saturated_name_hash = {:?}", dir.as_dir().unwrap().header.get_private_ref().saturated_name_hash); - trace!("\r\n wnfs13 init1 content_key = {:?}", dir.as_dir().unwrap().header.get_private_ref().content_key.0.as_bytes()); - - let PrivateOpResult { root_dir, forest, .. } = dir + trace!("\r\n wnfs13 header revision_key = {:?}", init_private_ref.revision_key.0.as_bytes()); + trace!("\r\n wnfs13 header saturated_name_hash = {:?}", init_private_ref.saturated_name_hash); + trace!("\r\n wnfs13 header content_key = {:?}", init_private_ref.content_key.0.as_bytes()); + (self.update_forest(forest).await.unwrap(), init_private_ref) + + /*let PrivateOpResult { root_dir, forest, .. } = dir .as_dir() .unwrap() .mkdir(&["root".into()], true, Utc::now(), forest, &mut self.store,&mut self.rng) @@ -151,7 +154,7 @@ impl<'a> PrivateDirectoryHelper<'a> { trace!("\r\n wnfs13 init2 saturated_name_hash = {:?}", init_private_ref.saturated_name_hash); trace!("\r\n wnfs13 init2 content_key = {:?}", init_private_ref.content_key.0.as_bytes()); - (self.update_forest(forest).await.unwrap(), init_private_ref) + (self.update_forest(forest).await.unwrap(), init_private_ref)*/ } fn get_file_as_byte_vec(&mut self, filename: &String) -> Vec { @@ -235,6 +238,7 @@ impl<'a> PrivateDirectoryHelper<'a> { } pub async fn ls_files(&mut self, forest: Rc, root_dir: Rc, path_segments: &[String]) -> Vec<(String, Metadata)> { + let PrivateOpResult { result, .. } = root_dir .ls(path_segments, true, forest, &mut self.store) .await From 9f077543e8214f231383e83aa3c357371f3de557 Mon Sep 17 00:00:00 2001 From: ehsan shariati Date: Tue, 13 Dec 2022 20:39:30 -0500 Subject: [PATCH 5/6] Updated WNFS to support fetching last root based on private_Ref --- .../androidTest/java/land/fx/app/WNFSTest.kt | 6 +- dep/wnfs/src/private/directory.rs | 92 ++++++++++++++++++- dep/wnfs/src/private/privateref.rs | 6 +- dep/wnfsutils/src/private_forest.rs | 51 ++++++++-- jitpack.yml | 2 +- lib/src/main/java/land/fx/wnfslib/Fs.java | 6 +- pom.xml | 2 +- wnfslib/src/lib.rs | 4 +- 8 files changed, 146 insertions(+), 23 deletions(-) diff --git a/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt b/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt index 4876036..778d172 100644 --- a/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt +++ b/appmock/src/androidTest/java/land/fx/app/WNFSTest.kt @@ -136,14 +136,14 @@ class WNFSTest { Log.d("AppMock", "wnfs12 Testing reload with cid="+config.cid+" & wnfsKey="+wnfsKey.toString()) //Testing reload Directory - var private_ref_reload: String = getPrivateRef(client, wnfsKey) + var private_ref_reload: String = getPrivateRef(client, wnfsKey, config.cid) Log.d("AppMock", "wnfs12 original PrivateRef. private_ref="+config.private_ref) Log.d("AppMock", "wnfs12 getPrivateRef. private_ref="+private_ref_reload) assertNotNull("private_ref should not be null", private_ref_reload) -/* + val fileNames_reloaded = ls(client, config.cid, private_ref_reload, "root") Log.d("AppMock", "ls. fileNames_reloaded="+fileNames_reloaded) - assertEquals(fileNames_reloaded, "test.txt\ntest1")*/ + assertEquals(fileNames_reloaded, "test.txt\ntest1") } diff --git a/dep/wnfs/src/private/directory.rs b/dep/wnfs/src/private/directory.rs index 64b908d..d1ceeb2 100644 --- a/dep/wnfs/src/private/directory.rs +++ b/dep/wnfs/src/private/directory.rs @@ -134,6 +134,70 @@ impl PrivateDirectory { } } + pub async fn with_store( + parent_bare_name: Namefilter, + time: DateTime, + forest: Rc, + store: &mut B, + rng: &mut R, + ) -> Result> { + let dir = Rc::new(Self { + version: Version::new(0, 2, 0), + header: PrivateNodeHeader::new(parent_bare_name, rng), + metadata: Metadata::new(time), + entries: BTreeMap::new(), + }); + + let forest = forest + .put( + dir.header.get_saturated_name(), + &dir.header.get_private_ref(), + &PrivateNode::Dir(Rc::clone(&dir)), + store, + rng, + ) + .await?; + + Ok(PrivateOpResult { + root_dir: dir, + forest, + result: (), + }) + } + + pub async fn with_seed_and_store( + parent_bare_name: Namefilter, + time: DateTime, + ratchet_seed: HashOutput, + inumber: HashOutput, + forest: Rc, + store: &mut B, + rng: &mut R, + ) -> Result> { + let dir = Rc::new(Self { + version: Version::new(0, 2, 0), + header: PrivateNodeHeader::with_seed(parent_bare_name, ratchet_seed, inumber), + metadata: Metadata::new(time), + entries: BTreeMap::new(), + }); + + let forest = forest + .put( + dir.header.get_saturated_name(), + &dir.header.get_private_ref(), + &PrivateNode::Dir(Rc::clone(&dir)), + store, + rng, + ) + .await?; + + Ok(PrivateOpResult { + root_dir: dir, + forest, + result: (), + }) + } + /// Gets the metadata of the directory /// /// # Examples @@ -410,11 +474,14 @@ impl PrivateDirectory { NotADirectory(_, _) => bail!(FsError::NotFound), } } - None => PrivateOpResult { - root_dir, - forest, - result: Some(PrivateNode::Dir(self)), - }, + None => { + let result = self.lookup_node("", search_latest, &forest, store).await?; + PrivateOpResult { + root_dir, + forest, + result, + } + } }) } @@ -685,6 +752,21 @@ impl PrivateDirectory { forest: &PrivateForest, store: &B, ) -> Result> { + if path_segment.is_empty() { + let private_node = forest + .get( + &self.header.get_private_ref(), + PrivateForest::resolve_lowest, + store, + ) + .await?; + + return Ok(match (search_latest, private_node) { + (true, Some(node)) => Some(node.search_latest(forest, store).await?), + (_, node) => node, + }); + } + Ok(match self.entries.get(path_segment) { Some(private_ref) => { let private_node = forest diff --git a/dep/wnfs/src/private/privateref.rs b/dep/wnfs/src/private/privateref.rs index 2336e76..b1f6a3f 100644 --- a/dep/wnfs/src/private/privateref.rs +++ b/dep/wnfs/src/private/privateref.rs @@ -12,11 +12,11 @@ use serde::{de::Error as DeError, ser::Error as SerError, Deserialize, Serialize #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct PrivateRef { /// Sha3-256 hash of saturated namefilter. - pub saturated_name_hash: HashOutput, + pub(crate) saturated_name_hash: HashOutput, /// Sha3-256 hash of the ratchet key. - pub content_key: ContentKey, + pub(crate) content_key: ContentKey, /// Skip-ratchet-derived key. - pub revision_key: RevisionKey, + pub(crate) revision_key: RevisionKey, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/dep/wnfsutils/src/private_forest.rs b/dep/wnfsutils/src/private_forest.rs index e80dfd6..3285e17 100644 --- a/dep/wnfsutils/src/private_forest.rs +++ b/dep/wnfsutils/src/private_forest.rs @@ -57,9 +57,13 @@ impl<'a> PrivateDirectoryHelper<'a> { .get_deserializable::>(&forest_cid) .await .unwrap(); + let loaded_forest = Rc::new( + dagcbor::decode::(cbor_bytes.as_ref()) + .unwrap() + ); // Decode private forest CBOR bytes. - Ok(Rc::new(dagcbor::decode::(cbor_bytes.as_ref()).unwrap())) + Ok(loaded_forest) } pub async fn update_forest(&mut self, hamt: Rc) -> Result { @@ -83,10 +87,45 @@ impl<'a> PrivateDirectoryHelper<'a> { .as_dir() } - pub async fn get_private_ref(&mut self, wnfs_key: Vec) -> PrivateRef { + pub async fn get_private_ref(&mut self, wnfs_key: Vec, forest_cid: Cid) -> PrivateRef { let ratchet_seed: [u8; 32] = Sha3_256::hash(&wnfs_key); let inumber: [u8; 32] = Sha3_256::hash(&ratchet_seed); - let private_ref = PrivateRef::with_seed(Namefilter::default(), ratchet_seed, inumber); + let reloaded_private_ref = PrivateRef::with_seed(Namefilter::default(), ratchet_seed, inumber); + + + let forest = self.load_forest(forest_cid) + .await + .unwrap(); + let fetched_node = forest + .get( + &reloaded_private_ref, + PrivateForest::resolve_lowest, + &mut self.store + ) + .await + .unwrap(); + + let latest_dir = { + let tmp = fetched_node + .unwrap() + .as_dir() + .unwrap(); + tmp.get_node( + &[], + true, + forest, + &mut self.store + ) + .await + .unwrap() + .result + .unwrap() + .as_dir() + } + .unwrap(); + + let private_ref = latest_dir.header.get_private_ref(); + trace!("\r\n wnfs13 get_private_ref.content_key {:?}", private_ref.content_key.0.as_bytes()); trace!("\r\n wnfs13 get_private_ref.saturated_name_hash {:?}", private_ref.saturated_name_hash); trace!("\r\n wnfs13 get_private_ref.revision_key {:?}", private_ref.revision_key.0.as_bytes()); @@ -141,7 +180,7 @@ impl<'a> PrivateDirectoryHelper<'a> { trace!("\r\n wnfs13 header saturated_name_hash = {:?}", init_private_ref.saturated_name_hash); trace!("\r\n wnfs13 header content_key = {:?}", init_private_ref.content_key.0.as_bytes()); (self.update_forest(forest).await.unwrap(), init_private_ref) - + /*let PrivateOpResult { root_dir, forest, .. } = dir .as_dir() .unwrap() @@ -264,11 +303,11 @@ impl<'a> PrivateDirectoryHelper<'a> { return runtime.block_on(self.load_forest(forest_cid)); } - pub fn synced_get_private_ref(&mut self, wnfs_key: Vec) -> PrivateRef + pub fn synced_get_private_ref(&mut self, wnfs_key: Vec, forest_cid: Cid) -> PrivateRef { let runtime = tokio::runtime::Runtime::new().expect("Unable to create a runtime"); - return runtime.block_on(self.get_private_ref(wnfs_key)); + return runtime.block_on(self.get_private_ref(wnfs_key, forest_cid)); } diff --git a/jitpack.yml b/jitpack.yml index 5f73917..f2aa4b5 100644 --- a/jitpack.yml +++ b/jitpack.yml @@ -2,4 +2,4 @@ before_install: - git lfs pull install: - FILE="-Dfile=lib/build/outputs/aar/lib-release.aar" - - mvn install:install-file $FILE -DgroupId=com.group.module -DartifactId=wnfs-android -Dversion=1.2.5 -Dpackaging=aar -DgeneratePom=true + - mvn install:install-file $FILE -DgroupId=com.group.module -DartifactId=wnfs-android -Dversion=1.3.1 -Dpackaging=aar -DgeneratePom=true diff --git a/lib/src/main/java/land/fx/wnfslib/Fs.java b/lib/src/main/java/land/fx/wnfslib/Fs.java index d9bbdc6..4dd0899 100644 --- a/lib/src/main/java/land/fx/wnfslib/Fs.java +++ b/lib/src/main/java/land/fx/wnfslib/Fs.java @@ -6,7 +6,7 @@ public final class Fs { private static native String createPrivateForestNative(Datastore datastore); - private static native String getPrivateRefNative(Datastore datastore, byte[] wnfsKey); + private static native String getPrivateRefNative(Datastore datastore, byte[] wnfsKey, String cid); private static native Config createRootDirNative(Datastore datastore, String cid, byte[] wnfsKey); @@ -28,8 +28,8 @@ public static String createPrivateForest(Datastore datastore) { return createPrivateForestNative(datastore); } - public static String getPrivateRef(Datastore datastore, byte[] wnfsKey) { - return getPrivateRefNative(datastore, wnfsKey); + public static String getPrivateRef(Datastore datastore, byte[] wnfsKey, String cid) { + return getPrivateRefNative(datastore, wnfsKey, cid); } public static Config createRootDir(Datastore datastore, String cid, byte[] wnfsKey) { diff --git a/pom.xml b/pom.xml index 897b7ab..b27e0e3 100644 --- a/pom.xml +++ b/pom.xml @@ -5,5 +5,5 @@ 4.0.0 com.group.module wnfs-android - 1.2.5 + 1.3.1 diff --git a/wnfslib/src/lib.rs b/wnfslib/src/lib.rs index b1c3037..638a984 100644 --- a/wnfslib/src/lib.rs +++ b/wnfslib/src/lib.rs @@ -132,13 +132,15 @@ pub mod android { _: JClass, jni_fula_client: JObject, jni_wnfs_key: jbyteArray, + jni_cid: JString, ) -> jstring { trace!("**********************getPrivateRefNative started**************"); let store = JNIStore::new(env, jni_fula_client); let block_store = FFIFriendlyBlockStore::new(Box::new(store)); let helper = &mut PrivateDirectoryHelper::new(block_store); let wnfs_key: Vec = jbyte_array_to_vec(env, jni_wnfs_key); - let private_ref = helper.synced_get_private_ref(wnfs_key); + let forest_cid = deserialize_cid(env, jni_cid); + let private_ref = helper.synced_get_private_ref(wnfs_key, forest_cid); trace!("**********************getPrivateRefNative finished**************"); serialize_private_ref(env, private_ref).into_inner() } From 100d58a714e8118d6e991075d64adf08e7800f9b Mon Sep 17 00:00:00 2001 From: ehsan shariati Date: Tue, 13 Dec 2022 20:49:01 -0500 Subject: [PATCH 6/6] removed the wrong logs --- dep/wnfsutils/src/private_forest.rs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/dep/wnfsutils/src/private_forest.rs b/dep/wnfsutils/src/private_forest.rs index 3285e17..4d0c97c 100644 --- a/dep/wnfsutils/src/private_forest.rs +++ b/dep/wnfsutils/src/private_forest.rs @@ -75,9 +75,6 @@ impl<'a> PrivateDirectoryHelper<'a> { } pub async fn get_root_dir(&mut self, forest: Rc, private_ref: PrivateRef) -> Result> { - //trace!("\r\n wnfs13 revision_key = {:?}", private_ref.revision_key.0.as_bytes()); - //trace!("\r\n wnfs13 saturated_name_hash = {:?}", private_ref.saturated_name_hash); - //trace!("\r\n wnfs13 content_key = {:?}", private_ref.content_key.0.as_bytes()); // Fetch and decrypt root directory from the private forest using provided private ref. forest .get(&private_ref, PrivateForest::resolve_lowest, &mut self.store) @@ -126,10 +123,6 @@ impl<'a> PrivateDirectoryHelper<'a> { let private_ref = latest_dir.header.get_private_ref(); - trace!("\r\n wnfs13 get_private_ref.content_key {:?}", private_ref.content_key.0.as_bytes()); - trace!("\r\n wnfs13 get_private_ref.saturated_name_hash {:?}", private_ref.saturated_name_hash); - trace!("\r\n wnfs13 get_private_ref.revision_key {:?}", private_ref.revision_key.0.as_bytes()); - private_ref } @@ -176,9 +169,6 @@ impl<'a> PrivateDirectoryHelper<'a> { let init_private_ref = root_dir.header.get_private_ref(); - trace!("\r\n wnfs13 header revision_key = {:?}", init_private_ref.revision_key.0.as_bytes()); - trace!("\r\n wnfs13 header saturated_name_hash = {:?}", init_private_ref.saturated_name_hash); - trace!("\r\n wnfs13 header content_key = {:?}", init_private_ref.content_key.0.as_bytes()); (self.update_forest(forest).await.unwrap(), init_private_ref) /*let PrivateOpResult { root_dir, forest, .. } = dir @@ -188,10 +178,6 @@ impl<'a> PrivateDirectoryHelper<'a> { .await .unwrap(); let init_private_ref = root_dir.header.get_private_ref(); - - trace!("\r\n wnfs13 init2 revision_key = {:?}", init_private_ref.revision_key.0.as_bytes()); - trace!("\r\n wnfs13 init2 saturated_name_hash = {:?}", init_private_ref.saturated_name_hash); - trace!("\r\n wnfs13 init2 content_key = {:?}", init_private_ref.content_key.0.as_bytes()); (self.update_forest(forest).await.unwrap(), init_private_ref)*/ }