1
0
Fork 0
mirror of https://github.com/bitcoin/bips.git synced 2025-02-23 23:27:22 +01:00

Merge pull request #1319 from JeremyRubin/119-syntax

[BIP-119] Use mediawiki syntax highlighting, add comment to spec
This commit is contained in:
Luke Dashjr 2022-07-25 21:15:16 +00:00 committed by GitHub
commit 43a48ec0bf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -66,31 +66,40 @@ OP_CHECKTEMPLATEVERIFY as implemented in C++ in the context of Bitcoin Core can
be seen in the reference implementation. be seen in the reference implementation.
The execution of the opcode is as follows: The execution of the opcode is as follows:
def execute_bip_119(self): <source lang="python">
# Before soft-fork activation / failed activation def execute_bip_119(self):
if not self.flags.script_verify_default_check_template_verify_hash: # Before soft-fork activation / failed activation
# Potentially set for node-local policy to discourage premature use # continue to treat as NOP4
if self.flags.script_verify_discourage_upgradable_nops: if not self.flags.script_verify_default_check_template_verify_hash:
return self.errors_with(errors.script_err_discourage_upgradable_nops) # Potentially set for node-local policy to discourage premature use
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 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: if self.flags.script_verify_discourage_upgradable_nops:
return self.errors_with(errors.script_err_discourage_upgradable_nops) return self.errors_with(errors.script_err_discourage_upgradable_nops)
else: return self.return_as_nop()
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 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, is the transaction type). Care must be taken that in any validation context,
@ -101,46 +110,80 @@ including hashes of the scriptsigs, sequences, and outputs. See the section
"Denial of Service and Validation Costs" below. This is not a performance "Denial of Service and Validation Costs" below. This is not a performance
optimization. optimization.
def get_default_check_template_precomputed_data(self): <source lang="python">
result = {}
# If there are no scriptSigs we do not need to precompute a hash
if any(inp.scriptSig for inp in self.vin):
result["scriptSigs"] = sha256(b"".join(ser_string(inp.scriptSig) for inp in self.vin))
# The same value is also pre-computed for and defined in BIP-341 and can be shared
result["sequences"] = sha256(b"".join(struct.pack("<I", inp.nSequence) for inp in self.vin))
# The same value is also pre-computed for and defined in BIP-341 and can be shared
result["outputs"] = sha256(b"".join(out.serialize() for out in self.vout))
return result
# parameter precomputed must be passed in for DoS resistance def ser_compact_size(l):
def get_default_check_template_hash(self, nIn, precomputed = None): r = b""
if precomputed == None: if l < 253:
precomputed = self.get_default_check_template_precomputed_data() # 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"" r = b""
# pack as 4 byte signed integer # serialize as signed 8 byte integer (little endian)
r += struct.pack("<i", self.nVersion) r += struct.pack("<q", self.nValue)
# pack as 4 byte unsigned integer r += ser_string(self.scriptPubKey)
r += struct.pack("<I", self.nLockTime) return r
# we do not include the hash in the case where there is no
# scriptSigs def get_default_check_template_precomputed_data(self):
if "scriptSigs" in precomputed: result = {}
r += precomputed["scriptSigs"] # If there are no scriptSigs we do not need to precompute a hash
# pack as 4 byte unsigned integer if any(inp.scriptSig for inp in self.vin):
r += struct.pack("<I", len(self.vin)) result["scriptSigs"] = sha256(b"".join(ser_string(inp.scriptSig) for inp in self.vin))
r += precomputed["sequences"] # The same value is also pre-computed for and defined in BIP-341 and can be shared.
# pack as 4 byte unsigned integer # each nSequence is packed as 4 byte unsigned integer (little endian)
r += struct.pack("<I", len(self.vout)) result["sequences"] = sha256(b"".join(struct.pack("<I", inp.nSequence) for inp in self.vin))
r += precomputed["outputs"] # The same value is also pre-computed for and defined in BIP-341 and can be shared
# pack as 4 byte unsigned integer # See class CTxOut above for details.
r += struct.pack("<I", nIn) result["outputs"] = sha256(b"".join(out.serialize() for out in self.vout))
return sha256(r) return result
# parameter precomputed must be passed in for DoS resistance
def get_default_check_template_hash(self, nIn, precomputed = None):
if precomputed == None:
precomputed = self.get_default_check_template_precomputed_data()
r = b""
# Serialize as 4 byte signed integer (little endian)
r += struct.pack("<i", self.nVersion)
# Serialize as 4 byte unsigned integer (little endian)
r += struct.pack("<I", self.nLockTime)
# we do not include the hash in the case where there is no
# scriptSigs
if "scriptSigs" in precomputed:
r += precomputed["scriptSigs"]
# Serialize as 4 byte unsigned integer (little endian)
r += struct.pack("<I", len(self.vin))
r += precomputed["sequences"]
# Serialize as 4 byte unsigned integer (little endian)
r += struct.pack("<I", len(self.vout))
r += precomputed["outputs"]
# Serialize as 4 byte unsigned integer (little endian)
r += struct.pack("<I", nIn)
return sha256(r)
</source>
A PayToBareDefaultCheckTemplateVerifyHash output matches the following template: A PayToBareDefaultCheckTemplateVerifyHash output matches the following template:
# Extra-fast test for pay-to-basic-standard-template CScripts: <source lang="python">
def is_pay_to_bare_default_check_template_verify_hash(self): # Extra-fast test for pay-to-basic-standard-template CScripts:
return len(self) == 34 and self[0] == 0x20 and self[-1] == OP_CHECKTEMPLATEVERIFY def is_pay_to_bare_default_check_template_verify_hash(self):
return len(self) == 34 and self[0] == 0x20 and self[-1] == OP_CHECKTEMPLATEVERIFY
</source>
==Deployment== ==Deployment==