* [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT @ 2018-11-19 22:37 Pieter Wuille 2018-11-20 20:29 ` Anthony Towns ` (4 more replies) 0 siblings, 5 replies; 55+ messages in thread From: Pieter Wuille @ 2018-11-19 22:37 UTC (permalink / raw) To: Bitcoin Dev Hello everyone, For future segwit versions, I think it would be good add a few things to the sighash by default that were overlooked in BIP143: * Committing to the absolute transaction fee (in addition to just the amount being spent in each input) would categorically remove concerns about wallets lying about fees to HW devices or airgapped signers. * Committing to the scriptPubKey (in addition to the scriptCode) would prevent lying to devices about the type of output being spent, even when the scriptCode is correct. As a reminder, the scriptCode is the actually executed script (which is the redeemscript in non-segwit P2SH, and the witnesscript in P2WSH/P2WPKH). As this implies additional information that may not be desirable to commit to in all circumstances, it makes sense to make these optional. This obviously interacts with SIGHASH_NOINPUT, which really adds two different ways of rebinding signatures to inputs: * Changing the prevout (so that the txid doesn't need to be known when the signature is created) * Changing the script (so that the exact scriptPubKey/redeemScript/... doesn't need to be known when the signature is created) Of course, the second implies the first, but do all use cases require both being able to change the prevout and (arbitrarily) changing the scriptPubKey? While BIP118 correctly points out this is secure if the same keys are only used in scripts with which binding is to be permitted, I feel it would be preferable if signatures/scripts would explicitly state what can change. One way to accomplish this is by indicating exactly what in a script is subject to change. Here is a combined proposal: * Three new sighash flags are added: SIGHASH_NOINPUT, SIGHASH_NOFEE, and SIGHASH_SCRIPTMASK. * A new opcode OP_MASK is added, which acts as a NOP during execution. * The sighash is computed like in BIP143, but: * If SIGHASH_SCRIPTMASK is present, for every OP_MASK in scriptCode the subsequent opcode/push is removed. * The scriptPubKey being spent is added to the sighash, unless SIGHASH_SCRIPTMASK is set. * The transaction fee is added to the sighash, unless SIGHASH_NOFEE is set. * hashPrevouts, hashSequence, and outpoint are set to null when SIGHASH_NOINPUT is set (like BIP118, but not for scriptCode). So my question is whether anyone can see ways in which this introduces redundant flexibility, or misses obvious use cases? Cheers, -- Pieter ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-19 22:37 [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT Pieter Wuille @ 2018-11-20 20:29 ` Anthony Towns 2018-11-21 11:20 ` Christian Decker 2018-11-21 17:55 ` Johnson Lau 2018-11-21 11:15 ` Christian Decker ` (3 subsequent siblings) 4 siblings, 2 replies; 55+ messages in thread From: Anthony Towns @ 2018-11-20 20:29 UTC (permalink / raw) To: Pieter Wuille, Bitcoin Protocol Discussion On Mon, Nov 19, 2018 at 02:37:57PM -0800, Pieter Wuille via bitcoin-dev wrote: > Here is a combined proposal: > * Three new sighash flags are added: SIGHASH_NOINPUT, SIGHASH_NOFEE, > and SIGHASH_SCRIPTMASK. > * A new opcode OP_MASK is added, which acts as a NOP during execution. > * The sighash is computed like in BIP143, but: > * If SIGHASH_SCRIPTMASK is present, for every OP_MASK in scriptCode > the subsequent opcode/push is removed. > * The scriptPubKey being spent is added to the sighash, unless > SIGHASH_SCRIPTMASK is set. > * The transaction fee is added to the sighash, unless SIGHASH_NOFEE is set. > * hashPrevouts, hashSequence, and outpoint are set to null when > SIGHASH_NOINPUT is set (like BIP118, but not for scriptCode). Current flags are {ALL, NONE, SINGLE} and ANYONECANPAY, and the BIP143 tx digest consists of the hash of: 1 nVersion 4 outpoint 5 input scriptCode 6 input's outpoint value 7 input's nSeq 9 nLocktime 10 sighash 2 hashPrevOuts (commits to 4,5,6; unless ANYONECANPAY) 3 hashSequence (commits to 7; only if ALL and not ANYONECANPAY) 8 hashOutputs - NONE: 0 - SINGLE: {value,scriptPubKey} for corresponding output - otherwise: {value,scriptPubKey} for all outputs The fee is committed to by hashPrevOuts and hashOutputs, which means NOFEE is only potentially useful if ANYONECANPAY or NONE or SINGLE is set. For NOINPUT, (2),(3),(4) are cleared, and SCRIPTMASK (which munges (5)) is only useful given NOINPUT, since (4) indirectly commits to (5). Given this implementation, NOINPUT effectively implies ANYONECANPAY, I think. (I think that is also true of BIP 118's NOINPUT spec) Does it make sense to treat this as two classes of options, affecting the input and output side: output: (pick one, using bits 0,1) * NONE -- don't care where the money goes * SINGLE -- want this output * ALL -- want exactly this set of outputs input: (pick one, using bits 4,5) * PARTIALSCRIPT -- spending from some tx with roughly this script (and maybe others; SCRIPTMASK|NOINPUT|ANYONECANPAY) * KNOWNSCRIPT -- spending from some tx with exactly this script (and maybe others; NOINPUT|ANYONECANPAY) * KNOWNTX -- spending from this tx (and maybe others; ANYONECANPAY) * ALL_INPUTS -- spending from exactly these txes combo: (flag, bit 6) * NOFEE -- don't commit to the fee I think NONE without NOFEE doesn't make much sense, and NOFEE|ALL|ALL_INPUTS would also be pretty weird. Might make sense to warn/error on signing when asking for those combinations, and maybe even to fail on validating them. (Does it make sense to keep SIGHASH_NONE? I guess SIGHASH_NONE|ALL_INPUTS could be useful if you just use sigs on one of the other inputs to commit to a useful output) FWIW, OP_MASK seems a bit complicated to me. How would you mask a script that looks like: OP_MASK IF <p> ENDIF <q> ... or: IF OP_MASK ENDIF <p> ... I guess if you make the rule be "for every OP_MASK in scriptCode the *immediately* subsequent opcode/push is removed (if present)" it would be fine though -- that would make OP_MASK in both the above not have any effect. (Maybe a more explicit name like "MASK_PUSH_FOR_SIGHASH" or something might be good?) I don't have a reason why, but committing to the scriptCode feels to me like it reduces the "hackiness" of NOINPUT a lot. Cheers, aj ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-20 20:29 ` Anthony Towns @ 2018-11-21 11:20 ` Christian Decker 2018-11-21 17:55 ` Johnson Lau 1 sibling, 0 replies; 55+ messages in thread From: Christian Decker @ 2018-11-21 11:20 UTC (permalink / raw) To: Anthony Towns, Bitcoin Protocol Discussion, Pieter Wuille, Bitcoin Protocol Discussion Anthony Towns via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> writes: > Given this implementation, NOINPUT effectively implies ANYONECANPAY, > I think. (I think that is also true of BIP 118's NOINPUT spec) I mentioned this in my reply to Pieter, but this may not be true if we remove the blanking of the `hashSequence` field. Anyonecanpay would allow changing the number of inputs in an arbitrary fashion, while `noinput` without the blanking would (in a weird roundabout way) still commit to the number of inputs. Maybe we want to make that more explicit by also hashing the number of inputs? But I can't think of a good usecase for keeping that, with noinput. Cheers, Christian ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-20 20:29 ` Anthony Towns 2018-11-21 11:20 ` Christian Decker @ 2018-11-21 17:55 ` Johnson Lau 1 sibling, 0 replies; 55+ messages in thread From: Johnson Lau @ 2018-11-21 17:55 UTC (permalink / raw) To: Anthony Towns, bitcoin-dev If we sign the txids of all inputs, we should also explicitly commit to their values. Only this could fully eliminate any possible way to lie about input value to hardware wallets > Does it make sense to keep SIGHASH_NONE? SIGHASH_NONE should be kept. ANYONECANPAY|NONE allows donation of dust UTXOs to miners > I think NONE without NOFEE doesn't make much sense……. We might refuse to sign weird combinations like NOFEE|ALLINPUT|ALLOUTPUT. But to keep the consensus logic simple, we should just validate it as usual. > OP_MASK seems a bit complicated to me. …... Yes, it looks complicated to me, and it improves security only in some avoidable edge cases in SIGHASH_NOINPUT: The common case: the exact masked script or address is reused. OP_MASK can’t prevent signature replay since the masked script is the same. The avoidable case: the same public key is reused in different script templates. OP_MASK may prevent signature replay is the masked script is not the same. The latter case is totally avoidable since one could and should use a different public key for different script. It could be made much simpler as NOINPUT with/without SCRIPT. This again is only helpful in the avoidable case above, but it doesn’t bring too much complexity. > I don't have a reason why, but committing to the scriptCode feels to me like it reduces the "hackiness" of NOINPUT a lot. OP_MASK is designed to preserve the hackiness, while provide some sort of replay protection (only in avoidable cases). However, I’m not sure who would actually need NOINPUT with KNOWNSCRIPT > On 21 Nov 2018, at 4:29 AM, Anthony Towns via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> wrote: > > On Mon, Nov 19, 2018 at 02:37:57PM -0800, Pieter Wuille via bitcoin-dev wrote: >> Here is a combined proposal: >> * Three new sighash flags are added: SIGHASH_NOINPUT, SIGHASH_NOFEE, >> and SIGHASH_SCRIPTMASK. >> * A new opcode OP_MASK is added, which acts as a NOP during execution. >> * The sighash is computed like in BIP143, but: >> * If SIGHASH_SCRIPTMASK is present, for every OP_MASK in scriptCode >> the subsequent opcode/push is removed. >> * The scriptPubKey being spent is added to the sighash, unless >> SIGHASH_SCRIPTMASK is set. >> * The transaction fee is added to the sighash, unless SIGHASH_NOFEE is set. >> * hashPrevouts, hashSequence, and outpoint are set to null when >> SIGHASH_NOINPUT is set (like BIP118, but not for scriptCode). > > Current flags are {ALL, NONE, SINGLE} and ANYONECANPAY, and the BIP143 > tx digest consists of the hash of: > > 1 nVersion > 4 outpoint > 5 input scriptCode > 6 input's outpoint value > 7 input's nSeq > 9 nLocktime > 10 sighash > > 2 hashPrevOuts (commits to 4,5,6; unless ANYONECANPAY) > 3 hashSequence (commits to 7; only if ALL and not ANYONECANPAY) > 8 hashOutputs > - NONE: 0 > - SINGLE: {value,scriptPubKey} for corresponding output > - otherwise: {value,scriptPubKey} for all outputs > > The fee is committed to by hashPrevOuts and hashOutputs, which means > NOFEE is only potentially useful if ANYONECANPAY or NONE or SINGLE is set. > > For NOINPUT, (2),(3),(4) are cleared, and SCRIPTMASK (which munges (5)) > is only useful given NOINPUT, since (4) indirectly commits to (5). > > Given this implementation, NOINPUT effectively implies ANYONECANPAY, > I think. (I think that is also true of BIP 118's NOINPUT spec) > > Does it make sense to treat this as two classes of options, affecting > the input and output side: > > output: (pick one, using bits 0,1) > * NONE -- don't care where the money goes > * SINGLE -- want this output > * ALL -- want exactly this set of outputs > > input: (pick one, using bits 4,5) > * PARTIALSCRIPT -- spending from some tx with roughly this script (and > maybe others; SCRIPTMASK|NOINPUT|ANYONECANPAY) > * KNOWNSCRIPT -- spending from some tx with exactly this script (and > maybe others; NOINPUT|ANYONECANPAY) > * KNOWNTX -- spending from this tx (and maybe others; ANYONECANPAY) > * ALL_INPUTS -- spending from exactly these txes > > combo: (flag, bit 6) > * NOFEE -- don't commit to the fee > > I think NONE without NOFEE doesn't make much sense, and > NOFEE|ALL|ALL_INPUTS would also be pretty weird. Might make sense to > warn/error on signing when asking for those combinations, and maybe even > to fail on validating them. > > (Does it make sense to keep SIGHASH_NONE? I guess SIGHASH_NONE|ALL_INPUTS > could be useful if you just use sigs on one of the other inputs to commit > to a useful output) > > FWIW, OP_MASK seems a bit complicated to me. How would you mask a script > that looks like: > > OP_MASK IF <p> ENDIF <q> ... > > or: > > IF OP_MASK ENDIF <p> ... > > I guess if you make the rule be "for every OP_MASK in scriptCode the > *immediately* subsequent opcode/push is removed (if present)" it would > be fine though -- that would make OP_MASK in both the above not have > any effect. (Maybe a more explicit name like "MASK_PUSH_FOR_SIGHASH" > or something might be good?) > > I don't have a reason why, but committing to the scriptCode feels to me > like it reduces the "hackiness" of NOINPUT a lot. > > Cheers, > aj > > _______________________________________________ > bitcoin-dev mailing list > bitcoin-dev@lists.linuxfoundation.org > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-19 22:37 [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT Pieter Wuille 2018-11-20 20:29 ` Anthony Towns @ 2018-11-21 11:15 ` Christian Decker 2018-11-23 6:04 ` Anthony Towns 2018-11-21 17:07 ` Russell O'Connor ` (2 subsequent siblings) 4 siblings, 1 reply; 55+ messages in thread From: Christian Decker @ 2018-11-21 11:15 UTC (permalink / raw) To: Pieter Wuille, Bitcoin Protocol Discussion, Bitcoin Dev Hi Pieter, great proposal, I think this may address some of the (perceived) downsides of BIP118, by committing to the script when possible (always?). One minor thing that I noticed a while ago and that I meant to fix on BIP118 is that `hashSequence` does not need to be blanked for eltoo to work (since where it is needed we also use `sighash_single`), so I'm tempted to remove that redundant blanking. It may not make a lot of difference but it'd limit the ability to change the number of inputs to a NOINPUT transaction (this now being the only field that commits to the set of inputs). As for your proposal, I really like the `sighash_scriptmask` proposal, and committing to the fees (with the `nofee` escape hatch) also works seems also a nice fix. My one concern is that introducing a new opcode to mask things in the sighash looks like a similar layering violation as `codeseparator` was, but that's just a minor issue imho. Cheers, Christian Pieter Wuille via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> writes: > Hello everyone, > > For future segwit versions, I think it would be good add a few things > to the sighash by default that were overlooked in BIP143: > * Committing to the absolute transaction fee (in addition to just the > amount being spent in each input) would categorically remove concerns > about wallets lying about fees to HW devices or airgapped signers. > * Committing to the scriptPubKey (in addition to the scriptCode) would > prevent lying to devices about the type of output being spent, even > when the scriptCode is correct. As a reminder, the scriptCode is the > actually executed script (which is the redeemscript in non-segwit > P2SH, and the witnesscript in P2WSH/P2WPKH). > > As this implies additional information that may not be desirable to > commit to in all circumstances, it makes sense to make these optional. > This obviously interacts with SIGHASH_NOINPUT, which really adds two > different ways of rebinding signatures to inputs: > * Changing the prevout (so that the txid doesn't need to be known when > the signature is created) > * Changing the script (so that the exact scriptPubKey/redeemScript/... > doesn't need to be known when the signature is created) > > Of course, the second implies the first, but do all use cases require > both being able to change the prevout and (arbitrarily) changing the > scriptPubKey? While BIP118 correctly points out this is secure if the > same keys are only used in scripts with which binding is to be > permitted, I feel it would be preferable if signatures/scripts would > explicitly state what can change. One way to accomplish this is by > indicating exactly what in a script is subject to change. > > Here is a combined proposal: > * Three new sighash flags are added: SIGHASH_NOINPUT, SIGHASH_NOFEE, > and SIGHASH_SCRIPTMASK. > * A new opcode OP_MASK is added, which acts as a NOP during execution. > * The sighash is computed like in BIP143, but: > * If SIGHASH_SCRIPTMASK is present, for every OP_MASK in scriptCode > the subsequent opcode/push is removed. > * The scriptPubKey being spent is added to the sighash, unless > SIGHASH_SCRIPTMASK is set. > * The transaction fee is added to the sighash, unless SIGHASH_NOFEE is set. > * hashPrevouts, hashSequence, and outpoint are set to null when > SIGHASH_NOINPUT is set (like BIP118, but not for scriptCode). > > So my question is whether anyone can see ways in which this introduces > redundant flexibility, or misses obvious use cases? > > Cheers, > > -- > Pieter > _______________________________________________ > bitcoin-dev mailing list > bitcoin-dev@lists.linuxfoundation.org > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-21 11:15 ` Christian Decker @ 2018-11-23 6:04 ` Anthony Towns 2018-11-23 9:40 ` Christian Decker 0 siblings, 1 reply; 55+ messages in thread From: Anthony Towns @ 2018-11-23 6:04 UTC (permalink / raw) To: Christian Decker, Bitcoin Protocol Discussion On Wed, Nov 21, 2018 at 12:15:44PM +0100, Christian Decker via bitcoin-dev wrote: > One minor thing that I noticed a while ago and that I meant > to fix on BIP118 is that `hashSequence` does not need to be blanked for > eltoo to work (since where it is needed we also use `sighash_single`), > so I'm tempted to remove that redundant blanking. It may not make a lot > of difference but it'd limit the ability to change the number of inputs > to a NOINPUT transaction (this now being the only field that commits to > the set of inputs). Commiting to just the sequence numbers seems really weird to me; it only really prevents you from adding inputs, since you could still replace any input that was meant to be there by almost any arbitrary other transaction... I could see this *maybe* making sense if you at least committed to the values of each input's outpoint; since that would be an actual constraint? I don't think you can commit to anything else about the other inputs: -- txids of the other transactions wouldn't work if you had other NOINPUT txes, and would introduce O(N^2) validation cost if someone signed every input with NOINPUT but committed to the txids of every other input -- scriptPubKeys wouldn't really work for eltoo-like constructions that want to vary the scripts but apply the same sig, but might work sometimes? -- witness scripts for the other inputs could be unknown at your signing time, or arbitrarily large and thus a pain to have to send to a hardware wallet Just treating NOINPUT as a subset of ANYONECANPAY seems simpler to me though... > As for your proposal, I really like the `sighash_scriptmask` proposal, > and committing to the fees (with the `nofee` escape hatch) also works > seems also a nice fix. My one concern is that introducing a new opcode > to mask things in the sighash looks like a similar layering violation as > `codeseparator` was, but that's just a minor issue imho. I think OP_MASK is okay as far as layering goes, if you just think of it as a (set of) multibyte "OP_MASKED_PUSH" opcode(s). So when you pseudocode a script like: <n> OP_CSV OP_DROP <p> OP_CHECKSIG and then decide <n> needs to be masked, you rewrite it as: [n] OP_CSV OP_DROP <p> OP_CHECKSIG indicating n is masked, and don't worry about the exact bytes that will encode the push, anymore than you currently worry about whether it's OP_0, OP_1..16, <1..75>+1..75-bytes, PUSHDATA[1,2,3]+n+n-bytes. As long as OP_MASK only applies to a PUSH and it's an error for OP_MASK not to be immediately followed by that PUSH, I think that all works out fine. Cheers, aj ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-23 6:04 ` Anthony Towns @ 2018-11-23 9:40 ` Christian Decker 2018-11-24 8:13 ` Johnson Lau 0 siblings, 1 reply; 55+ messages in thread From: Christian Decker @ 2018-11-23 9:40 UTC (permalink / raw) To: Anthony Towns, Bitcoin Protocol Discussion Anthony Towns <aj@erisian.com.au> writes: > Commiting to just the sequence numbers seems really weird to me; it > only really prevents you from adding inputs, since you could still > replace any input that was meant to be there by almost any arbitrary > other transaction... It's a really roundabout way of committing to the inputs, I agree. I'm actually wondering if it makes sense to correct that additional blanked field in BIP118 at all since it seems there is no real use-case for NOINPUT that doesn't involve blanking the `hashSequence` as well. > I could see this *maybe* making sense if you at least committed to the > values of each input's outpoint; since that would be an actual constraint? BIP118 still commits to the value of the input being spent, i.e., 6. value is not being blanked in the current proposal. This is on purpose since we commit to the outputs, not committing to the input values could end up with unexpected fees. >> As for your proposal, I really like the `sighash_scriptmask` proposal, >> and committing to the fees (with the `nofee` escape hatch) also works >> seems also a nice fix. My one concern is that introducing a new opcode >> to mask things in the sighash looks like a similar layering violation as >> `codeseparator` was, but that's just a minor issue imho. > > I think OP_MASK is okay as far as layering goes, if you just think of it > as a (set of) multibyte "OP_MASKED_PUSH" opcode(s). So when you > pseudocode a script like: > > <n> OP_CSV OP_DROP <p> OP_CHECKSIG > > and then decide <n> needs to be masked, you rewrite it as: > > [n] OP_CSV OP_DROP <p> OP_CHECKSIG > > indicating n is masked, and don't worry about the exact bytes that will > encode the push, anymore than you currently worry about whether it's > OP_0, OP_1..16, <1..75>+1..75-bytes, PUSHDATA[1,2,3]+n+n-bytes. > > As long as OP_MASK only applies to a PUSH and it's an error for OP_MASK > not to be immediately followed by that PUSH, I think that all works > out fine. Agreed, that makes more sense :-) ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-23 9:40 ` Christian Decker @ 2018-11-24 8:13 ` Johnson Lau 0 siblings, 0 replies; 55+ messages in thread From: Johnson Lau @ 2018-11-24 8:13 UTC (permalink / raw) To: Christian Decker, bitcoin-dev > On 23 Nov 2018, at 5:40 PM, Christian Decker via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> wrote: > > Anthony Towns <aj@erisian.com.au> writes: >> Commiting to just the sequence numbers seems really weird to me; it >> only really prevents you from adding inputs, since you could still >> replace any input that was meant to be there by almost any arbitrary >> other transaction... > > It's a really roundabout way of committing to the inputs, I > agree. I'm actually wondering if it makes sense to correct that > additional blanked field in BIP118 at all since it seems there is no > real use-case for NOINPUT that doesn't involve blanking the > `hashSequence` as well. I think we just make it as simple as this: Always commit to sequence of the same input. Commit to hashSequence if and only if all inputs and all outputs are signed. The next-generation SIGHASH will introduce not only NOINPUT, but also signing of fees, previous scriptPubKey, and all input values, etc. So it won’t be a simple hack over BIP143. BIP118 might be better changed to be an informational BIP, focus on the rationale and examples of NOINPUT, and be cross-referenced with the consensus BIP. ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-19 22:37 [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT Pieter Wuille 2018-11-20 20:29 ` Anthony Towns 2018-11-21 11:15 ` Christian Decker @ 2018-11-21 17:07 ` Russell O'Connor 2018-11-22 14:28 ` Johnson Lau 2018-11-23 5:03 ` Anthony Towns 2018-11-28 3:41 ` Pieter Wuille 2018-12-12 9:42 ` Rusty Russell 4 siblings, 2 replies; 55+ messages in thread From: Russell O'Connor @ 2018-11-21 17:07 UTC (permalink / raw) To: Pieter Wuille, Bitcoin Protocol Discussion [-- Attachment #1: Type: text/plain, Size: 2237 bytes --] On Mon, Nov 19, 2018 at 10:22 PM Pieter Wuille via bitcoin-dev < bitcoin-dev@lists.linuxfoundation.org> wrote: > So my question is whether anyone can see ways in which this introduces > redundant flexibility, or misses obvious use cases? > Hopefully my comment is on-topic for this thread: Given that we want to move away from OP_CODESEPARATOR, because each call to this operation effectively takes O(script-size) time, we need a replacement for the functionality it currently provides. While perhaps the original motivation for OP_CODESEPARTOR is surrounded in mystery, it currently can be used (or perhaps abused) for the task of creating signature that covers, not only which input is being signed, but which specific branch within that input Script code is being signed for. For example, one can place an OP_CODESEPARATOR within each branch of an IF block, or by placing an OP_CODESEPARATOR before each OP_CHECKSIG operation. By doing so, signatures created for one clause cannot be used as signatures for another clause. Since different clauses in Bitcoin Script may be enforcing different conditions (such as different time-locks, hash-locks, etc), it is useful to be able to sign in such a way that your signature is only valid when the conditions for a particular branch are satisfied. In complex Scripts, it may not be practical or possible to use different public keys for every different clause. (In practice, you will be able to get away with fewer OP_CODESEPARATORS than one in every IF block). One suggestion I heard (I think I heard it from Pieter) to achieve the above is to add an internal counter that increments on every control flow operator, OP_IF, OP_NOTIF, OP_ELSE, OP_ENDIF, and have the signature cover the value of this counter. Equivalently we divide every Bitcoin Script program into blocks deliminated by these control flow operator and have the signature cover the index of the block that the OP_CHECKSIG occurs within. More specifically, we will want a SigHash flag to enables/disable the signature covering this counter. There are many different ways one might go about replacing the remaining useful behaviour of OP_CODESEPARATOR than the one I gave above. I would be happy with any solution. [-- Attachment #2: Type: text/html, Size: 2634 bytes --] ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-21 17:07 ` Russell O'Connor @ 2018-11-22 14:28 ` Johnson Lau 2018-11-22 16:23 ` Russell O'Connor 2018-11-23 5:03 ` Anthony Towns 1 sibling, 1 reply; 55+ messages in thread From: Johnson Lau @ 2018-11-22 14:28 UTC (permalink / raw) To: Russell O'Connor, bitcoin-dev [-- Attachment #1: Type: text/plain, Size: 2849 bytes --] With MAST in taproot, OP_IF etc become mostly redundant, with worse privacy. To maximise fungibility, we should encourage people to use MAST, instead of improve the functionality of OP_IF and further complicate the protocol. > On 22 Nov 2018, at 1:07 AM, Russell O'Connor via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> wrote: > > On Mon, Nov 19, 2018 at 10:22 PM Pieter Wuille via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org <mailto:bitcoin-dev@lists.linuxfoundation.org>> wrote: > So my question is whether anyone can see ways in which this introduces > redundant flexibility, or misses obvious use cases? > > Hopefully my comment is on-topic for this thread: > > Given that we want to move away from OP_CODESEPARATOR, because each call to this operation effectively takes O(script-size) time, we need a replacement for the functionality it currently provides. While perhaps the original motivation for OP_CODESEPARTOR is surrounded in mystery, it currently can be used (or perhaps abused) for the task of creating signature that covers, not only which input is being signed, but which specific branch within that input Script code is being signed for. > > For example, one can place an OP_CODESEPARATOR within each branch of an IF block, or by placing an OP_CODESEPARATOR before each OP_CHECKSIG operation. By doing so, signatures created for one clause cannot be used as signatures for another clause. Since different clauses in Bitcoin Script may be enforcing different conditions (such as different time-locks, hash-locks, etc), it is useful to be able to sign in such a way that your signature is only valid when the conditions for a particular branch are satisfied. In complex Scripts, it may not be practical or possible to use different public keys for every different clause. (In practice, you will be able to get away with fewer OP_CODESEPARATORS than one in every IF block). > > One suggestion I heard (I think I heard it from Pieter) to achieve the above is to add an internal counter that increments on every control flow operator, OP_IF, OP_NOTIF, OP_ELSE, OP_ENDIF, and have the signature cover the value of this counter. Equivalently we divide every Bitcoin Script program into blocks deliminated by these control flow operator and have the signature cover the index of the block that the OP_CHECKSIG occurs within. More specifically, we will want a SigHash flag to enables/disable the signature covering this counter. > > There are many different ways one might go about replacing the remaining useful behaviour of OP_CODESEPARATOR than the one I gave above. I would be happy with any solution. > _______________________________________________ > bitcoin-dev mailing list > bitcoin-dev@lists.linuxfoundation.org > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev [-- Attachment #2: Type: text/html, Size: 3989 bytes --] ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-22 14:28 ` Johnson Lau @ 2018-11-22 16:23 ` Russell O'Connor 2018-11-22 20:52 ` Johnson Lau 0 siblings, 1 reply; 55+ messages in thread From: Russell O'Connor @ 2018-11-22 16:23 UTC (permalink / raw) To: Johnson Lau; +Cc: Bitcoin Protocol Discussion [-- Attachment #1: Type: text/plain, Size: 3384 bytes --] I see, so your suggestion is that a sequence of OP_IF ... OP_ENDIF can be replaced by a Merklized Script tree of that depth in practice. I'm concerned that at script creation time it takes exponential time to complete a Merkle root of depth 'n'. Can anyone provide benchmarks or estimates of how long it takes to compute a Merkle root of a full tree of various depths on typical consumer hardware? I would guess things stop becoming practical at a depth of 20-30. On Thu, Nov 22, 2018 at 9:28 AM Johnson Lau <jl2012@xbt.hk> wrote: > With MAST in taproot, OP_IF etc become mostly redundant, with worse > privacy. To maximise fungibility, we should encourage people to use MAST, > instead of improve the functionality of OP_IF and further complicate the > protocol. > > > On 22 Nov 2018, at 1:07 AM, Russell O'Connor via bitcoin-dev < > bitcoin-dev@lists.linuxfoundation.org> wrote: > > On Mon, Nov 19, 2018 at 10:22 PM Pieter Wuille via bitcoin-dev < > bitcoin-dev@lists.linuxfoundation.org> wrote: > >> So my question is whether anyone can see ways in which this introduces >> redundant flexibility, or misses obvious use cases? >> > > Hopefully my comment is on-topic for this thread: > > Given that we want to move away from OP_CODESEPARATOR, because each call > to this operation effectively takes O(script-size) time, we need a > replacement for the functionality it currently provides. While perhaps the > original motivation for OP_CODESEPARTOR is surrounded in mystery, it > currently can be used (or perhaps abused) for the task of creating > signature that covers, not only which input is being signed, but which > specific branch within that input Script code is being signed for. > > For example, one can place an OP_CODESEPARATOR within each branch of an IF > block, or by placing an OP_CODESEPARATOR before each OP_CHECKSIG > operation. By doing so, signatures created for one clause cannot be used > as signatures for another clause. Since different clauses in Bitcoin > Script may be enforcing different conditions (such as different time-locks, > hash-locks, etc), it is useful to be able to sign in such a way that your > signature is only valid when the conditions for a particular branch are > satisfied. In complex Scripts, it may not be practical or possible to use > different public keys for every different clause. (In practice, you will be > able to get away with fewer OP_CODESEPARATORS than one in every IF block). > > One suggestion I heard (I think I heard it from Pieter) to achieve the > above is to add an internal counter that increments on every control flow > operator, OP_IF, OP_NOTIF, OP_ELSE, OP_ENDIF, and have the signature cover > the value of this counter. Equivalently we divide every Bitcoin Script > program into blocks deliminated by these control flow operator and have the > signature cover the index of the block that the OP_CHECKSIG occurs within. > More specifically, we will want a SigHash flag to enables/disable the > signature covering this counter. > > There are many different ways one might go about replacing the remaining > useful behaviour of OP_CODESEPARATOR than the one I gave above. I would be > happy with any solution. > _______________________________________________ > bitcoin-dev mailing list > bitcoin-dev@lists.linuxfoundation.org > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev > > > [-- Attachment #2: Type: text/html, Size: 4492 bytes --] ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-22 16:23 ` Russell O'Connor @ 2018-11-22 20:52 ` Johnson Lau 2018-11-22 22:10 ` Russell O'Connor 0 siblings, 1 reply; 55+ messages in thread From: Johnson Lau @ 2018-11-22 20:52 UTC (permalink / raw) To: Russell O'Connor; +Cc: bitcoin-dev Assuming a script size of 128 bytes (including SHA256 padding), 2^20 scripts is 134MB. Double it to 268MB for the merkle branch hashes. With roughly 100MB/s, this should take 2.5s (or 42min for 30 levels). However, memory use is not considered. >each call to this operation effectively takes O(script-size) time I’m not sure if this is correct. Actually, CTransactionSignatureSerializer() scans every script for OP_CODESEPARATOR. Scripts with and without OP_CODESEPARATOR should take exactly the same O(script-size) time (see https://github.com/bitcoin/bitcoin/pull/14786) Also, this is no longer a concern under segwit (BIP143), which CTransactionSignatureSerializer() is not used. Actually, OP_CODESEPARATOR under segwit is way simpler than the proposed OP_MASK. If one finds OP_MASK acceptable, there should be no reason to reject OP_CODESEPARATOR. >One suggestion I heard (I think I heard it from Pieter) to achieve the above is to add an internal counter that increments on every control flow operator,……... If I have to choose among OP_CODESEPARATOR and “flow operator counting”, I’d rather choose OP_CODESEPARATOR. At least we don’t need to add more lines to the consensus code, just for something that is mostly archivable with MAST. > On 23 Nov 2018, at 12:23 AM, Russell O'Connor <roconnor@blockstream.io> wrote: > > I see, so your suggestion is that a sequence of OP_IF ... OP_ENDIF can be replaced by a Merklized Script tree of that depth in practice. > > I'm concerned that at script creation time it takes exponential time to complete a Merkle root of depth 'n'. Can anyone provide benchmarks or estimates of how long it takes to compute a Merkle root of a full tree of various depths on typical consumer hardware? I would guess things stop becoming practical at a depth of 20-30. > > On Thu, Nov 22, 2018 at 9:28 AM Johnson Lau <jl2012@xbt.hk> wrote: > With MAST in taproot, OP_IF etc become mostly redundant, with worse privacy. To maximise fungibility, we should encourage people to use MAST, instead of improve the functionality of OP_IF and further complicate the protocol. > > >> On 22 Nov 2018, at 1:07 AM, Russell O'Connor via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> wrote: >> >> On Mon, Nov 19, 2018 at 10:22 PM Pieter Wuille via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> wrote: >> So my question is whether anyone can see ways in which this introduces >> redundant flexibility, or misses obvious use cases? >> >> Hopefully my comment is on-topic for this thread: >> >> Given that we want to move away from OP_CODESEPARATOR, because each call to this operation effectively takes O(script-size) time, we need a replacement for the functionality it currently provides. While perhaps the original motivation for OP_CODESEPARTOR is surrounded in mystery, it currently can be used (or perhaps abused) for the task of creating signature that covers, not only which input is being signed, but which specific branch within that input Script code is being signed for. >> >> For example, one can place an OP_CODESEPARATOR within each branch of an IF block, or by placing an OP_CODESEPARATOR before each OP_CHECKSIG operation. By doing so, signatures created for one clause cannot be used as signatures for another clause. Since different clauses in Bitcoin Script may be enforcing different conditions (such as different time-locks, hash-locks, etc), it is useful to be able to sign in such a way that your signature is only valid when the conditions for a particular branch are satisfied. In complex Scripts, it may not be practical or possible to use different public keys for every different clause. (In practice, you will be able to get away with fewer OP_CODESEPARATORS than one in every IF block). >> >> One suggestion I heard (I think I heard it from Pieter) to achieve the above is to add an internal counter that increments on every control flow operator, OP_IF, OP_NOTIF, OP_ELSE, OP_ENDIF, and have the signature cover the value of this counter. Equivalently we divide every Bitcoin Script program into blocks deliminated by these control flow operator and have the signature cover the index of the block that the OP_CHECKSIG occurs within. More specifically, we will want a SigHash flag to enables/disable the signature covering this counter. >> >> There are many different ways one might go about replacing the remaining useful behaviour of OP_CODESEPARATOR than the one I gave above. I would be happy with any solution. >> _______________________________________________ >> bitcoin-dev mailing list >> bitcoin-dev@lists.linuxfoundation.org >> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev > ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-22 20:52 ` Johnson Lau @ 2018-11-22 22:10 ` Russell O'Connor 2018-11-23 10:47 ` Johnson Lau 0 siblings, 1 reply; 55+ messages in thread From: Russell O'Connor @ 2018-11-22 22:10 UTC (permalink / raw) To: Johnson Lau; +Cc: Bitcoin Protocol Discussion [-- Attachment #1: Type: text/plain, Size: 2163 bytes --] On Thu, Nov 22, 2018 at 3:53 PM Johnson Lau <jl2012@xbt.hk> wrote: > Assuming a script size of 128 bytes (including SHA256 padding), 2^20 > scripts is 134MB. Double it to 268MB for the merkle branch hashes. With > roughly 100MB/s, this should take 2.5s (or 42min for 30 levels). However, > memory use is not considered. > > >each call to this operation effectively takes O(script-size) time > I’m not sure if this is correct. Actually, > CTransactionSignatureSerializer() scans every script for OP_CODESEPARATOR. > Scripts with and without OP_CODESEPARATOR should take exactly the same > O(script-size) time (see https://github.com/bitcoin/bitcoin/pull/14786) > Also, this is no longer a concern under segwit (BIP143), which > CTransactionSignatureSerializer() is not used. Actually, OP_CODESEPARATOR > under segwit is way simpler than the proposed OP_MASK. If one finds OP_MASK > acceptable, there should be no reason to reject OP_CODESEPARATOR. > Even still, each call to OP_CODESEPARATOR / OP_CHECKSIG pair requires recomputing a new #5. scriptCode from BIP 143, and hence computes a new transaction digest. I understood that this issue was the main motivation for wanting to deprecate OP_CODESEPARATOR and remove it from later versions of script. However, given that we are looking at a combinatorial explosion in SIGHASH flag combinations already, coupled with existing SigOp limitations, maybe the cost of recomputing scriptCode with OP_CODESEPARATOR isn't such a big deal. And even if we choose remove the behavior of OP_CODESEPARATOR in new versions of Script, it seems more than 30 layers of sequential OP_IFs can be MASTified, so there is no need to use OP_CODESEPARATOR within that limit. >One suggestion I heard (I think I heard it from Pieter) to achieve the above is to add an internal counter that increments on every control flow operator,……... > If I have to choose among OP_CODESEPARATOR and “flow operator counting”, > I’d rather choose OP_CODESEPARATOR. At least we don’t need to add more > lines to the consensus code, just for something that is mostly archivable > with MAST. > [-- Attachment #2: Type: text/html, Size: 2721 bytes --] ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-22 22:10 ` Russell O'Connor @ 2018-11-23 10:47 ` Johnson Lau 0 siblings, 0 replies; 55+ messages in thread From: Johnson Lau @ 2018-11-23 10:47 UTC (permalink / raw) To: Russell O'Connor; +Cc: bitcoin-dev [-- Attachment #1: Type: text/plain, Size: 3604 bytes --] >Even still, each call to OP_CODESEPARATOR / OP_CHECKSIG pair requires recomputing a new #5. scriptCode from BIP 143, and hence computes a new transaction digest. In the existing sighash (i.e. legacy and BIP143), there are 6 canonical SIGHASH types: 1, 2, 3, 0x81, 0x82, 0x83. In consensus, however, all 256 types are valid and distinct. An adversarial miner could use non-standard sighash types to nullify any attempt to cache sighash values (i.e. you have to compute a new tx digest for every OP_CHECKSIG, even without using OP_CODESEPARATOR). The only way to prevent this is reject OP_CODESEPARATOR, FindAndDelete(), and non-standard SIGHASH with a softfork. However, this doesn’t work in the next-generation SIGHASH, as tens of standard sighash types will exist. And, more importantly, sighash cache is no longer necessary in segwit, with the legacy O(n^2) hash bug being fixed. In summary, sighash cache is not necessary nor efficient in the next-generation SIGHASH, and is not a sufficient reason to remove OP_CODESEPARATOR, especially when people find OP_CODESEPARATOR useful in some way. But just to be clear, I think OP_CODESEPARATOR should be deprecated in legacy scripts. There is a general negative sentiment against OP_CODESEPARATOR but I think we need to evaluate case by case. > On 23 Nov 2018, at 6:10 AM, Russell O'Connor <roconnor@blockstream.io> wrote: > > > > On Thu, Nov 22, 2018 at 3:53 PM Johnson Lau <jl2012@xbt.hk <mailto:jl2012@xbt.hk>> wrote: > Assuming a script size of 128 bytes (including SHA256 padding), 2^20 scripts is 134MB. Double it to 268MB for the merkle branch hashes. With roughly 100MB/s, this should take 2.5s (or 42min for 30 levels). However, memory use is not considered. > > >each call to this operation effectively takes O(script-size) time > I’m not sure if this is correct. Actually, CTransactionSignatureSerializer() scans every script for OP_CODESEPARATOR. Scripts with and without OP_CODESEPARATOR should take exactly the same O(script-size) time (see https://github.com/bitcoin/bitcoin/pull/14786 <https://github.com/bitcoin/bitcoin/pull/14786>) > Also, this is no longer a concern under segwit (BIP143), which CTransactionSignatureSerializer() is not used. Actually, OP_CODESEPARATOR under segwit is way simpler than the proposed OP_MASK. If one finds OP_MASK acceptable, there should be no reason to reject OP_CODESEPARATOR. > > Even still, each call to OP_CODESEPARATOR / OP_CHECKSIG pair requires recomputing a new #5. scriptCode from BIP 143, and hence computes a new transaction digest. I understood that this issue was the main motivation for wanting to deprecate OP_CODESEPARATOR and remove it from later versions of script. > > However, given that we are looking at a combinatorial explosion in SIGHASH flag combinations already, coupled with existing SigOp limitations, maybe the cost of recomputing scriptCode with OP_CODESEPARATOR isn't such a big deal. > > And even if we choose remove the behavior of OP_CODESEPARATOR in new versions of Script, it seems more than 30 layers of sequential OP_IFs can be MASTified, so there is no need to use OP_CODESEPARATOR within that limit. > > >One suggestion I heard (I think I heard it from Pieter) to achieve the above is to add an internal counter that increments on every control flow operator,……... > If I have to choose among OP_CODESEPARATOR and “flow operator counting”, I’d rather choose OP_CODESEPARATOR. At least we don’t need to add more lines to the consensus code, just for something that is mostly archivable with MAST. > [-- Attachment #2: Type: text/html, Size: 4989 bytes --] ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-21 17:07 ` Russell O'Connor 2018-11-22 14:28 ` Johnson Lau @ 2018-11-23 5:03 ` Anthony Towns 2018-11-23 20:18 ` Russell O'Connor 1 sibling, 1 reply; 55+ messages in thread From: Anthony Towns @ 2018-11-23 5:03 UTC (permalink / raw) To: Russell O'Connor, Bitcoin Protocol Discussion On Wed, Nov 21, 2018 at 12:07:30PM -0500, Russell O'Connor via bitcoin-dev wrote: > Given that we want to move away from OP_CODESEPARATOR, because each call to > this operation effectively takes O(script-size) time, we need a replacement for > the functionality it currently provides. While perhaps the original motivation > for OP_CODESEPARTOR is surrounded in mystery, it currently can be used (or > perhaps abused) for the task of creating signature that covers, not only which > input is being signed, but which specific branch within that input Script code > is being signed for. Would it be sufficient to sign the position within the script of the last OP_CODESEPARATOR? That is, if your script is: DUP DUP CHECKSIG CODESEP CHECKSIG CODESEP CHECKSIG with the idea being that it can be spent by providing any pub key and three different signatures by that key, with the first sig committing to a "codesep position" of 0, the second a "codesep position" of 4, and the third a "codesep position" of 6? In each case, the signature also commits to the full (possibly masked) script as well. I think that covers all the behaviour you can currently achieve with CODESEP (which is pretty limited since every sig effectively commits to the full redeem script, and you can't commit to subsets of the signature/witness), and it keeps the things you can do with the various features a bit orthogonal: NOINPUT -- lets the sig apply to different transactions OP_MASK -- lets the different txes have variations in the script the sig applies to CODESEP -- lets you require different sigs for different parts of a single script MAST[0] -- provides alternative scripts, doesn't affect sigs IF/etc -- provides control flow within a script, doesn't affect sigs Cheers, aj [0] (I think I'm going to claim "MAST" stands for "merkelized alternative script tree" these days, since they're not "abstract syntax trees") ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-23 5:03 ` Anthony Towns @ 2018-11-23 20:18 ` Russell O'Connor 0 siblings, 0 replies; 55+ messages in thread From: Russell O'Connor @ 2018-11-23 20:18 UTC (permalink / raw) To: Anthony Towns; +Cc: Bitcoin Protocol Discussion [-- Attachment #1: Type: text/plain, Size: 2158 bytes --] On Fri, Nov 23, 2018 at 12:03 AM Anthony Towns <aj@erisian.com.au> wrote: > On Wed, Nov 21, 2018 at 12:07:30PM -0500, Russell O'Connor via bitcoin-dev > wrote: > > Given that we want to move away from OP_CODESEPARATOR, because each call > to > > this operation effectively takes O(script-size) time, we need a > replacement for > > the functionality it currently provides. While perhaps the original > motivation > > for OP_CODESEPARTOR is surrounded in mystery, it currently can be used > (or > > perhaps abused) for the task of creating signature that covers, not only > which > > input is being signed, but which specific branch within that input > Script code > > is being signed for. > > Would it be sufficient to sign the position within the script of the > last OP_CODESEPARATOR? That is, if your script is: > > I think that covers all the behaviour you can currently achieve with > CODESEP (which is pretty limited since every sig effectively commits > to the full redeem script, and you can't commit to subsets of the > signature/witness), and it keeps the things you can do with the various > features a bit orthogonal: > Thanks for bringing this up. I was thinking the same thing as well, that yes that should be sufficient to cover the semantics of OP_CODESEPARATOR. Though to be more precise you would sign the position of the last _executed_ OP_CODESEPARATOR. That said, while I agree the above is a superior realization of the OP_CODESEPARATOR, given that we are probably going to support OP_CODESEPARATOR inside legacy P2SH scripts indefinitely, it is probably better to keep the existing akward implementation of OP_CODESEPARATOR in future versions of Script. (At least until we decide to stop mangling the Script consensus code with more and more flag combinations and decide it is better to cut and paste code for new versions of Script to help ensure we don't make consensus changes to legacy behaviour). > [0] (I think I'm going to claim "MAST" stands for "merkelized alternative > script tree" these days, since they're not "abstract syntax trees") > :thumbs-up: Sorry for hijacking the thread about OP_MASK and friends. [-- Attachment #2: Type: text/html, Size: 2757 bytes --] ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-19 22:37 [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT Pieter Wuille ` (2 preceding siblings ...) 2018-11-21 17:07 ` Russell O'Connor @ 2018-11-28 3:41 ` Pieter Wuille 2018-11-28 8:31 ` Johnson Lau ` (2 more replies) 2018-12-12 9:42 ` Rusty Russell 4 siblings, 3 replies; 55+ messages in thread From: Pieter Wuille @ 2018-11-28 3:41 UTC (permalink / raw) To: Bitcoin Dev On Mon, 19 Nov 2018 at 14:37, Pieter Wuille <pieter.wuille@gmail.com> wrote: > Here is a combined proposal: > * Three new sighash flags are added: SIGHASH_NOINPUT, SIGHASH_NOFEE, and SIGHASH_SCRIPTMASK. > * A new opcode OP_MASK is added, which acts as a NOP during execution. > * The sighash is computed like in BIP143, but: > * If SIGHASH_SCRIPTMASK is present, for every OP_MASK in scriptCode the subsequent opcode/push is removed. > * The scriptPubKey being spent is added to the sighash, unless SIGHASH_SCRIPTMASK is set. > * The transaction fee is added to the sighash, unless SIGHASH_NOFEE is set. > * hashPrevouts, hashSequence, and outpoint are set to null when SIGHASH_NOINPUT is set (like BIP118, but not for scriptCode). Thanks for all the input so far. Going over the suggestions and other ideas: * OP_MASK should be required to be followed by a push, as suggested by Anthony Towns. The alternative would permit substituting arbitrary opcodes for masked pushes, which is at least very hard to reason about. This would effectively turn it into a multi-byte OP_MASKEDPUSH opcode. * It's probably better to sign the amounts of all inputs, as suggested by Johnson Lau. As that would cause default sighashes to sign all input and output amounts, is there still a need to sign the tx fee explicitly? Or in other words, are there situations where changing the set of inputs or outputs after signing is desired, but the net difference between them cannot change? If not, that would remove the need for NOFEE. * Do we need to keep the rule that sequence values of other inputs are only signed with default sighash? It feels cleaner to always sign the sequence values of all inputs that are included in the sighash anyway (so all of them, unless ANYONECANPAY or NOINPUT, which would make it sign only the current input's sequence value). If NOINPUT also blanks the sequence values (as currently specified by BIP118), and all input amounts are signed, that would make amounts/sequence values always be treated identically. * If MASK implies NOINPUT, and NOINPUT implies ANYONECANPAY, the 3 of them can be encoded in just 2 bits using the PARTIALSCRIPT/KNOWNSCRIPT/KNOWNTX/ALL_INPUTS encoding Anthony Towns suggested. * Regarding the discussion about preventing signatures from being rebound to a different script(path)/checksig: * With MAST there is indeed less need for this, but at least single-tree MAST constructions cannot replace all script branches (a script with 40 IF/THEN/ELSE constructions may have 2^40 different execution paths, for which computing a Merkle tree is intractable). * Just signing the opcode position of the CHECKSIG operator isn't enough for all cases either. For example, you could have a complex nested set of branches that puts a number of pubkeys on the stack, and then a CHECKMULTISIG after the last ENDIF to verify all of them. In such a situation, if the same key can occur in multiple combinations, you still may want to prevent a signature generated for one combination from being rebindable to the same key in another combination. I believe that signing the opcode position plus the true/false condition of all previous(?) IF statements is probably sufficient to achieve that, but it would also introduce unnecessary complexity for signers in most cases (see next point). * Thinking about signing code, adding these sort of execution trace commitments to the sighash means they need to know which checksig operator etc. they are signing for. I believe that in practice for example HW devices will just whatever position the wallet indicated, rather than verifying it corresponds with a particular intended code path. Preventing rebinding isn't very useful if an attacker can make you bind to the wrong thing regardless, so I'm not convinced this is even worth having by default. * An alternative (not sure who suggested it) is to simply make every CHECKSIG sign the opcode position of the last executed CODESEPARATOR (and remove the earlier cut-of-scriptCode effect of CODESEPARATOR). This gives a simple (but somewhat limited) way for scripts that need to prevent certain kinds of cross-execution-trace rebinding. A few misc ideas: * (Taken from https://github.com/jl2012/bips/blob/sighash2/bip-sighash2.mediawiki) For a default sign-everything sighash, the sighash byte can be dropped. * For the commitments to the scriptPubKey and scriptCode, an intermediary hash should be used (so the data included in the sighash includes a hash of those, rather than the script directly). This prevents a blow up in hashing time for large scripts with many different sighash types in its signatures. * When masking the scriptCode, the push opcode immediately following OP_MASKEDPUSH can be replaced by OP_VERIF (which will never collide with any real script, as OP_VERIF makes a script invalid even when occurring in an unexecuted branch). * Sighashes (and really all new hashes that are introduced) should be prefixed with a fixed 64-byte array as "tag", chosen to not collide with any existing use of SHA256 in Bitcoin, to prevent signatures from being re-interpretable as something else. Picking 64 bytes as tag size means it can be efficiently implemented as just a modified SHA256 IV. So a combined proposal: * All existing sighash flags, plus NOINPUT and MASK (ANYONECANPAY/NOINPUT/MASK are encoded in 2 bits). * A new opcode called OP_MASKEDPUSH, whose only runtime behaviour is failing if not immediately followed by a push, or when appearing as last opcode in the script. * Signatures are 64 plus an optional sighash byte. A missing sighash byte implies ALL, and ALL cannot be specified explicitly. * The sighash is computed from the following: * A 64-byte constant tag * Data about the spending transaction: * The transaction version number * The hash of txins' prevouts+amounts+sequences (or nothing if ANYONECANPAY) * The hash of all txouts (or just the corresponding txout if SINGLE; nothing if NONE) * The transaction locktime * Data about the output being spent: * The prevout (or nothing if NOINPUT) * The amount * The sequence number * The hash of the scriptPubKey (or nothing if MASK) * Data about the script being executed: * The hash of the scriptCode (after masking out, if MASK is set) * The opcode number of the last executed OP_CODESEPARATOR (or 0xFFFFFFFF if none) * The sighash mode Cheers, -- Pieter ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-28 3:41 ` Pieter Wuille @ 2018-11-28 8:31 ` Johnson Lau 2018-11-29 17:00 ` Christian Decker 2018-12-06 16:57 ` Russell O'Connor 2 siblings, 0 replies; 55+ messages in thread From: Johnson Lau @ 2018-11-28 8:31 UTC (permalink / raw) To: Pieter Wuille, bitcoin-dev [-- Attachment #1: Type: text/plain, Size: 4204 bytes --] > On 28 Nov 2018, at 11:41 AM, Pieter Wuille via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> wrote: > > So a combined proposal: > * All existing sighash flags, plus NOINPUT and MASK > (ANYONECANPAY/NOINPUT/MASK are encoded in 2 bits). > * A new opcode called OP_MASKEDPUSH, whose only runtime behaviour is > failing if not immediately followed by a push, or when appearing as > last opcode in the script. I suggest to use the place of OP_RESERVED (0x50) as OP_MASKEDPUSH. The reason is 0x50 is not counted towards the 201 opcode limit, so people could mask as many pushes as needed. In a new script version, of course, we could make any opcode not being counted. But that would just create another special case in the EvalScript() code. (Or, maybe we should limit the use of OP_MASKEDPUSH? I think this is open for discussion.) > * Signatures are 64 plus an optional sighash byte. A missing sighash > byte implies ALL, and ALL cannot be specified explicitly. > * The sighash is computed from the following: > * A 64-byte constant tag > * Data about the spending transaction: > * The transaction version number > * The hash of txins' prevouts+amounts+sequences (or nothing if ANYONECANPAY) Do you want to make it 1 hash or 3 hashes? With 3 hashes, it could share hashPrevouts and hashSequence with BIP143. Making everything 1 hash will only result in redundent hashing for each input > * The hash of all txouts (or just the corresponding txout if > SINGLE; nothing if NONE) Starting from this sighash version, I think we should forbid the use of SINGLE without a matching output. Also, the undefined output type should also be invalid. > * The transaction locktime > * Data about the output being spent: > * The prevout (or nothing if NOINPUT) > * The amount > * The sequence number > * The hash of the scriptPubKey (or nothing if MASK) I think we should just use the scriptPubKey, since sPK is fixed size (23-byte for p2sh and 35-byte for native segwit). In order to distinguish p2sh and native segwit for MASKED NOINPUT, you also need to commit to an additional 1-bit value > * Data about the script being executed: > * The hash of the scriptCode (after masking out, if MASK is set) For direct key-spending (i.e. not taprooted script), I suggest to set the H(scriptCode) to zero, for the following reasons: 1) Since we have already committed to sPK, which is already a *direct* hash of scriptCode, it is redundant to do it again. 2) This could save one SHA256 compression for direct key-spending, which is probably 90% of all cases 3) This allows hardware wallet to tell whether they are using direct-spending path or taproot script path Since we may want 3) anyway, we don’t need to commit to another 1-bit value if we simply set H(scriptCode) to zero We should also ban MASKED NOINPUT for direct-spending, which doesn’t make sense. And it is not safe since both H(scriptCode) and sPK are empty. > * The opcode number of the last executed OP_CODESEPARATOR (or > 0xFFFFFFFF if none) > * The sighash mode This proposal will only use 4 out of the 8 sighash bits. Do we want to make those 4 unused bits invalid, or ignored? Leaving at least 1 bit valid but ignored (“bit-x"), and 1 bit invalid (“bit-y”), will allow opt-in/out hardfork replay-protection, for example: * default signatures are those with both bit-x and bit-y unset. * If we want to make default signatures replayable across chains, the new fork should reject signatures with bit-x, and accept sigs with or without bit-y. In this case, defaults sigs are valid for both chains. Sigs with bit-x is valid only for original chain, and sigs with bit-y is valid only for new chain. * If we want to make default signatures non-replayabble, the new fork should reject all default sigs, but accept sigs with either bit-x or bit-y set. In this case, default sig is valid only for original chain. Sigs with bit-x is valid for both chains, and sigs with bit-y is valid only for new chain. Replayability is sometimes desirable, for example, an LN opened before a fork should be able to be settled on both chains [-- Attachment #2: Type: text/html, Size: 23919 bytes --] ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-28 3:41 ` Pieter Wuille 2018-11-28 8:31 ` Johnson Lau @ 2018-11-29 17:00 ` Christian Decker 2018-11-29 18:29 ` Christian Decker 2018-12-06 16:57 ` Russell O'Connor 2 siblings, 1 reply; 55+ messages in thread From: Christian Decker @ 2018-11-29 17:00 UTC (permalink / raw) To: Pieter Wuille, Bitcoin Protocol Discussion, Bitcoin Dev Pieter Wuille via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> writes: > On Mon, 19 Nov 2018 at 14:37, Pieter Wuille <pieter.wuille@gmail.com> wrote: > * It's probably better to sign the amounts of all inputs, as suggested > by Johnson Lau. As that would cause default sighashes to sign all > input and output amounts, is there still a need to sign the tx fee > explicitly? Or in other words, are there situations where changing the > set of inputs or outputs after signing is desired, but the net > difference between them cannot change? If not, that would remove the > need for NOFEE. So the final proposal would be to append a new `hashValues` field to the hashed representation, with `hashValues` just being the double SHA256 of all values? In that case SINGLE needs to blank that hash, otherwise we'd be committing to all inputs again. Once we have that detail, we can start thinking about what it means to commit to the fee vs. committing to the values. Since the fee is given by the output values and the input values we only need to consider the cases in which they can be modified. - NOINPUT (as in BIP118) commits to the value (and I can't think of a usecase where we'd want to change that), and that transparently extends to all other inputs. - For ANYONECANPAY can't really commit to a fee anyway so ANYONECANPAY would likely imply NOFEE. - With NONE all bets are off anyway, so no need to consider that :-) - SINGLE is a bit special, and for value commitments it reduces to the current commitment to its own value, for fee commitment it's hard to see a use of that commitment at all afaik (I think the combination SINGLE|NOFEE would always be used). > * Do we need to keep the rule that sequence values of other inputs are > only signed with default sighash? It feels cleaner to always sign the > sequence values of all inputs that are included in the sighash anyway > (so all of them, unless ANYONECANPAY or NOINPUT, which would make it > sign only the current input's sequence value). If NOINPUT also blanks > the sequence values (as currently specified by BIP118), and all input > amounts are signed, that would make amounts/sequence values always be > treated identically. Single cannot commit to other the sequence of other inputs, otherwise we're breaking SINGLE completely. As mentioned before NOINPUT doesn't need to blank `hashSequence`, but I'm happy to make it match if that makes implementations handle fewer cases. > * If MASK implies NOINPUT, and NOINPUT implies ANYONECANPAY, the 3 of > them can be encoded in just 2 bits using the > PARTIALSCRIPT/KNOWNSCRIPT/KNOWNTX/ALL_INPUTS encoding Anthony Towns > suggested. So we'd end up enumerating the combinations rather than having independent bits for each of them? This might save us storage bits, but it'd also result in uglier code imho, not a strong feeling but might come back to haunt us if we ever come up with something new :-) > So a combined proposal: > * All existing sighash flags, plus NOINPUT and MASK > (ANYONECANPAY/NOINPUT/MASK are encoded in 2 bits). > * A new opcode called OP_MASKEDPUSH, whose only runtime behaviour is > failing if not immediately followed by a push, or when appearing as > last opcode in the script. > * Signatures are 64 plus an optional sighash byte. A missing sighash > byte implies ALL, and ALL cannot be specified explicitly. > * The sighash is computed from the following: > * A 64-byte constant tag > * Data about the spending transaction: > * The transaction version number > * The hash of txins' prevouts+amounts+sequences (or nothing if ANYONECANPAY) This needs to be partially blanked for SINGLE as well, otherwise we break SINGLE. > * The hash of all txouts (or just the corresponding txout if > SINGLE; nothing if NONE) > * The transaction locktime > * Data about the output being spent: > * The prevout (or nothing if NOINPUT) > * The amount > * The sequence number I assume the sequence number here refers to the input being signed, not the sequence number of the transaction output being spent :-) Might be easier if we consider 3 parts: the spending transaction, the input being signed, and the output (or TX) being spent. Cheers, Christian ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-29 17:00 ` Christian Decker @ 2018-11-29 18:29 ` Christian Decker 0 siblings, 0 replies; 55+ messages in thread From: Christian Decker @ 2018-11-29 18:29 UTC (permalink / raw) To: Pieter Wuille, Bitcoin Protocol Discussion, Bitcoin Dev I'd like to retract my comments regarding SINGLE. I was contacted in private and it was pointed out to me that I was confusing `sighash_single` with `sighash_single|sighash_anyonecanpay`. I appreciate the correction and would like to avoid creating confusion with my previous comments, hence the retraction :-) Cheers, Christian ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-28 3:41 ` Pieter Wuille 2018-11-28 8:31 ` Johnson Lau 2018-11-29 17:00 ` Christian Decker @ 2018-12-06 16:57 ` Russell O'Connor 2018-12-09 19:13 ` Johnson Lau 2018-12-09 22:41 ` David A. Harding 2 siblings, 2 replies; 55+ messages in thread From: Russell O'Connor @ 2018-12-06 16:57 UTC (permalink / raw) To: Pieter Wuille, Bitcoin Protocol Discussion [-- Attachment #1: Type: text/plain, Size: 8004 bytes --] One more item to consider is "signature covers witness weight". While signing the witness weight doesn't completely eliminate witness malleability (of the kind that can cause grief for compact blocks), it does eliminate the worst kind of witness malleability from the user's perspective, the kind where malicious relay nodes increase the amount of witness data and therefore reduce the overall fee-rate of the transaction. Generally users should strive to construct their Bitcoin Scripts in such a way that witness malleability isn't possible, but as you are probably aware, this can be quite difficult to achieve as Scripts become more complex and maybe isn't even possible for some complex Scripts. Given the new fixed-sized signature of the Schnorr BIP, it becomes much easier to compute the final witness weight prior to signing. In complex multi-party signing protocol, the final witness weight might not be known at signing time for everyone involved, so the "signature covers witness weight" ought to be optional. On Tue, Nov 27, 2018 at 11:59 PM Pieter Wuille via bitcoin-dev < bitcoin-dev@lists.linuxfoundation.org> wrote: > On Mon, 19 Nov 2018 at 14:37, Pieter Wuille <pieter.wuille@gmail.com> > wrote: > > Here is a combined proposal: > > * Three new sighash flags are added: SIGHASH_NOINPUT, SIGHASH_NOFEE, and > SIGHASH_SCRIPTMASK. > > * A new opcode OP_MASK is added, which acts as a NOP during execution. > > * The sighash is computed like in BIP143, but: > > * If SIGHASH_SCRIPTMASK is present, for every OP_MASK in scriptCode > the subsequent opcode/push is removed. > > * The scriptPubKey being spent is added to the sighash, unless > SIGHASH_SCRIPTMASK is set. > > * The transaction fee is added to the sighash, unless SIGHASH_NOFEE is > set. > > * hashPrevouts, hashSequence, and outpoint are set to null when > SIGHASH_NOINPUT is set (like BIP118, but not for scriptCode). > > Thanks for all the input so far. Going over the suggestions and other > ideas: > > * OP_MASK should be required to be followed by a push, as suggested by > Anthony Towns. The alternative would permit substituting arbitrary > opcodes for masked pushes, which is at least very hard to reason > about. This would effectively turn it into a multi-byte OP_MASKEDPUSH > opcode. > > * It's probably better to sign the amounts of all inputs, as suggested > by Johnson Lau. As that would cause default sighashes to sign all > input and output amounts, is there still a need to sign the tx fee > explicitly? Or in other words, are there situations where changing the > set of inputs or outputs after signing is desired, but the net > difference between them cannot change? If not, that would remove the > need for NOFEE. > > * Do we need to keep the rule that sequence values of other inputs are > only signed with default sighash? It feels cleaner to always sign the > sequence values of all inputs that are included in the sighash anyway > (so all of them, unless ANYONECANPAY or NOINPUT, which would make it > sign only the current input's sequence value). If NOINPUT also blanks > the sequence values (as currently specified by BIP118), and all input > amounts are signed, that would make amounts/sequence values always be > treated identically. > > * If MASK implies NOINPUT, and NOINPUT implies ANYONECANPAY, the 3 of > them can be encoded in just 2 bits using the > PARTIALSCRIPT/KNOWNSCRIPT/KNOWNTX/ALL_INPUTS encoding Anthony Towns > suggested. > > * Regarding the discussion about preventing signatures from being > rebound to a different script(path)/checksig: > * With MAST there is indeed less need for this, but at least > single-tree MAST constructions cannot replace all script branches (a > script with 40 IF/THEN/ELSE constructions may have 2^40 different > execution paths, for which computing a Merkle tree is intractable). > * Just signing the opcode position of the CHECKSIG operator isn't > enough for all cases either. For example, you could have a complex > nested set of branches that puts a number of pubkeys on the stack, and > then a CHECKMULTISIG after the last ENDIF to verify all of them. In > such a situation, if the same key can occur in multiple combinations, > you still may want to prevent a signature generated for one > combination from being rebindable to the same key in another > combination. I believe that signing the opcode position plus the > true/false condition of all previous(?) IF statements is probably > sufficient to achieve that, but it would also introduce unnecessary > complexity for signers in most cases (see next point). > * Thinking about signing code, adding these sort of execution trace > commitments to the sighash means they need to know which checksig > operator etc. they are signing for. I believe that in practice for > example HW devices will just whatever position the wallet indicated, > rather than verifying it corresponds with a particular intended code > path. Preventing rebinding isn't very useful if an attacker can make > you bind to the wrong thing regardless, so I'm not convinced this is > even worth having by default. > * An alternative (not sure who suggested it) is to simply make every > CHECKSIG sign the opcode position of the last executed CODESEPARATOR > (and remove the earlier cut-of-scriptCode effect of CODESEPARATOR). > This gives a simple (but somewhat limited) way for scripts that need > to prevent certain kinds of cross-execution-trace rebinding. > > A few misc ideas: > * (Taken from > https://github.com/jl2012/bips/blob/sighash2/bip-sighash2.mediawiki) > For a default sign-everything sighash, the sighash byte can be > dropped. > * For the commitments to the scriptPubKey and scriptCode, an > intermediary hash should be used (so the data included in the sighash > includes a hash of those, rather than the script directly). This > prevents a blow up in hashing time for large scripts with many > different sighash types in its signatures. > * When masking the scriptCode, the push opcode immediately following > OP_MASKEDPUSH can be replaced by OP_VERIF (which will never collide > with any real script, as OP_VERIF makes a script invalid even when > occurring in an unexecuted branch). > * Sighashes (and really all new hashes that are introduced) should be > prefixed with a fixed 64-byte array as "tag", chosen to not collide > with any existing use of SHA256 in Bitcoin, to prevent signatures from > being re-interpretable as something else. Picking 64 bytes as tag size > means it can be efficiently implemented as just a modified SHA256 IV. > > So a combined proposal: > * All existing sighash flags, plus NOINPUT and MASK > (ANYONECANPAY/NOINPUT/MASK are encoded in 2 bits). > * A new opcode called OP_MASKEDPUSH, whose only runtime behaviour is > failing if not immediately followed by a push, or when appearing as > last opcode in the script. > * Signatures are 64 plus an optional sighash byte. A missing sighash > byte implies ALL, and ALL cannot be specified explicitly. > * The sighash is computed from the following: > * A 64-byte constant tag > * Data about the spending transaction: > * The transaction version number > * The hash of txins' prevouts+amounts+sequences (or nothing if > ANYONECANPAY) > * The hash of all txouts (or just the corresponding txout if > SINGLE; nothing if NONE) > * The transaction locktime > * Data about the output being spent: > * The prevout (or nothing if NOINPUT) > * The amount > * The sequence number > * The hash of the scriptPubKey (or nothing if MASK) > * Data about the script being executed: > * The hash of the scriptCode (after masking out, if MASK is set) > * The opcode number of the last executed OP_CODESEPARATOR (or > 0xFFFFFFFF if none) > * The sighash mode > > Cheers, > > -- > Pieter > _______________________________________________ > bitcoin-dev mailing list > bitcoin-dev@lists.linuxfoundation.org > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev > [-- Attachment #2: Type: text/html, Size: 9195 bytes --] ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-06 16:57 ` Russell O'Connor @ 2018-12-09 19:13 ` Johnson Lau 2018-12-11 22:50 ` Russell O'Connor 2018-12-09 22:41 ` David A. Harding 1 sibling, 1 reply; 55+ messages in thread From: Johnson Lau @ 2018-12-09 19:13 UTC (permalink / raw) To: Russell O'Connor, bitcoin-dev The current proposal is that a 64-byte signature will be used for the default “signing all” sighash, and 65-byte for other sighash types. The space saved will allow a few more txs in a block, so I think it worths doing. However, this also makes witness weight estimation more difficult in multisig cases. This idea of signing witness weight has been brought up before. I think the concern is the difficulty to estimate the witness weight for complex scripts, which need this feature most. So it will work when it is not needed, and will not work when it is needed. Is there any script example that witness size malleability is unavoidable? > On 7 Dec 2018, at 12:57 AM, Russell O'Connor via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> wrote: > > One more item to consider is "signature covers witness weight". > > While signing the witness weight doesn't completely eliminate witness malleability (of the kind that can cause grief for compact blocks), it does eliminate the worst kind of witness malleability from the user's perspective, the kind where malicious relay nodes increase the amount of witness data and therefore reduce the overall fee-rate of the transaction. Generally users should strive to construct their Bitcoin Scripts in such a way that witness malleability isn't possible, but as you are probably aware, this can be quite difficult to achieve as Scripts become more complex and maybe isn't even possible for some complex Scripts. > > Given the new fixed-sized signature of the Schnorr BIP, it becomes much easier to compute the final witness weight prior to signing. In complex multi-party signing protocol, the final witness weight might not be known at signing time for everyone involved, so the "signature covers witness weight" ought to be optional. > > ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-09 19:13 ` Johnson Lau @ 2018-12-11 22:50 ` Russell O'Connor 2018-12-12 19:53 ` Johnson Lau ` (2 more replies) 0 siblings, 3 replies; 55+ messages in thread From: Russell O'Connor @ 2018-12-11 22:50 UTC (permalink / raw) To: Johnson Lau; +Cc: Bitcoin Protocol Discussion [-- Attachment #1: Type: text/plain, Size: 3326 bytes --] On Sun, Dec 9, 2018 at 2:13 PM Johnson Lau <jl2012@xbt.hk> wrote: > The current proposal is that a 64-byte signature will be used for the > default “signing all” sighash, and 65-byte for other sighash types. The > space saved will allow a few more txs in a block, so I think it worths > doing. However, this also makes witness weight estimation more difficult in > multisig cases. > > This idea of signing witness weight has been brought up before. I think > the concern is the difficulty to estimate the witness weight for complex > scripts, which need this feature most. So it will work when it is not > needed, and will not work when it is needed. > > Is there any script example that witness size malleability is unavoidable? > I tend to think in opposite terms. Is there a proof that any script can be transformed into an equivalent one that avoids witness weight malleability? But I admit there is a trade off: If we don't allow for signature covers weight, and we do need it, it will be too late to add. On the other hand if we add signature covers weight, but it turns out that no Script ever needs to use it, then we've added that software complexity for no gain. However, I think the software complexity is relatively low, making it worthwhile. Moreover, even if witness weight malleability is entirely avoidable, it always seems to come at a cost. Taking as an example libwally's proposed " <https://github.com/ElementsProject/libwally-core/blob/c6db6ccdfa54571afeeb582919240263424736a2/src/script.c#L718-L735>csv_2of3_then_2" Script <https://github.com/ElementsProject/libwally-core/blob/c6db6ccdfa54571afeeb582919240263424736a2/src/script.c#L718-L735>, it begins with "OP_DEPTH OP_1SUB OP_1SUB" spending 3 vbytes to avoid any possible witness malleability versus just taking a witness stack item to determine the branch, costing 1 or 2 (unmalleated) vbytes. Now to be fair, under Taproot this particular script's witness malleability problem probably goes away. Nonetheless, I think it is fair to say that Bitcoin Script was designed without any regard given to scriptSig/witness malleability concerns and the result is that one is constantly fighting against malleability issues. Short of a wholesale replacement of Bitcoin Script, I do think that having an option for signature covers weight is one of the best ways to address the whole problem. Regarding your point about 64/65-byte signatures; I speculate that in most protocols, all parties that are able to consider signing the weight, know what sighash flags the other parties are expected to be using. However, your point is well-taken, and if we choose to adopt the option of signatures covering weight, we ought to make sure there exists a 65-byte signature that performs the equivalent of a sigHashAll (of course, still covering that particular sighash flag under the signature), to ensure that anti-weight-malleability can be use even when the sighash flags that other parties will use are unknown. Even with the extra vbytes in the signatures, there may be a net weight savings by avoiding the need for anti-malleability Script code. (It might also be reasonable to have participants create signatures for a small range of different weight values? (Sorry in advance to PSBT)). [-- Attachment #2: Type: text/html, Size: 3846 bytes --] ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-11 22:50 ` Russell O'Connor @ 2018-12-12 19:53 ` Johnson Lau 2018-12-13 16:50 ` Russell O'Connor 2018-12-13 0:05 ` Anthony Towns [not found] ` <CAAS2fgRma+Pw-rHJSOKRVBqoxqJ3AxHO9d696fWoa-sb17JEOQ@mail.gmail.com> 2 siblings, 1 reply; 55+ messages in thread From: Johnson Lau @ 2018-12-12 19:53 UTC (permalink / raw) To: Russell O'Connor; +Cc: bitcoin-dev [-- Attachment #1: Type: text/plain, Size: 4692 bytes --] > On 12 Dec 2018, at 6:50 AM, Russell O'Connor <roconnor@blockstream.io> wrote: > > On Sun, Dec 9, 2018 at 2:13 PM Johnson Lau <jl2012@xbt.hk <mailto:jl2012@xbt.hk>> wrote: > The current proposal is that a 64-byte signature will be used for the default “signing all” sighash, and 65-byte for other sighash types. The space saved will allow a few more txs in a block, so I think it worths doing. However, this also makes witness weight estimation more difficult in multisig cases. > > This idea of signing witness weight has been brought up before. I think the concern is the difficulty to estimate the witness weight for complex scripts, which need this feature most. So it will work when it is not needed, and will not work when it is needed. > > Is there any script example that witness size malleability is unavoidable? > > I tend to think in opposite terms. Is there a proof that any script can be transformed into an equivalent one that avoids witness weight malleability? But I admit there is a trade off: If we don't allow for signature covers weight, and we do need it, it will be too late to add. On the other hand if we add signature covers weight, but it turns out that no Script ever needs to use it, then we've added that software complexity for no gain. However, I think the software complexity is relatively low, making it worthwhile. > > Moreover, even if witness weight malleability is entirely avoidable, it always seems to come at a cost. Taking as an example libwally's proposed " <https://github.com/ElementsProject/libwally-core/blob/c6db6ccdfa54571afeeb582919240263424736a2/src/script.c#L718-L735>csv_2of3_then_2" Script <https://github.com/ElementsProject/libwally-core/blob/c6db6ccdfa54571afeeb582919240263424736a2/src/script.c#L718-L735>, it begins with "OP_DEPTH OP_1SUB OP_1SUB" spending 3 vbytes to avoid any possible witness malleability versus just taking a witness stack item to determine the branch, costing 1 or 2 (unmalleated) vbytes. Now to be fair, under Taproot this particular script's witness malleability problem probably goes away. Nonetheless, I think it is fair to say that Bitcoin Script was designed without any regard given to scriptSig/witness malleability concerns and the result is that one is constantly fighting against malleability issues. Short of a wholesale replacement of Bitcoin Script, I do think that having an option for signature covers weight is one of the best ways to address the whole problem. > > Regarding your point about 64/65-byte signatures; I speculate that in most protocols, all parties that are able to consider signing the weight, know what sighash flags the other parties are expected to be using. However, your point is well-taken, and if we choose to adopt the option of signatures covering weight, we ought to make sure there exists a 65-byte signature that performs the equivalent of a sigHashAll (of course, still covering that particular sighash flag under the signature), to ensure that anti-weight-malleability can be use even when the sighash flags that other parties will use are unknown. Even with the extra vbytes in the signatures, there may be a net weight savings by avoiding the need for anti-malleability Script code. (It might also be reasonable to have participants create signatures for a small range of different weight values? (Sorry in advance to PSBT)). I think the root cause of witness weight malleability is some opcodes accept variable size input (without affecting the output), and that input is provided by the puzzle solver. Going through the opcode list, I think such opcodes include IF, NOTIF, VERIFY, DROP, 2DROP, NIP, DEPTH, and all arithmetic opcode that accepts CScriptNum (including CHECKMULTISIG) VERIFY, DROP, 2DROP, NIP are not real problem, since they should not be the first opcode to interact with data directly provided by the puzzle solver. CHECKMULTISIG is fixed by BIP147. For the key number and sig number, they should be part of the script, so not malleable. DEPTH is a problem only if its inputs are not later examined by other opcodes. Again, this is pointless. The liberally example should be protected by the MINIMAL_IF policy, which requires the input of OP_IF be minimal. As you note, OP_IF could be replaced by taproot in many cases Non-minimal CScriptNum is also banned as BIP62 policy. For the purpose of preventing malicious third party witness bloating, all we need is the miners to enforce the policy. There is no reason for miners to accept size malleated txs, as that will reduce the usable block space. If they hate a tx, they would simply drop it, instead of wasting the block space. [-- Attachment #2: Type: text/html, Size: 6226 bytes --] ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-12 19:53 ` Johnson Lau @ 2018-12-13 16:50 ` Russell O'Connor 0 siblings, 0 replies; 55+ messages in thread From: Russell O'Connor @ 2018-12-13 16:50 UTC (permalink / raw) To: Johnson Lau; +Cc: Bitcoin Protocol Discussion [-- Attachment #1: Type: text/plain, Size: 2693 bytes --] On Wed, Dec 12, 2018 at 2:53 PM Johnson Lau <jl2012@xbt.hk> wrote: > > I think the root cause of witness weight malleability is some opcodes > accept variable size input (without affecting the output), and that input > is provided by the puzzle solver. Going through the opcode list, I think > such opcodes include IF, NOTIF, VERIFY, DROP, 2DROP, NIP, DEPTH, and all > arithmetic opcode that accepts CScriptNum (including CHECKMULTISIG) > > VERIFY, DROP, 2DROP, NIP are not real problem, since they should not be > the first opcode to interact with data directly provided by the puzzle > solver. > > CHECKMULTISIG is fixed by BIP147. For the key number and sig number, they > should be part of the script, so not malleable. > > DEPTH is a problem only if its inputs are not later examined by other > opcodes. Again, this is pointless. > > The liberally example should be protected by the MINIMAL_IF policy, which > requires the input of OP_IF be minimal. As you note, OP_IF could be > replaced by taproot in many cases > > Non-minimal CScriptNum is also banned as BIP62 policy. > > For the purpose of preventing malicious third party witness bloating, all > we need is the miners to enforce the policy. There is no reason for miners > to accept size malleated txs, as that will reduce the usable block space. > If they hate a tx, they would simply drop it, instead of wasting the block > space. > I don't know if it such a clear cut case for miner's policy. A miner is passed a malleated tx. They know that there is probably a non-malleated variant floating around out there somewhere, and they would rather have it. But right now they don't, and they probably not going to try to unmalleate it themselves. So, why not stick it into their mempool? If it eventually makes it into one of their blocks, then it will because it has the best fee rate available, and to reject it outright is harmful to their bottom line. If they find the non-malleated variant later, great, they can replace it and gain a higher-fee rate tx. Of course, such a policy opens them up to a Denial of Service attack. So what do they do? Do they accept malleated tx's and implement an RBF policy that requires sufficient fee rate increases? Do they reject malleated txs outright to avoid falling in this trap in the first place as you suggest? I don't know, but I don't think things are as clear cut as you present. That aside, your list of weight malleable opcodes is shorter than I imagined and I'm grateful you've compiled it. Perhaps the best solution is to make MINIMAL_IF and minimal CScriptNum consensus enforced in the next version of Script and all but eliminate weight malleability in practice? [-- Attachment #2: Type: text/html, Size: 3242 bytes --] ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-11 22:50 ` Russell O'Connor 2018-12-12 19:53 ` Johnson Lau @ 2018-12-13 0:05 ` Anthony Towns 2018-12-13 16:21 ` Russell O'Connor [not found] ` <CAAS2fgRma+Pw-rHJSOKRVBqoxqJ3AxHO9d696fWoa-sb17JEOQ@mail.gmail.com> 2 siblings, 1 reply; 55+ messages in thread From: Anthony Towns @ 2018-12-13 0:05 UTC (permalink / raw) To: Russell O'Connor, Bitcoin Protocol Discussion On Tue, Dec 11, 2018 at 05:50:24PM -0500, Russell O'Connor via bitcoin-dev wrote: > On Sun, Dec 9, 2018 at 2:13 PM Johnson Lau <jl2012@xbt.hk> wrote: > The current proposal is that a 64-byte signature will be used for the > default “signing all” sighash, and 65-byte for other sighash types. The > space saved will allow a few more txs in a block, so I think it worths > doing. However, this also makes witness weight estimation more difficult in > multisig cases. This seems strange to me -- why wouldn't you just assume every signature is 65 witness bytes, and just be grateful for the prioritisation benefit if someone chooses a shorter signature? Your error margin is just 0.25 vbytes per signature. > I tend to think in opposite terms. Is there a proof that any script can be > transformed into an equivalent one that avoids witness weight malleability? An alternative generalisation: is there a proof that all valid witnesses will have a weight within some small range? > Moreover, even if witness weight malleability is entirely avoidable, it always > seems to come at a cost. Taking as an example libwally's proposed " > csv_2of3_then_2" Script, it begins with "OP_DEPTH OP_1SUB OP_1SUB" (DEPTH 2 NUMNOTEQUAL seems like it would have been more obvious...) Cheers, aj ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-13 0:05 ` Anthony Towns @ 2018-12-13 16:21 ` Russell O'Connor 2018-12-14 0:47 ` Anthony Towns 0 siblings, 1 reply; 55+ messages in thread From: Russell O'Connor @ 2018-12-13 16:21 UTC (permalink / raw) To: Anthony Towns; +Cc: Bitcoin Protocol Discussion [-- Attachment #1: Type: text/plain, Size: 2031 bytes --] On Wed, Dec 12, 2018 at 7:06 PM Anthony Towns <aj@erisian.com.au> wrote: > On Tue, Dec 11, 2018 at 05:50:24PM -0500, Russell O'Connor via bitcoin-dev > wrote: > > On Sun, Dec 9, 2018 at 2:13 PM Johnson Lau <jl2012@xbt.hk> wrote: > > The current proposal is that a 64-byte signature will be used for the > > default “signing all” sighash, and 65-byte for other sighash types. > The > > space saved will allow a few more txs in a block, so I think it > worths > > doing. However, this also makes witness weight estimation more > difficult in > > multisig cases. > > This seems strange to me -- why wouldn't you just assume every signature > is 65 witness bytes, and just be grateful for the prioritisation benefit > if someone chooses a shorter signature? Your error margin is just 0.25 > vbytes per signature. > The issue is that the proposal is to sign the actual weight, rather than sign an upper bound on the weight. The problem with signing an upper bound, is that you need to specify that upper bound someplace in the transaction, and we are out of sneaky places to stash that data. Signing the actual weight is easy because the total weight is implicit, but now you need to know the total weight before signing. > > I tend to think in opposite terms. Is there a proof that any script can > be > > transformed into an equivalent one that avoids witness weight > malleability? > > An alternative generalisation: is there a proof that all valid witnesses > will have a weight within some small range? > > > Moreover, even if witness weight malleability is entirely avoidable, it > always > > seems to come at a cost. Taking as an example libwally's proposed " > > csv_2of3_then_2" Script, it begins with "OP_DEPTH OP_1SUB OP_1SUB" > > (DEPTH 2 NUMNOTEQUAL seems like it would have been more obvious...) > > I think the 1SUB idea was derived from the csv_2of2_then_1 Script where DEPTH 1SUB is shorter than DEPTH 1 NUMNOTEQUAL. > Cheers, > aj > > [-- Attachment #2: Type: text/html, Size: 2768 bytes --] ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-13 16:21 ` Russell O'Connor @ 2018-12-14 0:47 ` Anthony Towns 0 siblings, 0 replies; 55+ messages in thread From: Anthony Towns @ 2018-12-14 0:47 UTC (permalink / raw) To: Russell O'Connor; +Cc: Bitcoin Protocol Discussion On Thu, Dec 13, 2018 at 11:21:10AM -0500, Russell O'Connor wrote: > On Wed, Dec 12, 2018 at 7:06 PM Anthony Towns <aj@erisian.com.au> wrote: > On Tue, Dec 11, 2018 at 05:50:24PM -0500, Russell O'Connor via bitcoin-dev > wrote: > > On Sun, Dec 9, 2018 at 2:13 PM Johnson Lau <jl2012@xbt.hk> wrote: > > The current proposal is that a 64-byte signature will be used for the > > default “signing all” sighash, and 65-byte for other sighash types. > The > > space saved will allow a few more txs in a block, so I think it > worths > > doing. However, this also makes witness weight estimation more > difficult in > > multisig cases. > This seems strange to me -- why wouldn't you just assume every signature > is 65 witness bytes, and just be grateful for the prioritisation benefit > if someone chooses a shorter signature? Your error margin is just 0.25 > vbytes per signature. > The issue is that the proposal is to sign the actual weight, rather than sign > an upper bound on the weight. Sorry, I elided some of my reasoning. Suppose witness data wasn't malleable; in that case any valid witness for a particular script would have the exact same weight, and it would be good enough to just sign the script, because that also commits to the witness weight. (And if you're doing SIGHASH_ALL, you're committing to the exact transaction weight too) I think the benefit of signing the weight is mostly that it also commits to the feerate and hence transaction priority: you know how much you're paying in fees when you sign, but the reason you're paying any fees is to get a particular priority for your transaction, so if that can change from under you because the tx weight changes, you're being ripped off (either because you get less priority than you were paying for, or because you get more than you wanted and would have paid less if you'd known). But if, just from looking at the script, you can be sure the witness weight will be between "w" and "w + 0.8%" and your fee is "f", you know your feerate (and hence priority) is between "f/w - 0.8%" and "f/w". If the "0.8%" is small enough, that's just a rounding error and you probably have more uncertainty in your feerate estimations anyway. So I think at that point it's reasonable to target the lower bound feerate ("f/w - 0.8%"), because your only potential loss is that you get a higher feerate and would have saved "0.8%" on f if you'd been able to be 100% sure of that. > The problem with signing an upper bound, is that you need to specify that upper > bound someplace in the transaction, and we are out of sneaky places to stash > that data. > Signing the actual weight is easy because the total weight is implicit, but now > you need to know the total weight before signing. The cases where the tx is malleable by someone else, and you know what the weight should be in advance, and you can't take the final tx once it hits your mempool and fix the weight to what it should be and rebroadcast, seem limited to me? Being able to commit to a minimum feerate seems like it would be more generally useful: it would apply for ANYONECANPAY crowd-funding type txes as well; "here's my input, and I'm paying 3 sat/vb feerate, but only if everyone else does too!". You could do that, I think, with a rule along the lines of: (a) take the actual tx feerate, f*4000/w (b) round it down to the nearest exponent of 1.05 sat/kvbyte, so 1.3 sat/vbyte becomes 1240.62 (1.05**146 < 1.05**147=1302) (c) if the signature doesn't have an extra byte, then it should commit to that exponent (146) (d) if the signature does have an extra byte, b, then b<=146 and the signature should commit to 146-(1+b) That way if you sign something that says "minimum fee rate of 0.001 sat per vbyte", you commit to an exponent of 0, and someone else can raise the feerate anywhere up to 265.7 sat/vb just by tweaking your signature to indicate how much they've raised the feerate. Likewise you could commit to some other exponent, and anyone else could adjust your signature to remain valid for a tx with a feerate of up to 265,742 times greater than what you expected, but never more than 5% less than what you expected. This seems too complicated to do any time soon; and maybe more complicated than will ever be worthwhile, though. Cheers, aj ^ permalink raw reply [flat|nested] 55+ messages in thread
[parent not found: <CAAS2fgRma+Pw-rHJSOKRVBqoxqJ3AxHO9d696fWoa-sb17JEOQ@mail.gmail.com>]
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT [not found] ` <CAAS2fgRma+Pw-rHJSOKRVBqoxqJ3AxHO9d696fWoa-sb17JEOQ@mail.gmail.com> @ 2018-12-13 16:34 ` Russell O'Connor 0 siblings, 0 replies; 55+ messages in thread From: Russell O'Connor @ 2018-12-13 16:34 UTC (permalink / raw) To: Gregory Maxwell; +Cc: Bitcoin Protocol Discussion [-- Attachment #1: Type: text/plain, Size: 2245 bytes --] On Wed, Dec 12, 2018 at 12:26 PM Gregory Maxwell <gmaxwell@gmail.com> wrote: > On Wed, Dec 12, 2018 at 5:15 PM Russell O'Connor via bitcoin-dev > <bitcoin-dev@lists.linuxfoundation.org> wrote: > > I tend to think in opposite terms. Is there a proof that any script can > be transformed into an equivalent one that avoids witness weight > malleability? But I admit there is a trade off: If we don't allow for > signature covers weight, and we do need it, it will be too late to add. On > the other hand if we add signature covers weight, but it turns out that no > Script ever needs to use it, then we've added that software complexity for > no gain. However, I think the software complexity is relatively low, > making it worthwhile. > > > > Moreover, even if witness weight malleability is entirely avoidable, it > always seems to come at a cost. Taking as an example libwally's proposed > "csv_2of3_then_2" > > I'm largely in agreement with you-- but my difficulty in arguing for > signing the weight is that it seemed to me that it was only easy to > sign an upper bound because some witnesses are variable size... and > signing an upper bound means more signalling overhead... offsetting > the space gains for demalleating. > In multi-party protocols, the last person to sign knows what the total weight is going to be (now that we have fixed sized signatures) and at least they have the ability to sign it. They are probably motivated to sign the weight as long as they are interested in the success of the transaction. I suppose there could be asynchronous protocols where there isn't a last person to sign, but that seems a bit weird. Greg, you are probably more familiar with examples of multi-party protocols than I am. OTOH maybe the last person to sign isn't interested in the success of the transaction and wants to cause grief by bloating the transaction and signing the bloated weight. I guess in such protocols, you'll have to keep the anti-malleablity Script Code. I totally get the idea that signing weight has a lot of issues in many scenarios. But I still feel than on the whole it is better to make the option available than to be forced to rely on anti-malleability Script Code or non-consensus relay policy. [-- Attachment #2: Type: text/html, Size: 2726 bytes --] ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-06 16:57 ` Russell O'Connor 2018-12-09 19:13 ` Johnson Lau @ 2018-12-09 22:41 ` David A. Harding 2018-12-11 15:36 ` Russell O'Connor 1 sibling, 1 reply; 55+ messages in thread From: David A. Harding @ 2018-12-09 22:41 UTC (permalink / raw) To: Russell O'Connor, Bitcoin Protocol Discussion [-- Attachment #1: Type: text/plain, Size: 1158 bytes --] On Thu, Dec 06, 2018 at 11:57:09AM -0500, Russell O'Connor via bitcoin-dev wrote: > One more item to consider is "signature covers witness weight". > > While signing the witness weight doesn't completely eliminate witness > malleability (of the kind that can cause grief for compact blocks), it does > eliminate the worst kind of witness malleability from the user's > perspective, the kind where malicious relay nodes increase the amount of > witness data and therefore reduce the overall fee-rate of the transaction. To what degree is this an actual problem? If the mutated transaction pays a feerate at least incremental-relay-fee[1] below the original transaction, then the original transaction can be rebroadcast as an RBF replacement of the mutated transaction (unless the mutated version has been pinned[2]). -Dave [1] $ bitcoind -help-debug | grep -A2 incremental -incrementalrelayfee=<amt> Fee rate (in BTC/kB) used to define cost of relay, used for mempool limiting and BIP 125 replacement. (default: 0.00001) [2] https://bitcoin.stackexchange.com/questions/80803/what-is-meant-by-transaction-pinning [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-09 22:41 ` David A. Harding @ 2018-12-11 15:36 ` Russell O'Connor 2018-12-11 17:47 ` David A. Harding 0 siblings, 1 reply; 55+ messages in thread From: Russell O'Connor @ 2018-12-11 15:36 UTC (permalink / raw) To: dave; +Cc: Bitcoin Protocol Discussion [-- Attachment #1: Type: text/plain, Size: 1830 bytes --] I don't believe that the default RBF policy works that way. My understanding is that current policy requires an absolute fee increase (by an amount related to incrementalrelayfee). There have been proposals to change default RBF policy, however even my proposal < https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-February/015717.html> still requires a minimal amount of absolute fee increase as a DoS defense. (I'm reading your comment as attempting to rebroadcast the original transaction with the same fee amount, with its relatively higher fee-rate). On Mon, Dec 10, 2018 at 10:00 AM David A. Harding <dave@dtrt.org> wrote: > On Thu, Dec 06, 2018 at 11:57:09AM -0500, Russell O'Connor via bitcoin-dev > wrote: > > One more item to consider is "signature covers witness weight". > > > > While signing the witness weight doesn't completely eliminate witness > > malleability (of the kind that can cause grief for compact blocks), it > does > > eliminate the worst kind of witness malleability from the user's > > perspective, the kind where malicious relay nodes increase the amount of > > witness data and therefore reduce the overall fee-rate of the > transaction. > > To what degree is this an actual problem? If the mutated transaction > pays a feerate at least incremental-relay-fee[1] below the original > transaction, then the original transaction can be rebroadcast as an RBF > replacement of the mutated transaction (unless the mutated version has > been pinned[2]). > > -Dave > > [1] $ bitcoind -help-debug | grep -A2 incremental > -incrementalrelayfee=<amt> > Fee rate (in BTC/kB) used to define cost of relay, used for mempool > limiting and BIP 125 replacement. (default: 0.00001) > > [2] > https://bitcoin.stackexchange.com/questions/80803/what-is-meant-by-transaction-pinning > > [-- Attachment #2: Type: text/html, Size: 2547 bytes --] ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-11 15:36 ` Russell O'Connor @ 2018-12-11 17:47 ` David A. Harding 0 siblings, 0 replies; 55+ messages in thread From: David A. Harding @ 2018-12-11 17:47 UTC (permalink / raw) To: Russell O'Connor; +Cc: Bitcoin Protocol Discussion [-- Attachment #1: Type: text/plain, Size: 1048 bytes --] On Tue, Dec 11, 2018 at 10:36:59AM -0500, Russell O'Connor wrote: > I don't believe that the default RBF policy works that way. My > understanding is that current policy requires an absolute fee increase (by > an amount related to incrementalrelayfee). Indeed, you are correct (BIP125 rule 4[1]). Thanks for the correction, -Dave [1] For the curious, the relevant code from master's validation.cpp: // Finally in addition to paying more fees than the conflicts the // new transaction must pay for its own bandwidth. CAmount nDeltaFees = nModifiedFees - nConflictingFees; if (nDeltaFees < ::incrementalRelayFee.GetFee(nSize)) { return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient fee", false, strprintf("rejecting replacement %s, not enough additional fees to relay; %s < %s", hash.ToString(), FormatMoney(nDeltaFees), FormatMoney(::incrementalRelayFee.GetFee(nSize)))); } [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-19 22:37 [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT Pieter Wuille ` (3 preceding siblings ...) 2018-11-28 3:41 ` Pieter Wuille @ 2018-12-12 9:42 ` Rusty Russell 2018-12-12 20:00 ` Johnson Lau 2018-12-13 0:24 ` Anthony Towns 4 siblings, 2 replies; 55+ messages in thread From: Rusty Russell @ 2018-12-12 9:42 UTC (permalink / raw) To: Pieter Wuille, Bitcoin Protocol Discussion, Bitcoin Dev Pieter Wuille via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> writes: > Here is a combined proposal: > * Three new sighash flags are added: SIGHASH_NOINPUT, SIGHASH_NOFEE, > and SIGHASH_SCRIPTMASK. > * A new opcode OP_MASK is added, which acts as a NOP during execution. > * The sighash is computed like in BIP143, but: > * If SIGHASH_SCRIPTMASK is present, for every OP_MASK in scriptCode > the subsequent opcode/push is removed. I'm asking on-list because I'm sure I'm not the only confused one. Having the SIGHASH_SCRIPTMASK flag is redundant AFAICT: why not always perform mask-removal for signing? If you're signing arbitrary scripts, you're surely in trouble already? And I am struggling to understand the role of scriptmask in a taproot world, where the alternate script is both hidden and general? I look forward to learning what I missed! Rusty. ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-12 9:42 ` Rusty Russell @ 2018-12-12 20:00 ` Johnson Lau 2018-12-12 23:49 ` Rusty Russell 2018-12-13 0:24 ` Anthony Towns 1 sibling, 1 reply; 55+ messages in thread From: Johnson Lau @ 2018-12-12 20:00 UTC (permalink / raw) To: Rusty Russell, bitcoin-dev > On 12 Dec 2018, at 5:42 PM, Rusty Russell via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> wrote: > > Pieter Wuille via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> writes: >> Here is a combined proposal: >> * Three new sighash flags are added: SIGHASH_NOINPUT, SIGHASH_NOFEE, >> and SIGHASH_SCRIPTMASK. >> * A new opcode OP_MASK is added, which acts as a NOP during execution. >> * The sighash is computed like in BIP143, but: >> * If SIGHASH_SCRIPTMASK is present, for every OP_MASK in scriptCode >> the subsequent opcode/push is removed. > > I'm asking on-list because I'm sure I'm not the only confused one. > > Having the SIGHASH_SCRIPTMASK flag is redundant AFAICT: why not always > perform mask-removal for signing? Because a hardware wallet may want to know what exact script it is signing? Masked script has reduced security, but this is a tradeoff with functionality (e.g. eltoo can’t work without masking part of the script). So when you don’t need that extra functionality, you go back to better security However, I’m not sure if there is any useful NOINPUT case with unmasked script. > > If you're signing arbitrary scripts, you're surely in trouble already? > > And I am struggling to understand the role of scriptmask in a taproot > world, where the alternate script is both hidden and general? It makes sure that your signature is applicable to a specific script branch, not others (assuming you use the same pubkey in many branches, which is avoidable) > > I look forward to learning what I missed! > Rusty. > _______________________________________________ > bitcoin-dev mailing list > bitcoin-dev@lists.linuxfoundation.org > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-12 20:00 ` Johnson Lau @ 2018-12-12 23:49 ` Rusty Russell 2018-12-13 0:37 ` Rusty Russell 0 siblings, 1 reply; 55+ messages in thread From: Rusty Russell @ 2018-12-12 23:49 UTC (permalink / raw) To: Johnson Lau, bitcoin-dev Johnson Lau <jl2012@xbt.hk> writes: >> On 12 Dec 2018, at 5:42 PM, Rusty Russell via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> wrote: >> >> Pieter Wuille via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> writes: >>> Here is a combined proposal: >>> * Three new sighash flags are added: SIGHASH_NOINPUT, SIGHASH_NOFEE, >>> and SIGHASH_SCRIPTMASK. >>> * A new opcode OP_MASK is added, which acts as a NOP during execution. >>> * The sighash is computed like in BIP143, but: >>> * If SIGHASH_SCRIPTMASK is present, for every OP_MASK in scriptCode >>> the subsequent opcode/push is removed. >> >> Having the SIGHASH_SCRIPTMASK flag is redundant AFAICT: why not always >> perform mask-removal for signing? > > Because a hardware wallet may want to know what exact script it is signing? OK, removing OP_MASKs unconditionally would introduce a hole without some explicit flag to say they've been removed (the "real script" could be something different with OP_MASKs). We could have the signature commit to the outputscript, but that's a bit meh. > Masked script has reduced security, but this is a tradeoff with > functionality (e.g. eltoo can’t work without masking part of the > script). So when you don’t need that extra functionality, you go back > to better security > > However, I’m not sure if there is any useful NOINPUT case with unmasked script. This is *not* true of Eltoo; the script itself need not change for the rebinding (Christian, did something change?). So, can we find an example where OP_MASK is useful? >> If you're signing arbitrary scripts, you're surely in trouble already? >> >> And I am struggling to understand the role of scriptmask in a taproot >> world, where the alternate script is both hidden and general? > > It makes sure that your signature is applicable to a specific script branch, not others (assuming you use the same pubkey in many branches, which is avoidable) If I'm using SIGHASH_NOINPUT, I'm already required to take care with key reuse. Without a concrete taproot proposal it's hard to make assertions, but if the signature flags that it's using the taproot script, it's no less safe, and more general AFAICT. Thanks! Rusty. ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-12 23:49 ` Rusty Russell @ 2018-12-13 0:37 ` Rusty Russell 2018-12-14 9:30 ` Anthony Towns 0 siblings, 1 reply; 55+ messages in thread From: Rusty Russell @ 2018-12-13 0:37 UTC (permalink / raw) To: Johnson Lau, bitcoin-dev Rusty Russell <rusty@rustcorp.com.au> writes: >> However, I’m not sure if there is any useful NOINPUT case with unmasked script. > > This is *not* true of Eltoo; the script itself need not change for the > rebinding (Christian, did something change?). This is wrong, sorry. I re-checked the paper, and the constant for the timelock comparison changes on each new update. (The alternative was a new opcode like OP_TIMELOCKGREATERVERIFY which required remembering the nLocktime for the UTXO). So now my opinion is closer to yours: what's the use for NOINPUT && !NOMASK? And is it worthwhile doing the mask complexity, rather than just removing the commitment to script with NOINPUT? It *feels* safer to restrict what scripts we can sign, but is it? Note that NOINPUT is only useful when you can't just re-sign the tx, and you need to be able to create a new tx even if this input is spent once (an attacker can do this with SIGHASH_MASK or not!). ie. any other inputs need to be signed NOINPUT or this one SIGHASH_SINGLE|ANYONECANPAY. You already need both key-reuse and amount-reuse to be exploited. SIGHASH_MASK only prevents you from reusing this input for a "normal" output; if you used this key for multiple scripts of the same form, you're vulnerable[1]. Which, given the lightning software will be using the One True Script, is more likely that your normal wallet using the same keys. So I don't think it's worth it. SIGHASH_NOINPUT is simply dangerous with key-reuse, and Don't Do That. Cheers, Rusty. [1] Attacker can basically clone channel state to another channel. ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-13 0:37 ` Rusty Russell @ 2018-12-14 9:30 ` Anthony Towns 2018-12-14 13:55 ` Johnson Lau 2018-12-16 6:55 ` Rusty Russell 0 siblings, 2 replies; 55+ messages in thread From: Anthony Towns @ 2018-12-14 9:30 UTC (permalink / raw) To: bitcoin-dev On Thu, Dec 13, 2018 at 11:07:28AM +1030, Rusty Russell via bitcoin-dev wrote: > And is it worthwhile doing the mask complexity, rather than just > removing the commitment to script with NOINPUT? It *feels* safer to > restrict what scripts we can sign, but is it? If it's not safer in practice, we've spent a little extra complexity committing to a subset of the script in each signature to no gain. If it is safer in practice, we've prevented people from losing funds. I'm all for less complexity, but not for that tradeoff. Also, saying "I can't see how to break this, so it's probably good enough, even if other people have a bad feeling about it" is a crypto anti-pattern, isn't it? I don't see how you could feasibly commit to more information than script masking does for use cases where you want to be able to spend different scripts with the same signature [0]. If that's possible, I'd probably be for it. At the same time, script masking does seem feasible, both for lightning/eltoo, and even for possibly complex variations of scripts. So committing to less doesn't seem wise. > You already need both key-reuse and amount-reuse to be exploited. > SIGHASH_MASK only prevents you from reusing this input for a "normal" > output; if you used this key for multiple scripts of the same form, > you're vulnerable[1]. For example, script masking seems general enough to prevent footguns even if (for some reason) key and value reuse across eltoo channels were a requirement, rather than prohibited: you'd make the script be "<eltoo-channel-id> MASK <statenum> CLTV 2DROP <a+b> CHECKSIG", and your signature will only apply to that channel, even if another channel has the same capacity and uses the same keys, a and b. > So I don't think it's worth it. SIGHASH_NOINPUT is simply dangerous > with key-reuse, and Don't Do That. For my money, "NOINPUT" commits to dangerously little context, and doesn't really feel safe to include as a primitive -- as evidenced by the suggestion to add "_UNSAFE" or similar to its name. Personally, I'm willing to accept a bit of risk, so that feeling doesn't make me strongly against the idea; but it also makes it hard for me to want to support adding it. To me, committing to a masked script is a huge improvement. Heck, if it also makes it easier to do something safer, that's also probably a win... Cheers, aj [0] You could, perhaps, commit to knowing the private keys for all the *outputs* you're spending to, as well as the inputs, which comes close to saying "I know this is a scary NOINPUT transaction, but we're paying to ourselves, so it will all be okay". ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-14 9:30 ` Anthony Towns @ 2018-12-14 13:55 ` Johnson Lau 2018-12-17 3:10 ` Rusty Russell 2018-12-16 6:55 ` Rusty Russell 1 sibling, 1 reply; 55+ messages in thread From: Johnson Lau @ 2018-12-14 13:55 UTC (permalink / raw) To: Anthony Towns, bitcoin-dev I don’t think this has been mentioned: without signing the script or masked script, OP_CODESEPARATOR becomes unusable or insecure with NOINPUT. In the new sighash proposal, we will sign the hash of the full script (or masked script), without any truncation. To make OP_CODESEPARATOR works like before, we will commit to the position of the last executed OP_CODESEPARATOR. If NOINPUT doesn’t commit to the masked script, it will just blindly committing to a random OP_CODESEPARATOR position, which a wallet couldn’t know what codes are actually being executed. > On 14 Dec 2018, at 5:30 PM, Anthony Towns via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> wrote: > > On Thu, Dec 13, 2018 at 11:07:28AM +1030, Rusty Russell via bitcoin-dev wrote: >> And is it worthwhile doing the mask complexity, rather than just >> removing the commitment to script with NOINPUT? It *feels* safer to >> restrict what scripts we can sign, but is it? > > If it's not safer in practice, we've spent a little extra complexity > committing to a subset of the script in each signature to no gain. If > it is safer in practice, we've prevented people from losing funds. I'm > all for less complexity, but not for that tradeoff. > > Also, saying "I can't see how to break this, so it's probably good > enough, even if other people have a bad feeling about it" is a crypto > anti-pattern, isn't it? > > I don't see how you could feasibly commit to more information than script > masking does for use cases where you want to be able to spend different > scripts with the same signature [0]. If that's possible, I'd probably > be for it. > > At the same time, script masking does seem feasible, both for > lightning/eltoo, and even for possibly complex variations of scripts. So > committing to less doesn't seem wise. > >> You already need both key-reuse and amount-reuse to be exploited. >> SIGHASH_MASK only prevents you from reusing this input for a "normal" >> output; if you used this key for multiple scripts of the same form, >> you're vulnerable[1]. > > For example, script masking seems general enough to prevent footguns > even if (for some reason) key and value reuse across eltoo channels > were a requirement, rather than prohibited: you'd make the script be > "<eltoo-channel-id> MASK <statenum> CLTV 2DROP <a+b> CHECKSIG", and your > signature will only apply to that channel, even if another channel has > the same capacity and uses the same keys, a and b. > >> So I don't think it's worth it. SIGHASH_NOINPUT is simply dangerous >> with key-reuse, and Don't Do That. > > For my money, "NOINPUT" commits to dangerously little context, and > doesn't really feel safe to include as a primitive -- as evidenced by > the suggestion to add "_UNSAFE" or similar to its name. Personally, I'm > willing to accept a bit of risk, so that feeling doesn't make me strongly > against the idea; but it also makes it hard for me to want to support > adding it. To me, committing to a masked script is a huge improvement. > > Heck, if it also makes it easier to do something safer, that's also > probably a win... > > Cheers, > aj > > [0] You could, perhaps, commit to knowing the private keys for all the > *outputs* you're spending to, as well as the inputs, which comes > close to saying "I know this is a scary NOINPUT transaction, but > we're paying to ourselves, so it will all be okay". > _______________________________________________ > bitcoin-dev mailing list > bitcoin-dev@lists.linuxfoundation.org > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-14 13:55 ` Johnson Lau @ 2018-12-17 3:10 ` Rusty Russell 2018-12-20 19:34 ` Johnson Lau 0 siblings, 1 reply; 55+ messages in thread From: Rusty Russell @ 2018-12-17 3:10 UTC (permalink / raw) To: Johnson Lau, Anthony Towns, bitcoin-dev Johnson Lau <jl2012@xbt.hk> writes: > I don’t think this has been mentioned: without signing the script or masked script, OP_CODESEPARATOR becomes unusable or insecure with NOINPUT. > > In the new sighash proposal, we will sign the hash of the full script (or masked script), without any truncation. To make OP_CODESEPARATOR works like before, we will commit to the position of the last executed OP_CODESEPARATOR. If NOINPUT doesn’t commit to the masked script, it will just blindly committing to a random OP_CODESEPARATOR position, which a wallet couldn’t know what codes are actually being executed. My anti-complexity argument leads me to ask why we'd support OP_CODESEPARATOR at all? Though my argument is weaker here: no wallet need support it. But I don't see how OP_CODESEPARATOR changes anything here, wrt NOINPUT? Remember, anyone can create an output which can be spent by any NOINPUT, whether we go for OP_MASK or simply not commiting to the input script. Confused, Rusty. ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-17 3:10 ` Rusty Russell @ 2018-12-20 19:34 ` Johnson Lau 2018-12-20 23:17 ` Rusty Russell 0 siblings, 1 reply; 55+ messages in thread From: Johnson Lau @ 2018-12-20 19:34 UTC (permalink / raw) To: Rusty Russell; +Cc: bitcoin-dev [-- Attachment #1: Type: text/plain, Size: 2791 bytes --] > On 17 Dec 2018, at 11:10 AM, Rusty Russell <rusty@rustcorp.com.au> wrote: > > Johnson Lau <jl2012@xbt.hk> writes: >> I don’t think this has been mentioned: without signing the script or masked script, OP_CODESEPARATOR becomes unusable or insecure with NOINPUT. >> >> In the new sighash proposal, we will sign the hash of the full script (or masked script), without any truncation. To make OP_CODESEPARATOR works like before, we will commit to the position of the last executed OP_CODESEPARATOR. If NOINPUT doesn’t commit to the masked script, it will just blindly committing to a random OP_CODESEPARATOR position, which a wallet couldn’t know what codes are actually being executed. > > My anti-complexity argument leads me to ask why we'd support > OP_CODESEPARATOR at all? Though my argument is weaker here: no wallet > need support it. Because it could make scripts more compact in some cases? This is an example: https://github.com/bitcoin/bitcoin/pull/11423#issuecomment-333441321 <https://github.com/bitcoin/bitcoin/pull/11423#issuecomment-333441321> But this is probably not a good example for taproot, as it could be more efficient by making the 2 branches as different script merkle leaves. > > But I don't see how OP_CODESEPARATOR changes anything here, wrt NOINPUT? > Remember, anyone can create an output which can be spent by any NOINPUT, > whether we go for OP_MASK or simply not commiting to the input script. > Let me elaborate more. Currently, scriptCode is truncated at the last executed CODESEPARATOR. If we have a very big script with many CODESEPARATORs and CHECKSIGs, there will be a lot of hashing to do. To fix this problem, it is proposed that the new sighash will always commit to the same H(script), instead of the truncated scriptCode. So we only need to do the H(script) once, even if the script is very big In the case of NOINPUT with MASKEDSCRIPT, it will commit to the H(masked_script) instead of H(script). To make CODESEPARATOR works as before, the sighash will also commit to the position of the last executed CODESEPARATOR. So the semantics doesn’t change. For scripts without CODESEPARATOR, the committed value is a constant. IF NOINPUT does not commit to H(masked_script), technically it could still commit to the position of the last executed CODESEPARATOR. But since the wallet is not aware of the actual content of the script, it has to guess the meaning of such committed positions, like “with the HD key path m/x/y/z, I assume the script template is blah blah blah because I never use this path for another script template, and the meaning of signing the 3rd CODESEPARATOR is blah blah blah”. It still works if the assumptions hold, but sounds quite unreliable to me. Johnson [-- Attachment #2: Type: text/html, Size: 3871 bytes --] ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-20 19:34 ` Johnson Lau @ 2018-12-20 23:17 ` Rusty Russell 2018-12-21 18:54 ` Johnson Lau 0 siblings, 1 reply; 55+ messages in thread From: Rusty Russell @ 2018-12-20 23:17 UTC (permalink / raw) To: Johnson Lau; +Cc: bitcoin-dev Johnson Lau <jl2012@xbt.hk> writes: >> On 17 Dec 2018, at 11:10 AM, Rusty Russell <rusty@rustcorp.com.au> wrote: >> My anti-complexity argument leads me to ask why we'd support >> OP_CODESEPARATOR at all? Though my argument is weaker here: no wallet >> need support it. > > Because it could make scripts more compact in some cases? > > This is an example: https://github.com/bitcoin/bitcoin/pull/11423#issuecomment-333441321 <https://github.com/bitcoin/bitcoin/pull/11423#issuecomment-333441321> > > But this is probably not a good example for taproot, as it could be more efficient by making the 2 branches as different script merkle leaves. Thanks, I hadn't seen this before! That's also the first time I've seen SIGHASH_NONE used. >> But I don't see how OP_CODESEPARATOR changes anything here, wrt NOINPUT? >> Remember, anyone can create an output which can be spent by any NOINPUT, >> whether we go for OP_MASK or simply not commiting to the input script. >> > > Let me elaborate more. Currently, scriptCode is truncated at the last executed CODESEPARATOR. If we have a very big script with many CODESEPARATORs and CHECKSIGs, there will be a lot of hashing to do. > > To fix this problem, it is proposed that the new sighash will always commit to the same H(script), instead of the truncated scriptCode. So we only need to do the H(script) once, even if the script is very big Yes, I read this as proposed, it is clever. Not sure we'd be introducing it if OP_CODESEPARATOR didn't already exist, but at least it's a simplfication. > In the case of NOINPUT with MASKEDSCRIPT, it will commit to the H(masked_script) instead of H(script). > > To make CODESEPARATOR works as before, the sighash will also commit to the position of the last executed CODESEPARATOR. So the semantics doesn’t change. For scripts without CODESEPARATOR, the committed value is a constant. > > IF NOINPUT does not commit to H(masked_script), technically it could still commit to the position of the last executed CODESEPARATOR. But since the wallet is not aware of the actual content of the script, it has to guess the meaning of such committed positions, like “with the HD key path m/x/y/z, I assume the script template is blah blah blah because I never use this path for another script template, and the meaning of signing the 3rd CODESEPARATOR is blah blah blah”. It still works if the assumptions hold, but sounds quite unreliable to me. My question is more fundamental. If NOINPUT doesn't commit to the input at all, no script, no code separator, nothing. I'm struggling to understand your original comment was "without signing the script or masked script, OP_CODESEPARATOR becomes unusable or insecure with NOINPUT." I mean, non-useful, sure. Its purpose is to alter signature behavior, and from the script POV there's no signature with this form of NOINPUT. But other than the already-established "I reused keys for multiple outputs" oops, I don't see any new dangers? Thanks, Rusty. ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-20 23:17 ` Rusty Russell @ 2018-12-21 18:54 ` Johnson Lau 2018-12-23 4:26 ` Anthony Towns 0 siblings, 1 reply; 55+ messages in thread From: Johnson Lau @ 2018-12-21 18:54 UTC (permalink / raw) To: Rusty Russell; +Cc: bitcoin-dev > On 21 Dec 2018, at 7:17 AM, Rusty Russell <rusty@rustcorp.com.au> wrote: > > Johnson Lau <jl2012@xbt.hk> writes: > >>> But I don't see how OP_CODESEPARATOR changes anything here, wrt NOINPUT? >>> Remember, anyone can create an output which can be spent by any NOINPUT, >>> whether we go for OP_MASK or simply not commiting to the input script. >>> >> >> Let me elaborate more. Currently, scriptCode is truncated at the last executed CODESEPARATOR. If we have a very big script with many CODESEPARATORs and CHECKSIGs, there will be a lot of hashing to do. >> >> To fix this problem, it is proposed that the new sighash will always commit to the same H(script), instead of the truncated scriptCode. So we only need to do the H(script) once, even if the script is very big > > Yes, I read this as proposed, it is clever. Not sure we'd be > introducing it if OP_CODESEPARATOR didn't already exist, but at least > it's a simplfication. > >> In the case of NOINPUT with MASKEDSCRIPT, it will commit to the H(masked_script) instead of H(script). >> >> To make CODESEPARATOR works as before, the sighash will also commit to the position of the last executed CODESEPARATOR. So the semantics doesn’t change. For scripts without CODESEPARATOR, the committed value is a constant. >> >> IF NOINPUT does not commit to H(masked_script), technically it could still commit to the position of the last executed CODESEPARATOR. But since the wallet is not aware of the actual content of the script, it has to guess the meaning of such committed positions, like “with the HD key path m/x/y/z, I assume the script template is blah blah blah because I never use this path for another script template, and the meaning of signing the 3rd CODESEPARATOR is blah blah blah”. It still works if the assumptions hold, but sounds quite unreliable to me. > > My question is more fundamental. If NOINPUT doesn't commit to the input > at all, no script, no code separator, nothing. I'm struggling to > understand your original comment was "without signing the script or > masked script, OP_CODESEPARATOR becomes unusable or insecure with > NOINPUT." > > I mean, non-useful, sure. Its purpose is to alter signature behavior, > and from the script POV there's no signature with this form of NOINPUT. > But other than the already-established "I reused keys for multiple > outputs" oops, I don't see any new dangers? > > Thanks, > Rusty. The question I would like to ask is: is OP_CODESEPARATOR useful under taproot? Generally speaking, CODESEPARATOR is useful only with conditional opcodes (OP_IF etc), and conditional opcodes are mostly replaced by merklized scripts. I am not sure how much usability is left with CODESEPARATOR If no one needs CODESEPARATOR, we might just disable it, and makes the validation code a bit simpler If CODESEPARATOR is useful, then we should find a way to make it works with NOINPUT. With H(masked_script) committed, the meaning of the CODESEPARATOR position is very clear. Without H(masked_script), the meaning of the position totally relies on the assumption that “this public key is only used in this script template”. Ignore CODESEPARATOR and more generally, I agree with you that script masking does not help in the case of address (scriptPubKey) reuse, which is the commonest type of reuse. However, it prevents replayability when the same public key is reused in different scripts ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-21 18:54 ` Johnson Lau @ 2018-12-23 4:26 ` Anthony Towns 2018-12-23 16:33 ` Johnson Lau 0 siblings, 1 reply; 55+ messages in thread From: Anthony Towns @ 2018-12-23 4:26 UTC (permalink / raw) To: Johnson Lau; +Cc: bitcoin-dev On Sat, Dec 22, 2018 at 02:54:42AM +0800, Johnson Lau wrote: > The question I would like to ask is: is OP_CODESEPARATOR useful under taproot? Generally speaking, CODESEPARATOR is useful only with conditional opcodes (OP_IF etc), and conditional opcodes are mostly replaced by merklized scripts. I am not sure how much usability is left with CODESEPARATOR If you don't have conditionals, then I think committing to the (masked) script gives you everything you could do with codeseparator. If you don't commit to the (masked) script, don't have conditionals, and don't have codeseparator, then I don't think you can make a signature distinguish which alternative script it's intending to sign; but you can just give each alternative script in the MAST a slight variation of the key and that seems good enough. OTOH, I think for (roughly) the example you gave: DEPTH 3 EQUAL IF <Bob> CHECKSIGVERIFY HASH160 <H> EQUALVERIFY CODESEP ELSE <n> CLTV DROP ENDIF <Alice> CHECKSIG then compared to the taproot equivalent: P = muSig(Alice,Bob) S1 = <Alice1> CHECKSIGVERIFY <Bob> CHECKSIGVERIFY HASH160 <H> EQUAL S2 = <Alice2> CHECKSIGVERIFY <n> CLTV the IF+CODESEP approach is actually cheaper (lighter weight) if you're mostly (>2/3rds of the time) taking the S1 branch. This is because the "DEPTH 3 EQUAL IF/ELSE/ENDIF CODESEP <n> CLTV DROP" overhead is less than the 32B overhead to choose a merkle branch). (That said, I'm not sure what Alice's signature in the S1 branch actually achieves in that script; and without that in S1, the taproot approach is cheaper all the time. Scriptless scripts would be cheaper still) > If no one needs CODESEPARATOR, we might just disable it, and makes the validation code a bit simpler Since it only affects the behaviour of the checkdls (checksig) operators, even if it was disabled, it could be re-enabled fairly easily in a new script subversion if needed (ie, it could be re-added when upgrading witness version 1 from script version 0 to 1). Cheers, aj ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-23 4:26 ` Anthony Towns @ 2018-12-23 16:33 ` Johnson Lau 2018-12-24 12:01 ` ZmnSCPxj 0 siblings, 1 reply; 55+ messages in thread From: Johnson Lau @ 2018-12-23 16:33 UTC (permalink / raw) To: Anthony Towns; +Cc: bitcoin-dev > On 23 Dec 2018, at 12:26 PM, Anthony Towns <aj@erisian.com.au> wrote: > > On Sat, Dec 22, 2018 at 02:54:42AM +0800, Johnson Lau wrote: >> The question I would like to ask is: is OP_CODESEPARATOR useful under taproot? Generally speaking, CODESEPARATOR is useful only with conditional opcodes (OP_IF etc), and conditional opcodes are mostly replaced by merklized scripts. I am not sure how much usability is left with CODESEPARATOR > > If you don't have conditionals, then I think committing to the (masked) > script gives you everything you could do with codeseparator. I don’t think CODESEPARATOR is useful without conditionals. By useful I mean making a script more compact > > If you don't commit to the (masked) script, don't have conditionals, > and don't have codeseparator, then I don't think you can make a signature > distinguish which alternative script it's intending to sign; but you can > just give each alternative script in the MAST a slight variation of the > key and that seems good enough. You can and should always use a different in different branch. If this best practice is always followed, committing to masked script is not necessary > > OTOH, I think for (roughly) the example you gave: > > DEPTH 3 EQUAL > IF <Bob> CHECKSIGVERIFY HASH160 <H> EQUALVERIFY CODESEP > ELSE <n> CLTV DROP > ENDIF > <Alice> CHECKSIG > > then compared to the taproot equivalent: > > P = muSig(Alice,Bob) > S1 = <Alice1> CHECKSIGVERIFY <Bob> CHECKSIGVERIFY HASH160 <H> EQUAL > S2 = <Alice2> CHECKSIGVERIFY <n> CLTV > > the IF+CODESEP approach is actually cheaper (lighter weight) if you're > mostly (>2/3rds of the time) taking the S1 branch. This is because the > "DEPTH 3 EQUAL IF/ELSE/ENDIF CODESEP <n> CLTV DROP" overhead is less > than the 32B overhead to choose a merkle branch). > > (That said, I'm not sure what Alice's signature in the S1 branch actually > achieves in that script; and without that in S1, the taproot approach is > cheaper all the time. Scriptless scripts would be cheaper still) > >> If no one needs CODESEPARATOR, we might just disable it, and makes the validation code a bit simpler > > Since it only affects the behaviour of the checkdls (checksig) operators, > even if it was disabled, it could be re-enabled fairly easily in a new > script subversion if needed (ie, it could be re-added when upgrading > witness version 1 from script version 0 to 1). > > Cheers, > aj > Yes, I don’t think it needs Alice signature in S1 at all. So the original example doesn’t even need CODESEPARATOR at all. Could anyone propose a better use case of CODESEPARATOR? ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-23 16:33 ` Johnson Lau @ 2018-12-24 12:01 ` ZmnSCPxj 2018-12-24 21:23 ` Johnson Lau 0 siblings, 1 reply; 55+ messages in thread From: ZmnSCPxj @ 2018-12-24 12:01 UTC (permalink / raw) To: Johnson Lau, Bitcoin Protocol Discussion Good morning, > Could anyone propose a better use case of CODESEPARATOR? Long ago, aj sent an email on Lightning-dev about use of CODESEPARATOR to impose Scriptless Script even without Schnorr. It involved 3 signatures with different CODESEPARATOR places, and forced R reuse so that the signatures to claim the funds revealed the privkey. The script shown had all CODESEPARATOR in a single branch. I cannot claim to understand the script, and am having difficulty digging through the mailinglist Regards, ZmnSCPxj ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-24 12:01 ` ZmnSCPxj @ 2018-12-24 21:23 ` Johnson Lau 0 siblings, 0 replies; 55+ messages in thread From: Johnson Lau @ 2018-12-24 21:23 UTC (permalink / raw) To: ZmnSCPxj; +Cc: bitcoin-dev [-- Attachment #1: Type: text/plain, Size: 1933 bytes --] I find another proposed use of CODESEPARATOR here: https://lists.linuxfoundation.org/pipermail/lightning-dev/2016-March/000455.html <https://lists.linuxfoundation.org/pipermail/lightning-dev/2016-March/000455.html> <KeyA> OP_CHECKSIG OP_IF <KeyB> OP_ELSE <Delay> OP_CSV OP_DROP OP_CODESEPARATOR <KeyA> OP_ENDIF OP_CHECKSIG It is actually 2 scripts: S1: <KeyA> OP_CHECKSIGVERIFY <KeyB> OP_CHECKSIG S2: <Delay> OP_CSV OP_DROP <KeyA> OP_CHECKSIG Under taproot, we could make Q = P + H(P||S2)G, where P = MuSig(KeyA, KeyB) S1 becomes a direct spending with Q, and there is no need to use OP_IF or CODESEPARATOR in S2 at all. ================== If it is only to force R reuse, there is no need to use CODESEPARATOR: Input: <R> <S2> <S1> Script: 2DUP EQUAL NOT VERIFY 2 PICK SWAP CAT <key> DUP TOALTSTACK CHECKSIGVERIFY CAT FROMALTSTACK CHECKSIG But using CODESEPARATOR will save 3 bytes Input: <S2> <R> <S1> Script: OVER SWAP CAT <key> DUP TOALTSTACK CHECKSIGVERIFY CODESEPARATOR SWAP CAT FROMALTSTACK CHECKSIG However, a much better way would be: Input: <S> Script: <known R> SWAP CAT <key> CHECKSIG The discrete log of R could be a shared secret between A and B. If the purpose is to publish the private key to the whole world, R = G could be used. > On 24 Dec 2018, at 8:01 PM, ZmnSCPxj <ZmnSCPxj@protonmail.com> wrote: > > Good morning, > >> Could anyone propose a better use case of CODESEPARATOR? > > Long ago, aj sent an email on Lightning-dev about use of CODESEPARATOR to impose Scriptless Script even without Schnorr. It involved 3 signatures with different CODESEPARATOR places, and forced R reuse so that the signatures to claim the funds revealed the privkey. > > The script shown had all CODESEPARATOR in a single branch. > > I cannot claim to understand the script, and am having difficulty digging through the mailinglist > > Regards, > ZmnSCPxj [-- Attachment #2: Type: text/html, Size: 3774 bytes --] ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-14 9:30 ` Anthony Towns 2018-12-14 13:55 ` Johnson Lau @ 2018-12-16 6:55 ` Rusty Russell 2018-12-17 19:08 ` Johnson Lau 1 sibling, 1 reply; 55+ messages in thread From: Rusty Russell @ 2018-12-16 6:55 UTC (permalink / raw) To: Anthony Towns, Bitcoin Protocol Discussion, bitcoin-dev Anthony Towns via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> writes: > On Thu, Dec 13, 2018 at 11:07:28AM +1030, Rusty Russell via bitcoin-dev wrote: >> And is it worthwhile doing the mask complexity, rather than just >> removing the commitment to script with NOINPUT? It *feels* safer to >> restrict what scripts we can sign, but is it? > > If it's not safer in practice, we've spent a little extra complexity > committing to a subset of the script in each signature to no gain. If > it is safer in practice, we've prevented people from losing funds. I'm > all for less complexity, but not for that tradeoff. There are many complexities we could add, each of which would prevent loss of funds in some theoretical case. From practical experience; reuse of private keys between lightning and other things is not how people will lose funds[1]. It *is* however non-trivially more complicated for wallets; they currently have a set of script templates which they will sign (ie. no OP_CODESEPARATOR) and I implemented BIP 143 with only the simplest of naive code[2]. In particular, there is no code to parse scripts. Bitcoind developers are not in a good position to assess complexity here. They have to implement *everything*, so each increment seems minor. In addition, none of these new script versions will ever make bitcoind simpler, since they have to support all prior ones. Wallets, however, do not have to. I also think that minimal complexity for (future) wallets is an underappreciated feature: the state of wallets in bitcoin is poor[3] so simplicity should be a key goal. Respectfully, Rusty. [1] Reusing your revocation base point across two channels will lose funds in a much more trivial way, as will reusing payment hashes across invoices. [2] In fact, I added SIGHASH_ANYONECANPAY and SIGHASH_SINGLE recently for Segwit and it worked first time! Kudos to BIP143's authors for such a clear guide. [3] Bitcoind's wallet can't restore from seed; this neatly demonstrates how hard the wallet problem is, but there are many others. code, as modern wallets currently don't have to parse the scripts they sign. I'm telling you that this is not how people are losing funds. > > Also, saying "I can't see how to break this, so it's probably good > enough, even if other people have a bad feeling about it" is a crypto > anti-pattern, isn't it? > > I don't see how you could feasibly commit to more information than script > masking does for use cases where you want to be able to spend different > scripts with the same signature [0]. If that's possible, I'd probably > be for it. > > At the same time, script masking does seem feasible, both for > lightning/eltoo, and even for possibly complex variations of scripts. So > committing to less doesn't seem wise. > >> You already need both key-reuse and amount-reuse to be exploited. >> SIGHASH_MASK only prevents you from reusing this input for a "normal" >> output; if you used this key for multiple scripts of the same form, >> you're vulnerable[1]. > > For example, script masking seems general enough to prevent footguns > even if (for some reason) key and value reuse across eltoo channels > were a requirement, rather than prohibited: you'd make the script be > "<eltoo-channel-id> MASK <statenum> CLTV 2DROP <a+b> CHECKSIG", and your > signature will only apply to that channel, even if another channel has > the same capacity and uses the same keys, a and b. > >> So I don't think it's worth it. SIGHASH_NOINPUT is simply dangerous >> with key-reuse, and Don't Do That. > > For my money, "NOINPUT" commits to dangerously little context, and > doesn't really feel safe to include as a primitive -- as evidenced by > the suggestion to add "_UNSAFE" or similar to its name. Personally, I'm > willing to accept a bit of risk, so that feeling doesn't make me strongly > against the idea; but it also makes it hard for me to want to support > adding it. To me, committing to a masked script is a huge improvement. > > Heck, if it also makes it easier to do something safer, that's also > probably a win... > > Cheers, > aj > > [0] You could, perhaps, commit to knowing the private keys for all the > *outputs* you're spending to, as well as the inputs, which comes > close to saying "I know this is a scary NOINPUT transaction, but > we're paying to ourselves, so it will all be okay". > _______________________________________________ > bitcoin-dev mailing list > bitcoin-dev@lists.linuxfoundation.org > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-16 6:55 ` Rusty Russell @ 2018-12-17 19:08 ` Johnson Lau 2018-12-18 4:22 ` Peter Todd 2018-12-19 0:39 ` Rusty Russell 0 siblings, 2 replies; 55+ messages in thread From: Johnson Lau @ 2018-12-17 19:08 UTC (permalink / raw) To: Rusty Russell, bitcoin-dev > On 16 Dec 2018, at 2:55 PM, Rusty Russell via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> wrote: > > Anthony Towns via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> writes: >> On Thu, Dec 13, 2018 at 11:07:28AM +1030, Rusty Russell via bitcoin-dev wrote: >>> And is it worthwhile doing the mask complexity, rather than just >>> removing the commitment to script with NOINPUT? It *feels* safer to >>> restrict what scripts we can sign, but is it? >> >> If it's not safer in practice, we've spent a little extra complexity >> committing to a subset of the script in each signature to no gain. If >> it is safer in practice, we've prevented people from losing funds. I'm >> all for less complexity, but not for that tradeoff. > > There are many complexities we could add, each of which would prevent > loss of funds in some theoretical case. Every security measures are overkill, until someone get burnt. If these security measures are really effective, no one will get burnt. The inevitable conclusion is: every effective security measures are overkill. > > From practical experience; reuse of private keys between lightning and > other things is not how people will lose funds[1]. Assuming an user holds a private key exclusively and securely, currently there are only 2 ways to lose funds by private key reuse: 1. reusing the same signature nonce; 2. signing the hash “one”, for the SIGHASH_SINGLE consensus bug. People lost money for the first reason. Since this is a feature of the signature schemes we use, unavoidably that will happen again from time to time. The second one has been fixed in segwit (though incompletely), and could be completely fixed with a simple softfork. Overall speaking, while private key reuse hurts fungibility and privacy, it is not terribly insecure, as long as you use rfc6979 and are not foolish enough to sign hash “one”. This actually thanks to the fact that signatures always committed to the previous txid. It makes sure that a signature is never valid for more than one UTXO. Unfortunately, the guarantee of non-replayability incentified the practice of key-reuse, since the day-one of bitcoin. While NOINPUT fundamentally changes this security assumption, it won’t change this long-established culture of key reuse. So you argument seems just begging the question. Without NOINPUT, it is just impossible to lose money by key reuse, and this is exactly the topic we are debating. > > It *is* however non-trivially more complicated for wallets; they > currently have a set of script templates which they will sign (ie. no > OP_CODESEPARATOR) and I implemented BIP 143 with only the simplest of > naive code[2]. In particular, there is no code to parse scripts. Sorry that I’m not familiar with the implementation details of your wallet. But as you don’t have code to parse scripts, I assume your wallet can’t handle OP_CODESEPARATOR? However, this is exactly what you should do: only implement what you actually need, and ignore those unrelated details. Also, trying to faithfully and completely reproduce the consensus code in a wallet (even if you don’t need that at all) could be extremely dangerous. Such wallet might be tricked, for example, to sign the hash “one” and get all money stolen (I was told someone really did that, but I don’t know the details) If you didn’t implement OP_CODESEPARATOR because you didn’t use it, there is no reason for you to fully implement OP_MASKEDPUSH nor script parsing. In existing signature schemes (e.g. BIP143), signatures always commit to the script being executed (the “scriptCode”). I assume that all wallets would re-construct the scriptCode at signing time, based on the limited set of script templates they support. If a wallet had a function called GetScriptCodeForMultiSig() for this purpose, all they need now is a GetMaskedScriptCodeForMultiSig() that returns the masked template, or a new option in the existing GetScriptCodeForMultiSig(). It does not need to be something like GetMaskedScript(GetScriptCodeForMultiSig()). After all, only a very small number of script templates really need NOINPUT. A GetMaskedScript() in a wallet is just an overkill (and a vulnerability if mis-implemented) > > Bitcoind developers are not in a good position to assess complexity > here. They have to implement *everything*, so each increment seems > minor. In addition, none of these new script versions will ever make > bitcoind simpler, since they have to support all prior ones. Wallets, > however, do not have to. > > I also think that minimal complexity for (future) wallets is an > underappreciated feature: the state of wallets in bitcoin is poor[3] > so simplicity should be a key goal. It is a 3-way tradeoff of security, complexity, and functionality. While not everyone might appreciate this, security seems to always be the dominent factor in bitcoin protocol development. It was the reason why most core contributors were hesitant towards BIP148, despite they all love the functionality of segwit. It’s also about functionality here: as I mentioned in another reply, OP_CODESEPARATOR couldn’t function properly with NOINPUT but without OP_MASKEDPUSH This debate happens because NOINPUT introduces the third way to lose fund with key reuse. And once it is deployed, we have to support it forever, and is not something that we could softfork it away. > > Respectfully, > Rusty. > > [1] Reusing your revocation base point across two channels will lose > funds in a much more trivial way, as will reusing payment hashes > across invoices. > [2] In fact, I added SIGHASH_ANYONECANPAY and SIGHASH_SINGLE recently > for Segwit and it worked first time! Kudos to BIP143's authors for > such a clear guide. > [3] Bitcoind's wallet can't restore from seed; this neatly demonstrates > how hard the wallet problem is, but there are many others. > > > > > > > > > > > > > code, as modern wallets currently don't have to parse the scripts they > sign. > > > > > > > > I'm telling you that this is not how people are losing funds. > > > >> >> Also, saying "I can't see how to break this, so it's probably good >> enough, even if other people have a bad feeling about it" is a crypto >> anti-pattern, isn't it? >> >> I don't see how you could feasibly commit to more information than script >> masking does for use cases where you want to be able to spend different >> scripts with the same signature [0]. If that's possible, I'd probably >> be for it. >> >> At the same time, script masking does seem feasible, both for >> lightning/eltoo, and even for possibly complex variations of scripts. So >> committing to less doesn't seem wise. >> >>> You already need both key-reuse and amount-reuse to be exploited. >>> SIGHASH_MASK only prevents you from reusing this input for a "normal" >>> output; if you used this key for multiple scripts of the same form, >>> you're vulnerable[1]. >> >> For example, script masking seems general enough to prevent footguns >> even if (for some reason) key and value reuse across eltoo channels >> were a requirement, rather than prohibited: you'd make the script be >> "<eltoo-channel-id> MASK <statenum> CLTV 2DROP <a+b> CHECKSIG", and your >> signature will only apply to that channel, even if another channel has >> the same capacity and uses the same keys, a and b. >> >>> So I don't think it's worth it. SIGHASH_NOINPUT is simply dangerous >>> with key-reuse, and Don't Do That. >> >> For my money, "NOINPUT" commits to dangerously little context, and >> doesn't really feel safe to include as a primitive -- as evidenced by >> the suggestion to add "_UNSAFE" or similar to its name. Personally, I'm >> willing to accept a bit of risk, so that feeling doesn't make me strongly >> against the idea; but it also makes it hard for me to want to support >> adding it. To me, committing to a masked script is a huge improvement. >> >> Heck, if it also makes it easier to do something safer, that's also >> probably a win... >> >> Cheers, >> aj >> >> [0] You could, perhaps, commit to knowing the private keys for all the >> *outputs* you're spending to, as well as the inputs, which comes >> close to saying "I know this is a scary NOINPUT transaction, but >> we're paying to ourselves, so it will all be okay". >> _______________________________________________ >> 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 ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-17 19:08 ` Johnson Lau @ 2018-12-18 4:22 ` Peter Todd 2018-12-19 0:39 ` Rusty Russell 1 sibling, 0 replies; 55+ messages in thread From: Peter Todd @ 2018-12-18 4:22 UTC (permalink / raw) To: Johnson Lau, Bitcoin Protocol Discussion [-- Attachment #1: Type: text/plain, Size: 1248 bytes --] On Tue, Dec 18, 2018 at 03:08:26AM +0800, Johnson Lau via bitcoin-dev wrote: > >> If it's not safer in practice, we've spent a little extra complexity > >> committing to a subset of the script in each signature to no gain. If > >> it is safer in practice, we've prevented people from losing funds. I'm > >> all for less complexity, but not for that tradeoff. > > > > There are many complexities we could add, each of which would prevent > > loss of funds in some theoretical case. > > Every security measures are overkill, until someone get burnt. If these security measures are really effective, no one will get burnt. The inevitable conclusion is: every effective security measures are overkill. This isn't really a security issue, it's a software reliability issue. And you're making a trade-off between complexity of the core protocol and complexity of wallet software. A core protocol failure has high costs for every single Bitcoin user; a wallet software failure affects a much smaller number of people. So I'd be inclined to prioritise core protocol simplicity rather than stamping out one of many, many, ways that wallet software can screw up and lose money. -- https://petertodd.org 'peter'[:-1]@petertodd.org [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-17 19:08 ` Johnson Lau 2018-12-18 4:22 ` Peter Todd @ 2018-12-19 0:39 ` Rusty Russell 2019-02-09 0:39 ` Pieter Wuille 1 sibling, 1 reply; 55+ messages in thread From: Rusty Russell @ 2018-12-19 0:39 UTC (permalink / raw) To: Johnson Lau, bitcoin-dev Johnson Lau <jl2012@xbt.hk> writes: >> On 16 Dec 2018, at 2:55 PM, Rusty Russell via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> wrote: >> >> Anthony Towns via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> writes: >>> On Thu, Dec 13, 2018 at 11:07:28AM +1030, Rusty Russell via bitcoin-dev wrote: >>>> And is it worthwhile doing the mask complexity, rather than just >>>> removing the commitment to script with NOINPUT? It *feels* safer to >>>> restrict what scripts we can sign, but is it? >>> >>> If it's not safer in practice, we've spent a little extra complexity >>> committing to a subset of the script in each signature to no gain. If >>> it is safer in practice, we've prevented people from losing funds. I'm >>> all for less complexity, but not for that tradeoff. >> >> There are many complexities we could add, each of which would prevent >> loss of funds in some theoretical case. > > Every security measures are overkill, until someone get burnt. If these security measures are really effective, no one will get burnt. The inevitable conclusion is: every effective security measures are overkill. > >> >> From practical experience; reuse of private keys between lightning and >> other things is not how people will lose funds[1]. > > So you argument seems just begging the question. Without NOINPUT, it is just impossible to lose money by key reuse, and this is exactly the topic we are debating. I think we're getting confused here. I'm contributing my thoughts from the lightning implementer's point of view; there are other important considerations, but this is my contribution. In *lightning* there are more ways to lose funds via secret reuse. Meanwhile, both SIGHASH_NOINPUT and OP_MASK have the reuse-is-dangerous property; with OP_MASK the danger is limited to reuse-on-the-same-script (ie. if you use the same key for a non-lightning output and a lightning output, you're safe with OP_MASK. However, this is far less likely in practice). I state again: OP_MASK doesn't seem to gain *lightning* any significant security benefit. > It does not need to be something like GetMaskedScript(GetScriptCodeForMultiSig()). After all, only a very small number of script templates really need NOINPUT. A GetMaskedScript() in a wallet is just an overkill (and a vulnerability if mis-implemented) Our current transaction signing code is quite generic (and, if I may say so, readable and elegant). We could, of course, special case GetMaskedScript() for the case we need (the Eltoo examples I've seen have a single OP_MASK at the front, which makes it trivial). > It’s also about functionality here: as I mentioned in another reply, OP_CODESEPARATOR couldn’t function properly with NOINPUT but without OP_MASKEDPUSH The mailing list seems a bit backed up or something; I replied to that in the hope you can clear my confusion on that one. > This debate happens because NOINPUT introduces the third way to lose fund with key reuse. And once it is deployed, we have to support it forever, and is not something that we could softfork it away. A would use the same words to encourage you to create the simplest possible implementation? I don't think we disagree on philosophy, just trade-offs. And that's OK. Cheers, Rusty. ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-19 0:39 ` Rusty Russell @ 2019-02-09 0:39 ` Pieter Wuille 0 siblings, 0 replies; 55+ messages in thread From: Pieter Wuille @ 2019-02-09 0:39 UTC (permalink / raw) To: Rusty Russell, Bitcoin Protocol Discussion On Wed, 19 Dec 2018 at 18:06, Rusty Russell via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> wrote: > > Meanwhile, both SIGHASH_NOINPUT and OP_MASK have the reuse-is-dangerous > property; with OP_MASK the danger is limited to reuse-on-the-same-script > (ie. if you use the same key for a non-lightning output and a lightning > output, you're safe with OP_MASK. However, this is far less likely in > practice). Having had some more time to consider this and seeing discussions about alternatives, I agree. It doesn't seem that OP_MASK protects against any likely failure modes. I do think that there are realistic risks around NOINPUT, but output tagging (as suggested in another ML thread) seems to match those much better than masking does. Cheers, -- Pieter ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-12-12 9:42 ` Rusty Russell 2018-12-12 20:00 ` Johnson Lau @ 2018-12-13 0:24 ` Anthony Towns 1 sibling, 0 replies; 55+ messages in thread From: Anthony Towns @ 2018-12-13 0:24 UTC (permalink / raw) To: Rusty Russell, Bitcoin Protocol Discussion On Wed, Dec 12, 2018 at 08:12:10PM +1030, Rusty Russell via bitcoin-dev wrote: > Pieter Wuille via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> writes: > > Here is a combined proposal: > > * Three new sighash flags are added: SIGHASH_NOINPUT, SIGHASH_NOFEE, > > and SIGHASH_SCRIPTMASK. > > * A new opcode OP_MASK is added, which acts as a NOP during execution. > > * The sighash is computed like in BIP143, but: > > * If SIGHASH_SCRIPTMASK is present, for every OP_MASK in scriptCode > > the subsequent opcode/push is removed. > I'm asking on-list because I'm sure I'm not the only confused one. > Having the SIGHASH_SCRIPTMASK flag is redundant AFAICT: why not always > perform mask-removal for signing? The way I'm thinking about it is there's four amounts of knowledge you could have about the input you're spending at the time you generate a signature: ALL: you know everything about every input for this tx SINGLE: you know everything about the input you're signing for, but not necessarily the others SCRIPTPUBKEY: you know the exact scriptPubKey you're trying to satisfy, but don't know the txid SCRIPTMASK: you don't know the txid, don't know the scriptPubKey, don't know the other taproot branches, and maybe don't even know the masked out terms in the script -- but you do know the structure of the script, and the non-masked terms There's no value to masking in any but the final case -- the txid and scriptPubKey commit to the full scriptcode already, so also signing the scriptcode is just belt-and-suspenders protection. (It might be that the "SCRIPTPUBKEY" option isn't very useful in practice; maybe you'll always either know the txid, or need to mask something?) > And I am struggling to understand the role of scriptmask in a taproot > world, where the alternate script is both hidden and general? In a taproot world, your scriptPubKey is a point P=Q+H(Q,S)*G, where S is a merkle root of possibly many scripts, and is spendable either by: sig(P) Q, path(S,script), script, witness(script) SCRIPTMASK lets you prepare a signature for one particular script in advance, even before you've decided what the other scripts are (and even what the base point Q is), let alone built an actual transaction. At least, that's my current understanding; and I think it makes sense... Cheers, aj ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT @ 2018-11-28 0:54 Bob McElrath 2018-11-28 8:40 ` Johnson Lau 0 siblings, 1 reply; 55+ messages in thread From: Bob McElrath @ 2018-11-28 0:54 UTC (permalink / raw) To: Bitcoin Protocol Discussion I have been working on an experimental wallet that implements Bitcoin Covenants/Vaults following a blog post I wrote about 2 years ago, using "Pay-to-Timelock Signed Transaction" (P2TST). (Also mentioned recently by kanzure in a talk somewheres...) The idea is that you deposit to an address for which you don't know the private key. Instead you construct a second transaction sending that to a timelocked staging address for which you DO have the privkey (it also has an IF/ELSE condition with a second spending condition for use in case of theft attempt). In order to do this you either have to delete the privkey of the deposit address (a difficult proposition to know it's actually been deleted), but instead one can construct a signature directly using a RNG, and use the SIGHASH to compute the corresponding pubkey via ECDSA recover, from which you compute the corresponding address. In this way your wallet is a set of P2TST transactions and a corresponding privkey, with a (set of) emergency keys. This interacts with NOINPUT in the following way: if the input to the transaction commits to the pubkey in any way, you have a circular dependency on the pubkey that could only be satisfied by breaking a hash function. This occurs with standard sighash's which commit to the txid, which in turn commit to the address, which commits to the pubkey, so this construction of covenants/vaults requires NOINPUT. AFAICT sipa's proposal is compatible with the above vaulted construction by using SIGHASH_NOINPUT | SIGHASH_SCRIPTMASK to remove the scriptPubKey/redeemScript from the sighash. Putting the scriptPubKey/redeemScript in the sighash introduces the same circular dependency, but SIGHASH_SCRIPTMASK removes it. One would probably want to provide the fee from a separate wallet so as to be able to account for fluctuating fee pressures when the unvaulting occurs a long time after vaulting. Thus you'd want to use SIGHASH_SINGLE so that a fee-wallet can add fees (or for composability of P2TSTs), and SIGHASH_NOFEE as well. P.S. Also very excited to combine the above idea with Taproot/Graftroot/g'Root. -- Cheers, Bob McElrath "For every complex problem, there is a solution that is simple, neat, and wrong." -- H. L. Mencken ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-28 0:54 Bob McElrath @ 2018-11-28 8:40 ` Johnson Lau 2018-11-28 14:04 ` Bob McElrath 0 siblings, 1 reply; 55+ messages in thread From: Johnson Lau @ 2018-11-28 8:40 UTC (permalink / raw) To: Bob McElrath, bitcoin-dev This is incompatible with bip-schnorr, which intentionally disallow such use by always committing to the public key: https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr.mediawiki With the recent fake Satoshi signature drama, and other potential ways to misuse and abuse, I think this is a better way to go, which unfortunately might disallow some legitimate applications. Covenants could be made using OP_CHECKSIGFROMSTACK (https://fc17.ifca.ai/bitcoin/papers/bitcoin17-final28.pdf) or OP_PUSHTXDATA (https://github.com/jl2012/bips/blob/vault/bip-0ZZZ.mediawiki). I think this is the next step following the taproot soft fork > On 28 Nov 2018, at 8:54 AM, Bob McElrath via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> wrote: > > I have been working on an experimental wallet that implements Bitcoin > Covenants/Vaults following a blog post I wrote about 2 years ago, using > "Pay-to-Timelock Signed Transaction" (P2TST). (Also mentioned recently by > kanzure in a talk somewheres...) The idea is that you deposit to an address for > which you don't know the private key. Instead you construct a second > transaction sending that to a timelocked staging address for which you DO have > the privkey (it also has an IF/ELSE condition with a second spending condition > for use in case of theft attempt). In order to do this you either have to > delete the privkey of the deposit address (a difficult proposition to know it's > actually been deleted), but instead one can construct a signature directly using > a RNG, and use the SIGHASH to compute the corresponding pubkey via ECDSA > recover, from which you compute the corresponding address. In this way your > wallet is a set of P2TST transactions and a corresponding privkey, with a (set > of) emergency keys. > > This interacts with NOINPUT in the following way: if the input to the > transaction commits to the pubkey in any way, you have a circular dependency on > the pubkey that could only be satisfied by breaking a hash function. This > occurs with standard sighash's which commit to the txid, which in turn commit to > the address, which commits to the pubkey, so this construction of > covenants/vaults requires NOINPUT. > > AFAICT sipa's proposal is compatible with the above vaulted construction by > using SIGHASH_NOINPUT | SIGHASH_SCRIPTMASK to remove the > scriptPubKey/redeemScript from the sighash. Putting the > scriptPubKey/redeemScript in the sighash introduces the same circular > dependency, but SIGHASH_SCRIPTMASK removes it. > > One would probably want to provide the fee from a separate wallet so as to be > able to account for fluctuating fee pressures when the unvaulting occurs a long > time after vaulting. Thus you'd want to use SIGHASH_SINGLE so that a fee-wallet > can add fees (or for composability of P2TSTs), and SIGHASH_NOFEE as well. > > P.S. Also very excited to combine the above idea with Taproot/Graftroot/g'Root. > > -- > Cheers, Bob McElrath > > "For every complex problem, there is a solution that is simple, neat, and wrong." > -- H. L. Mencken > > _______________________________________________ > bitcoin-dev mailing list > bitcoin-dev@lists.linuxfoundation.org > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev ^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT 2018-11-28 8:40 ` Johnson Lau @ 2018-11-28 14:04 ` Bob McElrath 0 siblings, 0 replies; 55+ messages in thread From: Bob McElrath @ 2018-11-28 14:04 UTC (permalink / raw) To: Johnson Lau; +Cc: bitcoin-dev We are also prototyping the OP_CHECKSIGFROMSTACK mechanism using Liquid/Elements. Given uncertainty about which features will actually be deployed on mainnet, we're exploring all possibilities so as to provide feedback about the "best" way to implement a covenant/vault, also including the OP_CHECKOUTPUTVERIFY originally proposed by Eyal et al. That's 3 ways to implement a covenant/vault, if there's others I'd be happy to hear about it. ;-) Thanks for the OP_PUSHTXDATA ref, I'm reading now... Personally I think the OP_CHECKSIGFROMSTACK is probably the most elegant mechanism. Thanks for the feedback! Johnson Lau [jl2012@xbt.hk] wrote: > This is incompatible with bip-schnorr, which intentionally disallow such use by always committing to the public key: https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr.mediawiki > > With the recent fake Satoshi signature drama, and other potential ways to misuse and abuse, I think this is a better way to go, which unfortunately might disallow some legitimate applications. > > Covenants could be made using OP_CHECKSIGFROMSTACK (https://fc17.ifca.ai/bitcoin/papers/bitcoin17-final28.pdf) or OP_PUSHTXDATA (https://github.com/jl2012/bips/blob/vault/bip-0ZZZ.mediawiki). I think this is the next step following the taproot soft fork > > > On 28 Nov 2018, at 8:54 AM, Bob McElrath via bitcoin-dev <bitcoin-dev@lists.linuxfoundation.org> wrote: > > > > I have been working on an experimental wallet that implements Bitcoin > > Covenants/Vaults following a blog post I wrote about 2 years ago, using > > "Pay-to-Timelock Signed Transaction" (P2TST). (Also mentioned recently by > > kanzure in a talk somewheres...) The idea is that you deposit to an address for > > which you don't know the private key. Instead you construct a second > > transaction sending that to a timelocked staging address for which you DO have > > the privkey (it also has an IF/ELSE condition with a second spending condition > > for use in case of theft attempt). In order to do this you either have to > > delete the privkey of the deposit address (a difficult proposition to know it's > > actually been deleted), but instead one can construct a signature directly using > > a RNG, and use the SIGHASH to compute the corresponding pubkey via ECDSA > > recover, from which you compute the corresponding address. In this way your > > wallet is a set of P2TST transactions and a corresponding privkey, with a (set > > of) emergency keys. > > > > This interacts with NOINPUT in the following way: if the input to the > > transaction commits to the pubkey in any way, you have a circular dependency on > > the pubkey that could only be satisfied by breaking a hash function. This > > occurs with standard sighash's which commit to the txid, which in turn commit to > > the address, which commits to the pubkey, so this construction of > > covenants/vaults requires NOINPUT. > > > > AFAICT sipa's proposal is compatible with the above vaulted construction by > > using SIGHASH_NOINPUT | SIGHASH_SCRIPTMASK to remove the > > scriptPubKey/redeemScript from the sighash. Putting the > > scriptPubKey/redeemScript in the sighash introduces the same circular > > dependency, but SIGHASH_SCRIPTMASK removes it. > > > > One would probably want to provide the fee from a separate wallet so as to be > > able to account for fluctuating fee pressures when the unvaulting occurs a long > > time after vaulting. Thus you'd want to use SIGHASH_SINGLE so that a fee-wallet > > can add fees (or for composability of P2TSTs), and SIGHASH_NOFEE as well. > > > > P.S. Also very excited to combine the above idea with Taproot/Graftroot/g'Root. > > > > -- > > Cheers, Bob McElrath > > > > "For every complex problem, there is a solution that is simple, neat, and wrong." > > -- H. L. Mencken > > > > _______________________________________________ > > bitcoin-dev mailing list > > bitcoin-dev@lists.linuxfoundation.org > > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev > > > > > !DSPAM:5bfe5494217527839717631! -- Cheers, Bob McElrath "For every complex problem, there is a solution that is simple, neat, and wrong." -- H. L. Mencken ^ permalink raw reply [flat|nested] 55+ messages in thread
end of thread, other threads:[~2019-02-09 0:40 UTC | newest] Thread overview: 55+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2018-11-19 22:37 [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT Pieter Wuille 2018-11-20 20:29 ` Anthony Towns 2018-11-21 11:20 ` Christian Decker 2018-11-21 17:55 ` Johnson Lau 2018-11-21 11:15 ` Christian Decker 2018-11-23 6:04 ` Anthony Towns 2018-11-23 9:40 ` Christian Decker 2018-11-24 8:13 ` Johnson Lau 2018-11-21 17:07 ` Russell O'Connor 2018-11-22 14:28 ` Johnson Lau 2018-11-22 16:23 ` Russell O'Connor 2018-11-22 20:52 ` Johnson Lau 2018-11-22 22:10 ` Russell O'Connor 2018-11-23 10:47 ` Johnson Lau 2018-11-23 5:03 ` Anthony Towns 2018-11-23 20:18 ` Russell O'Connor 2018-11-28 3:41 ` Pieter Wuille 2018-11-28 8:31 ` Johnson Lau 2018-11-29 17:00 ` Christian Decker 2018-11-29 18:29 ` Christian Decker 2018-12-06 16:57 ` Russell O'Connor 2018-12-09 19:13 ` Johnson Lau 2018-12-11 22:50 ` Russell O'Connor 2018-12-12 19:53 ` Johnson Lau 2018-12-13 16:50 ` Russell O'Connor 2018-12-13 0:05 ` Anthony Towns 2018-12-13 16:21 ` Russell O'Connor 2018-12-14 0:47 ` Anthony Towns [not found] ` <CAAS2fgRma+Pw-rHJSOKRVBqoxqJ3AxHO9d696fWoa-sb17JEOQ@mail.gmail.com> 2018-12-13 16:34 ` Russell O'Connor 2018-12-09 22:41 ` David A. Harding 2018-12-11 15:36 ` Russell O'Connor 2018-12-11 17:47 ` David A. Harding 2018-12-12 9:42 ` Rusty Russell 2018-12-12 20:00 ` Johnson Lau 2018-12-12 23:49 ` Rusty Russell 2018-12-13 0:37 ` Rusty Russell 2018-12-14 9:30 ` Anthony Towns 2018-12-14 13:55 ` Johnson Lau 2018-12-17 3:10 ` Rusty Russell 2018-12-20 19:34 ` Johnson Lau 2018-12-20 23:17 ` Rusty Russell 2018-12-21 18:54 ` Johnson Lau 2018-12-23 4:26 ` Anthony Towns 2018-12-23 16:33 ` Johnson Lau 2018-12-24 12:01 ` ZmnSCPxj 2018-12-24 21:23 ` Johnson Lau 2018-12-16 6:55 ` Rusty Russell 2018-12-17 19:08 ` Johnson Lau 2018-12-18 4:22 ` Peter Todd 2018-12-19 0:39 ` Rusty Russell 2019-02-09 0:39 ` Pieter Wuille 2018-12-13 0:24 ` Anthony Towns 2018-11-28 0:54 Bob McElrath 2018-11-28 8:40 ` Johnson Lau 2018-11-28 14:04 ` Bob McElrath
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox