summaryrefslogtreecommitdiff
path: root/bip-0119.mediawiki
diff options
context:
space:
mode:
authorLuke Dashjr <luke_github1@dashjr.org>2022-07-25 21:15:16 +0000
committerGitHub <noreply@github.com>2022-07-25 21:15:16 +0000
commit43a48ec0bffc0b3f437145c85ef000cb7c737c39 (patch)
tree4de1547245052d46b8f6fdd484ed3b3ddba653db /bip-0119.mediawiki
parent7d309564f9cb00b106237034d124afc6359dbe56 (diff)
parentaa1871b149b96e5d355df4253526231e006d313b (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.mediawiki159
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==