Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plan for Wasming WNFS incrementally #371

Open
Tracked by #543
expede opened this issue Apr 5, 2022 · 7 comments
Open
Tracked by #543

Plan for Wasming WNFS incrementally #371

expede opened this issue Apr 5, 2022 · 7 comments
Assignees

Comments

@expede
Copy link
Member

expede commented Apr 5, 2022

A rough plan for how this will break down, and general organizational questions. As an example, I've provided an almost certainly incorrect order of operations below:

Order of Operations

  1. Thin interfaces/abstractions (switching between WNFSv1 and WNFSv2 possible)
  2. Public WNFSv2
  3. Private WNFSv2
  4. Switch default to rs-ucan
  5. Keystore
  6. Blockstore
  7. AWAKE & Linking

Dependencies

Consider breaking out libraries as part of this work

  • wasm-wnfs
  • wasm-ucan
  • wasm-awake
  • wasm-blockstore
  • wasm-keystore
@matheus23
Copy link
Contributor

Sketching out an Interface for wasm-wnfs

Because wasm-wnfs should be invokable from typescript, I'll sketch the interface in typescript:

A first of sketch of the wasm-wnfs core should be just pure functions. No long-lived data structures on the wasm side. If we figure out that this is a bad idea performance-wise, we benchmark the first version and figure out a plan for an interface that allows better optimizations & performance as a second step.

import { CID } from "multiformats"

// e.g. { name: "dag-pb", code: 0x70 } or { name: "raw", code: 0x55 } etc.
interface Codec {
  name: string
  code: number
}

interface BlockStore {
  putBlock(bytes: Uint8Array, codec: Codec): Promise<CID>
  getBlock(cid: CID, signal: AbortSignal): Promise<Uint8Array>
}

export async function nodeLookup(
  fs: CID,
  path: string[],
  { blockStore: BlockStore, signal: AbortSignal }
): Promise<{ remainingPath: string[], entry: Entry }>

type Entry = File | Directory

interface File {
  metadata: Metadata
  content: CID
  previous?: CID
  // ...
}

interface Directory {
  metadata: Metadata
  userland: Record<string, CID>
  previous?: CID
}

I think that single function nodeLookup function is a good first step.
Because it's not a mutation, it doesn't require constructing the right previous link nor does it require figuring out how to write updates to the pretty tree (sorry for these probably unknown terms @appcypher . You can read something about the pretty tree here: https://whitepaper.fission.codes/file-system/partitions/pretty).

@expede
Copy link
Member Author

expede commented Apr 5, 2022

CHANGELOG: Updated the Issue description to reflect the conversation in Talk

@expede
Copy link
Member Author

expede commented Apr 5, 2022

@matheus23 even though I'm not the expert on this exact repo, at a quick glance that looks about right for a high level interface 👍

@appcypher
Copy link
Contributor

Shared this on Discord and thought it is relevant here too.

I started work on the Rust WNFS implementation a few days ago and I've been planning how we can make it work both as a regular library that the Rust ecosystem can leverage, as well as make it a good candidate for compiling to WebAssembly. Rust happens to have one of the best toolchains for compiling to lean WebAssembly code and a great JavaScript-based wrapper tool, so this made my work easier although there are still some issues with the current implementation.

I was able to acheive the reusability goal by:

  • Moving bindgen and wasm-specific code out into a separate project.
  • Avoiding library-specific async features. And if they are really needed, putting them behind a feature flag.
  • Using feature flags to choose between a bindgen-based wasm with dependency on JavaScript and a wasm-only build with imports and exports.
  • A lot of the dependencies used don't need io std stuff.

I was originally of the impression that asynchronous calls would be a pain to implement in wasm, but I was wrong. Given how Rust represents async code in the memory, the rust-wasm team created a wasm-bindgen-futures library that introduces its own async executor. With it, it is possible to call asynchronous JavaScript functions and vice versa. This is going to make our work a lot easier on the async front.

The Rust WNFS library is currently in a very early stage of development and there are a few issues I'm still trying to figure out.

  • Because of the separation of the between Rust-only stuff and wasm-specific code, there is duplication of code.
  • The async code crashes sometimes and I haven't figured out why yet.

@appcypher
Copy link
Contributor

appcypher commented May 9, 2022

@expede What does keystore refer to here?

  1. Keystore
  • wasm-keystore

@appcypher appcypher reopened this May 9, 2022
@expede
Copy link
Member Author

expede commented May 12, 2022

@appcypher the keystore is where we hold symmetric (e.g. AES) keys, skip ratchet material, and other keys that we need to use for decryption. WNFS has a recursive encryption scheme, but you need to get into that first "entry" node.

@expede
Copy link
Member Author

expede commented Jun 3, 2022

Related, but getting split out: https://github.com/fission-suite/internal/issues/15

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants