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

Initial Public FS and WebAssembly Work #6

Merged
merged 13 commits into from
Apr 21, 2022
Merged

Conversation

appcypher
Copy link
Member

@appcypher appcypher commented Apr 8, 2022

Summary

This PR implements the following features

  • Initial Public FS implementation that immutable core, filetree merging, etc. will be based on.
  • Rust unit tests
  • A wasm-bindgen interface implementation.

This is the first of a few PRs that will implement the WNFSv2 Public file system.

Test plan (required)

  • Testing the Rust core.

    cargo test -p wnfs
  • Testing the wasm binding.

    cd crates/wasm
    wasm-pack test --chrome
    open http://127.0.0.1:8000

Closing issues

Fixes #4

Ongoing Issues

@appcypher appcypher force-pushed the appcypher/initial-fs-wasm branch 5 times, most recently from a4ec85f to 8e1b90e Compare April 13, 2022 23:57
@appcypher appcypher marked this pull request as ready for review April 14, 2022 12:19
@appcypher appcypher force-pushed the appcypher/initial-fs-wasm branch 7 times, most recently from d4d94ee to c711c58 Compare April 14, 2022 20:20
/// For types that implement getting a block from a CID.
#[async_trait(?Send)]
pub trait BlockStoreLookup {
async fn get_block<'a>(&'a self, cid: &Cid) -> Result<Cow<'a, Vec<u8>>>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may just be me learning rust:
Can we return a slice [u8] here instead of a Vec<u8>?
Why do we return something clone-on-write-able? I was thinking a user of get_block would never want to change the result, so if there's no need for writes, we won't need the Cow.

#[async_trait(?Send)]
pub trait BlockStoreCidLoad {
/// Loads a decodable object from the store with provided CID.
async fn load<T: Decode<C>, C: Codec>(&self, cid: &Cid, decoder: C) -> Result<T>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is cool!
I'm thinking it might be better if this were a normal function instead of a trait though.
Something akin to async fn load<T: Decode<C>, C: Codec, B: BlockStoreLookup>(blockStore: &B, cid: &Cid, decoder: c) -> Result<T>

This way we wouldn't have to re-implement load for all the different structs that implement BlockStore. They all should work the same.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. We don't need to make it a trait here.


/// A directory in a WNFS public file system.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PublicDirectory(Shared<PublicDirectoryInner>);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm highly in favor of going with only Rc<...> in here for now, instead of Rc<RefCell<...>>, and remove mutation from our algorithms currently.
@appcypher and I talked about this, I think mutation is used in the upsert function. It may be slightly more complex to do immutably, but it's definitely possible.
We need the immutability for some of our upcoming algorithms, namely the base-history-on stuff to construct previous links and the file tree merge algorithm. They like to early-return when they detect that the two trees they compare have the same reference. These early returns are important, since we don't want to recurse into the file tree deeply so we don't fetch deeper nodes.


/// Looks up a node by its path name in the current directory.
///
/// TODO(appcypher): What is a valid path segment identifier?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's a great question. I can only link an old internal discussion about this: https://talk.fission.codes/t/valid-paths-in-wnfs/2015

My thinking is, let's assume UTF8. Technically any byte array is valid (even ones that utf8-decoded include a slash), because of how the encoding into IPLD works out.

This is something we'd need to think about a little harder if we want to implement the pretty tree maybe.

Comment on lines +41 to +48
pub struct OpResult<T> {
// The root node. It is the same as the previous root node if the directory has not been diverged.
pub root_node: Shared<PublicNode>,
// Implementation dependent but it usually the last leaf node operated on.
pub result: T,
/// Whether this is a divergence or not.
pub diverged: bool,
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we might be able to go without the OpResult type.

  • get_node returns an OpResult, but that means you get back a PublicNode in root_node and result, where I'd pretty much expect root_node to be the same thing that that's used to call get_node on.
  • read returns an OpResult, but like get_node, it returns back the root_node you originally called read on.
  • write returns the parent of the written node. That result isn't used anywhere at the moment.

diverged may not be needed when stuff is immutable, but I may just not really understand it yet! 😅

Copy link
Member

@matheus23 matheus23 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First end-to-end public filesystem implementation! 🎉

dance

Stephen and I talked about the comments I left above: The crux of it would be a change somewhat deeper down & technically only a refactor, the surface API would stay the same.
So let's capture that refactor (figuring out how/whether we can remove the RefCell, and make all algorithms only make use of mutation locally without needing a refcell and non-recursive) in an issue and we'll tackle that as the next PR. 👍
Technically we can continue poking the wasm blob this generates 😄

@appcypher appcypher merged commit 7a89949 into main Apr 21, 2022
@zeeshanlakhani zeeshanlakhani deleted the appcypher/initial-fs-wasm branch October 19, 2022 19:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Initial IPLD work and Wasm-bindgen Setup
2 participants