Electrum

Submarine Swaps ⛓️  ⇄  ⚡

BTC Prague 2026

Presenter Notes

Introduction into the Electrum Swap implementation.

Not just client <-> server, decentralised marketplace on Nostr.

Introduction

Electrum

  • Open-source Bitcoin wallet (MIT), around since 2011
  • Lightning · hardware wallets · multisig · plugin system
  • Desktop, CLI and Android

Felix

  • Contributing to Electrum for ~1.5 years
  • GPG: AA0B C682 4B39 7BBA 9977 6E15 7ED8 D82B 3719 2688

Presenter Notes

  • Around for a long time
  • Many features (Lightning, Plugins, Swaps, Multisig)
  • Focus on resilience (No dependence on Lightning Node, Electrum Server, infrastructure)

Brief personal intro and what I work on @ Electrum.

Submarine Swaps

Atomic, (possibly) trustless exchange between on-chain and Lightning balances.

Submarine

  • Channel rebalancing — e.g. getting inbound liquidity
  • Bridging — Lightning ⇄ on-chain payments
  • Privacy — protection against financial profiling

Throughout this talk: Alice (client) does a reverse swap with Bob (provider).

Presenter Notes

"Trustless" is implementation-dependent — we'll see why.

  • Allow to rebalance existing channels without opening/closing.
  • Common use case is to get inbound liquidity (give example).
  • Can be used to bridge between Lightning and on-chain users (Example).
  • Can be used to improve privacy (give Example, paying Proton).

A reverse swap = Alice sends Lightning and receives on-chain (most common one).

Talk is Electrum focused, some things might work differently elsewhere.

The Marketplace 📈

How it bootstrapped:

  • Started with one Electrum-run server (Nostr + legacy HTTP API)
  • Published operator docs → other operators appeared
  • Gradually raised Electrum's fees above 1%, then shut it down once multiple reliable providers became available

Now:

  • 8–11 active swap servers; lowest sticky fee ~0.39%
  • ~5–20 swaps/day estimated (from publicly visible encrypted RPCs)
  • Daily stats posted by an IRC bot in #electrum on libera.chat
  • Web interface based on Boltz fork (Whales Exchange)

Presenter Notes

  • Started with Boltz like API (actually their code)
  • We built a marketplace
  • Everyone can be an operator
  • Allows market to push the fees down

Submarine Swap Setup

Funding Transaction (Bob)

Funding TX

Claim Transaction (Alice) — or timeout by Bob

Claim TX

Lightning HTLCs (Alice -> Bob)

HTLCS

Presenter Notes

  • where is the bitcoin during the swap?
  • two parties
  • one creates UTXO, other claims UTXO

Submarine Swap Flow

Reverse swap: Alice sends Lightning, receives on-chain.

Submarine swap sequence diagram

Presenter Notes

  • more complete picture (including RPCs)
  • Alice creates Preimage
  • Bob has Lightning HTLCs but cannot redeem them
  • Once Alice claimed the UTXO, Bob will see the preimage and can claim the HTLCs

The Swap Witness Script

 1# Unified P2WSH witness script for all swaps
 2WITNESS_TEMPLATE_SWAP = [
 3    OP_SIZE,                               # --- claim branch ---
 4    OPPushDataGeneric(None),               # preimage length
 5    OP_EQUAL,
 6    OP_IF,                                 
 7    OP_HASH160,
 8    OPPushDataGeneric(lambda x: x == 20),  # payment_hash
 9    OP_EQUALVERIFY,
10    OPPushDataPubkey,                      # claim_pubkey
11    OP_ELSE,                               # --- refund branch ---
12    OP_DROP,
13    OPPushDataGeneric(None),               # locktime
14    OP_CHECKLOCKTIMEVERIFY,
15    OP_DROP,
16    OPPushDataPubkey,                      # refund_pubkey
17    OP_ENDIF,
18    OP_CHECKSIG,
19]

— electrum/submarine_swaps.py

Presenter Notes

Claim branch

  • preimage length
  • preimage hash
  • claim pubkey

Refund branch

  • locktime
  • refund pubkey

Show previous slide with blue address

Defending Against Griefing: Bundled Invoices

Electrum splits the swap into two Lightning invoices:

  1. A small mining-fee prepayment — the provider knows this preimage
  2. The main swap payment — preimage revealed on-chain

The provider settles the prepayment only once all HTLCs for both invoices arrive.

Worst case: the provider steals the prepayment — limited harm and loss of reputation.

Presenter Notes

  • Lightning Loop also has this (No show fee).
  • Boltz had this once (not exposed, web interface), at least in the past
  • Hard to expose in a web interface, user would have to scan/pay two qr codes.
  • small trust in provider (only mining fee)

Privacy: Buying a UTXO

Alice does a reverse swap over Lightning, messaging via Nostr:

  • She receives a UTXO with no link to her personal on-chain history
  • The provider never learns her IP or node id — can't tell who bought it
  • She can spend that UTXO to anyone, unlinkable to her past

glowie meme

Presenter Notes

  • cool feature
  • sending on LN, receiving UTXO
  • no IP (only to Relay), no ID, no correlation

What Is Nostr?

