More thoughts on NOINPUT safety

More thoughts on NOINPUT safety
2019-03-13  6:41 ` [bitcoin-dev] [Lightning-dev] " ZmnSCPxj
  2019-03-20  0:22 ` Rusty Russell
  
From: Anthony Towns @ 2019-03-13  1:41 UTC (permalink / raw)
  To: bitcoin-dev;  lightning-dev

Hi all,

The following has some more thoughts on trying to make a NOINPUT
implementation as safe as possible for the Bitcoin ecosystem.

One interesting property of NOINPUT usage like in eltoo is that it
actually reintroduces the possibility of third-party malleability to
transactions -- ie, you publish transactions to the blockchain (tx A,
which is spent by tx B, which is spent by tx C), and someone can come
along and change A or B so that C is no longer valid). The way this works
is due to eltoo's use of NOINPUT to "skip intermediate states". If you
publish to the blockchain:

      funding tx -> state 3 -> state 4[NOINPUT] -> state 5[NOINPUT] -> finish

then in the event of a reorg, state 4 could be dropped, state 5's
inputs adjusted to refer to state 3 instead (the sig remains valid
due to NOINPUT, so this can be done by anyone not just holders of some
private key), and finish would no longer be a valid tx (because the new
"state 5" tx has different inputs so a different txid, and finish uses
SIGHASH_ALL for the signature so committed to state 5's original txid).

There is a safety measure here though: if the "finish" transaction is
itself a NOINPUT tx, and has a a CSV delay (this is the case in eltoo;
the CSV delay is there to give time for a hypothetical state 6 to be
published), then the only way to have a problem is for some SIGHASH_ALL tx
that spends finish, and a reorg deeper than the CSV delay (so that state
4 can be dropped, state 5 and finish can be altered). Since the CSV delay
is chosen by the participants, the above is still a possible scenario
in eltoo, though, and it means there's some risk for someone accepting
bitcoins that result from a non-cooperative close of an eltoo channel.


Beyond that, I think NOINPUT has two fundamental ways to cause problems
for the people doing NOINPUT sigs:

 1) your signature gets applied to a unexpectedly different
    script, perhaps making it look like you've being dealing
    with some blacklisted entity. OP_MASK and similar solves
    this.

 2) your signature is applied to some transaction and works
    perfectly; but then someone else sends money to the same address
    and reuses your prior signature to forward it on to the same
    destination, without your consent

I still like OP_MASK as a solution to (1), but I can't convince myself that
the problem it solves is particularly realistic; it doesn't apply to
address blacklists, because for OP_MASK to make the signature invalid
the address has to be different, and you could just short circuit the
whole thing by sending money from a blacklisted address to the target's
personal address directly. Further, if the sig's been seen on chain
before, that's probably good evidence that someone's messing with you;
and if it hasn't been seen on chain before, how is anyone going to tell
it's your sig to blame you for it?

I still wonder if there isn't a real problem hiding somewhere here,
but if so, I'm not seeing it.

For the second case, that seems a little more concerning. The nightmare
scenario is maybe something like:

 * naive users do silly things with NOINPUT signatures, and end up
   losing funds due to replays like the above

 * initial source of funds was some major exchange, who decide it's
   cheaper to refund the lost funds than deal with the customer complaints

 * the lost funds end up costing enough that major exchanges just outright
   ban sending funds to any address capable of NOINPUT, which also bans
   all taproot/schnorr addresses

That's not super likely to happen by chance: NOINPUT sigs will commit
to the value being spent, so to lose money, you (Alice) have to have
done a NOINPUT sig spending a coin sent to your address X, to someone
(Bob) and then have to have a coin with the exact same value sent from
someone else again (Carol) to your address X (or if you did a script
path NOINPUT spend, to some related address Y with a script that uses the same
key). But because it involves losing money to others, bad actors might
trick people into having it happen more often than chance (or well
written software) would normally allow.

That "nightmare" could be stopped at either the first step or the
last step:

 * if we "tag" addresses that can be spent via NOINPUT then having an
   exchange ban those addresses doesn't also impact regular
   taproot/schnorr addresses, though it does mean you can tell when
   someone is using a protocol like eltoo that might need to make use
   of NOINPUT signatures.  This way exchanges and wallets could simply
   not provide NOINPUT capable addresses in the first place normally,
   and issue very large warnings when asked to send money to one. That's
   not a problem for eltoo, because all the NOINPUT-capable address eltoo
   needs are internal parts of the protocol, and are spent automatically.

 * or we could make it so NOINPUT signatures aren't replayable on
   different transactions, at least by third parties. one way of doing
   this might be to require NOINPUT signatures always be accompanied by a
   non-NOINPUT signature (presumably for a different public key, or there
   would be no point). This would prevent NOINPUT key-path spends, you'd
   always have to use the taproot script-path for a NOINPUT signature so
   that you could specify both public keys, and would also increase the
   witness size due to needing two signatures and specifying an additional
   public key -- this would increase the cost in fees by about 25% compared
   to a plain key-path spend.

Conversely, this "nightmare" scenario *can't* be stopped if we allow
key-path spending of (untagged) taproot addresses with NOINPUT signatures:
exchanges could not distinguish such addresses from regular addresses, and
the only way to prevent the signature from applying to two tx's with the
same value and address would be for the sig to commit to info from the tx.

It seems like there's one big choice then:

 - just ignore this concern

 - drop NOINPUT from normal taproot key path spending

If we drop NOINPUT from taproot key path spending, then we can do NOINPUT
as a logically separate upgrade to taproot, rather than it needing to
be done at the same time.  There's two ways we could do proceed:

 - introduce a new NOINPUT-capable scriptPubKey format (ie, "tag"
   NOINPUT spendable addresses); either a different length segwit v1
   output, or a different segwit version entirely. Using version "16" in
   this scenario might be appealing: we could reserve all v16 addresses
   for "not intended to be used by humans directly" and update BIP 173
   to say these aren't even something you should use bech32 to represent.

 - alternatively, we could require every script to have a valid signature
   that commits to the input. In that case, you could do eltoo with a
   script like either:

        <A> CHECKSIGVERIFY <B> CHECKSIG
     or <P> CHECKSIGVERIFY <Q> CHECKSIG

   where A is Alice's key and B is Bob's key, P is muSig(A,B) and Q is
   a key they both know the private key for. In the first case, Alice
   would give Bob a NOINPUT sig for the tx, and when Bob wanted to publish
   Bob would just do a SIGHASH_ALL sig with his own key. In the second,
   Alice and Bob would share partial NOINPUT sigs of the tx with P, and
   finish that when they wanted to publish.

   This is a bit more costly than a key path spend: you have to reveal
   the taproot point to do a script (+33B) and you have two signatures
   instead of one (+65B) and you have to reveal two keys as well
   (+66B), plus some script overhead. If we did the <P,Q> variant,
   we could provide a "PUSH_TAPROOT_KEY" opcode that would just push
   the taproot key to stack, saving 33B from pushing P as a literal,
   but you can't do much better than that. All in all, it'd be about 25%
   overhead in order to prevent cheating. [0]

I think that output tagging doesn't provide a workable defense against the
third party malleability via a deeper-than-the-CSV-delay reorg mentioned
earlier; but requiring a non-NOINPUT sig does: you'd have to replace
the non-NOINPUT sig to make state 5 spend state 3 instead of state 4,
and only the holders of the appropriate private key can do that.


In any event, if we get some experience with NOINPUT in practice, we can
reconsider whether NOINPUT key path spends are a good idea when we do
the next segwit version -- both cross-input signature aggregation and
graftroot will need an upgrade anyway.

