Lntenna-Python: Part 1 – Submarine Swaps Over Mesh
The goTenna mesh networking platform already allows goTenna Mesh devices connected to it to share GPS locations and text messages with other users within the mesh. And, if one or more of those mesh users has an internet connection, then they can act as a gateway and pass messages to and from the mesh network, to anyone in the world.
goTenna has released a software development kit which allows developers to program their own features on top of the device. One notable innovation in relation to bitcoin payments, the txTenna project allows you to run a full bitcoin node, with send and receive capabilities, from a device with no direct internet connection. This project utilised the Blockstream Satellite which broadcasts the bitcoin blockchain from a satellite.
We wanted to expand on this idea, of censorship-resistant, private and secure payments and message-sending capability over the goTenna mesh network. Because broadcasting of the bitcoin blockchain via satellite does not consume all the available bandwidth, Blockstream has also enabled arbitrary message transmissions, also broadcast over the same frequencies and able to be received and interpreted by those using their satellite downlink.
These transmissions however must be paid for via a layer 2 bitcoin technology using a type of payment channel, called Lightning. The aim of this project is to enable lightning payments to be made, from an off-grid goTenna user, via the goTenna mesh network, in order to enable messages to be sent and broadcast across the globe, via the Blockstream Satellite system.
Relatively speaking, lightning transactions are somewhat more complicated than bitcoin transactions to broadcast from an off-grid device, because each transaction is an interactive process between sender and receiver, requiring a number of back-and-forth negotiations in order to update the state (balance) of the lightning payment channel. Conversely with on-chain bitcoin, you can passively construct the transaction on your own offline, and it is then simply a matter of getting the transaction data uploaded to the bitcoin network — no negotiation with the recipient is required at any stage.
As a result of this additional complexity, we decided to split the project into two phases:
- Enable the basic functionality we wanted to achieve: sending and paying for Blockstream Satellite messages from an off-grid node in a trustless manner.
- Physically routing the lightning channel update messages over the goTenna mesh network in order to pay the message invoice directly ourselves.
Approach #1 — Sending and paying for a Blockstream Satellite message using lighting from an off-grid device over goTenna mesh network
To complete this first stage of the project, we are going to need a way to have someone else pay for the lightning invoice on our behalf in a trustless manner. Luckily this was already invented and implemented by Alex Bosworth of Lightning Labs (shout-out also to Olaoluwa Osuntokun ‘roasbeef’ for simultaneous invention). It is called a Submarine Swap.
The short explanation of a submarine swap revolves around the type of bitcoin contracts that lightning payments themselves use, Hash Time Locked Contracts (HTLCs). These contracts allow you to generate a receiving bitcoin address, whos UTXOs (balance) can only be spent by satisfying the contract. In this case, the recipient of the payment must reveal a secret to the sender, the so-called ‘preimage’ of the hash, which will hash to a certain value: the hash as determined by the ‘hash’ (lock) part of the contract. This secret also acts as a proof of payment, in other words it’s effectively a cryptographic receipt. If the secret is not revealed by the recipient before the time lock expires, then the recipient forfeits the ability to claim the coins, returning them to the sender.
In the case of the on-chain to off-chain Submarine Swap, two dependent HTLC transactions will be set up: one on-chain bitcoin HTLC in addition to the lightning network’s off-chain HTLC. In this way, there can be a chain of payments constructed, from on-chain bitcoin to off-chain lightning, which both rely on the secret revealed by the recipient of the lightning invoice in order to ‘claim’ (really spend) the funds sent to the on-chain bitcoin address.
The basic mechanism is as follows:
The user contacts the Blockstream Satellite service with a message they want to send and the bid (fee) they are willing to pay. If they accept the fee, the Blockstream service will respond with a lightning invoice (amongst other order details) which needs to be paid before a specified expiry time. Successful payment of this invoice will result in the message being broadcast via the Satellite system.
With this invoice in hand, the user then contacts a Submarine Swap service provider, such as submarineswaps.org, and presents them the lightning invoice they would like to have fulfilled. The swap provider will respond with an order quote of their own, including 3 main parts:
- a new amount payable in on-chain bitcoin, this time including their service fee
- an on-chain bitcoin Pay To Script Hash (P2SH) address to which payment should be made
- a redeem script which sets out the conditions under which the bitcoins sent to the bitcoin address from 2) can be spent
1 Note there is an alternative spending mechanism from the contract which relies on Time Locks rather than revealing the preimage, but we do not cover this here.
The user can decode this redeem script to check the spending conditions match those they are expecting: i) that the swap provider will need to provide their key and ii) additionally present a secret that will hash to the correct value (the payment hash taken from the lightning invoice) — this secret will be the payment preimage provided to the swap server from Blockstream Satellite service upon paying the lightning invoice.
The redeem script can also be hashed, RIPEMD160 (SHA256(redeem_scipt)), and then encoded using bitcoin’s base58check encoding. The resultant bitcoin address should match the Pay To Script Hash (P2SH) address provided to us as the on-chain bitcoin payment address from the swap server. This means the user can be sure that the swap provider must pay the lightning invoice in order to spend the funds sent to the on-chain address — trustlessness is maintained.
With those checks performed, the submarine swap is ready to be performed.
Once the user makes the on-chain bitcoin payment to the swap provider’s P2SH bitcoin address, the swap provider will attempt to fulfill the lightning invoice. If the swap provider is successful, they will be provided with the payment secret (preimage) to the Blockstream Satellite lightning invoice, as proof of payment. Once they have that preimage, the swap provider can use it to satisfy the on-chain bitcoin redeem script conditions and claim the on-chain bitcoin funds sent to them by the user, completing the process.
Optimising for mesh networks
Whilst the above method is operationally sound, it is not optimised for usage over mesh networks in a number of ways. Generally, the two biggest limitations when it comes to mesh network devices are bandwidth and (battery) power consumption.
To combat these pressure points, goTenna mesh network has a cap on (text) message size of ~230 Bytes. Sending an API request to Blockstream Satellite service with a 13 Byte message (“Hello, World!”) takes approximately 85 bytes, which can fit inside 1 text style message. The response however contains ~1000 Bytes, which would need to be split between 5 messages! Next we would repeat the same for the Submarine Swap quotation which responds with only slightly less data, approximately 4 messages worth. Ideally we need to outsource this job and get these messages off our mesh network.
The Lntenna system has been designed to work around a ‘client’/’server’ model, where the server has both an internet and mesh network connection, and the client has only a mesh network and Blockstream Satellite connection.
In this way, we can use specially formatted Lntenna messages between the client and server to transmit only the minimum required data via the mesh network. The reduction that we see is that we can reduce total mesh network message count from approximately 13 messages, to 6 under ideal conditions, a saving of > 50%.
The downsides of the model used in approach #1 are primarily privacy-related: the server will be able to see the message contents, if it is not end-to-end encrypted. It will also be able to see the bitcoin addresses and payments associated with the submarine swap and link those to your (ephemeral) goTenna ID, (GID). Realistically, some of these privacy implications will also be present in approach #2 too, because we will also be relying on a gateway node to be returning to us the result of the Blockstream Satellite quote, specifically the lightning invoice. With no on-chain bitcoin payments being made in the second approach, however, the superior privacy of lightning onion routing will afford us some extra privacy protection.
In absence of Blockstream operating their Satellite API as a Tor hidden service, and goTenna enabling onion routing across their mesh networks, this small potential privacy leak will be difficult to overcome.
There are other advantages to the Lntenna service in addition to the space and power consumption benefits. When run on a server machine, it completely automates requesting and relaying of responses to and from the Blockstream Satellite and Submarine Swap providers. It also automatically relays bitcoin transactions to the bitcoin network; if bitcoind is detected as running on the server machine, it will use this to upload directly into the P2P network, otherwise it will use the ’broadcast tx’ API provided by submarine swaps service. This also has the nice side-effect that the server machine can perform all these bitcoin functions for the mesh network user, without requiring its own instance of bitcoind or copy of the blockchain.
On the client side, the Lntenna service also automates decoding of the lightning invoices and the swap bitcoin redeem scripts, performing the verification of the relevant parts to ensure that the entire process is performed in a trustless manner. The client part of the software is packaged as a convenient Command Line Interface tool, which makes sending a satellite message as easy as cloning the github repository, installing the dependencies and running the CLI tool, and then using a single command: ‘send_sat_msg’.
Finally, the Lntenna service stores all the data it sends and receives in a simple sqlite database which not only further minimises data transmitted via the mesh network (orders are referred to using an 8 character UUID after initial request), but also allows users to easily look up order details and, in the case of the failed submarine swap, retrieve any redeem scripts and refund addresses they forgot to write down during the sending process, enabling them to claim their refund from the swap provider.
Further optimisations of this approach
There are still some further optimisations of this approach available which could be worked on if desired. Firstly, the lightning invoice returned by Blockstream’s Satellite API includes some tagged fields, specifically the ‘r’ routing/hop-hint fields, which could be stripped from the invoice before transmission across the mesh network to the off-grid client. This would very likely reduce the ‘Lntenna satellite response’ from 3 messages down to 2 as the third message in this sequence is often very small.
Additionally, the Lntenna message serialisation is quite basic: create the appropriate dictionary, dump it to json encoding and transmit it using the SDK’s TextPayload format where it can be decoded and interpreted at the other end. Using the CustomPayload message format, in conjunction with using a specified message header and body format we would likely be able to save some significant number of bytes from each Lntenna message sequence, possibly as much as a 30% size reduction.
The project is available via github at https://github.com/willcl-ark/lntenna-python.
The README.md from the repository also includes more technical details of how to setup and use the program.
If you have any more questions about the project or issues using it, please feel free to leave an issue on the GitHub repository, or contact me on Twitter @willcl_ark, or email to [email protected]