Eltoo / Anyprevout & Baked in Sequences

Eltoo / Anyprevout & Baked in Sequences
2021-07-08  8:44 ` Anthony Towns
  
From: Jeremy @ 2021-07-08  1:00 UTC (permalink / raw)
  To: Bitcoin development mailing list, lightning-dev

[-- Attachment #1: Type: text/plain, Size: 3484 bytes --]

I made a comment on
https://github.com/bitcoin/bips/pull/943#issuecomment-876034559 but it
occurred to me it is more ML appropriate.

In general, one thing that strikes me is that when anyprevout is used for
eltoo you're generally doing a script like:

```
IF
    10 CSV DROP
    1::musigkey(As,Bs) CHECKSIG
ELSE
    <S+1> CLTV DROP
   1::musigkey(Au,Bu) CHECKSIG
ENDIF
```

This means that you're overloading the CLTV clause, which means it's
impossible to use Eltoo and use a absolute lock time, it also means you
have to use fewer than a billion sequences, and if you pick a random # to
mask how many payments you've done / pick random gaps let's say that
reduces your numbers in half. That may be enough, but is still relatively
limited. There is also the issue that multiple inputs cannot be combined
into a transaction if they have signed on different locktimes.

Since Eltoo is the primary motivation for ANYPREVOUT, it's worth making
sure we have all the parts we'd need bundled together to see it be
successful.

A few options come to mind that might be desirable in order to better serve
the eltoo usecase

1) Define a new CSV type (e.g. define (1<<31 && 1<<30) as being dedicated
to eltoo sequences). This has the benefit of giving a per input sequence,
but the drawback of using a CSV bit. Because there's only 1 CSV per input,
this technique cannot be used with a sequence tag.
2) CSFS -- it would be possible to take a signature from stack for an
arbitrary higher number, e.g.:
```
IF
    10 CSV DROP
    1::musigkey(As,Bs) CHECKSIG
ELSE
    DUP musigkey(Aseq, BSeq) CSFSV <S+1> GTE VERIFY
   1::musigkey(Au,Bu) CHECKSIG
ENDIF
```
Then, posession of a higher signed sequence would allow for the use of the
update path. However, the downside is that there would be no guarantee that
the new state provided for update would be higher than the past one without
a more advanced covenant.
3) Sequenced Signature: It could be set up such that ANYPREVOUT keys are
tagged with a N byte sequence (instead of 1), and a part of the process of
signature verification includes hashing a sequence on the signature itself.

E.g.

```
IF
    10 CSV DROP
    1::musigkey(As,Bs) CHECKSIG
ELSE
   <N>::musigkey(Au,Bu) CHECKSIG
ENDIF
```
To satisfy this clause, a signature `<N+1>::S` would be required. When
validating the signature S, the APO digest would have to include the value
<N+1>. It is non cryptographically checked that N+1 > N.
5) Similar to 3, but look at more values off the stack. This is also OK,
but violates the principle of not making opcodes take variable numbers of
things off the stack. Verify semantics on the extra data fields could
ameliorate this concern, and it might make sense to do it that way.
4) Something in the Annex: It would also be possible to define a new
generic place for lock times in the annex (to permit dual height/time
relative/absolute, all per input. The pro of this approach is that it would
be solving an outstanding problem for script that we want to solve anyways,
the downside is that the Annex is totally undefined presently so it's
unclear that this is an appropriate use for it.
5) Do Nothing :)


Overall I'm somewhat partial to option 3 as it seems to be closest to
making ANYPREVOUT more precisely designed to support Eltoo. It would also
be possible to make it such that if the tag N=1, then the behavior is
identical to the proposal currently.

--
@JeremyRubin <https://twitter.com/JeremyRubin>
<https://twitter.com/JeremyRubin>

[-- Attachment #2: Type: text/html, Size: 4365 bytes --]

 permalink raw reply	[|nested]
2021-07-08  1:00 [bitcoin-dev] Eltoo / Anyprevout & Baked in Sequences Jeremy

  2021-07-08 15:48   ` Jeremy
  
