diff --git a/_Footer.md b/_Footer.md new file mode 100644 index 0000000..db8fbb5 --- /dev/null +++ b/_Footer.md @@ -0,0 +1,129 @@ +## +**`
+  BIP: 119
+  Layer: Consensus (soft fork)
+  Title: CHECKTEMPLATEVERIFY
+  Author: Jeremy Rubin 
+  Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0119
+  Status: Draft
+  Type: Standards Track
+  Created: 2020-01-06
+  License: BSD-3-Clause
+
+ +==Abstract== + +This BIP proposes a new opcode, OP_CHECKTEMPLATEVERIFY, to be activated +as a change to the semantics of OP_NOP4. + +==Summary== + +OP_CHECKTEMPLATEVERIFY uses opcode OP_NOP4 (0xb3) as a soft fork upgrade. + +OP_CHECKTEMPLATEVERIFY does the following: + +* There is at least one element on the stack, fail otherwise +* The element on the stack is 32 bytes long, NOP otherwise +* The DefaultCheckTemplateVerifyHash of the transaction at the current input index is equal to the element on the stack, fail otherwise + +The DefaultCheckTemplateVerifyHash commits to the serialized version, locktime, scriptSigs hash (if any +non-null scriptSigs), number of inputs, sequences hash, number of outputs, outputs hash, and +currently executing input index. + +The recommended standardness rules additionally: + +* Reject non-32 byte as SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS. + +==Motivation== + +This BIP introduces a transaction template, a simple spending restriction that +pattern matches a transaction against a hashed transaction specification. +OP_CHECKTEMPLATEVERIFY reduces many of the trust, interactivity, and storage +requirements inherent with the use of pre-signing in applications. +For more details on applications, please see the references. + + +==Detailed Specification== + +The below code is the main logic for verifying CHECKTEMPLATEVERIFY, described +in pythonic pseudocode. The canonical specification for the semantics of +OP_CHECKTEMPLATEVERIFY as implemented in C++ in the context of Bitcoin Core can +be seen in the reference implementation. + +The execution of the opcode is as follows: + +def execute_bip_119(self): + # Before soft-fork activation / failed activation + # continue to treat as NOP4 + if not self.flags.script_verify_default_check_template_verify_hash: + # Potentially set for node-local policy to discourage premature use + if self.flags.script_verify_discourage_upgradable_nops: + return self.errors_with(errors.script_err_discourage_upgradable_nops) + return self.return_as_nop() + + # CTV always requires at least one stack argument + if len(self.stack) < 1: + return self.errors_with(errors.script_err_invalid_stack_operation) + + # CTV only verifies the hash against a 32 byte argument + if len(self.stack[-1]) == 32: + # Ensure the precomputed data required for anti-DoS is available, + # or cache it on first use + if self.context.precomputed_ctv_data == None: + self.context.precomputed_ctv_data = self.context.tx.get_default_check_template_precomputed_data() + + # If the hashes do not match, return error + if stack[-1] != self.context.tx.get_default_check_template_hash(self.context.nIn, self.context.precomputed_ctv_data): + return self.errors_with(errors.script_err_template_mismatch) + + return self.return_as_nop() + + # future upgrade can add semantics for this opcode with different length args + # so discourage use when applicable + if self.flags.script_verify_discourage_upgradable_nops: + return self.errors_with(errors.script_err_discourage_upgradable_nops) + else: + return self.return_as_nop() + + +The computation of this hash can be implemented as specified below (where self +is the transaction type). Care must be taken that in any validation context, +the precomputed data must be initialized to prevent Denial-of-Service attacks. +Any implementation *must* cache these parts of the hash computation to avoid +quadratic hashing DoS. All variable length computations must be precomputed +including hashes of the scriptsigs, sequences, and outputs. See the section +"Denial of Service and Validation Costs" below. This is not a performance +optimization. + + + +def ser_compact_size(l): + r = b"" + if l < 253: + # Serialize as unsigned char + r = struct.pack("B", l) + elif l < 0x10000: + # Serialize as unsigned char 253 followed by unsigned 2 byte integer (little endian) + r = struct.pack("