rust-libp2p icon indicating copy to clipboard operation
rust-libp2p copied to clipboard

Add an example of rust-libp2p running in the browser

Open tomaka opened this issue 6 years ago • 21 comments

With asmjs and/or wasm.

Is that an objective as well? It should be easy to achieve.

tomaka avatar Nov 01 '17 16:11 tomaka

This is somewhat an objective. You're more experienced with the WASM side of things than I am, but I'd imagine all our generic future-based stuff would work, while tokio/mio/specific transports would not. We would need JS glue for hooking into the event loop, WS, WebRTC transports from there, along with Rust libraries meant to interface with that JS glue.

Datastore could be useful as well.

Plugging that into the light client code would be pretty straightforward then, and we could have a light client running in the chrome extension from that point.

rphmeier avatar Nov 07 '17 15:11 rphmeier

You can run libp2p in the browser today by using the JavaScript implementation https://github.com/libp2p/js-libp2p

You can find an example here https://github.com/libp2p/js-libp2p/tree/master/examples/libp2p-in-the-browser

daviddias avatar Nov 10 '17 17:11 daviddias

It is now possible to open a websocket listener from the browser by compiling for emscripten. The gist here shows how to drive a future to completion using the stdweb crate.

Things still to be done:

  • Get crypto to work. The ring library doesn't compile for emscripten.
  • Add continuous integration. Unfortunately travis is not the most appropriate solution to compile for emscripten, and even if we manage to compile the listener testing it would require a javascript interpreter.

tomaka avatar Jan 16 '18 09:01 tomaka

Add continuous integration. Unfortunately travis is not the most appropriate solution to compile for emscripten, and even if we manage to compile the listener testing it would require a javascript interpreter.

This is done.

Get crypto to work. The ring library doesn't compile for emscripten.

This is not going to happen anytime soon. I think the best solution is to tweak the paritytech/ring repo to use the WebCrypto API when compiling for emscripten.

tomaka avatar Mar 22 '18 10:03 tomaka

Futures supports stdweb (since version 0.2), which in turn supports wasm32-unknown-unknown-targets now, too. So, if we can upgrade futures to 0.2

Regarding

I think the best solution is to tweak the paritytech/ring repo to use the WebCrypto API when compiling for emscripten.

I very much agree with brian smith, that getting WebCrypto into Ring will be a challenge, already because ring is synchronous, while WebCrypto returns promises.

I think the better approach would be to refactor libp2p to use WebCrypto and std_web for wasm-targets, dropping ring altogether in that case. However, that means making a bunch of things async than they are right now.


Edit: that might also turn out to be non-trivial, as WebCrypto doesn't yet support all algorithms, that we need e.g. secp256k1. So I guess for some curves we might be more vulnerable within the wasm-environment :thinking: .

gnunicorn avatar Jul 18 '18 11:07 gnunicorn

So, if we can upgrade futures to 0.2

Nothing in the Rust ecosystem supports futures 0.2, so that's no-no. However it's possible to use futures 0.1 as well. We just need some manual glueing.

tomaka avatar Jul 18 '18 11:07 tomaka

See also https://github.com/paritytech/parity-ethereum/issues/7915

tomaka avatar Jul 18 '18 11:07 tomaka

Once #900 is done, it should be trivial to write an example.

tomaka avatar Feb 21 '19 09:02 tomaka

@tomaka are there any other blockers?

khimaros avatar Jun 28 '19 02:06 khimaros

No, libp2p is running just fine from within a browser, provided you use wasm-pack.

The last thing to do would be add an example that is tested on CI, so that we don't accidentally break it.

tomaka avatar Jun 28 '19 07:06 tomaka

i would love to see an example of this :D

ivoribeiro avatar Jan 31 '20 01:01 ivoribeiro

Hello! I'd like to take up this issue. I haven't thought of any specific example yet (any ideas/suggestions welcome). I'll figure it out in a few days. Thanks.

govardhangdg avatar Feb 29 '20 09:02 govardhangdg

A chat with the recently added Gossipsub protocol? That's what I'll try soon for my project so you'll be saving me some work 😅

olanod avatar Feb 29 '20 13:02 olanod

To give some hints:

  • By design, WebSockets in the browser can only establish outgoing connections, so you will need to run the browser example against a non-desktop example that listens on WebSockets. Also note that your browser might refuse non-secure WebSockets, so be aware of that.
  • Thanks to #1454, you should be able to do libp2p::wasm_ext::websocket_transport() and obtain an implementation of Transport equivalent to what is in libp2p::ws.
  • Only the low-level transport part needs to be customized for the browser/outside the browser. The rest (including secio/noise/mplex/yamux) is totally cross-platform.

tomaka avatar Mar 02 '20 13:03 tomaka

Thanks @tomaka.

@olanod that seems like a good idea. I'll look into it :)

govardhangdg avatar Mar 02 '20 23:03 govardhangdg

@tomaka, what do you mean by "non-desktop" in the previous comment? Do you mean "non-browser", i.e, a node/peer running on a terminal and not in a browser? So, the browser instances(peers running on browsers) should connect to some peer running on terminal (not on browser as browser doesn't allow incoming websocket connections) and supporting ws transport, is what I understood from it.

govardhangdg avatar Mar 03 '20 04:03 govardhangdg

BTW libp2p::wasm_ext::websocket_transport() is not found. I tried to use the latest code (from github) instead of the published crate (0.16.2), but still no luck. Then I tried adding feature "websocket", but I got the error saying that there is no such feature in the rust-libp2p crate.

govardhangdg avatar Mar 03 '20 06:03 govardhangdg

@tomaka I've had a minimum working example of this done a few weeks back. It was based off of the way substrate's browser light node uses the libp2p library. Repo Link. I'd be happy to make a PR if I could get some guidance on how the example should be setup. The linked repo is using vue as the front end but I'd imagine that a plain HTML version would be better for upstream.

dt665m avatar Jun 11 '20 04:06 dt665m

@dt665m I would definitely appreciate a browser example! I think a simple plain HTML example would be good, or maybe using Vue would even be fine, if you just used the UMD build of Vue from a CDN so it doesn't require any Webpack setup or anything. There's a super-remote chance I could help if you needed review or other input. I'm really wanting to understand if it's possible to effectively use Rust and libp2p in the Browser and it looks like the answer is yes!

zicklag avatar Jan 15 '21 04:01 zicklag

After looking around a bit, it looks like you need a signaling server like a webrtc star server to actually find peers and listen on a websocket, because Browsers can't listen on websockets. I'm not exactly sure what that looks like, but it also looks like I can't get rust-libp2p to actually connect to even a plain js-libp2p node running in the browser, which I would imagine would be a first step.

I'm a little confused, but would appreciate help figuring this out if anybody has any ideas. :smiley: I'm wanting to experiment with something like @olanod mentioned: a peer-to-peer chat built on rust-libp2p that can run in the browser.

zicklag avatar Jan 15 '21 18:01 zicklag

@zicklag should be possible by using the websocket server as a relay. I'm not too familiar this is supported in the Rust side, but I'd assume so.

There's a separate issue open regarding webrtc, but websockets should work (although like you mentioned, the browser won't be able to actually listen natively).

MichaelMackus avatar Feb 05 '21 23:02 MichaelMackus

I am closing here in favor of https://github.com/libp2p/rust-libp2p/issues/2617.

mxinden avatar Oct 06 '22 09:10 mxinden