Skip to content

Instantly share code, notes, and snippets.

@lukechilds
Last active December 2, 2024 22:19
Show Gist options
  • Save lukechilds/307341239beac72c9d8cfe3198f9bfff to your computer and use it in GitHub Desktop.
Save lukechilds/307341239beac72c9d8cfe3198f9bfff to your computer and use it in GitHub Desktop.

Ecash mints funded with Spillman channels: The ultimate nodeless Lightning wallet

Overview

This proposal introduces a self-custodial credit system that sits in front of an existing ecash mint. The users balance is held in a trustless credit contract that can be instantly swapped for ecash tokens offchain at the time of payment. Custodial risk only exists while payments are in flight, which is usually seconds, and only for the amount currently being transacted. The balance is always self-custodial and if the mint disappears or is uncooperative the user can unilaterally exit and reclaim their credits onchain.

The protocol works on Bitcoin today and does not require a soft fork or any new opcodes. Infact it doesn't require any opcodes at all. The protocol is almost entirely off chain, every possible way to execute the trustless credit contract results in a MuSig2 taproot key path spend onchain, no Bitcoin Script required.

The problem

A typical user flow is to be paid a salary, deposit monthly spending money into an ecash mint, and then make small low value payments throughout the month from the mint. The flow of money is mostly one way, it's very rare for an end user to receive money, other than their salary.

If a user makes four $10 payments a day, they will make 120 transactions a month totalling $1,200. They deposit one $1,200 transaction into the ecash mint at the begining of the month and then can freely spend the balance. This system works great because it compresses 120 economic transactions down to one onchain transaction a month.

The downside is that this efficiency improvement comes with significant risk. The entire balance is custodied by the mint and they are entirely trusted to not steal the money. If you have 1,000 users in the mint doing this, the mint is custodying a total of $1.2M in funds. If a mint operator thinks they can get away with stealing the money, there is significant incentive to do so. Even if the mint operator is honest, it's a huge target for attackers.

The solution

Instead of holding the balance in the mint, the balance can instead be held in a trustless credit contract between the user and the mint. The credits are self-custodial and either the user or the mint can unilaterally exit the credit contract without cooperation from the other party. Credits can be redeemed with the mint for ecash tokens instantly offchain. Credits are only exchanged for ecash tokens at the time of payment, and then immediately spent. There is custodial risk while the credits are held, but this is only while the transaction is in flight which generally lasts mere seconds, and only the value of the in flight transaction is at risk.

This trustless credit system can be built with Spillman payment channels. Spillman channels never gained much popularity because they have two significant drawbacks, they are unidirectional and they expire in a predetermined amount of time. However it just so happens that for this specific use case, those two drawbacks do not matter. Since for this use case the user primarily spends rather than receives money, one way channels work well. The user also already needs to make monthly topup transactions to the mint, so replacing that with a channel that expires every month is no worse.

Without the downsides being an issue, Spillman channels have the benefit that they are very simple. For the user there is no node that needs to be run, no liveness requirement, no complex backup state, no liquidity management. The user only needs to deposit funds into the channel, and simply then sends presigned transactions to the mint offchain to pay over the channel.

In this protocol we propose a novel variant of Spillman channels making use of modern additions to Bitcoin for improved privacy and efficiency. We implement Spillman channels in a way that every possible spending condition can be satisfied by a MuSig2 taproot key path spend. The downside is that interactivity is required for payment, however since interactivity with the mint is already required for issuing ecash tokens, that doesn't add significant complexity.

The protocol

The trustless credit contract is a 2-of-2 MuSig2 multisig between the user and the mint. The user funds the contract with one months worth of spending money but does not broadcast the funding transaction. They then create a refund transaction spending the entire balance back to themselves with an nLockTime value of one month in the future. The refund transaction is then collaboratively cosigned by the user and the mint. This is the user's unilateral exit transaction. Once this is signed, it's safe for the user to broadcast the funding transaction. After confirmation, the trustless credit contract is now active and the user has a months worth of spending money in credits with the mint.

To make a payment through the mint the user must now redeem trustless credits for trusted ecash tokens from the mint. The user creates a new transaction spending the funding transaction and paying the amount of desired credits to the mint and the remaining balance back to themselves. They create a partial musig signature and send it to the mint to aggregate with their own signature into a valid transaction. The mint does not share their partial signature or the valid signed transaction back with the user. This is the mints unilateral exit transaction that they can trustlessly execute at any point. They now credit the user with the equivalent amount of ecash tokens. The user now has custodial risk with these tokens, however they immediately spend them in the mint retaining full self custody over their remaining balance in the trustless credit contract.

The next time the user wants to make a transaction, they go through the same process, creating a new transaction that spends the same funding transaction, replacing the previous one. The new transaction pays the mint the balance from any previous payments plus the current payment. Since every state update results in a new unilateral exit transaction for the mint that is more valuable than the previous, they only ever need to care about the latest unilateral exit transaction, no complex state management is needed.

At the end of the month, the trustless credit contract can be rolled over to the next month and topped up with more credit. The user and the mint cooperatively cosign to spend the funding transaction, paying the mint the value of credits that were redeemed and paying any remaining balance into a new contract for the following month. The user can attach a new input to the transaction to top up credits for the next month. This results in a single onchain transaction once a month that both tops up the users credits for the next month and pays out the mint the credited amount for the past month.

All possible ways of executing the trustless credit contract—unilateral exits, cooperative closes, and cooperative contract rollovers—are just musig key path spends, resulting in a small on-chain footprint. There is no script path for any type of contract execution, so an onchain observer learns nothing about the contract.

