On Thu, May 10, 2018 at 08:34:58AM +0930, Rusty Russell wrote:
> > The big concern I have with _NOINPUT is that it has a huge failure
> > case: if you use the same key for multiple inputs and sign one of them
> > with _NOINPUT, you've spent all of them. The current proposal kind-of
> > limits the potential damage by still committing to the prevout amount,
> > but it still seems a big risk for all the people that reuse addresses,
> > which seems to be just about everyone.
> If I can convince you to sign with SIGHASH_NONE, it's already a problem
> today.

So, I don't find that very compelling: "there's already a way to lose
your money, so it's fine to add other ways to lose your money". And
again, I think NOINPUT is worse here, because a SIGHASH_NONE signature
only lets others take the coin you're trying to spend, messing up when
using NOINPUT can cause you to lose other coins as well (with caveats).

> [...]
> In a world where SIGHASH_NONE didn't exist, this might be an argument :)

I could see either dropping support for SIGHASH_NONE for segwit
v1 addresses, or possibly limiting SIGHASH_NONE in a similar way to
limiting SIGHASH_NOINPUT. Has anyone dug through the blockchain to see
if SIGHASH_NONE is actually used/useful?

> That was also suggested by Mark Friedenbach, but I think we'll end up
> with more "magic key" a-la Schnorr/taproot/graftroot and less script in
> future.

Taproot and graftroot aren't "less script" at all -- if anything they're
the opposite in that suddenly every address can have a script path.
I think NOINPUT has pretty much the same tradeoffs as taproot/graftroot
scripts: in the normal case for both you just use a SIGHASH_ALL
signature to spend your funds; in the abnormal case for NOINPUT, you use
a SIGHASH_NOINPUT (multi)sig for unilateral eltoo closes or watchtower
penalties, in the abnormal case for taproot/graftroot you use a script.

> That means we'd actually want a different Segwit version for
> "NOINPUT-can-be-used", which seems super ugly.

That's backwards. If you introduce a new opcode, you can use the existing
segwit version, rather than needing segwit v1. You certainly don't need
v1 segwit for regular coins and v2 segwit for NOINPUT coins, if that's
where you were going?

For segwit v0, that would mean your addresses for a key "X", might be:

   [pubkey]  X    
    - not usable with NOINPUT
   [script]  2 X Y 2 CHECKMULTISIG
    - not usable with NOINPUT
    - usable with NOINPUT (or SIGHASH_ALL)

CHECKMULTISIG_1USE_VERIFY being soft-forked in by replacing an OP_NOP,
of course. Any output spendable via a NOINPUT signature would then have
had to have been deliberately created as being spendable by NOINPUT.

For a new segwit version with taproot that likewise includes an opcode,
that might be:

   [taproot]  X
    - not usable with NOINPUT
   [taproot]  X or: X CHECKSIG_1USE
    - usable with NOINPUT

If you had two UTXOs (with the same value), then if you construct
a taproot witness script for the latter address it will look like:


and that signature can't be used for addresses that were just intending
to pay to X, because the NOINPUT sig/sighash simply isn't supported
without a taproot path that includes the CHECKSIG_1USE opcode.

In essence, with the above construction there's two sorts of addresses
you generate from a public key X: addresses where you spend each coin
individually, and different addresses where you spend the wallet of
coins with that public key (and value) at once; and that remains the
same even if you use a single key for both.

I think it's slightly more reasonable to worry about signing with NOINPUT
compared to signing with SIGHASH_NONE: you could pretty reasonably setup
your (light) bitcoin wallet to not be able to sign (or verify) with
SIGHASH_NONE ever; but if you want to use lightning v2, it seems pretty
likely your wallet will be signing things with SIGHASH_NOINPUT. From
there, it's a matter of having a bug or a mistake cause you to
cross-contaminate keys into your lightning subsystem, and not be
sufficiently protected by other measures (eg, muSig versus checkmultisig).

(For me the Debian ssh key generation bug from a decade ago is sufficient
evidence that people you'd think are smart and competent do make really
stupid mistakes in real life; so defense in depth here makes sense even
though you'd have to do really stupid things to get a benefit from it)

The other benefit of a separate opcode is support can be soft-forked in
independently of a new segwit version (either earlier or later).

I don't think the code has to be much more complicated with a separate
opcode; passing an extra flag to TransactionSignatureChecker::CheckSig()
is probably close to enough. Some sort of flag remains needed anyway
since v0 and pre-segwit signatures won't support NOINPUT.


Lightning-dev mailing list

Reply via email to