26 个版本

0.2.2 2024 年 3 月 8 日
0.1.27 2023 年 12 月 6 日
0.1.26 2023 年 9 月 10 日
0.1.21 2023 年 6 月 14 日
0.1.6 2022 年 5 月 23 日

#3 in #去中心化


2 crates 中使用

Apache-2.0

4.5MB
15K SLoC

WNFS Logo

WebNative FileSystem (WNFS)

Docs Code Coverage Build Status License Docs Discord

⚠️ 正在开发中 ⚠️

这是 WebNative FileSystem (WNFS) 规范的 Rust 实现。WNFS 是一个带版本号的、基于内容寻址的分布式文件系统,具有私有和公共子系统。私有文件系统是加密的,只有拥有正确密钥的用户才能访问其内容。它旨在防止推断元数据,如文件树的结构。WNFS 文件系统的另一部分是一个更简单的公共文件系统,未加密,任何拥有正确地址的人都可以访问。

WNFS 还具有文件树协作编辑的功能,允许多个用户同时编辑同一树。

WNFS 文件树可以序列化和反序列化自 IPLD 图,具有可扩展的元数据部分。这使得 WNFS 可以被其他基于 IPLD 的工具和系统理解。

用法

WNFS 对您希望持久化内容或文件树的位置没有意见。相反,API 接受任何实现了异步 BlockStore 特性的对象。该库还避免包含可能将其绑定到一组平台的系统功能调用。操作,如时间和随机数生成,必须通过 API 传递。这使得库可以在各种环境中使用。它尤其使虚拟化变得更容易。

让我们看看如何处理公共文件系统的示例。我们将使用库提供的内存块存储。

use anyhow::Result;
use chrono::Utc;
use wnfs::{
    common::MemoryBlockStore,
    public::PublicDirectory
};

#[async_std::main]
async fn main() -> Result<()> {
    // Create a new public directory.
    let dir = &mut PublicDirectory::new_rc(Utc::now());

    // Create an in-memory block store.
    let store = &MemoryBlockStore::default();

    // Add a /pictures/cats subdirectory.
    dir.mkdir(&["pictures".into(), "cats".into()], Utc::now(), store)
        .await?;

    // Store the the file tree in the in-memory block store.
    dir.store(store).await?;

    // List all files in /pictures directory.
    let result = dir.ls(&["pictures".into()], store).await?;

    println!("Files in /pictures: {:#?}", result);

    Ok(())
}

在这里,我们创建一个根目录 dir,然后向其中添加一个 /pictures/cats 子目录。如前所述,系统级操作,如时间,通过 API 传递。在这种情况下,我们使用来自 [chrono][chrono-crate] 库的 Utc::now() 函数来获取当前时间。

PublicDirectory 在这里被 Rc 包装起来,因为它允许我们无需担心所有权和生命周期就可以传递它。进一步将 &mut 的 Rc 应用到内部 PublicDirectory,并在需要时指向新的一个(基本上是每次写入时)。这种不可变的方式来处理更改具有跟踪和回滚更改等酷炫的好处。它还使得协作编辑更容易实现和推理。你可以在 wnfs/examples/ 文件夹中找到更多示例。

这是公开文件系统,另一方面,私有文件系统则更为复杂。我们存储私有文件树和一些与之相关的信息的地方是 哈希数组映射 trie (HAMT)。HAMT 允许有效地存储和检索加密和混淆的文件树以及 PrivateForest,它基本上是一个可以包含多个文件树(以哈希作为键,CIDs作为值)的 HAMT。

use anyhow::Result;
use chrono::Utc;
use rand_chacha::ChaCha12Rng;
use rand_core::SeedableRng;
use wnfs::{
    common::MemoryBlockStore,
    private::{
        PrivateDirectory,
        forest::{hamt::HamtForest, traits::PrivateForest},
    }
};

#[async_std::main]
async fn main() -> Result<()> {
    // Create an in-memory block store.
    let store = &MemoryBlockStore::default();

    // A random number generator.
    let rng = &mut ChaCha12Rng::from_entropy();

    // Create a private forest.
    let forest = &mut HamtForest::new_trusted_rc(rng);

    // Create a new private directory.
    let dir = &mut PrivateDirectory::new_rc(&forest.empty_name(), Utc::now(), rng);

    // Add a file to /pictures/cats directory.
    dir.mkdir(
        &["pictures".into(), "cats".into()],
        true,
        Utc::now(),
        forest,
        store,
        rng,
    )
    .await?;

    // Add a file to /pictures/dogs/billie.jpg file.
    dir.write(
        &["pictures".into(), "dogs".into(), "billie.jpg".into()],
        true,
        Utc::now(),
        b"Hello! This is billie".to_vec(),
        forest,
        store,
        rng,
    )
    .await?;

    // List all files in /pictures directory.
    let result = dir.ls(&["pictures".into()], true, forest, store).await?;

    println!("Files in /pictures: {:#?}", result);

    Ok(())
}

这个例子介绍了一些新概念。第一个是 HamtForest,它是一个可以包含多个文件树的 HAMT,并实现了用于持久化私有文件系统的 PrivateForest 接口。

第二个是 Name(由 forest.empty_name() 返回)和 NameAccumulator,它让我们能够识别文件系统中的节点,并且适合于后代证明。

最后,我们有随机数生成器 rng,库用它来生成新密钥和协议所需的其他随机值。

请查看 wnfs/examples/ 文件夹以获取更多示例。

依赖项

~14-22MB
~313K SLoC