From: Anthony Towns <aj@erisian.com.au>
To: Johnson Lau <jl2012@xbt.hk>
Cc: bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org>
Subject: Re: [bitcoin-dev] Safer NOINPUT with output tagging
Date: Sun, 10 Feb 2019 14:46:30 +1000 [thread overview]
Message-ID: <20190210044630.oiktdihkbyavglzp@erisian.com.au> (raw)
In-Reply-To: <E280BF09-ABE8-4AD8-BE29-A9D87AD09207@xbt.hk>
On Sun, Feb 10, 2019 at 12:48:40AM +0800, Johnson Lau wrote:
> In a 3 parties channel, let’s say the balance for A, B, C is 2, 3, 6BTC respectively, there are few ways they could make the settlement tx.
The way I look at this is:
* you can have a "channel factory" of 3 or more members (A,B,C,...)
* it's protected by an n-of-n multisig output
* it contains some combination of:
- spends directly to members
- lightning channels between pairs of members
- channel factories between subgroups of members
* when initially setup, the factory just has direct spends to each
member matching the amount they contributed to the factory
* whether you create a lightning channel or a sub-factory is the same
decision as whether you create a lightning channel or a factory
on-chain, so there's no combinatorial explosion.
You can close any channel factory by publishing it (and any higher level
channel factories it was a subgroup of) to the blockchain (at which point
the lower level channel factories and lightning channels remain open),
or you can update a channel factory off-chain by having everyone agree
to a new state -- which is only possible if everyone is online, of course.
Updates to transactions in a lightning channel in a factory, or updates
to a subfactory, don't generally involve updating the containing factory
at all, I think.
I don't think there's much use to having sub-factories -- maybe if you
have a subgroup that's much more active and wants to change channel
balances between each other more frequently than the least active member
of the main factory is online?
As far as NOINPUT goes; this impacts channel factories because cheating
could be by any member of the group, so you can't easily penalise the
cheater. So an eltoo-esque setup where you publish a commitment to the
state that's spendable only by any later state, and is then redeemed
after a timelock seems workable. In that case closing a factory when
you can't get all group members to cooperatively close looks like:
funding tx: n-of-n multisig
state commitment: n-of-n multisig
spends funding tx or earlier state commitment
spendable by later state commitment or settlement
settlement: n-of-n multisig
relative timelock
spends state commitment
spends to members, channels or sub-factories
The settlement tx has to spend with a NOINPUT sig, because the state
commitment could have had to spend different things. If it's a
sub-factory, the funding tx will have been in a factory, so the state
commitment would also have had to be a NOINPUT spend. So tagging
NOINPUT-spendable outputs would mean:
- tagging state commitment outputs (which will be spent shortly with
NOINPUT by the settlement tx, so no real loss here)
- tagging settlement tx outputs if they're lightning channels or
sub-factories (which is something of a privacy loss, I think, since
they could continue off-chain for an indefinite period before being
spent)
I think Johnson's suggested elsewhere that if you spend an input with a
NOINPUT signature, you should make all the outputs be tagged NOINPUT (as
a "best practice rule", rather than consensus-enforced or standardness).
That would avoid the privacy loss here, I think, but might be confusing.
If you wanted to close your factory and send your funds to an external
third-party (a cold-wallet, custodial wallet, or just paying someone
for something), you'd presumably do that via a cooperative close of the
factory, which doesn't require the state/settlement pair or NOINPUT
spends, so the NOINPUT-in means NOINPUT-tagged-outputs doesn't cause
a problem for that use case.
FWIW, I think an interesting way to improve this model might be to *add*
centralisation and trust; so that instead of having the factory have
an n-of-n multisig, have it be protected by k-of-n plus a trusted third
party. If you have the trusted third party check that the only balances
that change in the factory are from the "k" signers, that allows (n-k)
members to be offline at any time, but the remaining members to rebalance
their channels happily. (Theoretically you could do this trustlessly
with covenants, but the spending proofs on chain would be much larger)
Of course, this allows k-signers plus the trusted party to steal funds.
It might be possible for the trusted party to store audit logs of the
partial signatures from each of the k-signers for each transaction to
provide accountability -- where the lack of such logs implies the
trusted third party was cheating.
Cheers,
aj
>
>
>
> > On 9 Feb 2019, at 6:01 PM, Alejandro Ranchal Pedrosa via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> wrote:
> >
> > Hi all,
> >>
> >> Side note: I was not able to come up with an similar, eltoo-like protocol that works
> >> if you can't predict in advance who will become absent.
> >>
> > An eltoo-like protocol that works (without going on-chain) if you can't predict in advance who will become absent would be a childchain. If the off-chain protocol can continue updating in the abscence of other parties, it means that other parties' signatures must not be required when they are not involved in the off-chain state update. If other parties' signatures must not be required, there must be a way of having a common verifiable 'last state' to prevent a party to simultaneously 'fork' the state with two different parties, and double-spend. A solution for this is a childchain for Bitcoin. An example of this is what is known as a 'Broken Factory' attack [1] (https://bitcoin.stackexchange.com/questions/77434/how-does-channel-factory-act/81005#81005)
> >
> >> If the expectation is that the unresponsive party returns, fungibility is
> >> not reduced due to output tagging because the above scheme can be used
> >> off-chain until the original channel can be continued.
> >
> > I believe that in many cases other parties won't be able to continue until the unresponsive parties go back online. That might be true in particular scenarios, but generally speaking, the party might have gone unresponsive during a factory-level update (i.e. off-chain closing and opening of channels), while some parties might have given out their signature for the update without receiving a fully signed transaction. In this case they do not even know which channel they have open (the one of the old state that they have fully signed, or the one for the new state that they have given out their signature for). This is known as a 'Stale Factory', and can be exploited by an adversary in a 'Stale Factory' attack [1]. Even if they knew which state they are in (i.e. the party went unresponsive but not during a factory-level update), some of them might have run out of funds in some of their channels of the factory, and might want to update, while they will not be willing to wait for a party to go back online (something for which they also have zero guarantees of).
> >
> > An eltoo-like protocol that works (allowing going on-chain) if you can't in advance who will become absent, then this is precisely why 'Transaction Fragments' have been suggested. They allow an eltoo-like protocol even when one cannot predict in advance who will become absent, or malicious (by publishing invalid states), cause the non-absent parties can unite their fragments and create a valid spendable factory-level transaction that effectively kicks out the malicious parties, while leaving the rest of the factory as it was. To the best of my understanding, the eltoo original proposal also allows this though.
> >
> > Best,
> >
> > Alejandro.
> >
> > [1]: Scalable Lightning Factories for Bitcoin, https://eprint.iacr.org/2018/918.pdf
> >
> >
> > On 08/02/2019 20:01, Jonas Nick via bitcoin-dev wrote:
> >> Output tagging may result in reduced fungibility in multiparty eltoo channels.
> >> If one party is unresponsive, the remaining participants want to remove
> >> the party from the channel without downtime. This is possible by creating
> >> settlement transactions which pay off the unresponsive party and fund a new
> >> channel with the remaining participants.
> >>
> >> When the party becomes unresponsive, the channel is closed by broadcasting the
> >> update transaction as usual. As soon as that happens the remaining
> >> participants can start to update their new channel. Their update signatures
> >> must use SIGHASH_NOINPUT. This is because in eltoo the settlement txid is not
> >> final (because update tx is not confirmed and may have to rebind to another
> >> output). Therefore, the funding output of the new channel must be NOINPUT
> >> tagged. Assuming the remaining parties later settle cooperatively, this loss
> >> of fungibility would not have happened without output tagging.
> >>
> >> funding output update output settlement outputs update output
> >> [ A & B & C ] -> ... -> [ (A & B & C & state CLTV) | (As & Bs & Cs) ] -> [ NOINPUT tagged: (A' & B'), -> ...
> >> C' ]
> >> If the expectation is that the unresponsive party returns, fungibility is
> >> not reduced due to output tagging because the above scheme can be used
> >> off-chain until the original channel can be continued.
> >>
> >> Side note: I was not able to come up with an similar, eltoo-like protocol that works
> >> if you can't predict in advance who will become absent.
> >>
> >> On 12/13/18 12:32 PM, Johnson Lau via bitcoin-dev wrote:
> >>> NOINPUT is very powerful, but the tradeoff is the risks of signature replay. While the key holders are expected not to reuse key pair, little could be done to stop payers to reuse an address. Unfortunately, key-pair reuse has been a social and technical norm since the creation of Bitcoin (the first tx made in block 170 reused the previous public key). I don’t see any hope to change this norm any time soon, if possible at all.
> >>>
> >>> As the people who are designing the layer-1 protocol, we could always blame the payer and/or payee for their stupidity, just like those people laughed at victims of Ethereum dumb contracts (DAO, Parity multisig, etc). The existing bitcoin script language is so restrictive. It disallows many useful smart contracts, but at the same time prevented many dumb contracts. After all, “smart” and “dumb” are non-technical judgement. The DAO contract has always been faithfully executed. It’s dumb only for those invested in the project. For me, it was just a comedy show.
> >>>
> >>> So NOINPUT brings us more smart contract capacity, and at the same time we are one step closer to dumb contracts. The target is to find a design that exactly enables the smart contracts we want, while minimising the risks of misuse.
> >>>
> >>> The risk I am trying to mitigate is a payer mistakenly pay to a previous address with the exactly same amount, and the previous UTXO has been spent using NOINPUT. Accidental double payment is not uncommon. Even if the payee was honest and willing to refund, the money might have been spent with a replayed NOINPUT signature. Once people lost a significant amount of money this way, payers (mostly exchanges) may refuse to send money to anything other than P2PKH, native-P2WPKH and native-P2WSH (as the only 3 types without possibility of NOINPUT)
> >>>
> >>> The proposed solution is that an output must be “tagged” for it to be spendable with NOINPUT, and the “tag” must be made explicitly by the payer. There are 2 possible ways to do the tagging:
> >>>
> >>> 1. A certain bit in the tx version must be set
> >>> 2. A certain bit in the scriptPubKey must be set
> >>>
> >>> I will analyse the pros and cons later.
> >>>
> >>> Using eltoo as example. The setup utxo is a simple 2-of-2 multisig, and should not be tagged. This makes it indistinguishable from normal 1-of-1 utxo. The trigger tx, which spends the setup utxo, should be tagged, so the update txs could spend the trigger utxo with NOINPUT. Similarly, all update txs should be tagged, so they could be spent by other update txs and settlement tx with NOINPUT. As the final destination, there is no need to tag in the settlement tx.
> >>>
> >>> In payer’s perspective, tagging means “I believe this address is for one-time-use only” Since we can’t control how other people manage their addresses, we should never do tagging when paying to other people.
> >>>
> >>> I mentioned 2 ways of tagging, and they have pros and cons. First of all, tagging in either way should not complicate the eltoo protocol in anyway, nor bring extra block space overhead.
> >>>
> >>> A clear advantage of tagging with scriptPubKey is we could tag on a per-output basis. However, scriptPubKey tagging is only possible with native-segwit, not P2SH. That means we have to disallow NOINPUT in P2SH-segwit (Otherwise, *all* P2SH addresses would become “risky” for payers) This should be ok for eltoo, since it has no reason to use P2SH-segwit in intermediate txs, which is more expensive.
> >>>
> >>> Another problem with scriptPubKey tagging is all the existing bech32 implementations will not understand the special tag, and will pay to a tagged address as usual. An upgrade would be needed for them to refuse sending to tagged addresses by default.
> >>>
> >>> On the other hand, tagging with tx version will also protect P2SH-segwit, and all existing wallets are protected by default. However, it is somewhat a layer violation and you could only tag all or none output in the same tx. Also, as Bitcoin Core has just removed the tx version from the UTXO database, adding it back could be a little bit annoying, but doable.
> >>>
> >>> There is an extension to the version tagging, which could make NOINPUT even safer. In addition to tagging requirement, NOINPUT will also sign the version of the previous tx. If the wallet always uses a randomised tx version, it makes accidental replay very unlikely. However, that will burn a few more bits in the tx version field.
> >>>
> >>> While this seems fully compatible with eltoo, is there any other proposals require NOINPUT, and is adversely affected by either way of tagging?
> >>> _______________________________________________
> >>> bitcoin-dev mailing list
> >>> bitcoin-dev@lists.linuxfoundation.org
> >>> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
> >>>
> >> _______________________________________________
> >> bitcoin-dev mailing list
> >> bitcoin-dev@lists.linuxfoundation.org
> >> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
> > _______________________________________________
> > bitcoin-dev mailing list
> > bitcoin-dev@lists.linuxfoundation.org
> > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>
>
next prev parent reply other threads:[~2019-02-10 4:46 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-12-13 12:32 [bitcoin-dev] Safer NOINPUT with output tagging Johnson Lau
2018-12-17 15:48 ` Ruben Somsen
2018-12-17 20:08 ` Johnson Lau
2018-12-18 10:48 ` Johnson Lau
2018-12-19 22:09 ` Christian Decker
2018-12-20 11:00 ` Johnson Lau
2018-12-20 17:20 ` Christian Decker
2018-12-20 18:04 ` Johnson Lau
2018-12-21 11:15 ` Christian Decker
2018-12-21 16:21 ` Johnson Lau
2018-12-21 11:40 ` ZmnSCPxj
2018-12-21 15:37 ` Johnson Lau
2018-12-22 14:25 ` ZmnSCPxj
2018-12-22 16:56 ` Johnson Lau
2018-12-24 11:47 ` ZmnSCPxj
2019-01-31 6:04 ` Anthony Towns
2019-02-01 9:36 ` ZmnSCPxj
2019-02-08 19:01 ` Jonas Nick
2019-02-09 10:01 ` Alejandro Ranchal Pedrosa
2019-02-09 16:48 ` Johnson Lau
2019-02-10 4:46 ` Anthony Towns [this message]
2019-02-09 16:54 ` Jonas Nick
2019-02-09 10:15 ` Johnson Lau
2019-02-09 16:52 ` Jonas Nick
2019-02-09 17:43 ` Johnson Lau
2019-02-19 19:04 ` Luke Dashjr
2019-02-19 19:22 ` Johnson Lau
2019-02-19 20:24 ` Luke Dashjr
2019-02-19 20:36 ` Johnson Lau
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190210044630.oiktdihkbyavglzp@erisian.com.au \
--to=aj@erisian.com.au \
--cc=bitcoin-dev@lists.linuxfoundation.org \
--cc=jl2012@xbt.hk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox