diff --git a/Cargo.lock b/Cargo.lock index f652232b..60cedb78 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -522,6 +522,18 @@ dependencies = [ "tracing", ] +[[package]] +name = "blockstore" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "358358b19add120a5afc3dd1c8e9161d6d06c44dfec2ef8da58b7fe5c369c90d" +dependencies = [ + "cid 0.11.1", + "dashmap", + "multihash 0.19.1", + "thiserror", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -1365,6 +1377,18 @@ dependencies = [ "serde_bytes", ] +[[package]] +name = "ipld-dagpb" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5eb3c08f1508fa62ffe1a805aafa116d2eb034b3542c85596db132f279abc47" +dependencies = [ + "bytes", + "ipld-core", + "quick-protobuf", + "thiserror", +] + [[package]] name = "itertools" version = "0.10.5" @@ -2320,6 +2344,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_ipld_dagjson" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3359b47ba7f4a306ef5984665e10539e212e97217afa489437d533208eecda36" +dependencies = [ + "ipld-core", + "serde", + "serde_json", +] + [[package]] name = "serde_json" version = "1.0.116" @@ -3109,7 +3144,6 @@ dependencies = [ "futures", "hex", "insta", - "libipld-core", "multihash 0.19.1", "once_cell", "proptest", @@ -3123,6 +3157,7 @@ dependencies = [ "serde-byte-array", "serde_bytes", "serde_ipld_dagcbor 0.6.1", + "serde_ipld_dagjson", "serde_json", "sha2", "sha3", @@ -3165,12 +3200,14 @@ dependencies = [ "async-std", "base64", "base64-serde", + "blake3", + "blockstore", "bytes", "chrono", - "cid 0.10.1", - "dashmap", + "cid 0.11.1", "futures", - "libipld", + "ipld-core", + "ipld-dagpb", "multihash 0.18.1", "once_cell", "parking_lot", @@ -3179,7 +3216,9 @@ dependencies = [ "rand_core", "serde", "serde_ipld_dagcbor 0.4.2", + "serde_ipld_dagjson", "serde_json", + "testresult 0.4.0", "thiserror", ] @@ -3197,7 +3236,6 @@ dependencies = [ "either", "futures", "insta", - "libipld", "log", "multihash 0.18.1", "once_cell", @@ -3237,6 +3275,7 @@ dependencies = [ "rug", "serde", "serde_bytes", + "serde_ipld_dagcbor 0.6.1", "serde_json", "test-strategy", "thiserror", @@ -3254,7 +3293,6 @@ dependencies = [ "bytes", "data-encoding", "futures", - "libipld", "num_enum", "proptest", "prost", diff --git a/Cargo.toml b/Cargo.toml index 4aff6241..795c2c9a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ "wnfs-unixfs-file", "wnfs-wasm", ] +resolver = "2" # Speedup build on macOS # See https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#splitting-debug-information diff --git a/wnfs-bench/hamt.rs b/wnfs-bench/hamt.rs index f34fea05..ebe9d03e 100644 --- a/wnfs-bench/hamt.rs +++ b/wnfs-bench/hamt.rs @@ -6,8 +6,9 @@ use criterion::{ use proptest::{arbitrary::any, collection::vec, test_runner::TestRunner}; use std::cmp; use wnfs_common::{ + blockstore::{block::Block as _, Blockstore, InMemoryBlockstore}, utils::{Arc, Sampleable}, - BlockStore, Link, MemoryBlockStore, Storable, StoreIpld, + Blake3Block, Link, Storable, StoreIpld, }; use wnfs_hamt::{ diff, merge, @@ -17,7 +18,7 @@ use wnfs_hamt::{ fn node_set(c: &mut Criterion) { let mut runner = TestRunner::deterministic(); - let store = MemoryBlockStore::default(); + let store = InMemoryBlockstore::<64>::new(); let operations = operations(any::<[u8; 32]>(), any::(), 1_000_000).sample(&mut runner); let node = &async_std::task::block_on(async { node_from_operations(&operations, &store).await }) @@ -50,7 +51,7 @@ fn node_set_consecutive(c: &mut Criterion) { c.bench_function("node set 1000 consecutive", |b| { b.to_async(AsyncStdExecutor).iter_batched( || { - let store = MemoryBlockStore::default(); + let store = InMemoryBlockstore::<64>::new(); let operations = operations(any::<[u8; 32]>(), any::(), 1000).sample(&mut runner); let node = async_std::task::block_on(async { @@ -73,7 +74,7 @@ fn node_set_consecutive(c: &mut Criterion) { } fn node_load_get(c: &mut Criterion) { - let store = MemoryBlockStore::default(); + let store = InMemoryBlockstore::<64>::new(); let cid = async_std::task::block_on(async { let mut node = Arc::new(>::default()); for i in 0..50 { @@ -100,7 +101,7 @@ fn node_load_get(c: &mut Criterion) { } fn node_load_remove(c: &mut Criterion) { - let store = MemoryBlockStore::default(); + let store = InMemoryBlockstore::<64>::new(); let cid = async_std::task::block_on(async { let mut node = Arc::new(>::default()); for i in 0..50 { @@ -123,7 +124,7 @@ fn node_load_remove(c: &mut Criterion) { } fn hamt_load_decode(c: &mut Criterion) { - let store = MemoryBlockStore::default(); + let store = InMemoryBlockstore::<64>::new(); let (cid, bytes) = async_std::task::block_on(async { let mut node = Arc::new(>::default()); for i in 0..50 { @@ -137,7 +138,9 @@ fn hamt_load_decode(c: &mut Criterion) { .encode_ipld() .unwrap(); - let cid = store.put_block(encoded_hamt.clone(), codec).await.unwrap(); + let block = Blake3Block::new(codec, encoded_hamt.clone()); + let cid = block.cid().unwrap(); + store.put(block).await.unwrap(); (cid, encoded_hamt) }); @@ -157,7 +160,7 @@ fn hamt_set_encode(c: &mut Criterion) { b.to_async(AsyncStdExecutor).iter_batched( || { ( - MemoryBlockStore::default(), + InMemoryBlockstore::<64>::new(), Arc::new(>::default()), ) }, @@ -187,7 +190,7 @@ fn hamt_diff(c: &mut Criterion) { c.bench_function("hamt diff", |b| { b.to_async(AsyncStdExecutor).iter_batched( || { - let store = MemoryBlockStore::default(); + let store = InMemoryBlockstore::<64>::new(); let kvs1 = generate_kvs("[a-z0-9]{1,3}", 0u64..1000, 0..100).sample(&mut runner); let kvs2 = generate_kvs("[a-z0-9]{1,3}", 0u64..1000, 0..100).sample(&mut runner); let (node1, node2) = task::block_on(async { @@ -216,7 +219,7 @@ fn hamt_merge(c: &mut Criterion) { c.bench_function("hamt merge", |b| { b.to_async(AsyncStdExecutor).iter_batched( || { - let store = MemoryBlockStore::default(); + let store = InMemoryBlockstore::<64>::new(); let kvs1 = generate_kvs("[a-z0-9]{1,3}", 0u64..1000, 0..100).sample(&mut runner); let kvs2 = generate_kvs("[a-z0-9]{1,3}", 0u64..1000, 0..100).sample(&mut runner); let (node1, node2) = task::block_on(async { diff --git a/wnfs-common/Cargo.toml b/wnfs-common/Cargo.toml index 73664abc..87d2fc53 100644 --- a/wnfs-common/Cargo.toml +++ b/wnfs-common/Cargo.toml @@ -22,19 +22,22 @@ anyhow = "1.0" async-once-cell = "0.5" base64 = { version = "0.21", optional = true } base64-serde = { version = "0.7", optional = true } +blake3 = "1.5.1" +blockstore = "0.5" bytes = { version = "1.4", features = ["serde"] } chrono = { version = "0.4", default-features = false, features = ["clock", "std"] } -cid = "0.10" -dashmap = "5.5.3" +cid = "0.11" futures = "0.3" -libipld = { version = "0.16", features = ["dag-cbor", "derive", "serde-codec"] } +ipld-core = "0.4" +ipld-dagpb = { version = "0.2", optional = true } multihash = "0.18" once_cell = "1.16" parking_lot = "0.12" proptest = { version = "1.1", optional = true } rand_core = "0.6" serde = { version = "1.0", features = ["rc"] } -serde_ipld_dagcbor = "0.4.2" +serde_ipld_dagcbor = "0.4" +serde_ipld_dagjson = { version = "0.2", optional = true } serde_json = { version = "1.0", optional = true } thiserror = "1.0" @@ -42,9 +45,19 @@ thiserror = "1.0" async-std = { version = "1.11", features = ["attributes"] } base64 = "0.21" base64-serde = "0.7" +ipld-dagpb = "0.2" proptest = "1.1" rand = "0.8" +serde_ipld_dagjson = "0.2" serde_json = "1.0" +testresult = "0.4.0" [features] -test_utils = ["dep:proptest", "dep:base64-serde", "dep:base64", "dep:serde_json"] +test_utils = [ + "dep:proptest", + "dep:base64-serde", + "dep:base64", + "dep:serde_json", + "dep:serde_ipld_dagjson", + "dep:ipld-dagpb" +] diff --git a/wnfs-common/src/block.rs b/wnfs-common/src/block.rs new file mode 100644 index 00000000..a524e71e --- /dev/null +++ b/wnfs-common/src/block.rs @@ -0,0 +1,72 @@ +use bytes::Bytes; +use cid::{multihash::Multihash, Cid}; + +//-------------------------------------------------------------------------------------------------- +// Constants +//-------------------------------------------------------------------------------------------------- + +/// The value representing the DAG-JSON codec. +/// +/// - +/// - +pub const CODEC_DAG_JSON: u64 = 0x0129; + +/// The value representing the DAG-CBOR codec. +/// +/// - +/// - +pub const CODEC_DAG_CBOR: u64 = 0x71; + +/// The value representing the DAG-Protobuf codec. +/// +/// - +/// - +pub const CODEC_DAG_PB: u64 = 0x70; + +/// The value representing the raw codec. +/// +/// - +/// - +pub const CODEC_RAW: u64 = 0x55; + +const MULTICODEC_BLAKE3: u64 = 0x1e; + +//-------------------------------------------------------------------------------------------------- +// Traits +//-------------------------------------------------------------------------------------------------- + +pub struct Blake3Block { + cid: Cid, + bytes: Bytes, +} + +//-------------------------------------------------------------------------------------------------- +// Implementations +//-------------------------------------------------------------------------------------------------- + +impl Blake3Block { + pub fn new(codec: u64, bytes: impl Into) -> Self { + let bytes: Bytes = bytes.into(); + + // Compute the Blake3 hash of the bytes + let hash = blake3::hash(&bytes); + + let multihash = + Multihash::wrap(MULTICODEC_BLAKE3, hash.as_bytes()).expect("constant hash size"); + + // Represent the hash as a V1 CID + let cid = Cid::new_v1(codec, multihash); + + Self { cid, bytes } + } +} + +impl blockstore::block::Block<64> for Blake3Block { + fn cid(&self) -> Result { + Ok(self.cid) + } + + fn data(&self) -> &[u8] { + self.bytes.as_ref() + } +} diff --git a/wnfs-common/src/blockstore.rs b/wnfs-common/src/blockstore.rs deleted file mode 100644 index f5dd08e1..00000000 --- a/wnfs-common/src/blockstore.rs +++ /dev/null @@ -1,325 +0,0 @@ -use crate::{ - decode, encode, - utils::{Arc, CondSend, CondSync}, - BlockStoreError, MAX_BLOCK_SIZE, -}; -use bytes::Bytes; -use futures::Future; -use libipld::{ - cbor::DagCborCodec, - cid::Version, - multihash::{Code, MultihashDigest}, - Cid, -}; -use parking_lot::Mutex; -use serde::{Deserialize, Serialize}; -use std::collections::HashMap; - -//-------------------------------------------------------------------------------------------------- -// Constants -//-------------------------------------------------------------------------------------------------- - -/// The value representing the DAG-JSON codec. -/// -/// - -/// - -pub const CODEC_DAG_JSON: u64 = 0x0129; - -/// The value representing the DAG-CBOR codec. -/// -/// - -/// - -pub const CODEC_DAG_CBOR: u64 = 0x71; - -/// The value representing the DAG-Protobuf codec. -/// -/// - -/// - -pub const CODEC_DAG_PB: u64 = 0x70; - -/// The value representing the raw codec. -/// -/// - -/// - -pub const CODEC_RAW: u64 = 0x55; - -//-------------------------------------------------------------------------------------------------- -// Traits -//-------------------------------------------------------------------------------------------------- - -/// For types that implement block store operations like adding, getting content from the store. -pub trait BlockStore: CondSync { - /// Retrieve a block from this store via its hash (`Cid`). - /// - /// If this store can't find the block, it may raise an error like `BlockNotFound`. - fn get_block( - &self, - cid: &Cid, - ) -> impl Future> + CondSend; - - /// Put some bytes into the blockstore. These bytes should be encoded with the given codec. - /// - /// E.g. `CODEC_RAW` for raw bytes blocks, `CODEC_DAG_CBOR` for dag-cbor, etc. - /// - /// This codec will determine the codec encoded in the final `Cid` that's returned. - /// - /// If the codec is incorrect, this function won't fail, but any tools that depend on the - /// correctness of the codec may fail. (E.g. tools that follow the links of blocks). - /// - /// This funciton allows the blockstore to choose the hashing function itself. - /// The hashing function that was chosen will be readable from the `Cid` metadata. - /// - /// If you need control over the concrete hashing function that's used, see `put_block_keyed`. - fn put_block( - &self, - bytes: impl Into + CondSend, - codec: u64, - ) -> impl Future> + CondSend { - let bytes = bytes.into(); - async move { - let cid = self.create_cid(&bytes, codec)?; - self.put_block_keyed(cid, bytes).await?; - Ok(cid) - } - } - - /// Put a block of data into this blockstore. The block's CID needs to match the CID given. - /// - /// It's up to the blockstore whether to check this fact or assume it when this function is called. - /// - /// The default implementation of `put_block` will use this function under the hood and use - /// the correct CID provided by the `create_cid` function. - /// - /// This is useful to be able to add blocks that were generated from other - /// clients with differently configured hashing functions to this blockstore. - fn put_block_keyed( - &self, - cid: Cid, - bytes: impl Into + CondSend, - ) -> impl Future> + CondSend; - - /// Find out whether a call to `get_block` would return with a result or not. - /// - /// This is useful for data exchange protocols to find out what needs to be fetched - /// externally and what doesn't. - fn has_block( - &self, - cid: &Cid, - ) -> impl Future> + CondSend; - - // This should be the same in all implementations of BlockStore - fn create_cid(&self, bytes: &[u8], codec: u64) -> Result { - // If there are too many bytes, abandon this task - if bytes.len() > MAX_BLOCK_SIZE { - return Err(BlockStoreError::MaximumBlockSizeExceeded(bytes.len())); - } - - // Compute the Blake3 hash of the bytes - let hash = Code::Blake3_256.digest(bytes); - - // Represent the hash as a V1 CID - let cid = Cid::new(Version::V1, codec, hash)?; - - Ok(cid) - } -} - -//-------------------------------------------------------------------------------------------------- -// Implementations -//-------------------------------------------------------------------------------------------------- - -impl BlockStore for &B { - async fn get_block(&self, cid: &Cid) -> Result { - (**self).get_block(cid).await - } - - async fn put_block( - &self, - bytes: impl Into + CondSend, - codec: u64, - ) -> Result { - (**self).put_block(bytes, codec).await - } - - async fn put_block_keyed( - &self, - cid: Cid, - bytes: impl Into + CondSend, - ) -> Result<(), BlockStoreError> { - (**self).put_block_keyed(cid, bytes).await - } - - async fn has_block(&self, cid: &Cid) -> Result { - (**self).has_block(cid).await - } - - fn create_cid(&self, bytes: &[u8], codec: u64) -> Result { - (**self).create_cid(bytes, codec) - } -} - -impl BlockStore for Box { - async fn get_block(&self, cid: &Cid) -> Result { - (**self).get_block(cid).await - } - - async fn put_block( - &self, - bytes: impl Into + CondSend, - codec: u64, - ) -> Result { - (**self).put_block(bytes, codec).await - } - - async fn put_block_keyed( - &self, - cid: Cid, - bytes: impl Into + CondSend, - ) -> Result<(), BlockStoreError> { - (**self).put_block_keyed(cid, bytes).await - } - - async fn has_block(&self, cid: &Cid) -> Result { - (**self).has_block(cid).await - } - - fn create_cid(&self, bytes: &[u8], codec: u64) -> Result { - (**self).create_cid(bytes, codec) - } -} - -/// An in-memory block store to simulate IPFS. -/// -/// IPFS is basically a glorified HashMap. - -#[derive(Debug, Default, Clone, Serialize, Deserialize)] -pub struct MemoryBlockStore( - #[serde(serialize_with = "crate::utils::serialize_cid_map")] - #[serde(deserialize_with = "crate::utils::deserialize_cid_map")] - pub(crate) Arc>>, -); - -impl MemoryBlockStore { - /// Creates a new in-memory block store. - pub fn new() -> Self { - Self::default() - } -} - -impl BlockStore for MemoryBlockStore { - async fn get_block(&self, cid: &Cid) -> Result { - let bytes = self - .0 - .lock() - .get(cid) - .ok_or(BlockStoreError::CIDNotFound(*cid))? - .clone(); - - Ok(bytes) - } - - async fn put_block_keyed( - &self, - cid: Cid, - bytes: impl Into + CondSend, - ) -> Result<(), BlockStoreError> { - self.0.lock().insert(cid, bytes.into()); - - Ok(()) - } - - async fn has_block(&self, cid: &Cid) -> Result { - Ok(self.0.lock().contains_key(cid)) - } -} - -//-------------------------------------------------------------------------------------------------- -// Tests -//-------------------------------------------------------------------------------------------------- - -/// Tests the retrieval property of a BlockStore-conforming type. -pub async fn bs_retrieval_test(store: impl BlockStore) -> Result<(), BlockStoreError> { - // Example objects to insert and remove from the blockstore - let first_bytes = vec![1, 2, 3, 4, 5]; - let second_bytes = b"hello world".to_vec(); - - // Insert the objects into the blockstore - let first_cid = store.put_block(first_bytes.clone(), CODEC_RAW).await?; - let second_cid = store.put_block(second_bytes.clone(), CODEC_RAW).await?; - - // Retrieve the objects from the blockstore - let first_loaded = store.get_block(&first_cid).await?; - let second_loaded = store.get_block(&second_cid).await?; - - // Assert that the objects are the same as the ones we inserted - assert_eq!(first_loaded, first_bytes); - assert_eq!(second_loaded, second_bytes); - - Ok(()) -} - -/// Tests the duplication of a BlockStore-conforming type. -pub async fn bs_duplication_test(store: impl BlockStore) -> Result<(), BlockStoreError> { - // Example objects to insert and remove from the blockstore - let first_bytes = vec![1, 2, 3, 4, 5]; - let second_bytes = first_bytes.clone(); - - // Insert the objects into the blockstore - let first_cid = store.put_block(first_bytes.clone(), CODEC_RAW).await?; - let second_cid = store.put_block(second_bytes.clone(), CODEC_RAW).await?; - - // Assert that the two vecs produced the same CID - assert_eq!(first_cid, second_cid); - - // Retrieve the objects from the blockstore - let first_loaded = store.get_block(&first_cid).await?; - let second_loaded = store.get_block(&second_cid).await?; - - // Assert that the objects are the same as the ones we inserted - assert_eq!(first_loaded, first_bytes); - assert_eq!(second_loaded, second_bytes); - - // Assert that the objects we loaded are the same - assert_eq!(first_loaded, second_loaded); - - Ok(()) -} - -/// Tests the serialization of a BlockStore-conforming type. -pub async fn bs_serialization_test(store: &T) -> Result<(), BlockStoreError> -where - T: BlockStore + Serialize + for<'de> Deserialize<'de>, -{ - // Example objects to insert and remove from the blockstore - let bytes = vec![1, 2, 3, 4, 5]; - - // Insert the object into the blockstore - let cid = store.put_block(bytes.clone(), CODEC_RAW).await?; - - // Serialize the BlockStore - let serial_store: Vec = encode(&store, DagCborCodec)?; - // Construct a new BlockStore from the Serialized object - let deserial_store: T = decode(&serial_store, DagCborCodec)?; - // Retrieve the object from the blockstore - let loaded = deserial_store.get_block(&cid).await?; - - // Assert that the objects are the same as the ones we inserted - assert_eq!(loaded, bytes); - - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - use anyhow::Result; - - #[async_std::test] - async fn memory_blockstore() -> Result<()> { - let store = &MemoryBlockStore::new(); - bs_retrieval_test::(store).await?; - bs_duplication_test::(store).await?; - bs_serialization_test::(store).await?; - Ok(()) - } -} diff --git a/wnfs-common/src/encoding.rs b/wnfs-common/src/encoding.rs deleted file mode 100644 index 1cf1d8ba..00000000 --- a/wnfs-common/src/encoding.rs +++ /dev/null @@ -1,32 +0,0 @@ -use anyhow::Result; -use libipld::{ - codec::{Decode, Encode}, - prelude::Codec, - serde as ipld_serde, Ipld, -}; -use serde::{de::DeserializeOwned, Serialize}; -use std::io::Cursor; - -/// Encodes a serializable value into DagCbor bytes. -pub fn encode(value: &S, codec: C) -> Result> -where - S: Serialize, - C: Codec, - Ipld: Encode, -{ - let ipld = ipld_serde::to_ipld(value)?; - let mut bytes = Vec::new(); - >::encode(&ipld, codec, &mut bytes)?; - Ok(bytes) -} - -/// Decodes recieved DagCbor bytes into a deserializable value. -pub fn decode(bytes: &[u8], codec: C) -> Result -where - D: DeserializeOwned, - C: Codec, - Ipld: Decode, -{ - let ipld = >::decode(codec, &mut Cursor::new(bytes))?; - Ok(ipld_serde::from_ipld::<_>(ipld)?) -} diff --git a/wnfs-common/src/error.rs b/wnfs-common/src/error.rs index 6db9b2e3..7831df7b 100644 --- a/wnfs-common/src/error.rs +++ b/wnfs-common/src/error.rs @@ -1,6 +1,6 @@ //! Errors -use libipld::Cid; +use cid::Cid; use thiserror::Error; //-------------------------------------------------------------------------------------------------- diff --git a/wnfs-common/src/lib.rs b/wnfs-common/src/lib.rs index 74302b54..604f3e11 100644 --- a/wnfs-common/src/lib.rs +++ b/wnfs-common/src/lib.rs @@ -1,6 +1,5 @@ //! This crate contains the common types and functions used by the WNFS crates. -pub mod blockstore; -mod encoding; +pub mod block; mod error; mod link; mod metadata; @@ -8,8 +7,7 @@ mod pathnodes; mod storable; pub mod utils; -pub use blockstore::*; -pub use encoding::*; +pub use block::*; pub use error::*; pub use link::*; pub use metadata::*; @@ -34,6 +32,10 @@ pub type HashOutput = [u8; HASH_BYTE_SIZE]; // Re-exports //-------------------------------------------------------------------------------------------------- -pub mod libipld { - pub use libipld::*; +pub mod ipld_core { + pub use ipld_core::*; +} + +pub mod blockstore { + pub use blockstore::*; } diff --git a/wnfs-common/src/link.rs b/wnfs-common/src/link.rs index e9d9e8da..27276d4c 100644 --- a/wnfs-common/src/link.rs +++ b/wnfs-common/src/link.rs @@ -1,7 +1,8 @@ -use crate::{utils::CondSync, BlockStore, Storable}; +use crate::{utils::CondSync, Storable}; use anyhow::Result; use async_once_cell::OnceCell; -use libipld::Cid; +use blockstore::Blockstore; +use cid::Cid; use std::fmt::{self, Debug, Formatter}; //-------------------------------------------------------------------------------------------------- @@ -12,7 +13,7 @@ use std::fmt::{self, Debug, Formatter}; /// /// It supports representing the "link" with a Cid or the deserialized value itself. /// -/// Link needs a `BlockStore` to be able to resolve Cids to corresponding values of `T` and vice versa. +/// Link needs a `Blockstore` to be able to resolve Cids to corresponding values of `T` and vice versa. pub enum Link { /// A variant of `Link` that started out as a `Cid`. /// If the decoded value is resolved using `resolve_value`, then the `value_cache` gets populated and @@ -39,7 +40,7 @@ impl Link { } /// Gets the Cid stored in type. It attempts to get it from the store if it is not present in type. - pub async fn resolve_cid(&self, store: &impl BlockStore) -> Result { + pub async fn resolve_cid(&self, store: &impl Blockstore) -> Result { match self { Self::Encoded { cid, .. } => Ok(*cid), Self::Decoded { value } => value.store(store).await, @@ -47,7 +48,7 @@ impl Link { } /// Gets the value stored in link. It attempts to get it from the store if it is not present in link. - pub async fn resolve_value(&self, store: &impl BlockStore) -> Result<&T> { + pub async fn resolve_value(&self, store: &impl Blockstore) -> Result<&T> { match self { Self::Encoded { cid, value_cache } => { value_cache.get_or_try_init(T::load(cid, store)).await @@ -57,7 +58,7 @@ impl Link { } /// Gets mut value stored in link. It attempts to get it from the store if it is not present in link. - pub async fn resolve_value_mut(&mut self, store: &impl BlockStore) -> Result<&mut T> { + pub async fn resolve_value_mut(&mut self, store: &impl Blockstore) -> Result<&mut T> { match self { Self::Encoded { cid, value_cache } => { let value = match value_cache.take() { @@ -97,7 +98,7 @@ impl Link { } /// Gets an owned value from type. It attempts to it get from the store if it is not present in type. - pub async fn resolve_owned_value(self, store: &impl BlockStore) -> Result + pub async fn resolve_owned_value(self, store: &impl Blockstore) -> Result where T: Storable, { @@ -124,7 +125,7 @@ impl Link { } /// Compares two links for equality. Attempts to get them from store if they are not already cached. - pub async fn deep_eq(&self, other: &Link, store: &impl BlockStore) -> Result + pub async fn deep_eq(&self, other: &Link, store: &impl Blockstore) -> Result where T: PartialEq + Storable, { @@ -215,10 +216,11 @@ where #[cfg(test)] mod tests { - use crate::{BlockStore, Link, MemoryBlockStore, Storable}; + use crate::{Link, Storable}; use anyhow::Result; use async_once_cell::OnceCell; - use libipld::Cid; + use blockstore::{Blockstore, InMemoryBlockstore}; + use cid::Cid; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] @@ -231,7 +233,7 @@ mod tests { impl Storable for Example { type Serializable = Example; - async fn to_serializable(&self, _store: &impl BlockStore) -> Result { + async fn to_serializable(&self, _store: &impl Blockstore) -> Result { Ok(self.clone()) } @@ -279,7 +281,7 @@ mod tests { #[async_std::test] async fn link_value_can_be_resolved() { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let example = Example::new(256); let cid = example.store(store).await.unwrap(); let link = Link::::from_cid(cid); @@ -292,7 +294,7 @@ mod tests { #[async_std::test] async fn link_cid_can_be_resolved() { let example = Example::new(12_000_500); - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let link = Link::::from(example.clone()); let cid = link.resolve_cid(store).await.unwrap(); diff --git a/wnfs-common/src/metadata.rs b/wnfs-common/src/metadata.rs index bd12e05b..12a32ae9 100644 --- a/wnfs-common/src/metadata.rs +++ b/wnfs-common/src/metadata.rs @@ -2,8 +2,7 @@ use anyhow::{bail, Result}; use chrono::{DateTime, TimeZone, Utc}; -use libipld::{Ipld, Multihash}; -use multihash::{Code, MultihashDigest}; +use ipld_core::ipld::Ipld; use serde::{ de::{DeserializeOwned, Error as DeError}, Deserialize, Deserializer, Serialize, Serializer, @@ -153,7 +152,7 @@ impl Metadata { /// ``` /// use wnfs_common::Metadata; /// use chrono::Utc; - /// use libipld::Ipld; + /// use ipld_core::ipld::Ipld; /// /// let mut metadata = Metadata::new(Utc::now()); /// metadata.put("foo", Ipld::String("bar".into())); @@ -174,14 +173,14 @@ impl Metadata { /// Serializes and inserts given value at given key in metadata. pub fn put_serializable(&mut self, key: &str, value: impl Serialize) -> Result> { - let serialized = libipld::serde::to_ipld(value)?; + let serialized = ipld_core::serde::to_ipld(value)?; Ok(self.put(key, serialized)) } /// Returns deserialized metadata value behind given key. pub fn get_deserializable(&self, key: &str) -> Option> { self.get(key) - .map(|ipld| Ok(libipld::serde::from_ipld(ipld.clone())?)) + .map(|ipld| Ok(ipld_core::serde::from_ipld(ipld.clone())?)) } /// Deletes a key from the metadata. @@ -190,7 +189,7 @@ impl Metadata { /// ``` /// use wnfs_common::Metadata; /// use chrono::Utc; - /// use libipld::Ipld; + /// use ipld_core::ipld::Ipld; /// /// let mut metadata = Metadata::new(Utc::now()); /// metadata.put("foo", Ipld::String("bar".into())); @@ -210,7 +209,7 @@ impl Metadata { /// ``` /// use wnfs_common::Metadata; /// use chrono::Utc; - /// use libipld::Ipld; + /// use ipld_core::ipld::Ipld; /// /// let mut metadata1 = Metadata::new(Utc::now()); /// metadata1.put("foo", Ipld::String("bar".into())); @@ -225,10 +224,9 @@ impl Metadata { } } - pub(crate) fn hash(&self) -> Result { + pub(crate) fn hash(&self) -> Result { let vec = serde_ipld_dagcbor::to_vec(self)?; - let hash = Code::Blake3_256.digest(&vec); - Ok(hash) + Ok(blake3::hash(&vec)) } /// Tie break this node with another one. @@ -236,7 +234,7 @@ impl Metadata { /// together (yet), instead we compare their hashes. The one with the lower hash /// survives. pub fn tie_break_with(&mut self, other: &Self) -> Result<()> { - if self.hash()?.digest() > other.hash()?.digest() { + if self.hash()?.as_bytes() > other.hash()?.as_bytes() { self.0 = other.0.clone(); } @@ -308,17 +306,19 @@ impl<'de> Deserialize<'de> for NodeType { #[cfg(test)] mod tests { - use crate::{decode, encode, Metadata}; + use crate::Metadata; use chrono::Utc; - use libipld::cbor::DagCborCodec; + use testresult::TestResult; #[async_std::test] - async fn metadata_can_encode_decode_as_cbor() { + async fn metadata_can_encode_decode_as_cbor() -> TestResult { let metadata = Metadata::new(Utc::now()); - let encoded_metadata = encode(&metadata, DagCborCodec).unwrap(); - let decoded_metadata: Metadata = decode(encoded_metadata.as_ref(), DagCborCodec).unwrap(); + let encoded_metadata = serde_ipld_dagcbor::to_vec(&metadata)?; + let decoded_metadata: Metadata = serde_ipld_dagcbor::from_slice(&encoded_metadata)?; assert_eq!(metadata, decoded_metadata); + + Ok(()) } } diff --git a/wnfs-common/src/storable.rs b/wnfs-common/src/storable.rs index f48de854..246d60f5 100644 --- a/wnfs-common/src/storable.rs +++ b/wnfs-common/src/storable.rs @@ -3,13 +3,14 @@ //! `PublicNode`, `HamtForest` etc. use crate::{ utils::{Arc, CondSend, CondSync}, - BlockStore, + Blake3Block, BlockStoreError, CODEC_DAG_CBOR, }; use anyhow::{bail, Result}; use async_once_cell::OnceCell; +use blockstore::{block::Block, Blockstore}; use bytes::Bytes; +use cid::Cid; use futures::Future; -use libipld::{cbor::DagCborCodec, Cid}; use serde::{de::DeserializeOwned, Serialize}; //-------------------------------------------------------------------------------------------------- @@ -23,11 +24,11 @@ macro_rules! impl_storable_from_serde { impl $( < $( $generics ),+ > )? $crate::Storable for $ty $( where $( $generics: ::serde::Serialize + ::serde::de::DeserializeOwned + Clone + $crate::utils::CondSync ),+ )?{ type Serializable = $ty; - async fn to_serializable(&self, _store: &impl $crate::BlockStore) -> ::anyhow::Result { + async fn to_serializable(&self, _store: &impl Blockstore) -> ::anyhow::Result { Ok(self.clone()) } - async fn from_serializable(_cid: Option<&$crate::libipld::Cid>, serializable: Self::Serializable) -> ::anyhow::Result { + async fn from_serializable(_cid: Option<&Cid>, serializable: Self::Serializable) -> ::anyhow::Result { Ok(serializable) } } @@ -62,35 +63,38 @@ pub trait Storable: Sized { /// The at-rest representation of this storable type. type Serializable: StoreIpld + LoadIpld + CondSync; - /// Turn the current type into the at-rest representation of this type. + /// Turns the current type into the at-rest representation of this type. fn to_serializable( &self, - store: &impl BlockStore, + store: &impl Blockstore, ) -> impl Future> + CondSend; - /// Take an at-rest representation of this type and turn it into the in-memory representation. + /// Takes an at-rest representation of this type and turn it into the in-memory representation. /// You can use the `cid` parameter to populate a cache. fn from_serializable( cid: Option<&Cid>, serializable: Self::Serializable, ) -> impl Future> + CondSend; - /// Return a serialization cache, if it exists. + /// Returns a serialization cache, if it exists. /// By default, this always returns `None`. fn persisted_as(&self) -> Option<&OnceCell> { None } - /// Store this data type in a given `BlockStore`. + /// Stores this data type in a given `Blockstore`. /// /// This will short-circuit by using the `persisted_as` once-cell, if available. - fn store(&self, store: &impl BlockStore) -> impl Future> + CondSend + fn store(&self, store: &impl Blockstore) -> impl Future> + CondSend where Self: CondSync, { let store_future = async { let (bytes, codec) = self.to_serializable(store).await?.encode_ipld()?; - Ok(store.put_block(bytes, codec).await?) + let block = Blake3Block::new(codec, bytes); + let cid = block.cid()?; + store.put(block).await?; + Ok(cid) }; async { @@ -106,10 +110,13 @@ pub trait Storable: Sized { /// /// This will pass on the CID to the `from_serializable` function so it can /// populate a cache in some cases. - fn load(cid: &Cid, store: &impl BlockStore) -> impl Future> + CondSend { + fn load(cid: &Cid, store: &impl Blockstore) -> impl Future> + CondSend { async { - let bytes = store.get_block(cid).await?; - let serializable = Self::Serializable::decode_ipld(cid, bytes)?; + let block = store + .get(cid) + .await? + .ok_or_else(|| BlockStoreError::CIDNotFound(*cid))?; + let serializable = Self::Serializable::decode_ipld(cid, Bytes::from(block))?; Self::from_serializable(Some(cid), serializable).await } } @@ -126,14 +133,14 @@ pub trait LoadIpld: Sized { impl StoreIpld for T { fn encode_ipld(&self) -> Result<(Bytes, u64)> { let bytes = serde_ipld_dagcbor::to_vec(self)?; - Ok((bytes.into(), DagCborCodec.into())) + Ok((bytes.into(), CODEC_DAG_CBOR)) } } impl LoadIpld for T { fn decode_ipld(cid: &Cid, bytes: Bytes) -> Result { let codec = cid.codec(); - let dag_cbor: u64 = DagCborCodec.into(); + let dag_cbor = CODEC_DAG_CBOR; if codec != dag_cbor { bail!("Expected dag-cbor codec, but got {codec:X} in CID {cid}"); } @@ -167,7 +174,7 @@ impl LoadIpld for T { impl Storable for Arc { type Serializable = T::Serializable; - async fn to_serializable(&self, store: &impl BlockStore) -> Result { + async fn to_serializable(&self, store: &impl Blockstore) -> Result { self.as_ref().to_serializable(store).await } diff --git a/wnfs-common/src/utils/common.rs b/wnfs-common/src/utils/common.rs index 82d384b9..a57f025e 100644 --- a/wnfs-common/src/utils/common.rs +++ b/wnfs-common/src/utils/common.rs @@ -1,13 +1,7 @@ -use super::Arc; use crate::HashOutput; use anyhow::Result; -use bytes::Bytes; use futures::{AsyncRead, AsyncReadExt}; -use libipld::{Cid, IpldCodec}; -use parking_lot::Mutex; use rand_core::CryptoRngCore; -use serde::{Deserialize, Serialize, Serializer}; -use std::collections::HashMap; //-------------------------------------------------------------------------------------------------- // Functions @@ -79,42 +73,3 @@ pub fn to_hash_output(bytes: &[u8]) -> HashOutput { nibbles[..bytes.len()].copy_from_slice(bytes); nibbles } - -/// Tries to convert a u64 value to IPLD codec. -pub fn u64_to_ipld(value: u64) -> Result { - Ok(value.try_into()?) -} - -pub(crate) fn serialize_cid_map( - map: &Arc>>, - serializer: S, -) -> Result -where - S: Serializer, -{ - let map = map - .lock() - .iter() - .map(|(cid, bytes)| (cid.to_string(), bytes.to_vec())) - .collect::>(); - - map.serialize(serializer) -} - -pub(crate) fn deserialize_cid_map<'de, D>( - deserializer: D, -) -> Result>>, D::Error> -where - D: serde::Deserializer<'de>, -{ - let map = HashMap::>::deserialize(deserializer)?; - let map = map - .into_iter() - .map(|(cid, bytes)| { - let cid = cid.parse::().map_err(serde::de::Error::custom)?; - Ok((cid, bytes.into())) - }) - .collect::>()?; - - Ok(Arc::new(Mutex::new(map))) -} diff --git a/wnfs-common/src/utils/test.rs b/wnfs-common/src/utils/test.rs index 3bbc44e3..99fcf448 100644 --- a/wnfs-common/src/utils/test.rs +++ b/wnfs-common/src/utils/test.rs @@ -1,14 +1,11 @@ -use super::{Arc, CondSend, CondSync}; -use crate::{BlockStore, BlockStoreError, MemoryBlockStore, CODEC_DAG_CBOR, CODEC_RAW}; +use super::{Arc, CondSync}; +use crate::{BlockStoreError, CODEC_DAG_CBOR, CODEC_DAG_PB, CODEC_RAW}; use anyhow::Result; use base64_serde::base64_serde_type; +use blockstore::{Blockstore, InMemoryBlockstore}; use bytes::Bytes; -use libipld::{ - cbor::DagCborCodec, - json::DagJsonCodec, - prelude::{Decode, Encode, References}, - Cid, Ipld, IpldCodec, -}; +use cid::Cid; +use ipld_core::ipld::Ipld; use parking_lot::Mutex; use proptest::{ strategy::{Strategy, ValueTree}, @@ -16,10 +13,7 @@ use proptest::{ }; use serde::{Deserialize, Serialize}; use serde_json::Value; -use std::{ - collections::{HashMap, HashSet, VecDeque}, - io::Cursor, -}; +use std::collections::{HashMap, HashSet, VecDeque}; //-------------------------------------------------------------------------------------------------- // Type Definitions @@ -33,7 +27,7 @@ type BlockHandler = Arc; #[derive(Default)] pub struct SnapshotBlockStore { - inner: MemoryBlockStore, + inner: InMemoryBlockstore<64>, block_handlers: Arc>>, } @@ -58,13 +52,16 @@ pub trait Sampleable { impl SnapshotBlockStore { pub async fn get_block_snapshot(&self, cid: &Cid) -> Result { - let bytes = self.get_block(cid).await?; - self.handle_block(cid, &bytes) + let bytes = self + .get(cid) + .await? + .ok_or_else(|| BlockStoreError::CIDNotFound(*cid))?; + self.handle_block(cid, &Bytes::from(bytes)) } pub fn handle_block(&self, cid: &Cid, bytes: &Bytes) -> Result { let ipld = match cid.codec() { - CODEC_DAG_CBOR => Ipld::decode(DagCborCodec, &mut Cursor::new(bytes))?, + CODEC_DAG_CBOR => serde_ipld_dagcbor::from_slice(bytes)?, CODEC_RAW => match self.block_handlers.lock().get(cid) { Some(func) => func.convert(bytes)?, None => Ipld::Bytes(bytes.to_vec()), @@ -72,10 +69,8 @@ impl SnapshotBlockStore { _ => unimplemented!(), }; - let mut json_bytes = Vec::new(); - ipld.encode(DagJsonCodec, &mut json_bytes)?; - - let value = serde_json::from_slice(&json_bytes)?; + let json_value = serde_ipld_dagjson::to_vec(&ipld)?; + let value = serde_json::from_slice(&json_value)?; Ok(BlockSnapshot { cid: cid.to_string(), value, @@ -94,12 +89,14 @@ impl SnapshotBlockStore { } let snapshot = self.get_block_snapshot(&cid).await?; - let codec: IpldCodec = cid.codec().try_into()?; - >::references( - codec, - &mut Cursor::new(&snapshot.bytes), - &mut frontier, - )?; + // Compute further references: + match cid.codec() { + CODEC_DAG_CBOR => serde_ipld_dagcbor::from_slice::(&snapshot.bytes)? + .references(&mut frontier), + CODEC_DAG_PB => ipld_dagpb::links(&snapshot.bytes, &mut frontier)?, + CODEC_RAW => {} + other => unimplemented!("unimplemented codec: {other}"), + }; snapshots.push(snapshot); } @@ -111,33 +108,20 @@ impl SnapshotBlockStore { } } -impl BlockStore for SnapshotBlockStore { - #[inline] - async fn get_block(&self, cid: &Cid) -> Result { - self.inner.get_block(cid).await - } - - #[inline] - async fn put_block( +impl Blockstore for SnapshotBlockStore { + async fn get( &self, - bytes: impl Into + CondSend, - codec: u64, - ) -> Result { - self.inner.put_block(bytes, codec).await + cid: &cid::CidGeneric, + ) -> blockstore::Result>> { + self.inner.get(cid).await } - #[inline] - async fn put_block_keyed( + async fn put_keyed( &self, - cid: Cid, - bytes: impl Into + CondSend, - ) -> Result<(), BlockStoreError> { - self.inner.put_block_keyed(cid, bytes).await - } - - #[inline] - async fn has_block(&self, cid: &Cid) -> Result { - self.inner.has_block(cid).await + cid: &cid::CidGeneric, + data: &[u8], + ) -> blockstore::Result<()> { + self.inner.put_keyed(cid, data).await } } diff --git a/wnfs-hamt/Cargo.toml b/wnfs-hamt/Cargo.toml index 55309eaf..5ee3b799 100644 --- a/wnfs-hamt/Cargo.toml +++ b/wnfs-hamt/Cargo.toml @@ -27,7 +27,6 @@ chrono = { version = "0.4.23", default-features = false, features = ["clock", "s either = "1.8" futures = "0.3" insta = { version = "1.30", features = ["json"] } -libipld = { version = "0.16", features = ["dag-cbor", "derive", "serde-codec"] } log = { version = "0.4", optional = true } multihash = "0.18" once_cell = "1.16" diff --git a/wnfs-hamt/src/diff.rs b/wnfs-hamt/src/diff.rs index eb0f4f83..1ae6a64b 100644 --- a/wnfs-hamt/src/diff.rs +++ b/wnfs-hamt/src/diff.rs @@ -5,8 +5,9 @@ use async_recursion::async_recursion; use serde::{de::DeserializeOwned, Serialize}; use std::{collections::HashMap, hash::Hash, mem}; use wnfs_common::{ + blockstore::Blockstore, utils::{Arc, CondSync}, - BlockStore, Link, Storable, + Link, Storable, }; //-------------------------------------------------------------------------------------------------- @@ -67,11 +68,11 @@ impl KeyValueChange { /// ``` /// use std::sync::Arc; /// use wnfs_hamt::{Node, Pair, diff}; -/// use wnfs_common::{Link, MemoryBlockStore}; +/// use wnfs_common::{Link, MemoryBlockstore}; /// /// #[async_std::main] /// async fn main() { -/// let store = &MemoryBlockStore::new(); +/// let store = &InMemoryBlockstore::<64>::new(); /// let main_node = &mut Arc::new(Node::<[u8; 4], String>::default()); /// for i in 0u32..3 { /// main_node @@ -101,7 +102,7 @@ impl KeyValueChange { pub async fn diff( main_link: Link>>, other_link: Link>>, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> where K: Storable + Clone + Eq + Hash + AsRef<[u8]> + CondSync, @@ -119,7 +120,7 @@ pub async fn diff_helper( main_link: Link>>, other_link: Link>>, depth: usize, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> where K: Storable + Clone + Eq + Hash + AsRef<[u8]> + CondSync, @@ -195,7 +196,7 @@ where async fn generate_add_or_remove_changes( node_pointer: &Pointer, r#type: ChangeType, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> where K: Storable + Clone + Eq + Hash + AsRef<[u8]> + CondSync, @@ -237,7 +238,7 @@ async fn pointers_diff( main_pointer: Pointer, other_pointer: Pointer, depth: usize, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> where K: Storable + Clone + Eq + Hash + AsRef<[u8]> + CondSync, @@ -309,7 +310,7 @@ where async fn create_node_from_pairs( values: Vec>, depth: usize, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> where K: Storable + Clone + Eq + Hash + AsRef<[u8]> + CondSync, @@ -336,7 +337,7 @@ mod tests { use super::{ChangeType::*, *}; use helper::*; use std::collections::BTreeSet; - use wnfs_common::MemoryBlockStore; + use wnfs_common::blockstore::InMemoryBlockstore; mod helper { use crate::Hasher; @@ -368,7 +369,7 @@ mod tests { #[async_std::test] async fn can_diff_main_node_with_added_removed_pairs() { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let main_node = &mut Arc::new(Node::<[u8; 4], String>::default()); for i in 0u32..3 { @@ -439,7 +440,7 @@ mod tests { #[async_std::test] async fn can_diff_main_node_with_no_changes() { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let main_node = &mut Arc::new(Node::<_, _>::default()); for i in 0_u32..3 { @@ -470,7 +471,7 @@ mod tests { #[async_std::test] async fn can_diff_nodes_with_different_structure_and_modified_changes() { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); // A node that adds the first 3 pairs of HASH_KV_PAIRS. let other_node = &mut Arc::new(Node::<_, _, MockHasher>::default()); @@ -608,7 +609,7 @@ mod proptests { use proptest::{prop_assert, prop_assert_eq}; use std::collections::HashSet; use test_strategy::proptest; - use wnfs_common::{utils::Arc, Link, MemoryBlockStore}; + use wnfs_common::{blockstore::InMemoryBlockstore, utils::Arc, Link}; #[proptest(cases = 100, max_shrink_iters = 4000)] fn diff_correspondence( @@ -618,7 +619,7 @@ mod proptests { ), ) { task::block_on(async { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let (ops, strategy_changes) = ops_changes; let other_node = &mut strategies::node_from_operations(&ops, store).await.unwrap(); @@ -658,7 +659,7 @@ mod proptests { #[strategy(generate_kvs("[a-z0-9]{1,3}", 0u64..1000, 0..100))] kvs2: Vec<(String, u64)>, ) { task::block_on(async { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let node1 = strategies::node_from_kvs(kvs1, store).await.unwrap(); let node2 = strategies::node_from_kvs(kvs2, store).await.unwrap(); @@ -683,7 +684,7 @@ mod proptests { #[strategy(generate_kvs("[a-z0-9]{1,3}", 0u64..1000, 0..100))] kvs2: Vec<(String, u64)>, ) { task::block_on(async { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let node1 = strategies::node_from_kvs(kvs1, store).await.unwrap(); let node2 = strategies::node_from_kvs(kvs2, store).await.unwrap(); diff --git a/wnfs-hamt/src/hamt.rs b/wnfs-hamt/src/hamt.rs index 2211c96f..febc1a72 100644 --- a/wnfs-hamt/src/hamt.rs +++ b/wnfs-hamt/src/hamt.rs @@ -1,13 +1,14 @@ use super::{KeyValueChange, Node, HAMT_VERSION}; use crate::{serializable::HamtSerializable, Hasher}; use anyhow::Result; -use libipld::Cid; use semver::Version; use serde::{de::DeserializeOwned, Serialize}; use std::hash::Hash; use wnfs_common::{ + blockstore::Blockstore, + ipld_core::cid::Cid, utils::{Arc, CondSync}, - BlockStore, Link, Storable, + Link, Storable, }; //-------------------------------------------------------------------------------------------------- @@ -111,7 +112,7 @@ impl Hamt { pub async fn diff( &self, other: &Self, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> where K: Storable + Clone + Eq + Hash + AsRef<[u8]>, @@ -138,7 +139,7 @@ where { type Serializable = HamtSerializable; - async fn to_serializable(&self, store: &impl BlockStore) -> Result { + async fn to_serializable(&self, store: &impl Blockstore) -> Result { Ok(HamtSerializable { root: self.root.to_serializable(store).await?, version: self.version.clone(), @@ -183,11 +184,11 @@ where #[cfg(test)] mod tests { use super::*; - use wnfs_common::MemoryBlockStore; + use wnfs_common::blockstore::InMemoryBlockstore; #[async_std::test] async fn hamt_can_encode_decode_as_cbor() { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let root = Arc::new(Node::default()); let hamt: Hamt = Hamt::with_root(root); diff --git a/wnfs-hamt/src/merge.rs b/wnfs-hamt/src/merge.rs index f0b49c52..d0bf1b65 100644 --- a/wnfs-hamt/src/merge.rs +++ b/wnfs-hamt/src/merge.rs @@ -4,8 +4,9 @@ use anyhow::Result; use serde::{de::DeserializeOwned, Serialize}; use std::hash::Hash; use wnfs_common::{ + blockstore::Blockstore, utils::{Arc, CondSync}, - BlockStore, Link, Storable, + Link, Storable, }; //-------------------------------------------------------------------------------------------------- @@ -17,7 +18,7 @@ pub async fn merge( main_link: Link>>, other_link: Link>>, f: impl Fn(&V, &V) -> Result, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> where K: Storable + Eq + Clone + CondSync + Hash + AsRef<[u8]>, @@ -72,7 +73,7 @@ mod proptests { use proptest::prop_assert_eq; use std::cmp; use test_strategy::proptest; - use wnfs_common::{utils::Arc, Link, MemoryBlockStore}; + use wnfs_common::{blockstore::InMemoryBlockstore, utils::Arc, Link}; #[proptest(cases = 100)] fn merge_associativity( @@ -81,7 +82,7 @@ mod proptests { #[strategy(generate_kvs("[a-z0-9]{1,3}", 0u64..1000, 0..100))] kvs3: Vec<(String, u64)>, ) { task::block_on(async { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let node1 = strategies::node_from_kvs(kvs1, store).await.unwrap(); let node2 = strategies::node_from_kvs(kvs2, store).await.unwrap(); @@ -138,7 +139,7 @@ mod proptests { #[strategy(generate_kvs("[a-z0-9]{1,3}", 0u64..1000, 0..100))] kvs2: Vec<(String, u64)>, ) { task::block_on(async { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let node1 = strategies::node_from_kvs(kvs1, store).await.unwrap(); let node2 = strategies::node_from_kvs(kvs2, store).await.unwrap(); @@ -172,7 +173,7 @@ mod proptests { #[strategy(generate_kvs("[a-z0-9]{1,3}", 0u64..1000, 0..100))] kvs2: Vec<(String, u64)>, ) { task::block_on(async { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let node1 = strategies::node_from_kvs(kvs1, store).await.unwrap(); let node2 = strategies::node_from_kvs(kvs2, store).await.unwrap(); diff --git a/wnfs-hamt/src/node.rs b/wnfs-hamt/src/node.rs index 4af93444..2dbe78ce 100644 --- a/wnfs-hamt/src/node.rs +++ b/wnfs-hamt/src/node.rs @@ -9,7 +9,6 @@ use async_once_cell::OnceCell; use async_recursion::async_recursion; use bitvec::array::BitArray; use either::{Either, Either::*}; -use libipld::Cid; #[cfg(feature = "log")] use log::debug; use serde::{de::DeserializeOwned, Serialize}; @@ -21,8 +20,10 @@ use std::{ marker::PhantomData, }; use wnfs_common::{ + blockstore::Blockstore, + ipld_core::cid::Cid, utils::{boxed_fut, Arc, BoxFuture, CondSend, CondSync}, - BlockStore, HashOutput, Link, Storable, + HashOutput, Link, Storable, }; //-------------------------------------------------------------------------------------------------- @@ -86,7 +87,7 @@ where /// assert_eq!(node.get(&String::from("key"), store).await.unwrap(), Some(&42)); /// } /// ``` - pub async fn set(self: &mut Arc, key: K, value: V, store: &impl BlockStore) -> Result<()> + pub async fn set(self: &mut Arc, key: K, value: V, store: &impl Blockstore) -> Result<()> where K: Storable + AsRef<[u8]> + Clone, V: Storable + Clone, @@ -120,7 +121,7 @@ where /// assert_eq!(node.get(&String::from("key"), store).await.unwrap(), Some(&42)); /// } /// ``` - pub async fn get<'a>(&'a self, key: &K, store: &impl BlockStore) -> Result> + pub async fn get<'a>(&'a self, key: &K, store: &impl Blockstore) -> Result> where K: Storable + AsRef<[u8]>, V: Storable, @@ -165,7 +166,7 @@ where pub async fn get_mut<'a>( self: &'a mut Arc, key: &K, - store: &'a impl BlockStore, + store: &'a impl Blockstore, ) -> Result> where K: Storable + AsRef<[u8]> + Clone, @@ -209,7 +210,7 @@ where pub async fn remove( self: &mut Arc, key: &K, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> where K: Storable + AsRef<[u8]> + Clone, @@ -248,7 +249,7 @@ where pub async fn get_by_hash<'a>( &'a self, hash: &HashOutput, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> where K: Storable + AsRef<[u8]>, @@ -292,7 +293,7 @@ where pub async fn remove_by_hash( self: &mut Arc, hash: &HashOutput, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> where K: Storable + AsRef<[u8]> + Clone, @@ -346,7 +347,7 @@ where hashnibbles: &'a mut HashNibbles, key: K, value: V, - store: &'a impl BlockStore, + store: &'a impl Blockstore, ) -> BoxFuture<'a, Result<()>> where K: Storable + Clone + AsRef<[u8]> + 'a, @@ -429,7 +430,7 @@ where pub async fn get_value<'a>( &'a self, hashnibbles: &mut HashNibbles, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> where K: Storable + AsRef<[u8]>, @@ -463,7 +464,7 @@ where pub async fn get_value_mut<'a>( self: &'a mut Arc, hashnibbles: &mut HashNibbles, - store: &'a impl BlockStore, + store: &'a impl Blockstore, ) -> Result>> where K: Storable + AsRef<[u8]> + Clone, @@ -498,7 +499,7 @@ where pub fn remove_value<'a>( self: &'a mut Arc, hashnibbles: &'a mut HashNibbles, - store: &'a impl BlockStore, + store: &'a impl Blockstore, ) -> BoxFuture<'a, Result>>> where K: Storable + AsRef<[u8]> + Clone + 'a, @@ -603,7 +604,7 @@ where /// ``` #[cfg_attr(not(target_arch = "wasm32"), async_recursion)] #[cfg_attr(target_arch = "wasm32", async_recursion(?Send))] - pub async fn flat_map(&self, f: &F, store: &impl BlockStore) -> Result> + pub async fn flat_map(&self, f: &F, store: &impl Blockstore) -> Result> where F: Fn(&Pair) -> Result + CondSync, K: Storable + AsRef<[u8]>, @@ -663,7 +664,7 @@ where pub async fn get_node_at<'a>( &'a self, hashprefix: &HashPrefix, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result, &'a Arc>>> where K: Storable + AsRef<[u8]>, @@ -680,7 +681,7 @@ where &'a self, hashprefix: &HashPrefix, index: u8, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result, &'a Arc>>> where K: Storable + AsRef<[u8]>, @@ -741,7 +742,7 @@ where /// assert_eq!(map.len(), 100); /// } /// ``` - pub async fn to_hashmap(&self, store: &B) -> Result> + pub async fn to_hashmap(&self, store: &impl Blockstore) -> Result> where K: Storable + AsRef<[u8]> + Clone + Eq + Hash, V: Storable + Clone, @@ -847,7 +848,7 @@ where { type Serializable = NodeSerializable; - async fn to_serializable(&self, store: &impl BlockStore) -> Result { + async fn to_serializable(&self, store: &impl Blockstore) -> Result { let bitmask = ByteArray::from(self.bitmask.into_inner()); let mut pointers = Vec::with_capacity(self.pointers.len()); @@ -902,7 +903,7 @@ where mod tests { use super::*; use helper::*; - use wnfs_common::{utils, MemoryBlockStore}; + use wnfs_common::{blockstore::InMemoryBlockstore, utils}; mod helper { use crate::Hasher; @@ -933,7 +934,7 @@ mod tests { #[async_std::test] async fn get_value_fetches_deeply_linked_value() { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); // Insert 4 values to trigger the creation of a linked node. let working_node = &mut Arc::new(Node::::default()); @@ -956,7 +957,7 @@ mod tests { #[async_std::test] async fn remove_value_canonicalizes_linked_node() { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); // Insert 4 values to trigger the creation of a linked node. let working_node = &mut Arc::new(Node::::default()); @@ -995,7 +996,7 @@ mod tests { #[async_std::test] async fn set_value_splits_when_bucket_threshold_reached() { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); // Insert 3 values into the HAMT. let working_node = &mut Arc::new(Node::::default()); @@ -1040,7 +1041,7 @@ mod tests { #[async_std::test] async fn get_value_index_gets_correct_index() { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let hash_expected_idx_samples = [ (&[0x00], 0), (&[0x20], 1), @@ -1087,7 +1088,7 @@ mod tests { #[async_std::test] async fn node_can_insert_pair_and_retrieve() { - let store = MemoryBlockStore::default(); + let store = InMemoryBlockstore::<64>::new(); let node = &mut Arc::new(Node::::default()); node.set("pill".into(), (10, 0.315), &store).await.unwrap(); @@ -1103,7 +1104,7 @@ mod tests { let insert_key: String = "GL59 Tg4phDb bv".into(); let remove_key: String = "hK i3b4V4152EPOdA".into(); - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let node0: &mut Arc> = &mut Arc::new(Node::default()); node0.set(insert_key.clone(), 0, store).await.unwrap(); @@ -1114,7 +1115,7 @@ mod tests { #[async_std::test] async fn node_history_independence_regression() { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let node1: &mut Arc> = &mut Arc::new(Node::default()); let node2: &mut Arc> = &mut Arc::new(Node::default()); @@ -1141,7 +1142,7 @@ mod tests { #[async_std::test] async fn can_map_over_leaf_nodes() { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let node = &mut Arc::new(Node::<[u8; 4], String>::default()); for i in 0..99_u32 { @@ -1160,7 +1161,7 @@ mod tests { #[async_std::test] async fn can_fetch_node_at_hashprefix() { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let node = &mut Arc::new(Node::::default()); for (digest, kv) in HASH_KV_PAIRS.iter() { @@ -1185,7 +1186,7 @@ mod tests { #[async_std::test] async fn can_generate_hashmap_from_node() { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let node = &mut Arc::new(Node::<[u8; 4], String>::default()); const NUM_VALUES: u32 = 1000; @@ -1211,7 +1212,7 @@ mod proptests { }; use proptest::prelude::*; use test_strategy::proptest; - use wnfs_common::MemoryBlockStore; + use wnfs_common::blockstore::InMemoryBlockstore; fn small_key() -> impl Strategy { (0..1000).prop_map(|i| format!("key {i}")) @@ -1227,7 +1228,7 @@ mod proptests { #[strategy(0..1000u64)] value: u64, ) { async_std::task::block_on(async move { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let node = &mut node_from_operations(&operations, store).await.unwrap(); node.set(key.clone(), value, store).await.unwrap(); @@ -1250,7 +1251,7 @@ mod proptests { #[strategy(small_key())] key: String, ) { async_std::task::block_on(async move { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let node = &mut node_from_operations(&operations, store).await.unwrap(); node.remove(&key, store).await.unwrap(); @@ -1272,7 +1273,7 @@ mod proptests { >, ) { async_std::task::block_on(async move { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let node = node_from_operations(&operations, store).await.unwrap(); let node_cid = node.store(store).await.unwrap(); @@ -1293,7 +1294,7 @@ mod proptests { async_std::task::block_on(async move { let (original, shuffled) = pair; - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let node1 = node_from_operations(&original, store).await.unwrap(); let node2 = node_from_operations(&shuffled, store).await.unwrap(); @@ -1330,7 +1331,7 @@ mod proptests { >, ) { async_std::task::block_on(async move { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let node = node_from_operations(&operations, store).await.unwrap(); let map = HashMap::from(&operations); diff --git a/wnfs-hamt/src/pointer.rs b/wnfs-hamt/src/pointer.rs index 21181dd2..fe7bb126 100644 --- a/wnfs-hamt/src/pointer.rs +++ b/wnfs-hamt/src/pointer.rs @@ -1,12 +1,13 @@ use super::{error::HamtError, hash::Hasher, Node, HAMT_VALUES_BUCKET_SIZE}; use crate::serializable::PointerSerializable; use anyhow::Result; -use libipld::Cid; use serde::{de::DeserializeOwned, Serialize}; use std::fmt::Debug; use wnfs_common::{ + blockstore::Blockstore, + ipld_core::cid::Cid, utils::{error, Arc, CondSync}, - BlockStore, Link, Storable, + Link, Storable, }; //-------------------------------------------------------------------------------------------------- @@ -62,7 +63,7 @@ impl Pair { impl Pointer { /// Converts a Link pointer to a canonical form to ensure consistent tree representation after deletes. - pub async fn canonicalize(self, store: &impl BlockStore) -> Result> + pub async fn canonicalize(self, store: &impl Blockstore) -> Result> where K: Storable + Clone + AsRef<[u8]>, V: Storable + Clone, @@ -119,7 +120,7 @@ where { type Serializable = PointerSerializable; - async fn to_serializable(&self, store: &impl BlockStore) -> Result { + async fn to_serializable(&self, store: &impl Blockstore) -> Result { Ok(match self { Pointer::Values(values) => { let mut serializables = Vec::with_capacity(values.len()); @@ -161,7 +162,7 @@ where { type Serializable = (K::Serializable, V::Serializable); - async fn to_serializable(&self, store: &impl BlockStore) -> Result { + async fn to_serializable(&self, store: &impl Blockstore) -> Result { let key = self.key.to_serializable(store).await?; let value = self.value.to_serializable(store).await?; Ok((key, value)) @@ -227,11 +228,11 @@ where mod tests { use super::*; use testresult::TestResult; - use wnfs_common::MemoryBlockStore; + use wnfs_common::blockstore::InMemoryBlockstore; #[async_std::test] async fn pointer_can_encode_decode_as_cbor() -> TestResult { - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let pointer: Pointer = Pointer::Values(vec![ Pair { key: "James".into(), diff --git a/wnfs-hamt/src/serializable.rs b/wnfs-hamt/src/serializable.rs index 919b318d..d3a006d5 100644 --- a/wnfs-hamt/src/serializable.rs +++ b/wnfs-hamt/src/serializable.rs @@ -1,16 +1,8 @@ use crate::constants::HAMT_BITMASK_BYTE_SIZE; -use libipld::{ - cid::serde::{BytesToCidVisitor, CID_SERDE_PRIVATE_IDENTIFIER}, - Cid, -}; use semver::Version; -use serde::{ - de::{SeqAccess, Visitor}, - Deserialize, Deserializer, Serialize, Serializer, -}; +use serde::{Deserialize, Serialize}; use serde_byte_array::ByteArray; -use serde_bytes::ByteBuf; -use std::marker::PhantomData; +use wnfs_common::ipld_core::cid::Cid; //-------------------------------------------------------------------------------------------------- // Type Definitions @@ -29,64 +21,12 @@ pub struct NodeSerializable( pub(crate) Vec>, ); -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub(crate) enum PointerSerializable { Values(Vec<(K, V)>), Link(Cid), } -//-------------------------------------------------------------------------------------------------- -// Implementations -//-------------------------------------------------------------------------------------------------- - -impl Serialize for PointerSerializable { - fn serialize(&self, serializer: S) -> Result { - match *self { - Self::Values(ref vec) => vec.serialize(serializer), - Self::Link(ref cid) => { - let value = ByteBuf::from(cid.to_bytes()); - serializer.serialize_newtype_struct(CID_SERDE_PRIVATE_IDENTIFIER, &value) - } - } - } -} - -impl<'de, K: Deserialize<'de>, V: Deserialize<'de>> Deserialize<'de> for PointerSerializable { - fn deserialize>(deserializer: D) -> Result { - struct PointerVisitor(PhantomData<(K, V)>); - - impl<'de, K: Deserialize<'de>, V: Deserialize<'de>> Visitor<'de> for PointerVisitor { - type Value = PointerSerializable; - - fn expecting(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - write!( - fmt, - "a valid PointerSerializable represented as CID bytes or as a sequence of tuples of keys and values" - ) - } - - fn visit_newtype_struct>( - self, - deserializer: D, - ) -> Result { - let cid = deserializer.deserialize_bytes(BytesToCidVisitor)?; - Ok(PointerSerializable::Link(cid)) - } - - fn visit_seq>(self, mut seq: A) -> Result { - let mut values = Vec::new(); - while let Some(elem) = seq.next_element::<(K, V)>()? { - values.push(elem); - } - Ok(PointerSerializable::Values(values)) - } - } - - let visitor = PointerVisitor(PhantomData); - deserializer.deserialize_any(visitor) - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/wnfs-hamt/src/strategies/changes.rs b/wnfs-hamt/src/strategies/changes.rs index cb77c1b5..dfa2adb7 100644 --- a/wnfs-hamt/src/strategies/changes.rs +++ b/wnfs-hamt/src/strategies/changes.rs @@ -6,8 +6,9 @@ use proptest::{collection::vec, strategy::Strategy}; use serde::{de::DeserializeOwned, Serialize}; use std::{collections::HashMap, fmt::Debug}; use wnfs_common::{ + blockstore::Blockstore, utils::{Arc, CondSync}, - BlockStore, Storable, + Storable, }; //-------------------------------------------------------------------------------------------------- @@ -58,7 +59,7 @@ pub(crate) fn generate_ops_and_changes( pub(crate) async fn apply_changes( node: &mut Arc>, changes: &Vec>, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result<()> where K: Storable + Debug + Clone + AsRef<[u8]>, @@ -86,7 +87,7 @@ where pub(crate) async fn prepare_node( node: &mut Arc>, changes: &Vec>, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result<()> where K: Storable + Debug + Clone + AsRef<[u8]>, diff --git a/wnfs-hamt/src/strategies/kv.rs b/wnfs-hamt/src/strategies/kv.rs index f56c3252..3d973521 100644 --- a/wnfs-hamt/src/strategies/kv.rs +++ b/wnfs-hamt/src/strategies/kv.rs @@ -4,8 +4,9 @@ use proptest::{collection::vec, sample::SizeRange, strategy::Strategy}; use serde::{de::DeserializeOwned, Serialize}; use std::{collections::HashMap, fmt::Debug, hash::Hash}; use wnfs_common::{ + blockstore::Blockstore, utils::{Arc, CondSync}, - BlockStore, Storable, + Storable, }; //-------------------------------------------------------------------------------------------------- @@ -31,7 +32,7 @@ where pub async fn node_from_kvs( pairs: Vec<(K, V)>, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> where K: Storable + Clone + Debug + AsRef<[u8]> + CondSync, diff --git a/wnfs-hamt/src/strategies/operations.rs b/wnfs-hamt/src/strategies/operations.rs index ed3da7fc..206a182b 100644 --- a/wnfs-hamt/src/strategies/operations.rs +++ b/wnfs-hamt/src/strategies/operations.rs @@ -4,8 +4,9 @@ use proptest::{collection::*, prelude::*, strategy::Shuffleable}; use serde::{de::DeserializeOwned, Serialize}; use std::{collections::HashMap, fmt::Debug, hash::Hash}; use wnfs_common::{ + blockstore::Blockstore, utils::{Arc, CondSync}, - BlockStore, Storable, + Storable, }; //-------------------------------------------------------------------------------------------------- @@ -185,7 +186,7 @@ where /// ``` pub async fn node_from_operations( operations: &Operations, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> where K: Storable + Clone + Debug + CondSync + AsRef<[u8]>, diff --git a/wnfs-nameaccumulator/Cargo.toml b/wnfs-nameaccumulator/Cargo.toml index 2992f92f..268a5191 100644 --- a/wnfs-nameaccumulator/Cargo.toml +++ b/wnfs-nameaccumulator/Cargo.toml @@ -39,6 +39,7 @@ insta = { version = "1.31.0", features = ["json"] } proptest = "1.1" rand = "0.8.5" rand_chacha = "0.3" +serde_ipld_dagcbor = "0.6.1" serde_json = "1.0.103" test-strategy = "0.3" wnfs-common = { path = "../wnfs-common", features = ["test_utils"] } diff --git a/wnfs-nameaccumulator/src/name.rs b/wnfs-nameaccumulator/src/name.rs index 9fd1c0b8..14039c86 100644 --- a/wnfs-nameaccumulator/src/name.rs +++ b/wnfs-nameaccumulator/src/name.rs @@ -9,13 +9,12 @@ use crate::{ traits::Big, }; use anyhow::Result; -use libipld::Cid; use num_traits::{One, Zero}; use once_cell::sync::OnceCell; use rand_core::CryptoRngCore; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::{hash::Hash, str::FromStr}; -use wnfs_common::{BlockStore, Storable}; +use wnfs_common::Storable; /// The domain separation string for deriving the l hash in the PoKE* protocol. const L_HASH_DSI: &str = "wnfs/1.0/PoKE*/l 128-bit hash derivation"; @@ -448,13 +447,13 @@ macro_rules! impl_storable { async fn to_serializable( &self, - _store: &impl BlockStore, + _store: &impl ::wnfs_common::blockstore::Blockstore, ) -> Result { Ok(self.clone()) } async fn from_serializable( - _: Option<&Cid>, + _: Option<&::wnfs_common::ipld_core::cid::Cid>, serializable: Self::Serializable, ) -> Result { Ok(serializable) @@ -640,15 +639,14 @@ mod tests { use rand_chacha::ChaCha12Rng; use std::io::Cursor; use test_strategy::proptest; - use wnfs_common::{decode, encode}; #[test] fn name_segment_serialize_roundtrip() { let rng = &mut thread_rng(); let segment = NameSegment::new(rng); - let bytes = encode(&segment, DagCborCodec).unwrap(); - let segment_back: NameSegment = decode(&bytes, DagCborCodec).unwrap(); + let bytes = serde_ipld_dagcbor::to_vec(&segment).unwrap(); + let segment_back: NameSegment = serde_ipld_dagcbor::from_slice(&bytes).unwrap(); assert_eq!(segment_back, segment); } @@ -818,6 +816,7 @@ mod tests { #[cfg(test)] mod snapshot_tests { use super::*; + #[allow(unused_imports)] use crate::BigNumDig; use rand_chacha::ChaCha12Rng; use rand_core::SeedableRng; diff --git a/wnfs-unixfs-file/Cargo.toml b/wnfs-unixfs-file/Cargo.toml index 98682fd3..daf5d3a7 100644 --- a/wnfs-unixfs-file/Cargo.toml +++ b/wnfs-unixfs-file/Cargo.toml @@ -22,7 +22,6 @@ anyhow = "1.0" async-stream = "0.3" bytes = "1.5" futures = "0.3" -libipld = { version = "0.16", features = [] } num_enum = "0.5" proptest = { version = "1.1", optional = true } prost = "0.12" diff --git a/wnfs-unixfs-file/src/balanced_tree.rs b/wnfs-unixfs-file/src/balanced_tree.rs index 5515e968..f75d567c 100644 --- a/wnfs-unixfs-file/src/balanced_tree.rs +++ b/wnfs-unixfs-file/src/balanced_tree.rs @@ -8,9 +8,8 @@ use anyhow::Result; use async_stream::try_stream; use bytes::Bytes; use futures::{Stream, StreamExt}; -use libipld::Cid; use std::collections::VecDeque; -use wnfs_common::{utils::CondSend, BlockStore}; +use wnfs_common::{blockstore::Blockstore, ipld_core::cid::Cid, utils::CondSend}; /// Default degree number for balanced tree, taken from unixfs specs /// @@ -36,7 +35,7 @@ impl TreeBuilder { pub fn stream_tree<'a>( &self, chunks: impl Stream> + CondSend + 'a, - store: &'a impl BlockStore, + store: &'a impl Blockstore, ) -> impl Stream> + 'a { match self { TreeBuilder::Balanced { degree } => stream_balanced_tree(chunks, *degree, store), @@ -53,7 +52,7 @@ struct LinkInfo { fn stream_balanced_tree<'a>( in_stream: impl Stream> + CondSend + 'a, degree: usize, - store: &'a impl BlockStore, + store: &'a impl Blockstore, ) -> impl Stream> + 'a { try_stream! { // degree = 8 @@ -234,7 +233,7 @@ impl TreeNode { mod tests { use super::*; use bytes::BytesMut; - use wnfs_common::MemoryBlockStore; + use wnfs_common::blockstore::InMemoryBlockstore; // chunks are just a single usize integer const CHUNK_SIZE: u64 = std::mem::size_of::() as u64; @@ -244,7 +243,7 @@ mod tests { } async fn build_expect_tree(num_chunks: usize, degree: usize) -> Vec> { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let chunks = test_chunk_stream(num_chunks); tokio::pin!(chunks); let mut tree = vec![vec![]]; @@ -338,7 +337,7 @@ mod tests { build_expect_vec_from_tree(tree, num_chunks, degree).await } - async fn make_leaf(data: usize, store: &impl BlockStore) -> (Cid, Block, LinkInfo) { + async fn make_leaf(data: usize, store: &impl Blockstore) -> (Cid, Block, LinkInfo) { let (block, link_info) = TreeNode::Leaf(BytesMut::from(&data.to_be_bytes()[..]).freeze()) .encode() .unwrap(); @@ -348,7 +347,7 @@ mod tests { async fn make_stem( links: Vec<(Cid, LinkInfo)>, - store: &impl BlockStore, + store: &impl Blockstore, ) -> (Cid, Block, LinkInfo) { let (block, link_info) = TreeNode::Stem(links).encode().unwrap(); let cid = block.store(store).await.unwrap(); @@ -357,7 +356,7 @@ mod tests { #[tokio::test] async fn test_build_expect() { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); // manually build tree made of 7 chunks (11 total nodes) let (leaf_0_cid, leaf_0, len_0) = make_leaf(0, store).await; let (leaf_1_cid, leaf_1, len_1) = make_leaf(1, store).await; @@ -483,7 +482,7 @@ mod tests { #[tokio::test] async fn balanced_tree_test_leaf() { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let num_chunks = 1; let expect = build_expect(num_chunks, 3).await; let got = stream_balanced_tree(test_chunk_stream(1), 3, store); @@ -493,7 +492,7 @@ mod tests { #[tokio::test] async fn balanced_tree_test_height_one() { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let num_chunks = 3; let degrees = 3; let expect = build_expect(num_chunks, degrees).await; @@ -504,7 +503,7 @@ mod tests { #[tokio::test] async fn balanced_tree_test_height_two_full() { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let degrees = 3; let num_chunks = 9; let expect = build_expect(num_chunks, degrees).await; @@ -515,7 +514,7 @@ mod tests { #[tokio::test] async fn balanced_tree_test_height_two_not_full() { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let degrees = 3; let num_chunks = 10; let expect = build_expect(num_chunks, degrees).await; @@ -526,7 +525,7 @@ mod tests { #[tokio::test] async fn balanced_tree_test_height_three() { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let num_chunks = 125; let degrees = 5; let expect = build_expect(num_chunks, degrees).await; @@ -537,7 +536,7 @@ mod tests { #[tokio::test] async fn balanced_tree_test_large() { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let num_chunks = 780; let degrees = 11; let expect = build_expect(num_chunks, degrees).await; diff --git a/wnfs-unixfs-file/src/builder.rs b/wnfs-unixfs-file/src/builder.rs index 37519b3d..886c265b 100644 --- a/wnfs-unixfs-file/src/builder.rs +++ b/wnfs-unixfs-file/src/builder.rs @@ -7,11 +7,10 @@ use crate::{ use anyhow::{anyhow, ensure, Result}; use bytes::Bytes; use futures::{Stream, TryStreamExt}; -use libipld::Cid; use prost::Message; use std::fmt::Debug; use tokio::io::AsyncRead; -use wnfs_common::{utils::CondSend, BlockStore}; +use wnfs_common::{blockstore::Blockstore, ipld_core::cid::Cid, utils::CondSend}; /// Representation of a constructed File. pub struct File<'a> { @@ -36,13 +35,13 @@ impl<'a> Debug for File<'a> { impl<'a> File<'a> { pub fn encode( self, - store: &'a impl BlockStore, + store: &'a impl Blockstore, ) -> Result> + '_> { let chunks = self.chunker.chunks(self.content); Ok(self.tree_builder.stream_tree(chunks, store)) } - pub async fn store(self, store: &impl BlockStore) -> Result { + pub async fn store(self, store: &impl Blockstore) -> Result { let blocks = self.encode(store)?; tokio::pin!(blocks); @@ -173,11 +172,11 @@ pub struct Config { mod tests { use super::*; use crate::chunker::DEFAULT_CHUNKS_SIZE; - use wnfs_common::MemoryBlockStore; + use wnfs_common::blockstore::InMemoryBlockstore; #[tokio::test] async fn test_builder_stream_small() -> Result<()> { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); // Add a file let bar_encoded: Vec<_> = { let bar_reader = std::io::Cursor::new(b"bar"); @@ -192,7 +191,7 @@ mod tests { #[tokio::test] async fn test_builder_stream_large() -> Result<()> { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); // Add a file let bar_encoded: Vec<_> = { let bar_reader = std::io::Cursor::new(vec![1u8; 1024 * 1024]); @@ -256,7 +255,7 @@ mod proptests { use test_strategy::proptest; use testresult::TestResult; use tokio::io::{AsyncReadExt, AsyncSeekExt}; - use wnfs_common::{MemoryBlockStore, MAX_BLOCK_SIZE}; + use wnfs_common::{blockstore::InMemoryBlockstore, MAX_BLOCK_SIZE}; fn arb_chunker() -> impl Strategy { option::of(1_000..MAX_BLOCK_SIZE).prop_map(|opt| match opt { @@ -272,7 +271,7 @@ mod proptests { #[strategy(0usize..5_000_000)] len: usize, #[strategy(arb_chunker())] chunker: ChunkerConfig, ) { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let rng = &mut ChaCha12Rng::seed_from_u64(seed); let mut data = vec![0; len]; rng.fill_bytes(&mut data); @@ -286,7 +285,7 @@ mod proptests { .store(store) .await?; - let file = UnixFsFile::load(&root_cid, store).await?; + let file = UnixFsFile::load(root_cid, store).await?; assert_eq!(file.filesize(), Some(len as u64)); let mut buffer = Vec::new(); @@ -309,7 +308,7 @@ mod proptests { #[strategy(0usize..1_000)] seek_len: usize, #[strategy(arb_chunker())] chunker: ChunkerConfig, ) { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let rng = &mut ChaCha12Rng::seed_from_u64(seed); let mut data = vec![0; len]; rng.fill_bytes(&mut data); @@ -326,7 +325,7 @@ mod proptests { .store(store) .await?; - let file = UnixFsFile::load(&root_cid, store).await?; + let file = UnixFsFile::load(root_cid, store).await?; assert_eq!(file.filesize(), Some(len as u64)); let mut buffer = vec![0; seek_len]; diff --git a/wnfs-unixfs-file/src/lib.rs b/wnfs-unixfs-file/src/lib.rs index 6a382bd9..01dc0c2e 100644 --- a/wnfs-unixfs-file/src/lib.rs +++ b/wnfs-unixfs-file/src/lib.rs @@ -5,25 +5,3 @@ pub mod codecs; pub mod protobufs; mod types; pub mod unixfs; - -use crate::codecs::Codec; -use anyhow::{bail, Result}; -use libipld::{prelude::Codec as _, Cid, Ipld, IpldCodec}; -use std::collections::BTreeSet; - -/// Extract links from the given content. -/// -/// Links will be returned as a sorted vec -pub fn parse_links(codec: Codec, bytes: &[u8]) -> Result> { - let mut cids = BTreeSet::new(); - let codec = match codec { - Codec::DagCbor => IpldCodec::DagCbor, - Codec::DagPb => IpldCodec::DagPb, - Codec::DagJson => IpldCodec::DagJson, - Codec::Raw => IpldCodec::Raw, - _ => bail!("unsupported codec {:?}", codec), - }; - codec.references::(bytes, &mut cids)?; - let links = cids.into_iter().collect(); - Ok(links) -} diff --git a/wnfs-unixfs-file/src/types.rs b/wnfs-unixfs-file/src/types.rs index a669a0c5..da823c08 100644 --- a/wnfs-unixfs-file/src/types.rs +++ b/wnfs-unixfs-file/src/types.rs @@ -1,10 +1,13 @@ -use crate::{codecs::Codec, parse_links, protobufs}; +use crate::{codecs::Codec, protobufs}; use anyhow::{anyhow, Result}; use bytes::Bytes; -use libipld::Cid; use std::{io::Cursor, pin::Pin}; use tokio::io::AsyncRead; -use wnfs_common::BlockStore; +use wnfs_common::{ + blockstore::{block::Block as _, Blockstore}, + ipld_core::cid::Cid, + Blake3Block, +}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Block { @@ -37,26 +40,11 @@ impl Block { } } - pub async fn store(&self, store: &impl BlockStore) -> Result { - Ok(store - .put_block(self.data.clone(), self.codec.into()) - .await?) - } - - /// Validate the block. Will return an error if the links are wrong. - pub fn validate(&self) -> Result<()> { - // check that the links are complete - let expected_links = parse_links(self.codec, &self.data)?; - let mut actual_links = self.links.clone(); - actual_links.sort(); - // We need to deduplicate the actual links. An example case: - // A unixfs file which is 1GB of zeros. - // In that case, a node's links will contain multiple regions that hash to the same value, - // resulting in the same hash for whole ranges. - // But the parse_links function only accumulates a set of links. - actual_links.dedup(); - anyhow::ensure!(expected_links == actual_links, "links do not match"); - Ok(()) + pub async fn store(&self, store: &impl Blockstore) -> Result { + let block = Blake3Block::new(self.codec.into(), self.data.clone()); + let cid = block.cid()?; + store.put(block).await?; + Ok(cid) } pub fn into_parts(self) -> (Codec, Bytes, Vec) { diff --git a/wnfs-unixfs-file/src/unixfs.rs b/wnfs-unixfs-file/src/unixfs.rs index 2c3f9db2..38c13ec8 100644 --- a/wnfs-unixfs-file/src/unixfs.rs +++ b/wnfs-unixfs-file/src/unixfs.rs @@ -7,7 +7,6 @@ use crate::{ use anyhow::{anyhow, bail, ensure, Result}; use bytes::Bytes; use futures::FutureExt; -use libipld::Cid; use prost::Message; use std::{ collections::VecDeque, @@ -17,8 +16,10 @@ use std::{ }; use tokio::io::{AsyncRead, AsyncSeek}; use wnfs_common::{ + blockstore::Blockstore, + ipld_core::cid::Cid, utils::{boxed_fut, BoxFuture}, - BlockStore, LoadIpld, Storable, StoreIpld, + BlockStoreError, LoadIpld, Storable, StoreIpld, }; #[derive( @@ -92,9 +93,12 @@ impl UnixFsFile { UnixFsFile::Raw(Bytes::new()) } - pub async fn load(cid: &Cid, store: &impl BlockStore) -> Result { - let block = store.get_block(cid).await?; - Self::decode(cid, block) + pub async fn load(cid: Cid, store: &impl Blockstore) -> Result { + let block = store + .get(&cid) + .await? + .ok_or_else(|| BlockStoreError::CIDNotFound(cid))?; + Self::decode(&cid, Bytes::from(block)) } pub fn decode(cid: &Cid, buf: Bytes) -> Result { @@ -204,7 +208,7 @@ impl UnixFsFile { .transpose() } - pub fn into_content_reader( + pub fn into_content_reader( self, store: &B, pos_max: Option, @@ -225,7 +229,7 @@ impl UnixFsFile { impl Storable for UnixFsFile { type Serializable = UnixFsFile; - async fn to_serializable(&self, _store: &impl BlockStore) -> Result { + async fn to_serializable(&self, _store: &impl Blockstore) -> Result { Ok(self.clone()) } @@ -251,7 +255,7 @@ impl LoadIpld for UnixFsFile { } #[derive(Debug)] -pub struct UnixFsFileReader<'a, B: BlockStore> { +pub struct UnixFsFileReader<'a, B: Blockstore> { root_node: UnixFsFile, /// Absolute position in bytes pos: usize, @@ -264,14 +268,14 @@ pub struct UnixFsFileReader<'a, B: BlockStore> { store: &'a B, } -impl<'a, B: BlockStore> UnixFsFileReader<'a, B> { +impl<'a, B: Blockstore> UnixFsFileReader<'a, B> { /// Returns the size in bytes, if known in advance. pub fn size(&self) -> Option { self.root_node.filesize() } } -impl<'a, B: BlockStore + 'a> AsyncRead for UnixFsFileReader<'a, B> { +impl<'a, B: Blockstore + 'a> AsyncRead for UnixFsFileReader<'a, B> { fn poll_read( mut self: Pin<&mut Self>, cx: &mut Context<'_>, @@ -308,7 +312,7 @@ impl<'a, B: BlockStore + 'a> AsyncRead for UnixFsFileReader<'a, B> { } } -impl<'a, B: BlockStore + 'a> AsyncSeek for UnixFsFileReader<'a, B> { +impl<'a, B: Blockstore + 'a> AsyncSeek for UnixFsFileReader<'a, B> { fn start_seek(mut self: Pin<&mut Self>, position: std::io::SeekFrom) -> std::io::Result<()> { let UnixFsFileReader { root_node, @@ -457,7 +461,7 @@ fn load_next_node<'a>( next_node_offset: usize, current_node: &mut CurrentNodeState<'a>, current_links: &mut Vec>, - store: &'a impl BlockStore, + store: &'a impl Blockstore, ) -> bool { let links = loop { if let Some(last_mut) = current_links.last_mut() { @@ -476,15 +480,9 @@ fn load_next_node<'a>( let link = links.pop_front().unwrap(); - let fut = boxed_fut(async move { - let block = store.get_block(&link.cid).await?; - let node = UnixFsFile::decode(&link.cid, block)?; - - Ok(node) - }); *current_node = CurrentNodeState::Loading { node_offset: next_node_offset, - fut, + fut: boxed_fut(UnixFsFile::load(link.cid, store)), }; true } @@ -493,7 +491,7 @@ fn load_next_node<'a>( fn poll_read_file_at<'a>( cx: &mut Context<'_>, root_node: &Node, - store: &'a impl BlockStore, + store: &'a impl Blockstore, pos: &mut usize, pos_max: Option, buf: &mut tokio::io::ReadBuf<'_>, diff --git a/wnfs/Cargo.toml b/wnfs/Cargo.toml index 3d777d26..45e7f4a5 100644 --- a/wnfs/Cargo.toml +++ b/wnfs/Cargo.toml @@ -30,7 +30,6 @@ chrono = { version = "0.4", default-features = false, features = ["clock", "std" futures = "0.3" hex = "0.4.3" insta = { version = "1.30", features = ["json"] } -libipld-core = { version = "0.16" } multihash = "0.19" once_cell = "1.16" proptest = { version = "1.1", optional = true } @@ -61,6 +60,7 @@ insta = "1.30" proptest = "1.1" rand = "0.8" rsa = "0.9" +serde_ipld_dagjson = "0.2.0" serde_json = "1.0.103" sha2 = "0.10" test-log = "0.2" diff --git a/wnfs/examples/file_variants.rs b/wnfs/examples/file_variants.rs index 52b0286b..35cfa480 100644 --- a/wnfs/examples/file_variants.rs +++ b/wnfs/examples/file_variants.rs @@ -9,12 +9,12 @@ use wnfs::private::{ forest::{hamt::HamtForest, traits::PrivateForest}, PrivateFile, PrivateForestContent, }; -use wnfs_common::MemoryBlockStore; +use wnfs_common::blockstore::InMemoryBlockstore; #[async_std::main] async fn main() -> Result<()> { // The usual in-memory testing setup for WNFS - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let rng = &mut ChaCha12Rng::from_entropy(); let forest = &mut HamtForest::new_rsa_2048(rng); diff --git a/wnfs/examples/mnemonic_based.rs b/wnfs/examples/mnemonic_based.rs index cd2088ba..5a2be7d3 100644 --- a/wnfs/examples/mnemonic_based.rs +++ b/wnfs/examples/mnemonic_based.rs @@ -7,7 +7,6 @@ use rsa::{traits::PublicKeyParts, BigUint, Oaep, RsaPrivateKey, RsaPublicKey}; use sha2::Sha256; use std::sync::Arc; use wnfs::{ - common::{BlockStore, MemoryBlockStore}, private::{ forest::{hamt::HamtForest, traits::PrivateForest}, share::{recipient, sharer}, @@ -15,6 +14,7 @@ use wnfs::{ }, public::{PublicDirectory, PublicLink}, }; +use wnfs_common::blockstore::{Blockstore, InMemoryBlockstore}; //-------------------------------------------------------------------------------------------------- // Example Code @@ -24,7 +24,7 @@ use wnfs::{ async fn main() -> Result<()> { // We use a single in-memory block store for this example. // In practice, there would actually be network transfer involved. - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); // We create a directory, write something to it and get the private forest // and the directory's access key: @@ -52,7 +52,7 @@ async fn main() -> Result<()> { Ok(()) } -async fn root_dir_setup(store: &impl BlockStore) -> Result<(Arc, AccessKey)> { +async fn root_dir_setup(store: &impl Blockstore) -> Result<(Arc, AccessKey)> { // We generate a new simple example file system: let rng = &mut ChaCha12Rng::from_entropy(); let forest = &mut HamtForest::new_trusted_rc(rng); @@ -81,7 +81,7 @@ async fn root_dir_setup(store: &impl BlockStore) -> Result<(Arc, Acc async fn setup_seeded_keypair_access( forest: &mut Arc, access_key: AccessKey, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result { // Create a random mnemonic and derive a keypair from it let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); @@ -134,7 +134,7 @@ async fn setup_seeded_keypair_access( async fn regain_access_from_mnemonic( forest: &HamtForest, mnemonic: Mnemonic, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result { // Re-derive the same private key from the seed phrase let seed = Seed::new(&mnemonic, /* optional password */ ""); diff --git a/wnfs/examples/private.rs b/wnfs/examples/private.rs index ac6c294d..66c7e5ae 100644 --- a/wnfs/examples/private.rs +++ b/wnfs/examples/private.rs @@ -3,23 +3,26 @@ use anyhow::Result; use chrono::Utc; -use libipld_core::cid::Cid; use rand_chacha::ChaCha12Rng; use rand_core::{CryptoRngCore, SeedableRng}; use wnfs::{ - common::{BlockStore, MemoryBlockStore}, nameaccumulator::AccumulatorSetup, private::{ forest::{hamt::HamtForest, traits::PrivateForest}, AccessKey, PrivateDirectory, PrivateNode, }, }; -use wnfs_common::{utils::CondSend, Storable}; +use wnfs_common::{ + blockstore::{Blockstore, InMemoryBlockstore}, + ipld_core::cid::Cid, + utils::CondSend, + Storable, +}; #[async_std::main] async fn main() -> Result<()> { // Create an in-memory block store. - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); // Create a random number generator the private filesystem can use. let rng = &mut ChaCha12Rng::from_entropy(); @@ -40,7 +43,7 @@ async fn main() -> Result<()> { } async fn create_forest_and_add_directory( - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut (impl CryptoRngCore + CondSend), ) -> Result<(Cid, AccessKey)> { // Do a trusted setup for WNFS' name accumulators diff --git a/wnfs/examples/public.rs b/wnfs/examples/public.rs index e1b4eec3..c625de78 100644 --- a/wnfs/examples/public.rs +++ b/wnfs/examples/public.rs @@ -3,12 +3,13 @@ use anyhow::Result; use chrono::Utc; -use wnfs::{common::MemoryBlockStore, public::PublicDirectory}; +use wnfs::public::PublicDirectory; +use wnfs_common::blockstore::InMemoryBlockstore; #[async_std::main] async fn main() -> Result<()> { // Create an in-memory blockstore. - let store = MemoryBlockStore::default(); + let store = InMemoryBlockstore::<64>::new(); // Create a new directory. let root_dir = &mut PublicDirectory::new_rc(Utc::now()); diff --git a/wnfs/examples/tiered_blockstores.rs b/wnfs/examples/tiered_blockstores.rs index 4839e940..747cbe96 100644 --- a/wnfs/examples/tiered_blockstores.rs +++ b/wnfs/examples/tiered_blockstores.rs @@ -4,29 +4,28 @@ //! work with high latency. use anyhow::Result; -use bytes::Bytes; use chrono::Utc; -use libipld_core::cid::Cid; use rand_chacha::ChaCha12Rng; use rand_core::SeedableRng; -use wnfs::{ - common::{BlockStore, MemoryBlockStore}, - private::{ - forest::{hamt::HamtForest, traits::PrivateForest}, - PrivateDirectory, PrivateNode, - }, +use wnfs::private::{ + forest::{hamt::HamtForest, traits::PrivateForest}, + PrivateDirectory, PrivateNode, +}; +use wnfs_common::{ + blockstore::{self, Blockstore, InMemoryBlockstore}, + ipld_core::cid::CidGeneric, + Storable, }; -use wnfs_common::{utils::CondSend, BlockStoreError, Storable}; #[async_std::main] async fn main() -> Result<()> { // Create a block store that holds all 'hot' data: - let hot_store = MemoryBlockStore::default(); + let hot_store = InMemoryBlockstore::<64>::new(); // Create a block store that holds all 'cold' data. // In reality this would probably be something that's accessible // with very high latency, but with a lot of bandwidth & storage. - let cold_store = MemoryBlockStore::default(); + let cold_store = InMemoryBlockstore::<64>::new(); // Create a random number generator for randomized encryption. let rng = &mut ChaCha12Rng::from_entropy(); @@ -90,41 +89,28 @@ async fn main() -> Result<()> { Ok(()) } -struct TieredBlockStore { +struct TieredBlockStore { hot: H, cold: C, } -impl BlockStore for TieredBlockStore { - async fn get_block(&self, cid: &Cid) -> Result { - if self.hot.has_block(cid).await? { - self.hot.get_block(cid).await +impl Blockstore for TieredBlockStore { + async fn get( + &self, + cid: &CidGeneric, + ) -> Result>, blockstore::Error> { + if self.hot.has(cid).await? { + self.hot.get(cid).await } else { - self.cold.get_block(cid).await + self.cold.get(cid).await } } - async fn put_block( - &self, - bytes: impl Into + CondSend, - codec: u64, - ) -> Result { - self.hot.put_block(bytes, codec).await - } - - async fn put_block_keyed( + async fn put_keyed( &self, - cid: Cid, - bytes: impl Into + CondSend, - ) -> Result<(), BlockStoreError> { - self.hot.put_block_keyed(cid, bytes).await - } - - async fn has_block(&self, cid: &Cid) -> Result { - if self.hot.has_block(cid).await? { - return Ok(true); - } - - self.cold.has_block(cid).await + cid: &CidGeneric, + data: &[u8], + ) -> Result<(), blockstore::Error> { + self.hot.put_keyed(cid, data).await } } diff --git a/wnfs/examples/write_proofs.rs b/wnfs/examples/write_proofs.rs index 492c4e82..45f6369d 100644 --- a/wnfs/examples/write_proofs.rs +++ b/wnfs/examples/write_proofs.rs @@ -1,11 +1,9 @@ use anyhow::Result; use chrono::Utc; -use libipld_core::cid::Cid; use rand_chacha::ChaCha12Rng; use rand_core::SeedableRng; use std::{collections::BTreeSet, sync::Arc}; use wnfs::{ - common::{BlockStore, MemoryBlockStore}, nameaccumulator::NameAccumulator, private::{ forest::{ @@ -16,14 +14,18 @@ use wnfs::{ AccessKey, PrivateDirectory, PrivateNode, }, }; -use wnfs_common::Storable; +use wnfs_common::{ + blockstore::{Blockstore, InMemoryBlockstore}, + ipld_core::cid::Cid, + Storable, +}; #[async_std::main] async fn main() -> Result<()> { // In between operations, Alice, Bob, and the persistence service would // exchange blocks via bitswap, car mirror or some other protocol. // Here we're simplifying by sharing a 'global' block store. - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); // Alice creates a private file system with some data. // She shares read access with bob by securely transferring the access_key. @@ -54,7 +56,7 @@ async fn main() -> Result<()> { /// Alice creates a directory and gives access to it out to someone else. /// The returned AccessKey gives read access and the NameAccumulator is /// supposed to be publicly signed for verifyable write access. -async fn alice_actions(store: &impl BlockStore) -> Result<(Cid, AccessKey, NameAccumulator)> { +async fn alice_actions(store: &impl Blockstore) -> Result<(Cid, AccessKey, NameAccumulator)> { let rng = &mut ChaCha12Rng::from_entropy(); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -71,7 +73,7 @@ async fn alice_actions(store: &impl BlockStore) -> Result<(Cid, AccessKey, NameA async fn bob_actions( old_forest_cid: Cid, root_dir_access: AccessKey, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result<(ForestProofs, Cid)> { let hamt_forest = HamtForest::load(&old_forest_cid, store).await?; let mut forest = ProvingHamtForest::new(Arc::new(hamt_forest)); @@ -109,7 +111,7 @@ async fn persistence_service_actions( new_forest_cid: Cid, proofs: ForestProofs, allowed_access: NameAccumulator, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result<()> { let old_forest = HamtForest::load(&old_forest_cid, store).await?; let new_forest = HamtForest::load(&new_forest_cid, store).await?; diff --git a/wnfs/src/private/directory.rs b/wnfs/src/private/directory.rs index 7f25564f..1f585f6f 100644 --- a/wnfs/src/private/directory.rs +++ b/wnfs/src/private/directory.rs @@ -7,7 +7,6 @@ use crate::{error::FsError, is_readable_wnfs_version, traits::Id, SearchResult, use anyhow::{bail, ensure, Result}; use async_once_cell::OnceCell; use chrono::{DateTime, Utc}; -use libipld_core::cid::Cid; use rand_core::CryptoRngCore; use std::{ cmp::Ordering, @@ -15,8 +14,10 @@ use std::{ fmt::Debug, }; use wnfs_common::{ + blockstore::{block::Block as _, Blockstore}, + ipld_core::cid::Cid, utils::{error, Arc, CondSend}, - BlockStore, Metadata, PathNodes, PathNodesResult, CODEC_RAW, + Blake3Block, Metadata, PathNodes, PathNodesResult, CODEC_RAW, }; use wnfs_nameaccumulator::{Name, NameSegment}; @@ -130,7 +131,7 @@ impl PrivateDirectory { parent_name: &Name, time: DateTime, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut (impl CryptoRngCore + CondSend), ) -> Result> { let dir = Arc::new(Self::new(parent_name, time, rng)); @@ -146,7 +147,7 @@ impl PrivateDirectory { path_segments: &[String], search_latest: bool, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result { use PathNodesResult::*; let mut working_node = self; @@ -231,7 +232,7 @@ impl PrivateDirectory { /// /// #[async_std::main] /// async fn main() -> Result<()> { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -252,7 +253,7 @@ impl PrivateDirectory { path_segment: &str, search_latest: bool, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { Ok(match self.content.entries.get(path_segment) { Some(private_link) => { @@ -275,7 +276,7 @@ impl PrivateDirectory { path_segment: &str, search_latest: bool, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { Ok(match self.content.entries.get_mut(path_segment) { Some(private_link) => { @@ -297,7 +298,7 @@ impl PrivateDirectory { path_segments: &[String], search_latest: bool, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> { let mut working_dir = Arc::clone(self); @@ -326,7 +327,7 @@ impl PrivateDirectory { path_segments: &[String], search_latest: bool, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { if search_latest { *self = self.clone().search_latest_reconciled(forest, store).await?; @@ -366,7 +367,7 @@ impl PrivateDirectory { time: DateTime, search_latest: bool, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut (impl CryptoRngCore + CondSend), ) -> Result<&'a mut Self> { match self @@ -504,7 +505,7 @@ impl PrivateDirectory { /// /// #[async_std::main] /// async fn main() { - /// let store = &MemoryBlockStore::default(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -527,7 +528,7 @@ impl PrivateDirectory { path_segments: &[String], search_latest: bool, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { let Some((tail, path)) = path_segments.split_last() else { return Ok(None); @@ -559,7 +560,7 @@ impl PrivateDirectory { /// /// #[async_std::main] /// async fn main() -> Result<()> { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -592,7 +593,7 @@ impl PrivateDirectory { path_segments: &[String], search_latest: bool, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { let (path, filename) = crate::utils::split_last(path_segments)?; match self @@ -631,7 +632,7 @@ impl PrivateDirectory { /// }; /// #[async_std::main] /// async fn main() -> Result<()> { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -676,7 +677,7 @@ impl PrivateDirectory { search_latest: bool, time: DateTime, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut (impl CryptoRngCore + CondSend), ) -> Result<&'a mut PrivateFile> { let (path, filename) = crate::utils::split_last(path_segments)?; @@ -716,7 +717,7 @@ impl PrivateDirectory { /// /// #[async_std::main] /// async fn main() -> Result<()> { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -752,7 +753,7 @@ impl PrivateDirectory { time: DateTime, content: Vec, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut (impl CryptoRngCore + CondSend), ) -> Result<()> { let (path, filename) = crate::utils::split_last(path_segments)?; @@ -805,7 +806,7 @@ impl PrivateDirectory { /// /// #[async_std::main] /// async fn main() -> Result<()> { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// let mut init_dir = PrivateDirectory::new_and_store( @@ -837,7 +838,7 @@ impl PrivateDirectory { pub async fn search_latest( self: Arc, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { PrivateNode::Dir(self) .search_latest(forest, store) @@ -852,7 +853,7 @@ impl PrivateDirectory { pub async fn search_latest_reconciled( self: Arc, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { PrivateNode::Dir(self) .search_latest_reconciled(forest, store) @@ -880,7 +881,7 @@ impl PrivateDirectory { /// /// #[async_std::main] /// async fn main() { - /// let store = &MemoryBlockStore::default(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -903,7 +904,7 @@ impl PrivateDirectory { search_latest: bool, time: DateTime, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut (impl CryptoRngCore + CondSend), ) -> Result<()> { let _ = self @@ -929,7 +930,7 @@ impl PrivateDirectory { /// /// #[async_std::main] /// async fn main() -> Result<()> { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -966,7 +967,7 @@ impl PrivateDirectory { path_segments: &[String], search_latest: bool, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { match self .get_leaf_dir(path_segments, search_latest, forest, store) @@ -1020,7 +1021,7 @@ impl PrivateDirectory { /// /// #[async_std::main] /// async fn main() { - /// let store = &MemoryBlockStore::default(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -1063,7 +1064,7 @@ impl PrivateDirectory { path_segments: &[String], search_latest: bool, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result { let (path, node_name) = crate::utils::split_last(path_segments)?; let SearchResult::Found(dir) = self @@ -1095,7 +1096,7 @@ impl PrivateDirectory { search_latest: bool, time: DateTime, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut (impl CryptoRngCore + CondSend), ) -> Result<()> { let (path, node_name) = crate::utils::split_last(path_segments)?; @@ -1141,7 +1142,7 @@ impl PrivateDirectory { /// /// #[async_std::main] /// async fn main() { - /// let store = &MemoryBlockStore::default(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -1188,7 +1189,7 @@ impl PrivateDirectory { search_latest: bool, time: DateTime, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut (impl CryptoRngCore + CondSend), ) -> Result<()> { let removed_node = self @@ -1227,7 +1228,7 @@ impl PrivateDirectory { /// /// #[async_std::main] /// async fn main() { - /// let store = &MemoryBlockStore::default(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -1274,7 +1275,7 @@ impl PrivateDirectory { search_latest: bool, time: DateTime, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut (impl CryptoRngCore + CondSend), ) -> Result<()> { let result = self @@ -1297,7 +1298,7 @@ impl PrivateDirectory { pub(crate) async fn store( &self, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut (impl CryptoRngCore + CondSend), ) -> Result { let header_cid = self.header.store(store, forest).await?; @@ -1329,7 +1330,7 @@ impl PrivateDirectory { temporal_key: &TemporalKey, cid: Cid, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, parent_name: Option, ) -> Result { if !is_readable_wnfs_version(&serializable.version) { @@ -1383,7 +1384,7 @@ impl PrivateDirectory { other: &Arc, other_cid: Cid, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result<()> { if our_cid == other_cid { return Ok(()); @@ -1496,7 +1497,7 @@ impl PrivateDirectoryContent { temporal_key: &TemporalKey, header_cid: Cid, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut (impl CryptoRngCore + CondSend), ) -> Result> { let mut entries = BTreeMap::new(); @@ -1536,7 +1537,7 @@ impl PrivateDirectoryContent { header_cid: Cid, temporal_key: &TemporalKey, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut (impl CryptoRngCore + CondSend), ) -> Result { Ok(*self @@ -1554,7 +1555,10 @@ impl PrivateDirectoryContent { let block = snapshot_key.encrypt(&bytes, rng)?; // Store content section in blockstore and get Cid. - Ok(store.put_block(block, CODEC_RAW).await?) + let block = Blake3Block::new(CODEC_RAW, block); + let cid = block.cid()?; + store.put(block).await?; + Ok(cid) }) .await?) } @@ -1602,12 +1606,12 @@ mod tests { use rand_core::SeedableRng; use test_log::test; use testresult::TestResult; - use wnfs_common::MemoryBlockStore; + use wnfs_common::blockstore::InMemoryBlockstore; #[test(async_std::test)] async fn look_up_can_fetch_file_added_to_directory() { let rng = &mut ChaCha12Rng::seed_from_u64(0); - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -1637,7 +1641,7 @@ mod tests { #[test(async_std::test)] async fn look_up_cannot_fetch_file_not_added_to_directory() { let rng = &mut ChaCha12Rng::seed_from_u64(0); - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &HamtForest::new_rsa_2048_rc(rng); let root_dir = PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -1652,7 +1656,7 @@ mod tests { #[test(async_std::test)] async fn get_node_can_fetch_node_from_root_dir() { let rng = &mut ChaCha12Rng::seed_from_u64(0); - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -1729,7 +1733,7 @@ mod tests { #[test(async_std::test)] async fn mkdir_can_create_new_directory() { let rng = &mut ChaCha12Rng::seed_from_u64(0); - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -1756,7 +1760,7 @@ mod tests { #[test(async_std::test)] async fn ls_can_list_children_under_directory() { let rng = &mut ChaCha12Rng::seed_from_u64(0); - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -1810,7 +1814,7 @@ mod tests { #[test(async_std::test)] async fn rm_can_remove_children_from_directory() { let rng = &mut ChaCha12Rng::seed_from_u64(0); - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -1866,7 +1870,7 @@ mod tests { #[async_std::test] async fn read_can_fetch_userland_of_file_added_to_directory() { let rng = &mut ChaCha12Rng::seed_from_u64(0); - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -1894,7 +1898,7 @@ mod tests { #[test(async_std::test)] async fn search_latest_finds_the_most_recent() { let rng = &mut ChaCha12Rng::from_entropy(); - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -1943,7 +1947,7 @@ mod tests { #[async_std::test] async fn cp_can_copy_sub_directory_to_another_valid_location_with_updated_ancestry() { let rng = &mut ChaCha12Rng::seed_from_u64(0); - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -2039,7 +2043,7 @@ mod tests { #[async_std::test] async fn mv_can_move_sub_directory_to_another_valid_location_with_updated_ancestry() { let rng = &mut ChaCha12Rng::from_entropy(); - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -2134,7 +2138,7 @@ mod tests { #[async_std::test] async fn mv_cannot_move_sub_directory_to_invalid_location() { let rng = &mut ChaCha12Rng::from_entropy(); - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -2173,7 +2177,7 @@ mod tests { #[async_std::test] async fn mv_can_rename_directories() { let rng = &mut ChaCha12Rng::from_entropy(); - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); let content = b"file".to_vec(); @@ -2222,7 +2226,7 @@ mod tests { #[async_std::test] async fn mv_fails_moving_directories_to_files() { let rng = &mut ChaCha12Rng::from_entropy(); - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let root_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -2269,7 +2273,7 @@ mod tests { #[async_std::test] async fn write_doesnt_generate_previous_link() { let rng = &mut ChaCha12Rng::from_entropy(); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let old_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -2294,7 +2298,7 @@ mod tests { #[async_std::test] async fn store_before_write_generates_previous_link() { let rng = &mut ChaCha12Rng::from_entropy(); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let old_dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); old_dir.store(forest, store, rng).await.unwrap(); @@ -2320,7 +2324,7 @@ mod tests { #[async_std::test] async fn search_latest_also_searches_the_root() -> Result<()> { let rng = &mut ChaCha12Rng::from_entropy(); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048(rng); let old_dir = PrivateDirectory::new_and_store(&forest.empty_name(), Utc::now(), forest, store, rng) @@ -2345,7 +2349,7 @@ mod tests { #[async_std::test] async fn test_regression_read_old_access_key() -> Result<()> { let rng = &mut ChaCha12Rng::from_entropy(); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048(rng); let mut dir = PrivateDirectory::new_and_store(&forest.empty_name(), Utc::now(), forest, store, rng) @@ -2383,7 +2387,7 @@ mod tests { #[async_std::test] async fn test_regression_read_old_file_access_key() -> Result<()> { let rng = &mut ChaCha12Rng::from_entropy(); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048(rng); let mut dir = PrivateDirectory::new_and_store(&forest.empty_name(), Utc::now(), forest, store, rng) @@ -2424,7 +2428,7 @@ mod tests { #[async_std::test] async fn test_conflict_reconciliation_merges_dirs() -> TestResult { let rng = &mut ChaCha12Rng::from_entropy(); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut Arc::new(HamtForest::new_rsa_2048(rng)); let mut dir = PrivateDirectory::new_and_store(&forest.empty_name(), Utc::now(), forest, store, rng) @@ -2483,7 +2487,7 @@ mod tests { #[async_std::test] async fn test_conflict_reconciliation_concurrently_created_files() -> TestResult { let rng = &mut ChaCha12Rng::from_entropy(); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut Arc::new(HamtForest::new_rsa_2048(rng)); let mut dir = PrivateDirectory::new_and_store(&forest.empty_name(), Utc::now(), forest, store, rng) diff --git a/wnfs/src/private/file.rs b/wnfs/src/private/file.rs index 21b5aeb2..e6644e69 100644 --- a/wnfs/src/private/file.rs +++ b/wnfs/src/private/file.rs @@ -11,17 +11,14 @@ use async_once_cell::OnceCell; use async_stream::try_stream; use chrono::{DateTime, Utc}; use futures::{future, AsyncRead, Stream, StreamExt, TryStreamExt}; -use libipld_core::{ - cid::Cid, - ipld::Ipld, - serde::{from_ipld, to_ipld}, -}; use rand_core::CryptoRngCore; use serde::{Deserialize, Serialize}; use std::{cmp::Ordering, collections::BTreeSet, iter}; use wnfs_common::{ + blockstore::{block::Block as _, Blockstore}, + ipld_core::{cid::Cid, ipld::Ipld}, utils::{self, Arc, BoxStream}, - BlockStore, Metadata, CODEC_RAW, MAX_BLOCK_SIZE, + Blake3Block, BlockStoreError, Metadata, CODEC_RAW, MAX_BLOCK_SIZE, }; use wnfs_nameaccumulator::{Name, NameAccumulator, NameSegment}; @@ -58,7 +55,7 @@ pub const MAX_BLOCK_CONTENT_SIZE: usize = MAX_BLOCK_SIZE - NONCE_SIZE - AUTHENTI /// /// #[async_std::main] /// async fn main() -> Result<()> { -/// let store = &MemoryBlockStore::new(); +/// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// @@ -191,7 +188,7 @@ impl PrivateFile { /// /// #[async_std::main] /// async fn main() { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// @@ -214,7 +211,7 @@ impl PrivateFile { time: DateTime, content: Vec, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut impl CryptoRngCore, ) -> Result { let header = PrivateNodeHeader::new(parent_name, rng); @@ -246,7 +243,7 @@ impl PrivateFile { /// /// #[async_std::main] /// async fn main() { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// @@ -269,7 +266,7 @@ impl PrivateFile { time: DateTime, content: Vec, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut impl CryptoRngCore, ) -> Result> { Ok(Arc::new( @@ -299,7 +296,7 @@ impl PrivateFile { /// async fn main() -> Result<()> { /// let disk_file = File::open("./test/fixtures/Clara Schumann, Scherzo no. 2, Op. 14.mp3").await?; /// - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// @@ -323,7 +320,7 @@ impl PrivateFile { time: DateTime, content: impl AsyncRead + Unpin, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut impl CryptoRngCore, ) -> Result { let header = PrivateNodeHeader::new(parent_name, rng); @@ -360,7 +357,7 @@ impl PrivateFile { /// async fn main() -> Result<()> { /// let disk_file = File::open("./test/fixtures/Clara Schumann, Scherzo no. 2, Op. 14.mp3").await?; /// - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// @@ -384,7 +381,7 @@ impl PrivateFile { time: DateTime, content: impl AsyncRead + Unpin, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut impl CryptoRngCore, ) -> Result> { Ok(Arc::new( @@ -410,7 +407,7 @@ impl PrivateFile { /// /// #[async_std::main] /// async fn main() -> Result<()> { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// @@ -459,7 +456,7 @@ impl PrivateFile { /// /// #[async_std::main] /// async fn main() -> Result<()> { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// @@ -491,7 +488,7 @@ impl PrivateFile { &'a self, block_index: u64, forest: &'a impl PrivateForest, - store: &'a impl BlockStore, + store: &'a impl Blockstore, ) -> BoxStream<'a, Result>> { match &self.content.content { FileContent::Inline { data } => Box::pin(try_stream! { @@ -525,7 +522,7 @@ impl PrivateFile { /// /// #[async_std::main] /// async fn main() -> Result<()> { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// let content = b"Hello, World!\n".repeat(1000).to_vec(); @@ -553,7 +550,7 @@ impl PrivateFile { byte_offset: u64, len_limit: Option, forest: &'a impl PrivateForest, - store: &'a impl BlockStore, + store: &'a impl Blockstore, ) -> Result> { match &self.content.content { FileContent::Inline { data } => { @@ -603,7 +600,7 @@ impl PrivateFile { /// /// #[async_std::main] /// async fn main() -> Result<()> { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// @@ -625,7 +622,7 @@ impl PrivateFile { /// Ok(()) /// } /// ``` - pub async fn size(&self, forest: &impl PrivateForest, store: &impl BlockStore) -> Result { + pub async fn size(&self, forest: &impl PrivateForest, store: &impl Blockstore) -> Result { match &self.content.content { FileContent::Inline { data } => Ok(data.len() as u64), FileContent::External(forest_content) => forest_content.size(forest, store).await, @@ -648,7 +645,7 @@ impl PrivateFile { /// /// #[async_std::main] /// async fn main() -> Result<()> { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// @@ -673,7 +670,7 @@ impl PrivateFile { pub async fn get_content( &self, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { self.read_at(0, None, forest, store).await } @@ -684,7 +681,7 @@ impl PrivateFile { content: impl AsyncRead + Unpin, time: DateTime, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut impl CryptoRngCore, ) -> Result<()> { self.content.metadata.upsert_mtime(time); @@ -700,7 +697,7 @@ impl PrivateFile { file_name: &Name, content: Vec, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut impl CryptoRngCore, ) -> Result { // TODO(appcypher): Use a better heuristic to determine when to use external storage. @@ -717,7 +714,7 @@ impl PrivateFile { file_name: &Name, content: impl AsyncRead + Unpin, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut impl CryptoRngCore, ) -> Result { Ok(FileContent::External( @@ -821,7 +818,7 @@ impl PrivateFile { pub(crate) async fn store( &self, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut impl CryptoRngCore, ) -> Result { let header_cid = self.header.store(store, forest).await?; @@ -850,7 +847,7 @@ impl PrivateFile { temporal_key: &TemporalKey, cid: Cid, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, parent_name: Option, ) -> Result { if !is_readable_wnfs_version(&serializable.version) { @@ -959,7 +956,7 @@ impl PrivateFileContent { &self, header_cid: Cid, snapshot_key: &SnapshotKey, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut impl CryptoRngCore, ) -> Result { Ok(*self @@ -974,7 +971,10 @@ impl PrivateFileContent { let block = snapshot_key.encrypt(&bytes, rng)?; // Store content section in blockstore and get Cid. - Ok(store.put_block(block, CODEC_RAW).await?) + let block = Blake3Block::new(CODEC_RAW, block); + let cid = block.cid()?; + store.put(block).await?; + Ok(cid) }) .await?) } @@ -1002,7 +1002,7 @@ impl PrivateForestContent { file_name: &Name, content: Vec, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut impl CryptoRngCore, ) -> Result { let (key, base_name) = Self::prepare_key_and_base_name(file_name, rng); @@ -1015,7 +1015,10 @@ impl PrivateForestContent { let slice = &content[start..end]; let enc_bytes = key.encrypt(slice, rng)?; - let content_cid = store.put_block(enc_bytes, CODEC_RAW).await?; + + let block = Blake3Block::new(CODEC_RAW, enc_bytes); + let content_cid = block.cid()?; + store.put(block).await?; forest .put_encrypted(&name, Some(content_cid), store) @@ -1037,7 +1040,7 @@ impl PrivateForestContent { file_name: &Name, mut content: impl AsyncRead + Unpin, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut impl CryptoRngCore, ) -> Result { let (key, base_name) = Self::prepare_key_and_base_name(file_name, rng); @@ -1062,7 +1065,9 @@ impl PrivateForestContent { let tag = key.encrypt_in_place(&nonce, &mut current_block[NONCE_SIZE..])?; current_block.extend_from_slice(tag.as_ref()); - let content_cid = store.put_block(current_block, CODEC_RAW).await?; + let block = Blake3Block::new(CODEC_RAW, current_block); + let content_cid = block.cid()?; + store.put(block).await?; let name = Self::create_block_name(&key, block_index, &base_name); forest @@ -1087,7 +1092,8 @@ impl PrivateForestContent { /// Load some previously stored keys & pointers to encrypted private forest content /// from given metadata key. pub fn from_metadata_value(value: &Ipld) -> Result { - let wrapped: MetadataContentCapsule = from_ipld(value.clone())?; + let wrapped: MetadataContentCapsule = + wnfs_common::ipld_core::serde::from_ipld(value.clone())?; Ok(match wrapped { MetadataContentCapsule::PrivateForestContent(content) => content, @@ -1096,9 +1102,9 @@ impl PrivateForestContent { // Serialize these pointers & keys into some data that can be stored in a `PrivateFile`'s metadata. pub fn as_metadata_value(&self) -> Result { - Ok(to_ipld(MetadataContentCapsule::PrivateForestContent( - &self, - ))?) + Ok(wnfs_common::ipld_core::serde::to_ipld( + MetadataContentCapsule::PrivateForestContent(&self), + )?) } /// Decrypt & stream out the contents that `self` points to in given forest. @@ -1106,7 +1112,7 @@ impl PrivateForestContent { &'a self, block_index: u64, forest: &'a impl PrivateForest, - store: &'a impl BlockStore, + store: &'a impl Blockstore, ) -> impl Stream>> + 'a { try_stream! { for name in Self::generate_shard_labels( @@ -1128,7 +1134,7 @@ impl PrivateForestContent { byte_offset: u64, len_limit: Option, forest: &'a impl PrivateForest, - store: &'a impl BlockStore, + store: &'a impl Blockstore, ) -> Result> { let block_content_size = MAX_BLOCK_CONTENT_SIZE as u64; let mut chunk_size_upper_bound = (self.get_size_upper_bound() - byte_offset) as usize; @@ -1176,7 +1182,7 @@ impl PrivateForestContent { pub async fn get_content( &self, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { let mut content = Vec::with_capacity(Self::get_size_upper_bound(self) as usize); self.stream(0, forest, store) @@ -1194,7 +1200,7 @@ impl PrivateForestContent { } /// Gets the exact size of the content. - pub async fn size(&self, forest: &impl PrivateForest, store: &impl BlockStore) -> Result { + pub async fn size(&self, forest: &impl PrivateForest, store: &impl Blockstore) -> Result { let size_without_last_block = std::cmp::max(0, self.block_count - 1) * self.block_content_size; @@ -1228,7 +1234,7 @@ impl PrivateForestContent { key: &SnapshotKey, name: &Name, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { let cid = forest .get_encrypted(name, store) @@ -1238,7 +1244,10 @@ impl PrivateForestContent { .next() .expect("Expected set with at least a one cid"); - let enc_bytes = store.get_block(cid).await?; + let enc_bytes = store + .get(cid) + .await? + .ok_or_else(|| BlockStoreError::CIDNotFound(*cid))?; let bytes = key.decrypt(&enc_bytes)?; Ok(bytes) @@ -1321,11 +1330,11 @@ mod tests { use rand::Rng; use rand_chacha::ChaCha12Rng; use rand_core::SeedableRng; - use wnfs_common::MemoryBlockStore; + use wnfs_common::blockstore::InMemoryBlockstore; #[async_std::test] async fn can_create_empty_file() { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let rng = &mut ChaCha12Rng::seed_from_u64(0); let forest = &HamtForest::new_rsa_2048_rc(rng); @@ -1340,7 +1349,7 @@ mod tests { let mut content = vec![0u8; MAX_BLOCK_CONTENT_SIZE * 5]; rand::thread_rng().fill(&mut content[..]); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let rng = &mut ChaCha12Rng::seed_from_u64(0); let forest = &mut HamtForest::new_rsa_2048_rc(rng); @@ -1381,7 +1390,7 @@ mod tests { .await .unwrap(); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let rng = &mut ChaCha12Rng::seed_from_u64(0); let forest = &mut HamtForest::new_rsa_2048_rc(rng); @@ -1416,7 +1425,7 @@ mod proptests { use rand_chacha::ChaCha12Rng; use rand_core::SeedableRng; use test_strategy::proptest; - use wnfs_common::{BlockStoreError, MemoryBlockStore}; + use wnfs_common::{blockstore::InMemoryBlockstore, BlockStoreError}; /// Size of the test file at "./test/fixtures/Clara Schumann, Scherzo no. 2, Op. 14.mp3" const FIXTURE_SCHERZO_SIZE: usize = 4028150; @@ -1427,7 +1436,7 @@ mod proptests { ) { async_std::task::block_on(async { let content = vec![0u8; length]; - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let rng = &mut ChaCha12Rng::seed_from_u64(0); let forest = &mut HamtForest::new_rsa_2048_rc(rng); @@ -1455,7 +1464,7 @@ mod proptests { ) { async_std::task::block_on(async { let content = vec![0u8; length]; - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let rng = &mut ChaCha12Rng::seed_from_u64(0); let forest = &mut HamtForest::new_rsa_2048_rc(rng); @@ -1488,7 +1497,7 @@ mod proptests { #[strategy(0..(MAX_BLOCK_CONTENT_SIZE * 2))] length: usize, ) { async_std::task::block_on(async { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let rng = &mut ChaCha12Rng::seed_from_u64(0); let forest = &mut HamtForest::new_rsa_2048_rc(rng); @@ -1498,7 +1507,7 @@ mod proptests { &mut Cursor::new(vec![5u8; length]), Utc::now(), forest, - &MemoryBlockStore::default(), + &InMemoryBlockstore::<64>::new(), rng, ) .await @@ -1532,7 +1541,7 @@ mod proptests { let rng = &mut ChaCha12Rng::seed_from_u64(0); let forest = &mut HamtForest::new_rsa_2048_rc(rng); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let file = PrivateFile::with_content_streaming( &forest.empty_name(), diff --git a/wnfs/src/private/forest/hamt.rs b/wnfs/src/private/forest/hamt.rs index cb1fed72..d1f97818 100644 --- a/wnfs/src/private/forest/hamt.rs +++ b/wnfs/src/private/forest/hamt.rs @@ -1,16 +1,17 @@ use super::traits::PrivateForest; use crate::error::FsError; use anyhow::Result; -use libipld_core::cid::Cid; use quick_cache::sync::Cache; use rand_core::CryptoRngCore; use semver::Version; use serde::{Deserialize, Serialize}; use std::collections::BTreeSet; use wnfs_common::{ + blockstore::Blockstore, impl_storable_from_serde, + ipld_core::cid::Cid, utils::{Arc, CondSend}, - BlockStore, HashOutput, Link, Storable, + HashOutput, Link, Storable, }; use wnfs_hamt::{ constants::HAMT_VERSION, merge, serializable::NodeSerializable, Hamt, Hasher, KeyValueChange, @@ -129,7 +130,7 @@ impl HamtForest { pub async fn diff( &self, other: &Self, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> { if self.accumulator != other.accumulator { return Err(FsError::IncompatibleAccumulatorSetups.into()); @@ -160,7 +161,7 @@ impl HamtForest { /// /// #[async_std::main] /// async fn main() -> Result<()> { - /// let store = &mut MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); @@ -203,7 +204,7 @@ impl HamtForest { /// Ok(()) /// } /// ``` - pub async fn merge(&self, other: &Self, store: &impl BlockStore) -> Result { + pub async fn merge(&self, other: &Self, store: &impl Blockstore) -> Result { if self.accumulator != other.accumulator { return Err(FsError::IncompatibleAccumulatorSetups.into()); } @@ -250,7 +251,7 @@ impl PrivateForest for HamtForest { } } - async fn has_by_hash(&self, name_hash: &HashOutput, store: &impl BlockStore) -> Result { + async fn has_by_hash(&self, name_hash: &HashOutput, store: &impl Blockstore) -> Result { Ok(self .hamt .root @@ -259,7 +260,7 @@ impl PrivateForest for HamtForest { .is_some()) } - async fn has(&self, name: &Name, store: &impl BlockStore) -> Result { + async fn has(&self, name: &Name, store: &impl Blockstore) -> Result { self.has_by_hash( &blake3::Hasher::hash(&self.get_accumulated_name(name)), store, @@ -271,7 +272,7 @@ impl PrivateForest for HamtForest { &mut self, name: &Name, values: I, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result where I: IntoIterator + CondSend, @@ -296,7 +297,7 @@ impl PrivateForest for HamtForest { async fn get_encrypted_by_hash<'b>( &'b self, name_hash: &HashOutput, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> { Ok(self .hamt @@ -309,7 +310,7 @@ impl PrivateForest for HamtForest { async fn get_encrypted( &self, name: &Name, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> { let name_hash = &blake3::Hasher::hash(&self.get_accumulated_name(name)); self.get_encrypted_by_hash(name_hash, store).await @@ -318,7 +319,7 @@ impl PrivateForest for HamtForest { async fn remove_encrypted( &mut self, name: &Name, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>>> { let name_hash = &blake3::Hasher::hash(&self.get_accumulated_name(name)); Ok(self @@ -346,11 +347,11 @@ impl PrivateForest for Arc { (**self).get_proven_name(name) } - async fn has_by_hash(&self, name_hash: &HashOutput, store: &impl BlockStore) -> Result { + async fn has_by_hash(&self, name_hash: &HashOutput, store: &impl Blockstore) -> Result { (**self).has_by_hash(name_hash, store).await } - async fn has(&self, name: &Name, store: &impl BlockStore) -> Result { + async fn has(&self, name: &Name, store: &impl Blockstore) -> Result { (**self).has(name, store).await } @@ -358,7 +359,7 @@ impl PrivateForest for Arc { &mut self, name: &Name, values: I, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result where I: IntoIterator + CondSend, @@ -370,7 +371,7 @@ impl PrivateForest for Arc { async fn get_encrypted_by_hash<'b>( &'b self, name_hash: &HashOutput, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> { (**self).get_encrypted_by_hash(name_hash, store).await } @@ -378,7 +379,7 @@ impl PrivateForest for Arc { async fn get_encrypted( &self, name: &Name, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> { (**self).get_encrypted(name, store).await } @@ -386,7 +387,7 @@ impl PrivateForest for Arc { async fn remove_encrypted( &mut self, name: &Name, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>>> { Arc::make_mut(self).remove_encrypted(name, store).await } @@ -395,7 +396,7 @@ impl PrivateForest for Arc { impl Storable for HamtForest { type Serializable = HamtForestSerializable; - async fn to_serializable(&self, store: &impl BlockStore) -> Result { + async fn to_serializable(&self, store: &impl Blockstore) -> Result { Ok(HamtForestSerializable { root: self.hamt.root.to_serializable(store).await?, version: HAMT_VERSION, @@ -430,12 +431,12 @@ mod tests { use chrono::Utc; use rand_chacha::ChaCha12Rng; use rand_core::SeedableRng; - use wnfs_common::MemoryBlockStore; + use wnfs_common::blockstore::InMemoryBlockstore; use wnfs_nameaccumulator::NameSegment; #[async_std::test] async fn test_put_get() { - let store = &mut MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let rng = &mut ChaCha12Rng::seed_from_u64(0); let forest = &mut HamtForest::new_rsa_2048_rc(rng); @@ -456,7 +457,7 @@ mod tests { #[async_std::test] async fn inserted_items_can_be_fetched() { - let store = &mut MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let rng = &mut ChaCha12Rng::seed_from_u64(0); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let dir = PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -472,7 +473,7 @@ mod tests { #[async_std::test] async fn multivalue_conflict_can_be_fetched_individually() { - let store = &mut MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let rng = &mut ChaCha12Rng::seed_from_u64(0); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let dir = PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); diff --git a/wnfs/src/private/forest/proofs.rs b/wnfs/src/private/forest/proofs.rs index 3a3d7990..4a0eb41b 100644 --- a/wnfs/src/private/forest/proofs.rs +++ b/wnfs/src/private/forest/proofs.rs @@ -1,11 +1,12 @@ use super::{hamt::HamtForest, traits::PrivateForest}; use crate::error::{FsError, VerificationError}; use anyhow::{bail, Result}; -use libipld_core::cid::Cid; use std::collections::{BTreeSet, HashMap}; use wnfs_common::{ + blockstore::Blockstore, + ipld_core::cid::Cid, utils::{Arc, CondSend}, - BlockStore, HashOutput, + HashOutput, }; use wnfs_hamt::Pair; use wnfs_nameaccumulator::{ @@ -111,7 +112,7 @@ impl ProvingHamtForest { &self, previous: &HamtForest, allowed_bases: &BTreeSet, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result<()> { let setup = self.forest.get_accumulator_setup(); if setup != previous.get_accumulator_setup() { @@ -162,11 +163,11 @@ impl PrivateForest for ProvingHamtForest { self.forest.get_proven_name(name) } - async fn has_by_hash(&self, name_hash: &HashOutput, store: &impl BlockStore) -> Result { + async fn has_by_hash(&self, name_hash: &HashOutput, store: &impl Blockstore) -> Result { self.forest.has_by_hash(name_hash, store).await } - async fn has(&self, name: &Name, store: &impl BlockStore) -> Result { + async fn has(&self, name: &Name, store: &impl Blockstore) -> Result { self.forest.has(name, store).await } @@ -174,7 +175,7 @@ impl PrivateForest for ProvingHamtForest { &mut self, name: &Name, values: I, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result where I: IntoIterator + CondSend, @@ -192,7 +193,7 @@ impl PrivateForest for ProvingHamtForest { async fn get_encrypted_by_hash<'b>( &'b self, name_hash: &HashOutput, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> { self.forest.get_encrypted_by_hash(name_hash, store).await } @@ -200,7 +201,7 @@ impl PrivateForest for ProvingHamtForest { async fn get_encrypted( &self, name: &Name, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> { self.forest.get_encrypted(name, store).await } @@ -208,7 +209,7 @@ impl PrivateForest for ProvingHamtForest { async fn remove_encrypted( &mut self, name: &Name, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>>> { let ProvingHamtForest { forest, proofs } = self; @@ -225,11 +226,10 @@ mod tests { use super::{ForestProofs, ProvingHamtForest}; use crate::private::forest::{hamt::HamtForest, traits::PrivateForest}; use anyhow::Result; - use libipld_core::cid::Cid; use rand_chacha::ChaCha12Rng; use rand_core::SeedableRng; use std::collections::BTreeSet; - use wnfs_common::{utils::Arc, MemoryBlockStore}; + use wnfs_common::{blockstore::InMemoryBlockstore, ipld_core::cid::Cid, utils::Arc}; use wnfs_nameaccumulator::{AccumulatorSetup, Name, NameAccumulator, NameSegment}; #[test] @@ -256,7 +256,7 @@ mod tests { async fn proving_hamt_forest_can_be_verified() -> Result<()> { let rng = &mut ChaCha12Rng::from_entropy(); let setup = &AccumulatorSetup::from_rsa_2048(rng); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let old_forest = Arc::new(HamtForest::new(setup.clone())); let mut forest = ProvingHamtForest::new(Arc::clone(&old_forest)); diff --git a/wnfs/src/private/forest/snapshots/wnfs__private__forest__hamt__snapshot_tests__hamt.snap.new b/wnfs/src/private/forest/snapshots/wnfs__private__forest__hamt__snapshot_tests__hamt.snap.new new file mode 100644 index 00000000..fe1f8a8a --- /dev/null +++ b/wnfs/src/private/forest/snapshots/wnfs__private__forest__hamt__snapshot_tests__hamt.snap.new @@ -0,0 +1,82 @@ +--- +source: wnfs/src/private/forest/hamt.rs +assertion_line: 571 +expression: store +--- +{ + "cid": "bafyr4ihxqcx3frq52pfa5pxiwxd3adgsim5kmwkyx3ixs2qyl7oq5mkcjm", + "value": { + "accumulator": { + "generator": { + "/": { + "bytes": "DnwXmD/vORPcLzdf1evo7nGljNInOtYHpODrD3+82Nnpu0qfQPxFLKSB2dhylrLkh4UmTnLZtphq+jBbSjrWkqRf6C/qEToqzAhkAPtkF048lnLaI3UjBCXagQjJv8boXybWdaxiKxTFN2nu9B2vzNyUl1QqO9wXmNkzWM1P4T8lIm6FTjWSbHg/TVTXkpv8nTgQIUA1A0Kk7jEtjb/Vl8VdTZ2UgBywKE1Pvf8HbmXDc6Cjg0K5+XXC6SW1Bk71iLdLM174Mu8KWDjb3qotRpqrGGeSIv1KI1v1VWCI8ZuohkVe4zT5JvzyKIizsVDKcPTKGR60H6enSeQZgShFww" + } + }, + "modulus": { + "/": { + "bytes": "x5cM7tzDsHVEkCAaeqYTzXOREIHHkPXxqHJvRjVQu1t/8NuOHqEYnscvk9FlABG9chrurMKs3jKgQQfwZIwoE6MfWwt3Zf+LRLS2/8kzhLZG6wnHz16FktQOozyAA581tPFKBLUfe/14G+TRZzFkuo65kcLE1zC7vjX1kr3vUkr36Nrv0mxm/ALEea+J1k03P0QnCUOd5mzrlV8+o31RWfYTWAn4UzS1yxgTrdyAzQVgnxCsapWtZYcskJUlva0yvHKVkmQpIPJMYdxbPDt5I+VrFqTZ03PYch8ko/wPGzEx9VYVFyhmvMww+VBUyCTnM6XraBf3vBY5nUjGNhzH5Q" + } + } + }, + "root": [ + { + "/": { + "bytes": "IgQ" + } + }, + [ + { + "Values": [ + [ + { + "/": { + "bytes": "WzUFTg2et93G6urhSL2Viqdf49sAgAv0vv8SE1SgzA2V80ukVHaZR6+PcbbkvJa7kqRzKbUJ8si3pckU/2L30Kmr+JVM38v6cQAT5N0y9KiTmXX6EyUIkQ5r+zfH8xybEhJ00mPJbRpB76OgZ24z9a1VLWQCcenR6GsrPWUkU94p3r8XBQtIBni/uHjKlpFvR/Csq+pmoBqK5qOYaDsgWn6nV8pgMIIRFifu6S7bw9SSMtRUrW/FFfcu1GjRHeq7UV71wyUGGB2gpC4Ekm8Y/tri1S3zHbLnh54ck+tjUZM0MMRSWnL+FvwXcYKaxfRmxooi0Jajw3zF+xGdW8hlnw" + } + }, + [ + { + "/": "baeaaaaa" + } + ] + ] + ] + }, + { + "Values": [ + [ + { + "/": { + "bytes": "JpTYbHBVDGw5673kIA4lqeXDoKce4FWIcUzot6Dz7jlQu9P/oIsgyVqxOsyywQNdzwbCXdzscWCzafaoX46arhINT9o9aB2e88mQLJrs3Q19cVojT1MNS0ozckERxcmJdarrm3SQMX61pyRK796Su33+5bKZ2QfVQwlhpQ6zC6bFrsXNtcM+xk82MgpFkhNNg7vP+LRUVzmRgk8bdsnHypPQE0jAOS/tn93KMV4aA32KNeZdxDwvFDJ/BFqQ0X0uhs0NA1xQbNqlUOfLvfKa2ADlU+Gn+wilPLwjnelZbuQSu78e+Y1kGDuYJPYG5aCYKlNlYfjV/V2BqvTgY6Qt7w" + } + }, + [ + { + "/": "baeaaaaa" + } + ] + ] + ] + }, + { + "Values": [ + [ + { + "/": { + "bytes": "PIhixhlMETh9BGn4lF0klTdOCHH3/JngF0bGUZZg3HO25Qqp4c5K3eOyAohQYWIhyxgbOhkvzeVtG5oDNSVLcgd+6lMULgXBEEhavSX6CFLnxVoKLFqvvt7dxh5dUVTSQ6adIIa0E7hzu1Jt9E8mZm3C1rNz8js9+eaQwWzYynyRi78O/ubhgK8W5K1lIKtDdKI6VnOTaUKn/kih2kYhR/exZGWAzk9vwmDlsRRIJLHrTYX3cxZuTlMa2MwFov5WDE5zYSh/qe3jVmIXEhp/ffnWzEjwlbkZi6RpC/cT2NStprki+vwJdV4klvKpSdA8+5Ma+cUZ8PjeEBqLjl10WA" + } + }, + [ + { + "/": "baeaaaaa" + } + ] + ] + ] + } + ] + ], + "structure": "hamt", + "version": "0.1.0" + }, + "bytes": "pGRyb290gkIiBIOhZlZhbHVlc4GCWQEAWzUFTg2et93G6urhSL2Viqdf49sAgAv0vv8SE1SgzA2V80ukVHaZR6+PcbbkvJa7kqRzKbUJ8si3pckU/2L30Kmr+JVM38v6cQAT5N0y9KiTmXX6EyUIkQ5r+zfH8xybEhJ00mPJbRpB76OgZ24z9a1VLWQCcenR6GsrPWUkU94p3r8XBQtIBni/uHjKlpFvR/Csq+pmoBqK5qOYaDsgWn6nV8pgMIIRFifu6S7bw9SSMtRUrW/FFfcu1GjRHeq7UV71wyUGGB2gpC4Ekm8Y/tri1S3zHbLnh54ck+tjUZM0MMRSWnL+FvwXcYKaxfRmxooi0Jajw3zF+xGdW8hln4HYKkUAAQAAAKFmVmFsdWVzgYJZAQAmlNhscFUMbDnrveQgDiWp5cOgpx7gVYhxTOi3oPPuOVC70/+giyDJWrE6zLLBA13PBsJd3OxxYLNp9qhfjpquEg1P2j1oHZ7zyZAsmuzdDX1xWiNPUw1LSjNyQRHFyYl1quubdJAxfrWnJErv3pK7ff7lspnZB9VDCWGlDrMLpsWuxc21wz7GTzYyCkWSE02Du8/4tFRXOZGCTxt2ycfKk9ATSMA5L+2f3coxXhoDfYo15l3EPC8UMn8EWpDRfS6GzQ0DXFBs2qVQ58u98prYAOVT4af7CKU8vCOd6Vlu5BK7vx75jWQYO5gk9gbloJgqU2Vh+NX9XYGq9OBjpC3vgdgqRQABAAAAoWZWYWx1ZXOBglkBADyIYsYZTBE4fQRp+JRdJJU3Tghx9/yZ4BdGxlGWYNxztuUKqeHOSt3jsgKIUGFiIcsYGzoZL83lbRuaAzUlS3IHfupTFC4FwRBIWr0l+ghS58VaCixar77e3cYeXVFU0kOmnSCGtBO4c7tSbfRPJmZtwtazc/I7PfnmkMFs2Mp8kYu/Dv7m4YCvFuStZSCrQ3SiOlZzk2lCp/5IodpGIUf3sWRlgM5Pb8Jg5bEUSCSx602F93MWbk5TGtjMBaL+VgxOc2Eof6nt41ZiFxIaf3351sxI8JW5GYukaQv3E9jUraa5Ivr8CXVeJJbyqUnQPPuTGvnFGfD43hAai45ddFiB2CpFAAEAAABndmVyc2lvbmUwLjEuMGlzdHJ1Y3R1cmVkaGFtdGthY2N1bXVsYXRvcqJnbW9kdWx1c1kBAMeXDO7cw7B1RJAgGnqmE81zkRCBx5D18ahyb0Y1ULtbf/Dbjh6hGJ7HL5PRZQARvXIa7qzCrN4yoEEH8GSMKBOjH1sLd2X/i0S0tv/JM4S2RusJx89ehZLUDqM8gAOfNbTxSgS1H3v9eBvk0WcxZLqOuZHCxNcwu7419ZK971JK9+ja79JsZvwCxHmvidZNNz9EJwlDneZs65VfPqN9UVn2E1gJ+FM0tcsYE63cgM0FYJ8QrGqVrWWHLJCVJb2tMrxylZJkKSDyTGHcWzw7eSPlaxak2dNz2HIfJKP8DxsxMfVWFRcoZrzMMPlQVMgk5zOl62gX97wWOZ1IxjYcx+VpZ2VuZXJhdG9yWQEADnwXmD/vORPcLzdf1evo7nGljNInOtYHpODrD3+82Nnpu0qfQPxFLKSB2dhylrLkh4UmTnLZtphq+jBbSjrWkqRf6C/qEToqzAhkAPtkF048lnLaI3UjBCXagQjJv8boXybWdaxiKxTFN2nu9B2vzNyUl1QqO9wXmNkzWM1P4T8lIm6FTjWSbHg/TVTXkpv8nTgQIUA1A0Kk7jEtjb/Vl8VdTZ2UgBywKE1Pvf8HbmXDc6Cjg0K5+XXC6SW1Bk71iLdLM174Mu8KWDjb3qotRpqrGGeSIv1KI1v1VWCI8ZuohkVe4zT5JvzyKIizsVDKcPTKGR60H6enSeQZgShFww==" +} diff --git a/wnfs/src/private/forest/traits.rs b/wnfs/src/private/forest/traits.rs index 266edbd6..33f5dd17 100644 --- a/wnfs/src/private/forest/traits.rs +++ b/wnfs/src/private/forest/traits.rs @@ -5,11 +5,12 @@ use crate::{ use anyhow::Result; use async_stream::stream; use futures::Future; -use libipld_core::cid::Cid; use std::collections::BTreeSet; use wnfs_common::{ + blockstore::Blockstore, + ipld_core::cid::Cid, utils::{BoxStream, CondSend, CondSync}, - BlockStore, HashOutput, + HashOutput, }; use wnfs_hamt::Pair; use wnfs_nameaccumulator::{AccumulatorSetup, ElementsProof, Name, NameAccumulator}; @@ -87,14 +88,14 @@ pub trait PrivateForest: CondSync { fn has_by_hash( &self, name_hash: &HashOutput, - store: &impl BlockStore, + store: &impl Blockstore, ) -> impl Future> + CondSend; /// Check whether a certain name has any values. fn has( &self, name: &Name, - store: &impl BlockStore, + store: &impl Blockstore, ) -> impl Future> + CondSend; /// Adds new encrypted values at the given key. @@ -102,7 +103,7 @@ pub trait PrivateForest: CondSync { &mut self, name: &Name, values: I, - store: &impl BlockStore, + store: &impl Blockstore, ) -> impl Future> + CondSend where I: IntoIterator + CondSend, @@ -112,21 +113,21 @@ pub trait PrivateForest: CondSync { fn get_encrypted_by_hash<'b>( &'b self, name_hash: &HashOutput, - store: &impl BlockStore, + store: &impl Blockstore, ) -> impl Future>>> + CondSend; /// Gets the CIDs to blocks of ciphertext by name. fn get_encrypted( &self, name: &Name, - store: &impl BlockStore, + store: &impl Blockstore, ) -> impl Future>>> + CondSend; /// Removes the CIDs to blocks of ciphertext by name. fn remove_encrypted( &mut self, name: &Name, - store: &impl BlockStore, + store: &impl Blockstore, ) -> impl Future>>>> + CondSend; /// Returns a stream of all private nodes that could be decrypted at given revision. @@ -138,7 +139,7 @@ pub trait PrivateForest: CondSync { &'a self, label: &'a HashOutput, temporal_key: &'a TemporalKey, - store: &'a impl BlockStore, + store: &'a impl Blockstore, parent_name: Option, ) -> BoxStream<'a, Result<(Cid, PrivateNode)>> where diff --git a/wnfs/src/private/keys/access.rs b/wnfs/src/private/keys/access.rs index 67839f94..6660ac3c 100644 --- a/wnfs/src/private/keys/access.rs +++ b/wnfs/src/private/keys/access.rs @@ -3,9 +3,8 @@ use crate::{ private::{PrivateRef, SnapshotKey, TemporalKey}, }; use anyhow::{bail, Result}; -use libipld_core::cid::Cid; use serde::{Deserialize, Serialize}; -use wnfs_common::HashOutput; +use wnfs_common::{ipld_core::cid::Cid, HashOutput}; //-------------------------------------------------------------------------------------------------- // Type Definitions @@ -124,7 +123,7 @@ mod snapshot_tests { use rand_chacha::ChaCha12Rng; use rand_core::SeedableRng; use testresult::TestResult; - use wnfs_common::{encode, libipld::json::DagJsonCodec}; + use wnfs_common::ipld_core::serde; #[async_std::test] async fn test_access_key() -> TestResult { @@ -146,7 +145,7 @@ mod snapshot_tests { } fn as_dag_json_value(s: impl Serialize) -> Result { - let dag_json = encode(&libipld_core::serde::to_ipld(s)?, DagJsonCodec)?; + let dag_json = serde_ipld_dagjson::to_vec(&serde::to_ipld(s)?)?; let value = serde_json::from_slice(&dag_json)?; Ok(value) } diff --git a/wnfs/src/private/keys/privateref.rs b/wnfs/src/private/keys/privateref.rs index ecc95f11..2326eb90 100644 --- a/wnfs/src/private/keys/privateref.rs +++ b/wnfs/src/private/keys/privateref.rs @@ -3,10 +3,9 @@ use crate::{ private::{PrivateRefSerializable, TemporalKey, KEY_BYTE_SIZE}, }; use anyhow::Result; -use libipld_core::cid::Cid; use serde::{de::Error as DeError, ser::Error as SerError, Deserialize, Serialize}; use std::fmt::Debug; -use wnfs_common::HashOutput; +use wnfs_common::{ipld_core::cid::Cid, HashOutput}; //-------------------------------------------------------------------------------------------------- // Type Definitions diff --git a/wnfs/src/private/link.rs b/wnfs/src/private/link.rs index fa3dcf7c..a8f7ab5c 100644 --- a/wnfs/src/private/link.rs +++ b/wnfs/src/private/link.rs @@ -5,11 +5,12 @@ use crate::utils::OnceCellDebug; use anyhow::{anyhow, Result}; use async_once_cell::OnceCell; use async_recursion::async_recursion; -use libipld_core::{cid::Cid, multihash::MultihashGeneric}; +use multihash::Multihash; use rand_core::CryptoRngCore; use wnfs_common::{ + blockstore::Blockstore, + ipld_core::cid::Cid, utils::{Arc, CondSend}, - BlockStore, }; use wnfs_nameaccumulator::Name; @@ -51,7 +52,7 @@ impl PrivateLink { pub(crate) async fn resolve_ref( &self, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut (impl CryptoRngCore + CondSend), ) -> Result { match self { @@ -65,7 +66,7 @@ impl PrivateLink { pub(crate) async fn resolve_node( &self, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, parent_name: Option, ) -> Result<&PrivateNode> { match self { @@ -87,7 +88,7 @@ impl PrivateLink { pub(crate) async fn resolve_node_mut( &mut self, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, parent_name: Option, ) -> Result<&mut PrivateNode> { match self { @@ -120,7 +121,7 @@ impl PrivateLink { pub(crate) async fn resolve_owned_node( self, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, parent_name: Option, ) -> Result { match self { @@ -159,7 +160,7 @@ impl PrivateLink { Self::from(PrivateNode::File(Arc::new(file))) } - pub(crate) fn crdt_tiebreaker(&self) -> Result> { + pub(crate) fn crdt_tiebreaker(&self) -> Result> { Ok(*self.get_content_cid().ok_or_else(|| anyhow!("Impossible case: CRDT tiebreaker needed on node wasn't persisted before tie breaking"))?.hash()) } } diff --git a/wnfs/src/private/node/header.rs b/wnfs/src/private/node/header.rs index 2731b60a..1e094c10 100644 --- a/wnfs/src/private/node/header.rs +++ b/wnfs/src/private/node/header.rs @@ -5,11 +5,14 @@ use crate::{ }; use anyhow::{anyhow, bail, Result}; use futures::TryStreamExt; -use libipld_core::cid::Cid; use rand_core::CryptoRngCore; use skip_ratchet::Ratchet; use std::{collections::BTreeMap, fmt::Debug}; -use wnfs_common::{BlockStore, CODEC_RAW}; +use wnfs_common::{ + blockstore::{block::Block as _, Blockstore}, + ipld_core::cid::Cid, + Blake3Block, BlockStoreError, CODEC_RAW, +}; use wnfs_hamt::Hasher; use wnfs_nameaccumulator::{Name, NameSegment}; @@ -162,11 +165,14 @@ impl PrivateNodeHeader { /// BlockStore and returns its CID. /// /// This *does not* store the block itself in the forest, only in the given block store. - pub async fn store(&self, store: &impl BlockStore, forest: &impl PrivateForest) -> Result { + pub async fn store(&self, store: &impl Blockstore, forest: &impl PrivateForest) -> Result { let temporal_key = self.derive_temporal_key(); let cbor_bytes = serde_ipld_dagcbor::to_vec(&self.to_serializable(forest))?; let ciphertext = temporal_key.key_wrap_encrypt(&cbor_bytes)?; - Ok(store.put_block(ciphertext, CODEC_RAW).await?) + let block = Blake3Block::new(CODEC_RAW, ciphertext); + let cid = block.cid()?; + store.put(block).await?; + Ok(cid) } pub(crate) fn to_serializable( @@ -194,10 +200,13 @@ impl PrivateNodeHeader { cid: &Cid, temporal_key: &TemporalKey, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, parent_name: Option, ) -> Result { - let ciphertext = store.get_block(cid).await?; + let ciphertext = store + .get(cid) + .await? + .ok_or_else(|| BlockStoreError::CIDNotFound(*cid))?; let cbor_bytes = temporal_key.key_wrap_decrypt(&ciphertext)?; let decoded: PrivateNodeHeaderSerializable = serde_ipld_dagcbor::from_slice(&cbor_bytes)?; let serialized_name = decoded.name.clone(); @@ -221,7 +230,7 @@ impl PrivateNodeHeader { pub(crate) async fn get_multivalue( &self, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { let mountpoint = self.name.parent(); @@ -239,7 +248,7 @@ impl PrivateNodeHeader { pub(crate) async fn seek_unmerged_heads( &mut self, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { let mut previous_keys = Vec::with_capacity(1); let mut heads = BTreeMap::new(); diff --git a/wnfs/src/private/node/node.rs b/wnfs/src/private/node/node.rs index 76b2f6cb..8d2eb465 100644 --- a/wnfs/src/private/node/node.rs +++ b/wnfs/src/private/node/node.rs @@ -11,7 +11,6 @@ use anyhow::{bail, Result}; use async_once_cell::OnceCell; use async_recursion::async_recursion; use chrono::{DateTime, Utc}; -use libipld_core::cid::Cid; use rand_core::CryptoRngCore; use skip_ratchet::{JumpSize, RatchetSeeker}; use std::{ @@ -20,8 +19,10 @@ use std::{ fmt::Debug, }; use wnfs_common::{ + blockstore::Blockstore, + ipld_core::cid::Cid, utils::{Arc, CondSend}, - BlockStore, + BlockStoreError, }; use wnfs_nameaccumulator::Name; @@ -114,7 +115,7 @@ impl PrivateNode { &mut self, parent_name: &Name, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut (impl CryptoRngCore + CondSend), ) -> Result<()> { match self { @@ -368,7 +369,7 @@ impl PrivateNode { pub async fn search_latest( &self, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result { self.search_latest_nodes(forest, store) .await? @@ -385,7 +386,7 @@ impl PrivateNode { pub async fn reconcile_latest( &mut self, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut (impl CryptoRngCore + CondSend), ) -> Result<()> { self.store(forest, store, rng).await?; @@ -399,7 +400,7 @@ impl PrivateNode { pub async fn search_latest_reconciled( &self, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result { let mut header = self.get_header().clone(); let mut unmerged_heads = header.seek_unmerged_heads(forest, store).await?; @@ -425,7 +426,7 @@ impl PrivateNode { (cid, node): (Cid, PrivateNode), nodes: BTreeMap, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result { match node { PrivateNode::File(mut file) => { @@ -468,7 +469,7 @@ impl PrivateNode { pub async fn search_latest_nodes( &self, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { let header = self.get_header(); @@ -517,7 +518,7 @@ impl PrivateNode { pub(crate) async fn from_private_ref( private_ref: &PrivateRef, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, parent_name: Option, ) -> Result { let cid = match forest @@ -535,10 +536,13 @@ impl PrivateNode { cid: Cid, temporal_key: &TemporalKey, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, parent_name: Option, ) -> Result { - let encrypted_bytes = store.get_block(&cid).await?; + let encrypted_bytes = store + .get(&cid) + .await? + .ok_or_else(|| BlockStoreError::CIDNotFound(cid))?; let snapshot_key = temporal_key.derive_snapshot_key(); let bytes = snapshot_key.decrypt(&encrypted_bytes)?; let node: PrivateNodeContentSerializable = serde_ipld_dagcbor::from_slice(&bytes)?; @@ -580,7 +584,7 @@ impl PrivateNode { pub(crate) async fn store_and_get_private_ref( &self, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut (impl CryptoRngCore + CondSend), ) -> Result { match self { @@ -618,7 +622,7 @@ impl PrivateNode { /// /// #[async_std::main] /// async fn main() { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let forest = &mut HamtForest::new_rsa_2048_rc(rng); /// let dir = PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng); @@ -636,7 +640,7 @@ impl PrivateNode { pub async fn load( access_key: &AccessKey, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, parent_name: Option, ) -> Result { let private_ref = access_key.derive_private_ref()?; @@ -647,7 +651,7 @@ impl PrivateNode { pub async fn store( &self, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut (impl CryptoRngCore + CondSend), ) -> Result { let private_ref = &self.store_and_get_private_ref(forest, store, rng).await?; @@ -686,14 +690,14 @@ mod tests { use crate::private::forest::hamt::HamtForest; use rand_chacha::ChaCha12Rng; use rand_core::SeedableRng; - use wnfs_common::MemoryBlockStore; + use wnfs_common::blockstore::InMemoryBlockstore; #[async_std::test] async fn serialized_private_node_can_be_deserialized() { let rng = &mut ChaCha12Rng::seed_from_u64(0); let content = b"Lorem ipsum dolor sit amet"; let forest = &mut HamtForest::new_rsa_2048_rc(rng); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let file = PrivateFile::with_content( &forest.empty_name(), Utc::now(), diff --git a/wnfs/src/private/node/serializable.rs b/wnfs/src/private/node/serializable.rs index bc669664..875449a9 100644 --- a/wnfs/src/private/node/serializable.rs +++ b/wnfs/src/private/node/serializable.rs @@ -1,11 +1,10 @@ use super::SnapshotKey; use crate::private::{encrypted::Encrypted, FileContent}; -use libipld_core::cid::Cid; use semver::Version; use serde::{Deserialize, Serialize}; use skip_ratchet::Ratchet; use std::collections::BTreeMap; -use wnfs_common::{HashOutput, Metadata}; +use wnfs_common::{ipld_core::cid::Cid, HashOutput, Metadata}; use wnfs_nameaccumulator::{NameAccumulator, NameSegment}; //-------------------------------------------------------------------------------------------------- diff --git a/wnfs/src/private/previous.rs b/wnfs/src/private/previous.rs index 6564e2c1..cc9e38a6 100644 --- a/wnfs/src/private/previous.rs +++ b/wnfs/src/private/previous.rs @@ -4,10 +4,11 @@ use super::{ }; use crate::error::FsError; use anyhow::{bail, Result}; -use libipld_core::cid::Cid; use skip_ratchet::{PreviousIterator, Ratchet}; use std::collections::BTreeSet; -use wnfs_common::{utils::Arc, BlockStore, PathNodes, PathNodesResult}; +use wnfs_common::{ + blockstore::Blockstore, ipld_core::cid::Cid, utils::Arc, PathNodes, PathNodesResult, +}; //-------------------------------------------------------------------------------------------------- // Type Definitions @@ -107,7 +108,7 @@ impl PrivateNodeHistory { /// Returns `None` if there is no such node in the `PrivateForest` at that point in time. pub async fn get_previous_node( &mut self, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { let Some(previous_ratchet) = self.ratchets.next() else { return Ok(None); @@ -157,7 +158,7 @@ impl PrivateNodeHistory { /// That should only happen for all nodes or for none. pub async fn get_previous_dir( &mut self, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> { match self.get_previous_node(store).await? { Some(PrivateNode::Dir(dir)) => Ok(Some(dir)), @@ -173,7 +174,7 @@ impl PrivateNodeHistory { /// That should only happen for all nodes or for none. pub async fn get_previous_file( &mut self, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result>> { match self.get_previous_node(store).await? { Some(PrivateNode::File(file)) => Ok(Some(file)), @@ -201,7 +202,7 @@ impl PrivateNodeOnPathHistory { path_segments: &[String], search_latest: bool, forest: F, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { // To get the history on a node on a path from a given directory that we // know its newest and oldest ratchet of, we need to generate @@ -273,7 +274,7 @@ impl PrivateNodeOnPathHistory { target_path_segment: &String, search_latest: bool, forest: F, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result<(Vec<(Arc, String)>, PrivateNodeHistory)> { // We only search for the latest revision in the private node. // It may have been deleted in future versions of its ancestor directories. @@ -335,7 +336,7 @@ impl PrivateNodeOnPathHistory { /// Step the history one revision back and retrieve the node at the configured path. /// /// Returns `None` if there is no more previous revisions. - pub async fn get_previous(&mut self, store: &impl BlockStore) -> Result> { + pub async fn get_previous(&mut self, store: &impl Blockstore) -> Result> { // Finding the previous revision of a node works by trying to get // the previous revision of the path elements starting on the deepest // path node working upwards, in case the history of lower nodes @@ -403,7 +404,7 @@ impl PrivateNodeOnPathHistory { /// more history entries. async fn find_and_step_segment_history( &mut self, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result, String)>>> { let mut working_stack = Vec::with_capacity(self.path.len()); @@ -440,7 +441,7 @@ impl PrivateNodeOnPathHistory { async fn repopulate_segment_histories( &mut self, working_stack: Vec<(Arc, String)>, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result { // Work downwards from the previous history entry of a path segment we found for (directory, path_segment) in working_stack { @@ -501,11 +502,11 @@ mod tests { use chrono::Utc; use rand_chacha::ChaCha12Rng; use rand_core::SeedableRng; - use wnfs_common::MemoryBlockStore; + use wnfs_common::blockstore::InMemoryBlockstore; struct TestSetup { rng: ChaCha12Rng, - store: MemoryBlockStore, + store: InMemoryBlockstore<64>, forest: Arc, root_dir: Arc, discrepancy_budget: usize, @@ -514,7 +515,7 @@ mod tests { impl TestSetup { fn new() -> Self { let mut rng = ChaCha12Rng::seed_from_u64(0); - let store = MemoryBlockStore::default(); + let store = InMemoryBlockstore::<64>::new(); let forest = Arc::new(HamtForest::new_rsa_2048(&mut rng)); let root_dir = PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), &mut rng); diff --git a/wnfs/src/private/share.rs b/wnfs/src/private/share.rs index cf7b5cee..2164fd03 100644 --- a/wnfs/src/private/share.rs +++ b/wnfs/src/private/share.rs @@ -24,7 +24,10 @@ pub mod sharer { use anyhow::Result; use async_stream::try_stream; use futures::{Stream, TryStreamExt}; - use wnfs_common::{BlockStore, CODEC_RAW}; + use wnfs_common::{ + blockstore::{block::Block as _, Blockstore}, + Blake3Block, CODEC_RAW, + }; use wnfs_nameaccumulator::{Name, NameSegment}; /// Encrypts and shares a access key with multiple recipients using their @@ -36,7 +39,7 @@ pub mod sharer { sharer_root_did: &str, recipient_exchange_root: PublicLink, forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result<()> { let mut exchange_keys = fetch_exchange_keys(recipient_exchange_root, store).await; let encoded_key = &serde_ipld_dagcbor::to_vec(access_key)?; @@ -47,7 +50,9 @@ pub mod sharer { let share_label = create_share_name(share_count, sharer_root_did, &public_key_modulus, forest); - let access_key_cid = store.put_block(encrypted_key, CODEC_RAW).await?; + let block = Blake3Block::new(CODEC_RAW, encrypted_key); + let access_key_cid = block.cid()?; + store.put(block).await?; forest .put_encrypted(&share_label, Some(access_key_cid), store) @@ -62,7 +67,7 @@ pub mod sharer { /// yield the exchange key's value. pub async fn fetch_exchange_keys( recipient_exchange_root: PublicLink, - store: &impl BlockStore, + store: &impl Blockstore, ) -> impl Stream> + '_ { Box::pin(try_stream! { let root_dir = recipient_exchange_root @@ -106,7 +111,7 @@ pub mod recipient { private::{forest::traits::PrivateForest, AccessKey, PrivateKey, PrivateNode}, }; use anyhow::Result; - use wnfs_common::BlockStore; + use wnfs_common::{blockstore::Blockstore, BlockStoreError}; use wnfs_hamt::Hasher; use wnfs_nameaccumulator::Name; @@ -117,7 +122,7 @@ pub mod recipient { recipient_exchange_key: &[u8], sharer_root_did: &str, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { for share_count in share_count_start..share_count_start + limit { let share_label = sharer::create_share_name( @@ -149,7 +154,7 @@ pub mod recipient { share_label: &Name, recipient_key: &impl PrivateKey, forest: &impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result { // Get cid to encrypted payload from sharer's forest using share_label let access_key_cid = forest @@ -163,7 +168,10 @@ pub mod recipient { .ok_or(ShareError::AccessKeyNotFound)?; // Get encrypted access key from store using cid - let encrypted_access_key = store.get_block(access_key_cid).await?.to_vec(); + let encrypted_access_key = store + .get(access_key_cid) + .await? + .ok_or_else(|| BlockStoreError::CIDNotFound(*access_key_cid))?; // Decrypt access key using recipient's private key and decode it. let access_key: AccessKey = @@ -194,7 +202,7 @@ mod tests { use chrono::Utc; use rand_chacha::ChaCha12Rng; use rand_core::SeedableRng; - use wnfs_common::{utils::Arc, MemoryBlockStore}; + use wnfs_common::{blockstore::InMemoryBlockstore, utils::Arc}; mod helper { use crate::{ @@ -208,13 +216,13 @@ mod tests { use chrono::Utc; use rand_core::CryptoRngCore; use wnfs_common::{ + blockstore::Blockstore, utils::{Arc, CondSend}, - BlockStore, }; pub(super) async fn create_sharer_dir( forest: &mut impl PrivateForest, - store: &impl BlockStore, + store: &impl Blockstore, rng: &mut (impl CryptoRngCore + CondSend), ) -> Result> { let mut dir = PrivateDirectory::new_and_store( @@ -241,7 +249,7 @@ mod tests { } pub(super) async fn create_recipient_exchange_root( - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result<(RsaPrivateKey, Arc)> { let key = RsaPrivateKey::new()?; let exchange_key = key.get_public_key().get_public_key_modulus()?; @@ -263,7 +271,7 @@ mod tests { #[async_std::test] async fn can_share_and_recieve_share() { let rng = &mut ChaCha12Rng::seed_from_u64(0); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let sharer_root_did = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"; @@ -317,7 +325,7 @@ mod tests { #[async_std::test] async fn serialized_share_payload_can_be_deserialized() { let rng = &mut ChaCha12Rng::seed_from_u64(0); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let dir = PrivateDirectory::new_and_store(&forest.empty_name(), Utc::now(), forest, store, rng) @@ -339,7 +347,7 @@ mod tests { #[async_std::test] async fn find_latest_share_counter_finds_highest_count() { let rng = &mut ChaCha12Rng::seed_from_u64(0); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let forest = &mut HamtForest::new_rsa_2048_rc(rng); let sharer_root_did = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"; diff --git a/wnfs/src/private/snapshots/wnfs__private__directory__snapshot_tests__private_fs.snap.new b/wnfs/src/private/snapshots/wnfs__private__directory__snapshot_tests__private_fs.snap.new new file mode 100644 index 00000000..c0e61901 --- /dev/null +++ b/wnfs/src/private/snapshots/wnfs__private__directory__snapshot_tests__private_fs.snap.new @@ -0,0 +1,811 @@ +--- +source: wnfs/src/private/directory.rs +assertion_line: 2597 +expression: values +--- +[ + { + "cid": "bafyr4iaavxdony4qex6xrblo2n6gohzddppav4wioerxf2fn4ey47nagfe", + "value": { + "accumulator": { + "generator": { + "/": { + "bytes": "DnwXmD/vORPcLzdf1evo7nGljNInOtYHpODrD3+82Nnpu0qfQPxFLKSB2dhylrLkh4UmTnLZtphq+jBbSjrWkqRf6C/qEToqzAhkAPtkF048lnLaI3UjBCXagQjJv8boXybWdaxiKxTFN2nu9B2vzNyUl1QqO9wXmNkzWM1P4T8lIm6FTjWSbHg/TVTXkpv8nTgQIUA1A0Kk7jEtjb/Vl8VdTZ2UgBywKE1Pvf8HbmXDc6Cjg0K5+XXC6SW1Bk71iLdLM174Mu8KWDjb3qotRpqrGGeSIv1KI1v1VWCI8ZuohkVe4zT5JvzyKIizsVDKcPTKGR60H6enSeQZgShFww" + } + }, + "modulus": { + "/": { + "bytes": "x5cM7tzDsHVEkCAaeqYTzXOREIHHkPXxqHJvRjVQu1t/8NuOHqEYnscvk9FlABG9chrurMKs3jKgQQfwZIwoE6MfWwt3Zf+LRLS2/8kzhLZG6wnHz16FktQOozyAA581tPFKBLUfe/14G+TRZzFkuo65kcLE1zC7vjX1kr3vUkr36Nrv0mxm/ALEea+J1k03P0QnCUOd5mzrlV8+o31RWfYTWAn4UzS1yxgTrdyAzQVgnxCsapWtZYcskJUlva0yvHKVkmQpIPJMYdxbPDt5I+VrFqTZ03PYch8ko/wPGzEx9VYVFyhmvMww+VBUyCTnM6XraBf3vBY5nUjGNhzH5Q" + } + } + }, + "root": [ + { + "/": { + "bytes": "6Q0" + } + }, + [ + { + "Values": [ + [ + { + "/": { + "bytes": "lIqujxHCkwppW376IJssGcxy5p8TLQrS9DpbT14Dh5NsUpxAbhyp6ZOPX6GrWLIL2jxhfHMLACr/PUy/Xk5QM+MdTFbGInt/cT5Nr8ATR6r6RdEjU9wh7n7wDCxVoYceu4LwpoHa74Os7185/7DOBYiqdG7WV5Cy4AOpLSdabndXhb+wMKWHXrkoyOi9R0UxtBXJWnNdALZTvkEj3drKeHfaH2jvkAap1bL8th3mZr7HhfCJMO3gzu8Ut2tALsxWdVOL9BoVEc+GPjlo7W4pz2pCM8Io5unEnb8nwdlakQpgOGsjo9SxX7vjccMgoYma43PVxCUk4lrr0tn/Wite+g" + } + }, + [ + { + "/": "bafkr4ica5jxbgptjixaefiihhiueqiw2jh5opj77yhjf7xbalqjq3i7p24" + }, + { + "/": "bafkr4ihckkhdnl2o2aruyty5k43rzqserloitjkmc6c6tmmjqhz4kfyapa" + } + ] + ] + ] + }, + { + "Values": [ + [ + { + "/": { + "bytes": "oQFcAlCbAaqjLdfLoKs5ES5a+CNCfJz16DfVCFUsXAHhv1IFwEoWZrNxcm/e9ufBeH4YIGW05YN9aoy4iv6iHBeT8XgHay5LgBUKWAWl3NPMlt/N9Y7hk5kjynmAXNI8nkGwKfe0UamToMdLTpqpzeiTpjo2D/sIHDwZBpGAe/M496cLPZAXQe/nkqiePII8UfpIuoEJ0MaZWcOVIBJ+15YhJSW/f1ver2dr3TpWqJzZ80Ftc+oUJSZ3zqQwz6EJC1bqIfMufm1MjSZV4s09xe5QnI7WSjK/Z+jintpsAZOJ6znSrj+u12MKOKbxnykxRCm+8KmVqaeRqHzUmAY7Zg" + } + }, + [ + { + "/": "bafkr4ie3csut53hpy4iuinpnbub52zalqiskgjhu7avkyj7t553gfvxjbu" + }, + { + "/": "bafkr4igqi5pawxlga75cbj4rtmxviawihqrrndrmbmzfzt7membnfvpdgy" + } + ] + ] + ] + }, + { + "Values": [ + [ + { + "/": { + "bytes": "nn28+vTVE59osEe6bTqsYv8A8SfdDVCxvTOLSnJZYLld5XAOXozb/mY+7V4v5jiODRRrasZ8kAm9zypgrvMOtTgroVFEinGAShG+ps+ivxJwhG2xAKIsUnsOQ4t07ptavFyLbvBBg7L3Idm1fUIXIDfEZHAPb0UQzDGgZKBgNLlwEdmLRML0aOh7aMrEU0Y6bi+95Mild/lUxp8k1q/+brxn5hD7+C/aaFjSadKY7L1/4/szL/9A6Ss+WXVx+B8HHDpn5UfIYO9SDIcLzox/ywG/bxBF8safMPZwlrb5t6TRdpXBveTcVjDG+9cvPoftPoNm/PZCJ+Yf5sSWbhfUlA" + } + }, + [ + { + "/": "bafkr4ifclqucnvehol5nhv7o4it2jcrykb7vqfueh3h5qguziesf3dz4uq" + }, + { + "/": "bafkr4igm2czfndo37tusfikagtz5kejhstu4s6ti7jwzg7gajiie2zzc7y" + } + ] + ] + ] + }, + { + "Values": [ + [ + { + "/": { + "bytes": "pE8dY9E8CCiMGJRpCV9bGSxYSezB5SECK6mbnUJgXXZDs5taOLWSROGajSU0+I4UWQCND70APPfRhsEH2IxIYMBmnjS6iadwCB5l5IzS0qIMZp3SdeCOHysvX/mt7j7zMxvSgMYpd/yBV+JpjHW9EXv6Nt1np8dCCiQULZywZOoX3nJxy+BT6AEEytNJUFyPqefpXL3q7swVTyWw9UySP97mEjrEFdKEbtH4JdPmqIRwbEu4GA3gJ2w8psNdqzTxmUa4HuQcU/ta/M3l5zceNcD5E3G4PIcROZkSx7wLCdnDxXSU3vIBYvCn62DDgeyWLqcc4TwR78ls9QTXOQnN2g" + } + }, + [ + { + "/": "bafkr4ibojs5rmbq5bwcsi2lfi7zp2ktnr2awouczs3rul3b4mioxhqdi7q" + }, + { + "/": "bafkr4ig2dh6lqnfslf3waewp52o4m7vjgfe7rpaguf4r7hnltqelodz4om" + } + ] + ] + ] + }, + { + "Values": [ + [ + { + "/": { + "bytes": "J/4F0qCn+UoYdwTymAGlzfpfFMaqi6qaxDiQZ0UZiMnbmlz0tf6jD0vuYVaopoS40TSfQLRF9GJ9n1tItJsvPiQzgQg2O8LSRH9yPimXczCxzG6pVBbNzlq9kSeSA0ydIjE0MQIj7pDiq0dHjbJLAFgYo82bfndbtB7jlETUijI7lO6MJnrb0DonXzH8DKh1MDtG2SjFjUMmj4cp1t/gyZRTpYIxboqT7GYqPD/C4Tc1ulEeN1Px0evQs/V2ihdKi8/+oJND5ZddkSI0w0H8SvFRcXgyl95SXE9oA2u/JsJFNsDujBPH9nU5pikYknf4hEsQJWoM4RMR8l0ZS/Io1Q" + } + }, + [ + { + "/": "bafkr4icdf6vi235jl6bqrmg3fmdba7ximvdsac45syigmxmpb4wolbtidy" + }, + { + "/": "bafkr4ie4rlwzcbhcxirnqhgdxngizjvnybonto5hxevbipxkzpkhj2y55q" + } + ] + ] + ] + }, + { + "Values": [ + [ + { + "/": { + "bytes": "lKhU/rclBXugS/Th2tOyzwpPrsZd2C/gl/HHo9J4WaIXFgjvQyoqrvRPPcKzuHzbeHdTjcG1ihsQ5ia+atYGNCx9RhfxnjXrCxdMpP4ZTOLfuJhi6vQ840NjcutdMfUp3OmZCq3klhwMCLbvW3Rg9269FBEhXrzhjiFFopL9QuzUyv3jzbC9+nznXA3mg+8yO8lFCYCklRWiEe/23KZdmn8h0alILcw1KM2+0wcKIG0a7kh3GknnWBhZp0Rcm5aKvTca/E6Gna6145yCZ51Vra2QaiPq5xbngsnlpA/GHuaA1t+fVBnyi54eeFFNurfoxrq/hR2dq6gsJDpg2NDJAA" + } + }, + [ + { + "/": "bafkr4igljnzokpfougv3yiqmsxhkqpvz26q6y7jadyuhmzpsvggz2ver7e" + }, + { + "/": "bafkr4igtg3oup6h2veg7susxuthdrad6zlifvm2ejxt7gbiq6r5ptyrrzm" + } + ] + ], + [ + { + "/": { + "bytes": "ZCS6Ok+fnR00uTBixwlVE0L9Ch+lN3joVJ8yUl4cASzc420cupVjWmkETKVCuWtGOB87gKXG9+K5cJZwujztD3f02l1XVVnIrlIzxeMAIoeghKL2Bc//LccukHuM24yxuWO4ZK5Ui03nXmjVNp3AoUsGUYA9tcRHSgP39HSCvZRFMoB917TBzKgcYgne0ty2JYcovcGzzA6qMHeW70GOdolbfiHBGn2+4vB7et1rsh5eu5wnn4W9Rt0NwYaIklm5aXtuazFUI7SmA/DOzr42dGcayx5hk167gk7OWnrhzQgfNaDkLS5JFUwBAgV6o3/6HHn1Rk0BRRQ6l3RJuaI50g" + } + }, + [ + { + "/": "bafkr4ic4myx7wgjgmmygtaxaz33krp5mxx2zeciu6xvcwsv63eegcq4rju" + }, + { + "/": "bafkr4ih2d4uzcjq5uagh4r7woymauxmyg3qar2bea5pv7jul7mqpy5rljq" + } + ] + ] + ] + }, + { + "Values": [ + [ + { + "/": { + "bytes": "k72QbYimqbJUBm4paL8SliiDyvfzbH/W2LVTx73tSvlbi627HaB0Wl3yuCOXyKUsTHnflhG/PlD+FDhxyt41aBci/QCKNcWELMwbThzEvwVpOyr6nmY8CK2xZExMVYZG9X4p8yxoLk7lL7O7dmKANvD1c8dMtZ163XEFn1jfOEF9wgUutpZIJKYv25TNiuR7xQEvrkG12tglGTCFcYTlQqhrGusqStzWN2YxUhwAX5oJGLugzDIYzul72D4tMZTFuBeDfKkPc4AjCIZytRqo5nph+m0w866pHfQWaFVWF1UGjiBjr1bpMjem3/9kvmDIHbz5ul5ZERF+W57CzO/bAw" + } + }, + [ + { + "/": "bafkr4ig24orkcp75447hy2abpan36i3woaerfsg6bnu4z656d6xpa22jsu" + } + ] + ], + [ + { + "/": { + "bytes": "Aviy7qyjHRxS/HMSMxg012YAggdDAltf8w6ryYdTJiigaO6xjanOWCYKpoUOhgnQ1iuwuqnoyizRiN30TRHug6v/mp+8i3fghWAvYJ5rFatUikwCeMQu00iBBEvtBNGWF+xezlqByGPiF+YM2sEn0kt92CSunAOmvdGWAdJ3Eg3AF+gnSNhv2C4vIxFLgPcnbLAQfvB8yw+IH+ebykkMgkxPubPWT6Myu/OV3KsWsxQWYHHyYf7hD8oFn/CAoRMhLO+LNjUbrVg6ISC8eSK6yTOV+pPkstdXM3ew2WZ1sUr+4kV3fsRJTNkygT1dL3QwBzhxRaraxclc5QSBkXj2NQ" + } + }, + [ + { + "/": "bafkr4iabb422gnp45fdjd4onr567olqprcl53oblnyima3oenyqvae3ifq" + } + ] + ] + ] + }, + { + "Values": [ + [ + { + "/": { + "bytes": "q8NwXtwPFv7pCNj+dAhEN2fvf/jJktEWKbkzqbRlTVt4J289ERcIiSEm0jNWLqAJFchuK+3PhPWxqXdchcoyf1a1WS8DihWn7CkC3EId7KyJ5YGyCJ49VgbP7pbzkR/00db2Gkf4YBvoudfnXlA4lAQvz8RD3LzPmn9NQDIaq6m24xSFHTi5cRJhBP9PFq78JOcxz36J3qDdhQj7YOoME1YwyDP6Zi8KqgIofPZOwvTjykUkdfHIlxymI8Fheo4F0kXeffLl/Huqe9b9lydbVDTJliZF3lIw+CG6F+JtVUD8v53g4uLmxwc7CwDzKQd0WRTZQL3LOMYD/5v+665cWQ" + } + }, + [ + { + "/": "bafkr4iczjy3vg4v3snxzouqcf7hos3gta5ewwrqh6sp6243kp6nlxv6axi" + } + ] + ] + ] + } + ] + ], + "structure": "hamt", + "version": "0.1.0" + }, + "bytes": "pGRyb290gkLpDYihZlZhbHVlc4GCWQEAlIqujxHCkwppW376IJssGcxy5p8TLQrS9DpbT14Dh5NsUpxAbhyp6ZOPX6GrWLIL2jxhfHMLACr/PUy/Xk5QM+MdTFbGInt/cT5Nr8ATR6r6RdEjU9wh7n7wDCxVoYceu4LwpoHa74Os7185/7DOBYiqdG7WV5Cy4AOpLSdabndXhb+wMKWHXrkoyOi9R0UxtBXJWnNdALZTvkEj3drKeHfaH2jvkAap1bL8th3mZr7HhfCJMO3gzu8Ut2tALsxWdVOL9BoVEc+GPjlo7W4pz2pCM8Io5unEnb8nwdlakQpgOGsjo9SxX7vjccMgoYma43PVxCUk4lrr0tn/Wite+oLYKlglAAFVHiBA6m4TPmlFwEKhBzooSCLaSfrnp//B0l/cIFwTDaPv19gqWCUAAVUeIOJSjjavTtAjTE8dVzccwkSK3ImlTBeF6bGJgfPFFwB4oWZWYWx1ZXOBglkBAKEBXAJQmwGqoy3Xy6CrOREuWvgjQnyc9eg31QhVLFwB4b9SBcBKFmazcXJv3vbnwXh+GCBltOWDfWqMuIr+ohwXk/F4B2suS4AVClgFpdzTzJbfzfWO4ZOZI8p5gFzSPJ5BsCn3tFGpk6DHS06aqc3ok6Y6Ng/7CBw8GQaRgHvzOPenCz2QF0Hv55KonjyCPFH6SLqBCdDGmVnDlSASfteWISUlv39b3q9na906Vqic2fNBbXPqFCUmd86kMM+hCQtW6iHzLn5tTI0mVeLNPcXuUJyO1koyv2fo4p7abAGTies50q4/rtdjCjim8Z8pMUQpvvCplamnkah81JgGO2aC2CpYJQABVR4gmxSpPuzvxxFENe0NA91kC4IkoyT0+CqsJ/PvdmLW6Q3YKlglAAFVHiDQR14LXWYH+iCnkZsvVALIPCMWjiwLMlzP7CMC0tXjNqFmVmFsdWVzgYJZAQCefbz69NUTn2iwR7ptOqxi/wDxJ90NULG9M4tKcllguV3lcA5ejNv+Zj7tXi/mOI4NFGtqxnyQCb3PKmCu8w61OCuhUUSKcYBKEb6mz6K/EnCEbbEAoixSew5Di3Tum1q8XItu8EGDsvch2bV9QhcgN8RkcA9vRRDMMaBkoGA0uXAR2YtEwvRo6HtoysRTRjpuL73kyKV3+VTGnyTWr/5uvGfmEPv4L9poWNJp0pjsvX/j+zMv/0DpKz5ZdXH4HwccOmflR8hg71IMhwvOjH/LAb9vEEXyxp8w9nCWtvm3pNF2lcG95NxWMMb71y8+h+0+g2b89kIn5h/mxJZuF9SUgtgqWCUAAVUeIKJcKCbUh3L609fu4iekijhQf1gWhD7P2BqZQSRdjzyk2CpYJQABVR4gzNCyVo3b/OkioUA089URJ5TpyXpo+m2TfMBKEE1nIv6hZlZhbHVlc4GCWQEApE8dY9E8CCiMGJRpCV9bGSxYSezB5SECK6mbnUJgXXZDs5taOLWSROGajSU0+I4UWQCND70APPfRhsEH2IxIYMBmnjS6iadwCB5l5IzS0qIMZp3SdeCOHysvX/mt7j7zMxvSgMYpd/yBV+JpjHW9EXv6Nt1np8dCCiQULZywZOoX3nJxy+BT6AEEytNJUFyPqefpXL3q7swVTyWw9UySP97mEjrEFdKEbtH4JdPmqIRwbEu4GA3gJ2w8psNdqzTxmUa4HuQcU/ta/M3l5zceNcD5E3G4PIcROZkSx7wLCdnDxXSU3vIBYvCn62DDgeyWLqcc4TwR78ls9QTXOQnN2oLYKlglAAFVHiAuTLsWBh0NhSRpZUfy/SptjoFnUFmW40XsPGIdc8Bo/NgqWCUAAVUeINoZ/Lg0sll3YBLP7p3GfqkxSfi8BqF5H52rnAi3DzxzoWZWYWx1ZXOBglkBACf+BdKgp/lKGHcE8pgBpc36XxTGqouqmsQ4kGdFGYjJ25pc9LX+ow9L7mFWqKaEuNE0n0C0RfRifZ9bSLSbLz4kM4EINjvC0kR/cj4pl3MwscxuqVQWzc5avZEnkgNMnSIxNDECI+6Q4qtHR42ySwBYGKPNm353W7Qe45RE1IoyO5TujCZ629A6J18x/AyodTA7RtkoxY1DJo+HKdbf4MmUU6WCMW6Kk+xmKjw/wuE3NbpRHjdT8dHr0LP1dooXSovP/qCTQ+WXXZEiNMNB/ErxUXF4MpfeUlxPaANrvybCRTbA7owTx/Z1OaYpGJJ3+IRLECVqDOETEfJdGUvyKNWC2CpYJQABVR4gQy+qjW+pX4MIsNsrBhB+6GVHIAudlhBmXY8PLOWGaB7YKlglAAFVHiCciu2RBOK6Itgcw7tMjKatwFzZu6e5KhQ+6svUdOsd7KFmVmFsdWVzgoJZAQCUqFT+tyUFe6BL9OHa07LPCk+uxl3YL+CX8cej0nhZohcWCO9DKiqu9E89wrO4fNt4d1ONwbWKGxDmJr5q1gY0LH1GF/GeNesLF0yk/hlM4t+4mGLq9DzjQ2Ny610x9Snc6ZkKreSWHAwItu9bdGD3br0UESFevOGOIUWikv1C7NTK/ePNsL36fOdcDeaD7zI7yUUJgKSVFaIR7/bcpl2afyHRqUgtzDUozb7TBwogbRruSHcaSedYGFmnRFybloq9Nxr8ToadrrXjnIJnnVWtrZBqI+rnFueCyeWkD8Ye5oDW359UGfKLnh54UU26t+jGur+FHZ2rqCwkOmDY0MkAgtgqWCUAAVUeIMtLcuU8rqGrvCIMlc6oPrnXoex9IB4odmXyqY2dVJH52CpYJQABVR4g0zbdR/j6qQ35UlekzjiAfsrQWrNETefzBRD0evniMcuCWQEAZCS6Ok+fnR00uTBixwlVE0L9Ch+lN3joVJ8yUl4cASzc420cupVjWmkETKVCuWtGOB87gKXG9+K5cJZwujztD3f02l1XVVnIrlIzxeMAIoeghKL2Bc//LccukHuM24yxuWO4ZK5Ui03nXmjVNp3AoUsGUYA9tcRHSgP39HSCvZRFMoB917TBzKgcYgne0ty2JYcovcGzzA6qMHeW70GOdolbfiHBGn2+4vB7et1rsh5eu5wnn4W9Rt0NwYaIklm5aXtuazFUI7SmA/DOzr42dGcayx5hk167gk7OWnrhzQgfNaDkLS5JFUwBAgV6o3/6HHn1Rk0BRRQ6l3RJuaI50oLYKlglAAFVHiBcZi/7GSZjMGmC4M72qL+svfWSCRT16itKvtkIYUORTdgqWCUAAVUeIPofKZEmHaAMfkf2dhgKXZg24AjoJAdfX6aL+yD8ditMoWZWYWx1ZXOCglkBAJO9kG2IpqmyVAZuKWi/EpYog8r382x/1ti1U8e97Ur5W4utux2gdFpd8rgjl8ilLEx535YRvz5Q/hQ4ccreNWgXIv0AijXFhCzMG04cxL8FaTsq+p5mPAitsWRMTFWGRvV+KfMsaC5O5S+zu3ZigDbw9XPHTLWdet1xBZ9Y3zhBfcIFLraWSCSmL9uUzYrke8UBL65BtdrYJRkwhXGE5UKoaxrrKkrc1jdmMVIcAF+aCRi7oMwyGM7pe9g+LTGUxbgXg3ypD3OAIwiGcrUaqOZ6YfptMPOuqR30FmhVVhdVBo4gY69W6TI3pt//ZL5gyB28+bpeWRERfluewszv2wOB2CpYJQABVR4g2uOioT/95z58aAF4G78jdnAJEsjeC2nM+74frvBrSZWCWQEAAviy7qyjHRxS/HMSMxg012YAggdDAltf8w6ryYdTJiigaO6xjanOWCYKpoUOhgnQ1iuwuqnoyizRiN30TRHug6v/mp+8i3fghWAvYJ5rFatUikwCeMQu00iBBEvtBNGWF+xezlqByGPiF+YM2sEn0kt92CSunAOmvdGWAdJ3Eg3AF+gnSNhv2C4vIxFLgPcnbLAQfvB8yw+IH+ebykkMgkxPubPWT6Myu/OV3KsWsxQWYHHyYf7hD8oFn/CAoRMhLO+LNjUbrVg6ISC8eSK6yTOV+pPkstdXM3ew2WZ1sUr+4kV3fsRJTNkygT1dL3QwBzhxRaraxclc5QSBkXj2NYHYKlglAAFVHiABDzWjNfzpRpHxzY999y4PiJfduCtuEMBtxG4hUBNoLKFmVmFsdWVzgYJZAQCrw3Be3A8W/ukI2P50CEQ3Z+9/+MmS0RYpuTOptGVNW3gnbz0RFwiJISbSM1YuoAkVyG4r7c+E9bGpd1yFyjJ/VrVZLwOKFafsKQLcQh3srInlgbIInj1WBs/ulvORH/TR1vYaR/hgG+i51+deUDiUBC/PxEPcvM+af01AMhqrqbbjFIUdOLlxEmEE/08Wrvwk5zHPfoneoN2FCPtg6gwTVjDIM/pmLwqqAih89k7C9OPKRSR18ciXHKYjwWF6jgXSRd598uX8e6p71v2XJ1tUNMmWJkXeUjD4IboX4m1VQPy/neDi4ubHBzsLAPMpB3RZFNlAvcs4xgP/m/7rrlxZgdgqWCUAAVUeIFlON1Nyu5Nvl1ICL87pbNMHSWtGB/Sf7XNqf5q718C6Z3ZlcnNpb25lMC4xLjBpc3RydWN0dXJlZGhhbXRrYWNjdW11bGF0b3KiZ21vZHVsdXNZAQDHlwzu3MOwdUSQIBp6phPNc5EQgceQ9fGocm9GNVC7W3/w244eoRiexy+T0WUAEb1yGu6swqzeMqBBB/BkjCgTox9bC3dl/4tEtLb/yTOEtkbrCcfPXoWS1A6jPIADnzW08UoEtR97/Xgb5NFnMWS6jrmRwsTXMLu+NfWSve9SSvfo2u/SbGb8AsR5r4nWTTc/RCcJQ53mbOuVXz6jfVFZ9hNYCfhTNLXLGBOt3IDNBWCfEKxqla1lhyyQlSW9rTK8cpWSZCkg8kxh3Fs8O3kj5WsWpNnTc9hyHySj/A8bMTH1VhUXKGa8zDD5UFTIJOczpetoF/e8FjmdSMY2HMflaWdlbmVyYXRvclkBAA58F5g/7zkT3C83X9Xr6O5xpYzSJzrWB6Tg6w9/vNjZ6btKn0D8RSykgdnYcpay5IeFJk5y2baYavowW0o61pKkX+gv6hE6KswIZAD7ZBdOPJZy2iN1IwQl2oEIyb/G6F8m1nWsYisUxTdp7vQdr8zclJdUKjvcF5jZM1jNT+E/JSJuhU41kmx4P01U15Kb/J04ECFANQNCpO4xLY2/1ZfFXU2dlIAcsChNT73/B25lw3Ogo4NCufl1wukltQZO9Yi3SzNe+DLvClg4296qLUaaqxhnkiL9SiNb9VVgiPGbqIZFXuM0+Sb88iiIs7FQynD0yhketB+np0nkGYEoRcM=" + }, + { + "cid": "bafkr4ica5jxbgptjixaefiihhiueqiw2jh5opj77yhjf7xbalqjq3i7p24", + "value": { + "inumber": { + "/": { + "bytes": "9pQ3MSKex2oCplmGGVII5Owkk5agvM+2Vct/C+9ZjDk" + } + }, + "name": { + "/": { + "bytes": "S/ls0kBalPwc+iDXWpahp3wQ2+WOOxYGreewh79e1lFl3+Z2zFkTn4eKu8/HP5/BZqLxy4DwZB4Y/eejZF9ID7+rUizD3kzM0YmGBgiTujuXiVpIPNk4//qJm7Fa9qdZrBYTciHY9aoXip0UJK88GtCP6nn6TWutcuf+7prysBkYjRlFxswEDMfqmAy4dpgUPLWilkdj7IyHrokqo1VT8QzROow9NMv+mPhWF+4M2lQpKKIvQGQ3DZc7C419p5dLUBzzOjS4w9AFrxzElEFGAhqytWoXEyqV5Lz/AtkIBjvb+oTVvFs1r/hpbEhmXURFnELqV+vHMSpa9NGzBosmDQ" + } + }, + "ratchet": { + "large": { + "/": { + "bytes": "jplWEnfjcZTajnfsX7TYhbL2nB3LesG4Pj7uJd8cT2o" + } + }, + "medium": { + "/": { + "bytes": "0Ja9S3VJOqUQXtJ0nFpa8R4vboY0eYAjXon9WM3ehqE" + } + }, + "mediumCounter": 39, + "salt": { + "/": { + "bytes": "bt7le++zTEs5jkCzohJnSEiXJZ8uJSGUexDLp7zen2c" + } + }, + "small": { + "/": { + "bytes": "hZBPNt3qnCpdcqWUqvX0SiwUVrdr7rq9l2HHefy4YO8" + } + }, + "smallCounter": 224 + } + }, + "bytes": "oH2Gl+wNVSW3s7m7wWtgqtsIh1un/gPGDKX0rQOC1+NESEkTjvIiL/vOiF6R1VA3ivH393UkzXl/1cUcqWt853+Ob4gcFfyBLIMbJUXENBOY8o4Az5G5SoV6KVv6s6rn2o9GEdHVLhGAf4Cbgjkvl/kIkRSE60uNWCp3Yvxq9sKfREnSYMONuvb+y0Q3Xyiohm7IgvWo647xaEEdisnC5WQ2yngYD6YW45iQxLG7M8y7/wwq2zYayz9rUj3Dtv5n18ItKzZA9YXbyAN6Q0rCXz6fiD5zv/zSBVWn4nXhKiwqQ+1ZBJnqdOKhl9SBqCF/jEz2xJl9rkeMWc/hW4WdfEtZYaP1F4Q/1i5cOfOlkrV7JgybMQmkgwEw/4fy4VZYjCoDQrazlwDswanQjCL8vlgdAmRwcU1AoewvobAiOnWC3DvoAgvGPaXS6FmC6Pdm8ANKCIECzDQMl4QQN1/uhSJB6ooqLjztbc0sQZTJUz1qoqyANkzH/ajANMaXX6HuCBfY80F61aPCwciUt9T2Q9XgCpWqqyk/tvWywSuLCw8iOGMM3GQexFIzedcZ+g8GRniabBuAnv64UUHK/SYTHG9o+zv1ZZY226oT5nrxf6hZ9gVHbS89Bu3OFzpSDIOhNODLs9elWDL4ou4DAKkWRycYKHpGC4i5uM0FxhHniKD0jkfqH5JrLQ==" + }, + { + "cid": "bafkr4ihckkhdnl2o2aruyty5k43rzqserloitjkmc6c6tmmjqhz4kfyapa", + "value": { + "wnfs/priv/dir": { + "entries": { + "movies": { + "contentCid": { + "/": "bafkr4ih2d4uzcjq5uagh4r7woymauxmyg3qar2bea5pv7jul7mqpy5rljq" + }, + "label": { + "/": { + "bytes": "i+Vcn1q1WampAbwZmkCKZj17z8+hGTZsqojySJW/v3w" + } + }, + "snapshotKey": { + "/": { + "bytes": "xjVdETOZFxTc/3EYwdj6HaxAExeWR13hDrMvlJipxK0" + } + }, + "temporalKey": { + "/": { + "bytes": "8EV+cWCG7lqz5IJseUnKe45Gghwlbhb2Y+hZNxvYUrIL6eEzWhcNYA" + } + } + } + }, + "headerCid": { + "/": "bafkr4ica5jxbgptjixaefiihhiueqiw2jh5opj77yhjf7xbalqjq3i7p24" + }, + "metadata": { + "created": 0, + "modified": 0 + }, + "previous": [], + "version": "1.0.0" + } + }, + "bytes": "Cza5T+uIf+6zBPzXJcYOTSgpGd8O8kMRKVEAGPlts5APSVvpUjmGAoI7Y/XnWZHq1b15armGka7r17rpipM/huGA7xf3OfzoqbUU7YvlGCXZI+o14XHoWVVLL9cgxAY4uvzYHnPAzZHB+8X+RO0ycxSvD6+UF1ZxAfsPWjCzPv4DIPmrLSvCg6cwpqgEBvK8V+q2Z3QbtWWRqkO/gQkFesgG34gR2DamupzbrzIdnbus6Wz9+FLJ6ZkpQ/ChabiOtFsDdOG7Y+ac0W7FDmIDF9aW4EdjdIgkO2ktbUS/oVqgfmPUDKzokFonBRlMCuQ9VtPfOyUyfA+J4lsWHP0/KVM4GcInevnPHHHSqYOfMyYUjSVs1Gk10/QQKXpBXUX6TGLMIUAWiDaxBH2LmbSD+cmtehkVR7CbKTkq5/vDf+prWKgTDSypFawbOcUoT4L1mBuBtb73p+CC+sYoQ6giRTbQjym1pJ0NOwjqeYIL3VmM" + }, + { + "cid": "bafkr4ie3csut53hpy4iuinpnbub52zalqiskgjhu7avkyj7t553gfvxjbu", + "value": { + "wnfs/priv/dir": { + "entries": { + "music": { + "contentCid": { + "/": "bafkr4igljnzokpfougv3yiqmsxhkqpvz26q6y7jadyuhmzpsvggz2ver7e" + }, + "label": { + "/": { + "bytes": "h5sQVvcQqIiy7t2E6J5E+LFlurXKT5QLEbHxGPVlDrA" + } + }, + "snapshotKey": { + "/": { + "bytes": "5X7tyBMCXzOlkKCsXIbFLWcXexyUQj0hZUIKtp4Wxz8" + } + }, + "temporalKey": { + "/": { + "bytes": "F46+nL5NLAa7hPDhWqejs7sWL42jPBbnr+ERUXGAyjmOPchbLDIdJA" + } + } + }, + "text.txt": { + "contentCid": { + "/": "bafkr4ifclqucnvehol5nhv7o4it2jcrykb7vqfueh3h5qguziesf3dz4uq" + }, + "label": { + "/": { + "bytes": "U3E47CR00Ze8SwdG3p7H2vciA4ixQzldWgCtKYH2zjU" + } + }, + "snapshotKey": { + "/": { + "bytes": "P0JI2br1vLOnHBj+FvdhqShwftCZmMbk4ev+kVeU8oo" + } + }, + "temporalKey": { + "/": { + "bytes": "0mdxowC9s8LBOHOWL/H/yL8IOqpGn9jtLO8kjKeLFoiiJp33clLz3g" + } + } + }, + "videos": { + "contentCid": { + "/": "bafkr4ihckkhdnl2o2aruyty5k43rzqserloitjkmc6c6tmmjqhz4kfyapa" + }, + "label": { + "/": { + "bytes": "DdDyd491x/Wbwc6Y/zI7cDEcqTTmtvgQnALgnhiZS2Q" + } + }, + "snapshotKey": { + "/": { + "bytes": "ncNrAzuzVnDzGUSeEtE4x+3ahIoEflbc7y3KcTYfnic" + } + }, + "temporalKey": { + "/": { + "bytes": "D8R7Iuad+1HW+9NI4pbFRQuAHbqTPCKB+Ipjyee8MApkjeh3zEFf5A" + } + } + } + }, + "headerCid": { + "/": "bafkr4igqi5pawxlga75cbj4rtmxviawihqrrndrmbmzfzt7membnfvpdgy" + }, + "metadata": { + "created": 0, + "modified": 0 + }, + "previous": [], + "version": "1.0.0" + } + }, + "bytes": "2dCKfxMwtLYKoHGOWQffL7tjJ8bbRdU7a0x5374pwy5cjcGVt56PntkRomDTJDJmHC2Oop0R0biHMO1++S/EoufQWEYJ1gW7dACUXJjX/bOyQFGRu3I+WVm1+JdWSvlwhf51JDvb1qVvTJzYsTlA+BOoQvb8mJ52ilO/0yBJBBoPOaElEXZKAqz/mFHJGUT0FO105AJSgcDHY04dhEbDtm328WK8dxd1iCojTHBC56M8JASWN6/2YR1ttJBEIrCDwxfza8FipU68gURdWXVYhR4wgSAhI95JYh1OKeoP58WUcID/adhzGpkm0M3y4Z2AHJbJnMO886ZzfCWaRbvyFiTJ7SvPiCl38i5HfTO4dcF/l05GT8WgDufvIG9RpaoTTSwIzSNqrrwvkBvQhdqgQV5SI6nmMmOJ1wPny3w85DqCZRilaWaTQ1YkG0Z9UJ+5ygisExOkWaZkzuudwnu+X/A590iVkiV4M8cnyY/zq8VCApUBIMlLYbxEMeuMoQRCDvG7vDJT87thsgUWWL0WTvTDf0G3UXggS6r6jQVDaQ9ILucMFDwGX/+NF8/xgTdkiaioKymm8neK3ufHgF9JknQpVnPKPO8prlhrsHRhuCo8vmreidXcN+EllnDyk+N5N7IExo2tTi2XUzD/BgD/oUvCHsle/CgCkbhgc/ArglccNFiTjGViW42K01Le3sbUPj3ASPQ+4RUt7S5RZxKkRmjdvsGI/lCBMxnia2VqEQA1y6szDH6gEw6v4n6VBEfJMhbjic6DT5MgzirU463PRUAwENdcS6qjecYmU9pRTAVSGCXlJ3zdqfPMfPq0CMH57TcjFR602OvA98EUBpqjZBdf6oMSM9sEmW5EAuXff6iDizvwEgZNlvTDyruscv85mSMrx+BSod7Yke8459fFz7g246l7BaPB9qC12NPdEQKMwpkTT0ynL/pzkwfTkPerxbLSHBPNgP21apGmikr4u0iIhzJCsxs8Ok9THOg1pyYwk++ZO/SPIWXrB7Pc8Zaqi6I=" + }, + { + "cid": "bafkr4igqi5pawxlga75cbj4rtmxviawihqrrndrmbmzfzt7membnfvpdgy", + "value": { + "inumber": { + "/": { + "bytes": "wTIY5Lj52cZAPjN2QxQb04Tvs5ben9hjXKIVD5UpCeE" + } + }, + "name": { + "/": { + "bytes": "WzUFTg2et93G6urhSL2Viqdf49sAgAv0vv8SE1SgzA2V80ukVHaZR6+PcbbkvJa7kqRzKbUJ8si3pckU/2L30Kmr+JVM38v6cQAT5N0y9KiTmXX6EyUIkQ5r+zfH8xybEhJ00mPJbRpB76OgZ24z9a1VLWQCcenR6GsrPWUkU94p3r8XBQtIBni/uHjKlpFvR/Csq+pmoBqK5qOYaDsgWn6nV8pgMIIRFifu6S7bw9SSMtRUrW/FFfcu1GjRHeq7UV71wyUGGB2gpC4Ekm8Y/tri1S3zHbLnh54ck+tjUZM0MMRSWnL+FvwXcYKaxfRmxooi0Jajw3zF+xGdW8hlnw" + } + }, + "ratchet": { + "large": { + "/": { + "bytes": "0Xcz7RLjVmm+AzcWeY2i2QLcclCjoJktNy65o58rQDw" + } + }, + "medium": { + "/": { + "bytes": "Nk4K4fSXXGSIL1hQ0gHHVGKjY/xSLm4fcLv3z0IPI5U" + } + }, + "mediumCounter": 187, + "salt": { + "/": { + "bytes": "ONa5zrgjyuV6QSBzqKdagXT6HqmDbOX6b0+TK6spVOw" + } + }, + "small": { + "/": { + "bytes": "/L33L32w93i0T7oGYx8u0Yxb9QWBumanpcvXJWQQWHY" + } + }, + "smallCounter": 183 + } + }, + "bytes": "DHAqFkyhSq1pfHhVFwjM3mOGavKHKzImFFIHQFbCO9GW5F1WvrJyRJ/O1ddtH1Y10UElHzGdBWCDGmAeCD3s9LliEeX/zviQrxll+49pBLuemBCrEec41NMorg/Izhf2ggaGoAnHClDJRy6v0DsNKMegjjQcJ9HOOqPLRTnjEJKJr1RRRBoLia9ibSAmHb3W67okaE0PParzKfe5+qhzirTGlnoN5y9cpjsErV5WK/V0+6o1loFRE5dvsgX87KdmyM033rKaE2Las8VJq4p+hIGuVxenuhptNI+VyRKfi4ZBz/2pOxNqh5vQGywPwNh/kVY+H9Riy1oJMJMep8BfJoLYgt8e0Nl+EAjYc/RKUi6QoUWAENvd2nhHUKjjW0y8+sQBFM0i735gkZFgIL5V7Eq6YM0FlJcBniBSUjkJOf/cGHyhAmQH9/XMf5Q4/8DKmOU7XSMhmTR2M1SDRspBomPlarXtUUVtER7p8+lGNcWWZAAGzFYhPiJ4wyaJXRVkZ0E/yFn+lGgWiKs9H+VpJZ0xFrB1PXhLbuIoUNgFEZvErIuHQdFzdwIwHQPjeIeR4Sf9cyZFMZS3puKYkE2K2ItF8XH1g89pPhijKeDp8/wBPAuouX4VhaHZQVVv6+aVohKWGSUNXWX2bTpDLP+/1aM5gQb9U1EsNNUrW8J5DwS9rYZg43NWsg==" + }, + { + "cid": "bafkr4ifclqucnvehol5nhv7o4it2jcrykb7vqfueh3h5qguziesf3dz4uq", + "value": { + "wnfs/priv/file": { + "content": { + "external": { + "baseName": { + "/": { + "bytes": "D+6NErtDJP4zX8CQ0KoqP7qY7d+8Qgt76lHJ71OR5gmsccdJZuoezWWA/sROlHDdVM8w1DFXnZDfvSJOMOZm/JOW/aLK66U1Eem36fMWFvQZ1vQdIONmblKs5iWNrzXRRmsIZ0JEgd6s27XlDhYmBp728DLQMlvtcNIw8yZaJYlJMyw6CI0W+XVNqG0e6rmeKsLg8P+jERy04BqymagMIRUzKvP/OJ89UT9e1rZ5kj3WNlPCQ9tJBCvtVokfC7ZP3bNwwWMfilhj/ZMO/6ClzbIPy54JGnf0t55goIQwna4a9sONJnwnf5YRkBBv3kfqxhnHXFI8vjYvAicKrbNA8w" + } + }, + "blockContentSize": 262104, + "blockCount": 1, + "key": { + "/": { + "bytes": "ZKCSuHlM49WxT+92lwlfNPM+XxOoFM2AjU5e4dCLQ6M" + } + } + } + }, + "headerCid": { + "/": "bafkr4igm2czfndo37tusfikagtz5kejhstu4s6ti7jwzg7gajiie2zzc7y" + }, + "metadata": { + "created": 0, + "modified": 0 + }, + "previous": [], + "version": "1.0.0" + } + }, + "bytes": "+IU4xTGhOAuWwYvbYU3qdgyjhSyIOYpWtVNE1j5IG0GoQ+52FKMYJeScSHvheZ25QlH4UY4rXw85jclVdEg+VpWkhUtHVfjYKPEa7ISZXTi/AtdjfsLzF2XjTeXvJgJvfYHvKOJQhbdat8nG8/8Y7Eq8/20ZN2K5FoUA+MAuyqTC/Akd9TVrl1MpUGhpjEBjc84DTBqn8GgerjX6RX0pqJU6i0zzR/a8ICZqC5hV6KaGPh1jvuFy4FCap26v6TY5v0bQkiQn/KEwVLVyv7fh2xAzEhJs7h0CPfzdstqd6058Cw90hvWP89M9ZEm1RSPiWPGwCW9jOKiV5QOt6xB3HmG4n7iEe8qUFV1JPNzjy4Aqsbd4RfKOTnIA8j0HD+Wf43UfQrOrodsebeUXFrmGQtZ3mOKxnTa6J41S96IRrkEIvfgW45d6QqFeWPNLR8g2MASQSLSTC511p3AIGXFmWDna5YKpx7wGidmkFGX0wA7EodRWDDmHT/DABKqzsiYqxTBO/36IinuOGtR15e9gikGBPiRWVlYFbzdbmwIOVC7Jhi7d6gLPUh8DymfK9PBC07hDA631FzwyV08rSteQ7sYdLp5fh9Rfs8kFXyQrM6O7KqyNRMm6QbJcqYc16zwcoduZDdYTr7LWYRz3hRL9xtEzn+N3auAd4dCAZl0lr9/AgqQxUs6eUg==" + }, + { + "cid": "bafkr4igm2czfndo37tusfikagtz5kejhstu4s6ti7jwzg7gajiie2zzc7y", + "value": { + "inumber": { + "/": { + "bytes": "Np+etw7KoG7usE5PLJYorG9z/qvF2LRtF1leOfDA3ls" + } + }, + "name": { + "/": { + "bytes": "Ha6m9Qtvybi13t8xS6jCJVd8/4vIgb18hy+u3tewR1dSYw/YijfJhTE9SpO9WZWeMejVpHwVqNg37ieT5DogFfBBOo4eBlOaLUE1pUOZCvDHrXz5LXbw62decS+2XKNJMrF8k6T9nK05prowsfrIAOnGrvew2xCmmLoSiCVOrLghXPMNlvqMm8unic9k23fAg/vE4AEfKXGhCNy5zbeqK8vV5wOo0JBHPrWgNyP4IdR76IeiYa6Yrkxs3cPtDqY387JuyUsX8fyWdap4JXTP2ldNsr3X4G66mce1h6vkrVO1jfPvCswFevkdFOcqnoGZJsHuY9I1q0LDP2z3UI4jXg" + } + }, + "ratchet": { + "large": { + "/": { + "bytes": "Gsgh612kLZy5xCAXrHmAIbVkuVTAaSKQAs061PVJ1Ag" + } + }, + "medium": { + "/": { + "bytes": "o9OePElGO1DER+MHy5oABkbDIblbg+jUVNW7REa2Kyo" + } + }, + "mediumCounter": 31, + "salt": { + "/": { + "bytes": "zoSIa/gNcNGdLwpk591zPxnRl46bR2NVMovEgpAY8KE" + } + }, + "small": { + "/": { + "bytes": "A0L13AljldlXoBzDH6BVWBvbhZOQgPq8B0+xY00cMjk" + } + }, + "smallCounter": 149 + } + }, + "bytes": "+ruhxD5iWl3v0yvDSMJgFKSmnlR0lnisxzSTNwTXM1eHH1T9lz4uiW7rCphzDtgZPX/mHswwxSY7U9zjRq96NEd5S0cc/Oj3vM12Vcl+eUnmtdsgLiSy5oq0II99i/guuHFJ0merz0tAzWUzsCk9dUoFwfzvIpCEe/l4FCDLZaZiL2O91gnxFxZUenW4yxI5DOnHdtWnshPY29cg/LgbBd1IB0PnafWZWl3WqiQcsS5Op+xm7LvRXkkj07g953hULhAdNmAR3h5XCuyrmarQxUHoFPJpy8e5TPOy0SzBgZyaADibDggvAOLIItIKi/YkQ+bjl7cRx0xKMYRIjxahhH6bMIzcD3e+Vvu/t4Wa6Exlu/3iq6u/W1nOCzSFKnbU7VLdgjwr941aYPqEvCdsDP/61VNL4cfz74JoibAkRppXdd6Rh/QuSWnhazhWmPBa2phZYkg3CXhvrycR4XMPmyohLnvI2Ds2xoA5rv3Gj53JKbmMq8BOuwTBlFyNkO/RU2umVBhiXWT6HAt6U18kXUGxNlCQ1anQxmIdpzseaO9U8hOSPF1zM2Hk4Wd9yNMueio4CEJu+HsydIjGXY/bP1WVCvs/6K0Bfa1Tcs0CeIFH++EeMn8Bu0TR9nc/R11Jc6Fz8J7jh/ZKOM74xEU7nx6uJBJT76RObwreKKr0HGTBGAJUDUzLUQ==" + }, + { + "cid": "bafkr4ibojs5rmbq5bwcsi2lfi7zp2ktnr2awouczs3rul3b4mioxhqdi7q", + "value": { + "wnfs/priv/file": { + "content": { + "external": { + "baseName": { + "/": { + "bytes": "dVymeXd4adLmab4jsI0csAM5VOUW+87ceK/LaaPGseoozJqUDT9ZtPEFTxMRJPRMdOonmdcC09jM+0NyGhCCWftzsNrbvQz+iLLBpfFETG5JHTNH9Mn0lHMdKFhs5b0P0s2Y/jhljSepRgQ0XQAC76MNllO7xSjoQx5TW8X+ppkqNsAW6YljncWafmAvrytjEFw3AWZfLhUjCWCcxcpPxa0yrUcMbu7gIYKr1IHF+7oMxFSpsfdeAKTr+1FhNeClA3fnzrWcHPIbbYT74SaSXq/N1XNIk4BEu+aUEjDkTcZeY+VTen9/OSCrWLYzcaJgqGBTijls+I2gA3vik0EE2A" + } + }, + "blockContentSize": 262104, + "blockCount": 1, + "key": { + "/": { + "bytes": "jVcwDN/TdjHv5AfNidTSi4YTVNCx+2xZGF9Z1+pTi88" + } + } + } + }, + "headerCid": { + "/": "bafkr4ig2dh6lqnfslf3waewp52o4m7vjgfe7rpaguf4r7hnltqelodz4om" + }, + "metadata": { + "created": 0, + "modified": 0 + }, + "previous": [], + "version": "1.0.0" + } + }, + "bytes": "KNb/g8e03KQjyeUy9xeoZpgabhtQAkR7xRrY6QLQXuspUPs5yZ8aGFQ6jqbiYyDFqkPajTCy2wX+70g7N92+cyjQScmlQJxcLPGar2DJrMZn4JHo7/+RLWG+aL1irAEKOpel+f3vFemqvw+3VtcDr1VMrHWaYuKcyDElKzVZKV1aw6UeDgMd9tGG+GkBWUnNeCcSk4cBxyGOa1ehYGy+/UcDDETAh1xycJFq+Q8QgjdbExieWHRmvWlSxRiceVaBEHkHkvebJrE6wCgaV9XLy1SFkEabnQhI3CDRw1FTqtjaabN5sSk822gCyFmXvXEX/rxGjR2lE3BeM/Ntt+ShxXAZ9zlbtnRViERejw5f3Cow33bikyg92Kzxb+qX52ktGokczCrGOBAzYO94qxe21EggCyVr/QZDZ+bsPUVsYmD764hD25fUTbbLTPKeDCSpGFCmlc1HKM8CXDJ+jc25+c8r5Qj9Q1c03WPQoAM8gaSA/82kY2lkHmuzxS21h6c3qjj4cZAqYqjd2C5n1j4d1n+mzi+rWfkMpHV7/L+Vu8ec0YUhV6PHgA7lOeCEL6bRWiERUJV0fAAvb5aJgu4x1TiNIP72h1m9mBD8pGmrgioVCdlMrGdVQxVRiYRg4CiQmWmML0ztraOT1A9LyX7HzS6YrHNPmaQUnoZ3/9nWn6JxcCDYIXtrHA==" + }, + { + "cid": "bafkr4ig2dh6lqnfslf3waewp52o4m7vjgfe7rpaguf4r7hnltqelodz4om", + "value": { + "inumber": { + "/": { + "bytes": "27rTEmtE0nyKwyJ0LUnbDxvnpRHreQvkG4mrh6ed1NU" + } + }, + "name": { + "/": { + "bytes": "tUCUwv43o9ajn84gq0Gkow6PtTAIDe+uuViNVctIs4XNTnM6fi3Hk+X9eNJnIr5o7lvZr9Gf0DiENsQ/p4Vm9rtLP3KS2Hw1EBs/lLgqazbbK4At5GGgBhUL+NSvKJ1r2pX7urxx4iQy1Ag8i1zII143TuzFBe5nuN8jMLGMbLzAEuDwUTRL9bOCFdjJHvzbslyvMj6S60qqoNzxO+fgbvj0bRWaPaZvKCvdj/gTlaIcVOJ+jzR3ULoofORvPvcnGaC6XDqVL6wIShN/f7QgFRi05r0FcmIEP3ekAuA76KtA+ubULRMQg+JUMIi8srkckPaYlo3a+KvQ5TWroIXwdQ" + } + }, + "ratchet": { + "large": { + "/": { + "bytes": "GJqV9EMwaCbW8We2glA8bmgKkW5fv/bad0Ur8b+fvkI" + } + }, + "medium": { + "/": { + "bytes": "ZK2XGLHMoU5tLdTlXGYR9T+/nCf6h8iLKoJORu9qC/Y" + } + }, + "mediumCounter": 225, + "salt": { + "/": { + "bytes": "YuR9jMoolPnCxP1IUZDVuuXjvducRLiIJHWGwoB9VAw" + } + }, + "small": { + "/": { + "bytes": "CTVUMi4+gZVMOAECcB2vCDYflrCxctMqOcFuKpV7j7A" + } + }, + "smallCounter": 233 + } + }, + "bytes": "3DVHGu+1d0gWqsWtICwgQus6vALnIl1s35ZX06gx1Tm+b2nEYr4cy7k7OqiuTN2M2rMb8mAvHrfhby1A0jtqXUIfnFeC0RJVXClJUEUrFz6tjkGY+4w0aCMNIgLQTpuT4NT3Jjj4jukrh/+P5T6LAjRMXZpEar6Y22Mf4Q8nvRf02+mS9gE0EqUfFJUlfC/gXvfQj8e4uhDGM/WfSquz/adVsTEp/C9AE03LgzjYJMcsQpLIte0/YEZOEWKF/auMUiKaBWRlMDiFVz0ZNZ500s7SVBApRByt1RyhbBB0RlMd86opsSxZIQjzJUtgWaxikARIkRy+F4pDZA9+KH1OX5Bc0MFbY2cVh/0Iuu+F13LIlPMf7xclTminR3e7OBJiMnL6VZyqP/dS0RUtpfAGRuRMf8CTylYU6qKNwFE8QdC7bW2Hz/VSPOgoUI8A9Q1dfDaQNWPExSXZALMWVhIsZxDq4H3w1xqi3Zb4SkkxqNiG4G9+pgYXm6KM+PvpNiRGuPICjycV8dAy/Mkqg3guxaKWZDDugppWaNqp3wrViok1iVE8n18TovJIHQmMlYsNQmjc/q9D7PMg7+XhNcjkuJ4QMC0/UMuKOQKkYJrzFsnObyCYENkkSBX0pcnr1Z7q/AA2SPd787WZM8GJwpz1N5yMErKEe9djvDgGcejOczV/530xRNWmbQ==" + }, + { + "cid": "bafkr4icdf6vi235jl6bqrmg3fmdba7ximvdsac45syigmxmpb4wolbtidy", + "value": { + "inumber": { + "/": { + "bytes": "8oaNxyAwPOMftKOeX6vYTKpwmJ7RnyhOvzlheOziGUE" + } + }, + "name": { + "/": { + "bytes": "spIDAZGJKcmGiQzqOkSlfevPRmOkND7dmfxoKGSZn+L2U72swQgZWyqEGYFoBHkAOVfREN5puBpD39wif7cle1/NA6VmsEKTVVM2kOs9wWUj1ltUOjJdem6cIHGHKuuBfyT4cKkMeSlLIjO4G8plynMsnk2Wl06HATb9Z0OrarINH9Qja4dZ8LPIP7TqpKOjhmY4Uzh8VHb2/4J7LBKrTvu4uQAgZCEDixnZ0DlSCUtqEtVM7pz2E3esfx2EJtA8Jxu/wVwt1ca82sEpkZYKIqV8qxK1Mt6B7Zm91fjm4MhtN6UkHBNZyn0IflhZphLmbIxlfcViPHEQSBq8+Z1pXg" + } + }, + "ratchet": { + "large": { + "/": { + "bytes": "b7PHfJFquImGboCHvDVUIuasqPla7vum7OVpZjvwltQ" + } + }, + "medium": { + "/": { + "bytes": "7+aipcV8QxNDi5CI5u3xNERS/26h7l94ZtxVji53mNQ" + } + }, + "mediumCounter": 213, + "salt": { + "/": { + "bytes": "MlXknXWqPUtUIQ70Pc20OmddXfgd2u4lHRFt7GuDGRo" + } + }, + "small": { + "/": { + "bytes": "Bu9qjHcXjCr6W69E2B64PVPhOEfEmvGXYd8+LbJa1aY" + } + }, + "smallCounter": 116 + } + }, + "bytes": "T5fBA7x72km1/nQsgT3OaTo3ErQGl3UX/D/eMsj5elt82Zn2ImkvTPGj82norM4F3XJjOQQyb58iChLlBSB4DIEy7nU/4AVGChzIp4R1n8os5Y2Y824VGSBjwnQqAEpbN8kBQgK2ePAR6pdYwvpCGMjnwsSUrDhIZ8XFwO/+ISEC5iVfhKwFwvjqYyk7i/hkfTs+D75DsNRNpXhanhtUF+MVxvH7W9ncx2coCVU/8MvvOkPJkfErfp9nyE0RDsLbLMcJHRE+OY/zPXifbJYPH6wjubaw03SeDyeHsolGPQrbMnpzEuR85yVdZWTnNzgtoehnGFiWjTrEhDkbBWWCD9MGbREttYnwkjZZ0ACdn+l9jAB+uZdNiqzDJSU96AHZcScdGk1KQMFSkXNawsbBKNNMSvkGz7J2W/lZ5qOxswVqf61Ap4xPcoKV6j4osBzT3ZlrYkElNHpD7wCPp4/qCfBThr5FYJdFiIL7A54seXc9bGZjep3stSqevdPXBN19VB/ApXwvW54S9Stk0hqoFP86Rnd8M1usyD/UNSYx3T8GG2RvFAeBPgjrtTmIgJlpxfnG36sdXaWXecaTH43lE3zO5L6Jp8PRmBylHTKB2dUnG9xWDjZN4u4pR47LC2Kvk0Bg9XRlMd3zUWTubHxZB0Buzl9dnVGZwd5iiXp8/mOq4gA2gg+tDg==" + }, + { + "cid": "bafkr4ie4rlwzcbhcxirnqhgdxngizjvnybonto5hxevbipxkzpkhj2y55q", + "value": { + "wnfs/priv/file": { + "content": { + "external": { + "baseName": { + "/": { + "bytes": "qQgCU/1D0NPNpIAhSuG1+XTOKJiuQ9DKZTjVlJbJvMFV1l3esP1n9BClQCOf0YiKDwMQQ/jCxwhZwETlXpSbnFzZksgDBgNqzpYoGsDGBvjQGa+L1yWBbW7+ASlMTLajbJSzuLx7I8wp5KKNuLsqaeCv+XqhBWnNbG8Td16nuNX/hkYQ551hAGpl54drXgEFypcQvcwdV4oZSM08+VcPxqPio3uHRLi+Gw+mF0vs9UzdZFVPhaRjenRSYH7MvuenvWD8MISws8cxolYicaJkBoQEvP17qGCJq+lbSwE1vtyEI5NsAOWYQo6BcRC3e5UYXMEeLD8/gcrh3YtAa5PsyQ" + } + }, + "blockContentSize": 262104, + "blockCount": 1, + "key": { + "/": { + "bytes": "RTVvKoRFbRabxFk8iiPjWbiY2+UbTvYvEOuZ4hjFvoU" + } + } + } + }, + "headerCid": { + "/": "bafkr4icdf6vi235jl6bqrmg3fmdba7ximvdsac45syigmxmpb4wolbtidy" + }, + "metadata": { + "created": 0, + "modified": 0 + }, + "previous": [], + "version": "1.0.0" + } + }, + "bytes": "UxsjWntevfOu6Qzk1fNZJm6/iIpgysHyUiqc0wcGJrkynPLYAp44wsfTsSQLY4ADBOzBo9icHHyFYtHmXVZxTe/g9kHqHvuomUbkuXsD5OxmJ6JWKYKHqEmA0iVfuvv1oyFEQn2wbH2fI/HEDeGqTNH46AZAJDaFYFQkavUUmmcNFgnid8wD0R3lVpw27TOEDZZApRClRrsJ4olQn1opWQWD5KvWQNPAr4AWI10DUdVumwltoUP3wF9txl9xFx2aNdxsSJa748lkPVNpttmMtoU9+cdeAbTawB3grNSUIg0wQ/ln5GNDQDEBFn2gjOUIx1b/zqJLlY22DvkrYr+JbSipo+o/mdnyMSuXqKjMv7I/Azq7GzBIA1xqRx/DWvyxVPOcRzNjl3jzBdRk2qNcNFk2F4YMd1GGECewHvpdkJYujcP+SUExkwlULLimmBRxmwkSmoeWITE9fj+R0r2VCmSlYK/9W07isM1VR2n6rEOhzRwooJZn3l58MTIxj5dfh1OL+hlKSCdbAXsLjS6waGz7YpLTvWYuVz1d3O9UVmSqS982vldosaLLeqIAjZR05PZ4LgZ1UDgwq00KIlye6Rkf8+3Zidhoh2whRbn66v0aVAbEK98X47N6UpQJuyqN/ccCZghBs2NJt+oMKVner+j5+Z0mAPy7B01k/Qx3Ks1WgGWNxYfyNQ==" + }, + { + "cid": "bafkr4igljnzokpfougv3yiqmsxhkqpvz26q6y7jadyuhmzpsvggz2ver7e", + "value": { + "wnfs/priv/dir": { + "entries": { + "jazz": { + "contentCid": { + "/": "bafkr4ie4rlwzcbhcxirnqhgdxngizjvnybonto5hxevbipxkzpkhj2y55q" + }, + "label": { + "/": { + "bytes": "dQ5WMVfLlOwXDDZN7O0UPMOyDxztE80f9O8NLSe8Nd8" + } + }, + "snapshotKey": { + "/": { + "bytes": "wgoQtwsOrB+0hooUC/hIbIqrhOi2E1V0f6edZTMzNSE" + } + }, + "temporalKey": { + "/": { + "bytes": "Z0lE6T/vSa4vXjn0BQe12aJGA3wkotPuNb0Yq7yx0TxhNatdy+iFxA" + } + } + } + }, + "headerCid": { + "/": "bafkr4igtg3oup6h2veg7susxuthdrad6zlifvm2ejxt7gbiq6r5ptyrrzm" + }, + "metadata": { + "created": 0, + "modified": 0 + }, + "previous": [], + "version": "1.0.0" + } + }, + "bytes": "L4pYG5OW5YyMbIdJgNTG207RdlwnC6q86F59KgR/7lfiinXMhTN+Ha07HocErORldyHMfXm9mF0Bs4+O/VvSKgni5TrFZf1IibncaHucK+t6u2/0BEgPldqlqmf4wY//pRmXLNCZLu3LVOhD68otD8TKXaLACw9fbubKTLHCmkpuzwYGpmnR4f9lH7UVmh1+CHQaIFZpa5Ft/HlAaNmBYmbijrKBb/a3Vlw2FWOf7XcqNq8oWt2GfiwJN3MTMP0PHjXjntLd/d/mdWz9U5zqOztWAPDeDarfZiZ6IeLvYEcqB2tMJnThtDAPHnRtXo98bbK+FzSMYu73IY9TS4KQV4FC8NQnU7TTlYaRq7x1NxIoknvdVYfInKk6PT9wBcvGjszrqX4h8s9CwpdK4xn8wA5yZDGmITOYA13yrffxWj6ZrSsq4H0S4RE7WDmDDaNzcRp130Qn3yxAVV/t0MNgOxyfKHrrf4qZF/lC9R5kyQ==" + }, + { + "cid": "bafkr4igtg3oup6h2veg7susxuthdrad6zlifvm2ejxt7gbiq6r5ptyrrzm", + "value": { + "inumber": { + "/": { + "bytes": "F56/XmzyfsCdLoUmc9ysldn7Aq1AG+TAuAScnONygQE" + } + }, + "name": { + "/": { + "bytes": "hJOiX+spJVS+B8BTf9AHnee8iNlFnZEaANNQeHtoucSOGgUoHkD+R4KQ45f9nOB96yiLFtNb1SqBFDenwt1kHozDfFSnfVoUMg59lbsuAzI8HwzRsoL37HDemdDaRWOYgGNEN6UUyMHTZUPN0XQvfYv8OmAvQMi3kj5xgcRmj9P/iDSm3ZT2SofpPE9YEMV9f161S6XeLcvDd2cu5Sxa2bOZEOWzNAzEFgUMgRH5ZoGrQsznv2O/0NTtcaFIcDl5+/t0huNdjen1a/SIBWkr5amN33cwXzSujvrXxy2bVUTguY/wSZOsrNnG2LBn/sblU7g4c/d+SzERp6LmzOEJ5w" + } + }, + "ratchet": { + "large": { + "/": { + "bytes": "J9y/uUtzPtr2uMrizZhRSPKiYbj7mIZ5mhVGlY7QSUQ" + } + }, + "medium": { + "/": { + "bytes": "N7+d0A5VZ5QcCMrARPPM7Lp6pwjRYolfbfSBPAuv4so" + } + }, + "mediumCounter": 227, + "salt": { + "/": { + "bytes": "wJknDy/chixgR3PN4i/umUKgu9w/dBQkKPcc8bpPtwM" + } + }, + "small": { + "/": { + "bytes": "0yP5KKkIA3gskFH3ElX5nv3Z7iRD1GQSee7S4+xMSYg" + } + }, + "smallCounter": 253 + } + }, + "bytes": "++mhKSZ/fr+zbRp9cFm1FvswbhHAzNux47bZq1/re4APgBXRf9++Fz+pkcx2vOW6eagGs7E3n8EInQfSYDAl8cs9MdFz3dsIuTSIXj7deMLeafvMwpEeU0soefpW7c6K1U8Ad2I9KCpmKFjff2iGmkfZouuy1d6L8IfKk7qQej16S15xeidHnTXv0jaCwVBOEwb6bsfWtW5MI4OH97YDpdQUPE5mQMPaMNz/sU+fblO755LZlqBrm+W0Stb9NFpemtUMjoenvSX72YfA5tGA19y8EqzAVFPa26ns1dqmWOLM6CCH0oHF52gzN1lCGJ+qP3psyKU6dkbNYL3FeMEAx5yZfQk0sBQoV4Dxai4bbTF0tmxeKtN1hvxH5LRNgdj0CeukaNhap5Lmy00SVwC6IUqfDmLg4EnQDB4YVBjHjsJH2RmMriI0XQImkptnCxrti924bfIN4Asn5BYcVBTL0iBVi3yfo5FgMMaYL+G2DXw/qZky0RV88jsdCxPnbO31Dzk+VEg75N/QaqGBq8c9ZeGn0tHzbWtplCZ9E0pYo3dPTE3sy0zUaNNTh7ChrYHINLnORPfssQ6SdaM+9h+nbL9uvjElakPWMn/+JZBVx+/OFtcx4EWHJBjiu2gtlznAipt8WomIXEZO2GuVHIJ82SVVVcqhQE3lOmomHGlD/OXo/8ZM2tzbjw==" + }, + { + "cid": "bafkr4ic4myx7wgjgmmygtaxaz33krp5mxx2zeciu6xvcwsv63eegcq4rju", + "value": { + "inumber": { + "/": { + "bytes": "vne1WpMqViJqa03c5qoaSLUpA3XIBiJxwuMf9osbWlM" + } + }, + "name": { + "/": { + "bytes": "ElVG2/MKo+xcz+1lm3nFkl2MpM/PoWElg2C1H5sPfQ0YBSQW9+nMJR1otJy+dm0bg5bImWHMUpenrCxZ+W+JPdb6fXPe59F7gTO9j3zRJOVceZF9z/pDjTR9Ub8wNcilyrAA3T0DYcmD+4PDJXzWMlhDpMaTyEb0Ktza8ohwPwqZ+l8dGyMYAqoL+tZ1EdZeTaj2vH8D0GZ0G3jETwv0Sei9rpsraQD/sYvTFn3EiGSvmFfJciXVXM3nQ1iVp/qydKwlDxyW+E2qpL2ZAE/MsZ19l5FfaS+ZICT24TZqXP04r8LXdH8OmTwwusDi/RupMQQcHDieCGMVbeu4ClPDrg" + } + }, + "ratchet": { + "large": { + "/": { + "bytes": "fkQysCnE9+L5U6SI6r6TEjxAg9ypPYkILcyntk6i4MA" + } + }, + "medium": { + "/": { + "bytes": "Qyo7Rw0IyXRu6eL805pN9Uxlb41DahrvEHbw3qib1Aw" + } + }, + "mediumCounter": 18, + "salt": { + "/": { + "bytes": "/8FmnP2I6CnT0N6iXzyETzANlYRQeNrs9z+z/ClDPzQ" + } + }, + "small": { + "/": { + "bytes": "pZ0fTz4FIqjw54lxpz8l0NEGPo5l2XYgFN9dmGeHlZg" + } + }, + "smallCounter": 207 + } + }, + "bytes": "hyzKhZ/77ZbVsUsuCVsb8yO83+SFy3HoUahYEKHtpE3Qz/vCWjhoY09osolymIgOi0eD8Y9RiDTipK6uopTWkwRwPJZ2SEEkG/AK9Y+yXkxeH7JCkOkTDplYH5dn8Ru+vJu2pW/G/E5pLGvsn1yEGiG6igeM/vBT+P66wn7TACjJ5ZlYQTb5tBXzDvstaDhN3/Y470ncabaoRa5GhMRtxr5mYVftc1tSDuEQKFGYJSAZ3mRA82vplr74YaRLYAPcZVxn1L2P8bjgVIEjEoqxzdum/JdFYM/yZ05mjyfqCo0KzMy440cz/MklYGuGR3ky0hOIMz7Kou+q/WZwTuY6xAIH5hvMpoC5EoqdUftfHit/PL/24YeNcw9s3r+Txo0gP/M8/b3Hs0COJtzQdn6Gj4vRmUxZNb2Mpm9Qe4r6tboINJy1IbgyY90TGYYGyZO0TeomKezDgpcyicFQ8oFmY6PPfco+PIruTe9SWwUO/AJWuEqA2VJ9PY+nozUU6QVNyg91aLQTnu0wShz1snQWhqvRQmQrqt2MQEl5XSMwknFGXa+tFO/n0m5+KXnS5bJQpHRStW8O4Vqy7a25OFuc50LAw/CEgvRaH/LUFU/biovw4xPriTCLPKTZPzdS5lG0KiwwoHAYcbnXicgxr72nKFrjfIyYcMqubFFxw9omhXcFtwd1YDcmAg==" + }, + { + "cid": "bafkr4ih2d4uzcjq5uagh4r7woymauxmyg3qar2bea5pv7jul7mqpy5rljq", + "value": { + "wnfs/priv/dir": { + "entries": { + "anime": { + "contentCid": { + "/": "bafkr4ibojs5rmbq5bwcsi2lfi7zp2ktnr2awouczs3rul3b4mioxhqdi7q" + }, + "label": { + "/": { + "bytes": "YmGD28vSqSCxHVHCEKfRZnW9CwlYr51JDIU1mA25OMg" + } + }, + "snapshotKey": { + "/": { + "bytes": "NlzXezeSP3RAStijGSnUAoKOlGrEzqfMCphY424Jzww" + } + }, + "temporalKey": { + "/": { + "bytes": "j1sB3oEoYLgh4K2F/oWn+JcYBs1n0f5dqxkYw5blUDz6vRn2PREmKQ" + } + } + } + }, + "headerCid": { + "/": "bafkr4ic4myx7wgjgmmygtaxaz33krp5mxx2zeciu6xvcwsv63eegcq4rju" + }, + "metadata": { + "created": 0, + "modified": 0 + }, + "previous": [], + "version": "1.0.0" + } + }, + "bytes": "T6EjSLJGR1Ckk85SRNTa+2HUBkjM3oPJWq8lThHbxO1NzlGPDx3qlR0a+nNVegBsH+2jmnduFIeDODWIAYkUSN3WTm70FTUZrZQi228BogmBhpQVPB2ysCXLVtzRc3MomhMmmBH6JF0oYE8XkF2kf71RJTobSBJjGvgUMM14RPbA81HKtb+HdvLV4AHDoGd4YNw+AElILoO/2y6kyxCkIBV0zrwUz+uKYwp+5Ry5VjqTZB5fSf/W9h8bK8X5fL7XKM8Zjltn+dM3wlxuHEHtAZ/lwo0Rwhag/I4LQ/XMJqyNg+u7YMjx9M0aB6r0vsU3AJfVhtf+e527IDuaYkz37TQh5lRfhAFSylEsaFy20a9ZYIamv2Okok698Qr/8O+8BTZVc/VbfWiOIMOJoGuUhH5NhyWlwXthu3WeSmQb3ZoPnR4b27iT9x6Kt+5UhlmxXVhprLEWJftfP2uY499uXadfdYlDJi7etpoCk+UodVA=" + }, + { + "cid": "bafkr4ig24orkcp75447hy2abpan36i3woaerfsg6bnu4z656d6xpa22jsu", + "value": { + "/": { + "bytes": "SGVsbG8gV29ybGQ" + } + }, + "bytes": "XfKFnyZ9B/oCShlpO5aJQzasQmcQIQpAbn63DLcIBTFdjX2mYM5HJkXCjt+et7E0+Aro" + }, + { + "cid": "bafkr4iabb422gnp45fdjd4onr567olqprcl53oblnyima3oenyqvae3ifq", + "value": { + "/": { + "bytes": "SGVsbG8gV29ybGQ" + } + }, + "bytes": "2ARXvwnglXovkitY55ZG4ColKct8mePeDZ5fiwOGqsKPJKYCSecliCfU6Qosi0kfW8Cd" + }, + { + "cid": "bafkr4iczjy3vg4v3snxzouqcf7hos3gta5ewwrqh6sp6243kp6nlxv6axi", + "value": { + "/": { + "bytes": "SGVsbG8gV29ybGQ" + } + }, + "bytes": "VWB36mFajvViTP7DTRDQD6bINeHM4vYFrdw43P/I978t7cD4xwCQrnWrHHau8ViPU25T" + } +] diff --git a/wnfs/src/public/directory.rs b/wnfs/src/public/directory.rs index e54d6716..ba2c2019 100644 --- a/wnfs/src/public/directory.rs +++ b/wnfs/src/public/directory.rs @@ -14,14 +14,15 @@ use anyhow::{bail, ensure, Result}; use async_once_cell::OnceCell; use async_recursion::async_recursion; use chrono::{DateTime, Utc}; -use libipld_core::cid::Cid; use std::{ cmp::Ordering, collections::{btree_map::Entry, BTreeMap, BTreeSet}, }; use wnfs_common::{ + blockstore::Blockstore, + ipld_core::cid::Cid, utils::{boxed_fut, error, Arc}, - BlockStore, Metadata, NodeType, Storable, + Metadata, NodeType, Storable, }; //-------------------------------------------------------------------------------------------------- @@ -171,7 +172,7 @@ impl PublicDirectory { /// without causing further conflicts. pub(crate) async fn prepare_next_merge<'a>( self: &'a mut Arc, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result<&'a mut Self> { if self.previous.len() > 1 { // This is a merge node @@ -194,7 +195,7 @@ impl PublicDirectory { async fn get_leaf_dir<'a>( &'a self, path_segments: &[String], - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { let mut working_dir = self; for (depth, segment) in path_segments.iter().enumerate() { @@ -213,7 +214,7 @@ impl PublicDirectory { async fn get_leaf_dir_mut<'a>( self: &'a mut Arc, path_segments: &[String], - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { // TODO(matheus23) actually set the modification time of all these nodes let mut working_dir = self.prepare_next_revision(); @@ -244,7 +245,7 @@ impl PublicDirectory { self: &'a mut Arc, path_segments: &[String], time: DateTime, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result<&'a mut Self> { match self.get_leaf_dir_mut(path_segments, store).await? { SearchResult::Found(dir) => Ok(dir), @@ -282,7 +283,7 @@ impl PublicDirectory { /// #[async_std::main] /// async fn main() { /// let dir = &mut PublicDirectory::new_rc(Utc::now()); - /// let store = MemoryBlockStore::default(); + /// let store = InMemoryBlockstore::<64>::new(); /// /// dir /// .mkdir(&["pictures".into(), "cats".into()], Utc::now(), &store) @@ -300,7 +301,7 @@ impl PublicDirectory { pub async fn get_node<'a>( &'a self, path_segments: &[String], - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { let Some((tail, path)) = path_segments.split_last() else { return Ok(None); @@ -332,7 +333,7 @@ impl PublicDirectory { /// #[async_std::main] /// async fn main() -> Result<()> { /// let dir = &mut Arc::new(PublicDirectory::new(Utc::now())); - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// /// // Gain a mutable file reference /// let path = &["Documents".into(), "Notes.md".into()]; @@ -353,7 +354,7 @@ impl PublicDirectory { self: &'a mut Arc, path_segments: &[String], time: DateTime, - store: &'a impl BlockStore, + store: &'a impl Blockstore, ) -> Result<&'a mut PublicFile> { let (path, filename) = utils::split_last(path_segments)?; @@ -391,7 +392,7 @@ impl PublicDirectory { /// #[async_std::main] /// async fn main() { /// let dir = &mut PublicDirectory::new_rc(Utc::now()); - /// let mut store = MemoryBlockStore::default(); + /// let mut store = InMemoryBlockstore::<64>::new(); /// /// dir /// .mkdir(&["pictures".into(), "cats".into()], Utc::now(), &store) @@ -406,7 +407,7 @@ impl PublicDirectory { pub async fn lookup_node<'a>( &'a self, path_segment: &str, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { Ok(match self.userland.get(path_segment) { Some(link) => Some(link.resolve_value(store).await?), @@ -418,7 +419,7 @@ impl PublicDirectory { async fn lookup_node_mut<'a>( &'a mut self, path_segment: &str, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { Ok(match self.userland.get_mut(path_segment) { Some(link) => Some(link.resolve_value_mut(store).await?), @@ -440,7 +441,7 @@ impl PublicDirectory { /// #[async_std::main] /// async fn main() { /// let dir = &mut PublicDirectory::new_rc(Utc::now()); - /// let store = &MemoryBlockStore::default(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let content = b"Hello, World!".to_vec(); /// /// dir @@ -461,7 +462,7 @@ impl PublicDirectory { /// assert_eq!(result, content); /// } /// ``` - pub async fn read(&self, path_segments: &[String], store: &impl BlockStore) -> Result> { + pub async fn read(&self, path_segments: &[String], store: &impl Blockstore) -> Result> { let (path, filename) = utils::split_last(path_segments)?; match self.get_leaf_dir(path, store).await? { SearchResult::Found(dir) => match dir.lookup_node(filename, store).await? { @@ -488,7 +489,7 @@ impl PublicDirectory { /// #[async_std::main] /// async fn main() -> Result<()> { /// let dir = &mut PublicDirectory::new_rc(Utc::now()); - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// /// dir /// .write( @@ -507,7 +508,7 @@ impl PublicDirectory { path_segments: &[String], content: Vec, time: DateTime, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result<()> { let (path, filename) = utils::split_last(path_segments)?; let dir = self.get_or_create_leaf_dir_mut(path, time, store).await?; @@ -545,7 +546,7 @@ impl PublicDirectory { /// #[async_std::main] /// async fn main() { /// let dir = &mut PublicDirectory::new_rc(Utc::now()); - /// let store = MemoryBlockStore::default(); + /// let store = InMemoryBlockstore::<64>::new(); /// /// dir /// .mkdir(&["pictures".into(), "cats".into()], Utc::now(), &store) @@ -567,7 +568,7 @@ impl PublicDirectory { self: &mut Arc, path_segments: &[String], time: DateTime, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result<()> { let _ = self .get_or_create_leaf_dir_mut(path_segments, time, store) @@ -591,7 +592,7 @@ impl PublicDirectory { /// #[async_std::main] /// async fn main() { /// let dir = &mut PublicDirectory::new_rc(Utc::now()); - /// let store = MemoryBlockStore::default(); + /// let store = InMemoryBlockstore::<64>::new(); /// /// dir /// .write( @@ -615,7 +616,7 @@ impl PublicDirectory { pub async fn ls( &self, path_segments: &[String], - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { match self.get_leaf_dir(path_segments, store).await? { SearchResult::Found(dir) => { @@ -652,7 +653,7 @@ impl PublicDirectory { /// #[async_std::main] /// async fn main() -> Result<()> { /// let dir = &mut PublicDirectory::new_rc(Utc::now()); - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// /// dir /// .write( @@ -685,7 +686,7 @@ impl PublicDirectory { pub async fn rm( self: &mut Arc, path_segments: &[String], - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result { // TODO(matheus23) set modification time let (path, node_name) = utils::split_last(path_segments)?; @@ -719,7 +720,7 @@ impl PublicDirectory { /// #[async_std::main] /// async fn main() { /// let dir = &mut PublicDirectory::new_rc(Utc::now()); - /// let store = MemoryBlockStore::default(); + /// let store = InMemoryBlockstore::<64>::new(); /// /// dir /// .write( @@ -754,7 +755,7 @@ impl PublicDirectory { path_segments_from: &[String], path_segments_to: &[String], time: DateTime, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result<()> { let (path, filename) = utils::split_last(path_segments_to)?; let mut removed_node = self.rm(path_segments_from, store).await?; @@ -792,7 +793,7 @@ impl PublicDirectory { /// #[async_std::main] /// async fn main() -> Result<()> { /// let dir = &mut PublicDirectory::new_rc(Utc::now()); - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// /// dir /// .write( @@ -826,7 +827,7 @@ impl PublicDirectory { path_segments_from: &[String], path_segments_to: &[String], time: DateTime, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result<()> { let (path, filename) = utils::split_last(path_segments_to)?; let Some(mut node) = self.get_node(path_segments_from, store).await?.cloned() else { @@ -853,7 +854,7 @@ impl PublicDirectory { pub async fn causal_compare( self: Arc, other: Arc, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { let causal_order = PublicNode::Dir(self) .causal_compare(&PublicNode::Dir(other), store) @@ -872,7 +873,7 @@ impl PublicDirectory { pub async fn reconcile( self: &mut Arc, other: &Arc, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result { let causal_order = self.clone().causal_compare(other.clone(), store).await?; @@ -897,7 +898,7 @@ impl PublicDirectory { async fn reconcile_helper<'a>( self: &'a mut Arc, other: &'a Arc, - store: &'a impl BlockStore, + store: &'a impl Blockstore, current_path: &[String], file_tie_breaks: &mut BTreeSet>, ) -> Result<()> { @@ -1026,7 +1027,7 @@ impl Clone for PublicDirectory { impl Storable for PublicDirectory { type Serializable = PublicNodeSerializable; - async fn to_serializable(&self, store: &impl BlockStore) -> Result { + async fn to_serializable(&self, store: &impl Blockstore) -> Result { let userland = { let mut map = BTreeMap::new(); for (name, link) in self.userland.iter() { @@ -1082,14 +1083,13 @@ impl Storable for PublicDirectory { #[cfg(test)] mod tests { use super::*; - use libipld_core::ipld::Ipld; use testresult::TestResult; - use wnfs_common::{decode, libipld::cbor::DagCborCodec, MemoryBlockStore}; + use wnfs_common::{blockstore::InMemoryBlockstore, ipld_core::ipld::Ipld}; #[async_std::test] async fn look_up_can_fetch_file_added_to_directory() -> TestResult { let root_dir = &mut PublicDirectory::new_rc(Utc::now()); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let time = Utc::now(); root_dir @@ -1111,7 +1111,7 @@ mod tests { #[async_std::test] async fn look_up_cannot_fetch_file_not_added_to_directory() { let root = PublicDirectory::new(Utc::now()); - let store = MemoryBlockStore::default(); + let store = InMemoryBlockstore::<64>::new(); let node = root.lookup_node("Unknown", &store).await; @@ -1123,7 +1123,7 @@ mod tests { #[async_std::test] async fn get_node_can_fetch_node_from_root_dir() -> TestResult { let time = Utc::now(); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let root_dir = &mut PublicDirectory::new_rc(time); root_dir @@ -1177,7 +1177,7 @@ mod tests { #[async_std::test] async fn mkdir_can_create_new_directory() -> TestResult { let time = Utc::now(); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let root_dir = &mut PublicDirectory::new_rc(time); root_dir @@ -1196,7 +1196,7 @@ mod tests { #[async_std::test] async fn ls_can_list_children_under_directory() -> TestResult { let time = Utc::now(); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let root_dir = &mut PublicDirectory::new_rc(time); root_dir @@ -1236,7 +1236,7 @@ mod tests { #[async_std::test] async fn rm_can_remove_children_from_directory() -> TestResult { let time = Utc::now(); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let mut root_dir = PublicDirectory::new_rc(time); root_dir @@ -1277,7 +1277,7 @@ mod tests { #[async_std::test] async fn read_can_fetch_userland_of_file_added_to_directory() -> TestResult { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let time = Utc::now(); let content = b"Hello".to_vec(); let mut root_dir = PublicDirectory::new_rc(time); @@ -1296,7 +1296,7 @@ mod tests { #[async_std::test] async fn mv_can_move_sub_directory_to_another_valid_location() -> TestResult { let time = Utc::now(); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let mut root_dir = PublicDirectory::new_rc(time); root_dir @@ -1343,7 +1343,7 @@ mod tests { #[async_std::test] async fn mv_cannot_move_sub_directory_to_invalid_location() { let time = Utc::now(); - let store = MemoryBlockStore::default(); + let store = InMemoryBlockstore::<64>::new(); let mut root_dir = PublicDirectory::new_rc(time); root_dir @@ -1375,7 +1375,7 @@ mod tests { #[async_std::test] async fn mv_can_rename_directories() -> TestResult { let time = Utc::now(); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let root_dir = &mut PublicDirectory::new_rc(time); root_dir @@ -1401,7 +1401,7 @@ mod tests { #[async_std::test] async fn mv_fails_moving_directories_to_files() -> TestResult { let time = Utc::now(); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let root_dir = &mut PublicDirectory::new_rc(time); root_dir @@ -1429,18 +1429,18 @@ mod tests { #[async_std::test] async fn previous_links_get_set() { let time = Utc::now(); - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let root_dir = &mut PublicDirectory::new_rc(time); let previous_cid = root_dir.store(store).await.unwrap(); root_dir.mkdir(&["test".into()], time, store).await.unwrap(); - let ipld: Ipld = decode( + let ipld: Ipld = serde_ipld_dagcbor::from_slice( &store - .get_block(&root_dir.store(store).await.unwrap()) + .get(&root_dir.store(store).await.unwrap()) .await + .unwrap() .unwrap(), - DagCborCodec, ) .unwrap(); match ipld { @@ -1460,7 +1460,7 @@ mod tests { #[async_std::test] async fn prepare_next_revision_shortcuts_if_possible() { let time = Utc::now(); - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let root_dir = &mut PublicDirectory::new_rc(time); let previous_cid = &root_dir.store(store).await.unwrap(); @@ -1483,7 +1483,7 @@ mod tests { // we should be left with `b.txt` removed, while `file.txt` is there. let time = Utc::now(); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let root_dir = &mut PublicDirectory::new_rc(time); root_dir.store(store).await?; root_dir.write(path1, vec![0], time, store).await?; @@ -1509,13 +1509,12 @@ mod tests { #[cfg(test)] mod proptests { use super::*; - use libipld_core::ipld::Ipld; use proptest::{ collection::{btree_map, vec}, prelude::*, }; use test_strategy::proptest; - use wnfs_common::MemoryBlockStore; + use wnfs_common::{blockstore::InMemoryBlockstore, ipld_core::ipld::Ipld}; type MockMetadata = String; @@ -1572,7 +1571,7 @@ mod proptests { async fn convert_fs( fs: FileSystem, time: DateTime, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { let mut dir = PublicDirectory::new_rc(time); let FileSystem { files, dirs } = fs; @@ -1607,7 +1606,7 @@ mod proptests { #[proptest] fn test_merge_directory_preferred(#[strategy(vec(simple_string(), 1..10))] path: Vec) { async_std::task::block_on(async move { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let time = Utc::now(); let root0 = &mut PublicDirectory::new_rc(time); @@ -1640,7 +1639,7 @@ mod proptests { #[strategy(file_system())] fs1: FileSystem, ) { async_std::task::block_on(async move { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let time = Utc::now(); let root0 = convert_fs(fs0, time, store).await.unwrap(); @@ -1667,7 +1666,7 @@ mod proptests { #[strategy(file_system())] fs2: FileSystem, ) { async_std::task::block_on(async move { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let time = Utc::now(); let root0 = convert_fs(fs0, time, store).await.unwrap(); let root1 = convert_fs(fs1, time, store).await.unwrap(); @@ -1697,7 +1696,7 @@ mod proptests { #[strategy(file_system())] fs1: FileSystem, ) { async_std::task::block_on(async move { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let time = Utc::now(); let mut all_dirs = fs0.dirs.keys().cloned().collect::>(); diff --git a/wnfs/src/public/file.rs b/wnfs/src/public/file.rs index 6e0c736f..a96d01b4 100644 --- a/wnfs/src/public/file.rs +++ b/wnfs/src/public/file.rs @@ -8,13 +8,14 @@ use anyhow::{anyhow, bail, Result}; use async_once_cell::OnceCell; use chrono::{DateTime, Utc}; use futures::{AsyncRead, AsyncReadExt}; -use libipld_core::cid::Cid; use std::{cmp::Ordering, collections::BTreeSet, io::SeekFrom}; use tokio::io::AsyncSeekExt; use tokio_util::compat::{FuturesAsyncReadCompatExt, TokioAsyncReadCompatExt}; use wnfs_common::{ + blockstore::Blockstore, + ipld_core::cid::Cid, utils::{Arc, CondSend}, - BlockStore, Link, Metadata, NodeType, Storable, + Link, Metadata, NodeType, Storable, }; use wnfs_unixfs_file::{builder::FileBuilder, unixfs::UnixFsFile}; @@ -79,7 +80,7 @@ impl PublicFile { /// /// #[async_std::main] /// async fn main() -> Result<()> { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let content = b"Hello, World!".to_vec(); /// let file = PublicFile::with_content(Utc::now(), content, store).await?; /// @@ -91,7 +92,7 @@ impl PublicFile { pub async fn with_content( time: DateTime, content: Vec, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result { let content_cid = FileBuilder::new() .content_bytes(content) @@ -111,7 +112,7 @@ impl PublicFile { pub async fn with_content_rc( time: DateTime, content: Vec, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { Ok(Arc::new(Self::with_content(time, content, store).await?)) } @@ -135,7 +136,7 @@ impl PublicFile { /// #[async_std::main] /// async fn main() -> Result<()> { /// let disk_file = File::open("./test/fixtures/Clara Schumann, Scherzo no. 2, Op. 14.mp3").await?; - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let file = PublicFile::with_content_streaming( /// Utc::now(), /// disk_file, @@ -151,7 +152,7 @@ impl PublicFile { pub async fn with_content_streaming<'a>( time: DateTime, content: impl AsyncRead + CondSend + 'a, - store: &'a impl BlockStore, + store: &'a impl Blockstore, ) -> Result { let content_cid = FileBuilder::new() .content_reader(FuturesAsyncReadCompatExt::compat(content)) @@ -172,7 +173,7 @@ impl PublicFile { pub async fn with_content_streaming_rc<'a>( time: DateTime, content: impl AsyncRead + CondSend + 'a, - store: &'a impl BlockStore, + store: &'a impl Blockstore, ) -> Result> { Ok(Arc::new( Self::with_content_streaming(time, content, store).await?, @@ -194,7 +195,7 @@ impl PublicFile { /// /// #[async_std::main] /// async fn main() -> Result<()> { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// /// let file = PublicFile::with_content( /// Utc::now(), @@ -235,7 +236,7 @@ impl PublicFile { /// /// #[async_std::main] /// async fn main() -> Result<()> { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let content = b"Hello, World!\n".repeat(1000).to_vec(); /// let file = PublicFile::with_content(Utc::now(), content, store).await?; /// @@ -251,7 +252,7 @@ impl PublicFile { pub async fn stream_content<'a>( &'a self, byte_offset: u64, - store: &'a impl BlockStore, + store: &'a impl Blockstore, ) -> Result { let mut reader = self .userland @@ -281,7 +282,7 @@ impl PublicFile { /// /// #[async_std::main] /// async fn main() -> Result<()> { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let content = b"Hello, World!\n".repeat(1000).to_vec(); /// let file = PublicFile::with_content(Utc::now(), content, store).await?; /// @@ -296,7 +297,7 @@ impl PublicFile { &'a self, byte_offset: u64, len_limit: Option, - store: &'a impl BlockStore, + store: &'a impl Blockstore, ) -> Result> { let size = self.size(store).await?; let mut reader = self.stream_content(byte_offset, store).await?; @@ -328,7 +329,7 @@ impl PublicFile { /// /// #[async_std::main] /// async fn main() -> Result<()> { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let content = get_random_bytes::<324_568>(rng).to_vec(); /// let file = PublicFile::with_content( @@ -345,7 +346,7 @@ impl PublicFile { /// Ok(()) /// } /// ``` - pub async fn size(&self, store: &impl BlockStore) -> Result { + pub async fn size(&self, store: &impl Blockstore) -> Result { self.userland .resolve_value(store) .await? @@ -369,7 +370,7 @@ impl PublicFile { /// /// #[async_std::main] /// async fn main() -> Result<()> { - /// let store = &MemoryBlockStore::new(); + /// let store = &InMemoryBlockstore::<64>::new(); /// let rng = &mut ChaCha12Rng::from_entropy(); /// let content = get_random_bytes::<100>(rng).to_vec(); /// let file = PublicFile::with_content( @@ -386,7 +387,7 @@ impl PublicFile { /// Ok(()) /// } /// ``` - pub async fn get_content(&self, store: &impl BlockStore) -> Result> { + pub async fn get_content(&self, store: &impl Blockstore) -> Result> { self.read_at(0, None, store).await } @@ -412,7 +413,7 @@ impl PublicFile { /// without causing further conflicts. pub(crate) async fn prepare_next_merge<'a>( self: &'a mut Arc, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result<&'a mut Self> { if self.previous.len() > 1 { // This is a merge node @@ -438,7 +439,7 @@ impl PublicFile { &mut self, content: Vec, time: DateTime, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result<()> { let content_cid = FileBuilder::new() .content_bytes(content) @@ -453,7 +454,7 @@ impl PublicFile { } /// Gets the content cid of the file. - pub async fn get_raw_content_cid(&self, store: &impl BlockStore) -> Cid { + pub async fn get_raw_content_cid(&self, store: &impl Blockstore) -> Cid { let content_cid: Result = self.userland.resolve_cid(store).await; content_cid.unwrap() } @@ -504,7 +505,7 @@ impl PublicFile { pub async fn merge( self: &mut Arc, other: &Arc, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result { let our_cid = self.store(store).await?; let other_cid = other.store(store).await?; @@ -570,7 +571,7 @@ impl std::fmt::Debug for PublicFile { impl Storable for PublicFile { type Serializable = PublicNodeSerializable; - async fn to_serializable(&self, store: &impl BlockStore) -> Result { + async fn to_serializable(&self, store: &impl Blockstore) -> Result { Ok(PublicNodeSerializable::File(PublicFileSerializable { version: WNFS_VERSION, metadata: self.metadata.clone(), @@ -641,12 +642,12 @@ impl Clone for PublicFile { #[cfg(test)] mod tests { use super::*; - use wnfs_common::MemoryBlockStore; + use wnfs_common::blockstore::InMemoryBlockstore; #[async_std::test] async fn previous_links_get_set() { let time = Utc::now(); - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let file = &mut PublicFile::new_rc(time); let previous_cid = &file.store(store).await.unwrap(); @@ -661,7 +662,7 @@ mod tests { #[async_std::test] async fn prepare_next_revision_shortcuts_if_possible() { let time = Utc::now(); - let store = &MemoryBlockStore::default(); + let store = &InMemoryBlockstore::<64>::new(); let file = &mut PublicFile::new_rc(time); let previous_cid = &file.store(store).await.unwrap(); diff --git a/wnfs/src/public/link.rs b/wnfs/src/public/link.rs index 234f094e..830c718a 100644 --- a/wnfs/src/public/link.rs +++ b/wnfs/src/public/link.rs @@ -2,8 +2,7 @@ use super::{PublicDirectory, PublicFile, PublicNode}; use anyhow::Result; -use libipld_core::cid::Cid; -use wnfs_common::{utils::Arc, BlockStore, Link}; +use wnfs_common::{blockstore::Blockstore, ipld_core::cid::Cid, utils::Arc, Link}; //-------------------------------------------------------------------------------------------------- // Type Definitions @@ -52,31 +51,31 @@ impl PublicLink { /// Gets the Cid stored in type. It attempts to get it from the store if it is not present in type. #[inline] - pub async fn resolve_cid(&self, store: &impl BlockStore) -> Result { + pub async fn resolve_cid(&self, store: &impl Blockstore) -> Result { self.0.resolve_cid(store).await } /// Gets the value stored in link. It attempts to get it from the store if it is not present in link. #[inline] - pub async fn resolve_value(&self, store: &impl BlockStore) -> Result<&PublicNode> { + pub async fn resolve_value(&self, store: &impl Blockstore) -> Result<&PublicNode> { self.0.resolve_value(store).await } /// Gets mut value stored in link. It attempts to get it from the store if it is not present in link. #[inline] - pub async fn resolve_value_mut(&mut self, store: &impl BlockStore) -> Result<&mut PublicNode> { + pub async fn resolve_value_mut(&mut self, store: &impl Blockstore) -> Result<&mut PublicNode> { self.0.resolve_value_mut(store).await } /// Gets an owned value from type. It attempts to it get from the store if it is not present in type. #[inline] - pub async fn resolve_owned_value(self, store: &impl BlockStore) -> Result { + pub async fn resolve_owned_value(self, store: &impl Blockstore) -> Result { self.0.resolve_owned_value(store).await } /// Compares two links for equality. Attempts to get them from store if they are not already cached. #[inline] - pub async fn deep_eq(&self, other: &Self, store: &impl BlockStore) -> Result { + pub async fn deep_eq(&self, other: &Self, store: &impl Blockstore) -> Result { self.0.deep_eq(&other.0, store).await } } diff --git a/wnfs/src/public/node/node.rs b/wnfs/src/public/node/node.rs index 79da130e..aa575852 100644 --- a/wnfs/src/public/node/node.rs +++ b/wnfs/src/public/node/node.rs @@ -9,9 +9,8 @@ use crate::{ use anyhow::{bail, Result}; use async_once_cell::OnceCell; use chrono::{DateTime, Utc}; -use libipld_core::cid::Cid; use std::{cmp::Ordering, collections::BTreeSet}; -use wnfs_common::{utils::Arc, BlockStore, Storable}; +use wnfs_common::{blockstore::Blockstore, ipld_core::cid::Cid, utils::Arc, Storable}; //-------------------------------------------------------------------------------------------------- // Type Definitions @@ -243,12 +242,12 @@ impl PublicNode { pub async fn causal_compare( &self, other: &Self, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { async fn next_previous_set( previous_set: BTreeSet, visited_cids: &mut BTreeSet, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result> { let mut previous = BTreeSet::new(); @@ -347,7 +346,7 @@ impl From for PublicNode { impl Storable for PublicNode { type Serializable = PublicNodeSerializable; - async fn to_serializable(&self, store: &impl BlockStore) -> Result { + async fn to_serializable(&self, store: &impl Blockstore) -> Result { Ok(match self { Self::File(file) => file.to_serializable(store).await?, Self::Dir(dir) => dir.to_serializable(store).await?, @@ -386,11 +385,11 @@ mod tests { use crate::public::{PublicDirectory, PublicFile, PublicNode}; use chrono::Utc; use testresult::TestResult; - use wnfs_common::{MemoryBlockStore, Storable}; + use wnfs_common::{blockstore::InMemoryBlockstore, Storable}; #[async_std::test] async fn serialized_public_node_can_be_deserialized() -> TestResult { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let dir_node: PublicNode = PublicDirectory::new(Utc::now()).into(); let file_node: PublicNode = PublicFile::new(Utc::now()).into(); @@ -416,7 +415,7 @@ mod proptests { use futures::{stream, StreamExt, TryStreamExt}; use proptest::{collection::vec, prelude::*}; use test_strategy::proptest; - use wnfs_common::MemoryBlockStore; + use wnfs_common::blockstore::InMemoryBlockstore; #[derive(Debug, Clone, Copy)] enum Operation { @@ -455,7 +454,7 @@ mod proptests { &mut self.heads[n % len] // so we don't need to account for the current state (number of heads) when generating n } - pub async fn run(&mut self, op: &Operation, store: &impl BlockStore) -> Result<()> { + pub async fn run(&mut self, op: &Operation, store: &impl Blockstore) -> Result<()> { match op { Operation::Write(n) => { let head = self.get_head_mut(*n); @@ -485,7 +484,7 @@ mod proptests { pub async fn run_all( &mut self, ops: impl IntoIterator, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result<()> { for op in ops { self.run(&op, store).await?; @@ -513,7 +512,7 @@ mod proptests { async fn run_ops( init_time: i64, operations: impl IntoIterator, - store: &impl BlockStore, + store: &impl Blockstore, ) -> Result { let mut state = State::new(init_time); state.run_all(operations, store).await?; @@ -524,7 +523,7 @@ mod proptests { fn test_reflexivity(#[strategy(vec(op(), 0..100))] operations: Vec) { async_std::task::block_on(async move { let mut state = State::new(0); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); state.run_all(operations, store).await.unwrap(); let head_one = state.head_node(); @@ -545,7 +544,7 @@ mod proptests { #[strategy(vec(op(), 0..30))] operations_two: Vec, ) { async_std::task::block_on(async move { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let node_one = run_ops(0, operations_one, store).await.unwrap(); let node_two = run_ops(0, operations_two, store).await.unwrap(); @@ -572,7 +571,7 @@ mod proptests { #[strategy(vec(op(), 0..20))] operations2: Vec, ) { async_std::task::block_on(async move { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let node0 = run_ops(0, operations0, store).await.unwrap(); let node1 = run_ops(0, operations1, store).await.unwrap(); let node2 = run_ops(0, operations2, store).await.unwrap(); @@ -621,7 +620,7 @@ mod proptests { #[strategy(vec(op(), 0..100))] operations1: Vec, ) { async_std::task::block_on(async move { - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); let node0 = run_ops(0, operations0, store).await.unwrap(); let node1 = run_ops(1, operations1, store).await.unwrap(); @@ -638,7 +637,7 @@ mod proptests { ) { async_std::task::block_on(async move { let mut state = State::new(0); - let store = &MemoryBlockStore::new(); + let store = &InMemoryBlockstore::<64>::new(); state.run_all(operations, store).await.unwrap(); let head_one = state.head_node(); diff --git a/wnfs/src/public/node/serializable.rs b/wnfs/src/public/node/serializable.rs index bee3c24b..54a2d36f 100644 --- a/wnfs/src/public/node/serializable.rs +++ b/wnfs/src/public/node/serializable.rs @@ -1,8 +1,7 @@ -use libipld_core::cid::Cid; use semver::Version; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; -use wnfs_common::Metadata; +use wnfs_common::{ipld_core::cid::Cid, Metadata}; //-------------------------------------------------------------------------------------------------- // Type Definitions diff --git a/wnfs/src/public/node/snapshots/wnfs__public__node__node__snapshot_tests__public_fs.snap.new b/wnfs/src/public/node/snapshots/wnfs__public__node__node__snapshot_tests__public_fs.snap.new new file mode 100644 index 00000000..36e85423 --- /dev/null +++ b/wnfs/src/public/node/snapshots/wnfs__public__node__node__snapshot_tests__public_fs.snap.new @@ -0,0 +1,134 @@ +--- +source: wnfs/src/public/node/node.rs +assertion_line: 710 +expression: values +--- +[ + { + "cid": "bafyr4igcgvnnbd6xh7waotpqdopqcesi4wfmfcl2u42gyspjfc3djzt6wa", + "value": { + "wnfs/pub/dir": { + "metadata": { + "created": 0, + "modified": 0 + }, + "previous": [ + { + "/": "bafyr4ih3k2ipwwqryrlmtmwtolma4t772gknmx7pxqu5opjwsrr2nc27qq" + } + ], + "userland": { + "music": { + "/": "bafyr4ieu4jffr7sjcakgzk6jr4w5gbbmjs6oe7q2trrutjqcugr4orvmuu" + }, + "text.txt": { + "/": "bafyr4ihsg6l6g5tw45a3zh2dilphrtafnb6pyc7dpdxbuncgekjycqchnu" + }, + "videos": { + "/": "bafyr4ifobgzwli26fibfladmtouh32okhnmhc7jpy5dvmocz5dgg3wqrnq" + } + }, + "version": "1.0.0" + } + }, + "bytes": "oWx3bmZzL3B1Yi9kaXKkZ3ZlcnNpb25lMS4wLjBobWV0YWRhdGGiZ2NyZWF0ZWQAaG1vZGlmaWVkAGhwcmV2aW91c4HYKlglAAFxHiD7VpD7WhHEVsmy03LYDk//0ZTWX++8Kdc9NpRjpotfhGh1c2VybGFuZKNlbXVzaWPYKlglAAFxHiCU4kpY/kkQFGyryY8t0wQsTLzifhqcY0mmAqGjx0aspWZ2aWRlb3PYKlglAAFxHiCuCbNlo14qAlWAbJuofenKO1hxfS/HR1Y4WejMbdoRbGh0ZXh0LnR4dNgqWCUAAXEeIPI3l+N2dudBvJ9DQt54zAVofPwL43juGjRGIpOBQEdt" + }, + { + "cid": "bafyr4ih3k2ipwwqryrlmtmwtolma4t772gknmx7pxqu5opjwsrr2nc27qq", + "value": { + "wnfs/pub/dir": { + "metadata": { + "created": 0, + "modified": 0 + }, + "previous": [], + "userland": {}, + "version": "1.0.0" + } + }, + "bytes": "oWx3bmZzL3B1Yi9kaXKkZ3ZlcnNpb25lMS4wLjBobWV0YWRhdGGiZ2NyZWF0ZWQAaG1vZGlmaWVkAGhwcmV2aW91c4BodXNlcmxhbmSg" + }, + { + "cid": "bafyr4ieu4jffr7sjcakgzk6jr4w5gbbmjs6oe7q2trrutjqcugr4orvmuu", + "value": { + "wnfs/pub/dir": { + "metadata": { + "created": 0, + "modified": 0 + }, + "previous": [], + "userland": { + "jazz": { + "/": "bafyr4ihsg6l6g5tw45a3zh2dilphrtafnb6pyc7dpdxbuncgekjycqchnu" + } + }, + "version": "1.0.0" + } + }, + "bytes": "oWx3bmZzL3B1Yi9kaXKkZ3ZlcnNpb25lMS4wLjBobWV0YWRhdGGiZ2NyZWF0ZWQAaG1vZGlmaWVkAGhwcmV2aW91c4BodXNlcmxhbmShZGphenrYKlglAAFxHiDyN5fjdnbnQbyfQ0LeeMwFaHz8C+N47ho0RiKTgUBHbQ==" + }, + { + "cid": "bafyr4ihsg6l6g5tw45a3zh2dilphrtafnb6pyc7dpdxbuncgekjycqchnu", + "value": { + "wnfs/pub/file": { + "metadata": { + "created": 0, + "modified": 0 + }, + "previous": [], + "userland": { + "/": "bafkr4ibirkdkphzauplnztoko4j35lwrpb4yffv57j4rh6rkmlmxe67y7a" + }, + "version": "1.0.0" + } + }, + "bytes": "oW13bmZzL3B1Yi9maWxlpGd2ZXJzaW9uZTEuMC4waG1ldGFkYXRhomdjcmVhdGVkAGhtb2RpZmllZABocHJldmlvdXOAaHVzZXJsYW5k2CpYJQABVR4gKIqGp58go9bczcp3E76u0Xh5gpa9+nkT+ipi2XJ7+Pg=" + }, + { + "cid": "bafyr4ifobgzwli26fibfladmtouh32okhnmhc7jpy5dvmocz5dgg3wqrnq", + "value": { + "wnfs/pub/dir": { + "metadata": { + "created": 0, + "modified": 0 + }, + "previous": [], + "userland": { + "movies": { + "/": "bafyr4icjyr6bcipvqzguj3gctaihetpeqxgine3zw7zkw4eyzrn2ojxwhe" + } + }, + "version": "1.0.0" + } + }, + "bytes": "oWx3bmZzL3B1Yi9kaXKkZ3ZlcnNpb25lMS4wLjBobWV0YWRhdGGiZ2NyZWF0ZWQAaG1vZGlmaWVkAGhwcmV2aW91c4BodXNlcmxhbmShZm1vdmllc9gqWCUAAXEeIEnEfBEh9YZNROzCmBByTeSFzIaTebfyq3CYzFunJvY5" + }, + { + "cid": "bafkr4ibirkdkphzauplnztoko4j35lwrpb4yffv57j4rh6rkmlmxe67y7a", + "value": { + "/": { + "bytes": "SGVsbG8sIFdvcmxkIQ" + } + }, + "bytes": "SGVsbG8sIFdvcmxkIQ==" + }, + { + "cid": "bafyr4icjyr6bcipvqzguj3gctaihetpeqxgine3zw7zkw4eyzrn2ojxwhe", + "value": { + "wnfs/pub/dir": { + "metadata": { + "created": 0, + "modified": 0 + }, + "previous": [], + "userland": { + "anime": { + "/": "bafyr4ihsg6l6g5tw45a3zh2dilphrtafnb6pyc7dpdxbuncgekjycqchnu" + } + }, + "version": "1.0.0" + } + }, + "bytes": "oWx3bmZzL3B1Yi9kaXKkZ3ZlcnNpb25lMS4wLjBobWV0YWRhdGGiZ2NyZWF0ZWQAaG1vZGlmaWVkAGhwcmV2aW91c4BodXNlcmxhbmShZWFuaW1l2CpYJQABcR4g8jeX43Z250G8n0NC3njMBWh8/AvjeO4aNEYik4FAR20=" + } +] diff --git a/wnfs/src/root_tree.rs b/wnfs/src/root_tree.rs index 1fa4e746..bd12fb9b 100644 --- a/wnfs/src/root_tree.rs +++ b/wnfs/src/root_tree.rs @@ -11,19 +11,16 @@ use anyhow::{bail, Result}; #[cfg(test)] use chrono::TimeZone; use chrono::{DateTime, Utc}; -use libipld_core::cid::Cid; use rand_chacha::ChaCha12Rng; use rand_core::{CryptoRngCore, SeedableRng}; use semver::Version; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; -#[cfg(test)] -use wnfs_common::MemoryBlockStore; use wnfs_common::{ - decode, encode, - libipld::cbor::DagCborCodec, + blockstore::{block::Block as _, Blockstore}, + ipld_core::cid::Cid, utils::{Arc, CondSend}, - BlockStore, Metadata, Storable, + Blake3Block, BlockStoreError, Metadata, Storable, CODEC_DAG_CBOR, }; //-------------------------------------------------------------------------------------------------- @@ -31,7 +28,7 @@ use wnfs_common::{ //-------------------------------------------------------------------------------------------------- #[derive(Debug, Clone)] -pub struct RootTree { +pub struct RootTree { pub store: B, pub forest: Arc, pub public_root: Arc, @@ -59,7 +56,7 @@ pub enum Partition { // Implementations //-------------------------------------------------------------------------------------------------- -impl RootTree { +impl RootTree { pub fn empty_with(store: B, rng: &mut impl CryptoRngCore, time: DateTime) -> RootTree { Self { store, @@ -423,17 +420,20 @@ impl RootTree { version: WNFS_VERSION, }; - let cid = self - .store - .put_block(encode(&serializable, DagCborCodec)?, DagCborCodec.into()) - .await?; + let block = Blake3Block::new(CODEC_DAG_CBOR, serde_ipld_dagcbor::to_vec(&serializable)?); + let cid = block.cid()?; + self.store.put(block).await?; Ok(cid) } pub async fn load(cid: &Cid, store: B) -> Result> { - let deserialized: RootTreeSerializable = - decode(&store.get_block(cid).await?, DagCborCodec)?; + let deserialized: RootTreeSerializable = serde_ipld_dagcbor::from_slice( + &store + .get(cid) + .await? + .ok_or_else(|| BlockStoreError::CIDNotFound(*cid))?, + )?; let forest = Arc::new(HamtForest::load(&deserialized.forest, &store).await?); let public_root = Arc::new(PublicDirectory::load(&deserialized.public, &store).await?); let exchange_root = Arc::new(PublicDirectory::load(&deserialized.exchange, &store).await?); @@ -455,10 +455,11 @@ impl RootTree { #[cfg(test)] mod tests { use super::*; + use wnfs_common::blockstore::InMemoryBlockstore; #[async_std::test] async fn test_roots_read_write() { - let store = MemoryBlockStore::default(); + let store = InMemoryBlockstore::<64>::new(); let mut root_tree = RootTree::empty(store); root_tree .create_private_root(&["private".into()]) diff --git a/wnfs/src/snapshots/wnfs__root_tree__snapshot_tests__root_filesystems.snap.new b/wnfs/src/snapshots/wnfs__root_tree__snapshot_tests__root_filesystems.snap.new new file mode 100644 index 00000000..60566288 --- /dev/null +++ b/wnfs/src/snapshots/wnfs__root_tree__snapshot_tests__root_filesystems.snap.new @@ -0,0 +1,328 @@ +--- +source: wnfs/src/root_tree.rs +assertion_line: 564 +expression: values +--- +[ + { + "cid": "bafyr4idl6dsrce6cnjmh4mb2q3442vvkspzzu665mltinoojwo2pwtcimy", + "value": { + "exchange": { + "/": "bafyr4ih3k2ipwwqryrlmtmwtolma4t772gknmx7pxqu5opjwsrr2nc27qq" + }, + "forest": { + "/": "bafyr4ifg6jkzfcijnvgaxbndd6p3szyapvgdb5hr2uuw35pdhqmjauzqyu" + }, + "public": { + "/": "bafyr4ih3k2ipwwqryrlmtmwtolma4t772gknmx7pxqu5opjwsrr2nc27qq" + }, + "version": "1.0.0" + }, + "bytes": "pGZmb3Jlc3TYKlglAAFxHiCm8lWSiQltTAuFox+fuWcAfUww9PHVKW314zwYkFMwxWZwdWJsaWPYKlglAAFxHiD7VpD7WhHEVsmy03LYDk//0ZTWX++8Kdc9NpRjpotfhGd2ZXJzaW9uZTEuMC4waGV4Y2hhbmdl2CpYJQABcR4g+1aQ+1oRxFbJstNy2A5P/9GU1l/vvCnXPTaUY6aLX4Q=" + }, + { + "cid": "bafyr4ih3k2ipwwqryrlmtmwtolma4t772gknmx7pxqu5opjwsrr2nc27qq", + "value": { + "wnfs/pub/dir": { + "metadata": { + "created": 0, + "modified": 0 + }, + "previous": [], + "userland": {}, + "version": "1.0.0" + } + }, + "bytes": "oWx3bmZzL3B1Yi9kaXKkZ3ZlcnNpb25lMS4wLjBobWV0YWRhdGGiZ2NyZWF0ZWQAaG1vZGlmaWVkAGhwcmV2aW91c4BodXNlcmxhbmSg" + }, + { + "cid": "bafyr4ifg6jkzfcijnvgaxbndd6p3szyapvgdb5hr2uuw35pdhqmjauzqyu", + "value": { + "accumulator": { + "generator": { + "/": { + "bytes": "DnwXmD/vORPcLzdf1evo7nGljNInOtYHpODrD3+82Nnpu0qfQPxFLKSB2dhylrLkh4UmTnLZtphq+jBbSjrWkqRf6C/qEToqzAhkAPtkF048lnLaI3UjBCXagQjJv8boXybWdaxiKxTFN2nu9B2vzNyUl1QqO9wXmNkzWM1P4T8lIm6FTjWSbHg/TVTXkpv8nTgQIUA1A0Kk7jEtjb/Vl8VdTZ2UgBywKE1Pvf8HbmXDc6Cjg0K5+XXC6SW1Bk71iLdLM174Mu8KWDjb3qotRpqrGGeSIv1KI1v1VWCI8ZuohkVe4zT5JvzyKIizsVDKcPTKGR60H6enSeQZgShFww" + } + }, + "modulus": { + "/": { + "bytes": "x5cM7tzDsHVEkCAaeqYTzXOREIHHkPXxqHJvRjVQu1t/8NuOHqEYnscvk9FlABG9chrurMKs3jKgQQfwZIwoE6MfWwt3Zf+LRLS2/8kzhLZG6wnHz16FktQOozyAA581tPFKBLUfe/14G+TRZzFkuo65kcLE1zC7vjX1kr3vUkr36Nrv0mxm/ALEea+J1k03P0QnCUOd5mzrlV8+o31RWfYTWAn4UzS1yxgTrdyAzQVgnxCsapWtZYcskJUlva0yvHKVkmQpIPJMYdxbPDt5I+VrFqTZ03PYch8ko/wPGzEx9VYVFyhmvMww+VBUyCTnM6XraBf3vBY5nUjGNhzH5Q" + } + } + }, + "root": [ + { + "/": { + "bytes": "DBg" + } + }, + [ + { + "Values": [ + [ + { + "/": { + "bytes": "ksJLdMWDZFkSS3E3g7OaTZJVjaWiwATU3XWgr7mv8c9oBYDPNafx3PU76U8BtPYtJBKt2kOdWAicQyd5vRrb41khHrBtf+j0+SFOaWPhcFo0ucq2ZFMf2BC2TqbQ7H5b21SMnPMxLrw1HMER48e9Z/SDb0S5+RntXoOLUJtPAbn9g4CHGLeqLnYcyZevrzeX1ta0kuFvbcS4/xFsrzEuwfAFQ+1eeZOFOMU0DsiptAwSFKCnMwNMbGwdxmnFqmVtCHQf+0/9yv642eZSs2Q5+5GA9wp9BN7tINbrqWHNTcKZlTHzvtAtcMysmlULyovcySxy/zuOIki75xwSAnrlFA" + } + }, + [ + { + "/": "bafkr4ia7j7qr7tr5mjtfubc3gymkywenrgox467roubruh5zxk25h3zaoq" + }, + { + "/": "bafkr4ifqkvnneofnypnyy5earqinowocjkmr2ermdhobraxej5x7ymhyfq" + } + ] + ] + ] + }, + { + "Values": [ + [ + { + "/": { + "bytes": "oQFcAlCbAaqjLdfLoKs5ES5a+CNCfJz16DfVCFUsXAHhv1IFwEoWZrNxcm/e9ufBeH4YIGW05YN9aoy4iv6iHBeT8XgHay5LgBUKWAWl3NPMlt/N9Y7hk5kjynmAXNI8nkGwKfe0UamToMdLTpqpzeiTpjo2D/sIHDwZBpGAe/M496cLPZAXQe/nkqiePII8UfpIuoEJ0MaZWcOVIBJ+15YhJSW/f1ver2dr3TpWqJzZ80Ftc+oUJSZ3zqQwz6EJC1bqIfMufm1MjSZV4s09xe5QnI7WSjK/Z+jintpsAZOJ6znSrj+u12MKOKbxnykxRCm+8KmVqaeRqHzUmAY7Zg" + } + }, + [ + { + "/": "bafkr4ie6tsog34cj43okjbawm3oihenft5phyojfjocgtckzfpcqa2sp3a" + }, + { + "/": "bafkr4igqi5pawxlga75cbj4rtmxviawihqrrndrmbmzfzt7membnfvpdgy" + } + ] + ] + ] + }, + { + "Values": [ + [ + { + "/": { + "bytes": "PRRTWbJEdyP2vNQYaAM2E8jBbkHbdEvYlyQIrBxM4QIfU20qmFzVRgWvQ+V6kXmBymY1NS/zdD4Y3Y8HwWiwKeL/J1ngQMFyyyYa+e8AHzEe0m9L6bCIy/TS2mLndg9tjOYDgc/P9g7m03tna7y5RUwFnNexMyzqUz9PLB24GtvpMjFNAbXejG1DGL0BoNqQnA6C+YneurC1bMIzKXfkjf2CPtmdU0GGLY4wWXfaDMuIhobHxrGPUXhdLCIEGiuDweEzALy8B6Q/WxVJ6xf3r8dug5ke2/Qg6qaMJUhaDfnNTXKMhsmkPA38yGEcGKo8ZLYUlJdyG9VdHesNai1jHg" + } + }, + [ + { + "/": "bafkr4if5i2ranqh33wx2ztludcfuvkk2wak56dz4iuu23pi3hfna4aqboa" + } + ] + ] + ] + }, + { + "Values": [ + [ + { + "/": { + "bytes": "LKRDbcOUq6sRIKQ3uduezN/gGUud1Otd+xAu1yJmGl4UkXqhRIIKCi7V5wP37+li32u8F25eg/5Per2y/kDMpANePEiooTECYlXWiLcux+6uOfdw8nFJBwFTQQmNAErs6jRpOcy3K9uamJwgB80GQa/XnieHMEo5d5giJJwUlcDBUO+27XL8RNn7m4WoCVjnaijjoGtVGVnF2pS/qsYAfHwBKCcP1wITdNd5ZwNVxSTqrEHu+vy0Z1rpjAvzHOZwgBZGiE6PYx0VcNI1MKakOzojvSJA2laqx5YAkDxQW3g/o1ihovjZHFWhaRoNKJzAkEbmWaGeHpIAFczEf3usAg" + } + }, + [ + { + "/": "bafkr4iadhte4pke7e7rlbggscpbhgcejcfiue5wszithlcs3xpx436x6oa" + }, + { + "/": "bafkr4ieaxnzqx2afsmwmpf6boru6ke5j3hybs73xmx456vljohcbdiw52m" + } + ] + ] + ] + } + ] + ], + "structure": "hamt", + "version": "0.1.0" + }, + "bytes": "pGRyb290gkIMGIShZlZhbHVlc4GCWQEAksJLdMWDZFkSS3E3g7OaTZJVjaWiwATU3XWgr7mv8c9oBYDPNafx3PU76U8BtPYtJBKt2kOdWAicQyd5vRrb41khHrBtf+j0+SFOaWPhcFo0ucq2ZFMf2BC2TqbQ7H5b21SMnPMxLrw1HMER48e9Z/SDb0S5+RntXoOLUJtPAbn9g4CHGLeqLnYcyZevrzeX1ta0kuFvbcS4/xFsrzEuwfAFQ+1eeZOFOMU0DsiptAwSFKCnMwNMbGwdxmnFqmVtCHQf+0/9yv642eZSs2Q5+5GA9wp9BN7tINbrqWHNTcKZlTHzvtAtcMysmlULyovcySxy/zuOIki75xwSAnrlFILYKlglAAFVHiAfT+Efzj1iZloEWzYYrFiNiZ1+e/F1Axofubq10+8gdNgqWCUAAVUeILBVWtI4rcPbjHSAjBDXWcJKmR0SLBncGILkT2/8MPgsoWZWYWx1ZXOBglkBAKEBXAJQmwGqoy3Xy6CrOREuWvgjQnyc9eg31QhVLFwB4b9SBcBKFmazcXJv3vbnwXh+GCBltOWDfWqMuIr+ohwXk/F4B2suS4AVClgFpdzTzJbfzfWO4ZOZI8p5gFzSPJ5BsCn3tFGpk6DHS06aqc3ok6Y6Ng/7CBw8GQaRgHvzOPenCz2QF0Hv55KonjyCPFH6SLqBCdDGmVnDlSASfteWISUlv39b3q9na906Vqic2fNBbXPqFCUmd86kMM+hCQtW6iHzLn5tTI0mVeLNPcXuUJyO1koyv2fo4p7abAGTies50q4/rtdjCjim8Z8pMUQpvvCplamnkah81JgGO2aC2CpYJQABVR4gnpycbfBJ5tykhBZm3IORpZ9efDklS4RpiVkrxQBqT9jYKlglAAFVHiDQR14LXWYH+iCnkZsvVALIPCMWjiwLMlzP7CMC0tXjNqFmVmFsdWVzgYJZAQA9FFNZskR3I/a81BhoAzYTyMFuQdt0S9iXJAisHEzhAh9TbSqYXNVGBa9D5XqReYHKZjU1L/N0PhjdjwfBaLAp4v8nWeBAwXLLJhr57wAfMR7Sb0vpsIjL9NLaYud2D22M5gOBz8/2DubTe2drvLlFTAWc17EzLOpTP08sHbga2+kyMU0Btd6MbUMYvQGg2pCcDoL5id66sLVswjMpd+SN/YI+2Z1TQYYtjjBZd9oMy4iGhsfGsY9ReF0sIgQaK4PB4TMAvLwHpD9bFUnrF/evx26DmR7b9CDqpowlSFoN+c1NcoyGyaQ8DfzIYRwYqjxkthSUl3Ib1V0d6w1qLWMegdgqWCUAAVUeIL1GogbA+92vrM10GItKqVqwFd8PPEUprb0bOVoOAgFwoWZWYWx1ZXOBglkBACykQ23DlKurESCkN7nbnszf4BlLndTrXfsQLtciZhpeFJF6oUSCCgou1ecD9+/pYt9rvBduXoP+T3q9sv5AzKQDXjxIqKExAmJV1oi3Lsfurjn3cPJxSQcBU0EJjQBK7Oo0aTnMtyvbmpicIAfNBkGv154nhzBKOXeYIiScFJXAwVDvtu1y/ETZ+5uFqAlY52oo46BrVRlZxdqUv6rGAHx8ASgnD9cCE3TXeWcDVcUk6qxB7vr8tGda6YwL8xzmcIAWRohOj2MdFXDSNTCmpDs6I70iQNpWqseWAJA8UFt4P6NYoaL42RxVoWkaDSicwJBG5lmhnh6SABXMxH97rAKC2CpYJQABVR4gAzzJx6ifJ+KwmNITwnMIiRFRQnbSyiZ1ilu77836/nDYKlglAAFVHiCAu3ML6AWTLMeXwXRp5ROp2fAZf3dl+d9VaXHEEaLd02d2ZXJzaW9uZTAuMS4waXN0cnVjdHVyZWRoYW10a2FjY3VtdWxhdG9yomdtb2R1bHVzWQEAx5cM7tzDsHVEkCAaeqYTzXOREIHHkPXxqHJvRjVQu1t/8NuOHqEYnscvk9FlABG9chrurMKs3jKgQQfwZIwoE6MfWwt3Zf+LRLS2/8kzhLZG6wnHz16FktQOozyAA581tPFKBLUfe/14G+TRZzFkuo65kcLE1zC7vjX1kr3vUkr36Nrv0mxm/ALEea+J1k03P0QnCUOd5mzrlV8+o31RWfYTWAn4UzS1yxgTrdyAzQVgnxCsapWtZYcskJUlva0yvHKVkmQpIPJMYdxbPDt5I+VrFqTZ03PYch8ko/wPGzEx9VYVFyhmvMww+VBUyCTnM6XraBf3vBY5nUjGNhzH5WlnZW5lcmF0b3JZAQAOfBeYP+85E9wvN1/V6+jucaWM0ic61gek4OsPf7zY2em7Sp9A/EUspIHZ2HKWsuSHhSZOctm2mGr6MFtKOtaSpF/oL+oROirMCGQA+2QXTjyWctojdSMEJdqBCMm/xuhfJtZ1rGIrFMU3ae70Ha/M3JSXVCo73BeY2TNYzU/hPyUiboVONZJseD9NVNeSm/ydOBAhQDUDQqTuMS2Nv9WXxV1NnZSAHLAoTU+9/wduZcNzoKODQrn5dcLpJbUGTvWIt0szXvgy7wpYONveqi1GmqsYZ5Ii/UojW/VVYIjxm6iGRV7jNPkm/PIoiLOxUMpw9MoZHrQfp6dJ5BmBKEXD" + }, + { + "cid": "bafkr4ia7j7qr7tr5mjtfubc3gymkywenrgox467roubruh5zxk25h3zaoq", + "value": { + "wnfs/priv/dir": { + "entries": { + "videos": { + "contentCid": { + "/": "bafkr4iadhte4pke7e7rlbggscpbhgcejcfiue5wszithlcs3xpx436x6oa" + }, + "label": { + "/": { + "bytes": "yQGatUO3pB+M+/GgYGbsHjG2uEBQiVWnu1/SkujoD0Y" + } + }, + "snapshotKey": { + "/": { + "bytes": "IG+kr1DmwFUNkhYAoCWczPt9zGIu9mTODMovJXO2JDg" + } + }, + "temporalKey": { + "/": { + "bytes": "BfXAsCDWBrqgeSWmPiIo2zxJ9nX5c6DnEJpzf1ouUXh+scPQemfBWQ" + } + } + } + }, + "headerCid": { + "/": "bafkr4ifqkvnneofnypnyy5earqinowocjkmr2ermdhobraxej5x7ymhyfq" + }, + "metadata": { + "created": 0, + "modified": 0 + }, + "previous": [ + [ + 1, + { + "/": { + "bytes": "qF533vnhhUek/eYchX7NHXD18uLePur7zdCVFgPLTtmoP3j0spdv4ApNGJoWvoiyWQJ/5tGdp/4" + } + } + ] + ], + "version": "1.0.0" + } + }, + "bytes": "lGkOYRCu2AOX6pLROoK4EeP9HdsoYT+ezxC7LvMo7B3FY4atKGO3On6KRS913ok09c35cjsq0aG0GO/IcimakFL8//LcZMMOKdFxKY2l5tC1nsoy72o3HDtKd7aOPr70h26AQL+UfTefIJKJtsyU3DYDuUNVuMhxAYRzSgR+93tw8CAQyx18yQTQyM/p/eEERvHJtNFLrLAxl76/r7gJhwtnRjxv2NUcnf2HBDI26m6SXlZHFD+ekNQ91A5grdNSq7VHRH8Y7qp/IIZOut3yiwzkxTd1U5b/sQJmfsq4T0+EdQShX2Ta+7uyU+gl+Ncc6CRmd3I2a3JD3miqp8fhxhqEhB+k5M6avr8fZDJZgDY1S+xT/4QetbZ99cceNGSWktX5HpYP7pvL8SzQEPlkq8EZp0X3q55TLl3DS+gtEZs1vPWbZPy7M43oy0hhctEyq8YXCIOuj2Ui8Safm0q3xU7zjsAnHTKfYUWUg32UX9bfgYBgKYd0Lyet5vmqeAD46A9WimBSo0z/2yWpVAVKlPX21SVptXQiIyhThruGNEGTtDBMZmQQEydNFyEP" + }, + { + "cid": "bafkr4ifqkvnneofnypnyy5earqinowocjkmr2ermdhobraxej5x7ymhyfq", + "value": { + "inumber": { + "/": { + "bytes": "wTIY5Lj52cZAPjN2QxQb04Tvs5ben9hjXKIVD5UpCeE" + } + }, + "name": { + "/": { + "bytes": "WzUFTg2et93G6urhSL2Viqdf49sAgAv0vv8SE1SgzA2V80ukVHaZR6+PcbbkvJa7kqRzKbUJ8si3pckU/2L30Kmr+JVM38v6cQAT5N0y9KiTmXX6EyUIkQ5r+zfH8xybEhJ00mPJbRpB76OgZ24z9a1VLWQCcenR6GsrPWUkU94p3r8XBQtIBni/uHjKlpFvR/Csq+pmoBqK5qOYaDsgWn6nV8pgMIIRFifu6S7bw9SSMtRUrW/FFfcu1GjRHeq7UV71wyUGGB2gpC4Ekm8Y/tri1S3zHbLnh54ck+tjUZM0MMRSWnL+FvwXcYKaxfRmxooi0Jajw3zF+xGdW8hlnw" + } + }, + "ratchet": { + "large": { + "/": { + "bytes": "0Xcz7RLjVmm+AzcWeY2i2QLcclCjoJktNy65o58rQDw" + } + }, + "medium": { + "/": { + "bytes": "Nk4K4fSXXGSIL1hQ0gHHVGKjY/xSLm4fcLv3z0IPI5U" + } + }, + "mediumCounter": 187, + "salt": { + "/": { + "bytes": "ONa5zrgjyuV6QSBzqKdagXT6HqmDbOX6b0+TK6spVOw" + } + }, + "small": { + "/": { + "bytes": "GW6XCdcS0jHPZikFzLxI+KfsQ7zW4fZDxUHoah+l5hU" + } + }, + "smallCounter": 184 + } + }, + "bytes": "EAc+yk8dlWg1IgUl8Qi5Hc6njiV2dZLiOHLA8wPnB37EhWYy7mBS+6DxHeY7iiDbBNjVG+93Sy5QYK3G1VBwIi/mu2ECvrtVghiHcB1JZNDjUApu8STu5vc5YaR44w/l+K5Fq3NLRye9pc1fYOj3om6OtUOMzGxOjgI7NsvP0u7OI4hIV9lv6SsLYNZAmQA3+IkhCO6GNWJE9yT2dKPEe6R2nqLvf8QhUowapFuhfaP5aa1ui/9fi9CYGqK/UeVEUVwBTvd0rECiwR2nt4ioFQlVrsvQV7+qhkhZuksmfywu0PgEaWAylcdcWLsjDWYtnHEnEu1pRgEtZIf+yAEdl/GvgliHns/urWviOmj1bIf3Yqu3/2jrnNg/rYhgOMZ/i/C4JTZI2KbXi86MVCmNwc0CcqyuyfCP3AQqrTb6QGfAfwyVweCFaWHsweNVZFnoKIzZVbp4ew59mMksJ9Y4aswQDNe9LCAyzBUpE1PR6HxG2bkZt0UrcLv2S7e8uKFB59JqqBZUIh+xS5w3C80g1IpeuKF2GbNME6TIKXMAy0McqdTUybQHKBaoDnanF4foElHwD9hP2sr5u/+AcN8GPsqc1IcWQx2Tm4ne1k3Sz+BFGd4BcCVobORd2c/jDKukQLKNgoS+olgqjktgvQjlQ9CtxmYjX5j6nbbEDPzgzhduArVMbSxoUQ==" + }, + { + "cid": "bafkr4ie6tsog34cj43okjbawm3oihenft5phyojfjocgtckzfpcqa2sp3a", + "value": { + "/": { + "bytes": "e7jkHFUGlv3veP/28BO7NGJ7pQyi1jtux67NqxpxYiDeYXYnuRl8LKEKreqYrh51gc+20hSeleXs0ZEc8gI4ORRHcBKlt6aVmSH6CpfubeN4H7nWlwspcPJlf6FVq54r/DSyajNZCYMFDT58D75PolUL7x4Gd723YACtm6pT9sMD+HFjGigi+tL9D1LzubEv2D7K8Ns3Fa2IUBa2JuTDqhp+uC4Z0RiVvg" + } + }, + "bytes": "e7jkHFUGlv3veP/28BO7NGJ7pQyi1jtux67NqxpxYiDeYXYnuRl8LKEKreqYrh51gc+20hSeleXs0ZEc8gI4ORRHcBKlt6aVmSH6CpfubeN4H7nWlwspcPJlf6FVq54r/DSyajNZCYMFDT58D75PolUL7x4Gd723YACtm6pT9sMD+HFjGigi+tL9D1LzubEv2D7K8Ns3Fa2IUBa2JuTDqhp+uC4Z0RiVvg==" + }, + { + "cid": "bafkr4igqi5pawxlga75cbj4rtmxviawihqrrndrmbmzfzt7membnfvpdgy", + "value": { + "/": { + "bytes": "DHAqFkyhSq1pfHhVFwjM3mOGavKHKzImFFIHQFbCO9GW5F1WvrJyRJ/O1ddtH1Y10UElHzGdBWCDGmAeCD3s9LliEeX/zviQrxll+49pBLuemBCrEec41NMorg/Izhf2ggaGoAnHClDJRy6v0DsNKMegjjQcJ9HOOqPLRTnjEJKJr1RRRBoLia9ibSAmHb3W67okaE0PParzKfe5+qhzirTGlnoN5y9cpjsErV5WK/V0+6o1loFRE5dvsgX87KdmyM033rKaE2Las8VJq4p+hIGuVxenuhptNI+VyRKfi4ZBz/2pOxNqh5vQGywPwNh/kVY+H9Riy1oJMJMep8BfJoLYgt8e0Nl+EAjYc/RKUi6QoUWAENvd2nhHUKjjW0y8+sQBFM0i735gkZFgIL5V7Eq6YM0FlJcBniBSUjkJOf/cGHyhAmQH9/XMf5Q4/8DKmOU7XSMhmTR2M1SDRspBomPlarXtUUVtER7p8+lGNcWWZAAGzFYhPiJ4wyaJXRVkZ0E/yFn+lGgWiKs9H+VpJZ0xFrB1PXhLbuIoUNgFEZvErIuHQdFzdwIwHQPjeIeR4Sf9cyZFMZS3puKYkE2K2ItF8XH1g89pPhijKeDp8/wBPAuouX4VhaHZQVVv6+aVohKWGSUNXWX2bTpDLP+/1aM5gQb9U1EsNNUrW8J5DwS9rYZg43NWsg" + } + }, + "bytes": "DHAqFkyhSq1pfHhVFwjM3mOGavKHKzImFFIHQFbCO9GW5F1WvrJyRJ/O1ddtH1Y10UElHzGdBWCDGmAeCD3s9LliEeX/zviQrxll+49pBLuemBCrEec41NMorg/Izhf2ggaGoAnHClDJRy6v0DsNKMegjjQcJ9HOOqPLRTnjEJKJr1RRRBoLia9ibSAmHb3W67okaE0PParzKfe5+qhzirTGlnoN5y9cpjsErV5WK/V0+6o1loFRE5dvsgX87KdmyM033rKaE2Las8VJq4p+hIGuVxenuhptNI+VyRKfi4ZBz/2pOxNqh5vQGywPwNh/kVY+H9Riy1oJMJMep8BfJoLYgt8e0Nl+EAjYc/RKUi6QoUWAENvd2nhHUKjjW0y8+sQBFM0i735gkZFgIL5V7Eq6YM0FlJcBniBSUjkJOf/cGHyhAmQH9/XMf5Q4/8DKmOU7XSMhmTR2M1SDRspBomPlarXtUUVtER7p8+lGNcWWZAAGzFYhPiJ4wyaJXRVkZ0E/yFn+lGgWiKs9H+VpJZ0xFrB1PXhLbuIoUNgFEZvErIuHQdFzdwIwHQPjeIeR4Sf9cyZFMZS3puKYkE2K2ItF8XH1g89pPhijKeDp8/wBPAuouX4VhaHZQVVv6+aVohKWGSUNXWX2bTpDLP+/1aM5gQb9U1EsNNUrW8J5DwS9rYZg43NWsg==" + }, + { + "cid": "bafkr4if5i2ranqh33wx2ztludcfuvkk2wak56dz4iuu23pi3hfna4aqboa", + "value": { + "/": { + "bytes": "aGVsbG8gd29ybGQ" + } + }, + "bytes": "VgFiuyjwLxAVo9zsONyk/HNTWymLC4A3EEuSozh0iYFkMP8FTIeeG/VSDYTUaa7kwqcP" + }, + { + "cid": "bafkr4iadhte4pke7e7rlbggscpbhgcejcfiue5wszithlcs3xpx436x6oa", + "value": { + "wnfs/priv/file": { + "content": { + "external": { + "baseName": { + "/": { + "bytes": "vQ54kY5pL8AvwnQs6JRG2n8jd/Z3tBSiBNlGvN0kafeMqx4FS9k+4nFNQJXIkZ/WhFRMS6GbkCQSVrPXYzdvjM5Q03Opb7UvzXIuk4QbGFkFBFoQaxmbHmOnVGbpwFLk9qpVos8IdeRuty21U7Q6Ls8YL56VZy4DSdqR3ZBthhrlzPvtK3mdvBeX649NvSatbTdfCa7RvLpaJ92q95Mb7GC0jq740HLINUdcLOI/gcn2rXV8dJvWAtp1kCvXXlZDbZv+3+ZNyu2ajXhIHsxDbUyPSDjpcWdQp8wqAR6Ul1ckOcNbqZ4FsJhxdAi31pQjAjcLFNNE2Mg5YHEtDBOJVw" + } + }, + "blockContentSize": 262104, + "blockCount": 1, + "key": { + "/": { + "bytes": "jU5e4dCLQ6PYBFe/CeCVei+SK1jnlkbgKiUpy3yZ494" + } + } + } + }, + "headerCid": { + "/": "bafkr4ieaxnzqx2afsmwmpf6boru6ke5j3hybs73xmx456vljohcbdiw52m" + }, + "metadata": { + "created": 0, + "modified": 0 + }, + "previous": [], + "version": "1.0.0" + } + }, + "bytes": "B37cb+IrIPpyzAtM7pjd6qWgYmMRNV2tU+3ZCp6e/xGfkyaJ2+ocfd9mURj0YdRSYStW6969aJY50skbSGQg4CwfvGBtPLgKBg2YbPqsCVvO6aSxkZjV1twj7tHifApj2+sS1ju9KcqgaFUOXmaEJJu5dSMGvjOQqIMx67rjirS6OKsufZHhvfnwA65Wf9Es6aFGmyfXG2DoEb90zLOGhXzupQaIlzxqVolFnKeIMBiThSpaf4JM8T/RFM/aUGDf+h5yJ0AB+mATtHybnVIHWcDWGjcPV30PIB4pz3UTavlOt0k4Wcfei8S+mssieqhXPpExAZf9yx+sln+/Vrv2kWPo3JReGttQgjvgmRZ8wBk9lHGW9jOtl2OIWiRfisXQMR5KOfhOMlWX8GxNbLTzB3pOvFC0Na/5vz5YbIJkOtbfgBgzF6Xb9R1pHDMEcAUYRYgIuzQXaShFKkMYvWR+Hra/6ZFyJ8Q61azjxbp+dhS0bFibTy3/BIBRKHtkTgVI3AuWMIEUMVavnCKTL4vzvB4XYpBJWv5NKc8UudhyPhHdIXQz/wYtpvUfVKFSOJhukJAPGv+vlhfhlJcxyNn/hQFwuTI0xoIvIchfgHM8o/jEnlwpw/uRSbGgq8sRVhmIj6xgclxy42XBNsz8lAhcliugH4L5uG6KLoXecj3D+Y0ggOr0OnDZ1A==" + }, + { + "cid": "bafkr4ieaxnzqx2afsmwmpf6boru6ke5j3hybs73xmx456vljohcbdiw52m", + "value": { + "inumber": { + "/": { + "bytes": "me0X91Is5qDx06gvyQPXcPK5uv4JFHhvz6uTH50unZ8" + } + }, + "name": { + "/": { + "bytes": "j6YzwzpX6DUWE/zrM4KvY5WFhBOSjdry0gCan5UNBZ0hPAV1Oz6oiOfv8Kg2pAb6Y/NQSqtYfLSfNsFWb6gKK/GPklCVw5cOAd38HZh2E4dQopSFBfU9TJzbVfvYuLuoA+RsQDcXzuRQi52TLzaO4DC+z84JqNt0BlR7SSZE96ca4FQZCK3MKr7e1EEv2gQfla9UNenvCIUBQdJJZsxfPic6EUT+/2tg5VrjFCgiXMdtgrOnHZ4cSjHeG5L/BW6BNNjbPsg2sigB6KVjZp8fzLVZL3lk5/8e6Fgi3P9jW/SDVxJi+8EKfqz+qRzhRTTxWcpjRl2RcDHNIxsHr4Xh1w" + } + }, + "ratchet": { + "large": { + "/": { + "bytes": "Bt+ey5Boc0Fgx4R78mg9A5Q4DJeZYVzfhja2lwm97Bk" + } + }, + "medium": { + "/": { + "bytes": "3AkDRYPkuG+x+Mp/miOAJ1yS+9W8Iy+wcue3MK43D6g" + } + }, + "mediumCounter": 168, + "salt": { + "/": { + "bytes": "0Ee3Zec2xWFCuo0RnICxnKIJBmcu20LvFKPh4lLjzoM" + } + }, + "small": { + "/": { + "bytes": "AVPlenVmZaC/go5ocjSdkW9R+KorleUn8NIzESoQMZE" + } + }, + "smallCounter": 20 + } + }, + "bytes": "N7wdaPdPxzmYQOJ7edmSQLgLG1h/dh/o2iGEwgrUgcVOGCH3l+LZGlWTWSUpThsAUJ9PthEHx1Vh35E+ruszmko1D1VanK/HD4Xd43o5LQoYjpPZua05+niYlfwUu6C9tpO8STn3nozwJxKDmOAnKzZ8Wfi+OafWAPpGG1ilAScwpXNDwPupW+3XC4XsYvDv1ARaWKlMA6jMcQU+isa/VjvpFB6DJRiF/I6oCF+V1zlW6gxt8yh4w7vN5Q2A+n7XmMLtRyad3QmFvch/oo+2M+Hny/wdGOOb4ch5tn0rC90aiQnsGteF8DejqhRSjGvuXOyZ4MnClGJ75E70QoOAtmWFUB5Nrqg8L5W7ZUQTc+TiaVlj9H8mxbmxwoGxEMZzncT6LIUyuvEjyWOOuje3zsBadpe29nmjc/BmP2ASerG+CtxYj7Ogzrt+uQ7GroRylElCGJz1sn7DmCMKOuJJlRK5aR9cbM2BrCKLaTXQkYUlnI1Vahk/st/GbvMvP7b5yWghRlMTpiRZta7GycJ2oKMpm0JBsjeLpbIxn6PIOMuY3jGpjQ9vOc52FH/tItN+FheT1Rbl05+8AgPuS3m3S4fsahWqpWpyMAKD0qaFVV7cAu0cKQnnQeK7uoOWSieoG4eBk2DHwovJo/xSBypO6U6PF+hI4q3Oer4LdGNjeenba2mtj/NsMA==" + } +] diff --git a/wnfs/src/utils/test.rs b/wnfs/src/utils/test.rs index 899c76af..338164ec 100644 --- a/wnfs/src/utils/test.rs +++ b/wnfs/src/utils/test.rs @@ -5,11 +5,9 @@ use crate::private::{ }; use anyhow::Result; use bytes::Bytes; -use libipld_core::ipld::Ipld; use rand_core::CryptoRngCore; use wnfs_common::{ - decode, - libipld::cbor::DagCborCodec, + ipld_core::ipld::Ipld, utils::{Arc, BytesToIpld, CondSend, SnapshotBlockStore}, }; use wnfs_nameaccumulator::Name; @@ -20,7 +18,9 @@ struct EncryptedBlockHandler { impl BytesToIpld for EncryptedBlockHandler { fn convert(&self, bytes: &Bytes) -> Result { - decode(&self.snapshot_key.decrypt(bytes.as_ref())?, DagCborCodec) + Ok(serde_ipld_dagcbor::from_slice( + &self.snapshot_key.decrypt(bytes.as_ref())?, + )?) } } @@ -30,10 +30,9 @@ struct KeyWrappedBlockHandler { impl BytesToIpld for KeyWrappedBlockHandler { fn convert(&self, bytes: &Bytes) -> Result { - decode( + Ok(serde_ipld_dagcbor::from_slice( &self.temporal_key.key_wrap_decrypt(bytes.as_ref())?, - DagCborCodec, - ) + )?) } }