(Also, note that, at least for eltoo, all of the above only applies to
non-cooperative closes: the funding tx's txid is known from the start,
so you can always arrange to spend it via SIGHASH_ALL, so it doesn't
need to be tagged, and a cooperative/mutual close of the channel will
still just be a simple key path spend)


Anyway, presented for your consideration.


FWIW, I don't have a strong opinion here yet, but:

 - I'm still inclined to err on the side of putting more safety
   measures in for NOINPUT, rather than fewer

 - the "must have a sig that commits to the input tx" seems like it
   should be pretty safe, not too expensive, and keeps taproot's privacy
   benefits in the cases where you end up needing to use NOINPUT

Cheers,
aj


 permalink raw reply	[|nested]
2019-03-13  1:41 [bitcoin-dev] More thoughts on NOINPUT safety Anthony Towns

  2019-03-13 11:10   ` Anthony Towns
  2019-03-20  0:22 ` Rusty Russell
  
From: ZmnSCPxj @ 2019-03-13  6:41 UTC (permalink / raw)
  To: Anthony Towns;  bitcoin-dev, lightning-dev

Good morning aj,

First off, I have little to no idea of the issues at the lower-level Bitcoin.

In any case ---

> -   alternatively, we could require every script to have a valid signature
>     that commits to the input. In that case, you could do eltoo with a
>     script like either:
>
>     <A> CHECKSIGVERIFY <B> CHECKSIG
>     or <P> CHECKSIGVERIFY <Q> CHECKSIG
>
>
> where A is Alice's key and B is Bob's key, P is muSig(A,B) and Q is
> a key they both know the private key for. In the first case, Alice
> would give Bob a NOINPUT sig for the tx, and when Bob wanted to publish
> Bob would just do a SIGHASH_ALL sig with his own key. In the second,
> Alice and Bob would share partial NOINPUT sigs of the tx with P, and
> finish that when they wanted to publish.
>
> This is a bit more costly than a key path spend: you have to reveal
> the taproot point to do a script (+33B) and you have two signatures
> instead of one (+65B) and you have to reveal two keys as well
> (+66B), plus some script overhead. If we did the <P,Q> variant,
> we could provide a "PUSH_TAPROOT_KEY" opcode that would just push
> the taproot key to stack, saving 33B from pushing P as a literal,
> but you can't do much better than that. All in all, it'd be about 25%
> overhead in order to prevent cheating. [0]
>
> I think that output tagging doesn't provide a workable defense against the
> third party malleability via a deeper-than-the-CSV-delay reorg mentioned
> earlier; but requiring a non-NOINPUT sig does: you'd have to replace
> the non-NOINPUT sig to make state 5 spend state 3 instead of state 4,
> and only the holders of the appropriate private key can do that.

At my point of view, if a NONINPUT sig is restricted and cannot be used to spend an "ordinary" 2-of-2, this is output tagging regardless of exact mechanism.
So the restriction to add a non-NOINPUT sig in addition to a NOINPUT sig is still output tagging, as a cooperative close would still reveal that the output is not a 2-of-2.

Ideally, historical data of whether onchain coin was used in Lightning or not should be revealed as little as possible.
So in a cooperative close (which we hope, to be a common case), ideally the spend should look no different from an ordinary 2-of-2 spend.
Of course if the channel is published on Lightning, those who participated in Lightning at the time will learn of it, but at least the effort to remember this information is on those who want to remember this fact.

Now, this can be worked around by adding a "kickoff" transaction that spends the eltoo setup transaction.
The eltoo setup transaction outputs to an ordinary 2-of-2.
The kickoff outputs to an output that allows NOINPUT.
Then the rest of the protocol anchors on top of the kickoff.

The kickoff is kept offchain, until a non-cooperative close is needed.
Of course, as it is not a NOINPUT itself, it must need onchain fees attached to it.
This of course complicates fees, as we know.
Alternately maybe the kickoff can be signed with `SIGHASH_SINGLE | SIGHASH_ANYONECANPAY` so that it is possible to add a fee-paying UTXO to it.

Regards,
ZmnSCPxj


 permalink raw reply	[|nested]
2019-03-13  6:41 ` [bitcoin-dev] [Lightning-dev] " ZmnSCPxj

  2019-03-14  5:22     ` ZmnSCPxj
  
From: Anthony Towns @ 2019-03-13 11:10 UTC (permalink / raw)
  To: ZmnSCPxj;  bitcoin-dev, lightning-dev

On Wed, Mar 13, 2019 at 06:41:47AM +0000, ZmnSCPxj via Lightning-dev wrote:
> > -   alternatively, we could require every script to have a valid signature
> >     that commits to the input. In that case, you could do eltoo with a
> >     script like either:
> >     <A> CHECKSIGVERIFY <B> CHECKSIG
> >     or <P> CHECKSIGVERIFY <Q> CHECKSIG
> > where A is Alice's key and B is Bob's key, P is muSig(A,B) and Q is
> > a key they both know the private key for. In the first case, Alice
> > would give Bob a NOINPUT sig for the tx, and when Bob wanted to publish
> > Bob would just do a SIGHASH_ALL sig with his own key. In the second,
> > Alice and Bob would share partial NOINPUT sigs of the tx with P, and
> > finish that when they wanted to publish.
> At my point of view, if a NONINPUT sig is restricted and cannot be
> used to spend an "ordinary" 2-of-2, this is output tagging regardless
> of exact mechanism.

With taproot, you could always do the 2-of-2 spend without revealing a
script at all, let alone that it was meant to be NOINPUT capable. The
setup I'm thinking of in this scenario is something like:

  0) my key is A, your key is B, we want to setup an eltoo channel

  1) post a funding tx to the blockchain, spending money to an address
     P = muSig(A,B)

  2) we cycle through a bunch of states from 0..N, with "0" being the
     refund state we establish before publishing the funding tx to
     the blockchain. each state essentially has two corresponding tx's,
     and update tx and a settlement tx.

  3) the update tx for state k spends to an output Qk which is a
     taproot address Qk = P + H(P,Sk)*G where Sk is the eltoo ratchet
     condition:
        Sk = (5e8+k+1) CLTV A CHECKDLS_NOINPUT B CHECKDLS_NOINPUT_VERIFY

     we establish two partial signatures for update state k, one which
     is a partial signature spending the funding tx with key P and
     SIGHASH_ALL, the other is a NOINPUT signature via A (for you) and
     via B (for me) with locktime set to (k+5e8), so that we can spend
     any earlier state's update tx's, but not itself or any later
     state's update tx's.

  4) for each state we have also have a settlement transaction,
     Sk, which spends update tx k, to outputs corresponding to the state
     of the channel, after a relative timelock delay.

     we have two partial signatures for this transaction too, one with
     SIGHASH_ALL assuming that we directly spent the funding tx with
     update state k (so the input txid is known), via the key path with
     key Qk; the other SIGHASH_NOINPUT via the Sk path. both partially
     signed tx's have nSequence set to the required relative timelock
     delay.

  5) if you're using scriptless scripts to do HTLCs, you'll need to
     allow for NOINPUT sigs when claiming funds as well (and update
     the partial signatures for the non-NOINPUT cases if you want to
     maximise privacy), which is a bit fiddly

  6) when closing the channel the process is then:

       - if you're in contact with the other party, negotiate a new
         key path spend of the funding tx, publish it, and you're done.

       - otherwise, if the funding tx hasn't been spent, post the latest
         update tx you know about, using the "spend the funding tx via
	 key path" partial signature

       - otherwise, trace the children of the funding tx, so you can see
         the most recent published state:
	   - if that's newer than the latest state you know about, your
	     info is out of date (restored from an old backup?), and you
	     have to wait for your counterparty to post the settlement tx
	   - if it's equal to the latest state you know about, wait
	   - if it's older than the latest state, post the latest update
	     tx (via the NOINPUT script path sig), and wait

       - once the CSV delay for the latest update tx has expired, post
	 the corresponding settlement tx (key path if the update tx
	 spent the funding tx, NOINPUT if the update tx spent an earlier
	 update tx)

       - once the settlement tx is posted, claim your funds

So the cases look like:

   mutual close:
     funding tx -> claimed funds

     -- only see one key via muSig, single signature, SIGHASH_ALL
     -- if there are active HTLCs when closing the channel, and they
        timeout, then the claiming tx will likely be one-in, one-out,
	SIGHASH_ALL, with a locktime, which may be unusual enough to
	indicate a lightning channel.

   unilateral close, no cheating: 
     funding tx -> update N -> settlement N -> claimed funds

     -- update N is probably SINGLE|ANYONECANPAY, so chain analysis
        of accompanying inputs might reveal who closed the channel
     -- settlement N has relative timelock
     -- claimed funds may have timelocks if they claim active HTLCs via
        the refund path
     -- no NOINPUT signatures needed, and all signatures use the key path
        so don't reveal any scripts

   unilateral close, attempted cheating:
     funding tx -> update K -> update N -> settlement N -> claimed funds

     -- update K, update N are probably SINGLE|ANYONECANPAY, so chain
        analysis might reveal the identity of both sides of the channel 
     -- update N and settlement N both use NOINPUT signatures and
        reveal CLTV script that looks like eltoo
     -- update N has timelock set
     -- settlement N has a relative timelock
     -- claimed funds may have timelocks if they claim active HTLCs via
        the refund path

     Notes:
      * cheating isn't 100% accurate: could be due to someone having to
        restore from an old backup

      * you could end up with:

          funding tx -> update K -> update W -> update N
	             -> settlement N -> claimed funds

	if someone restored from an old backup and posted K, a watchtower
	had a newer but not current state W, and finally you posted
	state N directly. with multiple watchtowers you might have more
	intermediate states' update tx's posted. afaics it has similar
	privacy results to the 2-update-tx case.

> So the restriction to add a non-NOINPUT sig in addition to a NOINPUT sig is still output tagging, as a cooperative close would still reveal that the output is not a 2-of-2.

With the above setup, you don't discover that NOINPUT was possible unless it
is actually needed because someone cheated.

As long as you're using muSig key path spending for a cooperative close,
you're not even revealing the output is 2-of-2, let alone a weird
2-of-2 variant.

> Ideally, historical data of whether onchain coin was used in Lightning or not should be revealed as little as possible.
> So in a cooperative close (which we hope, to be a common case), ideally the spend should look no different from an ordinary 2-of-2 spend.

With taproot, the goal is it shouldn't look different from an ordinary
"pay to public key" spend, and I think that's pretty achievable.

> Of course if the channel is published on Lightning, those who participated in Lightning at the time will learn of it, but at least the effort to remember this information is on those who want to remember this fact.

Well, presumaby lightning will continue to support private channels that
don't get published, and the concern's definitely valid for them!

> Now, this can be worked around by adding a "kickoff" transaction that spends the eltoo setup transaction.
> The eltoo setup transaction outputs to an ordinary 2-of-2.
> The kickoff outputs to an output that allows NOINPUT.
> Then the rest of the protocol anchors on top of the kickoff.
> [...]

I think this is possible too, but I think the scheme I describe above
is superior: iit means calculating a few more signatures each update,
but keeps more information off chain, which is better for privacy, and
probably cheaper (unless you have very high-frequency channel updates?).

Cheers,
aj



 permalink raw reply	[|nested]
2019-03-13 11:10   ` Anthony Towns

  2019-03-14  7:24       ` Anthony Towns
  
From: ZmnSCPxj @ 2019-03-14  5:22 UTC (permalink / raw)
  To: Anthony Towns;  bitcoin-dev, lightning-dev

Good morning aj,

When reading through your original post I saw you mentioned something about output tagging somehow conflicting with Taproot, so I assumed Taproot is not useable in this case.
However, it is probably more likely that I simply misunderstood what you said, so if you can definitively say that it would be possible to hide the clause "or a NOINPUT sig from A with a non-NOINPUT sig from B" behind a Taproot then I am fine.

Minor pointless reactions:

> 5.  if you're using scriptless scripts to do HTLCs, you'll need to
>     allow for NOINPUT sigs when claiming funds as well (and update
>     the partial signatures for the non-NOINPUT cases if you want to
>     maximise privacy), which is a bit fiddly

If I remember accurately, we do not allow bilateral/cooperative close when HTLC is in-flight.
However, I notice that later you point out that a non-cheating unilateral close does not need NOINPUT, so I suppose. the above thought applies to that case.


Regards,
ZmnSCPxj


 permalink raw reply	[|nested]
2019-03-14  5:22     ` ZmnSCPxj

  2019-03-14  7:55         ` ZmnSCPxj
  2019-03-14 12:00         ` Christian Decker
  
From: Anthony Towns @ 2019-03-14  7:24 UTC (permalink / raw)
  To: ZmnSCPxj;  bitcoin-dev, lightning-dev

On Thu, Mar 14, 2019 at 05:22:59AM +0000, ZmnSCPxj via Lightning-dev wrote:
> When reading through your original post I saw you mentioned something about output tagging somehow conflicting with Taproot, so I assumed Taproot is not useable in this case.

I'm thinking of tagged outputs as "taproot plus" (ie, plus noinput),
so if you used a tagged output, you could do everything normal taproot
address could, but also do noinput sigs for them.

So you might have:

   funding tx -> cooperative claim

   funding tx -> update 3 [TAGGED] -> settlement 3 -> claim

   funding tx -> update 3 [TAGGED] -> 
                 update 4 [TAGGED,NOINPUT] -> 
		 settlement 4 [TAGGED,NOINPUT] -> 
		 claim [NOINPUT]

In the cooperative case, no output tagging needed.

For the unilateral case, you need to tag all the update tx's, because
they *could* be spend by a later update with a NOINPUT sig, and if
that actually happens, then the settlement tx also needs to use a
NOINPUT sig, and if you're using scriptless scripts to resolve HTLCs,
claiming/refunding the HTLCs needs a partially-pre-signed tx which also
needs to be a NOINPUT sig, meaning the settlement tx also needs to be
tagged in that case.

You'd only need the script path for the last case where there actually
are multiple updates, but because you have to have a tagged output in the
second case anyway, maybe you've already lost privacy and always using
NOINPUT and the script path for update and settlement tx's would be fine.

> However, it is probably more likely that I simply misunderstood what you said, so if you can definitively say that it would be possible to hide the clause "or a NOINPUT sig from A with a non-NOINPUT sig from B" behind a Taproot then I am fine.

Yeah, that's my thinking.

> Minor pointless reactions:
> > 5.  if you're using scriptless scripts to do HTLCs, you'll need to
> >     allow for NOINPUT sigs when claiming funds as well (and update
> >     the partial signatures for the non-NOINPUT cases if you want to
> >     maximise privacy), which is a bit fiddly
> If I remember accurately, we do not allow bilateral/cooperative close when HTLC is in-flight.
> However, I notice that later you point out that a non-cheating unilateral close does not need NOINPUT, so I suppose. the above thought applies to that case.

Yeah, exactly.

Trying to maximise privacy there has the disadvantage that you have to
do a new signature for every in-flight HTLC every time you update the
state, which could be a lot of signatures for very active channels.

Cheers,
aj



 permalink raw reply	[|nested]
2019-03-14  7:24       ` Anthony Towns

  2019-03-14 12:00         ` Christian Decker
  
From: ZmnSCPxj @ 2019-03-14  7:55 UTC (permalink / raw)
  To: Anthony Towns;  bitcoin-dev, lightning-dev

Good morning aj,

>
> Trying to maximise privacy there has the disadvantage that you have to
> do a new signature for every in-flight HTLC every time you update the
> state, which could be a lot of signatures for very active channels.

If I remember accurately this is already true for current Poon-Dryja channels in BOLT 1.0, so at least it is not a degradation of performance.
It does make this modified form of Decker-Russell-Osuntokun much less attractive for use with DLC as the Fulgurite effort would like, but the Fulgurite effort already mitigates this by splitting a channel into two sub-channels (one for high-activity LN payments, one for rare-activity DLC bets) anyway.

Regards,
ZmnSCPxj



 permalink raw reply	[|nested]
2019-03-14  7:24       ` Anthony Towns
  2019-03-14  7:55         ` ZmnSCPxj

  
From: Christian Decker @ 2019-03-14 12:00 UTC (permalink / raw)
  To: Anthony Towns, ZmnSCPxj;  bitcoin-dev, lightning-dev

Anthony Towns <aj@erisian•com.au> writes:
> I'm thinking of tagged outputs as "taproot plus" (ie, plus noinput),
> so if you used a tagged output, you could do everything normal taproot
> address could, but also do noinput sigs for them.
>
> So you might have:
>
>    funding tx -> cooperative claim
>
>    funding tx -> update 3 [TAGGED] -> settlement 3 -> claim
>
>    funding tx -> update 3 [TAGGED] -> 
>                  update 4 [TAGGED,NOINPUT] -> 
> 		 settlement 4 [TAGGED,NOINPUT] -> 
> 		 claim [NOINPUT]
>
> In the cooperative case, no output tagging needed.

I might be missing something here, but how do you bind update 3 to the
funding tx output, when that output is not tagged? Do we keep each
update in multiple separate states, one bound to the funding tx output
and another signed with noinput? If that's the case we just doubled our
storage and communication requirements for very little gain. An
alternative is to add a trigger transaction that needs to be published
in a unilateral case, but that'd increase our on-chain footprint.


 permalink raw reply	[|nested]
2019-03-13  1:41 [bitcoin-dev] More thoughts on NOINPUT safety Anthony Towns
  2019-03-13  6:41 ` [bitcoin-dev] [Lightning-dev] " ZmnSCPxj

  2019-03-20  3:33   ` Rusty Russell
  
From: Rusty Russell @ 2019-03-20  0:22 UTC (permalink / raw)
  To: Anthony Towns, bitcoin-dev;  lightning-dev

Anthony Towns <aj@erisian•com.au> writes:
> If you publish to the blockchain:
...
> 4 can be dropped, state 5 and finish can be altered). Since the CSV delay
> is chosen by the participants, the above is still a possible scenario
> in eltoo, though, and it means there's some risk for someone accepting
> bitcoins that result from a non-cooperative close of an eltoo channel.

AJ, this was a meandering random walk which shed very little light.

I don't find the differentiation between malicious and non-malicious
double-spends convincing.  Even if you trust A, you already have to
worry about person-who-sent-the-coins-to-A.  This expands that set to be
"miner who mined coins sent-to-A", but it's very hard to see what
difference that makes to how you'd handle coins from A.

> Beyond that, I think NOINPUT has two fundamental ways to cause problems
> for the people doing NOINPUT sigs:
>
>  1) your signature gets applied to a unexpectedly different
>     script, perhaps making it look like you've being dealing
>     with some blacklisted entity. OP_MASK and similar solves
>     this.

... followed by two paragraphs describing how it's not a "fundamental
way to cause problems" that you (or I) can see.

> For the second case, that seems a little more concerning. The nightmare
> scenario is maybe something like:
>
>  * naive users do silly things with NOINPUT signatures, and end up
>    losing funds due to replays like the above

As we've never seen with SIGHASH_NONE?

>  * initial source of funds was some major exchange, who decide it's
>    cheaper to refund the lost funds than deal with the customer complaints
>
>  * the lost funds end up costing enough that major exchanges just outright
>    ban sending funds to any address capable of NOINPUT, which also bans
>    all taproot/schnorr addresses

I don't find this remotely credible.

> FWIW, I don't have a strong opinion here yet, but:
>
>  - I'm still inclined to err on the side of putting more safety
>    measures in for NOINPUT, rather than fewer

In theory, sure.  But not feel-good and complex "safety measures" which
don't actually help in practical failure scenarios.

>  - the "must have a sig that commits to the input tx" seems like it
>    should be pretty safe, not too expensive, and keeps taproot's privacy
>    benefits in the cases where you end up needing to use NOINPUT

If this is considered necessary, can it be a standardness rule rather
than consensus?

Thanks,
Rusty.


 permalink raw reply	[|nested]
2019-03-20  0:22 ` Rusty Russell

  2019-03-20  7:38     ` ZmnSCPxj
  
From: Rusty Russell @ 2019-03-20  3:33 UTC (permalink / raw)
  To: Anthony Towns, bitcoin-dev;  lightning-dev

Sorry AJ, my prior email was not constructive :(

I consider the "my software reused my keys" the most reasonable attack
scenario, though still small compared to other lightning attack surfaces.

But I understand the general wariness of third-parties reusing
SIGHASH_NOINPUT signatures.

Since "must have a non-SIGHASH_NOINPUT" rule addresses the first reuse
scenario (as well as the second), I'd be content with that proposal.
Future segwit versions may choose to relax it.[1]

Cheers,
Rusty.
[1] Must be consensus, not standardness; my prev suggestion was bogus.

Rusty Russell <rusty@rustcorp•com.au> writes:
> Anthony Towns <aj@erisian•com.au> writes:
>> If you publish to the blockchain:
> ...
>> 4 can be dropped, state 5 and finish can be altered). Since the CSV delay
>> is chosen by the participants, the above is still a possible scenario
>> in eltoo, though, and it means there's some risk for someone accepting
>> bitcoins that result from a non-cooperative close of an eltoo channel.
>
> AJ, this was a meandering random walk which shed very little light.
>
> I don't find the differentiation between malicious and non-malicious
> double-spends convincing.  Even if you trust A, you already have to
> worry about person-who-sent-the-coins-to-A.  This expands that set to be
> "miner who mined coins sent-to-A", but it's very hard to see what
> difference that makes to how you'd handle coins from A.
>
>> Beyond that, I think NOINPUT has two fundamental ways to cause problems
>> for the people doing NOINPUT sigs:
>>
>>  1) your signature gets applied to a unexpectedly different
>>     script, perhaps making it look like you've being dealing
>>     with some blacklisted entity. OP_MASK and similar solves
>>     this.
>
> ... followed by two paragraphs describing how it's not a "fundamental
> way to cause problems" that you (or I) can see.
>
>> For the second case, that seems a little more concerning. The nightmare
>> scenario is maybe something like:
>>
>>  * naive users do silly things with NOINPUT signatures, and end up
>>    losing funds due to replays like the above
>
> As we've never seen with SIGHASH_NONE?
>
>>  * initial source of funds was some major exchange, who decide it's
>>    cheaper to refund the lost funds than deal with the customer complaints
>>
>>  * the lost funds end up costing enough that major exchanges just outright
>>    ban sending funds to any address capable of NOINPUT, which also bans
>>    all taproot/schnorr addresses
>
> I don't find this remotely credible.
>
>> FWIW, I don't have a strong opinion here yet, but:
>>
>>  - I'm still inclined to err on the side of putting more safety
>>    measures in for NOINPUT, rather than fewer
>
> In theory, sure.  But not feel-good and complex "safety measures" which
> don't actually help in practical failure scenarios.
>
>>  - the "must have a sig that commits to the input tx" seems like it
>>    should be pretty safe, not too expensive, and keeps taproot's privacy
>>    benefits in the cases where you end up needing to use NOINPUT
>
> If this is considered necessary, can it be a standardness rule rather
> than consensus?
>
> Thanks,
> Rusty.


 permalink raw reply	[|nested]
2019-03-20  3:33   ` Rusty Russell

  2019-03-20  8:07       ` ZmnSCPxj
  
From: ZmnSCPxj @ 2019-03-20  7:38 UTC (permalink / raw)
  To: Rusty Russell;  bitcoin-dev, lightning-dev

Hi all,

> Since "must have a non-SIGHASH_NOINPUT" rule addresses the first reuse
> scenario (as well as the second), I'd be content with that proposal.

How would this work with watchtowers?

As I understand it, the current plan for eltoo watchtowers would be to store both `SIGHASH_NOINPUT` signatures from both sides in the blob sent to the watchtower.

Then the watchtower can always attach this to whatever is the tipmost available on the chain of transactions.

However, if one of the signatures MUST be non-`SIGHASH_NOINPUT` --- how does the watchtower create such a non-`SIGHASH_NOINPUT` signature?

Regards,
ZmnSCPxj


> Future segwit versions may choose to relax it.[1]
>
> Cheers,
> Rusty.
> [1] Must be consensus, not standardness; my prev suggestion was bogus.
>
> Rusty Russell rusty@rustcorp•com.au writes:
>
> > Anthony Towns aj@erisian•com.au writes:
> >
> > > If you publish to the blockchain:
> > > ...
> > > 4 can be dropped, state 5 and finish can be altered). Since the CSV delay
> > > is chosen by the participants, the above is still a possible scenario
> > > in eltoo, though, and it means there's some risk for someone accepting
> > > bitcoins that result from a non-cooperative close of an eltoo channel.
> >
> > AJ, this was a meandering random walk which shed very little light.
> > I don't find the differentiation between malicious and non-malicious
> > double-spends convincing. Even if you trust A, you already have to
> > worry about person-who-sent-the-coins-to-A. This expands that set to be
> > "miner who mined coins sent-to-A", but it's very hard to see what
> > difference that makes to how you'd handle coins from A.
> >
> > > Beyond that, I think NOINPUT has two fundamental ways to cause problems
> > > for the people doing NOINPUT sigs:
> > >
> > > 1.  your signature gets applied to a unexpectedly different
> > >     script, perhaps making it look like you've being dealing
> > >     with some blacklisted entity. OP_MASK and similar solves
> > >     this.
> > >
> >
> > ... followed by two paragraphs describing how it's not a "fundamental
> > way to cause problems" that you (or I) can see.
> >
> > > For the second case, that seems a little more concerning. The nightmare
> > > scenario is maybe something like:
> > >
> > > -   naive users do silly things with NOINPUT signatures, and end up
> > >     losing funds due to replays like the above
> > >
> >
> > As we've never seen with SIGHASH_NONE?
> >
> > > -   initial source of funds was some major exchange, who decide it's
> > >     cheaper to refund the lost funds than deal with the customer complaints
> > >
> > > -   the lost funds end up costing enough that major exchanges just outright
> > >     ban sending funds to any address capable of NOINPUT, which also bans
> > >     all taproot/schnorr addresses
> > >
> >
> > I don't find this remotely credible.
> >
> > > FWIW, I don't have a strong opinion here yet, but:
> > >
> > > -   I'm still inclined to err on the side of putting more safety
> > >     measures in for NOINPUT, rather than fewer
> > >
> >
> > In theory, sure. But not feel-good and complex "safety measures" which
> > don't actually help in practical failure scenarios.
> >
> > > -   the "must have a sig that commits to the input tx" seems like it
> > >     should be pretty safe, not too expensive, and keeps taproot's privacy
> > >     benefits in the cases where you end up needing to use NOINPUT
> > >
> >
> > If this is considered necessary, can it be a standardness rule rather
> > than consensus?
> > Thanks,
> > Rusty.
>
> Lightning-dev mailing list
> Lightning-dev@lists•linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev




 permalink raw reply	[|nested]
2019-03-20  7:38     ` ZmnSCPxj

  2019-03-21  8:37         ` Johnson Lau
  2019-03-21  9:06         ` Anthony Towns
  
