Return-Path: Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 302AFFFE for ; Tue, 20 Feb 2018 22:42:24 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-ua0-f175.google.com (mail-ua0-f175.google.com [209.85.217.175]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id B1B44466 for ; Tue, 20 Feb 2018 22:42:21 +0000 (UTC) Received: by mail-ua0-f175.google.com with SMTP id i15so9461737uak.3 for ; Tue, 20 Feb 2018 14:42:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to; bh=D+Ao4tdtbT7YJokj5xphKUVqVnyHJwqclfSGABSx3xs=; b=sUbie12E0yrM5rsVTeDkFuSnTh62GpQlbYLTh5oShLkcU++wq9FoEiJkRRz6XN3M+d BLyJp6EUqBBkNhO/a2V6H47TtWXgPp2gMNy86h6BykRhyCqZnCsCNnaTHlObCHCYYWHD PyPQGehTih8iQi4Ph/s1my8404L9pI7j9bhcTd4Kl2rdrYKt6my8AQWSQ/w53ogOob/t WACfEV7uTifiR47pw3ilj42HFw8GoPfOPELOp+zAO3CWcEa3+T4+cEz/13slQDvfic7w zrViqaq81o7pnjJY+eF0BSP8ID6Wg4ivY9rRsKsPz45+Nz3baMQuexr2ythRW36AcGks zQbw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to; bh=D+Ao4tdtbT7YJokj5xphKUVqVnyHJwqclfSGABSx3xs=; b=NRh/s1+SGUdxLWEmapGkSWae+j4Kj+k1mL+qKA2Aa9aGajrvsiYA0MtovME7Tc8IgY cEu7BmoRwJcyEBMmXVcbzLUprsn4ETv2JRrTZA2sj7gA9jnzDx5+PQB68tJIZO+wNhuu dFbcMdkPyNedBOF6Clhy4uj12qGCX7BKfaRUDJgTkBLlq36KT2fy9P7TXplk/F7s9VSp LFqG/VlN/wg4Ef4AR19sDhXExWHGPPjUODWSFL0O8s+apdjv0CbsJ/GhbpIDVs/8kGbY +IV3bc4e1a1ODhffYBeheRZiuiXJpXdmqfBnsPQq7UyciFIpXaioFyvuANcg8/8AKjUE iOsw== X-Gm-Message-State: APf1xPDaqRj9DeqK4d3hscd77ssrJiM/Yg8yzS6OfJ0hofSwAPJJgucf uZZV6gFQH3pFtM90ELA36wwimESI76fps09wj2F/5w== X-Google-Smtp-Source: AH8x227q5Ovfd3yqqxIHODv57PQD3omUB/7wzazfS2Phs4cinZuFVp3+T2qumMHM9gZ6FTdXQNCyI9MYaZMS/uY2ic4= X-Received: by 10.159.54.47 with SMTP id r44mr984673uad.133.1519166540463; Tue, 20 Feb 2018 14:42:20 -0800 (PST) MIME-Version: 1.0 Received: by 10.176.22.133 with HTTP; Tue, 20 Feb 2018 14:42:19 -0800 (PST) In-Reply-To: <20180219225907.GA16444@erisian.com.au> References: <20180219225907.GA16444@erisian.com.au> From: Bryan Bishop Date: Tue, 20 Feb 2018 16:42:19 -0600 Message-ID: To: Bitcoin Dev , Bryan Bishop Content-Type: multipart/alternative; boundary="001a1147b016ffc54b0565ac85bc" X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, HTML_MESSAGE, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [bitcoin-dev] Fwd: [Lightning-dev] Post-Schnorr lightning txes X-BeenThere: bitcoin-dev@lists.linuxfoundation.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: Bitcoin Protocol Discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Feb 2018 22:42:24 -0000 --001a1147b016ffc54b0565ac85bc Content-Type: text/plain; charset="UTF-8" ---------- Forwarded message ---------- From: Anthony Towns Date: Mon, Feb 19, 2018 at 4:59 PM Subject: [Lightning-dev] Post-Schnorr lightning txes To: lightning-dev@lists.linuxfoundation.org Hi *, My understanding of lightning may be out of date, so please forgive (or at least correct :) any errors on my behalf. I was thinking about whether Greg Maxwell's graftroot might solve the channel monitoring problem (spoiler: not really) and ended up with maybe an interesting take on Schnorr. I don't think I've seen any specific writeup of what that might look like, so hopefully at least some of this is novel! I'm assuming familiarity with current thinking on Schnorr sigs -- but all you should need to know is the quick summary at footnote [0]. So I think there's four main scenarios for closing a lightning channel: - both parties are happy to close, do so cooperatively, and can sign a new unconditional transaction that they agree on. already fine. (should happen almost all of the time, call it 80%) - communications failure: one side has to close, but the other side is happy to cooperate as far as they're able but can only do so via the blockchain and maybe with some delay (maybe 15% of the time) - disappearance, uncooperative: one side effectively completely disappears so the other side has to fully close the channel on their own (5% of the time) - misbehaviour: one side tries publishing an old channel state due to error or maliciousness, and the other collects the entire balance as penalty (0% of the time) With "graftroot" in mind, I was thinking that optimising for the last case might be interesting -- despite expecting it to be vanishingly rare. That would have to look something like: (0) funding tx (1) ...which is spent by a misbehaving commitment tx (2) ...which is spent by a penalty tx You do need 3 txes for that case, but you really only need 1 output for each: so (0) is 2-in-1-out, (1) is 1-in-1-out, (2) is 1-in-1-out; which could all be relatively cheap. (And (2) could be batched with other txes making it 1 input in a potentially large tx) For concreteness, I'm going to treat A as the one doing the penalising, and B (Bad?) as the one that's misbehaving. If you treat each of those txes as a muSig Schnorr pay-to-pubkey, the output addresses would be: (0) funding tx pays to [A,B] (1) commitment tx pays to [A(i),Revocation(B,i)] (2) pays to A (where i is a commitment id / counter for the channel state) If B misbehaves by posting the commitment tx after revealing the revocation secret, A can calculate A(i) and Revocation(B,i) and claim all the funds immediately. As far as the other cases go: - In a cooperative close, you don't publish any commitment txes, you just spend the funding to each party's preferred destinations directly; so this is already great. - Otherwise, you need to be able to actually commit to how the funds get distributed. But committing to distributing funds is easy: just jointly sign a transaction with [A(i),Revocation(B,i)]. Since B is the one we're worrying about misbehaving, it needs to hold a transaction with the appropriate outputs that is: - timelocked to `to_self_delay` blocks/seconds in advance via nSequence - signed by A(i) That ensures A has `to_self_delay` blocks/seconds to penalise misehaviour, and that when closing properly, B can complete the signature using the current revocation secret. This means the "appropriate outputs" no longer need the OP_CSV step, which should simplify the scripts a bit. Having B have a distribution transaction isn't enough -- B could vanish between publishing the commitment transaction and the distribution transaction, leaving A without access to any funds. So A needs a corresponding distribution transaction. But because that transaction can only be published if B signs and publishes the corresponding commitment transaction, the fact that it's published indicates both A and B are happy with the channel close -- so this is a semi-cooperative close and no delay is needed. So A should hold a partially signed transaction with the same outputs: - without any timelock - signed by Revocation(B,i), waiting for signature by A(i) Thus, if B does a non-cooperative close, either: - A proves misbehaviour and claims all the funds immediately - A agrees that the channel state is correct, signs and publishes the un-timelocked distribution transaction, then claims A's outputs; B can then immediately claim its outputs - A does nothing, and B waits for the `to_self_delay` period, signs and publishes its transaction, then claims B's outputs; A can eventually claim its own outputs In that case all of the transactions except the in-flight HTLCs just look like simple pay-to-pubkey transactions. Further, other than the historical secrets no old information needs to be retained: misbehaviour can be dealt with (and can only be dealt with) by creating a new transaction signed by your own secrets and the revocation information. None of that actually relies on Schnorr-multisig, I think -- it could be done today with normal 2-of-2 multisig as far as I can see. I'm not 100% sure how this approach works compared to the current one for the CSV/CLTV overlap problem. I think any case you could solve by obtaining a HTLC-Timeout or HTLC-Success transaction currently, you could solve in the above scenario by just updating the channel state to remove the HTLC. So I believe the above lets you completely forget info about old HTLCs, while still enforcing correct behavior, and also makes enforcing correct behaviour cheaper because it's just two extremely simple transactions to post. If I haven't missed any corner cases, it also seems to simplify the scripts a fair bit. Does this make sense? It seems to to me... So for completeness, it would make sense to do HTLCs via Schnorr -- at least to make them reveal elliptic curve private keys, and ideally to make them mostly indistinguishable from regular transactions as a "scriptless script" [1] or "discreet log contract" [2]. (I think, at least for HTLCs, these end up being the same?) The idea then is to have the HTLC payment hash be R=r*G, where r is the secret/payment receipt. Supposing your current commitment has n HTLCs in-flight, some paying A if the HTLC succeeds and "r" is revealed, others paying B. We'll focus on one paying A. So you succeed by A completing a signature that reveals r to B, and which simultaneously allows collection of the funds on chain. A needs to be able to do this knowing nothing other than r (and their own private keys). So agree to sign to muSig 2-of-2 multisig [A,B]. A and B generate random values i and j respectively and reveal I=i*G and J=j*G, and each calculates Q=I+J+R, and they generate partial signatures of a transaction paying A: I, i + H(X,Q,m)*H(L,A)*a J, j + H(X,Q,m)*H(L,B)*b where L = H(A,B) and X = H(L,A)*A + H(L,B)*B as usual. Once A knows r, A can construct a full signature by adding R, r to the above values, and B can then determine r by subtracting the above values from signature A generated. To ensure B gets paid if the HTLC timesout, they should also sign a timelocked transaction paying B directly, that B can hold onto until the channel state gets updated. And once you're doing payment hashes via ECC, you can of course change them at each hop to make it harder to correlate steps in a payment route. I think that when combined with the above method of handling CSV delays and revocation, this covers all the needed cases with a straightforward pay-to-pubkey(hash) output, no script info needed at all. It does mean each HTLC needs a signature every time the channel state updates (B needs to sign a tx allowing A to claim the output once A knows the secret, A needs to sign a tx allowing B to claim the output on timeout). For channel monitoring this is pretty good, I think. You need to keep track of the revocation info and your secret keys -- but that's essentially a constant amount of data. If you're happy to have the data grow by 64 bytes every time the channel state updates, you can outsource channel monitoring: arrange a formula for constructing a penalty tx based on the channel commitment tx -- eg, 95% of the balance goes to me, 4% goes to the monitor's address, 1% goes to fees, there's a relative locktime of to_self_delay/3 to allow me to directly claim 100% of the funds if I happen to be paying attention; then do a partial signature with A(i), and then allow the monitoring service to catch fraudulent transactions, work out the appropriate revocation secret, and finish the signature. If your channel updates 100 times a second for an entire year, that's 200GB of data, which seems pretty feasible. (You can't just regenerate that data though, unless you keep each commitment tx) And it's pretty easy to work out which bit of data you need to access: the funding tx that's being spent tells you which channel, and the channel state index is encoded in the locktime and sequence, so you should only need small/logarithmic overhead even for frequently updated channels rather than any serious indexes. I don't think you can do better than that without serious changes to bitcoin: if you let the monitoring agency sign on its own, you'd need some sort of covenant opcode to ensure it sends any money to you; and with segwit outputs, there's no way to provide a signature for a transaction without committing to exactly which transaction you're signing. I was hoping covenants and graftroot would be enough, but I don't think they are. The idea would be that since the transaction spends to A(i)+Rev(B,i), you'd sign an output script with A that uses covenant opcodes to ensure the transaction only pays the appropriate monitoring reward, and the monitor could then work out A(i)-A and Rev(B,i) and finish the signature. But the signature by "A" would need to know A(i)+Rev(B,i) when calculating the hash, and that's different for every commitment transaction, so as far as I can see, it just doesn't work. You can't drop the muSig-style construction because you need to be protect yourself against potential malicious choice of the revocation secret [3]. Summary: - Funding txes as 2-of-2 multisig is still great. Convert to Schnorr/muSig when available of course. - Generate 6+8*n transactions everytime the channel state is updated, (n = number of HTLCs in-flight) 1. Channel state commitment tx, held by A, spends funding tx, payable to Schnorr muSig address [A(i),Rev(B,i)], signed by B 2. Channel fund distribution tx, held by A (CSV), spends (1), signed by Rev(B,i) 3. Channel fund distribution tx, held by B (no CSV), spends (1), signed by A(i) 4. Channel state commitment tx, held by B, spends funding tx payable to Schnorr muSig address [B(i),Rev(A,i)], signed by A 5. Channel fund distribution tx, held by B (CSV), spends (4), signed by Rev(A,i) 6. Channel fund distribution tx, held by A (no CSV), spends (4), signed by B(i) The fund distribution txs all pay the same collection of addresses: - channel balance for A directly to A's preferred address - channel balance for B directly to B's preferred address - HTLC balance to muSig address for [A,B] for each in-flight HTLC paying A on success - HTLC balance to muSig address for [B,A] for each in-flight HTLC paying B on success - (probably makes sense to bump the HTLC addresses by some random value to make it harder for third parties to tell which addresses were balances versus HTLCs) Both (1) and (4) include obscured channel state ids as per current standard. For each HTLC that pays X on timeout and Y on success: a. Timeout tx, held by X, signed by Y, spends from (2) b. Timeout tx, held by X, signed by Y, spends from (3) c. Timeout tx, held by X, signed by Y, spends from (5) d. Timeout tx, held by X, signed by Y, spends from (6) e. Success tx, held by Y, signed by X, spends from (2) f. Success tx, held by Y, signed by X, spends from (3) g. Success tx, held by Y, signed by X, spends from (5) h. Success tx, held by Y, signed by X, spends from (6) (these should all be able to be SIGHASH_SINGLE, ANYONECANPAY to allow some level of aggregation) - Fund distribution tx outputs can all be pay2pubkey(hash): HTLCs work by pre-signed timelocked transactions and scriptless scripts/discreet-log contracts to reveal the secret; balances work directly; CSV and revocations are already handled by that point - You can discard all old transaction info and HTLC parameters once they're not relevant to the current channel state - Channel monitoring can be outsourced pretty efficiently -- as little as a signature per state could be made to works as far as I can see, which doesn't add up too fast. - There's still no plausible way of doing constant space outsourced channel monitoring without some sort of SIGHASH_NOINPUT, at least that I can see Thoughts? [4] Cheers, aj, very sad that this didn't turn out to be a potential use case for graftroot :( [0] In particular, I'm assuming that: - Schnorr sigs in bitcoin will look something like: R, r + H(X,R,m)*x (where m is the message being signed by private key x, r is a random per-sig nonce, R and X are public keys corresponding to r,x; H is the secure hash function) - muSig is a secure way for untrusting parties to construct an n-of-n combined signature; for public keys A and B, it produces a combined public key: X = H(L,A)*A + H(L,B)*B with L = H(A,B) See https://blockstream.com/2018/01/23/musig-key-aggregation- schnorr-signatures.html [1] https://scalingbitcoin.org/stanford2017/Day2/Using-the- Chain-for-what-Chains-are-Good-For.pdf http://diyhpl.us/wiki/transcripts/scalingbitcoin/ stanford-2017/using-the-chain-for-what-chains-are-good-for/ [2] https://adiabat.github.io/dlc.pdf https://diyhpl.us/wiki/transcripts/discreet-log-contracts/ [3] Well, maybe you could request a zero-knowledge proof to ensure a new revocation hash conforms to the standard for generating revocation secrets without revealing the secret, and have the public key be a(i)*G + r(B,i)*G without using the muSig construct, but that would probably be obnoxious to have to generate every time you update the channel state. [4] As an aside -- this could make it feasible and interesting to penalise disappearance as well as misbehaviour. If you add a transaction the B pre-signs, spending the commitment tx A holds, giving all the channel funds to A but only after a very large CSV timeout, perhaps `to_self_delay`*50, then the scenarios are: If A is present: - B publishes an old commitment: A immediately steals all the funds if active or outsourced misbehaviour monitoring. Whoops! - B publishes the current commitment: A publishes its distribution transaction and collects its funds immediately, allowing B to do likewise If A has disappeared: - B publises the current commitment and waits a modest amount of time, publishes its distribution transaction claiming its rightful funds, and allowing A to collect its funds if it ever does reappear and still knows its secrets - B publishes the current commitment, waits a fair while, A reappears and publishes its distribution transactions, both parties get their rightful funds - B publishes the current commitment, waits an extended period of time, and claims the entire channel's funds. If B is particularly reputable, and A can prove its identity (but not recover all its secrets) maybe B even refunds A some/all of its rightful balance Perhaps that provides too much of an incentive to try blocking someone from having access to the blockchain though. _______________________________________________ Lightning-dev mailing list Lightning-dev@lists.linuxfoundation.org https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev -- - Bryan http://heybryan.org/ 1 512 203 0507 --001a1147b016ffc54b0565ac85bc Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable

---------- Forwarded messag= e ----------
From: Anthony Towns <aj@erisian.com.au= >
Date: Mon, Feb 19, 2018 at 4:59 PM
Subject: [Lightning-de= v] Post-Schnorr lightning txes
To: lightning-dev@lists.linuxfoundation.org

Hi *,

My understanding of lightning may be out of date, so please forgive
(or at least correct :) any errors on my behalf.

I was thinking about whether Greg Maxwell's graftroot might solve the channel monitoring problem (spoiler: not really) and ended up with maybe an interesting take on Schnorr. I don't think I've seen any specifi= c
writeup of what that might look like, so hopefully at least some of this is novel!

I'm assuming familiarity with current thinking on Schnorr sigs -- but a= ll
you should need to know is the quick summary at footnote [0].

So I think there's four main scenarios for closing a lightning channel:=

=C2=A0- both parties are happy to close, do so cooperatively, and can
=C2=A0 =C2=A0sign a new unconditional transaction that they agree on. alrea= dy fine.
=C2=A0 =C2=A0(should happen almost all of the time, call it 80%)

=C2=A0- communications failure: one side has to close, but the other side =C2=A0 =C2=A0is happy to cooperate as far as they're able but can only = do so via
=C2=A0 =C2=A0the blockchain and maybe with some delay (maybe 15% of the tim= e)

=C2=A0- disappearance, uncooperative: one side effectively completely
=C2=A0 =C2=A0disappears so the other side has to fully close the channel on= their
=C2=A0 =C2=A0own (5% of the time)

=C2=A0- misbehaviour: one side tries publishing an old channel state due to=
=C2=A0 =C2=A0error or maliciousness, and the other collects the entire bala= nce as
=C2=A0 =C2=A0penalty (0% of the time)

With "graftroot" in mind, I was thinking that optimising for the = last
case might be interesting -- despite expecting it to be vanishingly
rare. That would have to look something like:

=C2=A0 =C2=A0(0) funding tx
=C2=A0 =C2=A0(1) ...which is spent by a misbehaving commitment tx
=C2=A0 =C2=A0(2) ...which is spent by a penalty tx

You do need 3 txes for that case, but you really only need 1 output
for each: so (0) is 2-in-1-out, (1) is 1-in-1-out, (2) is 1-in-1-out;
which could all be relatively cheap. (And (2) could be batched with other txes making it 1 input in a potentially large tx)

For concreteness, I'm going to treat A as the one doing the penalising,=
and B (Bad?) as the one that's misbehaving.

If you treat each of those txes as a muSig Schnorr pay-to-pubkey, the
output addresses would be:

=C2=A0 =C2=A0(0) funding tx pays to [A,B]
=C2=A0 =C2=A0(1) commitment tx pays to [A(i),Revocation(B,i)]
=C2=A0 =C2=A0(2) pays to A

(where i is a commitment id / counter for the channel state)

If B misbehaves by posting the commitment tx after revealing the
revocation secret, A can calculate A(i) and Revocation(B,i) and claim
all the funds immediately.

As far as the other cases go:

=C2=A0 - In a cooperative close, you don't publish any commitment txes,= you
=C2=A0 =C2=A0 just spend the funding to each party's preferred destinat= ions
=C2=A0 =C2=A0 directly; so this is already great.

=C2=A0 - Otherwise, you need to be able to actually commit to how the funds=
=C2=A0 =C2=A0 get distributed.

But committing to distributing funds is easy: just jointly sign
a transaction with [A(i),Revocation(B,i)]. Since B is the one we're
worrying about misbehaving, it needs to hold a transaction with the
appropriate outputs that is:

=C2=A0 - timelocked to `to_self_delay` blocks/seconds in advance via nSeque= nce
=C2=A0 - signed by A(i)

That ensures A has `to_self_delay` blocks/seconds to penalise misehaviour,<= br> and that when closing properly, B can complete the signature using the
current revocation secret.

This means the "appropriate outputs" no longer need the OP_CSV st= ep, which
should simplify the scripts a bit.

Having B have a distribution transaction isn't enough -- B could vanish=
between publishing the commitment transaction and the distribution
transaction, leaving A without access to any funds. So A needs a
corresponding distribution transaction. But because that transaction can only be published if B signs and publishes the corresponding commitment
transaction, the fact that it's published indicates both A and B are happy with the channel close -- so this is a semi-cooperative close and
no delay is needed. So A should hold a partially signed transaction with the same outputs:

=C2=A0 - without any timelock
=C2=A0 - signed by Revocation(B,i), waiting for signature by A(i)

Thus, if B does a non-cooperative close, either:

=C2=A0 - A proves misbehaviour and claims all the funds immediately
=C2=A0 - A agrees that the channel state is correct, signs and publishes =C2=A0 =C2=A0 the un-timelocked distribution transaction, then claims A'= ;s outputs;
=C2=A0 =C2=A0 B can then immediately claim its outputs
=C2=A0 - A does nothing, and B waits for the `to_self_delay` period, signs<= br> =C2=A0 =C2=A0 and publishes its transaction, then claims B's outputs; A= can eventually
=C2=A0 =C2=A0 claim its own outputs

In that case all of the transactions except the in-flight HTLCs just look like simple pay-to-pubkey transactions.

Further, other than the historical secrets no old information needs
to be retained: misbehaviour can be dealt with (and can only be dealt
with) by creating a new transaction signed by your own secrets and the
revocation information.

None of that actually relies on Schnorr-multisig, I think -- it could
be done today with normal 2-of-2 multisig as far as I can see.



I'm not 100% sure how this approach works compared to the current one for the CSV/CLTV overlap problem. I think any case you could solve by
obtaining a HTLC-Timeout or HTLC-Success transaction currently, you could solve in the above scenario by just updating the channel state to remove the HTLC.


So I believe the above lets you completely forget info about old HTLCs,
while still enforcing correct behavior, and also makes enforcing correct behaviour cheaper because it's just two extremely simple transactions to post. If I haven't missed any corner cases, it also seems to simplif= y
the scripts a fair bit.

Does this make sense? It seems to to me...


So for completeness, it would make sense to do HTLCs via Schnorr --
at least to make them reveal elliptic curve private keys, and ideally
to make them mostly indistinguishable from regular transactions as a
"scriptless script" [1] or "discreet log contract" [2].= (I think, at
least for HTLCs, these end up being the same?)

The idea then is to have the HTLC payment hash be R=3Dr*G, where r is the secret/payment receipt.

Supposing your current commitment has n HTLCs in-flight, some paying A
if the HTLC succeeds and "r" is revealed, others paying B. We'= ;ll focus
on one paying A.

So you succeed by A completing a signature that reveals r to B,
and which simultaneously allows collection of the funds on chain. A
needs to be able to do this knowing nothing other than r (and their own
private keys). So agree to sign to muSig 2-of-2 multisig [A,B]. A and B
generate random values i and j respectively and reveal I=3Di*G and J=3Dj*G,=
and each calculates Q=3DI+J+R, and they generate partial signatures of a transaction paying A:

=C2=A0 =C2=A0 I, i + H(X,Q,m)*H(L,A)*a
=C2=A0 =C2=A0 J, j + H(X,Q,m)*H(L,B)*b

where L =3D H(A,B) and X =3D H(L,A)*A + H(L,B)*B as usual. Once A knows r,<= br> A can construct a full signature by adding R, r to the above values,
and B can then determine r by subtracting the above values from signature A generated.

To ensure B gets paid if the HTLC timesout, they should also sign a
timelocked transaction paying B directly, that B can hold onto until
the channel state gets updated.

And once you're doing payment hashes via ECC, you can of course change<= br> them at each hop to make it harder to correlate steps in a payment route.
I think that when combined with the above method of handling CSV delays
and revocation, this covers all the needed cases with a straightforward
pay-to-pubkey(hash) output, no script info needed at all. It does mean
each HTLC needs a signature every time the channel state updates (B needs to sign a tx allowing A to claim the output once A knows the secret,
A needs to sign a tx allowing B to claim the output on timeout).


For channel monitoring this is pretty good, I think. You need to
keep track of the revocation info and your secret keys -- but that's essentially a constant amount of data.

If you're happy to have the data grow by 64 bytes every time the channe= l
state updates, you can outsource channel monitoring: arrange a formula
for constructing a penalty tx based on the channel commitment tx --
eg, 95% of the balance goes to me, 4% goes to the monitor's address, 1%=
goes to fees, there's a relative locktime of to_self_delay/3 to allow m= e
to directly claim 100% of the funds if I happen to be paying attention;
then do a partial signature with A(i), and then allow the monitoring
service to catch fraudulent transactions, work out the appropriate
revocation secret, and finish the signature.

If your channel updates 100 times a second for an entire year, that's 200GB of data, which seems pretty feasible. (You can't just regenerate<= br> that data though, unless you keep each commitment tx) And it's pretty easy to work out which bit of data you need to access: the funding
tx that's being spent tells you which channel, and the channel state index is encoded in the locktime and sequence, so you should only need
small/logarithmic overhead even for frequently updated channels rather
than any serious indexes.

I don't think you can do better than that without serious changes to bitcoin: if you let the monitoring agency sign on its own, you'd need s= ome
sort of covenant opcode to ensure it sends any money to you; and with
segwit outputs, there's no way to provide a signature for a transaction=
without committing to exactly which transaction you're signing.

I was hoping covenants and graftroot would be enough, but I don't
think they are. The idea would be that since the transaction spends to
A(i)+Rev(B,i), you'd sign an output script with A that uses covenant opcodes to ensure the transaction only pays the appropriate monitoring
reward, and the monitor could then work out A(i)-A and Rev(B,i) and finish<= br> the signature. But the signature by "A" would need to know A(i)+R= ev(B,i)
when calculating the hash, and that's different for every commitment transaction, so as far as I can see, it just doesn't work. You can'= t
drop the muSig-style construction because you need to be protect yourself against potential malicious choice of the revocation secret [3].


Summary:

=C2=A0- Funding txes as 2-of-2 multisig is still great. Convert to
=C2=A0 =C2=A0Schnorr/muSig when available of course.

=C2=A0- Generate 6+8*n transactions everytime the channel state is updated,=
=C2=A0 =C2=A0(n =3D number of HTLCs in-flight)

