Introducing Phoenix
Tags: Bitcoin, Lightning Network

Today we are releasing Phoenix, a 2nd-generation mobile Lightning Wallet.

Why do you call it a 2nd-generation wallet?

When we first announced Eclair Mobile back in 2017, we chose to make it a standard Bitcoin wallet with opt-in Lightning support. Eclair Mobile has a pretty UI, but the UX still lets you see a lot of the inner workings of Lightning. For example, users see separate on-chain and off-chain balances, have to manage channels, incoming liquidity, and so on.

With Phoenix, we started again from scratch — hence the name. UX is basically that of a good old bitcoin wallet, but with instant and cheap payments.

No more channel management, no more liquidity issues, no more backup headaches! UX improvements are so significant that it deserved to be in a class of its own.

“Same UX as a Bitcoin wallet”. Really?

Let’s review a typical use case for a Bitcoin wallet, before Lightning existed.

Install a new wallet app Receive 0.004 BTC Send 0.001 BTC Receive 0.003 BTC Uninstall & Restore Send the remaining 0.006 BTC and end up with an empty wallet

This is seemingly very simple, and indeed this is trivial with a legacy Bitcoin wallet, but is utterly difficult to achieve with Lightning. Here are all the hurdles to overcome:

Step 1) is easy. Or is it really? On a traditional Bitcoin wallet this is where you would write down your seed. You can’t do that with Lightning because backups need to be updated after each transaction. There are attempts at static backups, but those have edge cases and won’t cover in-flight payments.

Step 2) gets worse. You can’t receive funds over Lightning if you don’t have a channel. But you need bitcoins to open a channel right? So you can’t receive bitcoins if you don’t already have bitcoins. Quite annoying.

Step 3) is straightforward on a standard Bitcoin wallet. Even if the incoming transaction made in 2) isn’t yet confirmed, you can spend it right away and create a chain of unconfirmed transactions. But on Lightning you can’t, because a channel needs to be confirmed to be usable. So if you created a channel in 2), you will have to wait typically 2 or 3 confirmations before you can make a payment.

Step 4): same as 2).

Step 5) at best, if your Lightning wallet supports static backups of some sort, you will be able to close your channels and retrieve your funds on-chain. But it is going to cost you network fees, and you won’t be on Lightning anymore.

Step 6) here the user sends out all her remaining funds in one transaction. Note that, in this particular example, that would be the sum of two UTXOs (0.003 BTC + 0.003 BTC). Let’s suppose that you created two channels in steps 2) and 4), then until very recently you wouldn’t have been able to combine them in a single payment. Another thing: in Lightning, both sides of a channel have to maintain a minimum “reserve” amount, as part of the incentive mechanism. This can quickly turn into an UX nightmare because a) you can’t spend all your funds, and b) the unspendable amount depends on the number of underlying channels. Phew!

The good news is, we solved all those challenges one by one. Here is what the use case looks like, with Phoenix (100% on Lightning!):

Lightning made easy

There is no magic, of course, and achieving this required a combination of new features and trade-offs.

Features

Phoenix is packed with new features. We will detail some of them in other blog posts:

Pay-to-open. Phoenix will automatically create a channel on-the-fly if you don’t have enough inbound liquidity to receive a payment.

Spend-unconfirmed. Also known as turbo channels. Allows you to use channels as soon as they are created, without having to wait for confirmations.

Peer backup. No more headaches with channels backup. Just reinstall the app, enter your 12 words, and your money will be there.

Zero-reserve + AMP. This allows you to spend your money as one single balance, even if internally it is spread over multiple channels.

Trampoline payments. Trustlessly delegate payment route computation, saving you from lengthy routing table sync. There is a privacy gotcha in the current version of Phoenix, detailed below.

Swaps. Send and receive on-chain transactions seamlessly, even if you are on Lightning.

Trade-offs

There are quite a few Lightning wallets out there, and we learnt during the past 12 months that a good number of users are ready to use a hosted wallet, because they feel that’s the only way to have a good UX.

We believe that we can have both: a non-custodial wallet with a good UX. This was our starting point and we didn’t compromise on that. Phoenix, just like Eclair Mobile, is a non-custodial Lightning wallet. It is based on Eclair and runs a real Lightning node under the hood. The keys never leave the wallet and you would still be in full control of your funds if ACINQ disappeared overnight, or even the whole Lightning Network for that matter.

