Return-Path: Received: from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id EFC9AC0174 for ; Mon, 3 Feb 2020 08:21:09 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id D057820016 for ; Mon, 3 Feb 2020 08:21:09 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from silver.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Ujsk1X4iSfZA for ; Mon, 3 Feb 2020 08:21:06 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from outgoing.mit.edu (outgoing-auth-1.mit.edu [18.9.28.11]) by silver.osuosl.org (Postfix) with ESMTPS id 607E01FEE0 for ; Mon, 3 Feb 2020 08:21:06 +0000 (UTC) Received: from mail-io1-f54.google.com (mail-io1-f54.google.com [209.85.166.54]) (authenticated bits=0) (User authenticated as jlrubin@ATHENA.MIT.EDU) by outgoing.mit.edu (8.14.7/8.12.4) with ESMTP id 0138L4bc015902 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=NOT) for ; Mon, 3 Feb 2020 03:21:04 -0500 Received: by mail-io1-f54.google.com with SMTP id n21so15702703ioo.10 for ; Mon, 03 Feb 2020 00:21:04 -0800 (PST) X-Gm-Message-State: APjAAAWW1O42wGbNMEyxry0ZbsBEG7CN7eS48tAKmHtSdQDVgugNRO1k 8sn8r5/BA+wld2gUVnwW77sv9dnr16X2dsOujFc= X-Google-Smtp-Source: APXvYqzFOO+MaOsslK37odoks5zUoWtQlNYeI6HVvkPHR1IMBvxkF+8FsP5yWQrvcDWVDNl5G1VZML8rlp4Qjy+Z76k= X-Received: by 2002:a5e:a809:: with SMTP id c9mr18512424ioa.105.1580718064029; Mon, 03 Feb 2020 00:21:04 -0800 (PST) MIME-Version: 1.0 References: <20200201203941.GE28549@mcelrath.org> In-Reply-To: <20200201203941.GE28549@mcelrath.org> From: Jeremy Date: Mon, 3 Feb 2020 00:20:52 -0800 X-Gmail-Original-Message-ID: Message-ID: To: Bob McElrath , Bitcoin Protocol Discussion Content-Type: multipart/alternative; boundary="000000000000b2563f059da79a3b" X-Mailman-Approved-At: Mon, 03 Feb 2020 08:31:49 +0000 Subject: Re: [bitcoin-dev] CTV through SIGHASH flags X-BeenThere: bitcoin-dev@lists.linuxfoundation.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Bitcoin Protocol Discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 03 Feb 2020 08:21:10 -0000 --000000000000b2563f059da79a3b Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable I think these ideas shows healthy review of how OP_CTV is specified against alternatives, but I think most of the ideas presented are ill advised. -- @JeremyRubin On Sat, Feb 1, 2020 at 2:15 PM Bob McElrath via bitcoin-dev < bitcoin-dev@lists.linuxfoundation.org> wrote: > We propose that OP_CHECKTEMPLATEVERIFY should behave more like CHECKSIG, > including a flags byte that specify what is hashed. This unifies the ways= a > SigHash is computed, differing only in the final checksig which is omitte= d > in > favor of chacking the hash directly. Having two paths to create a > signature hash > introduces extra complexity, especially as concerns potential future > SIGHASH > flag upgrades. > I believe the above may be possible *without* a new opcode and simply wit= h > a > sighash flag. That is, consider a flag SIGHASH_NOSIG which behaves as > follows: > The stack is expected to contain , where the hash to be > checked is > and is in the place where you'd normally put a pubkey. The byte > > is the second thing on the stack. This is intended to be an empty > "signature" > with the flags byte appended (which must contain SIGHASH_NOSIG to succeed= ). > I've previously brought this up in IRC http://gnusha.org/bitcoin-wizards/2019-11-28.log AFAIK, using an actual CheckSig SIGHASH Flag as is is a bad idea because then you need to include an encoding valid signature and pubkey that map onto the hash to check. This is not just extra 11 extra bytes of data (33 bytes PubKey + 9 bytes Signature + 2 push -32 bytes - 1 byte push), it's also a very awkward API. I don't think you can soft-fork around these encoding rules. But you're right that it's possible to add this as a SIGHASH flag. I don't think doing CTV as a sighash flag is worth considering further. I get your point that CTV is kind of a signature hash, and that we might want to not have a separate path. This ignores, however, that the current SIGHASH code-path is kind of garbage and literally no one likes it and it has been the source of nasty issues previously. Thus I posit that a separate path creates less complexity, as we don't need to worry about accidentally introducing a weird interaction with other sighash flags. > CTV omits inputs as part of its semantics, so CTV-type functionality usin= g > CHECKSIG is also achievable if some form of NOINPUT flag is also deployed= . > With > NOINPUT alone, a standard CHECKSIG can be used to implement a covenant -- > though > it uses an unnecessarily large number of bytes just to check a 32-byte > hash. > Therefore, any pitfalls CTV intends to evade can be evaded by using a > CHECKSIG, > if NOINPUT is deployed in some form, adding new flexibility. Beyond what= 's > possible with NOINPUT/ANYPREVOUT, CTV additionally commits to: > > =C2=BB=C2=B7=C2=B7=C2=B7=C2=B7=C2=B7=C2=B7=C2=B71. Number of inputs > =C2=BB=C2=B7=C2=B7=C2=B7=C2=B7=C2=B7=C2=B7=C2=B72. Number of outputs > =C2=BB=C2=B7=C2=B7=C2=B7=C2=B7=C2=B7=C2=B7=C2=B73. Index of input > NOINPUT as specified here https://github.com/ajtowns/bips/blob/bip-anyprevout/bip-anyprevout.mediawik= i (is this the latest?) isn't a great surrogate for CTV because CTV commits to the input index which prevents half-spend. This also encumbers, as proposed, an additional chaperone signature to fix it to a specific output. This adds a lot of complexity and space to using CTV. Maybe NOINPUT could make changes to special-case CTV, but then we're back to CTV again. > > The justification given for committing to the number of inputs and output= s > is > that "it makes CTV hashes easier to compute with script", however doing s= o > would > require OP_CAT. It's noted that both of these are actually redundant > commitments. Since the constexpr requirement was removed, if OP_CAT were > enabled, this commitment to the input index could be evaded by computing > the CTV > hash within the script, modifying the input index using data taken from t= he > witness. Therefore committing to the input index is a > sender-specified-policy > choice, and not an anti-footgun measure for the redeemer. As such, it's > appropriate to consider committing to the input index using a flag instea= d. > > This is incorrect almost entirely. 1. There is a semantic difference between the *commitment* being strictly redundant, which has more to do with malleation, and being redundant from a feature perspective. I could maybe do a better job here of expanding what "easier" means here -- there are actually some scripts which are quite difficult to write/impossible without this. I've described this a couple places outside of the BIP, but essentially it allows you to pin the number of inputs/outputs separately from the hashes themselves. So if you're trying to build the template in script, you might want to allow the Sequences to be set to any value, and pass them via a hash. But then from a hash you can't check the validity of the length. An external length commitment lets you do this, but without it you would have to pass in the sequences directly. 2. The constexpr requirement was implemented in a soft-fork re-moveable manner specifically so that if we wanted OP_CAT, we could add it without also introducing constructing CTVs on the stack. Similarly, it would be possible to specify with OP_CAT as a soft-fork removeable rule that if OP_CAT executes before an OP_CTV, the script is invalid. The constexpr rule was removed on the sentiment that if we introduce OP_CAT, we almost surely intend to introduce it for OP_CTV (or related) use cases. 3. Committing to the input-index is not a *sender* policy choice. It's a receiver policy choice. I tell a Payer my invoice/address, and they emit a transaction matching it. From an address containing a CTV, I as the receiver set the input_index. I don't see how this is related to the anti-footgun-ness 4. You write as if OP_CTV + OP_CAT allows the input index to stripped *unconditionally*. That's wrong. It's an opt in if you write a script taking it as a parameter. You can't evade it in general use. 5. The "anti-footgun" measure is that it precludes reused-keys being spent in the same transaction. Were you to opt out of the mechanism (via OP_CAT input_index), then you opt out of the reuse protection. (This only matters if there is more than one input to begin with). 6. Committing to it via a flag is strictly less flexible, because I can do a lot more with OP_CAT than with a flag. For instance, I can do OP_WITHIN OP_VERIFY to ensure that it falls within a certain range of inputs. 7. A flag is also an extra byte somewhere or uses a sighash bit. 8. Enabling a flag right away enables a big footgun right off the bat. I think it's bad for use safety. 9. Rather than add flags, if you wanted to add this, I would suggest reserving max input_index to specify a don't care value. Then you always check a given CTV against the don't care value and the specified value. Hashing the don't care value can be done in the PreComputedTxData. But I don't think it's worth special casing or making available today because of 8. > There are probably reasons this might not work as a flag that I haven't > discovered yet. Alternatively CTV might be considered to be an alternativ= e > type > of CHECKSIG operator and might be renamed to CHECKSIGHASH, appending flag > bytes > to the hash to be checked. > Sure -- happy to go down the renaming path again. Keep in mind that CTV currently only applies rules when the argument is 32-bytes. Future soft-forkers are welcome to define a rule for a 33byte 1st argument that treats it as a pubkey and has CHECKSIG semantics, and looks for another argument. > > The flags discussed above, NOINPUT, NOSIG, INPUTINDEX are all really > sender-policy choices, while SIGHASH flags are redeemer-choice as they > usually > occur in the witness. There's really no way currently for an output to > specify > that the redeemer must use a particular set of flags. One way to achieve > this is > to put the CHECKSIG(HASH) including its flags into the redeemScript -- > which is > functionally what CTV does (or a CHECKSIG in a redeemScript using NOINPUT= ). > This is committed to in outputs and therefore specifies sender policies, > however > the redeemScript is specified by the receiver. Perhaps an anti-footgun > measure > would be to require that certain SIGHASH flags like these MUST be > committed to > in the output, by the sender. > > I think this "sender/redeemer" framework is a bit bunk. Ultimately all redeemers are senders, and you aren't forcing a choice on someone. You could be on to something though, but I think in general Bitcoin has gone the way of opaque addresses so that people can't encumber arbitrary policies on your coins. Maybe it swings the other way... > CSV (CHECKSEQUENCEVERIFY) is an example that redemption policies are > committed > to in the output by the sender via the sequence_no field, and then checke= d > with > an opcode OP_CSV to enable relative timelocks. It's probably possible to > add new > flags to the sequence_no field, and check the new semantics with CSV > instead of > an entiely new opcode. > The sender commits to them, but legally, if you add a contract that I didn't agree to as receipt (e.g., in segwit address -- which the script is hashed) I won't even know I got paid. So the way Bitcoin works today, these are receiver set policies. One way to think of CTV is it's precise the opcode that lets you "wrap" someone's known address in arbitrary new scripts. E.g., if you gave me an address X, but I need to (for whatever reason) add an additional 1 month CSV. So i just get the txn: A: sequence 1mo 1 input 1 output: pay X 1 coin then take the STH(A), and create B B: ... inputs 1 output pay `STH(A) CTV` 1 coin I can also add other things, like secondary signers/alternatives `IF {some checksig program} STH(A) CTV ELSE {multisig program} ENDIF > As user policy choices, NOINPUT might be considered "MAY" conditions. A > user MAY > use NOINPUT on an output, but let's not require it. Covenants on the oth= er > hand, are a MUST condition. The CTV proposal imposes "MUST" conditions on > the > existence of the covenant itself, as well as the number of inputs and > outputs, > to prevent txid malleability so that such transactions can be used in > offline > protocols. Txid non-malleability can be achieved by enforcing that the > output > must be spent using SIGHASH_ALL instead of committing to the number of > inputs > separately with a new opcode. The MUST condition also helps with sighash > caching > for batch validation. > ANYPREVOUT/ANYSCRIPT are actually weirder than that, because once it has been used that key is permanently "burned". Hence ANYPREVOUT has such pubkeys be explicity tagged as ANYPREVOUT compatible. So a user kind of has to pre-decide if they want to have ANYPREVOUT semantics or not. And in this case, key-reuse is relatively unsafe (as you need to track what else you've signed) so I think what you're suggesting is not robust. These "MUST" conditions sound nice, but they don't actually help with validity caching because we want to be able to compute this information before we've fetched the outputs from the database so we can't know what to cache yet. Contextless things are things you can precompute not knowing input scripts. Again, I don't think this sender/redeemer framework is super useful but I admire the attempt. > > INPUTINDEX is required in a CTV/CHECKSIGHASH world because of the > half-spend > problem. Normally outputs are spent uniquely as long as different > addresses are > used on the outputs. A transaction with the same address appearing twice > would > also have a half-spend problem. Anyone signing the first output and givin= g > that > PSBT to another person can allow them to spend the second input. Therefor= e > one > might even want INPUTINDEX for non-covenant transactions, though making a > tx > with the same address twice seems like a silly idea to me. > I'm confused. Transactions don't have addresses. What are you talking about= ? Input indexes accomplish two goals. One, they eliminate third-party malleability of input order (which would muck with sighash singles too). Two, they prevent half-spend. Signatures today commit to this in the signature hash (the field is nIn, which is confusing because nIn might also look like vin.size()). So the half spend problem doesn't exist today... > > Therefore, assuming a CSV-type mechanism can be devised using sequence_no= , > CTV > is equivalent to a flag in sequence_no that is logically > MUST|ALL|NOSIG|INPUTINDEX and a redeemScript of . > > Lightning-like use cases might put sequence_no flags that are logically > MAY|ALL|NOINPUT. > > The other mechanism for sender policy is scriptPubKey, which is heavily > restricted by isStandard, but might be another place to specify flags lik= e > the > above. > > Thoughts? > > So OP_CAT already lets you do this kind of stuff with the SIGHASHes rather than a new special-purpose verifier. Just pass the signature separately from the flags, and cat them togehther for the checker but just look at the flags for your new thing. Then check that the flags are exactly what you wanted. If you don't want OP_CAT, you can also add OP_SUBSTRVERIFY wherein you verify that a provided substr was inside another string. Then you pass in the witness the full string you want, as well as sub-bits you want to check properties on (like the flags). It's not clear to me that we want this kind of stuff though. OP_CAT requires very careful review because it has very surprising functional consequences across the board. > Does this idea address any of the NOINPUT footguns? (which I'm not up on) > Is there a reason this cannot be done with sequence_no and OP_CSV? > ANYPREVOUT already precludes these by using a separate key type and chaperone signatures. I think a flag for MUST NOT ANYPREVOUT would maybe help with making it safer. But this is a complete sidebar from CTV. This exists already by generating a non-anyprevout capable key though... > Is there a reason that a separate opcode (CTV) is different/better than > this > approach? > > I'll let the email above serve as the answer to your question. I don't think there's anything gained by expressing CTV as a sighash type today, especially since a future soft fork (when we've taking the time to deeply rethink sighash flags, like bitmask sighash flags proposed for elements) can make CTV (as specified today) a valid hash in this new language and use the OP_NOP4 with a non 32-byte argument as the new CheckSig operator anyways. But now I'll pose a different question: why shouldn't we compute the sighash entirely as a type of Bitcoin Script? SIGHASH_FLAGS are essentially a tiny, crappy, language for putting together a message digest. You can think of SIGHASH_FLAGS as being like optimized "jets" for known programs. For custom programs, you can construct the digest pattern you want in script. This is essentially what the bitmask sighash flags proposal is. I think you're going to waste a lot of mental-cycles trying to cram in all this logic into flags. As this stuff gets more complicated, you should just write an actual language for dealing with sighashes and go from there. Now why don't we want this sighash language? Quadratic hashing. If every output commits to some different complex thing, we end up doing a lot of rehashing. Flags are actually kind of bad because a few different flags can trigger a lot of rehashing. But the way flags are *today* is relatively OK because we can cache the important parts so validation is cheap. The more complicated you plan gets, the less context free validation we can do. CTV is fully compatible with context free validation optimizations, trivially. It's not clear if your other stuff is, I suspect not. --000000000000b2563f059da79a3b Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
I think = these ideas shows healthy review of how OP_CTV is specified against alterna= tives, but I think most of the ideas presented are ill advised.

<= /div>

On Sat, Feb 1, 2020 at 2:15 PM Bob McElrath via bitcoin-dev <bitcoin-dev@lists.li= nuxfoundation.org> wrote:
We propose that OP_CHECKTEMPLATEVERIFY should behave more = like CHECKSIG,
including a flags byte that specify what is hashed. This unifies the ways a=
SigHash is computed, differing only in the final checksig which is omitted = in
favor of chacking the hash directly. Having two paths to create a signature= hash
introduces extra complexity, especially as concerns potential future SIGHAS= H
flag upgrades.
<snip>=
I believe the= above may be possible *without* a new opcode and simply with a
sighash flag. That is, consider a flag SIGHASH_NOSIG which behaves as follo= ws:
The stack is expected to contain <hash> <flags>, where the hash= to be checked is
<hash> and is in the place where you'd normally put a pubkey. The= byte <flags>
is the second thing on the stack. This is intended to be an empty "sig= nature"
with the flags byte appended (which must contain SIGHASH_NOSIG to succeed).=

= =C2=A0

I'v= e previously brought this up in IRC http://gnusha.org/bitcoin-wizards/2019-11-28.log =


AFA= IK, using an actual CheckSig SIGHASH Flag as is is a bad idea because then = you need to include an encoding valid signature and pubkey that map onto th= e hash to check. This is not just extra 11 extra bytes of data (33 bytes Pu= bKey + 9 bytes Signature + 2 push -32 bytes - 1 byte push), it's also a= very awkward API. I don't think you can soft-fork around these encodin= g rules. But you're right that it's possible to add this as a SIGHA= SH flag. I don't think doing CTV as a sighash flag is worth considering= further.