=C2=A0 =C2=A01. Channel state commitment tx, held by A, spends funding tx,<= br> =C2=A0 =C2=A0 =C2=A0 payable to Schnorr muSig address [A(i),Rev(B,i)], sign= ed by B
=C2=A0 =C2=A02. Channel fund distribution tx, held by A (CSV), spends (1),<= br> =C2=A0 =C2=A0 =C2=A0 signed by Rev(B,i)
=C2=A0 =C2=A03. Channel fund distribution tx, held by B (no CSV), spends (1= ),
=C2=A0 =C2=A0 =C2=A0 signed by A(i)
=C2=A0 =C2=A04. Channel state commitment tx, held by B, spends funding tx =C2=A0 =C2=A0 =C2=A0 payable to Schnorr muSig address [B(i),Rev(A,i)], sign= ed by A
=C2=A0 =C2=A05. Channel fund distribution tx, held by B (CSV), spends (4),<= br> =C2=A0 =C2=A0 =C2=A0 signed by Rev(A,i)
=C2=A0 =C2=A06. Channel fund distribution tx, held by A (no CSV), spends (4= ),
=C2=A0 =C2=A0 =C2=A0 signed by B(i)

=C2=A0 =C2=A0The fund distribution txs all pay the same collection of addre= sses:
=C2=A0 =C2=A0 =C2=A0- channel balance for A directly to A's preferred a= ddress
=C2=A0 =C2=A0 =C2=A0- channel balance for B directly to B's preferred a= ddress
=C2=A0 =C2=A0 =C2=A0- HTLC balance to muSig address for [A,B] for each in-f= light HTLC
=C2=A0 =C2=A0 =C2=A0 =C2=A0paying A on success
=C2=A0 =C2=A0 =C2=A0- HTLC balance to muSig address for [B,A] for each in-f= light HTLC
=C2=A0 =C2=A0 =C2=A0 =C2=A0paying B on success
=C2=A0 =C2=A0 =C2=A0- (probably makes sense to bump the HTLC addresses by s= ome random
=C2=A0 =C2=A0 =C2=A0 =C2=A0value to make it harder for third parties to tel= l which addresses
=C2=A0 =C2=A0 =C2=A0 =C2=A0were balances versus HTLCs)

=C2=A0 =C2=A0Both (1) and (4) include obscured channel state ids as per cur= rent
=C2=A0 =C2=A0standard.

=C2=A0 =C2=A0For each HTLC that pays X on timeout and Y on success:
=C2=A0 =C2=A0 =C2=A0a. Timeout tx, held by X, signed by Y, spends from (2)<= br> =C2=A0 =C2=A0 =C2=A0b. Timeout tx, held by X, signed by Y, spends from (3)<= br> =C2=A0 =C2=A0 =C2=A0c. Timeout tx, held by X, signed by Y, spends from (5)<= br> =C2=A0 =C2=A0 =C2=A0d. Timeout tx, held by X, signed by Y, spends from (6)<= br>
=C2=A0 =C2=A0 =C2=A0e. Success tx, held by Y, signed by X, spends from (2)<= br> =C2=A0 =C2=A0 =C2=A0f. Success tx, held by Y, signed by X, spends from (3)<= br> =C2=A0 =C2=A0 =C2=A0g. Success tx, held by Y, signed by X, spends from (5)<= br> =C2=A0 =C2=A0 =C2=A0h. Success tx, held by Y, signed by X, spends from (6)<= br>
=C2=A0 =C2=A0 =C2=A0(these should all be able to be SIGHASH_SINGLE, ANYONEC= ANPAY
=C2=A0 =C2=A0 =C2=A0 to allow some level of aggregation)

=C2=A0- Fund distribution tx outputs can all be pay2pubkey(hash): HTLCs wor= k
=C2=A0 =C2=A0by pre-signed timelocked transactions and scriptless
=C2=A0 =C2=A0scripts/discreet-log contracts to reveal the secret; balances = work
=C2=A0 =C2=A0directly; CSV and revocations are already handled by that poin= t

=C2=A0- You can discard all old transaction info and HTLC parameters once =C2=A0 =C2=A0they're not relevant to the current channel state

=C2=A0- Channel monitoring can be outsourced pretty efficiently -- as littl= e as
=C2=A0 =C2=A0a signature per state could be made to works as far as I can s= ee,
=C2=A0 =C2=A0which doesn't add up too fast.

=C2=A0- There's still no plausible way of doing constant space outsourc= ed
=C2=A0 =C2=A0channel monitoring without some sort of SIGHASH_NOINPUT, at le= ast
=C2=A0 =C2=A0that I can see

Thoughts?

[4]

Cheers,
aj, very sad that this didn't turn out to be a potential use case for =C2=A0 =C2=A0 graftroot :(

[0] In particular, I'm assuming that:

=C2=A0 =C2=A0 - Schnorr sigs in bitcoin will look something like:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 R, r + H(X,R,m)*x

