signalapp / libsignal

Home to the Signal Protocol as well as other cryptographic primitives which make Signal possible.
GNU Affero General Public License v3.0
3.06k stars 362 forks source link

WASM Bridge / Build for libsignal-client #350

Closed ThisIsMissEm closed 2 years ago

ThisIsMissEm commented 2 years ago

Hi! It's really great to see libsignal has been rewritten in Rust, and this opens up an interesting possibility: libsignal-client bindings for the web via wasm

Given a few days looking through the codebase, I think it should be possible to get libsignal-client compiling to wasm, but unfortunately my rust knowledge is barely there, and I don't really understand the structure of all the macros used in this codebase.

I've pushed some early work on this here, but I'm having difficulty getting bridge_fn and similar macros working (I think I mostly lack information as to how to debug macros and see the code that they'd generate).

Is delivering libsignal-client via WASM of interest to Signal?

https://github.com/signalapp/libsignal-client/compare/master...unobvious-technology:wasm-bridge

jrose-signal commented 2 years ago

Our policy still matches what's in the README: Contributions that will not be used directly by one of Signal's official client apps may still be considered, but only if they do not pose an undue maintenance burden or conflict with the goals of the project. This is at least partly an issue of developer bandwidth at Signal! I think supporting a full wasm bridge would qualify as too much of a maintenance burden to land in the main repository.

That said, we're happy to take contributions that make it easier to use libsignal-client with other codebases, including some sort of wasm bridge.


Using libsignal-client from wasm apps could mean a few things:

  1. Making sure the main libsignal-protocol crate compiles successfully for a wasm target, then using it from other Rust code that you also compile to wasm. This is easiest (it probably nearly works already) but it doesn't sound like that's your goal here.

  2. Writing a manual wasm-friendly Rust wrapper library for the operations you care about, depending again on libsignal-protocol rather than libsignal-bridge. Basically the same as the previous one, except instead of making the entire app in Rust you're only making a library.

  3. Using#[bridge_fn]* to autogenerate an API for wasm the same way we do for the three existing platforms. This has the obvious benefit that new bridged API will just appear when you update, but as you've seen there's an awful lot to #[bridge_fn]. cargo-expand is the tool you're looking for to expand macros, though.

  4. Using the existing C API (libsignal-ffi) as a clunky wasm-compatible interface. I'm not really sure I recommend this because we don't treat the C API as a product, just a means to an end for the Swift API, and so there's been no effort put into making it a proper friendly abstraction. But it's there and depending on your goals it could be useful.

"Depending on your goals" is really an operative phrase here. (2) is probably the target I'd suggest aiming for, since it means you get control over how libsignal-client's operations are translated to wasm, and that becomes insulation from changes to some extent. #[bridge_fn] may have been designed to be generic over multiple language bridges, but it's also not API in any sense, and as an implementation detail a change on our end could easily knock down an entire external house of cards.

Since we're not planning to make large changes directly in the main repo at this time, I'm going to close this issue, but please feel free to ask further questions at https://community.signalusers.org/c/development/6 (and tag me in your post to make sure I see it).

* a towering abstraction that I really need to break back down into something approachable, but that's a separate issue!

ThisIsMissEm commented 2 years ago

Okay, so, I think I'm actually making forwards progress on this, as the rustwasm / wasm_bindgen projects can mostly automatically generate things correctly, there's just a little marshalling with serdes needed, I think.

For example, I've already managed to get it generating this:

Screen Shot 2021-09-01 at 11 49 48 pm

I guess I could manually create a wrapper package, but if it's minimal code to actually support wasm as a target within the core, then I'd likely be happy to maintain that aspect of the project? (My goal is to use libsignal as an underlying messaging layer for an application my company is developing)

jrose-signal commented 2 years ago

I appreciate the offer! But we're not really taking maintainers outside of Signal at this time, and we wouldn't, for example, want a feature for Signal's official clients blocked because it isn't building for wasm. You could do this by maintaining a downstream fork, though, like the Whisperfish project did before they got their work upstreamed. Then you deal with new features and changes on your schedule.