Skip to content

Commit

Permalink
feat: Preliminary RootTree APIs (#390)
Browse files Browse the repository at this point in the history
* feat: Expose & work on root tree module

* feat: Add private root storing & loading in `RootTree`

Also:
- Fix nameaccumulator lib not working when the "rug" features is on, but "num-bigint-dig" is off.
- Avoid `.unwrap()` in `AccessKey`.

* feat: `#[derive(Clone)] RootTree`

* chore: Remove left-over debugging `println!`

* fix: Make `RootTree` snapshot test deterministic

* fix: Wasm compilation

* feat: Add `PublicFile::size` function

* fix: Handle greater than file size read limits

* fix: Filesize computation

* chore: Hide `root_tree` module from documentation

It's not yet documented/finished.
  • Loading branch information
matheus23 authored Apr 14, 2024
1 parent 87839b7 commit 1554bb3
Show file tree
Hide file tree
Showing 12 changed files with 506 additions and 389 deletions.
1 change: 0 additions & 1 deletion wnfs-nameaccumulator/src/traits.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#[cfg(feature = "num-bigint-dig")]
use num_bigint_dig::{prime::probably_prime, BigUint, ModInverse, RandBigInt, RandPrime};
#[cfg(feature = "num-bigint-dig")]
use num_traits::{One, Zero};
use rand_core::CryptoRngCore;
#[cfg(feature = "rug")]
Expand Down
14 changes: 10 additions & 4 deletions wnfs-wasm/src/fs/private/access_key.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::fs::{utils::error, JsResult};
use wasm_bindgen::prelude::wasm_bindgen;
use wnfs::private::AccessKey as WnfsAccessKey;

Expand Down Expand Up @@ -53,13 +54,18 @@ impl AccessKey {
/// Make sure to keep safe or encrypt
/// (e.g. using the WebCrypto and asymmetrically encrypting these bytes).
#[wasm_bindgen(js_name = "toBytes")]
pub fn into_bytes(&self) -> Vec<u8> {
Vec::<u8>::from(&self.0)
pub fn into_bytes(&self) -> JsResult<Vec<u8>> {
let bytes = self
.0
.to_bytes()
.map_err(error("Couldn't serialize access key"))?;
Ok(bytes)
}

/// Deserialize an AccessKey previously generated from `into_bytes`.
#[wasm_bindgen(js_name = "fromBytes")]
pub fn from_bytes(bytes: &[u8]) -> Self {
Self(WnfsAccessKey::from(bytes).into())
pub fn from_bytes(bytes: &[u8]) -> JsResult<AccessKey> {
let access_key = WnfsAccessKey::parse(bytes).map_err(error("Couldn't parse access key"))?;
Ok(Self(access_key))
}
}
2 changes: 1 addition & 1 deletion wnfs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ multihash = "0.19"
once_cell = "1.16"
proptest = { version = "1.1", optional = true }
quick_cache = "0.4.0"
rand_chacha = "0.3"
rand_core = "0.6"
semver = { version = "1.0", features = ["serde"] }
serde = { version = "1.0", features = ["rc"] }
Expand All @@ -58,7 +59,6 @@ fake = { version = "2.6.1", features = ["chrono"] }
insta = "1.30"
proptest = "1.1"
rand = "0.8"
rand_chacha = "0.3"
rsa = "0.9"
serde_json = "1.0.103"
sha2 = "0.10"
Expand Down
4 changes: 2 additions & 2 deletions wnfs/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ pub enum FsError {
#[error("Mismatch between PrivateNode name {0} and its mountpoint {0}")]
MountPointAndDeserializedNameMismatch(String, String),

#[error("Cannot find private ref with specified root path")]
PrivateRefNotFound,
#[error("Cannot find the partition with this name")]
PartitionNotFound,
}

/// Data sharing related errors
Expand Down
3 changes: 2 additions & 1 deletion wnfs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@
pub mod error;
pub mod private;
pub mod public;
pub(crate) mod root_tree;
#[doc(hidden)] // The API is in "prerelease" for now
pub mod root_tree;
pub mod traits;
mod utils;

Expand Down
20 changes: 8 additions & 12 deletions wnfs/src/private/keys/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ pub struct SnapshotAccessKey {
//--------------------------------------------------------------------------------------------------

impl AccessKey {
pub fn parse(bytes: impl AsRef<[u8]>) -> Result<Self> {
Ok(serde_ipld_dagcbor::from_slice(bytes.as_ref())?)
}

pub fn to_bytes(&self) -> Result<Vec<u8>> {
Ok(serde_ipld_dagcbor::to_vec(self)?)
}

pub fn get_label(&self) -> &HashOutput {
match self {
Self::Temporal(key) => &key.label,
Expand Down Expand Up @@ -105,18 +113,6 @@ impl From<&PrivateRef> for SnapshotAccessKey {
}
}

impl From<&[u8]> for AccessKey {
fn from(bytes: &[u8]) -> Self {
serde_ipld_dagcbor::from_slice(bytes).unwrap()
}
}

impl From<&AccessKey> for Vec<u8> {
fn from(key: &AccessKey) -> Self {
serde_ipld_dagcbor::to_vec(key).unwrap()
}
}

//--------------------------------------------------------------------------------------------------
// Tests
//--------------------------------------------------------------------------------------------------
Expand Down
1 change: 0 additions & 1 deletion wnfs/src/private/node/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,6 @@ impl SnapshotKey {
#[cfg(test)]
mod proptests {
use super::*;
use crate::private::KEY_BYTE_SIZE;
use proptest::{prelude::any, prop_assert_eq, prop_assert_ne};
use rand_chacha::ChaCha12Rng;
use rand_core::SeedableRng;
Expand Down
2 changes: 1 addition & 1 deletion wnfs/src/private/previous.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ impl<F: PrivateForest + Clone> PrivateNodeOnPathHistory<F> {
#[cfg(test)]
mod tests {
use super::*;
use crate::private::{forest::hamt::HamtForest, PrivateDirectory};
use crate::private::forest::hamt::HamtForest;
use chrono::Utc;
use rand_chacha::ChaCha12Rng;
use rand_core::SeedableRng;
Expand Down
3 changes: 2 additions & 1 deletion wnfs/src/public/directory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ impl PublicDirectory {
path_segments: &[String],
store: &impl BlockStore,
) -> Result<SearchResult<&'a mut Self>> {
// TODO(matheus23) actually set the modification time of all these nodes
let mut working_dir = self.prepare_next_revision();
for (depth, segment) in path_segments.iter().enumerate() {
match working_dir.lookup_node(segment, store).await? {
Expand Down Expand Up @@ -634,6 +635,7 @@ impl PublicDirectory {
path_segments: &[String],
store: &impl BlockStore,
) -> Result<PublicNode> {
// TODO(matheus23) set modification time
let (path, node_name) = utils::split_last(path_segments)?;

let SearchResult::Found(dir) = self.get_leaf_dir_mut(path, store).await? else {
Expand Down Expand Up @@ -885,7 +887,6 @@ impl Storable for PublicDirectory {
#[cfg(test)]
mod tests {
use super::*;
use chrono::Utc;
use libipld_core::ipld::Ipld;
use testresult::TestResult;
use wnfs_common::{decode, libipld::cbor::DagCborCodec, MemoryBlockStore};
Expand Down
12 changes: 8 additions & 4 deletions wnfs/src/public/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use super::{PublicFileSerializable, PublicNodeSerializable};
use crate::{error::FsError, is_readable_wnfs_version, traits::Id, WNFS_VERSION};
use anyhow::{bail, Result};
use anyhow::{anyhow, bail, Result};
use async_once_cell::OnceCell;
use chrono::{DateTime, Utc};
use futures::{AsyncRead, AsyncReadExt};
Expand Down Expand Up @@ -297,8 +297,10 @@ impl PublicFile {
len_limit: Option<usize>,
store: &'a impl BlockStore,
) -> Result<Vec<u8>> {
let size = self.size(store).await?;
let mut reader = self.stream_content(byte_offset, store).await?;
if let Some(len) = len_limit {
let len = std::cmp::min(len as u64, size - byte_offset) as usize;
let mut buffer = vec![0; len];
reader.read_exact(&mut buffer).await?;
Ok(buffer)
Expand Down Expand Up @@ -343,8 +345,11 @@ impl PublicFile {
/// }
/// ```
pub async fn size(&self, store: &impl BlockStore) -> Result<u64> {
let value = self.userland.resolve_value(store).await?;
Ok(value.filesize().unwrap_or(0))
self.userland
.resolve_value(store)
.await?
.filesize()
.ok_or_else(|| anyhow!("Missing size on dag-pb node"))
}

/// Gets the entire content of a file.
Expand Down Expand Up @@ -533,7 +538,6 @@ impl Clone for PublicFile {
#[cfg(test)]
mod tests {
use super::*;
use chrono::Utc;
use wnfs_common::MemoryBlockStore;

#[async_std::test]
Expand Down
Loading

0 comments on commit 1554bb3

Please sign in to comment.