@@ -66,31 +66,40 @@ OP_CHECKTEMPLATEVERIFY as implemented in C++ in the context of Bitcoin Core can
6666be seen in the reference implementation.
6767
6868The execution of the opcode is as follows:
69- def execute_bip_119(self):
70- # Before soft-fork activation / failed activation
71- if not self.flags.script_verify_default_check_template_verify_hash:
72- # Potentially set for node-local policy to discourage premature use
73- if self.flags.script_verify_discourage_upgradable_nops:
74- return self.errors_with(errors.script_err_discourage_upgradable_nops)
75- return self.return_as_nop()
76- # CTV always requires at least one stack argument
77- if len(self.stack) < 1:
78- return self.errors_with(errors.script_err_invalid_stack_operation)
79- # CTV only verifies the hash against a 32 byte argument
80- if len(self.stack[-1]) == 32:
81- # Ensure the precomputed data required for anti-DoS is available,
82- # or cache it on first use
83- if self.context.precomputed_ctv_data == None:
84- self.context.precomputed_ctv_data = self.context.tx.get_default_check_template_precomputed_data()
85- if stack[-1] != self.context.tx.get_default_check_template_hash(self.context.nIn, self.context.precomputed_ctv_data)
86- return self.errors_with(errors.script_err_template_mismatch)
87- return self.return_as_nop()
88- # future upgrade can add semantics for this opcode with different length args
89- # so discourage use when applicable
69+ <source lang="python">
70+ def execute_bip_119(self):
71+ # Before soft-fork activation / failed activation
72+ # continue to treat as NOP4
73+ if not self.flags.script_verify_default_check_template_verify_hash:
74+ # Potentially set for node-local policy to discourage premature use
9075 if self.flags.script_verify_discourage_upgradable_nops:
9176 return self.errors_with(errors.script_err_discourage_upgradable_nops)
92- else:
93- return self.return_as_nop()
77+ return self.return_as_nop()
78+
79+ # CTV always requires at least one stack argument
80+ if len(self.stack) < 1:
81+ return self.errors_with(errors.script_err_invalid_stack_operation)
82+
83+ # CTV only verifies the hash against a 32 byte argument
84+ if len(self.stack[-1]) == 32:
85+ # Ensure the precomputed data required for anti-DoS is available,
86+ # or cache it on first use
87+ if self.context.precomputed_ctv_data == None:
88+ self.context.precomputed_ctv_data = self.context.tx.get_default_check_template_precomputed_data()
89+
90+ # If the hashes do not match, return error
91+ if stack[-1] != self.context.tx.get_default_check_template_hash(self.context.nIn, self.context.precomputed_ctv_data)
92+ return self.errors_with(errors.script_err_template_mismatch)
93+
94+ return self.return_as_nop()
95+
96+ # future upgrade can add semantics for this opcode with different length args
97+ # so discourage use when applicable
98+ if self.flags.script_verify_discourage_upgradable_nops:
99+ return self.errors_with(errors.script_err_discourage_upgradable_nops)
100+ else:
101+ return self.return_as_nop()
102+ </source>
94103
95104The computation of this hash can be implemented as specified below (where self
96105is 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
101110"Denial of Service and Validation Costs" below. This is not a performance
102111optimization.
103112
104- def get_default_check_template_precomputed_data(self):
105- result = {}
106- # If there are no scriptSigs we do not need to precompute a hash
107- if any(inp.scriptSig for inp in self.vin):
108- result["scriptSigs"] = sha256(b"".join(ser_string(inp.scriptSig) for inp in self.vin))
109- # The same value is also pre-computed for and defined in BIP-341 and can be shared
110- result["sequences"] = sha256(b"".join(struct.pack("<I", inp.nSequence) for inp in self.vin))
111- # The same value is also pre-computed for and defined in BIP-341 and can be shared
112- result["outputs"] = sha256(b"".join(out.serialize() for out in self.vout))
113- return result
114-
115- # parameter precomputed must be passed in for DoS resistance
116- def get_default_check_template_hash(self, nIn, precomputed = None):
117- if precomputed == None:
118- precomputed = self.get_default_check_template_precomputed_data()
113+ <source lang ="python" >
114+
115+ def ser_compact_size(l):
116+ r = b""
117+ if l < 253:
118+ # Serialize as unsigned char
119+ r = struct.pack("B", l)
120+ elif l < 0x10000:
121+ # Serialize as unsigned char 253 followed by unsigned 2 byte integer (little endian)
122+ r = struct.pack("<BH", 253, l)
123+ elif l < 0x100000000:
124+ # Serialize as unsigned char 254 followed by unsigned 4 byte integer (little endian)
125+ r = struct.pack("<BI", 254, l)
126+ else:
127+ # Serialize as unsigned char 255 followed by unsigned 8 byte integer (little endian)
128+ r = struct.pack("<BQ", 255, l)
129+ return r
130+
131+ def ser_string(s):
132+ return ser_compact_size(len(s)) + s
133+
134+ class CTxOut:
135+ def serialize(self):
119136 r = b""
120- # pack as 4 byte signed integer
121- r += struct.pack("<i", self.nVersion)
122- # pack as 4 byte unsigned integer
123- r += struct.pack("<I", self.nLockTime)
124- # we do not include the hash in the case where there is no
125- # scriptSigs
126- if "scriptSigs" in precomputed:
127- r += precomputed["scriptSigs"]
128- # pack as 4 byte unsigned integer
129- r += struct.pack("<I", len(self.vin))
130- r += precomputed["sequences"]
131- # pack as 4 byte unsigned integer
132- r += struct.pack("<I", len(self.vout))
133- r += precomputed["outputs"]
134- # pack as 4 byte unsigned integer
135- r += struct.pack("<I", nIn)
136- return sha256(r)
137+ # serialize as signed 8 byte integer (little endian)
138+ r += struct.pack("<q", self.nValue)
139+ r += ser_string(self.scriptPubKey)
140+ return r
141+
142+ def get_default_check_template_precomputed_data(self):
143+ result = {}
144+ # If there are no scriptSigs we do not need to precompute a hash
145+ if any(inp.scriptSig for inp in self.vin):
146+ result["scriptSigs"] = sha256(b"".join(ser_string(inp.scriptSig) for inp in self.vin))
147+ # The same value is also pre-computed for and defined in BIP-341 and can be shared.
148+ # each nSequence is packed as 4 byte unsigned integer (little endian)
149+ result["sequences"] = sha256(b"".join(struct.pack("<I", inp.nSequence) for inp in self.vin))
150+ # The same value is also pre-computed for and defined in BIP-341 and can be shared
151+ # See class CTxOut above for details.
152+ result["outputs"] = sha256(b"".join(out.serialize() for out in self.vout))
153+ return result
154+
155+ # parameter precomputed must be passed in for DoS resistance
156+ def get_default_check_template_hash(self, nIn, precomputed = None):
157+ if precomputed == None:
158+ precomputed = self.get_default_check_template_precomputed_data()
159+ r = b""
160+ # Serialize as 4 byte signed integer (little endian)
161+ r += struct.pack("<i", self.nVersion)
162+ # Serialize as 4 byte unsigned integer (little endian)
163+ r += struct.pack("<I", self.nLockTime)
164+ # we do not include the hash in the case where there is no
165+ # scriptSigs
166+ if "scriptSigs" in precomputed:
167+ r += precomputed["scriptSigs"]
168+ # Serialize as 4 byte unsigned integer (little endian)
169+ r += struct.pack("<I", len(self.vin))
170+ r += precomputed["sequences"]
171+ # Serialize as 4 byte unsigned integer (little endian)
172+ r += struct.pack("<I", len(self.vout))
173+ r += precomputed["outputs"]
174+ # Serialize as 4 byte unsigned integer (little endian)
175+ r += struct.pack("<I", nIn)
176+ return sha256(r)
177+ </source >
137178
138179
139180A PayToBareDefaultCheckTemplateVerifyHash output matches the following template:
140181
141- # Extra-fast test for pay-to-basic-standard-template CScripts:
142- def is_pay_to_bare_default_check_template_verify_hash(self):
143- return len(self) == 34 and self[0] == 0x20 and self[-1 ] == OP_CHECKTEMPLATEVERIFY
182+ <source lang ="python" >
183+ # Extra-fast test for pay-to-basic-standard-template CScripts:
184+ def is_pay_to_bare_default_check_template_verify_hash(self):
185+ return len(self) == 34 and self[0] == 0x20 and self[-1] == OP_CHECKTEMPLATEVERIFY
186+ </source >
144187
145188
146189==Deployment ==
0 commit comments