Return-Path: Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id D5C84C0171 for ; Sat, 1 Feb 2020 20:52:08 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id BD87285061 for ; Sat, 1 Feb 2020 20:52:08 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id bcgcAwdUYw8f for ; Sat, 1 Feb 2020 20:52:07 +0000 (UTC) X-Greylist: delayed 00:12:24 by SQLgrey-1.7.6 Received: from mcelrath.org (moya.mcelrath.org [50.31.3.130]) by hemlock.osuosl.org (Postfix) with ESMTPS id 0BAEE84F53 for ; Sat, 1 Feb 2020 20:52:06 +0000 (UTC) Received: from mcelrath.org (localhost [127.0.0.1]) by mcelrath.org (8.14.4/8.14.4/Debian-8+deb8u2) with ESMTP id 011KdgrJ032029 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Sat, 1 Feb 2020 20:39:42 GMT Received: (from mcelrath@localhost) by mcelrath.org (8.14.4/8.14.4/Submit) id 011Kdg85032028 for bitcoin-dev@lists.linuxfoundation.org; Sat, 1 Feb 2020 20:39:42 GMT X-Authentication-Warning: mcelrath.org: mcelrath set sender to bob@mcelrath.org using -f Date: Sat, 1 Feb 2020 20:39:42 +0000 From: Bob McElrath To: Bitcoin Protocol Discussion Message-ID: <20200201203941.GE28549@mcelrath.org> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit User-Agent: Mutt/1.5.23 (2014-03-12) X-Mailman-Approved-At: Sat, 01 Feb 2020 22:12:27 +0000 Subject: [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: Sat, 01 Feb 2020 20:52:09 -0000 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 SIGHASH flag upgrades. CTV omits inputs as part of its semantics, so CTV-type functionality using 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: »·······1. Number of inputs »·······2. Number of outputs »·······3. Index of input 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 the 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-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 instead. 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 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). 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 bytes to the hash to be checked. 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. CSV (CHECKSEQUENCEVERIFY) is an example that redemption policies are committed 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 to add new flags to the sequence_no field, and check the new semantics with CSV instead of an entiely new opcode. 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 other 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. 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 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 tx with the same address twice seems like a silly idea to me. 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 like the above. Thoughts? 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? Is there a reason that a separate opcode (CTV) is different/better than this approach? -- Cheers, Bob McElrath "For every complex problem, there is a solution that is simple, neat, and wrong." -- H. L. Mencken