mirror of
https://github.com/bitcoin/bips.git
synced 2026-02-09 15:23:09 +00:00
Created _Footer (markdown)
parent
b33c3b92e1
commit
8aa07ad6fb
129
_Footer.md
Normal file
129
_Footer.md
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
##
|
||||||
|
**`<pre>
|
||||||
|
BIP: 119
|
||||||
|
Layer: Consensus (soft fork)
|
||||||
|
Title: CHECKTEMPLATEVERIFY
|
||||||
|
Author: Jeremy Rubin <j@rubin.io>
|
||||||
|
Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0119
|
||||||
|
Status: Draft
|
||||||
|
Type: Standards Track
|
||||||
|
Created: 2020-01-06
|
||||||
|
License: BSD-3-Clause
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
==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:
|
||||||
|
<source lang="python">
|
||||||
|
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()
|
||||||
|
</source>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
<source lang="python">
|
||||||
|
|
||||||
|
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("<BH", 253, l)
|
||||||
|
elif l < 0x100000000:
|
||||||
|
# Serialize as unsigned char 254 followed by unsigned 4 byte integer (little endian)
|
||||||
|
r = struct.pack("<BI", 254, l)
|
||||||
|
else:
|
||||||
|
# Serialize as unsigned char 255 followed by unsigned 8 byte integer (little endian)
|
||||||
|
r = struct.pack("<BQ", 255, l)
|
||||||
|
return r
|
||||||
|
|
||||||
|
def ser_string(s):
|
||||||
|
return ser_compact_size(len(s)) + s
|
||||||
|
|
||||||
|
class CTxOut:
|
||||||
|
def serialize(self):
|
||||||
|
r = b""
|
||||||
|
# serialize as signed 8 byte integer (little endian)
|
||||||
|
r += struct.pack("<q", self.nValue)
|
||||||
|
r += ser_string(self.scriptPubKey)
|
||||||
|
return r
|
||||||
|
|
||||||
|
def get_default_check_template_precomputed_data(self):
|
||||||
|
result = {}
|
||||||
|
# If there are no s`**
|
||||||
Loading…
x
Reference in New Issue
Block a user