Anthony Towns [ARCHIVE] on Nostr: 📅 Original date posted:2022-12-07 📝 Original message: Hi all, On the eltoo irc ...
📅 Original date posted:2022-12-07
📝 Original message:
Hi all,
On the eltoo irc channel we discussed optimising eltoo for the 2-party
scenario; figured it was probably worth repeating that here.
This is similar to:
- 2018-07-18, simplified eltoo: https://lists.linuxfoundation.org/pipermail/lightning-dev/2018-July/001363.html
- 2021-09-17, IID 2Stage, https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-September/019470.html
- 2022-09-29, Daric: https://eprint.iacr.org/2022/1295
- 2022-10-21, eltoo/chia: https://twitter.com/bramcohen/status/1583122833932099585
The basic idea is "if it's a two party channel with just Alice and Bob,
then if Alice starts a unilateral close, then she's already had her say,
so it's only Bob's opinion that matters from now on, and he should be
able to act immediately", and once it's only Bob's opinion that matters,
you can simplify a bunch of things.
A "gist" for this idea is https://gist.github.com/ajtowns/53e0f735f4d5c06a681429d937200aa5 (it goes into a little more detail in places, though doesn't cover trustless watchtowers at all).
In particular, there are a few practical constraints that we might like
to consider for 2-party channels with eltoo:
- fast forwards: we might want to allow our channel partner
to immediately rely on a new state we propose without needing a
round-trip delay -- this potentially makes forwarding payments much
faster (though with some risk of locking the funds up, if you do a
fast forward to someone who's gone offline)
- doubled delays: once we publish the latest state we can, we want to
be able to claim the funds immediately after to_self_delay expires;
however if our counterparty has signatures for a newer state than we
do (which will happen if it was fast forwarded), they could post that
state shortly before to_self_delay expires, potentially increasing
the total delay to 2*to_self_delay.
- penalties: when you do a unilateral close, attempting to cheat comes
with no cost to you and a possible benefit if you succeed, but
potentially does cost your channel partner (either in forcing them
to spend on-chain fees to update to the correct state, or in the risk
of loss if their node malfunctions occassionally) -- a penalty could
reduce this incentive to cheat
- trustless watchtowers: we may want to consider the possibility of a
watchtower holding onto obsolete states and colluding with an
attacker to attempt to cheat us
What follows is a rough approach for dealing with all those issues for
two-party channels. It's spelled out in a little more detail in the gist.
(I think for initial eltoo experimentation it doesn't make sense to try to
deal with all (or perhaps any) of those constraints; simple and working
is better than complex and theoretical. But having them written down so
the ideas can be thought about and looked up later still seems useful)
In more detail: unilateral closes are handled by each channel participant
maintaining five transactions, which we'll call:
* UA.n, UB.n : unilaterally propose closing at state n
- this is for Alice or Bob to spend the funding tx for a unilater
close to state n. Spends the funding transaction.
* WA.n, WB.n : watchtower update to state n
- this is for an untrusted watchtower to correct attempted cheating
by Bob on behalf of Alice (or vice-versa). Spends UB.k or WA.k
(or UA.k/WB.k) respectively, provided k < n.
* CA.n, CB.n : cooperatively claim funds according to state n
- this is for Alice to confirm Bob's unilateral close (or vice-versa).
Spends UB.k, WA.k (or UA.k/WB.k respectively), provided k <= n
* SA.n, SB.n : slowly claim funds according to state n
- this is for Alice to claim her funds if Bob is completely offline
(or vice-versa). Spends UA.n, UB.n, WA.n or WB.n with relative
timelock of to_self_delay.
* RA.n, RB.n : claim funds with penalty after unilateral close to
revoked state
- this is for Alice to update the state if Bob attempted to cheat
(or vice-versa). Spends UB.k or WA.k (or UA.k/WB.k respectively)
conditional on k < n - 1; outputs are adjusted to transfer a fixed
penalty of penalty_msat from Bob's balance to Alice's (or vice-versa)
Each of these "transactions" requires a pre-signed signature; however
the actual transaction/txid will vary in cases where a transaction has
the possibility of spending different inputs (eg "Spends UB.k or WA.k").
In particular UA.n/UB.n can be constructed with known txids and non-APO
signatures but WA.n/WB.n/CA.n/CB.n/SA.n/SB.n/RA.n/RB.n all require
APO signatures.
They're named such that Alice can immediately broadcast all the *A.n
transactions (provided a tx that it can spend has been broadcast) and
Bob can likewise immediately broadcast all the *B.n transactions.
Scenarios where Alice decides to unilaterally close the channel might
look like:
* if Alice/Bob can't communicate directly, but both are online:
F -> UA.n -> CB.n -> money
(balances and htlcs claimed, no delay)
* if Bob has gone offline entirely:
F -> UA.n -> (to_self_delay) -> SA.n -> money
* Alice cheats, Bob punishes:
F -> UA.k -> RB.n -> money[Alice pays Bob penalty]
* Bob is offline, Alice cheats, but Bob has a watchtower:
F -> UA.k -> WB.n -> (to_self_delay) -> SA.n -> money
* Alice and Bob's watchtower collude, but Bob's not offline:
F -> UA.k1 -> WB.k2 -> RB.n -> money[Alice pays Bob penalty]
* Alice and Bob's watchtower collude, but Bob has many watchtowers:
F -> UA.k1 -> WB.k2 -> WB.n -> (to_self_delay) -> SA.n -> money
For Alice to successfully cheat, she needs Bob to be offline for at least
to_self_delay, and for all Bob's watchtowers to either also be offline,
or colluding.
This can be simplified somewhat, if you don't care about all the features:
* If you don't care about trustless watchtowers you can drop WA.n/WB.n
(and simplify SA.n/SB.n to not require an APO signature)
* If you don't care about penalties you can set penalty_msat to 0 and
allow RA.n/RB.n to spend k<=n. In this case, you can either drop
CA.n/CB.n entirely, or you can have CA.n/CB.n only be used for directly
spending of UB.n/UA.n and thus not require APO signatures
In order to allow fast-forwards, when Alice proposes a new state,
she needs to send her partial signatures to allow Bob to unilaterally
accept the new state, ie sigs for: UB.n, CB.n, SB.n, RB.n. But she
also needs to be able to claim the funds if Bob proposes the new state
and broadcasts UB.n, she needs to be able broadcast CA.n. This can be
achieved with an adaptor signature approach (spelt out a bit more fully
in the gist) or a CTV-like approach, provided that UB.n reveals the
state needed to calculate the the CTV commitment (see "EXPR_SETTLE" in
https://github.com/instagibbs/bolts/blob/29fe6d36cbad4101d5ec76c2b19c83c1494ac2fc/XX-eltoo-transactions.md).
Note that in this scenario Alice doesn't provide WB.n to Bob
immediately. This is okay, as if Alice proposes UA.(n-1) (her most
recent state), Bob can still immediately claim via CA.n. If Bob did have
WB.n; then if Alice proposed UA.(n-1) Bob could wait for an initial
to_self_delay period and broadcast WB.n, forcing Alice to wait for an
additional to_self_delay before being able to claim her funds via SA.n.
Note also that this is why RA.n/RB.n require "k < n - 1" -- otherwise
Alice would only be able to broadcast UA.(n-1) and Bob would immediately
be able to penalise by broadcasting RB.n.
Note that if you're using a watchtower and wish to punish your
counterparty if it attempts to cheat, you should only pass WA.(n-2)
to your watchtowers, not WA.(n-1) or WA.n.
This doesn't address any potential issues from:
* how to add fees -- the U/W transactions are 1-in/1-out transactions
that can't be trivially CPFPed by the proposer and need to have
fees added (either SINGLE/ANYONECANPAY signatures or having a 0-sat
ephemeral output and package relay might be workable); the C/S/R
transactions are 1-in/many-out transactions, but have balance outputs
that can be immediately spent to pay for fees via CPFP if package
relay is available.
* how to pay watchtowers -- when a watchtower broadcasts a W
transaction, it needs to add fees, and it's not clear (to me) how it
could fairly and reliably ensure it's compensated for those costs,
particularly if multiple W transactions are broadcast for a single
unilateral close attempt, due to one or more watchtowers colluding
with an attacker, or simply having out of date information.
* lack of layered transactions -- while this prevents you having to
wait longer than to_self_delay before you can claim channel funds,
it still means that any htlc that is going to timeout sooner than that
may not be claimable on-chain, meaning you need to set
cltv_expiry_delta >= to_self_delay.
* extending to multiparty channels -- penalising is hard if there's
more than two parties, fast forwards are probably impossible since
you need multiple round-trips to coordinate signatures anyway, and if
you're doing channels-within-channels to reduce your n-party channel
to an easier to update 2-party channel you're probably forced to have
to_self_delay for each layer of channels. Also, just figuring out how
to coordinate multiparty state updates and even keeping everyone in
a multiparty channel online consistently to generate new signatures
seems potentially hard?
Cheers,
aj
📝 Original message:
Hi all,
On the eltoo irc channel we discussed optimising eltoo for the 2-party
scenario; figured it was probably worth repeating that here.
This is similar to:
- 2018-07-18, simplified eltoo: https://lists.linuxfoundation.org/pipermail/lightning-dev/2018-July/001363.html
- 2021-09-17, IID 2Stage, https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-September/019470.html
- 2022-09-29, Daric: https://eprint.iacr.org/2022/1295
- 2022-10-21, eltoo/chia: https://twitter.com/bramcohen/status/1583122833932099585
The basic idea is "if it's a two party channel with just Alice and Bob,
then if Alice starts a unilateral close, then she's already had her say,
so it's only Bob's opinion that matters from now on, and he should be
able to act immediately", and once it's only Bob's opinion that matters,
you can simplify a bunch of things.
A "gist" for this idea is https://gist.github.com/ajtowns/53e0f735f4d5c06a681429d937200aa5 (it goes into a little more detail in places, though doesn't cover trustless watchtowers at all).
In particular, there are a few practical constraints that we might like
to consider for 2-party channels with eltoo:
- fast forwards: we might want to allow our channel partner
to immediately rely on a new state we propose without needing a
round-trip delay -- this potentially makes forwarding payments much
faster (though with some risk of locking the funds up, if you do a
fast forward to someone who's gone offline)
- doubled delays: once we publish the latest state we can, we want to
be able to claim the funds immediately after to_self_delay expires;
however if our counterparty has signatures for a newer state than we
do (which will happen if it was fast forwarded), they could post that
state shortly before to_self_delay expires, potentially increasing
the total delay to 2*to_self_delay.
- penalties: when you do a unilateral close, attempting to cheat comes
with no cost to you and a possible benefit if you succeed, but
potentially does cost your channel partner (either in forcing them
to spend on-chain fees to update to the correct state, or in the risk
of loss if their node malfunctions occassionally) -- a penalty could
reduce this incentive to cheat
- trustless watchtowers: we may want to consider the possibility of a
watchtower holding onto obsolete states and colluding with an
attacker to attempt to cheat us
What follows is a rough approach for dealing with all those issues for
two-party channels. It's spelled out in a little more detail in the gist.
(I think for initial eltoo experimentation it doesn't make sense to try to
deal with all (or perhaps any) of those constraints; simple and working
is better than complex and theoretical. But having them written down so
the ideas can be thought about and looked up later still seems useful)
In more detail: unilateral closes are handled by each channel participant
maintaining five transactions, which we'll call:
* UA.n, UB.n : unilaterally propose closing at state n
- this is for Alice or Bob to spend the funding tx for a unilater
close to state n. Spends the funding transaction.
* WA.n, WB.n : watchtower update to state n
- this is for an untrusted watchtower to correct attempted cheating
by Bob on behalf of Alice (or vice-versa). Spends UB.k or WA.k
(or UA.k/WB.k) respectively, provided k < n.
* CA.n, CB.n : cooperatively claim funds according to state n
- this is for Alice to confirm Bob's unilateral close (or vice-versa).
Spends UB.k, WA.k (or UA.k/WB.k respectively), provided k <= n
* SA.n, SB.n : slowly claim funds according to state n
- this is for Alice to claim her funds if Bob is completely offline
(or vice-versa). Spends UA.n, UB.n, WA.n or WB.n with relative
timelock of to_self_delay.
* RA.n, RB.n : claim funds with penalty after unilateral close to
revoked state
- this is for Alice to update the state if Bob attempted to cheat
(or vice-versa). Spends UB.k or WA.k (or UA.k/WB.k respectively)
conditional on k < n - 1; outputs are adjusted to transfer a fixed
penalty of penalty_msat from Bob's balance to Alice's (or vice-versa)
Each of these "transactions" requires a pre-signed signature; however
the actual transaction/txid will vary in cases where a transaction has
the possibility of spending different inputs (eg "Spends UB.k or WA.k").
In particular UA.n/UB.n can be constructed with known txids and non-APO
signatures but WA.n/WB.n/CA.n/CB.n/SA.n/SB.n/RA.n/RB.n all require
APO signatures.
They're named such that Alice can immediately broadcast all the *A.n
transactions (provided a tx that it can spend has been broadcast) and
Bob can likewise immediately broadcast all the *B.n transactions.
Scenarios where Alice decides to unilaterally close the channel might
look like:
* if Alice/Bob can't communicate directly, but both are online:
F -> UA.n -> CB.n -> money
(balances and htlcs claimed, no delay)
* if Bob has gone offline entirely:
F -> UA.n -> (to_self_delay) -> SA.n -> money
* Alice cheats, Bob punishes:
F -> UA.k -> RB.n -> money[Alice pays Bob penalty]
* Bob is offline, Alice cheats, but Bob has a watchtower:
F -> UA.k -> WB.n -> (to_self_delay) -> SA.n -> money
* Alice and Bob's watchtower collude, but Bob's not offline:
F -> UA.k1 -> WB.k2 -> RB.n -> money[Alice pays Bob penalty]
* Alice and Bob's watchtower collude, but Bob has many watchtowers:
F -> UA.k1 -> WB.k2 -> WB.n -> (to_self_delay) -> SA.n -> money
For Alice to successfully cheat, she needs Bob to be offline for at least
to_self_delay, and for all Bob's watchtowers to either also be offline,
or colluding.
This can be simplified somewhat, if you don't care about all the features:
* If you don't care about trustless watchtowers you can drop WA.n/WB.n
(and simplify SA.n/SB.n to not require an APO signature)
* If you don't care about penalties you can set penalty_msat to 0 and
allow RA.n/RB.n to spend k<=n. In this case, you can either drop
CA.n/CB.n entirely, or you can have CA.n/CB.n only be used for directly
spending of UB.n/UA.n and thus not require APO signatures
In order to allow fast-forwards, when Alice proposes a new state,
she needs to send her partial signatures to allow Bob to unilaterally
accept the new state, ie sigs for: UB.n, CB.n, SB.n, RB.n. But she
also needs to be able to claim the funds if Bob proposes the new state
and broadcasts UB.n, she needs to be able broadcast CA.n. This can be
achieved with an adaptor signature approach (spelt out a bit more fully
in the gist) or a CTV-like approach, provided that UB.n reveals the
state needed to calculate the the CTV commitment (see "EXPR_SETTLE" in
https://github.com/instagibbs/bolts/blob/29fe6d36cbad4101d5ec76c2b19c83c1494ac2fc/XX-eltoo-transactions.md).
Note that in this scenario Alice doesn't provide WB.n to Bob
immediately. This is okay, as if Alice proposes UA.(n-1) (her most
recent state), Bob can still immediately claim via CA.n. If Bob did have
WB.n; then if Alice proposed UA.(n-1) Bob could wait for an initial
to_self_delay period and broadcast WB.n, forcing Alice to wait for an
additional to_self_delay before being able to claim her funds via SA.n.
Note also that this is why RA.n/RB.n require "k < n - 1" -- otherwise
Alice would only be able to broadcast UA.(n-1) and Bob would immediately
be able to penalise by broadcasting RB.n.
Note that if you're using a watchtower and wish to punish your
counterparty if it attempts to cheat, you should only pass WA.(n-2)
to your watchtowers, not WA.(n-1) or WA.n.
This doesn't address any potential issues from:
* how to add fees -- the U/W transactions are 1-in/1-out transactions
that can't be trivially CPFPed by the proposer and need to have
fees added (either SINGLE/ANYONECANPAY signatures or having a 0-sat
ephemeral output and package relay might be workable); the C/S/R
transactions are 1-in/many-out transactions, but have balance outputs
that can be immediately spent to pay for fees via CPFP if package
relay is available.
* how to pay watchtowers -- when a watchtower broadcasts a W
transaction, it needs to add fees, and it's not clear (to me) how it
could fairly and reliably ensure it's compensated for those costs,
particularly if multiple W transactions are broadcast for a single
unilateral close attempt, due to one or more watchtowers colluding
with an attacker, or simply having out of date information.
* lack of layered transactions -- while this prevents you having to
wait longer than to_self_delay before you can claim channel funds,
it still means that any htlc that is going to timeout sooner than that
may not be claimable on-chain, meaning you need to set
cltv_expiry_delta >= to_self_delay.
* extending to multiparty channels -- penalising is hard if there's
more than two parties, fast forwards are probably impossible since
you need multiple round-trips to coordinate signatures anyway, and if
you're doing channels-within-channels to reduce your n-party channel
to an easier to update 2-party channel you're probably forced to have
to_self_delay for each layer of channels. Also, just figuring out how
to coordinate multiparty state updates and even keeping everyone in
a multiparty channel online consistently to generate new signatures
seems potentially hard?
Cheers,
aj