Lightning Optimizing Opening Server

Overview

Lightning Optimizing Opening Server

(loptoš ~ naughty boy/brat/hooligan/..., not to be confused with lopta == ball)

WARNING: ULTRA-EXPERIMENTAL SOFTWARE!!!

This project is very early and lacks basic checks (that means it's NOT fully BIP78-compliant)! For the love of god, do NOT use it on mainnet just yet! If you don't want to wait long, help with reviews and PRs.

About

This server optimizes your channel opening from a remote wallet which supports PayJoin. It enables you to open one or more channels from remote LND with empty wallet using sats in PayJoin-compliant wallet. This way you save one chain transaction when opening from Wasabi, Blue Wallet, BTCPayServer (currently buggy), or other PayJoin-supporting wallet. It's basically a user-friendly way to do PSBT funding flow.

And yes, in the future you could give the URI/QR code to someone else, so you receive PayJoin transaction and simultaneously open Lightning channel with received money.

Expected fee savings

The classic scenario of sending to LND wallet and then opening a channel involves two transactions. With PayJoin it involves just one transaction, saving 106 vB (68 vB input + 22 vB script pubkey + 8 vB output amount + 4 vB version + 4vB timelock) Sending to a node and then opening 10 channels can turn 11 transactions into one, saving 1060 vB. Same if someone else pays you and you already decided to use the received money to open channel(s). You will also save shitton of time not having to wait for confirmations. (There's --spend-unconfirmed, but maybe not a good idea for long chains?)

Expected privacy implications

If you open a channel with ususal LN wallet, it's pretty much certain that the change belongs to the funder. This tool makes it uncertain because it could've been a payer. This tool may produce two changes - it's still unclear whether both or only one belongs to the funder and it may be hard to find which one. (But there's a good chance it'll be revealed eventually.)

Just as with any other PayJoin, it's unclear whether all inputs belong to the funder or some of them don't.

Sadly, I don't think the payer can safely open a channel from change(s) but I have some ideas how it could be achieved in the future. If the channels were truly private it'd make analysis even more confusing (incorrectly assume it's one node).

Post-Taproot-LN it will be impossible to distinguish CoinJoin from batch open of several same-sized private channels. Actually, CoinJoin and batch opening of several same-sized private channels could be one transaction. Good luck analyzing that!

UX implications

All this is possible without loptos by manually exchanging PSBTs. BIP78 just turns that tedious back and forth into scanning/clicking one link followed by confirmation in the wallet. In other words, your grandmother will be able to somewhat privately open a bunch of channels for you, if she has a BIP78-capable wallet.

Limitations and future plans

  • MOST LIKELY UNSAFE does not implement required BIP78 checks
  • Only works with a forked LND - there's a PR against LND, should land in 0.14.
  • Funds in LND or other wallet are not used, so it's not true PayJoin, just abuses the protocol to coordinate PSBT.
  • Unpolished UI
  • No way to inteligently manipulate the amount
  • No discount possible
  • Invalid request can kill whole server
  • .unwraps()s EVERYWHERE!
  • I swear I knew about a few more but can't remember right now :D

Usage

  1. You need a recent version of Rust to compile this.
  2. You need to clone the forked LND: git clone -b awesome-lnd-preview https://github.com/Kixunil/lnd/
  3. LND_REPO_DIR=path/to/forked/lnd/ cargo build
  4. Build forked LND
  5. Deploy forked LND (replacing binary in deployment followed by restart works)
  6. Setup reverse HTTP proxy with HTTPS forwarding to some port - e.g. 3000. You can do this in a few lines using selfhost in Cryptoanarchy Debian Repository.
  7. Connect to the peer using lncli connect ...
  8. ./target/debug/loptos HTTP_BIND_PORT https://LND_GRPC_ADDRESS /path/to/cert/file /path/to/admin.macaroon FEE_RATE_SAT_PER_VB DEST_NODE_ID AMOUNS_IN_SATS [DEST_NODE_ID AMOUNS_IN_SATS ...] [CHAIN_WALLET_AMOUNT_SATS]
  9. Copy BIP21 from command line output and paste it into one of the supported wallets
  10. Confirm the transaction and pray it works

Note: if CHAIN_WALLET_AMOUNT_SATS is present another output will be added to send the amount to the internal wallet. This may be required in case the wallet is empty as in such case LND can not reserve sats for anchor commitments. However, to truly work, you need another LND fix (merge with the other branch).

License

The license is MIT, with one restriction and one warning:

You are forbidden from preventing people from distributing, analyzing or modifying your source code or binaries they unless they specifically signed a contract with you in which they committed to not do so.

I will be maximally helpful towards your victims suing you if you ever market, vendor or distribute this software in exchange for payment or free of charge in a way that could make it look like a reliable or tested product unless you demonstrate serious work done reviewing and improving the code before doing so. Such must be done by people with good knowledge of Rust, cryptography, Bitcoin, network protocols and security.

Comments
  • Automate lnd on-chain allowence to be sufficient for anchor closing

    Automate lnd on-chain allowence to be sufficient for anchor closing

    By

    Note: if CHAIN_WALLET_AMOUNT_SATS is present another output will be added to send the amount to the internal wallet. This may be required in case the wallet is empty as in such case LND can not reserve sats for anchor commitments. However, to truly work, you need LND 0.14.2.

    I thought LND 14.2 would be able to open a channel without setting CHAIN_WALLET_AMOUNT_SATS. What am I missing? Is there some setting to allow 0 internal wallet balance opens? Is that behavior even desirable or is the on-chain utxo better?

    Running LND 14.2 (and 14.0, 14.3, 15.0) from lightning polar. Loptos works like a charm with CHAIN_WALLET_AMOUNT_SATS set sufficiently high.

    opened by DanGould 3
  • GetInfo call returns:

    GetInfo call returns: "unmarshal v1: cannot parse field name"

    Using lnd version: 0.14.2-beta commit=v0.14.2-beta Calling getInfo() returns thread 'main' panicked at 'failed to get info: Status { code: Unknown, message: "unmarshal v1: cannot parse field name", metadata: MetadataMap { headers: {"content-type": "application/grpc"} }, source: None }'

    Any help would be appreciated. Thank you

    opened by 0xBEEFCAF3 3
  • Spooky UI with QR codes

    Spooky UI with QR codes

    Builds on top of https://github.com/chaincase-app/nolooking/pull/30 Squashed from original PR: https://github.com/DanGould/loin/pull/1

    "/pj/schedule" creates a qr code in qr_codes, as <address>.png which is retrieved on the website and shown.

    Not sure if we can do the styled QR code as easily as we could with the other library, we can try some CSS

    image

    opened by nickfarrow 2
  • Update `configure_me_codegen`

    Update `configure_me_codegen`

    The new version improves developer error reporting and reduces warnings in the generated code.

    Cc @DanGould you may want to import this change into your fork. build/test/check with --features=configure_me_codegen/spanned during development to get nice error messages in case of malformed configuration specification.

    enhancement 
    opened by Kixunil 0
  • Cargo fmt and other misc updates

    Cargo fmt and other misc updates

    Got a working example using Wasabi. In the process of getting everything set up, I updated some docs, updated some dependency versions, gitignore, and setup a template config file. Hope others will find this useful

    opened by 0xBEEFCAF3 0
  • Document & bolster calculate_fees

    Document & bolster calculate_fees

    calculate fees seems to work for a subset of possible transaction creations. What do the magic numbers mean? I'd like to add the ability to batch another arbitrary output. Nolooking also failed to meet min relayfee in an off by one error when sending from sparrow (https://github.com/chaincase-app/nolooking/issues/34)

    https://github.com/Kixunil/loptos/blob/4390bb008bbd67b4428bbd46b6fe11dc109c4489/src/main.rs#L187-L195

    bug 
    opened by DanGould 6
  • Taproot Stonewall opening

    Taproot Stonewall opening

    With Taproot we can turn PayJoin-based opening into Stonewall-like transaction:

    • Let the desired channel size be between min and max
    • If the original transaction has a single change of change_value which is between min and max and the wallet already has reserve for anchors:
      • Add our UTXO(s) such that (paid_amount + added_utxos_value - change_value) / 2 is between min and max
      • Create three channels A, B, C; A, B having value (paid_amount + added_utxos_value - change_value) / 2, C with change_value; fourth output is the original change
    • If change_value is out of range or (the wallet doesn't have reserve and change_value is larger or equal to required reserve)
      • Consider doing the same as above but instead of channel C create a non-channel UTXO
      • C has same value as it would following algorithm above
    • If original transaction has no change
      • For payment values between up to 4*max open four channels simulating Stonewall (add our inputs if needed)
      • For payment values above 4*max open two channels with max value and split the rest into two UTXOs. This is a bit of a footgun, those UTXOs should not be joined.
    • If the original transaction has two changes of equal value
      • Split the payment into two channels, add our inputs if required to meet min requirement
    • If the original transaction has two changes of unequal value
      • Can we find UTXO(s) such that sum of the changes equals payment_value + added_utxo_value?
      • If yes do it and create two channels with values equal to change values
    • If the transaction has two equal values x and one unequal value y
      • Can we open exactly one channel with the value y?
      • If not, can we open one or more channels of value x? (Looks like Wasabi CoinJoin, consider adding an output faking fee.)
    • If the transaction has multiple outputs, some of them being equal to x
      • Same as above - last option
    • If the transaction has a bunch of outputs none of them being equal
      • Probably not worth it trying to look like CJ. Try looking like an exchange withdraw instead - add outputs randomly.
    • Failing to find suitable UTXOs
      • Consider creating two channels of the same value
      • Consider keeping reserve of same value as a single opened channel
    • Failing steps above continue with the usual (current) flow which still has some privacy

    Plus have some tool that simulates this for direct open from LND wallet. Note that not all edge cases are covered by the above

    Each case should make sure there are at least two inputs. This trick assumes at most two channels will be announced, ideally none. Chain analysis still doesn't know whether any of the unannounced UTXOs is change or private channel. Shitty chain analysis that doesn't listen to LN gossip is confused more than those that do. At most two channels are with the same node (non-strict-forwarding public-private trick.)

    Some of the tricks may be useful without Taproot (CoinJoin-like opening).

    Examples:

    • 1-2M sats requested size; 1.5M change, 5M payment, original TX has multiple inputs => one channel 1.5M, two 1.75M channels, 1.5M change
    • 1-2M sats requested size; 1.5M change, 5M payment, original TX has a single input, we have 0.5M output => one channel 1.5M, two 2M channels, 1.5M change
    enhancement 
    opened by Kixunil 0
  • Fallback on payjjoining money to wallet if one open fails

    Fallback on payjjoining money to wallet if one open fails

    Currently if any LND call fails we just blow up the entire thing. It'd be nicer to attempt to continue skipping the failed channel and if no more channles are scheduled then continue with just ordinary PayJoin.

    enhancement 
    opened by Kixunil 0
  • Use rust-bitcoin feature instead of base64 dep

    Use rust-bitcoin feature instead of base64 dep

    https://github.com/Kixunil/loptos/blob/965aeda80a0e81b3250585020608e2e9ab533542/Cargo.toml#L17

    rust-bitcoin has feature base64 adding the capability to create a PSBT from a base64 string and viceversa

    opened by RCasatta 5
Owner
Martin Habovštiak
Beside programming, I'm interested in security, cryptography, Bitcoin and freedom.
Martin Habovštiak
Core library for Lightning Network peer-to-peer nostr platform

Mostro server This document explains how Mostro works. Overview Due to the growing need to be able to operate with Bitcoin without giving up personal

Mostro 16 Jan 4, 2023
A Lightning-Fast DNS Resolver written in Rust 🦀

dnsresolver A Lightning-Fast DNS Resolver Table of Contents Installation Usage Basic Usage Resolving Hosts with Ports Virtual Host Enumeration Using U

zoidsec 47 Nov 8, 2023
axum-server is a hyper server implementation designed to be used with axum framework.

axum-server axum-server is a hyper server implementation designed to be used with axum framework. Features Conveniently bind to any number of addresse

null 79 Jan 4, 2023
Jex Compiler Server - Server that runs Jex code

Server that compiles and runs Jex code.

furetur 3 Nov 18, 2021
Dav-server-rs - Rust WebDAV server library. A fork of the webdav-handler crate.

dav-server-rs A fork of the webdav-handler-rs project. Generic async HTTP/Webdav handler Webdav (RFC4918) is defined as HTTP (GET/HEAD/PUT/DELETE) plu

messense 30 Dec 29, 2022
A simple web server(and library) to display server stats over HTTP and Websockets/SSE or stream it to other systems.

x-server-stats A simple web server(and library) to display server stats over HTTP and Websockets/SSE or stream it to other systems. x-server(in x-serv

Pratyaksh 11 Oct 17, 2022
DNS Server written in Rust for fun, see https://dev.to/xfbs/writing-a-dns-server-in-rust-1gpn

DNS Fun Ever wondered how you can write a DNS server in Rust? No? Well, too bad, I'm telling you anyways. But don't worry, this is going to be a fun o

Patrick Elsen 26 Jan 13, 2023
QUIC proxy that allows to use QUIC to connect to an SSH server without needing to patch the client or the server.

quicssh-rs ?? quicssh-rs is a QUIC proxy that allows to use QUIC to connect to an SSH server without needing to patch the client or the server. quicss

Jun Ouyang 18 May 5, 2023
A telnet chat server written in Rust, running on Lunatic.

Lunatic.chat A telnet chat server written in Rust, running on Lunatic. If you just would like to try it out, join the hosted version with: # US server

Lunatic 101 Jan 2, 2023
server security proxy write by Rust

server-security-proxy server security proxy write by Rust how to use config toml file

baoyachi. Aka Rust Hairy crabs 3 May 24, 2021
Imagine your SSH server only listens on an IPv6 address, and where the last 6 digits are changing every 30 seconds as a TOTP code...

tosh Imagine your SSH server only listens on an IPv6 address, and where the last 6 digits are changing every 30 seconds as a TOTP code... Inspired fro

Mark Vainomaa 409 Oct 23, 2022
A working demo of RustDesk server implementation

A working demo of RustDesk server implementation This is a super simple working demo implementation with only one relay connection allowed, without NA

RustDesk 461 Jan 1, 2023
A Matrix Server Stats bot

A bot running trough the matrix network to find all rooms.

Marcel 14 Dec 8, 2021
A standalone libp2p rendezvous server binary.

Standalone Rendezvous Server A standalone libp2p rendezvous server binary. Usage Run the rendezvous_server: rendezvous_server --secret-file <PATH-TO-S

COMIT 15 Jul 20, 2022
pam-send-slack-message is a program that publishes messages on slack when a linux server is accessed through ssh.

pam-send-slack-message pam-send-slack-message is a program that publishes messages on slack when the linux server is accessed through ssh. Installatio

Iuri Diniz 2 Aug 17, 2022
A simple tcp server that written in rustlang

rust_tcp A simple tcp server that written in rustlang How to build In the root dir cargo run Then you can do a test by using telnet as a client telne

null 1 Oct 25, 2021
PubSubRT - an industrial pub/sub server

PubSubRT - an industrial real-time pub/sub server What is PSRT PSRT is a pub/sub real-time telemetry protocol, optimized for industrial needs: providi

Altertech 87 Jan 2, 2023
Simple project to test grpc between ruby (client) and rust (server)

grpc-example Simple project to test grpc between ruby (client) and rust (server). Usage To simplify a lot this project uses docker and docker compose

Bruno Arueira 2 Oct 14, 2021
Proxy sentry request to a sentry server using a tunnel/proxy endpoint

Sentry Tunnel This is a proxy that forwards tunneled sentry requests to the real sentry server. The implementation is based on the explanation provide

Paul FLORENCE 14 Dec 20, 2022