=C2=A0 =C2=A0 =C2=A0 (where m is the message being signed by private key x,= r is a
=C2=A0 =C2=A0 =C2=A0 random per-sig nonce, R and X are public keys correspo= nding to r,x;
=C2=A0 =C2=A0 =C2=A0 H is the secure hash function)

=C2=A0 =C2=A0 - muSig is a secure way for untrusting parties to construct a= n n-of-n
=C2=A0 =C2=A0 =C2=A0 combined signature; for public keys A and B, it produc= es a combined
=C2=A0 =C2=A0 =C2=A0 public key:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 X =3D H(L,A)*A + H(L,B)*B
=C2=A0 =C2=A0 =C2=A0 with L =3D H(A,B)

=C2=A0 =C2=A0See htt= ps://blockstream.com/2018/01/23/musig-key-aggregation-schnorr-sig= natures.html

[1] htt= ps://scalingbitcoin.org/stanford2017/Day2/Using-the-Chain-for-wha= t-Chains-are-Good-For.pdf
=C2=A0 =C2=A0 http://diyhpl.us/wiki/transcripts/scalingbitcoin= /stanford-2017/using-the-chain-for-what-chains-are-good-for/<= br>
[2] https://adiabat.github.io/dlc.pdf
=C2=A0 =C2=A0 https://diyhpl.us/wiki/= transcripts/discreet-log-contracts/

[3] Well, maybe you could request a zero-knowledge proof to ensure a new =C2=A0 =C2=A0 revocation hash conforms to the standard for generating revoc= ation
=C2=A0 =C2=A0 secrets without revealing the secret, and have the public key= be
=C2=A0 =C2=A0 a(i)*G + r(B,i)*G without using the muSig construct, but that= would
=C2=A0 =C2=A0 probably be obnoxious to have to generate every time you upda= te
=C2=A0 =C2=A0 the channel state.

[4] As an aside -- this could make it feasible and interesting to penalise<= br> =C2=A0 =C2=A0 disappearance as well as misbehaviour. If you add a transacti= on
=C2=A0 =C2=A0 the B pre-signs, spending the commitment tx A holds, giving a= ll the
=C2=A0 =C2=A0 channel funds to A but only after a very large CSV timeout, p= erhaps
=C2=A0 =C2=A0 `to_self_delay`*50, then the scenarios are:

=C2=A0 =C2=A0 If A is present:

=C2=A0 =C2=A0 =C2=A0 - B publishes an old commitment: A immediately steals = all the
=C2=A0 =C2=A0 =C2=A0 =C2=A0 funds if active or outsourced misbehaviour moni= toring. Whoops!

=C2=A0 =C2=A0 =C2=A0 - B publishes the current commitment: A publishes its = distribution
=C2=A0 =C2=A0 =C2=A0 =C2=A0 transaction and collects its funds immediately,= allowing B to
=C2=A0 =C2=A0 =C2=A0 =C2=A0 do likewise

=C2=A0 =C2=A0 If A has disappeared:

=C2=A0 =C2=A0 =C2=A0 - B publises the current commitment and waits a modest= amount
=C2=A0 =C2=A0 =C2=A0 =C2=A0 of time, publishes its distribution transaction= claiming its
=C2=A0 =C2=A0 =C2=A0 =C2=A0 rightful funds, and allowing A to collect its f= unds if it ever
=C2=A0 =C2=A0 =C2=A0 =C2=A0 does reappear and still knows its secrets

=C2=A0 =C2=A0 =C2=A0 - B publishes the current commitment, waits a fair whi= le,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 A reappears and publishes its distribution tran= sactions, both
=C2=A0 =C2=A0 =C2=A0 =C2=A0 parties get their rightful funds

=C2=A0 =C2=A0 =C2=A0 - B publishes the current commitment, waits an extende= d period
=C2=A0 =C2=A0 =C2=A0 =C2=A0 of time, and claims the entire channel's fu= nds. If B is
=C2=A0 =C2=A0 =C2=A0 =C2=A0 particularly reputable, and A can prove its ide= ntity (but not
=C2=A0 =C2=A0 =C2=A0 =C2=A0 recover all its secrets) maybe B even refunds A= some/all of its
=C2=A0 =C2=A0 =C2=A0 =C2=A0 rightful balance

=C2=A0 =C2=A0 Perhaps that provides too much of an incentive to try blockin= g
=C2=A0 =C2=A0 someone from having access to the blockchain though.

_______________________________________________
Lightning-dev mailing list
Lightning-dev@li= sts.linuxfoundation.org
https://lists.linuxfoundation.o= rg/mailman/listinfo/lightning-dev



--
- Bryan
http://heybryan.org/
1 512 203 0507
--001a1147b016ffc54b0565ac85bc--