Discussion:
SIGHASH_NOINPUT in Segregated Witness
(too old to reply)
Joseph Poon via bitcoin-dev
2016-02-26 01:07:46 UTC
Permalink
As Segregated Witness will be merged soon as a solution for transaction
malleability, especially with multi-party adversarial signatures, there
may be an additional use case/functionality which is helpful for
Lightning Network and possibly other Bitcoin use cases. This requires a
new SIGHASH flag inside Segregated Witness which does not sign the input
txid/index.

Segwit is very helpful in resolving malleability in pretty much every
case which matters. It is especially helpful in having solid and safe
defaults for standard Bitcoin payments; it's very difficult to mess up
if you are writing code in conjunction with the Bitcoin RPC API.

However, it is very useful for LN if there is a certain level of
outsourcibility for transactions without this 3rd party taking on
onerous costs. In LN, there is a dispute resolution period established
to prevent the counterparty from attesting an incorrect channel state
(represented by broadcasting a timelocked transaction). In other words,
if someone in a channel broadcasts an incorrect state, the output can be
redeemed by a 3rd party (but this 3rd party is not a custodian, since
the output goes to the other party in the channel).

Ideally, a 3rd-party can be handed a transaction which can encompass all
prior states in a compact way. For currently-designed Segregated Witness
transactions, this requires storing all previous signatures, which can
become very costly if individuals to thousands of channel state updates
per day. This is very possible, as fees are near-zero, the value in
atomizing all payments to many transactions becomes viable (reducing
transaction/information costs). If individuals are doing tens of
thousands of transactions per day, and one presumes something like
70-bytes of data per Commitment state in the channel, it quickly becomes
infeasible to watch on behalf of many channels without material costs.

This is especially necessary because it is highly desirable to make
keeping track of these channels be very cheap, as it allows for more
participants to be watching on one's behalf (reducing the chance of a
3rd party fail to watch). Further, it may reduce the need to notify the
3rd party for every single channel Commitment state, instead only
providing the most recent one should provide sufficient information for
all prior states (since the signature will apply for any type of
transaction), making the only updated information the revocation
secret/preimage. Without this SIGHASH flag, every single state would
need to be contacted and updated with 3rd parties. With this SIGHASH
flag, one could instead delegate outsourcing when one's client goes
offline with a single message several hundred bytes in size,
encompassing all prior states.

Of course, while running a 24/7 full-node is encouraged, I suspect many
people will not want to do so at the current time, and it needs to be
functional for those who elect to be connected intermittently. This
requires outsourcing or watching on one's behalf.

This would be achieved using a SIGHASH flag, termed SIGHASH_NOINPUT. It
does not include as part of the signature, the outpoint being spent
(txid and index), nor the amount. It however, would include the spent
outpoint's script as part of the signature. Note that this is just a
SIGHASH flag, and the outpoints are still being included as part of the
txins (if they are mutated, the new txids can be updated by the wallet
without resigning). This allows for a signature to apply to anything
with that pubkey (therefore pubkeys with this flag should not be
reused). For safety, this only applies in SegWit transactions, as segwit
provides a sufficient malleability solution, there is no incentive to
improperly use this sighash flag as a roundabout way to resolve
malleability.

This helps with 3rd-party outsourcing for watching the blockchain, as
one can provide a signature (and the most recent hash-chain of
revocation preimages), which encompasses penalty transactions for all
prior states. Functionally, this allows for opt-in wildcard inputs, but
wallets which do not require these transactions do not need to be
concerned with this flag; since they will never be signing with this
flag, they do not need to be concerned with address re-use.

I'm interested in input and in the level of receptiveness to this. If
there is interest, I'll write up a draft BIP in the next couple days.
--
Joseph Poon
Gregory Maxwell via bitcoin-dev
2016-02-26 01:32:34 UTC
Permalink
On Fri, Feb 26, 2016 at 1:07 AM, Joseph Poon via bitcoin-dev
Post by Joseph Poon via bitcoin-dev
I'm interested in input and in the level of receptiveness to this. If
there is interest, I'll write up a draft BIP in the next couple days.
The design of segwit was carefully constructed to make it maximally
easy and safe to soft-fork in future script enhancements after its
deployment with the specific goal of avoiding indefinite delays in its
deployment from inevitable scope creep from additional things that are
"easy" to deploy as part of segwit. I think to be successful we must
be absolutely ruthless about changes that go in there beyond the
absolute minimum needed for the safe deployment of segwit... so I
think this should probably be constructed as a new segwit script type,
and not a base feature.

The exact construction you're thinking of there isn't clear to me...
one thing that comes to mind is that I think it is imperative that we
do not deploy a without-inputs SIGHASH flag without also deploying at
least a fee-committing sighash-all. The reason for this is that if
hardware wallets are forced to continue transferring input
transactions to check fees or to use without-inputs, they may choose
the latter and leave the users needlessly exposed to replay attacks.