From: ZmnSCPxj @ 2019-03-20  8:07 UTC (permalink / raw)
  To: ZmnSCPxj;  bitcoin-dev, lightning-dev

Hi aj,

Re-reading again, I think perhaps I was massively confused by this:

> - alternatively, we could require every script to have a valid signature
> that commits to the input. In that case, you could do eltoo with a
> script like either:
>
> <A> CHECKSIGVERIFY <B> CHECKSIG
> or <P> CHECKSIGVERIFY <Q> CHECKSIG
>
>
> where A is Alice's key and B is Bob's key, P is muSig(A,B) and Q is
> a key they both know the private key for. In the first case, Alice
> would give Bob a NOINPUT sig for the tx, and when Bob wanted to publish
> Bob would just do a SIGHASH_ALL sig with his own key. In the second,
> Alice and Bob would share partial NOINPUT sigs of the tx with P, and
> finish that when they wanted to publish.

Do you mean that *either* of the above two scripts is OK, *or* do you mean they are alternatives within a single MAST or `OP_IF`?

If you mean that *either* of the above two scripts is OK, then this script:

    <muSig(A,B)> CHECKVERIFY <Q> CHECKSIG

should probably be used for Watchtower-compatibility.

When creating a new state, both A and B would cooperatively sign with `muSig(A,B)` with a `SIGHASH_NOINPUT` that ensures the state transaction is correct.
Then they somehow derive or share the private key to `Q`.

In the blob sent to Watchtower, A (or B) includes the `SIGHASH_NOINPUT` as well as the `q` private key.
Would it be safe for Watchtower to know that?

Note that the above `Q` would need to be the same in the "state" trunk of the Decker-Russell-Osuntokun construction.

So, building this, our initial setup transaction pays out to script:

    <muSig(A_u,B_u)> CHECKVERIFY <Q> CHECKSIG

Then each update transaction pays out to:

    OP_IF
        <csv_delta> OP_CSV OP_DROP
        <muSig(A_si,B_si)> OP_CHECKSIGVERIFY <Q> OP_CHECKSIG
    OP_ELSE
        <i> OP_CHECKLOCKTIMEVERIFY OP_DROP
        <muSig(A_u,B_u)> OP_CHECKSIGVERIFY <Q> OP_CHECKSIG
    OP_ENDIF

The `SIGHASH_NOINPUT` signature for `muSig(A_u,B_u)` would then be sufficient to unlock the setup transaction, or any update transaction with lower `nLockTime`.
The watchtower would then have to generate the signature for `Q`, committing to a particular UTXO.

Regards,
ZmnSCPxj


Sent with ProtonMail Secure Email.

‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Wednesday, March 20, 2019 3:38 PM, ZmnSCPxj via Lightning-dev <lightning-dev@lists•linuxfoundation.org> wrote:

