{"id":15431451,"url":"https://github.com/ehsan6sha/rs-wnfs","last_synced_at":"2025-10-11T09:32:16.258Z","repository":{"id":257806158,"uuid":"689725863","full_name":"ehsan6sha/rs-wnfs","owner":"ehsan6sha","description":"Rust implementation of the WebNative FileSystem (WNFS) specification","archived":false,"fork":true,"pushed_at":"2023-09-10T15:46:53.000Z","size":6140,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-03-28T05:41:31.514Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://github.com/wnfs-wg","language":null,"has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"wnfs-wg/rs-wnfs","license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ehsan6sha.png","metadata":{},"created_at":"2023-09-10T17:59:10.000Z","updated_at":"2023-09-10T17:59:10.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ehsan6sha/rs-wnfs","commit_stats":null,"previous_names":["ehsan6sha/rs-wnfs"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ehsan6sha/rs-wnfs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehsan6sha%2Frs-wnfs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehsan6sha%2Frs-wnfs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehsan6sha%2Frs-wnfs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehsan6sha%2Frs-wnfs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ehsan6sha","download_url":"https://codeload.github.com/ehsan6sha/rs-wnfs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehsan6sha%2Frs-wnfs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279006752,"owners_count":26084180,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-11T02:00:06.511Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-01T18:22:23.177Z","updated_at":"2025-10-11T09:32:16.250Z","avatar_url":"https://github.com/ehsan6sha.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://github.com/wnfs-wg\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://raw.githubusercontent.com/wnfs-wg/rs-wnfs/main/assets/logo.png\" alt=\"WNFS Logo\" width=\"100\" height=\"100\"\u003e\u003c/img\u003e\n  \u003c/a\u003e\n\n  \u003ch1 align=\"center\"\u003eWebNative FileSystem (WNFS)\u003c/h1\u003e\n\n  \u003cp\u003e\n    \u003ca href=\"https://crates.io/crates/wnfs\"\u003e\n      \u003cimg src=\"https://img.shields.io/crates/v/wnfs?label=crates\" alt=\"Concurrency Docs\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://codecov.io/gh/wnfs-wg/rs-wnfs\"\u003e\n      \u003cimg src=\"https://codecov.io/gh/wnfs-wg/rs-wnfs/branch/main/graph/badge.svg?token=95YHXFMFF4\" alt=\"Code Coverage\"/\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/wnfs-wg/rs-wnfs/actions?query=\"\u003e\n      \u003cimg src=\"https://github.com/wnfs-wg/rs-wnfs/actions/workflows/checks.yaml/badge.svg\" alt=\"Build Status\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/wnfs-wg/rs-wnfs/blob/main/LICENSE\"\u003e\n      \u003cimg src=\"https://img.shields.io/badge/License-Apache%202.0-blue.svg\" alt=\"License\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://docs.rs/wnfs\"\u003e\n      \u003cimg src=\"https://img.shields.io/static/v1?label=Docs\u0026message=docs.rs\u0026color=blue\" alt=\"Concurrency Docs\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://discord.gg/zAQBDEq\"\u003e\n      \u003cimg src=\"https://img.shields.io/static/v1?label=Discord\u0026message=join%20us!\u0026color=mediumslateblue\" alt=\"Discord\"\u003e\n    \u003c/a\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\u003csub\u003e:warning: Work in progress :warning:\u003c/sub\u003e\u003c/div\u003e\n\n##\n\nThis is a Rust implementation of [the WebNative FileSystem (WNFS) specification][wnfs-spec]. WNFS is a versioned content-addressable distributed filesystem with private and public sub systems. The private filesystem is encrypted so that only users with the right keys can access its contents. It is designed to prevent inferring metadata like the structure of the file tree. The other part of the WNFS filesystem is a simpler public filesystem that is not encrypted and can be accessed by anyone with the right address.\n\nWNFS also features collaborative editing of file trees, where multiple users can edit the same tree at the same time.\n\nWNFS file trees can serialize and be deserialized from [IPLD graphs][ipld-spec] with an extensible metadata section. This allows WNFS to be understood by other [IPLD-based tools][npm-ipld-tools] and systems.\n\nThis library is designed with WebAssembly in mind. You can follow instructions on how to use it in your browser applications [here][wnfs-wasm-readme].\n\n## Outline\n\n- [Crates](#crates)\n- [Building the Project](#building-the-project)\n- [Usage](#usage)\n- [Testing the Project](#testing-the-project)\n- [Contributing](#contributing)\n- [Getting Help](#getting-help)\n- [External Resources](#external-resources)\n- [License](#license)\n\n## Crates\n\n- [wnfs](https://github.com/wnfs-wg/rs-wnfs/tree/main/wnfs)\n- [wnfs-common](https://github.com/wnfs-wg/rs-wnfs/tree/main/wnfs-common)\n- [wnfs-hamt](https://github.com/wnfs-wg/rs-wnfs/tree/main/wnfs-hamt)\n- [wnfs-nameaccumulator](https://github.com/wnfs-wg/rs-wnfs/tree/main/wnfs-nameaccumulator)\n- [wnfs-wasm](https://github.com/wnfs-wg/rs-wnfs/tree/main/wnfs-wasm)\n\n## Building the Project\n\n### REQUIREMENTS\n\n- **The Rust Toolchain**\n\n  Follow the instructions [here][rust-toolchain-guide] to install the official Rust toolchain.\n\n- **The WebAssembly Toolchain**\n\n  If you are interested in compiling the project for WebAssembly, you can follow the instructions below.\n\n  \u003cdetails\u003e\n    \u003csummary\u003eRead more\u003c/summary\u003e\n\n  - Install `wasm32-unknown-unknown` target\n\n    ```bash\n    rustup target add wasm32-unknown-unknown\n    ```\n\n  - [rust-analyzer][rust-analyzer-guide] is the go-to IDE tool for Rust and if you have it set up, you may want to set the `rust-analyzer.cargo.target` [setting][vscode-settings] to `wasm32-unknown-unknown`\n\n  - Install wasm-bindgen\n\n    ```bash\n    cargo install wasm-bindgen-cli\n    ```\n\n  - Install [playwright][playwright-guide] binaries\n\n    ```bash\n    npx playwright install\n    ```\n\n  **Architecture-specifics**\n\n  - On ARM-based (M1 family) macOS, you might need to explicitly install the following:\n\n    - Install wasm-bindgen\n\n      ```bash\n      cargo install -f wasm-bindgen-cli\n      ```\n\n    - Install wasm-opt\n\n      ```bash\n      brew install binaryen\n      ```\n\n  - On Arch Linux based distributions, you might need to explicitly install the following:\n\n    - Install wasm-opt\n\n      ```bash\n      sudo pacman -S binaryen\n      ```\n\n  \u003c/details\u003e\n\n- **The _rs-wnfs_ Command**\n\n  You can optionally set up the `rs-wnfs` script.\n\n  \u003cdetails\u003e\n    \u003csummary\u003eRead more\u003c/summary\u003e\n\n  - Install it using the following command:\n\n    ```bash\n    sh ./scripts/rs-wnfs.sh setup\n    ```\n\n  - This lets you run the `rs-wnfs.sh` script as a command.\n\n    ```bash\n    rs-wnfs help\n    ```\n\n  \u003c/details\u003e\n\n### STEPS\n\n- Clone the repository.\n\n  ```bash\n  git clone https://github.com/wnfs-wg/rs-wnfs.git\n  ```\n\n- Change directory\n\n  ```bash\n  cd rs-wnfs\n  ```\n\n- Build the project\n\n  Check [REQUIREMENTS](#requirements) on how to set up the `rs-wnfs` command.\n\n  ```bash\n  scripts/rs-wnfs build\n  ```\n\n- You can also build for specific crates\n\n  ```bash\n  scripts/rs-wnfs build --wasm\n  ```\n\n## Usage\n\nWNFS does not have an opinion on where you want to persist your content or the file tree. Instead, the API takes any object that implements the asynchronous [`BlockStore`][blockstore-trait] trait. The library also avoids including system function calls that could possibly tie it to a set of platforms. Operations like time and random number generation have to be passed in via the API. This allows the library to be used in a wide variety of environments. It particularly makes virtualisation easier.\n\nLet's see an example of working with a public filesystem. We will use the in-memory block store provided by the library.\n\n```rust\nuse anyhow::Result;\nuse chrono::Utc;\nuse wnfs::{\n    common::MemoryBlockStore,\n    public::PublicDirectory\n};\n\n#[async_std::main]\nasync fn main() -\u003e Result\u003c()\u003e {\n    // Create a new public directory.\n    let dir = \u0026mut PublicDirectory::new_rc(Utc::now());\n\n    // Create an in-memory block store.\n    let store = \u0026MemoryBlockStore::default();\n\n    // Add a /pictures/cats subdirectory.\n    dir.mkdir(\u0026[\"pictures\".into(), \"cats\".into()], Utc::now(), store)\n        .await?;\n\n    // Store the the file tree in the in-memory block store.\n    dir.store(store).await?;\n\n    // List all files in /pictures directory.\n    let result = dir.ls(\u0026[\"pictures\".into()], store).await?;\n\n    println!(\"Files in /pictures: {:#?}\", result);\n\n    Ok(())\n}\n```\n\nHere we create a root directory `dir` and subsequently add a `/pictures/cats` subdirectory to it. As mentioned earlier, system-level operations like time are passed in from the API. In this case, we use the `Utc::now()` function from the [chrono][chrono-crate] crate to get the current time.\n\n`PublicDirectory` gets wrapped in `Rc` here because it lets us pass it around without worrying about ownership and lifetimes. Making the Rc `\u0026mut` futher allows us to relinquish ownership to the interior `PublicDirectory` and point to a new one when needed (essentially for every write). This immutable way of handling changes has cool benefits like tracking and rolling back changes. It also makes collaborative editing easier to implement and reason about. You can find more examples in the [`wnfs/examples/`][wnfs-examples] folder.\n\nThat's the public filesystem, the private filesystem, on the other hand, is a bit more involved. The [Hash Array Mapped Trie (HAMT)][hamt-wiki] is where we store the private filesystem tree and some other information related to it. HAMT allows for effective storage and retrieval of encrypted and obfuscated filesystem trees and `PrivateForest` is basically a HAMT that can contain multiple file trees with hash for keys and CIDs for values.\n\n```rust\nuse anyhow::Result;\nuse chrono::Utc;\nuse rand::thread_rng;\nuse wnfs::{\n    common::MemoryBlockStore,\n    private::{\n        PrivateDirectory,\n        forest::{hamt::HamtForest, traits::PrivateForest},\n    }\n};\n\n#[async_std::main]\nasync fn main() -\u003e Result\u003c()\u003e {\n    // Create an in-memory block store.\n    let store = \u0026MemoryBlockStore::default();\n\n    // A random number generator.\n    let rng = \u0026mut thread_rng();\n\n    // Create a private forest.\n    let forest = \u0026mut HamtForest::new_trusted_rc(rng);\n\n    // Create a new private directory.\n    let dir = \u0026mut PrivateDirectory::new_rc(\u0026forest.empty_name(), Utc::now(), rng);\n\n    // Add a file to /pictures/cats directory.\n    dir.mkdir(\n        \u0026[\"pictures\".into(), \"cats\".into()],\n        true,\n        Utc::now(),\n        forest,\n        store,\n        rng,\n    )\n    .await?;\n\n    // Add a file to /pictures/dogs/billie.jpg file.\n    dir.write(\n        \u0026[\"pictures\".into(), \"dogs\".into(), \"billie.jpg\".into()],\n        true,\n        Utc::now(),\n        b\"Hello! This is billie\".to_vec(),\n        forest,\n        store,\n        rng,\n    )\n    .await?;\n\n    // List all files in /pictures directory.\n    let result = dir.ls(\u0026[\"pictures\".into()], true, forest, store).await?;\n\n    println!(\"Files in /pictures: {:#?}\", result);\n\n    Ok(())\n}\n```\n\nThis example introduces a few new concepts. The first is the `HamtForest` which is a HAMT that can contain multiple file trees and implements the `PrivateForest` interface needed for persisting private file systems.\n\nThe second is the `Name` (returned from `forest.empty_name()`) and `NameAccumulator` that lets us identify nodes in the filesystem, and are suitable for offspring proving.\n\nFinally, we have the random number generator, `rng`, that the library uses for generating new keys and other random values needed for the protocol.\n\nCheck the [`wnfs/examples/`][wnfs-examples] folder for more examples.\n\n## Testing the Project\n\n- Run all tests\n\n  ```bash\n  scripts/rs-wnfs test\n  ```\n\n- Run benchmarks\n\n  ```bash\n  scripts/rs-wnfs bench\n  ```\n\n  You can also find a nice graph of the CI benchmarks [here][benchmarks].\n\n## Contributing\n\n### Pre-commit Hook\n\nThis library recommends using [pre-commit][pre-commit-guide] for running pre-commit hooks. Please run this before every commit and/or push.\n\n- Once installed, Run `pre-commit install` to setup the pre-commit hooks locally. This will reduce failed CI builds.\n- If you are doing interim commits locally, and for some reason if you _don't_ want pre-commit hooks to fire, you can run\n  `git commit -a -m \"Your message here\" --no-verify`.\n\n### Conventional Commits\n\nThis project _lightly_ follows the [Conventional Commits convention][commit-spec-site]\nto help explain commit history and tie in with our release process. The full\nspecification can be found [here][commit-spec]. We recommend prefixing your\ncommits with a type of `fix`, `feat`, `docs`, `ci`, `refactor`, etc...,\nstructured like so:\n\n```\n\u003ctype\u003e[optional scope]: \u003cdescription\u003e\n\n[optional body]\n\n[optional footer(s)]\n```\n\n## Getting Help\n\nFor usage questions, usecases, or issues reach out to us in our [Discord webnative-fs channel][webnative-discord].\nWe would be happy to try to answer your question or try opening a new issue on Github.\n\n## License\n\nThis project is licensed under the [Apache License 2.0](https://github.com/wnfs-wg/rs-wnfs/blob/main/LICENSE).\n\n[benchmarks]: https://wnfs-wg.github.io/rs-wnfs/dev/bench/\n[blockstore-trait]: https://github.com/wnfs-wg/rs-wnfs/blob/main/wnfs-common/src/blockstore.rs\n[commit-spec]: https://www.conventionalcommits.org/en/v1.0.0/#specification\n[commit-spec-site]: https://www.conventionalcommits.org/\n[hamt-wiki]: https://en.wikipedia.org/wiki/Hash_array_mapped_trie\n[ipld-spec]: https://ipld.io/\n[npm-ipld-tools]: https://www.npmjs.com/search?q=ipld\n[playwright-guide]: https://playwright.dev/\n[pre-commit-guide]: https://pre-commit.com/\n[rust-analyzer-guide]: https://rust-analyzer.github.io/manual.html#installation\n[rust-toolchain-guide]: https://doc.rust-lang.org/cargo/getting-started/installation.html\n[shared-private-fs-talk]: https://vimeo.com/534517727\n[vscode-settings]: https://code.visualstudio.com/docs/getstarted/settings#_workspace-settings\n[webnative-discord]: https://discord.gg/YbT6x7Wkvk\n[wnfs-examples]: wnfs/examples/\n[wnfs-graph-demo]: https://calm-thin-barista.fission.app\n[wnfs-spec]: https://github.com/wnfs-wg/spec\n[wnfs-wasm-readme]: wnfs-wasm/README.md\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fehsan6sha%2Frs-wnfs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fehsan6sha%2Frs-wnfs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fehsan6sha%2Frs-wnfs/lists"}