I get your point that CTV is kind of a signature hash= , and that we might want to not have a separate path. This ignores, however= , that the current SIGHASH code-path is kind of garbage and literally no on= e likes it and it has been the source of nasty issues previously. Thus I po= sit that a separate path creates less complexity, as we don't need to w= orry about accidentally introducing a weird interaction with other sighash = flags.


=C2=A0
CTV omits inputs as part of its semantics, so CTV-type functionality using<= br> CHECKSIG is also achievable if some form of NOINPUT flag is also deployed. = With
NOINPUT alone, a standard CHECKSIG can be used to implement a covenant -- t= hough
it uses an unnecessarily large number of bytes just to check a 32-byte hash= .
Therefore, any pitfalls CTV intends to evade can be evaded by using a CHECK= SIG,
if NOINPUT is deployed in some form, adding new flexibility.=C2=A0 Beyond w= hat's
possible with NOINPUT/ANYPREVOUT, CTV additionally commits to:

=C2=BB=C2=B7=C2=B7=C2=B7=C2=B7=C2=B7=C2=B7=C2=B71. Number of inputs
=C2=BB=C2=B7=C2=B7=C2=B7=C2=B7=C2=B7=C2=B7=C2=B72. Number of outputs
=C2=BB=C2=B7=C2=B7=C2=B7=C2=B7=C2=B7=C2=B7=C2=B73. Index of input