When you do write a BIP for this its imperative that the vulnerability
to replay is called out in bold blinking flaming text, along with the
necessary description of how to use it safely. The fact that without
input commitments transactions are replayable is highly surprising to
many developers... Personally, I'd even go so far as to name the flag
SIGHASH_REPLAY_VULNERABLE. :)
Joseph Poon via bitcoin-dev
2016-02-26 01:48:07 UTC
Permalink
Hi Greg,
I think to be successful we must be absolutely ruthless about changes
that go in there beyond the absolute minimum needed for the safe
deployment of segwit... so I think this should probably be constructed
as a new segwit script type, and not a base feature.
Absolutely, I'd certainly be interested in this being the first
proof/example for the script upgrade mechanisms if it's not ideal for
this to be implemented as part of Segregated Witness itself.
The reason for this is that if hardware wallets are forced to continue
transferring input transactions to check fees or to use
without-inputs, they may choose the latter and leave the users
needlessly exposed to replay attacks.
Yes, I think it's necessary to include the fees as part of the
signature, which will also allow for wallets to not require downloading
the input transactions. However, it's necessary to not include the input
amount itself, as they may differ. SegWit itself is very nice in that it
prevents improperly designed wallets and services using the bitcoin RPC
from making mistakes, you can resolve malleability without compromises
-- I also think any proposed SIGHASH should ensure some measure of
safety from design error/shortcuts.
The fact that without input commitments transactions are replayable is
highly surprising to many developers... Personally, I'd even go so far
as to name the flag SIGHASH_REPLAY_VULNERABLE. :)
That's a good point, choosing a scary name is probably very helpful.

Thanks, I'll clarify with a specific BIP soon.
--
Joseph Poon
Anthony Towns via bitcoin-dev
2016-02-26 03:20:56 UTC
Permalink
Post by Gregory Maxwell via bitcoin-dev
On Fri, Feb 26, 2016 at 1:07 AM, Joseph Poon via bitcoin-dev
Post by Joseph Poon via bitcoin-dev
I'm interested in input and in the level of receptiveness to this. If
there is interest, I'll write up a draft BIP in the next couple days.
.. I think this should probably be constructed as a new segwit script type,
and not a base feature.
+1 to both
Post by Gregory Maxwell via bitcoin-dev
The exact construction you're thinking of there isn't clear to me...
I think the idea is that you have three transactions:

anchor:
input: whatever
output:
- single output, spendable by 2-of-2 multisig
- [possibly others as well, whatever]

commitment:
input: anchor
outputs:
1. payment to A
2. payment to B
3. HTLC to A on R1, timeout T1
4. HTLC to A on R2, timeout T2
5. HTLC to B on R3, timeout T3
...

penalty:
inputs:
all the outputs from the commitment tx
outputs:
1. 99% as payment to me
2. 1% as outsourcing fee

As long as the key I use for spending each of commitment transactions
outputs is "single use" -- ie, I don't use it for other channels or
anywhere else on the blockchain, then as long as the signature commits
to the outputs it's safe afaics.

(You still have to send a lot of data to the place you're outsourcing
chain-monitoring to; all the R1,R2,R3 and T1,T2,T3 values are needed in
order to reconstruct the redeem scripts)
Post by Gregory Maxwell via bitcoin-dev
one thing that comes to mind is that I think it is imperative that we
do not deploy a without-inputs SIGHASH flag without also deploying at
least a fee-committing sighash-all.
If the fee for commitment transactions changes regularly (eg, a new
commitment transaction is generated every few seconds/minutes, and the fee
is chosen based on whatever estimatefee returns), I think this would cause
problems -- you couldn't use a single signature to cover every revoked
commitment, you'd need one for each different fee level that you'd used
for the lifetime of the channel. Actually, the size of the commitment
transaction will differ anyway depending on how many HTLCs are open,
so even if estimatefee didn't change, the fee would still differ. So I
think commiting to a fee isn't workable for the lightning use case...
Post by Gregory Maxwell via bitcoin-dev
When you do write a BIP for this its imperative that the vulnerability
to replay is called out in bold blinking flaming text, along with the
necessary description of how to use it safely. The fact that without
input commitments transactions are replayable is highly surprising to
many developers... Personally, I'd even go so far as to name the flag
SIGHASH_REPLAY_VULNERABLE. :)
+1, though I'm not sure it's so much "vulnerable" to replay as it is
"explicitly designed" to be replayable...

Cheers,
aj
Bryan Bishop via bitcoin-dev
2016-02-26 01:34:24 UTC
Permalink
Post by Joseph Poon via bitcoin-dev
This would be achieved using a SIGHASH flag, termed SIGHASH_NOINPUT. It
does not include as part of the signature, the outpoint being spent
(txid and index), nor the amount. It however, would include the spent
outpoint's script as part of the signature. Note that this is just a
Well if you are bothering to draft up a BIP about that SIGHASH flag,
then perhaps also consider some other SIGHASH flag types as well while
you are at it?

Various proposed sighash types:
http://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-August/010759.html

"Build your own nHashType" proposal draft:
https://github.com/scmorse/bitcoin-misc/blob/master/sighash_proposal.md

jl2012's reply:
http://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-August/010779.html

petertodd's reply about OP_CODESEPARATOR linked back to this thread
regarding "Build your own nHashType":
http://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-April/007771.html
http://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-April/007802.html
http://gnusha.org/bitcoin-wizards/2014-12-09.log

((That particular thread had other replies which can be viewed here:
http://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-April/thread.html
))

Also, there was a draft implementation of SIGHASH_NOINPUT:
https://github.com/Roasbeef/bitcoin/commit/4b3c3f1baf7985208ceb6887261ee150ab6e3328
https://github.com/Roasbeef/btcd/commit/67830e506fa135d5239177340918cea39909e6a4

FWIW there was some concern about replay using SIGHAHS_NOINPUT or something:
http://gnusha.org/bitcoin-wizards/2015-04-07.log

- Bryan
http://heybryan.org/
1 512 203 0507
Joseph Poon via bitcoin-dev
2016-02-26 02:02:26 UTC
Permalink
Hi Bryan,
Post by Bryan Bishop via bitcoin-dev
Well if you are bothering to draft up a BIP about that SIGHASH flag,
then perhaps also consider some other SIGHASH flag types as well while
you are at it?
I'll take a look at those proposals when drafting the BIP. I think for
LN, there is a single clean way to achieve outsourcability, but may be
compatible with other arrangements. I'm somewhat averse to proposing too
much flexibility before there's clear use-cases, though. However, if
others do have uses/examples for other sighash flags, I'd be very
interested while drafting this BIP!
Post by Bryan Bishop via bitcoin-dev
http://gnusha.org/bitcoin-wizards/2015-04-07.log
Yeah, I think the nice thing about SegWit is that you resolve
malleability without worrying about replay attacks in the event of key
reuse. That's why I think it's only safe to do this new sighash type
inside segwit itself -- if you only wanted protection against
malleability you'd use segwit, and not touch this new sighash type
(you'd only use the new sighash flag if you actually need its features).
--
Joseph Poon
Luke Dashjr via bitcoin-dev
2016-02-26 02:35:23 UTC
Permalink
Post by Joseph Poon via bitcoin-dev
This would be achieved using a SIGHASH flag, termed SIGHASH_NOINPUT. It
does not include as part of the signature, the outpoint being spent
(txid and index), nor the amount. It however, would include the spent
outpoint's script as part of the signature. Note that this is just a
SIGHASH flag, and the outpoints are still being included as part of the
txins (if they are mutated, the new txids can be updated by the wallet
without resigning). This allows for a signature to apply to anything
with that pubkey (therefore pubkeys with this flag should not be
reused).
I'd like this regardless of Lightning, as it makes it possible to write fully
malleability-proof wallet software also.
Post by Joseph Poon via bitcoin-dev
For safety, this only applies in SegWit transactions, as segwit
provides a sufficient malleability solution, there is no incentive to
improperly use this sighash flag as a roundabout way to resolve
malleability.
SegWit's malleability solution is not really sufficient in comparison, but I
don't think there's a need to make this available to pre-SegWit transactions
anyway (and doing so would probably complicate it).

Luke
Rusty Russell via bitcoin-dev
2016-02-29 00:25:53 UTC
Permalink
Post by Joseph Poon via bitcoin-dev
Ideally, a 3rd-party can be handed a transaction which can encompass all
prior states in a compact way. For currently-designed Segregated Witness
transactions, this requires storing all previous signatures, which can
become very costly if individuals to thousands of channel state updates
per day.
AFAICT we need more than this. Or are you using something other than
the deployable lightning commit tx style?

If each HTLC output is a p2sh[1], you need the timeout and rhash for
each one to build the script to redeem it. In practice, there's not
much difference between sending a watcher a tx for every commit tx and
sending it information for every new HTLC (roughly a factor of 2).

So we also need to put more in the scriptPubKey for this to work; either
the entire redeemscript, or possibly some kind of multiple-choice P2SH
where any one of the hashes will redeem the payment.

Cheers,
Rusty.
[1] eg. from https://github.com/ElementsProject/lightning/blob/master/doc/deployable-lightning.pdf
OP_HASH160 OP_DUP # Replace top element with two copies of its hash
<R-HASH> OP_EQUAL # Test if they supplied the HTLC R value
OP_SWAP <COMMIT-REVOCATION-HASH> OP_EQUAL OP_ADD
# Or the commitment revocation hash
OP_IF # If any hash matched.
<KEY-B> # Pay to B.
OP_ELSE # Must be A, after HTLC has timed out.
<HTLC-TIMEOUT> OP_CHECKLOCKTIMEVERIFY Ensure (absolute) time has passed.
<DELAY> OP_CHECKSEQUENCEVERIFY # Delay gives B enough time to use revocation if it has it.
OP_2DROP # Drop the delay and htlc-timeout from the stack.
<KEY-A> # Pay to A.
OP_ENDIF
OP_CHECKSIG # Verify A or B's signature is correct.

Cheers,
Rusty.

Loading...