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

Run nim-libp2p in browser with e.g. WASM #409

Open
oskarth opened this issue Oct 19, 2020 · 11 comments
Open

Run nim-libp2p in browser with e.g. WASM #409

oskarth opened this issue Oct 19, 2020 · 11 comments

Comments

@oskarth
Copy link
Contributor

oskarth commented Oct 19, 2020

Problem

(This might be the wrong repo for this, not sure).

For Waku v2 to run in browsers we currently have to develop a new (ideally light) client in JS. This leads to duplication of efforts.

It'd be nice to be able to compile nim-libp2p to WASM and have basic transports working. That way it can be used as a kernel, with the JS code being glue code for application developers.

Also see:
https://github.com/vacp2p/waku-web-chat/
#407
#408

Acceptance criteria

Hello world from nim-libp2p in the browser.

@sinkingsugar
Copy link
Contributor

Ideally possible but would require the ARC mode to be working, as the GC is definitely (experience talking) not WASM friendly.

That said I suspect a JS implementation would work better as the backbone would still be JS apis. WASM is mostly meant to compile heavy lifting specific code (say encryption) but when it comes back to use anyway JS calls, directly using JS is likely better, and with libp2p WASM would often call JS/Browser land.

@dryajov
Copy link
Contributor

dryajov commented Oct 21, 2020

Ideally possible but would require the ARC mode to be working, as the GC is definitely (experience talking) not WASM friendly.

Any specific info on what causes the GC issues? It should be possible to build the entire thing to C++ and then to WASM with emscripten for example, which should be a pretty complete execution environment, but YMMV.

That said, since we have a pure JS backed it's probably the easiest route and as @sinkingsugar mentioned, we'd still need to call into JS from WASM for all the networking parts either way.

@sinkingsugar
Copy link
Contributor

Well, first and foremost, WASM is literally not designed for GCs because of the memory model, fragmentation happens almost immediately. There is a work in progress official GC but still in very early stage.
( btw yes I know WASM fairly well, used it in few projects )
So yes while nim compiles fine, you will not get to run anything complex easily and sometimes it's actually not possible due to the program simply not fitting the boundaries WASM imposes ( there are parameters yes but not enough ).
Also nim GC code for wasm is quite experimental on top of that.

@arnetheduck
Copy link
Contributor

@yglukhov has some experience using the GC with wasm - I'm not sure what version and when, but afair it involved calling the gc explicitly at times - might be worth digging around

@dryajov
Copy link
Contributor

dryajov commented Oct 21, 2020

My reasoning was that WASM uses a flat memory model (essentially an array), and it should be possible to map it relatively well to Nim's simplistic GC, but fragmentation is probably the nail in the coffin and requires some address space emulation voodoo. In any case, there is hardly any need for WASM to run libp2p, in fact, for what we need it is probably counterproductive because we'd need to call out to JS for every network interaction, which requires copying to and from the WASM runtime.


Now, in order to make nim-libp2p work in the browser we'd need to:

  • Make sure that it builds with the Js backed (but maybe WASM is still an option worth exploring), which requires
    • A browser capable transport - WebSockets and WebRTC
      • WebSockets only allow you to dial other nodes, there is no way of receiving incoming connections unless using a Relay (see the infrastructure requirements)
      • WebRTC allows true browser to browser dials, but require a third node to negotiate the connection, this requires some transport (HTTP or WebSockets) to perform the initial handshake, so WebSockets is a prerequisite for WebRTC
  • Port all the required crypto to either webcrypto primitives (probably harder) or port the ones we already use to WASM (still some overhead from copying, but I've seen this done and it seems to be even faster than the webcrypto backend, not to mention not as limited)
  • Finish the work that splits out the upgrade flows per transport (in progress)
  • At the infrastructure level, we also need
    • A Circuit Relay to enable seamless interop with other browser and non browser runtimes
    • A Rendezvous to enable service discovery, in particular Circuit Relays. This allows reusing Relays to negotiate WebRTC connections as well.

@sinkingsugar
Copy link
Contributor

@yglukhov has some experience using the GC with wasm - I'm not sure what version and when, but afair it involved calling the gc explicitly at times - might be worth digging around

I built a AI application using nimtorch and WASM for a customer, I think I really know what I am talking about, of course calling full collect every so was very necessary. But in the end it was really a hell of an experience. The final version used gc:regions rather than the regular GC cos the model was too big and would crash when collecting.

@sinkingsugar
Copy link
Contributor

sinkingsugar commented Oct 21, 2020

There https://github.com/sinkingsugar/nimtorch/blob/master/examples/webassembly/xor.nim
Even this sample had to use gc:regions or would fail.
Yeah maybe fiddling with parameters for an indefinite time might make it work for a bit, but doubt it would keep running for very long.

@dryajov
Copy link
Contributor

dryajov commented Oct 21, 2020

I really think we should scope WASM to the crypto primitives, there isn't anything else in nim-libp2p that would benefit from it, specially considering the frequent copies to and from the Js runtime for all the networking calls. The crypto primitives on the other hand would be much harder to port to webcrypto(?) and on top of that will most likely end up being slower than the WASM implementation, and memory is probably already deterministic for most crypto stuff, so maybe we can resort to arc/orc for those already.

@D4nte
Copy link

D4nte commented Mar 4, 2021

@oskarth considering our discussion from yesterday regarding wrapping nim-waku functionalities in WakuJS instead of rewriting them in JS. We agreed that for standard functionalities, a re-write in JS is the most straightforward approach. Using nim code could have some benefits when we start to touch cryptographic functionalities such as spam protection, security and noise related protocol.

Do we know how tightly close with the libp2p layer these functionalities are? Would it be an option to extract those as a lib from waku-nim and have them interact with libp2p-js?
Or are they so close to the libp2p layer that we are sure we'll ultimately need to use nim-libp2p in Waku JS?

e.g., for the spam protection, can it be one layer above the libp2p layer, allowing it to be used with libp2p-js instead of nim-libp2p? I am guessing the boundaries may not be clear at this time.

@oskarth
Copy link
Contributor Author

oskarth commented Mar 5, 2021

Currently, I believe all of these types of modules would interact with nim-waku, above nim-libp2p. E.g. RLN spam protection is wrapping a Rust library with Nim bindings and being imported as a submodule to nim-waku. This is outside of nim-libp2p scope.

@arnetheduck
Copy link
Contributor

RLN spam protection is wrapping a Rust library with Nim bindings and being imported as a submodule to nim-waku.

for RLN in particular, although it would be nice to simple compile the nim+rust version to wasm, probably what makes more sense for a browser is to look for an optimized wasm library for the crypto primitives and take it from there - ie something like https://github.com/iden3/snarkjs

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

No branches or pull requests

5 participants