diff options
author | Luke Dashjr <luke_github1@dashjr.org> | 2022-07-25 21:15:16 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-25 21:15:16 +0000 |
commit | 43a48ec0bffc0b3f437145c85ef000cb7c737c39 (patch) | |
tree | 4de1547245052d46b8f6fdd484ed3b3ddba653db /bip-0119.mediawiki | |
parent | 7d309564f9cb00b106237034d124afc6359dbe56 (diff) | |
parent | aa1871b149b96e5d355df4253526231e006d313b (diff) |
Merge pull request #1319 from JeremyRubin/119-syntax
[BIP-119] Use mediawiki syntax highlighting, add comment to spec
Diffstat (limited to 'bip-0119.mediawiki')
-rw-r--r-- | bip-0119.mediawiki | 159 |
1 files changed, 101 insertions, 58 deletions
diff --git a/bip-0119.mediawiki b/bip-0119.mediawiki index 552e1f0..aa226d0 100644 --- a/bip-0119.mediawiki +++ b/bip-0119.mediawiki @@ -66,31 +66,40 @@ 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 - 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 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 +<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) - 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 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 optimization. - def get_default_check_template_precomputed_data(self): - 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 get_default_check_template_hash(self, nIn, precomputed = None): - if precomputed == None: - precomputed = self.get_default_check_template_precomputed_data() +<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"" - # pack as 4 byte signed integer - r += struct.pack("<i", self.nVersion) - # pack as 4 byte unsigned integer - 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"] - # pack as 4 byte unsigned integer - r += struct.pack("<I", len(self.vin)) - r += precomputed["sequences"] - # pack as 4 byte unsigned integer - r += struct.pack("<I", len(self.vout)) - r += precomputed["outputs"] - # pack as 4 byte unsigned integer - r += struct.pack("<I", nIn) - return sha256(r) + # 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 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. + # each nSequence is packed as 4 byte unsigned integer (little endian) + 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 + # See class CTxOut above for details. + result["outputs"] = sha256(b"".join(out.serialize() for out in self.vout)) + 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: - # Extra-fast test for pay-to-basic-standard-template CScripts: - 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 lang="python"> +# Extra-fast test for pay-to-basic-standard-template CScripts: +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== |