> Hi all,
>
> > Since "must have a non-SIGHASH_NOINPUT" rule addresses the first reuse
> > scenario (as well as the second), I'd be content with that proposal.
>
> How would this work with watchtowers?
>
> As I understand it, the current plan for eltoo watchtowers would be to store both `SIGHASH_NOINPUT` signatures from both sides in the blob sent to the watchtower.
>
> Then the watchtower can always attach this to whatever is the tipmost available on the chain of transactions.
>
> However, if one of the signatures MUST be non-`SIGHASH_NOINPUT` --- how does the watchtower create such a non-`SIGHASH_NOINPUT` signature?
>
> Regards,
> ZmnSCPxj
>
> > Future segwit versions may choose to relax it.[1]
> > Cheers,
> > Rusty.
> > [1] Must be consensus, not standardness; my prev suggestion was bogus.
> > Rusty Russell rusty@rustcorp•com.au writes:
> >
> > > Anthony Towns aj@erisian•com.au writes:
> > >
> > > > If you publish to the blockchain:
> > > > ...
> > > > 4 can be dropped, state 5 and finish can be altered). Since the CSV delay
> > > > is chosen by the participants, the above is still a possible scenario
> > > > in eltoo, though, and it means there's some risk for someone accepting
> > > > bitcoins that result from a non-cooperative close of an eltoo channel.
> > >
> > > AJ, this was a meandering random walk which shed very little light.
> > > I don't find the differentiation between malicious and non-malicious
> > > double-spends convincing. Even if you trust A, you already have to
> > > worry about person-who-sent-the-coins-to-A. This expands that set to be
> > > "miner who mined coins sent-to-A", but it's very hard to see what
> > > difference that makes to how you'd handle coins from A.
> > >
> > > > Beyond that, I think NOINPUT has two fundamental ways to cause problems
> > > > for the people doing NOINPUT sigs:
> > > >
> > > > 1.  your signature gets applied to a unexpectedly different
> > > >     script, perhaps making it look like you've being dealing
> > > >     with some blacklisted entity. OP_MASK and similar solves
> > > >     this.
> > > >
> > >
> > > ... followed by two paragraphs describing how it's not a "fundamental
> > > way to cause problems" that you (or I) can see.
> > >
> > > > For the second case, that seems a little more concerning. The nightmare
> > > > scenario is maybe something like:
> > > >
> > > > -   naive users do silly things with NOINPUT signatures, and end up
> > > >     losing funds due to replays like the above
> > > >
> > >
> > > As we've never seen with SIGHASH_NONE?
> > >
> > > > -   initial source of funds was some major exchange, who decide it's
> > > >     cheaper to refund the lost funds than deal with the customer complaints
> > > >
> > > > -   the lost funds end up costing enough that major exchanges just outright
> > > >     ban sending funds to any address capable of NOINPUT, which also bans
> > > >     all taproot/schnorr addresses
> > > >
> > >
> > > I don't find this remotely credible.
> > >
> > > > FWIW, I don't have a strong opinion here yet, but:
> > > >
> > > > -   I'm still inclined to err on the side of putting more safety
> > > >     measures in for NOINPUT, rather than fewer
> > > >
> > >
> > > In theory, sure. But not feel-good and complex "safety measures" which
> > > don't actually help in practical failure scenarios.
> > >
> > > > -   the "must have a sig that commits to the input tx" seems like it
> > > >     should be pretty safe, not too expensive, and keeps taproot's privacy
> > > >     benefits in the cases where you end up needing to use NOINPUT
> > > >
> > >
> > > If this is considered necessary, can it be a standardness rule rather
> > > than consensus?
> > > Thanks,
> > > Rusty.
> >
> > Lightning-dev mailing list
> > Lightning-dev@lists•linuxfoundation.org
> > https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev
>
> Lightning-dev mailing list
> Lightning-dev@lists•linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev




 permalink raw reply	[|nested]
2019-03-20  8:07       ` ZmnSCPxj

  2019-03-21  9:06         ` Anthony Towns
  
From: Johnson Lau @ 2019-03-21  8:37 UTC (permalink / raw)
  To: ZmnSCPxj, bitcoin-dev;  lightning-dev

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



> On 20 Mar 2019, at 4:07 PM, ZmnSCPxj via bitcoin-dev <bitcoin-dev@lists•linuxfoundation.org> wrote:
> 
> Hi aj,
> 
> Re-reading again, I think perhaps I was massively confused by this:
> 
>> - alternatively, we could require every script to have a valid signature
>> that commits to the input. In that case, you could do eltoo with a
>> script like either:
>> 
>> <A> CHECKSIGVERIFY <B> CHECKSIG
>> or <P> CHECKSIGVERIFY <Q> CHECKSIG
>> 
>> 
>> where A is Alice's key and B is Bob's key, P is muSig(A,B) and Q is
>> a key they both know the private key for. In the first case, Alice
>> would give Bob a NOINPUT sig for the tx, and when Bob wanted to publish
>> Bob would just do a SIGHASH_ALL sig with his own key. In the second,
>> Alice and Bob would share partial NOINPUT sigs of the tx with P, and
>> finish that when they wanted to publish.
> 
> Do you mean that *either* of the above two scripts is OK, *or* do you mean they are alternatives within a single MAST or `OP_IF`?
> 

It means either.

If you use <A> CHECKSIGVERIFY <B> CHECKSIG style, A and B will exchange the NOINPUT sig, and they will add the required non-NOINPUT sig when needed.

If you use <muSig(A,B)> CHECKVERIFY <Q> CHECKSIG, A and B will co-sign the muSig(A,B) with NOINPUT. They will also share the private key of Q, so they could produce a non-NOINPUT sig when needed.

The first style is slightly easier as it doesn’t need muSig. But with 3 or more parties, the second style is more efficient.

However, if you use watchtower, you have to use the second style. That means you need to share the private key for Q with the watchtower, That also means the watchtower will have the ability to reply the NOINPU muSig. But it is still strictly better than anyone-can-replay.


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

 permalink raw reply	[|nested]
2019-03-20  8:07       ` ZmnSCPxj
  2019-03-21  8:37         ` Johnson Lau

  2019-03-21 10:05           ` ZmnSCPxj
  
From: Anthony Towns @ 2019-03-21  9:06 UTC (permalink / raw)
  To: ZmnSCPxj;  bitcoin-dev, lightning-dev

On Wed, Mar 20, 2019 at 08:07:00AM +0000, ZmnSCPxj via Lightning-dev wrote:
> Re-reading again, I think perhaps I was massively confused by this:
> > that commits to the input. In that case, you could do eltoo with a
> > script like either:
> > <A> CHECKSIGVERIFY <B> CHECKSIG
> > or <P> CHECKSIGVERIFY <Q> CHECKSIG
> Do you mean that *either* of the above two scripts is OK, *or* do you mean they are alternatives within a single MAST or `OP_IF`?

I meant "either of the two scripts is okay".

> In the blob sent to Watchtower, A (or B) includes the `SIGHASH_NOINPUT` as well as the `q` private key.
> Would it be safe for Watchtower to know that?

I think so. From Alice/Bob's point-of-view, the NOINPUT sig ensures they
control their money; and from the network's point-of-view (or at least
that part of the network that thinks NOINPUT is unsafe) the Q private
key being shared makes the tx no worse than a 1-of-n multisig setup,
which has to be dealt with anyway.

> Then each update transaction pays out to:
>     OP_IF
>         <csv_delta> OP_CSV OP_DROP
>         <muSig(A_si,B_si)> OP_CHECKSIGVERIFY <Q> OP_CHECKSIG
>     OP_ELSE
>         <i> OP_CHECKLOCKTIMEVERIFY OP_DROP
>         <muSig(A_u,B_u)> OP_CHECKSIGVERIFY <Q> OP_CHECKSIG
>     OP_ENDIF

Yeah.

I think we could potentially make that shorter still:

   IF OP_CODESEPARATOR <i> OP_CHECKLOCKTIMEVERIFY OP_DROP ENDIF
   <muSig(A_u,B_u)> OP_CHECKDLSVERIFY <Q> OP_CHECKDLS

Signing with NOINPUT,NOSCRIPT and codeseparatorpos=1 enforces CLTV
and allows binding to any prior update tx -- so works for an update tx
spending previous update txs; while signing with codeseparatorpos=-1
and NOINPUT but committing to the script code and nSequence (for the
CSV delay) allows binding to only that update tx -- so works for the
settlement tx. That's two pubkeys, two sigs, and the taproot point
reveal.

Cheers,
aj



 permalink raw reply	[|nested]
2019-03-21  9:06         ` Anthony Towns

  2019-03-21 11:55             ` Anthony Towns
  
From: ZmnSCPxj @ 2019-03-21 10:05 UTC (permalink / raw)
  To: Anthony Towns;  bitcoin-dev, lightning-dev

Good morning aj,

> > Then each update transaction pays out to:
> > OP_IF
> > <csv_delta> OP_CSV OP_DROP
> > <muSig(A_si,B_si)> OP_CHECKSIGVERIFY <Q> OP_CHECKSIG
> > OP_ELSE
> > <i> OP_CHECKLOCKTIMEVERIFY OP_DROP
> > <muSig(A_u,B_u)> OP_CHECKSIGVERIFY <Q> OP_CHECKSIG
> > OP_ENDIF
>
> Yeah.
>
> I think we could potentially make that shorter still:
>
> IF OP_CODESEPARATOR <i> OP_CHECKLOCKTIMEVERIFY OP_DROP ENDIF
> <muSig(A_u,B_u)> OP_CHECKDLSVERIFY <Q> OP_CHECKDLS
>
> Signing with NOINPUT,NOSCRIPT and codeseparatorpos=1 enforces CLTV
> and allows binding to any prior update tx -- so works for an update tx
> spending previous update txs; while signing with codeseparatorpos=-1
> and NOINPUT but committing to the script code and nSequence (for the
> CSV delay) allows binding to only that update tx -- so works for the
> settlement tx. That's two pubkeys, two sigs, and the taproot point
> reveal.


Actually, the shared keys are different in the two branches above.
The "update" branch (which has no `OP_CSV`) uses the same constant `A_u` and `B_u` points.
The "state commit" branch (which has `OP_CSV`) uses different `A_si` and `B_si` points depending on `i` (state/sequence number).

Also, I cannot understand `OP_CODESEPARATOR`, please no.

Regards,
ZmnSCPxj


 permalink raw reply	[|nested]
2019-03-21 10:05           ` ZmnSCPxj

  2019-03-22  1:59               ` ZmnSCPxj
  
From: Anthony Towns @ 2019-03-21 11:55 UTC (permalink / raw)
  To: ZmnSCPxj;  bitcoin-dev, lightning-dev

On Thu, Mar 21, 2019 at 10:05:09AM +0000, ZmnSCPxj wrote:
> > IF OP_CODESEPARATOR <i> OP_CHECKLOCKTIMEVERIFY OP_DROP ENDIF
> > <muSig(A_u,B_u)> OP_CHECKDLSVERIFY <Q> OP_CHECKDLS
> > Signing with NOINPUT,NOSCRIPT and codeseparatorpos=1 enforces CLTV
> > and allows binding to any prior update tx -- so works for an update tx
> > spending previous update txs; while signing with codeseparatorpos=-1
> > and NOINPUT but committing to the script code and nSequence (for the
> > CSV delay) allows binding to only that update tx -- so works for the
> > settlement tx. That's two pubkeys, two sigs, and the taproot point
> > reveal.
> 
> Actually, the shared keys are different in the two branches above.

Yes, if you're not committing to the script code you need the separate
keys as otherwise any settlement transaction could be used with any
update transaction. 

If you are committing to the script code, though, then each settlement
sig is already only usable with the corresponding update tx, so you
don't need to roll the keys. But you do need to make it so that the
update sig requires the CLTV; one way to do that is using codeseparator
to distinguish between the two cases.

> Also, I cannot understand `OP_CODESEPARATOR`, please no.

If codeseparator is too scary, you could probably also just always
require the locktime (ie for settlmenet txs as well as update txs), ie:

  OP_CHECKLOCKTIMEVERIFY OP_DROP
  <muSig(A_u,B_u)> OP_CHECKDLSVERIFY <Q> OP_CHECKDLS

and have update txs set their timelock; and settlement txs set a absolute
timelock, relative timelock via sequence, and commit to the script code.

(Note that both those approaches (with and without codesep) assume there's
some flag that allows you to commit to the scriptcode even though you're
not committing to your input tx (and possibly not committing to the
scriptpubkey). BIP118 doesn't have that flexibility, so the A_s_i and
B_s_i key rolling is necessary)

Cheers,
aj



 permalink raw reply	[|nested]
2019-03-21 11:55             ` Anthony Towns

  2019-03-22  2:58                 ` Anthony Towns
  2019-03-22  4:23                 ` Johnson Lau
  
From: ZmnSCPxj @ 2019-03-22  1:59 UTC (permalink / raw)
  To: Anthony Towns;  bitcoin-dev, lightning-dev

Good morning aj,
>
> If you are committing to the script code, though, then each settlement
> sig is already only usable with the corresponding update tx, so you
> don't need to roll the keys. But you do need to make it so that the
> update sig requires the CLTV; one way to do that is using codeseparator
> to distinguish between the two cases.
>
> > Also, I cannot understand `OP_CODESEPARATOR`, please no.
>
> If codeseparator is too scary, you could probably also just always
> require the locktime (ie for settlmenet txs as well as update txs), ie:
>
> OP_CHECKLOCKTIMEVERIFY OP_DROP
> <muSig(A_u,B_u)> OP_CHECKDLSVERIFY <Q> OP_CHECKDLS
>
> and have update txs set their timelock; and settlement txs set a absolute
> timelock, relative timelock via sequence, and commit to the script code.
>
> (Note that both those approaches (with and without codesep) assume there's
> some flag that allows you to commit to the scriptcode even though you're
> not committing to your input tx (and possibly not committing to the
> scriptpubkey). BIP118 doesn't have that flexibility, so the A_s_i and
> B_s_i key rolling is necessary)

I think the issue I have here is the lack of `OP_CSV` in the settlement branch.

Consider a channel with offchain transactions update-1, settlement-1, update-2, and settlement-2.
If update-1 is placed onchain, update-1 is also immediately spendable by settlement-1.
But settlement-1 cannot be spent by update-2 and thus the invalidation of older state fails.

The `OP_CSV` in the settlement branch of the update transaction outputs exists to allow later update transactions have higher priority over settlement transactions.

To ensure that a settlement signature can only take the settlement branch, we need a distinct public key for the branch, so at least `A_s` and `B_s` without rolling them for each `i`, if we use `nLockTime` on the settlement transactions and enforce it with `OP_CHECKLOCKTIMEVERIFY`.
It might be possible to do this with `OP_CODESEPARATOR`, but we do need the `OP_CSV` in the settlement branch.

Regards,
ZmnSCPxj


 permalink raw reply	[|nested]
2019-03-22  1:59               ` ZmnSCPxj

  2019-03-22  7:46                   ` ZmnSCPxj
  2019-03-22  4:23                 ` Johnson Lau
  
From: Anthony Towns @ 2019-03-22  2:58 UTC (permalink / raw)
  To: ZmnSCPxj;  bitcoin-dev, lightning-dev

On Fri, Mar 22, 2019 at 01:59:14AM +0000, ZmnSCPxj wrote:
> > If codeseparator is too scary, you could probably also just always
> > require the locktime (ie for settlmenet txs as well as update txs), ie:
> > OP_CHECKLOCKTIMEVERIFY OP_DROP
> > <muSig(A_u,B_u)> OP_CHECKDLSVERIFY <Q> OP_CHECKDLS
> > and have update txs set their timelock; and settlement txs set a absolute
> > timelock, relative timelock via sequence, and commit to the script code.
> 
> I think the issue I have here is the lack of `OP_CSV` in the settlement branch.

You can enforce the relative timelock in the settlement branch simply
by refusing to sign a settlement tx that doesn't have the timelock set;
the OP_CSV is redundant.

> Consider a channel with offchain transactions update-1, settlement-1, update-2, and settlement-2.
> If update-1 is placed onchain, update-1 is also immediately spendable by settlement-1.

settlement-1 was signed by you, and when you signed it you ensured that
nsequence was set as per BIP-68, and NOINPUT sigs commit to nsequence,
so if anyone changed that after the fact the sig isn't valid. Because
BIP-68 is enforced by consensus, update-1 isn't immediately spendable
by settlement-1.

Cheers,
aj



 permalink raw reply	[|nested]
2019-03-22  1:59               ` ZmnSCPxj
  2019-03-22  2:58                 ` Anthony Towns

  
From: Johnson Lau @ 2019-03-22  4:23 UTC (permalink / raw)
  To: ZmnSCPxj, bitcoin-dev;  lightning-dev

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



> On 22 Mar 2019, at 9:59 AM, ZmnSCPxj via bitcoin-dev <bitcoin-dev@lists•linuxfoundation.org> wrote:
> 
> Good morning aj,
>> 
>> If you are committing to the script code, though, then each settlement
>> sig is already only usable with the corresponding update tx, so you
>> don't need to roll the keys. But you do need to make it so that the
>> update sig requires the CLTV; one way to do that is using codeseparator
>> to distinguish between the two cases.
>> 
>>> Also, I cannot understand `OP_CODESEPARATOR`, please no.
>> 
>> If codeseparator is too scary, you could probably also just always
>> require the locktime (ie for settlmenet txs as well as update txs), ie:
>> 
>> OP_CHECKLOCKTIMEVERIFY OP_DROP
>> <muSig(A_u,B_u)> OP_CHECKDLSVERIFY <Q> OP_CHECKDLS
>> 
>> and have update txs set their timelock; and settlement txs set a absolute
>> timelock, relative timelock via sequence, and commit to the script code.
>> 
>> (Note that both those approaches (with and without codesep) assume there's
>> some flag that allows you to commit to the scriptcode even though you're
>> not committing to your input tx (and possibly not committing to the
>> scriptpubkey). BIP118 doesn't have that flexibility, so the A_s_i and
>> B_s_i key rolling is necessary)
> 
> I think the issue I have here is the lack of `OP_CSV` in the settlement branch.
> 
> Consider a channel with offchain transactions update-1, settlement-1, update-2, and settlement-2.
> If update-1 is placed onchain, update-1 is also immediately spendable by settlement-1.
> But settlement-1 cannot be spent by update-2 and thus the invalidation of older state fails.
> 
> The `OP_CSV` in the settlement branch of the update transaction outputs exists to allow later update transactions have higher priority over settlement transactions.
> 
> To ensure that a settlement signature can only take the settlement branch, we need a distinct public key for the branch, so at least `A_s` and `B_s` without rolling them for each `i`, if we use `nLockTime` on the settlement transactions and enforce it with `OP_CHECKLOCKTIMEVERIFY`.
> It might be possible to do this with `OP_CODESEPARATOR`, but we do need the `OP_CSV` in the settlement branch.
> 
> Regards,
> ZmnSCPxj
> _______________________________________________
> bitcoin-dev mailing list
> bitcoin-dev@lists•linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev <https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev>

OP_CSV (BIP112) is not needed. Only BIP68 relative-time is needed.

With this script:

<t> OP_CHECKLOCKTIMEVERIFY OP_DROP <muSig(A,B)> OP_CHECKSIGVERIFY <Q> OP_CHECKSIG

For update purpose, A and B will co-sign the muSig with nLockTime = t, not committing to the scriptCode, and no BIP68 lock time

For settlement purpose, A and B will co-sign the muSig with nLockTime = t, committing to the scriptCode, and with an agreed BIP68 locktime

Without committing to the scriptCode and BIP68 lock time, the update sig could be bind to any previous update tx immediately.

OTOH, the settlement sig will only bind to a specific update tx (thought scriptCode), and only after the relative locktime is passed.

The eltoo paper is wrong about using OP_CSV. That’s a common mistake even for experienced bitcoin developer. OP_CSV is needed only if one party could single handedly decide the relative-lock-time. However, this is not the case here as it is a muSig.

(With some risks of distracting the discussion, please note that even this script: <t> OP_CHECKLOCKTIMEVERIFY OP_DROP <A> OP_CHECKSIGVERIFY <B> OP_CHECKSIG doesn’t need OP_CSV, despite not using muSig. It is because the 2 sigs must use the same relative locktime, or the tx is invalid.)

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

 permalink raw reply	[|nested]
2019-03-22  2:58                 ` Anthony Towns

  
From: ZmnSCPxj @ 2019-03-22  7:46 UTC (permalink / raw)
  To: Anthony Towns;  bitcoin-dev, lightning-dev

Good morning aj,

I understand.
Looks like that makes sense.
It seems possible to use this, then, together with watchtowers.

Regards,
ZmnSCPxj


Sent with ProtonMail Secure Email.

‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Friday, March 22, 2019 10:58 AM, Anthony Towns <aj@erisian•com.au> wrote:

> On Fri, Mar 22, 2019 at 01:59:14AM +0000, ZmnSCPxj wrote:
>
> > > If codeseparator is too scary, you could probably also just always
> > > require the locktime (ie for settlmenet txs as well as update txs), ie:
> > > OP_CHECKLOCKTIMEVERIFY OP_DROP
> > > <muSig(A_u,B_u)> OP_CHECKDLSVERIFY <Q> OP_CHECKDLS
> > > and have update txs set their timelock; and settlement txs set a absolute
> > > timelock, relative timelock via sequence, and commit to the script code.
> >
> > I think the issue I have here is the lack of `OP_CSV` in the settlement branch.
>
> You can enforce the relative timelock in the settlement branch simply
> by refusing to sign a settlement tx that doesn't have the timelock set;
> the OP_CSV is redundant.
>
> > Consider a channel with offchain transactions update-1, settlement-1, update-2, and settlement-2.
> > If update-1 is placed onchain, update-1 is also immediately spendable by settlement-1.
>
> settlement-1 was signed by you, and when you signed it you ensured that
> nsequence was set as per BIP-68, and NOINPUT sigs commit to nsequence,
> so if anyone changed that after the fact the sig isn't valid. Because
> BIP-68 is enforced by consensus, update-1 isn't immediately spendable
> by settlement-1.
>
> Cheers,
> aj




 permalink raw reply	[|nested]