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

Reply via email to