Toward a Lightning node in the browser

Alex Akselrod
SimpleCoin
Published in
4 min readNov 17, 2020

In recent years, as the Lightning Network has gotten more mature, so has Go’s support for WebAssembly. SimpleCoin started with a mission to take advantage of this progress to enable a new kind of non-custodial Lightning wallet: one where the node runs right in the browser! Today, we’d like to share some of our research and development progress on getting LND, the Lightning Network Daemon, to run in a browser environment.

Storing our files

We started out by deciding on a filesystem abstraction. The Go runtime for WebAssembly expects a NodeJS-compatible filesystem to be available, so we needed a replacement that works in the browser. We chose BrowserFS, which supports multiple back-ends and works in multiple browsers.

BoltDB woes

One of the first obstacles we ran into was the fact that LND uses BoltDB for storing wallet, blockchain, and network graph data locally. BoltDB stores its database as a single file, which is very convenient, but it requires a mechanism called mmap to make it work. Unfortunately, Go, mmap, and WebAssembly don’t go together for now.

Luckily, PingCAP has done much of the work of porting LevelDB to WebAssembly. LevelDB doesn’t require mmap, so it’s a nice fit for our application. We were able to fill in some of the gaps in the LevelDB port to make it work with BrowserFS, and built a database driver for LND to be able to use it.

Talking to LND from JavaScript

A WebAssembly process running in the browser can’t listen on a TCP port directly. Since we’re running in the browser and need to talk to it from JavaScript, we can use the widely-available browser MessageChannel API to call LND’s RPC API. As we work on getting LND running in a separate thread from the UI, the MessageChannel API will allow us to keep the RPC calls working the same way. Our lead front-end engineer, Ilya Fadeev, has spearheaded the work on this as part of building out our wallet front-end.

Talking to the outside world

Our LND node running in the browser needs a source of blockchain data. It also needs to be able to connect to other nodes in the Lightning Network to establish channels for making and receiving payments.

While Chrome has a TCP API, only the WebSocket API is supported across major browsers such as Firefox. We found a Go library which wraps the Javascript WebSocket API in a net.Conn interface and used it to connect outbound to a BIP 157/158-supporting Bitcoin full node and to other Lightning nodes.

Bitcoin Core, forks such as Bitcoin Knots, and Lightning nodes don’t support tunneling their peer-to-peer protocols over WebSockets directly. To allow our browser-based wallets to connect, our lead DevOps engineer, Wesley Charles Blake, set up websockify as a proxy in front of our Bitcoin and Lightning nodes.

Getting the data there

When using a neutrino-based Lightning wallet, verifying the graph can be pretty slow, even though we’ve verified that the chain synchronization works correctly. Currently, for testing the code on testnet and mainnet, we’re pre-loading the chain and graph data the first time we run the wallet. In the future, as we experiment with novel ways to keep the browser node’s graph updated, we’ll revisit and improve this process as well.

Reckless all the way down

We’ve got this working well enough to show off a mainnet demo of a Lightning payment with a node that runs in the browser! However, this is far from ready for any kind of real use.

Screenshot of a successful Lightning payment from a node running in the browser
First mainnet (multihop!) Lightning payment from LND running in WebAssembly in a browser

Go’s WebAssembly support is still experimental. The LevelDB ports are experimental. There are lots of bits that aren’t completely implemented in the LND port, including the JavaScript fixtures required to run it in the browser. All in all, this is still a research and development project, not ready for risking funds on mainnet.

Dreams of the future

These are just some of the things we’ve been building! Mila Krus, our UX director, has been creating a fresh and accessible experience for our web wallet. Ilya has been implementing this vision and integrating it with the WebAssembly LND. Wesley has been building a set of resilient back-end services to support the wallet and related infrastructure. Expect more blog posts soon about the cool, novel stuff they’ve been working on!

A Lightning node running in the browser has some limitations, but also opens up a variety of possibilities for building a new foundation for the decentralized web. We’re not afraid to build on the bleeding edge and explore what’s possible. Will you join us?

--

--