Hello list,

Here is an idea to make lightning channels resumable from wallet seed.
I have not implemented it yet, and there might be issues I am not
seeing. Thus, I would be grateful for feedback.

Thanks to SomberNight and Peter Todd for reviewing earlier versions of
this proposal.

Thomas


-----------------------------------------------

Resumable channels using OP_CHECKSIGFROMSTACK
=============================================


In order to resume the activity of a Lightning channel, one needs a
backup that contains all the information about the current channel
state. The need to perform channel backups has plagued user
experience, with many implementations reverting to static backups,
which can be used to recover funds, but not to resume channel
operations.

Asking your channel counterparty to store your channel state has the
advantage to make backup operations atomic. However, there is no
guarantee that this is safe. Indeed, if the other party suspects that
you have lost your state (for example, because you have been offline
for a long time, or if they can see that you requested blockchain
information following a certain pattern), they can try to send you a
revoked state, and there is no way to punish them for doing that.

Here is a proposal for a new type of channel funding transaction,
where the redeem script has an additional spending path, that accepts
a fraud proof: a proof that the channel counterparty has lied about
the current state. This proposal requires two opcodes that are
currently not available in Bitcoin: OP_CAT and OP_CHECKSIGFROMSTACK.

Roles are asymmetric in this channel: Alice is a client, and Bob is a
server, who stores Alice's state. Thus, this proposal is mostly suited
for private channels with Lightning service providers. During channel
reestablishment, Bob will send her latest state to Alice, using an
extra field in the channel_reestablish message. Since Alice cannot
punish Bob if she has lost her state, she must not let Bob learn
whether she still has her state. Thus, Alice will never send
channel_reestablish first.

This proposal assumes that Alice and Bob each have a clock, and that
these clocks do not drift too much relative to each other. The channel
may become unusable if clocks differ too much, as discussed below.


Simplified description
----------------------

The *state* of the channel refers to everything Alice needs in order
to resume channel operations. With every new commitment, Alice sends
her current state, with her signature of that state:

 - if Alice sends commitment_signed, the state and signature are
   included in that message.

 - if Alice receives commitment_signed, the state and signature will
   be included in the next revoke_and_ack sent by Alice.

With every new commitment, Bob sends a signed tuple (ctn, timestamp),
where ctn is the current commitment number (for the moment, forget
about the distinction between local and remote ctns), and timestamp is
the current time for Bob.

 - if Bob sends commitment_signed, the signed tuple is included in
   that message.
- if Bob receives commitment_signed, the signed tuple will be
   included in the next revoke_and_ack sent by Bob.

The private key used by Bob to sign the tuples is constant over the
lifetime of the channel, and it must not be reused in other
channels. The corresponding public key will be used in the fraud proof
spending path of the redeem script.

Alice verifies Bob's signature. She also checks that the received
timestamps are reasonable (see below) and strictly monotonic.

With every channel_reestablish message, Bob will send two extra fields:
 - (ctn, timestamp, bob_signature)
 - (alice_state, alice_signature).

Alice verifies that the state she received was signed by her, and that
the (ctn, timestamp) tuple was signed by Bob. She also checks that the
timestamp is reasonable.

Fraud Proofs
------------

Let us assume that Bob tries to send a revoked state to Alice in
channel_reestablish. The channel_reestablish received by Alice
contains a signed tuple (ctn1, t1), with t1 current timestamp.

However, another signed tuple (ctn2, t2) has been received in the
past, with ctn1 < ctn2 and t1 > t2.

If Alice has not lost her state, she will now hold two signed tuples
(ctn1, t1) and (ctn2, t2), that satisfy ctn1 < ctn2 and t1 > t2.

This constitutes a fraud proof. With OP_CAT and OP_CHECKSIGFROMSTACK,
we can build a script that verifies the fraud proof, and allows Alice
to unilaterally spend the channel funding output.

Here is an example of such a script:

witness:
[
 alice_signature(transaction)
 bob_signature((ctn1,timestamp1))
 ctn1
 timestamp1
 bob_signature((ctn2,timestamp2))
 ctn2
 timestamp2
]

