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 中使用
4.5MB
15K SLoC
这是 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