"Notes and Other Stuff Transmitted by Relays"

  • Clients ⇄ relays ⇄ clients over WebSockets
  • Messages are JSON, signed with Schnorr (also used in Taproot)
  • Identities are keypairs — ephemeral & permissionless; content can be encrypted
  • Common message formats are standardized as NIPs

Nostr protocol: clients exchanging messages through relays

Presenter Notes

  • Quick Nostr intro
  • signed messages exchanged over websockets
  • relays are dumb public databases
  • events are sent to multiple relays
  • permissionless!

Electrum Swap Marketplace on Nostr

Discovery: swap servers announce themselves on Nostr

  • NIP-38 status events — replaceable, re-announced regularly
  • Clients rank servers by an included proof-of-work
  • Swap RPCs are encrypted to the server's pubkey, always routed through relays
  • Clients use random, ephemeral identities

Library: electrum-aionostr — asyncio, shares Electrum's dependencies

Presenter Notes

  • server publish NIP-38 events (interval, liquidity)
  • clients can request them
  • also used for RPCs (encrypted)
  • clients use random IDs
  • ephemeral and replaceable events, scalable
  • electrum-aionostr

A Swap Server Announcement

 1{
 2  "pubkey": "ba3aa04a...",          // persistent identity
 3  "created_at": 1779375552,         // re-announced every 10 min
 4  "kind": 30315,                    // NIP-38 status (replaceable)
 5  "content": {
 6    "percentage_fee": 0.39,         // currently symmetric
 7    "mining_fee": 285,              // charged for the funding tx
 8    "min_amount": 20000,
 9    "max_forward_amount": 1200000,  // server receives LN
10    "max_reverse_amount": 8900000,  // server sends LN
11    "pow_nonce": "0x41d00190",      // anti-spam proof-of-work
12    "relays": ["wss://relay.damus.io", "..."]
13  },
14  "sig": "5c26c159..."              // schnorr signature over the id
15}

Presenter Notes

  • this is what providers publish
  • basic proof of work (GUI ranking)
  • relay list (client rebroadcasts)

  • no symmetric fees (future)

Three Ways to Swap (in the UI)

  1. Regular Swap (Android · Desktop · CLI) — pick forward/reverse and do a swap
  2. Send change to Lightning — a normal tx's change funds a swap; the provider sends it over LN → no change UTXO
  3. Submarine Payments — pay a server over LN (reverse swap), then claim the funding UTXO straight to the payee's address

Presenter Notes

  • Swap dialog (Desktop & Android)
  • change to ln
  • submarine payments

Demo Time

Swaps on Mutinynet — live in the GUI.

Swap Dialog

Presenter Notes

Three demos, in order: 1. A regular swap via the Swap Dialog. 1. A Submarine Payment — Lightning → on-chain to an external address. 1. Send change to Lightning — an on-chain tx's change goes out over Lightning.

Pre-flight: Mutinynet wallet funded, Lightning channels open and balanced, a target external address ready. Have a fallback screen recording in case the network misbehaves.

Running a Swap Server 🧑‍💻

Same codebase as the Android & desktop apps — just config vars.

  1. Run Electrum as a daemon on a server
  2. Add funds, open balanced lightning channels
  3. Set the config variable plugins.swapserver.enabled

Potato server

  • Low hardware requirements
  • Can run fully behind Tor
  • Docs available online (see docs.electrum.org)

Presenter Notes

  • you can earn some money
  • play with the tech (its fun)
  • get rid of utxos
  • same codebase, just config

Future Development

Time is the limiting factor — wishlist:

  • Taproot / MuSig2 — signature aggregation, smaller on-chain footprint
  • NIP-44 / Lightning onion messages for RPCs — better metadata privacy
  • Prepayment authentication — to enable rate-limiting spammy clients
  • Asymmetric fees — independent pricing of swap directions
  • Revive the old protocol (no hold/bundled invoices) — easier 3rd-party & web clients

Presenter Notes

  • many things to improve still
  • takes time
  • spec out once stable (NIP)

Asymmetric Fees

Currently swap providers can only configure a single feerate.

  • Inbound liquidity is usually more expensive
  • Having asymmetric fees would allow more granular pricing
  • Would allow providers to rebalance their channels through pricing

Presenter Notes

Taproot / MuSig2

Use a Taproot funding UTXO; the collaborative claim uses MuSig2.

  • Reduced fees
  • Improved privacy

Presenter Notes

Client Authentication through Prepayment

Idea: Make swap requests costly for clients.

  • Client sends a small unsolicited Lightning payment (Keysend, BOLT12 offer)
  • Server requires preimage as authentication token for future swaps
  • Server can blacklist preimage to rate limit

Presenter Notes

Specification

  • Allows other clients to implement the scheme
  • Invites more discussion and contribution

Presenter Notes

Thanks! Let's Talk

Interested in any of these ideas? I'll be around the next days.

⛓️ ⚡   Electrum Submarine Swaps

AA0B C682 4B39 7BBA 9977 6E15 7ED8 D82B 3719 2688

Presenter Notes

Please talk to me if you'd like to discuss any of these points or ideas. Thank you — I hope this was interesting!