Profile: 45050727...
📅 Original date posted:2023-10-17
🗒️ Summary of this message: Batched splicing is risky because if an old state is broadcasted and confirmed before the splice, it can disrupt the process. It is important for batched splicing mechanisms to have a backout option.
📝 Original message:
> I do not know if existing splice implementations actually perform such a
check.
Unless all splice implementations do this, then any kind of batched
splicing is risky.
As long as the implementation decides to splice again at some point when a
prior
splice isn't confirming, it will self-resolve once any subsequent splice is
confirmed.
Cheers,
Greg
On Tue, Oct 17, 2023 at 1:04 PM ZmnSCPxj via bitcoin-dev <
bitcoin-dev at lists.linuxfoundation.org> wrote:
> Good morning Bastien,
>
> I have not gotten around to posting it yet, but I have a write-up in my
> computer with the title:
>
> > Batched Splicing Considered Risky
>
> The core of the risk is that if:
>
> * I have no funds right now in a channel (e.g. the LSP allowed me to have
> 0 reserve, or this is a newly-singlefunded channel from the LSP to me).
> * I have an old state (e.g. for a newly-singlefunded channel, it could
> have been `update_fee`d, so that the initial transaction is old state).
>
> Then if I participate in a batched splice, I can disrupt the batched
> splice by broadcasting the old state and somehow convincing miners to
> confirm it before the batched splice.
>
> Thus, it is important for *any* batched splicing mechanism to have a
> backout, where if the batched splice transaction can no longer be confirmed
> due to some participant disrupting it by posting an old commitment
> transaction, either a subset of the splice is re-created or the channels
> revert back to pre-splice state (with knowledge that the post-splice state
> can no longer be confirmed).
>
> I know that current splicing tech is to run both the pre-splice and
> post-splice state simultaneously until the splicing transaction is
> confirmed.
> However we need to *also* check if the splicing transaction *cannot* be
> confirmed --- by checking if the other inputs to the splice transaction
> were already consumed by transactions that have deeply confirmed, and in
> that case, to drop the post-splice state and revert to the pre-splice state.
> I do not know if existing splice implementations actually perform such a
> check.
> Unless all splice implementations do this, then any kind of batched
> splicing is risky.
>
> Regards,
> ZmnSCPxj
>
> _______________________________________________
> bitcoin-dev mailing list
> bitcoin-dev at lists.linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
📅 Original date posted:2023-10-17
🗒️ Summary of this message: Batched splicing can be risky if not all splice implementations perform a check to ensure subsequent splices confirm, potentially leading to loss of funds.
📝 Original message:
Good morning Greg,
> > I do not know if existing splice implementations actually perform such a check.
> Unless all splice implementations do this, then any kind of batched splicing is risky.
> As long as the implementation decides to splice again at some point when a prior
> splice isn't confirming, it will self-resolve once any subsequent splice is confirmed.
Do note that there is a risk here that the reason for "not confirming" is because of an unexpected increase in mempool usage.
In particular, if the attack is not being performed, it is possible for the previous splice tx that was not confirming for a while, to be the one that confirms in the end, instead of the subsequent splice.
This is admittedly an edge case, but one that could potentially be specifically attacked and could lead to loss of funds if the implementations naively deleted the signatures for commitment transactions for the previously-not-confirming splice transaction.
Indeed, as I understood it, part of the splice proposal is that while a channel is being spliced, it should not be spliced again, which your proposal seems to violate.
Regards,
ZmnSCPxj
📅 Original date posted:2023-10-17
🗒️ Summary of this message: Batched splicing can be risky if certain conditions are met, such as having no funds in a channel and using an old state. It is important for batched splicing mechanisms to have a backout option to prevent disruptions.
📝 Original message:
Good morning Bastien,
I have not gotten around to posting it yet, but I have a write-up in my computer with the title:
> Batched Splicing Considered Risky
The core of the risk is that if:
* I have no funds right now in a channel (e.g. the LSP allowed me to have 0 reserve, or this is a newly-singlefunded channel from the LSP to me).
* I have an old state (e.g. for a newly-singlefunded channel, it could have been `update_fee`d, so that the initial transaction is old state).
Then if I participate in a batched splice, I can disrupt the batched splice by broadcasting the old state and somehow convincing miners to confirm it before the batched splice.
Thus, it is important for *any* batched splicing mechanism to have a backout, where if the batched splice transaction can no longer be confirmed due to some participant disrupting it by posting an old commitment transaction, either a subset of the splice is re-created or the channels revert back to pre-splice state (with knowledge that the post-splice state can no longer be confirmed).
I know that current splicing tech is to run both the pre-splice and post-splice state simultaneously until the splicing transaction is confirmed.
However we need to *also* check if the splicing transaction *cannot* be confirmed --- by checking if the other inputs to the splice transaction were already consumed by transactions that have deeply confirmed, and in that case, to drop the post-splice state and revert to the pre-splice state.
I do not know if existing splice implementations actually perform such a check.
Unless all splice implementations do this, then any kind of batched splicing is risky.
Regards,
ZmnSCPxj
📅 Original date posted:2023-10-17
🗒️ Summary of this message: The summary of the text is that there is a vulnerability in the Lightning Network where a node can cheat and claim funds from an HTLC transaction.
📝 Original message:
Good morning Antoine et al.,
Let me try to rephrase the core of the attack.
There exists these nodes on the LN (letters `A`, `B`, and `C` are nodes, `==` are channels):
A ===== B ===== C
`A` routes `A->B->C`.
The timelocks, for example, could be:
A->B timeelock = 144
B->C timelock = 100
The above satisfies the LN BOLT requirements, as long as `B` has a `cltv_expiry_delta` of 44 or lower.
After `B` forwards the HTLC `B->C`, C suddenly goes offline, and all the signed transactions --- commitment transaction and HTLC-timeout transactions --- are "stuck" at the feerate at the time.
At block height 100, `B` notices the `B->C` HTLC timelock is expired without `C` having claimed it, so `B` forces the `B====C` channel onchain.
However, onchain feerates have risen and the commitment transaction and HTLC-timeout transaction do not confirm.
In the mean time, `A` is still online with `B` and updates the onchain fees of the `A====B` channel pre-signed transactions (commitment tx and HTLC-timeout tx) to the latest.
At block height 144, `B` is still not able to claim the `A->B` HTLC, so `A` drops the `A====B` channel onchain.
As the fees are up-to-date, this confirms immediately and `A` is able to recover the HTLC funds.
However, the feerates of the `B====C` pre-signed transactions remain at the old, uncompetitive feerates.
At this point, `C` broadcasts an HTLC-success transaction with high feerates that CPFPs the commitment tx.
However, it replaces the HTLC-timeout transaction, which is at the old, low feerate.
`C` is thus able to get the value of the HTLC, but `B` is now no longer able to use the knowledge of the preimage, as its own incoming HTLC was already confirmed as claimed by `A`.
Is the above restatement accurate?
----
Let me also explain to non-Lightning experts why HTLC-timeout is presigned in this case and why `B` cannot feebump it.
In the Poon-Dryja mechanism, the HTLCs are "infected" by the Poon-Dryja penalty case, and are not plain HTLCs.
A plain HTLC offerred by `B` to `C` would look like this:
(B && OP_CLTV) || (C && OP_HASH160)
However, on the commitment transaction held by `B`, it would be infected by the penalty case in this way:
(B && C && OP_CLTV) || (C && OP_HASH160) || (C && revocation)
There are two changes:
* The addition of a revocation branch `C && revocation`.
* The branch claimable by `B` in the "plain" HTLC (`B && OP_CLTV`) also includes `C`.
These are necessary in case `B` tries to cheat and this HTLC is on an old, revoked transaction.
If the revoked transaction is *really* old, the `OP_CLTV` would already impose a timelock far in the past.
This means that a plain `B && OP_CLTV` branch can be claimed by `B` if it retained this very old revoked transaction.
To prevent that, `C` is added to the `B && OP_CLTV` branch.
We also introduce an HTLC-timeout transaction, which spends the `B && C && OP_CLTV` branch, and outputs to:
(B && OP_CSV) || (C && revocation)
Thus, even if `B` held onto a very old revoked commitment transaction and attempts to spend the timelock branch (because the `OP_CLTV` is for an old blockheight), it still has to contend with a new output with a *relative* timelock.
Unfortunately, this means that the HTLC-timeout transaction is pre-signed, and has a specific feerate.
In order to change the feerate, both `B` and `C` have to agree to re-sign the HTLC-timeout transaction at the higher feerate.
However, the HTLC-success transaction in this case spends the plain `(C && OP_HASH160)` branch, which only involves `C`.
This allows `C` to feebump the HTLC-success transaction arbitrarily even if `B` does not cooperate.
While anchor outputs can be added to the HTLC-timeout transaction as well, `C` has a greater advantage here due to being able to RBF the HTLC-timeout out of the way (1 transaction), while `B` has to get both HTLC-timeout and a CPFP-RBF of the anchor output of the HTLC-timeout transaction (2 transactions).
`C` thus requires a smaller fee to achieve a particular feerate due to having to push a smaller number of bytes compared to `B`.
Regards,
ZmnSCPxj
📅 Original date posted:2023-09-25
🗒️ Summary of this message: Payment pools and channel factories face limitations in interactivity, affecting the security of user funds. Proposed solutions include introducing a coordinator or partitioning balances, but these may not be economically practical. A potential solution is to prevent off-chain group equivocation by editing the funding utxo in a way that allows for the registration of new off-chain subgroups. CoinPool's idea of including user pubkeys and balance amounts in Taproot leaves could be utilized for privacy-preserving payments and contracts.
📝 Original message:
Payment pools and channel factories are afflicted by severe interactivity
constraints worsening with the number of users owning an off-chain balance
in the construction. The security of user funds is paramount on the ability
to withdraw unilaterally from the off-chain construction. As such any
update applied to the off-chain balances requires a signature contribution
from the unanimity of the construction users to ensure this ability is
conserved along updates.
As soon as one user starts to be offline or irresponsive, the updates of
the off-chain balances must have to be halted and payments progress are
limited among subsets of 2 users sharing a channel. Different people have
proposed solutions to this issue: introducing a coordinator, partitioning
or layering balances in off-chain users subsets. I think all those
solutions have circled around a novel issue introduced, namely equivocation
of off-chain balances at the harm of construction counterparties [0].
As ZmnSCPxj pointed out recently, one way to mitigate this equivocation
consists in punishing the cheating pre-nominated coordinator on an external
fidelity bond. One can even imagine more trust-mimized and decentralized
fraud proofs to implement this mitigation, removing the need of a
coordinator [1].
However, I believe punishment equivocation to be game-theory sound should
compensate a defrauded counterparty of the integrity of its lost off-chain
balance. As one cheating counterparty can equivocate in the worst-case
against all the other counterparties in the construction, one fidelity bond
should be equal to ( C - 1 ) * B satoshi amount, where C is the number of
construction counterparty and B the initial off-chain balance of the
cheating counterparty.
Moreover, I guess it is impossible to know ahead of a partition or
transition who will be the "honest" counterparties from the "dishonest"
ones, therefore this ( C - 1 ) * B-sized fidelity bond must be maintained
by every counterparty in the pool or factory. On this ground, I think this
mitigation and other corrective ones are not economically practical for
large-scale pools among a set of anonymous users.
I think the best solution to solve the interactivity issue which is
realistic to design is one ruling out off-chain group equivocation in a
prophylactic fashion. The pool or factory funding utxo should be edited in
an efficient way to register new off-chain subgroups, as lack of
interactivity from a subset of counterparties demands it.
With CoinPool, there is already this idea of including a user pubkey and
balance amount to each leaf composing the Taproot tree while preserving the
key-path spend in case of unanimity in the user group. Taproot leaves can
be effectively regarded as off-chain user accounts available to realize
privacy-preserving payments and contracts.
I think one (new ?) idea can be to introduce taproot leaves "cut-through"
spends where multiple leaves are updated with a single witness,
interactively composed by the owners of the spent leaves. This spend sends
back the leaves amount to a new single leaf, aggregating the amounts and
user pubkeys. The user leaves not participating in this "cut-through" are
inherited with full integrity in the new version of the Taproot tree, at
the gain of no interactivity from their side.
Let's say you have a CoinPool funded and initially set with Alice, Bob,
Caroll, Dave and Eve. Each pool participant has a leaf L.x committing to an
amount A.x and user pubkey P.x, where x is the user name owning a leaf.
Bob and Eve are deemed to be offline by the Alice, Caroll and Dave subset
(the ACD group).
The ACD group composes a cut-through spend of L.a + L.c + L.d. This spends
generates a new leaf L.(acd) leaf committing to amount A.(acd) and P.(acd).
Amount A.(acd) = A.a + A.c + A.d and pubkey P.(acd) = P.a + P.c + P.d.
Bob's leaf L.b and Eve's leaf L.e are left unmodified.
The ACD group generates a new Taproot tree T' = L.(acd) + L.b + L.e, where
the key-path K spend including the original unanimity of pool
counterparties is left unmodified.
The ACD group can confirm a transaction spending the pool funding utxo to a
new single output committing to the scriptpubkey K + T'.
>From then, the ACD group can pursue off-chain balance updates among the
subgroup thanks to the new P.(acd) and relying on the known Eltoo
mechanism. There is no possibility for any member of the ACD group to
equivocate with Bob or Eve in a non-observable fashion.
Once Bob and Eve are online and ready to negotiate an on-chain pool
"refresh" transaction, the conserved key-path spend can be used to
re-equilibrate the Taproot tree, prune out old subgroups unlikely to be
used and provision future subgroups, all with a compact spend based on
signature aggregation.
Few new Taproot tree update script primitives have been proposed, e.g [2].
Though I think none with the level of flexibility offered to generate
leaves cut-through spends, or even batch of "cut-through" where M subgroups
are willing to spend N leaves to compose P new subgroups fan-out in Q new
outputs, with showing a single on-chain witness. I believe such a
hypothetical primitive can also reduce the chain space consumed in the
occurrence of naive mass pool withdraws at the same time.
I think this solution to the high-interactivity issue of payment pools and
factories shifts the burden on each individual user to pre-commit fast
Taproot tree traversals, allowing them to compose new pool subgroups as
fluctuations in pool users' level of liveliness demand it. Pool efficiency
becomes the sum of the quality of user prediction on its counterparties'
liveliness during the construction lifetime. Recursive taproot tree spends
or more efficient accumulator than merkle tree sounds ideas to lower the
on-chain witness space consumed by every pool in the average
non-interactive case.
Cheers,
Antoine
[0]
https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2022-April/020370.html
[1]
https://lists.linuxfoundation.org/pipermail/lightning-dev/2023-August/004043.html
[2]
https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-September/019420.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.linuxfoundation.org/pipermail/bitcoin-dev/attachments/20230925/77e3936d/attachment.html>
📅 Original date posted:2023-09-26
🗒️ Summary of this message: The email discusses the issue of interactivity constraints in payment pools and channel factories and proposes a solution to mitigate equivocation of off-chain balances.
📝 Original message:
Good morning Antoine,
Does `OP_EVICT` not fit?
https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2022-February/019926.html
Regards,
ZmnSCPxj
Sent with Proton Mail secure email.
------- Original Message -------
On Monday, September 25th, 2023 at 6:18 PM, Antoine Riard via bitcoin-dev
> Payment pools and channel factories are afflicted by severe interactivity constraints worsening with the number of users owning an off-chain balance in the construction. The security of user funds is paramount on the ability to withdraw unilaterally from the off-chain construction. As such any update applied to the off-chain balances requires a signature contribution from the unanimity of the construction users to ensure this ability is conserved along updates.
> As soon as one user starts to be offline or irresponsive, the updates of the off-chain balances must have to be halted and payments progress are limited among subsets of 2 users sharing a channel. Different people have proposed solutions to this issue: introducing a coordinator, partitioning or layering balances in off-chain users subsets. I think all those solutions have circled around a novel issue introduced, namely equivocation of off-chain balances at the harm of construction counterparties [0].
>
> As ZmnSCPxj pointed out recently, one way to mitigate this equivocation consists in punishing the cheating pre-nominated coordinator on an external fidelity bond. One can even imagine more trust-mimized and decentralized fraud proofs to implement this mitigation, removing the need of a coordinator [1].
>
> However, I believe punishment equivocation to be game-theory sound should compensate a defrauded counterparty of the integrity of its lost off-chain balance. As one cheating counterparty can equivocate in the worst-case against all the other counterparties in the construction, one fidelity bond should be equal to ( C - 1 ) * B satoshi amount, where C is the number of construction counterparty and B the initial off-chain balance of the cheating counterparty.
>
> Moreover, I guess it is impossible to know ahead of a partition or transition who will be the "honest" counterparties from the "dishonest" ones, therefore this ( C - 1 ) * B-sized fidelity bond must be maintained by every counterparty in the pool or factory. On this ground, I think this mitigation and other corrective ones are not economically practical for large-scale pools among a set of anonymous users.
>
> I think the best solution to solve the interactivity issue which is realistic to design is one ruling out off-chain group equivocation in a prophylactic fashion. The pool or factory funding utxo should be edited in an efficient way to register new off-chain subgroups, as lack of interactivity from a subset of counterparties demands it.
>
> With CoinPool, there is already this idea of including a user pubkey and balance amount to each leaf composing the Taproot tree while preserving the key-path spend in case of unanimity in the user group. Taproot leaves can be effectively regarded as off-chain user accounts available to realize privacy-preserving payments and contracts.
>
> I think one (new ?) idea can be to introduce taproot leaves "cut-through" spends where multiple leaves are updated with a single witness, interactively composed by the owners of the spent leaves. This spend sends back the leaves amount to a new single leaf, aggregating the amounts and user pubkeys. The user leaves not participating in this "cut-through" are inherited with full integrity in the new version of the Taproot tree, at the gain of no interactivity from their side.
>
> Let's say you have a CoinPool funded and initially set with Alice, Bob, Caroll, Dave and Eve. Each pool participant has a leaf L.x committing to an amount A.x and user pubkey P.x, where x is the user name owning a leaf.
>
> Bob and Eve are deemed to be offline by the Alice, Caroll and Dave subset (the ACD group).
>
> The ACD group composes a cut-through spend of L.a + L.c + L.d. This spends generates a new leaf L.(acd) leaf committing to amount A.(acd) and P.(acd).
>
> Amount A.(acd) = A.a + A.c + A.d and pubkey P.(acd) = P.a + P.c + P.d.
>
> Bob's leaf L.b and Eve's leaf L.e are left unmodified.
>
> The ACD group generates a new Taproot tree T' = L.(acd) + L.b + L.e, where the key-path K spend including the original unanimity of pool counterparties is left unmodified.
>
> The ACD group can confirm a transaction spending the pool funding utxo to a new single output committing to the scriptpubkey K + T'.
>
> From then, the ACD group can pursue off-chain balance updates among the subgroup thanks to the new P.(acd) and relying on the known Eltoo mechanism. There is no possibility for any member of the ACD group to equivocate with Bob or Eve in a non-observable fashion.
>
> Once Bob and Eve are online and ready to negotiate an on-chain pool "refresh" transaction, the conserved key-path spend can be used to re-equilibrate the Taproot tree, prune out old subgroups unlikely to be used and provision future subgroups, all with a compact spend based on signature aggregation.
>
> Few new Taproot tree update script primitives have been proposed, e.g [2]. Though I think none with the level of flexibility offered to generate leaves cut-through spends, or even batch of "cut-through" where M subgroups are willing to spend N leaves to compose P new subgroups fan-out in Q new outputs, with showing a single on-chain witness. I believe such a hypothetical primitive can also reduce the chain space consumed in the occurrence of naive mass pool withdraws at the same time.
>
> I think this solution to the high-interactivity issue of payment pools and factories shifts the burden on each individual user to pre-commit fast Taproot tree traversals, allowing them to compose new pool subgroups as fluctuations in pool users' level of liveliness demand it. Pool efficiency becomes the sum of the quality of user prediction on its counterparties' liveliness during the construction lifetime. Recursive taproot tree spends or more efficient accumulator than merkle tree sounds ideas to lower the on-chain witness space consumed by every pool in the average non-interactive case.
>
> Cheers,
> Antoine
>
> [0] https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2022-April/020370.html
> [1] https://lists.linuxfoundation.org/pipermail/lightning-dev/2023-August/004043.html
> [2] https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-September/019420.html