That was the non-negotiable part. Now here are the trade-offs that we made:

Trust trade-offs

Phoenix only connects to ACINQ nodes. This allows us to modify/enrich the Lightning protocol at the immediate peer level, while staying 100% LN compliant at the network level. It also makes it possible to have asymmetrical incentives, sometimes in favour of the user’s node, sometimes in favour of our node. Here are a few examples:

Example #1: A trivial example is the ability to open large channels.

Example #2: Because we trust our ability to detect cheating attempts, we decided to not require a channel reserve from Phoenix users (we still have to maintain one on our side). This is an example of asymmetrical incentives: Phoenix users may be in a situation where they have nothing at stake (so a cheating attempt would cost them nothing), while our node always has something at stake. Having a zero reserve means that you can spend all your balance, and makes multi-parts payments seamless because your total balance is simply the sum of all your funds in all your channels, as you would expect.

Example #3: Because we know that the route to a Phoenix wallet will always go through our node, we can offer additional services, like automatically offer to open a new channel when receiving payments if the user has no channels or not enough inbound liquidity.

Channel funding is trusted, until confirmed , a bit like trusting an unconfirmed incoming transaction on a bitcoin wallet. Note that the way Phoenix works, all channels are always funded by our node, with a non-zero pushed amount, following an inbound layer 1 or layer 2 payment. We could have used a more advanced construct to make the funding tx depend on a payment_preimage , but that would also have required a delay (otherwise we would still be able to double-spend the tx) and would have prevented turbo channels. On the other hand, Phoenix users can’t fund channels themselves, because they don’t have UTXOs, and we wouldn’t trust them to not double spend their channels anyway.

, a bit like trusting an unconfirmed incoming transaction on a bitcoin wallet. Note that the way Phoenix works, all channels are always funded by our node, with a non-zero pushed amount, following an inbound layer 1 or layer 2 payment. We could have used a more advanced construct to make the funding tx depend on a , but that would also have required a delay (otherwise we would still be able to double-spend the tx) and would have prevented turbo channels. On the other hand, Phoenix users can’t fund channels themselves, because they don’t have UTXOs, and we wouldn’t trust them to not double spend their channels anyway. Swaps are trusted (basically we get paid and then we make the swap). Submarine (“trustless”) swaps are a thing, but they are not perfect. First they are not 100% trustless: for a swap-out you still need to trust the swap server with your prepayment. They are also more complex and require two on-chain transactions, making them more expensive. Last but not least, in the swap-out scenario, they require the receiving wallet to understand the swap protocol. You wouldn’t be able to directly send bitcoin from Phoenix to a normal bitcoin wallet.

So, yes there is some level of trust involved, for a limited number of operations, and for a limited, well defined amount of time.Those are trade-offs that we believe are worth making when UX is at stake.

It’s also worth noting that requiring trust, even for limited operations, is never the best option for us. It’s a liability, and if we find ways to reduce the level of trust we will do it.

Privacy trade-offs

Information about payments (destination, amount) currently leaks to our node. To put it another way, Phoenix in its current version offers no privacy benefit over a traditional hosted wallet. Why is that? Phoenix relies on trampoline to outsource the computation of payment routes and the specification of this new tech is still a work-in-progress. As a result our node is the only one currently supporting trampoline, hence the privacy issue.

That’s obviously not satisfactory, and it only makes sense as a temporary measure, the goal being to have a multitude of trampoline nodes (*), which would result in a similar (actually, arguably better) level of privacy as non-trampoline LN payments. Why would people run trampoline nodes you ask? Because it allows them to earn more fees. Trampoline creates a new market for payment route calculation, but that’s a topic for another day.

In the meantime, we plan to have Phoenix always connect over Tor (*), à la Blockstream Green, which would significantly alleviate the issue.

(*) Which is actually another trade-off in itself, depending on where you live.

When iOS?

For now Phoenix is Android-only, but we are working on an iOS version for 2020.

What about Eclair Mobile?

Phoenix isn’t a replacement for Eclair Mobile, it operates with different assumptions and targets different users. We intend to keep supporting Eclair Mobile for the foreseeable future.