NOINPUT as s= pecified here https://github.com/ajtowns/bips/blob/bip-anypre= vout/bip-anyprevout.mediawiki (is this the latest?) isn't a great s= urrogate for CTV because CTV commits to the input index which prevents half= -spend. This also encumbers, as proposed, an additional chaperone signature= to fix it to a specific output.
<= br>
This adds a lot of complexity = and space to using CTV. Maybe NOINPUT could make changes to special-case CT= V, but then we're back to CTV again.

=C2=A0

The justification given for committing to the number of inputs and outputs = is
that "it makes CTV hashes easier to compute with script", however= doing so would
require OP_CAT. It's noted that both of these are actually redundant commitments. Since the constexpr requirement was removed, if OP_CAT were enabled, this commitment to the input index could be evaded by computing th= e CTV
hash within the script, modifying the input index using data taken from the=
witness. Therefore committing to the input index is a sender-specified-poli= cy
choice, and not an anti-footgun measure for the redeemer. As such, it's=
appropriate to consider committing to the input index using a flag instead.=

This is incorrect= almost entirely.

1. There is a semantic difference between the= *commitment* being strictly redundant, which has more to do with malleatio= n, and being redundant from a feature perspective. I could maybe do a bette= r job here of expanding what "easier" means here -- there are act= ually some scripts which are quite difficult to write/impossible without th= is. I've described this a couple places outside of the BIP, but essenti= ally it allows you to pin the number of inputs/outputs separately from the = hashes themselves. So if you're trying to build the template in script,= you might want to allow the Sequences to be set to any value, and pass the= m via a hash. But then from a hash you can't check the validity of the = length. An external length commitment lets you do this, but without it you = would have to pass in the sequences directly.
2. The constexpr requirement was implemented in a soft-fork re-= moveable manner specifically so that if we wanted OP_CAT, we could add it w= ithout also introducing constructing CTVs on the stack. Similarly, it would= be possible to specify with OP_CAT as a soft-fork removeable rule that if = OP_CAT executes before an OP_CTV, the script is invalid. The constexpr rule= was removed on the sentiment that if we introduce OP_CAT, we almost surely= intend to introduce it for OP_CTV (or related) use cases.
3. Committing to the input-index is not a *sender= * policy choice. It's a receiver policy choice. I tell a Payer my invoi= ce/address, and they emit a transaction matching it. From an address contai= ning a CTV, I as the receiver set the input_index. I don't see how this= is related to the anti-footgun-ness
4. You write as if OP_CTV + OP_CAT allows the input index to strippe= d *unconditionally*. That's wrong. It's an opt in if you write a sc= ript taking it as a parameter. You can't evade it in general use.
=
5. The "anti-footgun" measure= is that it precludes reused-keys being spent in the same transaction. Were= you to opt out of the mechanism (via OP_CAT input_index), then you opt out= of the reuse protection. (This only matters if there is more than one inpu= t to begin with).
6. Committing to= it via a flag is strictly less flexible, because I can do a lot more with = OP_CAT than with a flag. For instance, I can do <input_index> <min= > <max> OP_WITHIN OP_VERIFY to ensure that it falls within a certa= in range of inputs.
7. A flag is a= lso an extra byte somewhere or uses a sighash bit.
8. Enabling a flag right away enables a big footgun ri= ght off the bat. I think it's bad for use safety.
9. Rather than add flags, if you wanted to add this, I = would suggest reserving max input_index to specify a don't care value. = Then you always check a given CTV against the don't care value and the = specified value. Hashing the don't care value can be done in the PreCom= putedTxData. But I don't think it's worth special casing or making = available today because of 8.

