@@ -66,31 +66,40 @@ OP_CHECKTEMPLATEVERIFY as implemented in C++ in the context of Bitcoin Core can
66
66
be seen in the reference implementation.
67
67
68
68
The 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
90
75
if self.flags.script_verify_discourage_upgradable_nops:
91
76
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>
94
103
95
104
The computation of this hash can be implemented as specified below (where self
96
105
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
101
110
"Denial of Service and Validation Costs" below. This is not a performance
102
111
optimization.
103
112
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):
119
136
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 >
137
178
138
179
139
180
A PayToBareDefaultCheckTemplateVerifyHash output matches the following template:
140
181
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 >
144
187
145
188
146
189
==Deployment ==
0 commit comments