From: Anthony Towns @ 2021-07-08  8:44 UTC (permalink / raw)
  To: Jeremy, Bitcoin Protocol Discussion;  lightning-dev

On Wed, Jul 07, 2021 at 06:00:20PM -0700, Jeremy via bitcoin-dev wrote:
> This means that you're overloading the CLTV clause, which means it's impossible
> to use Eltoo and use a absolute lock time,

It's already impossible to simultaneously spend two inputs if one
requires a locktime specified by mediantime and the other by block
height. Having per-input locktimes would satisfy both concerns.

> 1) Define a new CSV type (e.g. define (1<<31 && 1<<30) as being dedicated to
> eltoo sequences). This has the benefit of giving a per input sequence, but the
> drawback of using a CSV bit. Because there's only 1 CSV per input, this
> technique cannot be used with a sequence tag.

This would disallow using a relative locktime and an absolute locktime
for the same input. I don't think I've seen a use case for that so far,
but ruling it out seems suboptimal.

Adding a per-input absolute locktime to the annex is what I've had in
mind. That could also be used to cheaply add a commitment to an historical
block hash (eg "the block at height 650,000 ended in cc6a") in order to
disambiguate which branch of a chain split or reorg your tx is valid for.

Cheers,
aj



 permalink raw reply	[|nested]
2021-07-08  8:44 ` Anthony Towns

  2021-07-12  5:01     ` [bitcoin-dev] [Lightning-dev] " Anthony Towns
  
From: Jeremy @ 2021-07-08 15:48 UTC (permalink / raw)
  To: Anthony Towns;  Bitcoin Protocol Discussion, lightning-dev