witness_script:
 OP_PICK 1
 OP_PICK 4
 OP_LESSTHAN                 # verify ctn1 < ctn2
 OP_VERIFY
 OP_PICK 0
 OP_PICK 3
 OP_GREATERTHANOREQUAL       # verify timestamp1 >= timestamp2
 OP_VERIFY
 # check signatures
 OP_CAT
 OP_PUSHDATA bob_pubkey      # we may use Bob's funding_pubkey
 OP_CHECKSIGFROMSTACK
 OP_VERIFY
 OP_CAT
 OP_PUSHDATA bob_pubkey
 OP_CHECKSIGFROMSTACK
 OP_VERIFY
 OP_PUSHDATA alice_pubkey    # we may use Alice's funding_pubkey
 OP_CHECKSIGVERIFY


In order to keep things simple, a few details have been omitted in the
description:

 - Bob actually needs to send both the local and the remote ctns in
   his signed tuples. A pair of tuples is a fraud proof if the order
   is violated for either local or remote ctns. Thus, the actual
   script will be more complex than what has been drafted above.

 - Integers pushed on the Bitcoin stack are maximum 4 bytes (31 bits +
   1 bit for the sign). Since commitment numbers are 48 bits long,
   they will need to be split into two integers. Timestamps might
   require a similar decomposition. This adds further complexity to
   the redeem script.

 - Note that Bob must strictly increase his timestamp on each
   ctn. This puts a lower bound on the precision used for timestamps.


Reasonable Timestamps
---------------------

Since Alice and Bob do not have the same clock, Bob may legitimately
send a timestamp that is in Alice's past or future. Every time Alice
receives a timestamp from Bob, she compares it to her current time.

 - If Alice receives a timestamp that is in her future, instead of
   closing the channel, she may wait it out before she accepts to
   resume operations.

 - If Alice receives a timestamp that is too far in her past, she
   should disconnect. Indeed, Bob may be sending an old state and
   replaying old timestamps, which is not punishable. In that case,
   Alice should not automatically force close the channel, because she
   can only do that if she has not lost her state; if force-closing
   was automatic, not force-closing would reveal to Bob that she
   has lost her state.

A delay needs to be tolerated by Alice, because Bob does not have the
same clock; that delay should be chosen so that it is always smaller
than the interval between two sessions.


Saving Bandwidth
----------------

Alice's channel state does not need to be sent with every commitment,
if it is made of information that is known by both parties. In that
case, it is sufficient for Alice to send her signature of the current
state. Both Alice and Bob must be able to serialize the state, so that
Alice can verify her own signature against a serialization of the
state created by Bob. The state only needs to be sent by Bob once, in
channel_reestablish.

For this to work, the channel state cannot include information that is
private to Alice. If the private keys used by Alice in the channel are
derived deterministically from her wallet seed, they do not need to be
part of the state. Alternatively, private keys may be included in an
encrypted blob that is included in the state. Since that encrypted
blob is constant, it only needs to be sent once by Alice, during the
channel opening negotiation. Bob will save it and add it to the state
sent in channel_reestablish.

In addition, the state must not include any payment_hash preimage
known by Alice; thus, Alice will have to fail incoming payments for
those preimages, if she has lost her state.

The channel state should include the compact storage of per-commitment
secrets sent by Bob.


Concluding remarks
------------------

 - Obviously, this proposal assumes that Alice remembers with whom she
   has an open channel.

 - Alice may restore her wallet from seed on a new device, while the
   initial wallet is still active. In that case, Alice must stop using
   the channels on her old device. Thus, Alice should disconnect if
   she has not lost her state and receives a state with a ctn that is
   in her future. This ensures that only one device uses the channels.

 - Without waiting for OP_CHECKSIGFROMSTACK to be available in
   Bitcoin, it would be possible for Bob to lockup funds on another
   blockchain such as Liquid. It is also possible to create fraud
   proofs that are not used in a redeem script, but that are tied to
   Bob's public identity and reputation. In that case, Bob should sign
   with his node pubkey, and fraud proofs will need to include a short
   channel id.
_______________________________________________
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev

Reply via email to