25
25
#include < bitcoin/system/chain/enums/opcode.hpp>
26
26
#include < bitcoin/system/chain/operation.hpp>
27
27
#include < bitcoin/system/chain/script.hpp>
28
+ #include < bitcoin/system/crypto/crypto.hpp>
28
29
#include < bitcoin/system/data/data.hpp>
29
30
#include < bitcoin/system/define.hpp>
30
31
#include < bitcoin/system/error/error.hpp>
@@ -82,11 +83,11 @@ static inline const hash_digest& to_array32(const data_chunk& program) NOEXCEPT
82
83
static bool is_valid_control_block (const data_chunk& control) NOEXCEPT
83
84
{
84
85
const auto size = control.size ();
85
- constexpr auto max = add1 (hash_size ) + hash_size * taproot_max_nodes ;
86
+ constexpr auto max = add1 (ec_xonly_size ) + ec_xonly_size * taproot_max_keys ;
86
87
87
88
// Control block must be add1(32) + 32m, for integer m [0..128] [bip341].
88
- return !is_limited (size, add1 (hash_size ), max) && is_zero (
89
- floored_modulo (size - add1 (hash_size ), hash_size ));
89
+ return !is_limited (size, add1 (ec_xonly_size ), max) && is_zero (
90
+ floored_modulo (size - add1 (ec_xonly_size ), ec_xonly_size ));
90
91
}
91
92
92
93
// out_script is only useful only for sigop counting.
@@ -146,6 +147,86 @@ inline bool witness::drop_annex(chunk_cptrs& stack) NOEXCEPT
146
147
return false ;
147
148
}
148
149
150
+ static hash_digest get_tapleaf_hash (uint8_t version,
151
+ const script& script) NOEXCEPT
152
+ {
153
+ hash_digest out{};
154
+ stream::out::fast stream{ out };
155
+ hash::sha256t::fast<" TapLeaf" > sink{ stream };
156
+ sink.write_byte (version);
157
+ script.to_data (sink, true );
158
+ sink.flush ();
159
+ return out;
160
+ }
161
+
162
+ static hash_digest get_taptweak_hash (const ec_xonly& key,
163
+ const hash_digest& merkle) NOEXCEPT
164
+ {
165
+ hash_digest out{};
166
+ stream::out::fast stream{ out };
167
+ hash::sha256t::fast<" TapTweak" > sink{ stream };
168
+ sink.write_bytes (key);
169
+ sink.write_bytes (merkle);
170
+ sink.flush ();
171
+ return out;
172
+ }
173
+
174
+ static hash_digest get_tapbranch_hash (const hash_digest& left,
175
+ const hash_digest& right) NOEXCEPT
176
+ {
177
+ hash_digest out{};
178
+ stream::out::fast stream{ out };
179
+ hash::sha256t::fast<" TapBranch" > sink{ stream };
180
+
181
+ if (std::lexicographical_compare (left.begin (), left.end (),
182
+ right.begin (), right.end ()))
183
+ {
184
+ sink.write_bytes (left);
185
+ sink.write_bytes (right);
186
+ }
187
+ else
188
+ {
189
+ sink.write_bytes (right);
190
+ sink.write_bytes (left);
191
+ }
192
+
193
+ sink.flush ();
194
+ return out;
195
+ }
196
+
197
+ static hash_digest get_merkle_root (const data_chunk& control,
198
+ const hash_digest& tapleaf_hash) NOEXCEPT
199
+ {
200
+ BC_ASSERT (is_valid_control_block (control));
201
+
202
+ constexpr auto start = add1 (ec_xonly_size);
203
+ const auto bytes = floored_subtract (control.size (), start);
204
+ const auto count = floored_divide (bytes, ec_xonly_size);
205
+ const auto begin = std::next (control.data (), start);
206
+ const auto nodes = unsafe_array_cast<ec_xonly, taproot_max_keys>(begin);
207
+
208
+ hash_digest hash{ tapleaf_hash };
209
+ for (size_t node{}; node < count; ++node)
210
+ hash = get_tapbranch_hash (hash, nodes.at (node));
211
+
212
+ return hash;
213
+ }
214
+
215
+ static bool verify_commitment (const data_chunk& control,
216
+ const data_chunk& program, const hash_digest& hash,
217
+ bool parity) NOEXCEPT
218
+ {
219
+ BC_ASSERT (is_valid_control_block (control));
220
+
221
+ const auto out = program.data ();
222
+ const auto & out_key = unsafe_array_cast<uint8_t , ec_xonly_size>(out);
223
+ const auto in = std::next (control.data ());
224
+ const auto & in_key = unsafe_array_cast<uint8_t , ec_xonly_size>(in);
225
+ const auto merkle = get_merkle_root (control, hash);
226
+ const auto tweak = get_taptweak_hash (out_key, merkle);
227
+ return schnorr::verify_commitment (in_key, tweak, out_key, parity);
228
+ }
229
+
149
230
// Extract script and initial execution stack.
150
231
code witness::extract_script (script::cptr& out_script,
151
232
chunk_cptrs_ptr& out_stack, const script& program_script) const NOEXCEPT
@@ -205,7 +286,7 @@ code witness::extract_script(script::cptr& out_script,
205
286
case script_version::taproot:
206
287
{
207
288
// witness stack : [annex]...
208
- if (program->size () == hash_size )
289
+ if (program->size () == ec_xonly_size )
209
290
{
210
291
auto stack_size = out_stack->size ();
211
292
@@ -227,139 +308,30 @@ code witness::extract_script(script::cptr& out_script,
227
308
// The second-to-last stack element is the script.
228
309
out_script = to_shared<script>(*pop (*out_stack), false );
229
310
311
+ // Extract version and parity from control byte.
230
312
const auto bits = control->front ();
231
313
const auto version = bit_and (bits, tapleaf_root_mask);
232
314
const auto parity = bit_and (bits, bit_not (tapleaf_root_mask));
233
315
234
- // TODO: pass into signature hashing.
235
- const auto tapscript = (version == tapleaf_tapscript);
236
-
237
- if (tapscript)
316
+ if (version == tapleaf_tapscript)
238
317
{
239
- const auto get_tapleaf_hash = [](uint8_t version,
240
- const script& script) NOEXCEPT
241
- {
242
- hash_digest out{};
243
- stream::out::fast stream{ out };
244
- hash::sha256t::fast<" TapLeaf" > sink{ stream };
245
- sink.write_byte (version);
246
- script.to_data (sink, true );
247
- sink.flush ();
248
- return out;
249
- };
250
-
251
318
// TODO: pass into tapscript signature hashing.
252
- const auto tapleaf_hash = get_tapleaf_hash (version,
253
- *out_script);
254
-
255
- const auto get_taptweak_hash = [](
256
- const hash_digest& out_key,
257
- const hash_digest& merkle) NOEXCEPT
258
- {
259
- hash_digest out{};
260
- stream::out::fast stream{ out };
261
- hash::sha256t::fast<" TapTweak" > sink{ stream };
262
- sink.write_bytes (out_key);
263
- sink.write_bytes (merkle);
264
- sink.flush ();
265
- return out;
266
- };
267
-
268
- // TODO: add secp256k1_xonly_pubkey_parse to secp256k1.
269
- // TODO: add secp256k1_xonly_pubkey_tweak_add_check to secp256k1.
270
- const auto check_taptweak = [&](
271
- const hash_digest& /* in_key */ ,
272
- const hash_digest& out_key,
273
- const hash_digest& merkle,
274
- bool /* parity */ ) NOEXCEPT
275
- {
276
- // //secp256k1_xonly_pubkey xonly_pubkey{};
277
- // //if (!secp256k1_xonly_pubkey_parse(
278
- // // secp256k1_context_static,
279
- // // &xonly_pubkey,
280
- // // out_key.data()))
281
- // // return false;
282
-
283
- /* const auto hash = */ get_taptweak_hash (out_key, merkle);
284
- // //return secp256k1_xonly_pubkey_tweak_add_check(
285
- // // secp256k1_context_static,
286
- // // in_key.begin(),
287
- // // parity,
288
- // // &xonly_pubkey,
289
- // // hash.data());
290
- return false ;
291
- };
292
-
293
- const auto get_tapbranch_hash = [](const hash_digest& left,
294
- const hash_digest& right) NOEXCEPT
295
- {
296
- hash_digest out{};
297
- stream::out::fast stream{ out };
298
- hash::sha256t::fast<" TapBranch" > sink{ stream };
299
-
300
- // lesser is true, shorter is lesser, equal is not.
301
- if (std::lexicographical_compare (left.begin (), left.end (),
302
- right.begin (), right.end ()))
303
- {
304
- sink.write_bytes (left);
305
- sink.write_bytes (right);
306
- }
307
- else
308
- {
309
- sink.write_bytes (right);
310
- sink.write_bytes (left);
311
- }
312
-
313
- sink.flush ();
314
- return out;
315
- };
316
-
317
- // There is no null in validation path.
318
- const auto get_merkle_root = [&](const data_chunk& control,
319
- const hash_digest& tapleaf_hash) NOEXCEPT
320
- {
321
- BC_ASSERT (is_valid_control_block (control));
322
- using node_t = std_array<uint8_t , hash_size>;
323
- constexpr auto key = add1 (hash_size);
324
- constexpr auto max = taproot_max_nodes;
325
- hash_digest hash{ tapleaf_hash };
326
-
327
- // Cast control into std::array<node_t, 128> (unsafe).
328
- const auto bytes = floored_subtract (control.size (), key);
329
- const auto count = floored_divide (bytes, hash_size);
330
- const auto first = std::next (control.data (), key);
331
- const auto nodes = unsafe_array_cast<node_t , max>(first);
332
-
333
- // Read only to actual count of nodes (safe).
334
- for (size_t node{}; node < count; ++node)
335
- hash = get_tapbranch_hash (hash, nodes.at (node));
336
-
337
- return hash;
338
- };
339
-
340
- const auto verify_commitment = [&](const data_chunk& control,
341
- const data_chunk& program, const hash_digest& hash) NOEXCEPT
342
- {
343
- const auto out = program.data ();
344
- const auto in = std::next (control.data ());
345
- const auto & in_key = unsafe_array_cast<uint8_t , hash_size>(in);
346
- const auto & out_key = unsafe_array_cast<uint8_t , hash_size>(out);
347
- const auto merkle = get_merkle_root (control, hash);
348
- return check_taptweak (in_key, out_key, merkle, parity);
349
- };
350
-
351
- if (!verify_commitment (*control, *program, tapleaf_hash))
319
+ const auto tapleaf_hash = get_tapleaf_hash (version, *out_script);
320
+ if (!verify_commitment (*control, *program, tapleaf_hash, parity))
352
321
return error::invalid_commitment;
353
322
354
- // Execute script with remaining stack.
323
+ // TODO: return tapleaf_hash in pointer.
324
+ // Execute tapleaf script.
325
+ // out stack : [stack-elements]
326
+ // out script : (popped-from-stack)
355
327
return error::script_success;
356
328
}
357
329
358
- // This op_success script succeeds immediately.
330
+ // Others remain unencumbered (success).
331
+ // out stack : (empty)
332
+ // out script : <op_success>
359
333
out_script = success_script_ptr ();
360
334
out_stack->clear ();
361
-
362
- // Others remain unencumbered (success).
363
335
return error::script_success;
364
336
}
365
337
@@ -371,34 +343,42 @@ code witness::extract_script(script::cptr& out_script,
371
343
{
372
344
// Stack element is a signature that must be valid for q.
373
345
// Program is q, a 32 byte bip340 public key, so push it.
346
+ // out stack : (empty)
347
+ // out script : <op_checksig>
374
348
out_stack->push_back (program);
375
349
out_script = checksig_script_ptr ();
376
-
377
- // out_stack : <public-key> <signature>
378
- // out_script : <op_checksig>
379
350
return error::script_success;
380
351
}
381
352
382
353
// Fail if witness stack was empty.
354
+ // witness stack : (empty)
355
+ // input script : (empty)
356
+ // output script : <1> <32-byte-value>
383
357
return error::invalid_witness;
384
358
}
385
359
386
- // pay-to-anchor (p2a) programs land here (standardness).
360
+ // pay-to-anchor (p2a) programs pass by here (standardness).
387
361
// //script::is_anchor_program_pattern(program_script.ops())
388
362
389
- // This op_success script succeeds immediately.
363
+ // Version 1 other than 32 bytes...
364
+ // witness stack : [stack-elements]
365
+ // input script : (empty)
366
+ // output script : <1> <2..40 byte program>
367
+ // ...remain unencumbered (success).
368
+ // out stack : (empty)
369
+ // out script : <op_success>
390
370
out_script = success_script_ptr ();
391
371
out_stack->clear ();
392
-
393
- // Version 1 other than 32 bytes remain unencumbered (success).
394
372
return error::script_success;
395
373
}
396
374
397
375
// These versions are reserved for future extensions [bip141].
376
+ // output script : <2..16> <2..40 byte program>
398
377
case script_version::reserved:
399
378
return error::script_success;
400
379
401
380
// The witness version is undefined.
381
+ // output script : <!0..16> <2..40 byte program>
402
382
case script_version::unversioned:
403
383
default :
404
384
return error::invalid_witness;
0 commit comments