[-- Attachment #1: Type: text/plain, Size: 334 bytes --]

>
> This would disallow using a relative locktime and an absolute locktime
> for the same input. I don't think I've seen a use case for that so far,
> but ruling it out seems suboptimal.


I think you meant disallowing a relative locktime and a sequence locktime?
I agree it is suboptimal.


What do you make of sequence tagged keys?

[-- Attachment #2: Type: text/html, Size: 833 bytes --]

 permalink raw reply	[|nested]
2021-07-08 15:48   ` Jeremy

  2021-07-12 22:07       ` Jeremy
  
From: Anthony Towns @ 2021-07-12  5:01 UTC (permalink / raw)
  To: Jeremy;  Bitcoin Protocol Discussion, lightning-dev

On Thu, Jul 08, 2021 at 08:48:14AM -0700, Jeremy wrote:
>     This would disallow using a relative locktime and an absolute locktime
>     for the same input. I don't think I've seen a use case for that so far,
>     but ruling it out seems suboptimal.
> I think you meant disallowing a relative locktime and a sequence locktime? I
> agree it is suboptimal.

No? If you overload the nSequence for a per-input absolute locktime
(well in the past for eltoo), then you can't reuse the same input's
nSequence for a per-input relative locktime (ie CSV).

Apparently I have thought of a use for it now -- cut-through of PTLC
refunds when the timeout expires well after the channel settlement delay
has passed. (You want a signature that's valid after a relative locktime
of the delay and after the absolute timeout)

> What do you make of sequence tagged keys?

I think we want sequencing restrictions to be obvious from some (simple)
combination of nlocktime/nsequence/annex so that you don't have to
evaluate scripts/signatures in order to determine if a transaction
is final.

Perhaps there's a more general principle -- evaluating a script should
only return one bit of info: "bool tx_is_invalid_script_failed"; every
other bit of information -- how much is paid in fees (cf ethereum gas
calculations), when the tx is final, if the tx is only valid in some
chain fork, if other txs have to have already been mined / can't have
been mined, who loses funds and who gets funds, etc... -- should already
be obvious from a "simple" parsing of the tx.

Cheers,
aj



 permalink raw reply	[|nested]
2021-07-12  5:01     ` [bitcoin-dev] [Lightning-dev] " Anthony Towns

  2021-07-14  3:32         ` Anthony Towns
  
From: Jeremy @ 2021-07-12 22:07 UTC (permalink / raw)
  To: Anthony Towns;  Bitcoin Protocol Discussion, lightning-dev

[-- Attachment #1: Type: text/plain, Size: 2485 bytes --]

On Sun, Jul 11, 2021 at 10:01 PM Anthony Towns <aj@erisian•com.au> wrote:

> On Thu, Jul 08, 2021 at 08:48:14AM -0700, Jeremy wrote:
> >     This would disallow using a relative locktime and an absolute
> locktime
> >     for the same input. I don't think I've seen a use case for that so
> far,
> >     but ruling it out seems suboptimal.
> > I think you meant disallowing a relative locktime and a sequence
> locktime? I
> > agree it is suboptimal.
>
> No? If you overload the nSequence for a per-input absolute locktime
> (well in the past for eltoo), then you can't reuse the same input's
> nSequence for a per-input relative locktime (ie CSV).
>
> Apparently I have thought of a use for it now -- cut-through of PTLC
> refunds when the timeout expires well after the channel settlement delay
> has passed. (You want a signature that's valid after a relative locktime
> of the delay and after the absolute timeout)
>

Ah -- I didn't mean a per input abs locktime, I mean the  tx global
locktime.

I agree that at some point we should just separate all locktime types per
input so we get rid of all weirdness/overlap.



>
> > What do you make of sequence tagged keys?
>
> I think we want sequencing restrictions to be obvious from some (simple)
> combination of nlocktime/nsequence/annex so that you don't have to
> evaluate scripts/signatures in order to determine if a transaction
> is final.
>
> Perhaps there's a more general principle -- evaluating a script should
> only return one bit of info: "bool tx_is_invalid_script_failed"; every
> other bit of information -- how much is paid in fees (cf ethereum gas
> calculations), when the tx is final, if the tx is only valid in some
> chain fork, if other txs have to have already been mined / can't have
> been mined, who loses funds and who gets funds, etc... -- should already
> be obvious from a "simple" parsing of the tx.
>
> Cheers,
> aj
>
>
I don't think we have this property as is.

E.g. consider the transaction:

TX:
   locktime: None
   sequence: 100
   scriptpubkey: 101 CSV

How will you tell it is able to be included without running the script?

I agree this is a useful property, but I don't think we can do it
practically.

What's nice is the transaction in this form cannot go from invalid to valid
-- once invalid it is always invalid for a given UTXO.

sequence tagged keys have this property -- a txn is either valid or invalid
and that never changes w/o any external information needing to be passed up.

[-- Attachment #2: Type: text/html, Size: 5556 bytes --]

 permalink raw reply	[|nested]
2021-07-12 22:07       ` Jeremy

  
From: Anthony Towns @ 2021-07-14  3:32 UTC (permalink / raw)
  To: Jeremy;  Bitcoin Protocol Discussion, lightning-dev

On Mon, Jul 12, 2021 at 03:07:29PM -0700, Jeremy wrote:
>     Perhaps there's a more general principle -- evaluating a script should
>     only return one bit of info: "bool tx_is_invalid_script_failed"; every
>     other bit of information -- how much is paid in fees (cf ethereum gas
>     calculations), when the tx is final, if the tx is only valid in some
>     chain fork, if other txs have to have already been mined / can't have
>     been mined, who loses funds and who gets funds, etc... -- should already
>     be obvious from a "simple" parsing of the tx.
> I don't think we have this property as is.
> E.g. consider the transaction:
> TX:
>    locktime: None
>    sequence: 100
>    scriptpubkey: 101 CSV

That tx will never be valid, no matter the state of the chain -- even if
it's 420 blocks after the utxo it's spending: it fails because "top stack
item is greater than the transaction input sequence" rule from BIP 112.

> How will you tell it is able to be included without running the script?

You have to run the script at some point, but you don't need to run the
script to differentiate between it being valid on one chain vs valid on
some other chain.

> What's nice is the transaction in this form cannot go from invalid to valid --
> once invalid it is always invalid for a given UTXO.

Huh? Timelocks always go from invalid to valid -- they're invalid prior
to some block height (IsFinal() returns false), then valid after.

Not going from valid to invalid is valuable because it limits the cases
where you have to remove txs (and their descendents) from the mempool.

Cheers,
aj



 permalink raw reply	[|nested]