|
| 1 | +<pre> |
| 2 | + BIP: tbd |
| 3 | + Layer: Consensus (soft fork) |
| 4 | + Title: OP_TXHASH and OP_CHECKTXHASHVERIFY |
| 5 | + Author: Steven Roose < [email protected]> |
| 6 | + Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-tbd |
| 7 | + Status: Draft |
| 8 | + Type: Standards Track |
| 9 | + Created: 2023-09-03 |
| 10 | + License: BSD-3-Clause |
| 11 | +</pre> |
| 12 | + |
| 13 | +==Abstract== |
| 14 | + |
| 15 | +This BIP proposes two new opcodes, OP_CHECKTXHASHVERIFY, to be activated |
| 16 | +as a change to the semantics of OP_NOP4 in legacy script, segwit and tapscript; |
| 17 | +and OP_TXHASH, to be activated as a change to the semantics of OP_SUCCESS189 |
| 18 | +in tapscript only. |
| 19 | + |
| 20 | +These opcodes provide a generalized method for introspecting certain details of |
| 21 | +the spending transaction, which enables non-interactive enforcement of certain |
| 22 | +properties of the transaction spending a certain UTXO. |
| 23 | + |
| 24 | +The constructions specified in this BIP also open up the way for other |
| 25 | +potential updates; see Motivation section for more details. |
| 26 | + |
| 27 | + |
| 28 | +==Summary== |
| 29 | + |
| 30 | +OP_CHECKTXHASHVERIFY uses opcode OP_NOP4 (0xb3) as a soft fork upgrade. |
| 31 | + |
| 32 | +OP_CHECKTXHASHVERIFY does the following: |
| 33 | + |
| 34 | +* There is at least one element on the stack, fail otherwise. |
| 35 | +* The element on the stack is at least 32 bytes long, fail otherwise. |
| 36 | +* The first 32 bytes are interpreted as the TxHash and the remaining suffix |
| 37 | + bytes specify the TxFieldSelector. |
| 38 | +* If the TxFieldSelector is invalid, fail. |
| 39 | +* The actual TxHash of the transaction at the current input index, calculated |
| 40 | + using the given TxFieldSelector must be equal to the first 32 bytes of the |
| 41 | + element on the stack, fail otherwise. |
| 42 | +
|
| 43 | + |
| 44 | +OP_TXHASH uses tapscript opcode OP_SUCCESS189 (0xbd) as a soft fork upgrade. |
| 45 | + |
| 46 | +OP_TXHASH does the following: |
| 47 | + |
| 48 | +* There is at least one element on the stack, fail otherwise. |
| 49 | +* The element is interpreted as the TxFieldSelector and is popped off the stack. |
| 50 | +* If the TxFieldSelector is invalid, fail. |
| 51 | +* The 32-byte TxHash of the transaction at the current input index, |
| 52 | + calculated using the given TxFieldSelector is pushed onto the stack. |
| 53 | +
|
| 54 | + |
| 55 | +The TxFieldSelector has the following semantics. We will give a brief conceptual |
| 56 | +summary, followed by a reference implementation of the CalculateTxHash function. |
| 57 | + |
| 58 | +* There are two special cases for the TxFieldSelector: |
| 59 | + - the empty value, zero bytes long: it is set equal to 0xff|0xf6|0xbf|0xbf, |
| 60 | + the de-facto default value which means everything except the prevouts and |
| 61 | + the prevout scriptPubkeys. |
| 62 | + - the 0x00 byte: it is set equal to 0xff|0xff|0xbf|0xbf, which means "ALL" |
| 63 | + and is primarily useful to emulate SIGHASH_ALL when OP_TXHASH is used in |
| 64 | + combination with OP_CHECKSIGFROMSTACK. |
| 65 | +
|
| 66 | +* The first byte of the TxFieldSelector has its 8 bits assigned as follows, |
| 67 | + from lowest to highest: |
| 68 | + 1. version |
| 69 | + 2. locktime |
| 70 | + 3. current input index |
| 71 | + 4. current input control block (or empty) |
| 72 | + 5. current script last OP_CODESEPARATOR position (or 0xffffffff) |
| 73 | + 6. inputs |
| 74 | + 7. outputs |
| 75 | +
|
| 76 | +* The last (highest) bit of the first byte, we will call the "control bit", and |
| 77 | + it can be used to control the behavior of the opcode. For OP_TXHASH and |
| 78 | + OP_CHECKTXHASHVERIFY, the control bit is used to determine whether the |
| 79 | + TxFieldSelector itself has to be included in the resulting hash. (For |
| 80 | + potential other uses of the TxFieldSelector (like a hypothetical OP_TX), this |
| 81 | + bit can be repurposed.) |
| 82 | +
|
| 83 | +* If either "inputs" or "outputs" is set to 1, expect another byte with its 8 |
| 84 | + bits assigning the following variables, from lowest to highest: |
| 85 | + * Specifying which fields of the inputs will be selected: |
| 86 | + 1. prevouts |
| 87 | + 2. sequences |
| 88 | + 3. scriptSigs |
| 89 | + 4. prevout scriptPubkeys |
| 90 | + 5. prevout values |
| 91 | + 6. taproot annexes |
| 92 | + * Specifying which fields of the outputs will be selected: |
| 93 | + 7. scriptPubkeys |
| 94 | + 8. values |
| 95 | +
|
| 96 | +For both inputs and then outputs, do the following: |
| 97 | + |
| 98 | +* If the "in/outputs" field is set to 1, another additional byte is expected: |
| 99 | + * The highest bit indicates whether the "number of in-/outputs" should be |
| 100 | + committed to. |
| 101 | + * For the remaining bits, there are three exceptional values: |
| 102 | + - 0x00 means "no in/outputs" (hence only the number of them as 0x80). |
| 103 | + - 0x40 means "select only the in/output of the current input index" |
| 104 | + (it is invalid when current index exceeds number of outputs). |
| 105 | + - 0x3f means "select all in/outputs". |
| 106 | + * The second highest bit is the "specification mode": |
| 107 | + - Set to 0 it means "leading mode". |
| 108 | + - Set to 1 it means "individual mode". |
| 109 | + * The third highest bit is used to indicate the "index size", i.e. the number |
| 110 | + of bytes will be used to represent in/output indices. |
| 111 | + * In "leading mode", |
| 112 | + - With "index size" set to 0, the remaining lowest 5 bits of the first byte |
| 113 | + will be interpreted as the number of leading in/outputs to select. |
| 114 | + - With "index size" set to 1, the remaining lowest 5 bits of the first byte |
| 115 | + together with the 8 bits of the next byte will be interpreted as the |
| 116 | + number of leading in/outputs to select. |
| 117 | + * In "individual mode", the remaining lowest 5 bits of the first byte will be |
| 118 | + interpreted as `n`, the number of individual in/outputs to select. |
| 119 | + - With "index size" set to 0, interpret the following `n` individual bytes |
| 120 | + as the indices of an individual in/outputs to select. |
| 121 | + - With "index size" set to 1, interpret the next `n` pairs of two bytes as |
| 122 | + the indices of individual in/outputs to select. |
| 123 | +
|
| 124 | +Effectively, this allows a user to select |
| 125 | +- all in/outputs |
| 126 | +- the current input index |
| 127 | +- the leading in/outputs up to 8192 |
| 128 | +- up to 32 individually selected in/outputs |
| 129 | + |
| 130 | +The TxFieldSelector is invalid when |
| 131 | +- a byte is expected but missing |
| 132 | +- additional unexpected bytes are present |
| 133 | +- index size is set to 1 while not being necessary |
| 134 | +- a leading number of individual index is selected out of bounds of the in/outputs |
| 135 | +- individual indices are duplicated or not in increasing order |
| 136 | + |
| 137 | +These limitations are to avoid potential TxFieldSelector malleability. It is |
| 138 | +however allowed to use leading mode where it could be "all". This |
| 139 | +is important to allow for optional addition of extra inputs or outputs. |
| 140 | +//TODO(stevenroose) should we disallow individual that could be leading? |
| 141 | + |
| 142 | + |
| 143 | +===Resource limits=== |
| 144 | + |
| 145 | +* For legacy scripts and segwit, we don't add any extra resource limitations, |
| 146 | + with the argumentation that OP_CHECKTXHASHVERIFY already requires the user to |
| 147 | + provide at least 32 bytes of extra transaction size, either in the input |
| 148 | + scriptSig, or the witness. Additional more complex hashes require additional |
| 149 | + witness bytes. Given that OP_CAT is not available in this context, if a |
| 150 | + malicious user tries to increase the number of TransactionHashes being |
| 151 | + calculated by using opcodes like OP_DUP, the TxFieldSelector for all these |
| 152 | + calculations is identical, so the calculation can be cached within the same |
| 153 | + transaction. |
| 154 | +
|
| 155 | +* For tapscript, primarily motivated by the cheaper opcode OP_TXHASH (it |
| 156 | + doesn't require an additional 32 witness bytes be provided) and the potential |
| 157 | + future addition of byte manipulation opcodes like OP_CAT, an additional cost |
| 158 | + is specified per TransactionHash execution. |
| 159 | + Using the same validation budget ("sigops budget") introduced in BIP-0342, |
| 160 | + each TransactionHash decreases the validation budget by 10. |
| 161 | + If this brings the budget below zero, the script fails immediately. |
| 162 | +
|
| 163 | + The following considerations should be made: |
| 164 | +
|
| 165 | + * All fields that can be of arbitrary size are cachable as TransactionHash |
| 166 | + always hashes their hashed values. |
| 167 | + * In "individual mode", a user can at most commit 32 inputs or outputs, which we |
| 168 | + don't consider excessive for potential repeated use. |
| 169 | + * In "prefix mode", a caching strategy can be used where the SHA256 context is |
| 170 | + stored every N in/outputs so that multiple executions of the TransactionHash |
| 171 | + function can use the caches and only have to hash an additional N-1 items at |
| 172 | + most. |
| 173 | +
|
| 174 | + |
| 175 | +==Motivation== |
| 176 | + |
| 177 | +This BIP specifies a basic transaction introspection primitive that is useful |
| 178 | +to either reduce interactivity in multi-user protocols or to enforce some basic |
| 179 | +constraints on transactions. |
| 180 | + |
| 181 | +Additionally, the constructions specified in this BIP can lay the groundwork for |
| 182 | +some potential future upgrades: |
| 183 | +* The TxFieldSelector construction would work well with a hypothetical opcode |
| 184 | + OP_TX that allows for directly introspecting the transaction by putting the |
| 185 | + fields selected on the stack instead of hashing them together. |
| 186 | +* The TransactionHash obtained by OP_TXHASH can be combined with a hypothetical |
| 187 | + opcode OP_CHECKSIGFROMSTACK to effectively create an incredibly flexible |
| 188 | + signature hash, which would enable constructions like SIGHASH_ANYPREVOUT. |
| 189 | +
|
| 190 | +===Comparing with some alternative proposals=== |
| 191 | + |
| 192 | +* This proposal strictly generalizes BIP-119's OP_CHECKTEMPLATEVERIFY, as the |
| 193 | + default mode of our TxFieldSelector is effectively the same (though not |
| 194 | + byte-for-byte identical) as what OP_CTV acomplishes, without costing any |
| 195 | + additional bytes. Additionally, using OP_CHECKTXHASHVERIFY allows for more |
| 196 | + flexibility which can help in the case for |
| 197 | + * enabling adding fees to a transaction without breaking a multi-tx protocol; |
| 198 | + * multi-user protocols where users are only concerned about their own inputs |
| 199 | + and outputs. |
| 200 | +
|
| 201 | +* Constructions like OP_IN_OUT_VALUE used with OP_EQUALVERIFY can be emulated by |
| 202 | + two OP_TXHASH instances by using the TxFieldSelector to select a single input |
| 203 | + value first and a single output value second and enforcing equality on the |
| 204 | + hashes. Neither of these alternatives can be used to enforce small value |
| 205 | + differencials without the use of 64-bit arithmetic. |
| 206 | +
|
| 207 | +* Like mentioned above, SIGHASH_ANYPREVOUT can be emulated using OP_TXHASH when |
| 208 | + combined with OP_CHECKSIGFROMSTACK: |
| 209 | + `<txfs> OP_TXHASH <pubkey> OP_CHECKSIGFROMSTACK` effectively emulates |
| 210 | + SIGHASH_ANYPREVOUT. |
| 211 | +
|
| 212 | + |
| 213 | + |
| 214 | + |
| 215 | +==Detailed Specification== |
| 216 | + |
| 217 | +A reference implementation in Rust is provided attached as part of this BIP |
| 218 | +together with a JSON file of test vectors generated using the reference |
| 219 | +implementation. |
| 220 | + |
| 221 | + |
| 222 | +==Acknowledgement== |
| 223 | + |
| 224 | +Credit for this proposal mostly goes to Jeremy Rubin for his work on BIP-119's |
| 225 | +OP_CHECKTEMPLATEVERIFY and to Russell O'Connor for the original idea of |
| 226 | +generalizing CTV into OP_TXHASH. |
| 227 | + |
| 228 | +Additional thanks to Andrew Poelstra, Greg Sanders, Rearden Code, Rusty Russell |
| 229 | +and others for their feedback on the specification. |
| 230 | + |
0 commit comments