=


There are probably reasons this might not work as a flag that I haven't=
discovered yet. Alternatively CTV might be considered to be an alternative = type
of CHECKSIG operator and might be renamed to CHECKSIGHASH, appending flag b= ytes
to the hash to be checked.

Sure -- happy to go down the renaming path again.= Keep in mind that CTV currently only applies rules when the argument is 32= -bytes. Future soft-forkers are welcome to define a rule for a 33byte 1st a= rgument that treats it as a pubkey and has CHECKSIG semantics, and looks fo= r another argument.

=C2=A0

The flags discussed above, NOINPUT, NOSIG, INPUTINDEX are all really
sender-policy choices, while SIGHASH flags are redeemer-choice as they usua= lly
occur in the witness. There's really no way currently for an output to = specify
that the redeemer must use a particular set of flags. One way to achieve th= is is
to put the CHECKSIG(HASH) including its flags into the redeemScript -- whic= h is
functionally what CTV does (or a CHECKSIG in a redeemScript using NOINPUT).=
This is committed to in outputs and therefore specifies sender policies, ho= wever
the redeemScript is specified by the receiver.=C2=A0 Perhaps an anti-footgu= n measure
would be to require that certain SIGHASH flags like these MUST be committed= to
in the output, by the sender.


I = think this "sender/redeemer" framework is a bit bunk. Ultimately = all redeemers are senders, and you aren't forcing a choice on someone. = You could be on to something though, but I think in general Bitcoin has gon= e the way of opaque addresses so that people can't encumber arbitrary p= olicies on your coins. Maybe it swings the other way...

=C2=A0
CSV (CHECKSEQUENCEVERIFY) is an example that redemption policies are commit= ted
to in the output by the sender via the sequence_no field, and then checked = with
an opcode OP_CSV to enable relative timelocks. It's probably possible t= o add new
flags to the sequence_no field, and check the new semantics with CSV instea= d of
an entiely new opcode.


The sender commits to them, but legally, if y= ou add a contract that I didn't agree to as receipt (e.g., in segwit ad= dress -- which the script is hashed) I won't even know I got paid. So t= he way Bitcoin works today, these are receiver set policies.

On= e way to think of CTV is it's precise the opcode that lets you "wr= ap" someone's known address in arbitrary new scripts. E.g., if you= gave me an address X, but I need to (for whatever reason) add an additiona= l 1 month CSV.

So i just get the txn:

A:
=C2=A0=C2=A0=C2=A0 sequence 1mo
=C2=A0=C2=A0=C2=A0 1 input
=C2=A0=C2=A0=C2=A0 1 output: pay X 1 coin

then take the STH(A), and create B


B:
=C2=A0= =C2=A0=C2=A0 ... inputs
=C2=A0=C2= =A0=C2=A0 1 output pay `STH(A) CTV` 1 coin

I can also add other things, like secondar= y signers/alternatives

`IF {some checksig program} STH(A) CTV ELSE {multisig program} ENDIF

=C2=A0
As user policy choices, NOINPUT might be considered "MAY" conditi= ons. A user MAY
use NOINPUT on an output, but let's not require it.=C2=A0 Covenants on = the other
hand, are a MUST condition. The CTV proposal imposes "MUST" condi= tions on the
existence of the covenant itself, as well as the number of inputs and outpu= ts,
to prevent txid malleability so that such transactions can be used in offli= ne
protocols. Txid non-malleability can be achieved by enforcing that the outp= ut
must be spent using SIGHASH_ALL instead of committing to the number of inpu= ts
separately with a new opcode. The MUST condition also helps with sighash ca= ching
for batch validation.

ANYPREVOUT/ANYSCRIPT are actually weirder than that, bec= ause once it has been used that key is permanently "burned". Henc= e ANYPREVOUT has such pubkeys be explicity tagged as ANYPREVOUT compatible.= So a user kind of has to pre-decide if they want to have ANYPREVOUT semant= ics or not.
And in this case, key-= reuse is relatively unsafe (as you need to track what else you've signe= d) so I think what you're suggesting is not robust.

These &= quot;MUST" conditions sound nice, but they don't actually help wit= h validity caching because we want to be able to compute this information b= efore we've fetched the outputs from the database so we can't know = what to cache yet. Contextless things are things you can precompute not kno= wing input scripts.

=
Again, I don't think this sender/re= deemer framework is super useful but I admire the attempt.

<= div>=C2=A0

INPUTINDEX is required in a CTV/CHECKSIGHASH world because of the half-spen= d
problem. Normally outputs are spent uniquely as long as different addresses= are
used on the outputs. A transaction with the same address appearing twice wo= uld
also have a half-spend problem. Anyone signing the first output and giving = that
PSBT to another person can allow them to spend the second input. Therefore = one
might even want INPUTINDEX for non-covenant transactions, though making a t= x
with the same address twice seems like a silly idea to me.
=

I'm confused. Transa= ctions don't have addresses. What are you talking about?

In= put indexes accomplish two goals.
=
One, they eliminate third-par= ty malleability of input order (which would muck with sighash singles too).=
Two, they prevent half-spend.=

Signatures today commit to this in the signature hash (t= he field is nIn, which is confusing because nIn might also look like vin.si= ze()).

So the half spend problem doesn't exist today...
=

Therefore, assuming a CSV-type mechanism can be devised using sequence_no, = CTV
is equivalent to a flag in sequence_no that is logically
MUST|ALL|NOSIG|INPUTINDEX and a redeemScript of <hash> <flags>.=

Lightning-like use cases might put sequence_no flags that are logically
MAY|ALL|NOINPUT.

The other mechanism for sender policy is scriptPubKey, which is heavily
restricted by isStandard, but might be another place to specify flags like = the
above.

Thoughts?



So OP_CAT already lets you do this kind of stuff with the SIGH= ASHes rather than a new special-purpose verifier. Just pass the signature s= eparately from the flags, and cat them togehther for the checker but just l= ook at the flags for your new thing. Then check that the flags are exactly = what you wanted. If you don't want OP_CAT, you can also add OP_SUBSTRVE= RIFY wherein you verify that a provided substr was inside another string. T= hen you pass in the witness the full string you want, as well as sub-bits y= ou want to check properties on (like the flags).

It's not c= lear to me that we want this kind of stuff though. OP_CAT requires very car= eful review because it has very surprising functional consequences across t= he board.

=C2=A0
Does this idea address any of the NOINPUT footguns? (which I'm not up o= n)
Is there a reason this cannot be done with sequence_no and OP_CSV?

ANYPREVOUT = already precludes these by using a separate key type and chaperone signatur= es.=C2=A0 I think a flag for MUST NOT ANYPREVOUT would maybe help with maki= ng it safer. But this is a complete sidebar from CTV. This exists already b= y generating a non-anyprevout capable key though...

=C2= =A0
Is there a reason that a separate opcode (CTV) is different/better than thi= s
approach?


I'll let the email above serve as the answ= er to your question.

I don't think there's anything gai= ned by expressing CTV as a sighash type today, especially since a future so= ft fork (when we've taking the time to deeply rethink sighash flags, li= ke bitmask sighash flags proposed for elements) can make CTV (as specified = today) a valid hash in this new language and use the OP_NOP4 with a non 32-= byte argument as the new CheckSig operator anyways.


=




But now I'll pose a differen= t question: why shouldn't we compute the sighash entirely as a type of = Bitcoin Script? SIGHASH_FLAGS are essentially a tiny, crappy, language for = putting together a message digest. You can think of SIGHASH_FLAGS as being = like optimized "jets" for known programs. For custom programs, yo= u can construct the digest pattern you want in script. This is essentially = what the bitmask sighash flags proposal is. I think you're going to was= te a lot of mental-cycles trying to cram in all this logic into flags. As t= his stuff gets more complicated, you should just write an actual language f= or dealing with sighashes and go from there.

Now why don't = we want this sighash language? Quadratic hashing. If every output commits t= o some different complex thing, we end up doing a lot of rehashing. Flags a= re actually kind of bad because a few different flags can trigger a lot of = rehashing. But the way flags are *today* is relatively OK because we can ca= che the important parts so validation is cheap.

The more compli= cated you plan gets, the less context free validation we can do.

CTV is fully compatible with context free validation optimizations, trivi= ally. It's not clear if your other stuff is, I suspect not.
--000000000000b2563f059da79a3b--