More thoughts on NOINPUT safety
19 messages, 13 to 22 Mar 2019. Started by Anthony Towns.
ZmnSCPxj (8), Anthony Towns (6), Rusty Russell (2), Johnson Lau (2), Christian Decker
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
Good morning aj,
First off, I have little to no idea of the issues at the lower-level Bitcoin.
In any case ---
Quoted text (29 lines)
> - 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
On Wed, Mar 13, 2019 at 06:41:47AM +0000, ZmnSCPxj via Lightning-dev wrote:
Quoted text (14 lines)
> > - 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.
Quoted text (1 line)
> 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.
Quoted text (2 lines)
> 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.
Quoted text (1 line)
> 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!
Quoted text (5 lines)
> 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
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:
Quoted text (4 lines)
> 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
On Thu, Mar 14, 2019 at 05:22:59AM +0000, ZmnSCPxj via Lightning-dev wrote:
Quoted text (1 line)
> 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.
Quoted text (1 line)
> 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.
Quoted text (7 lines)
> 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
Good morning aj,
Quoted text (4 lines)
> > 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
Anthony Towns <aj@erisian•com•au> writes:
Quoted text (16 lines)
> 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.
Anthony Towns <aj@erisian•com•au> writes:
Quoted text (1 line)
> If you publish to the blockchain:
...
Quoted text (4 lines)
> 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.
Quoted text (7 lines)
> 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.
Quoted text (5 lines)
> 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?
Quoted text (6 lines)
> * 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.
Quoted text (4 lines)
> 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.
Quoted text (3 lines)
> - 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.
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:
Quoted text (61 lines)
> 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.
Hi all,
Quoted text (2 lines)
> 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
Quoted text (77 lines)
> 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
Hi aj,
Re-reading again, I think perhaps I was massively confused by this:
Quoted text (14 lines)
> - 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:
Quoted text (95 lines)
> 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
Quoted text (23 lines)
> 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.
On Wed, Mar 20, 2019 at 08:07:00AM +0000, ZmnSCPxj via Lightning-dev wrote:
Quoted text (6 lines)
> 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".
Quoted text (2 lines)
> 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.
Quoted text (8 lines)
> 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
Good morning aj,
Quoted text (23 lines)
> > 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
On Thu, Mar 21, 2019 at 10:05:09AM +0000, ZmnSCPxj wrote:
Quoted text (11 lines)
> > 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.
Quoted text (1 line)
> 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
Good morning aj,
Quoted text (23 lines)
> > 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
On Fri, Mar 22, 2019 at 01:59:14AM +0000, ZmnSCPxj wrote:
Quoted text (8 lines)
> > 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.
Quoted text (2 lines)
> 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
Quoted text (44 lines)
> 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.)
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:
Quoted text (26 lines)
> 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