Fri. Nov 22nd, 2024

Many people these days are finally starting to realize the shortcomings and limitations of off-chain channels limited to two participants, i.e. the Lightning Network, and the necessity to start exploring designs for channels with more than two participants for this direction in scaling to work successfully in the long term. That necessitates accepting new trade-offs, namely that the price for solving some of Lightning’s existing problems by packing more than two people into a shared control arrangement for a UTXO is the creation of a whole new class of problems.

The biggest problem introduced in making the move from two parties to more than two parties is the interactivity requirement. If you have 10 people in a single channel sharing control of one UTXO, you need all 10 parties online at the same time in order to update the state of that base channel. This presents a much worse coordination problem than the current implementation of Lightning channels where only two people need to be online to make use of the channel.

Currently the best thinking regarding this issue is simply to introduce trust into the situation through what is essentially a federation. Lightning (and future multiparty channel systems) work as a self custodial system because the multisig holding funds on chain is n-of-n, requiring 100% of the participants to sign off to change the state of off-chain funds. If you yourself as a member to such an agreement refuse to sign a new update, then it is impossible for your funds to be reassigned in any way. Ignoring the requirement to stay online and watch the blockchain to deal with old states, this security model is equivalent to sole custody on the mainchain. Control of funds cannot be changed from the current state of things without your signature.

Reducing the key threshold from n-of-n to m-of-n completely undermines that security equivalence to sole custody on-chain. It is effectively custodial, in that your key is no longer absolutely and non-negotiably required in order to move control of your funds. ZmnSCPxj (not Zman!) has proposed an interesting solution to the interactivity problem.

OP_CHECKSEPARATESIG

This proposal would require two softforks, SIGHASH_ANYPREVOUT and OP_CHECKSEPARATESIG. The scope of OP_CHECKSEPARATESIG is so small and tiny of a change I would be amazed if there is any serious contention with it, and APO has a relatively large consensus in the ecosystem as a desirable change.

OP_CHECKSIG and OP_CHECKSIGVERIFY are the two main ways signatures are verified in Bitcoin script currently. There are two parts of a signature, the S value and the r value. OP_CHECKSIG(VERIFY) takes the r and S of the signature as one whole argument, and the public key to verify it against as another, for a total of two arguments, and then checks whether the signature is valid or not. OP_CHECKSEPARATESIG takes the public key, the r value, and the S value all as separate arguments (for a total of three), and verifies the signature.

Yes, that is literally the entirety of the proposal. A softfork even simpler and less complicated than CHECKTEMPLATEVERIFY (CTV). Why is this needed? Well, you’ll see here right now.

State Updates Without Everyone Online

A multiparty channel.

This is what the starting state of a very basic multiparty channel would look like. A pre-signed transaction needing Alice, Bob, and Charlie to sign for a UTXO they share control over with an output for each member. If Alice wants to pay Bob while Charlie is offline, the only option she has is to create a pre-signed transaction from her output in the channel state splitting those funds between herself and the payment to Bob like this:

Alice paying Bob.

The problem with this arrangement is that Alice can simply sign a conflicting transaction taking back the payment to Bob at any time and use it before Charlie comes online and everyone updates the channel, and because only her key is needed to do that Bob can do nothing to stop her. We need to have some kind of arbitrator that ensures Alice cannot double-spend Bob when making payments in this way because Charlie is unresponsive.

You could just add a condition requiring that a Actuary (M) also be a keyholder for everyone’s outputs, meaning they would have to sign to approve any transactions spending Alice, Bob, or Charlie’s outputs from the channel state. The problem with that is, now Bob has to trust the Actuary instead of Alice. If the Actuary cooperates with Alice, Bob can still be double spent.

This is where OP_CHECKSEPARATESIG comes in. Here’s how: the r value in a signature is derived from the nonce used to sign. One of the key risks in nonce handling is the risk of key leakage, reusing the same nonce twice for different transactions will leak enough information for someone with both of those transactions to be able to regenerate the private key used. This can be used to take the Actuary role from above and remove trust in them. Whatever key the Actuary uses for this role, they can load with a bond that can be confiscated. From this point we add their key to everyone’s outputs like described above, except specifying in each script exactly what r value has to be used in the signature from M ahead of time. We also have a CSV timelocked path needing only the owner’s key; this way users can always spend their funds however they want if the channel is closed on chain after a timelock.

Now when Alice goes to pay Bob while Charlie is offline using a pre-signed transaction spending her output in the channel, she goes to the Actuary to sign off on it. After the signatures are completed and Bob has a copy of the transaction, he has an immensely stronger guarantee that these funds will not be double spent. If the Actuary collaborates with Alice to double-spend Bob, his key is leaked and the funds he put in a bond can be confiscated. If the channel is closed out on-chain in this state Bob will be able to confirm the transaction co-signed by the Actuary before Alice can double-spend him, because Alice has to wait for a timelock to expire before she can double-spend, Bob doesn’t because the Alice and Actuary spending path has no timelock. This can be added as a clause to every level of the multiparty channel if you nest smaller channels on top as well.

This provides a security model for Alice and Bob to update the multiparty channel without Charlie being online, which while not being strictly speaking trustless, is about as close as you can get without meeting that bar. Bob can have a strong guarantee that he won’t be double spent, which is virtually 100% as long as the bond value the Actuary uses is greater than the payment value, and Alice can make this payment with a guarantee good enough for Bob even though Charlie is offline. This can be used in that likely very frequent situation where not everyone is available to continue processing updates, and cleanly cut-through whenever everyone is online to update the base level of the channel and remove the extra transactions using this scheme.

OP_CHECKSEPARATESIG and the Actuary role it enables in multiparty channels solve a huge problem in actually making the concept of more than two people sharing a channel workable at scale. I’m sure there are plenty of other situations besides multiparty channels where enforcing with a bond that some party only ever signs one version of something. This should be something very seriously considered by Bitcoiners, it provides a big solution to a known problem with no complexity by just slightly changing a tiny aspect of how signatures are verified.