Exiting the trustless credit contract

Both parties can cooperatively exit the contract at any point. The mint can unilaterally exit with the latest state at any point. The user can unilaterally exit only after the contract expires. It's important that if the contract is not cooperatively closed, the mint unilaterally exits before expiry, otherwise the user can unilaterally exit and claim all the funds back.

Further thoughts

Privacy implications

One of the best things about ecash is the near perfect privacy it offers. Part of what enables this privacy is the time you spend sitting in the mint. If you use this protocol to pay recipients staying in the mint, privacy is preserved. However if you use this protocal to pay a lightning invoice outside of the mint, you do not inherit the privacy properties of ecash. You still retain good onchain privacy and good sender privacy over lightning. However it's trivial for the mint operator to perform timing and amount analysis on the credit > token swap entering the mint, and the token > lightning swap leaving the mint. You have zero privacy from the perspective of the mint operator.

However this can be solved by holding a small balance of custodial ecash tokens within the mint. For example holding roughly 95% of your balance in trustless credits, and 5% in ecash tokens is probably enough to fuzz the amounts and break the timing/amount correlation between entering and exiting the mint. You recover the great privacy properties of ecash while only exposing yourself to 5% custody risk. An interesting thing about this is that it's user configurable. Users can adjust this percentage for themselves based on if they favour more privacy or less custody risk.

Inabiltiy to trustlessly receive

This protocol only enabled trustless sending, it does not enable trustless receiving. As described in the typical user flow above, this is probably not something many users need to do often so it's not an issue. Users can just receive custodial ecash tokens, and prioritise spending them before redeeming more trustless credits.

Taking the previous example, if a user typically makes four $10 payments per day requiring a monthly top up of $1,200. If they receive a refund for one of their payments, they just expose themselves to $10 of custody risk (0.8% of their total balance) for a quarter of a day before they spend it again in their next payment.

Extending the protocol for trustless receive

It is possible to duplicate the protocol in reverse to enable trustless receive, however I think it's overcomplicated and unnecessary for the reasons explained above. Potentially it could make sense for merchants who want to receive in an ecash mint. The mint then becomes a centralised hub for fast, private, trust minimised payments between users and merchants.

You can have a reverse trustless credit channel going from the mint to a merchant. In this setup the mint opens a Spillman channel to the merchant. In the reverse construct the mint must provide the expected liquidity up front and charge the merchant for it. The merchant trusts the mint to not steal in flight payments, but once they are received they are self custodial and the merchant can perform a unilateral exit to claim the funds if the mint becomes uncooperative. If the merchant does not remember to close or roll over the contract before expiry, the mint can steal the last months worth of funds.

Due to the extra complexities in the reverse method I don't see a significant advantage to this over the merchant just using lightning.

Liquidity

This protocol does place some extra liquidity requirements on the mint. If they have many custodial and non-custodial users at the same time, topping up and spending at different intervals, it's unlikely to cause any problems. However if a large amount of non-custodial users enter into large trustless credit contracts and then try and pay out a lot of money over lightning at the same time, they may pay out more than the mint operator is able to fulfil.

Note that the mint is not undercollatoralised, it has all the required funds to process the withdrawals, it's just that some of these funds are in trustless credit contracts with users. If there was heavy traffic exiting the mint they may need to close some users credit contracts to honour other users withdrawals. Since closing contracts with users is fustrating, this can be mitigated by the mint having extra funds on hand to process withdrawals, or by outsourcing lightning payments to a third party and settling with them monthly.

Contract expiry

Contract expiry length is arbitrary. We propose one month to line up with typical budgeting and accounting alongside monthly salary payments. However this means an onchain transaction is needed once per month to keep the contract open, even if there is still plenty of balance left in the credit contract. Expiry could be increased to one year, which allows the contract to be held open without an onchain transaction for up to a year. If top ups are required more frequently they can still be done so cooperatively. However this has the downside that if the mint operator becomes uncooperative, the users funds will be locked for up to a year before they can unilaterally exit the contract. Potentially this is a reasonbale tradeoff since the current trust model is that if the mint operator becomes uncooperative, all funds are lost. All funds being locked for a year is still a strict improvement.

Credit

Thanks to @tiero and the @ArkLabsHQ team for their research into Spillman channels on Ark that lead me to this idea.

Thanks to @moonsettler and his prior research trying to solve the same problem with credit based ecash that helped me connect the dots.

Thanks to @tiero @robinlinus @stevenroose @kukks @mayankchhabra @nmfretz @gandlafbtc for taking the time to proof read this proposal and give me your thoughts.

@emtll
Copy link

emtll commented Nov 27, 2024

Amazing! It solves problems that put off the average user or even companies, such as the complexity of maintaining and managing either a non-custodial LN wallet or a Lightning node to receive or send instant payments with sovereignty.

Extremely bullish!

@pool2win
Copy link

Nice. I like the idea of one way channels used with a mint. I have two small thoughts to share.

however since interactivity with the mint is already required for issuing ecash tokens, that doesn't add significant complexity.

I thought the interaction with the mint was limited to the time of issuance. After that the tokens could be exchanged between users offline. With the channel approach the use needs to connect to the mint for each payment. Not a big downside, just asking for clarification.

Another point to think about might be the leakage of information through repeated connections to the mint. I don't know how cashu addresses that tbh, maybe cause it doesn't require repeated connections to make payments.

@adamhackbarth
Copy link

This is great! How do you ensure the mint cannot unilaterally exit the trustless credit contract and steal the user's funds before the contract expires? Also, what safeguards are in place to prevent the mint from manipulating the timing or conditions of the contract expiration?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment