|
65 | 65 | #include <stdio.h>
|
66 | 66 |
|
67 | 67 | #include "bignum.h"
|
68 |
| -#include "btc_helpers.h" |
69 | 68 | #include "btc_script.h"
|
70 | 69 | #include "utils.h"
|
71 | 70 |
|
@@ -328,277 +327,10 @@ STATIC bool calculate_p2wpkh_digest(const btc_txn_context_t *context,
|
328 | 327 | return true;
|
329 | 328 | }
|
330 | 329 |
|
331 |
| -static void update_hash(btc_verify_input_t *verify_input_data, |
332 |
| - const uint8_t *raw_txn_chunk, |
333 |
| - int chunk_index, |
334 |
| - int32_t offset) { |
335 |
| - hash_case update = DEFAULT; |
336 |
| - |
337 |
| - if (0 == chunk_index) { |
338 |
| - update = FIRST_CHUNK_HASH; |
339 |
| - } |
340 |
| - switch (update) { |
341 |
| - case FIRST_CHUNK_HASH: { |
342 |
| - if (verify_input_data->is_segwit) { |
343 |
| - sha256_Update(&(verify_input_data->sha_256_ctx), raw_txn_chunk, 4); |
344 |
| - // skip marker and flag |
345 |
| - sha256_Update( |
346 |
| - &(verify_input_data->sha_256_ctx), raw_txn_chunk + 6, offset - 6); |
347 |
| - } else { |
348 |
| - sha256_Update(&(verify_input_data->sha_256_ctx), raw_txn_chunk, offset); |
349 |
| - } |
350 |
| - return; |
351 |
| - break; |
352 |
| - } |
353 |
| - |
354 |
| - default: { |
355 |
| - sha256_Update(&(verify_input_data->sha_256_ctx), raw_txn_chunk, offset); |
356 |
| - break; |
357 |
| - } |
358 |
| - } |
359 |
| -} |
360 |
| - |
361 |
| -static void update_locktime(btc_verify_input_t *verify_input_data, |
362 |
| - const uint8_t *raw_txn_chunk, |
363 |
| - int chunk_index) { |
364 |
| - if (verify_input_data->is_locktime_split) { |
365 |
| - // last second chunk |
366 |
| - if (chunk_index + 2 == verify_input_data->chunk_total) { |
367 |
| - memcpy( |
368 |
| - verify_input_data->locktime, |
369 |
| - raw_txn_chunk + (CHUNK_SIZE - 4 - verify_input_data->size_last_chunk), |
370 |
| - 4 - verify_input_data->size_last_chunk); |
371 |
| - return; |
372 |
| - } else if (chunk_index + 1 == verify_input_data->chunk_total) { |
373 |
| - memcpy( |
374 |
| - verify_input_data->locktime + 4 - verify_input_data->size_last_chunk, |
375 |
| - raw_txn_chunk, |
376 |
| - verify_input_data->size_last_chunk); |
377 |
| - verify_input_data->has_locktime = true; |
378 |
| - return; |
379 |
| - } else { |
380 |
| - // wait for subsequent chunks |
381 |
| - return; |
382 |
| - } |
383 |
| - } else if (chunk_index + 1 == verify_input_data->chunk_total) { |
384 |
| - memcpy(verify_input_data->locktime, |
385 |
| - raw_txn_chunk + verify_input_data->size_last_chunk - 4, |
386 |
| - 4); |
387 |
| - verify_input_data->has_locktime = true; |
388 |
| - } else { |
389 |
| - // wait for subsequent chunks |
390 |
| - return; |
391 |
| - } |
392 |
| -} |
393 |
| - |
394 |
| -// TODO: Add chunking condition for varint decode |
395 |
| -// refer: https://app.clickup.com/t/9002019994/PRF-7288 |
396 |
| -static int64_t varint_decode(const uint8_t *raw_txn_chunk, int32_t *offset) { |
397 |
| - uint8_t first_byte = raw_txn_chunk[*offset]; |
398 |
| - if (first_byte < 0xFD) { |
399 |
| - return first_byte; |
400 |
| - } else { |
401 |
| - // TODO: var-int varies between 1-9 bytes |
402 |
| - // current implementation supports decoding |
403 |
| - // upto 3 bytes only |
404 |
| - uint8_t result[2]; |
405 |
| - memcpy(result, raw_txn_chunk + *offset + 1, 2); |
406 |
| - *offset += 2; |
407 |
| - return U16_READ_LE_ARRAY(result); |
408 |
| - } |
409 |
| -} |
410 | 330 | /*****************************************************************************
|
411 | 331 | * GLOBAL FUNCTIONS
|
412 | 332 | *****************************************************************************/
|
413 | 333 |
|
414 |
| -int btc_verify_input(const uint8_t *raw_txn_chunk, |
415 |
| - const uint32_t chunk_index, |
416 |
| - btc_verify_input_t *verify_input_data, |
417 |
| - const btc_sign_txn_input_t *input) { |
418 |
| - if (NULL == input || NULL == raw_txn_chunk || |
419 |
| - 0 == verify_input_data->chunk_total) { |
420 |
| - return -1; |
421 |
| - } |
422 |
| - |
423 |
| - int32_t offset = 0; |
424 |
| - if (chunk_index == 0) { |
425 |
| - // ignore network version (4-bytes), skip marker & flag (in segwit) |
426 |
| - offset += (raw_txn_chunk[4] == 0 ? 6 : 4); |
427 |
| - if (6 == offset) { |
428 |
| - verify_input_data->is_segwit = true; |
429 |
| - } |
430 |
| - |
431 |
| - // TODO: Improve varint decode. |
432 |
| - // size of variable containing script size and ip-count/op-count |
433 |
| - // varies (1-9 Bytes) depending on its value. |
434 |
| - // refer: |
435 |
| - // https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer |
436 |
| - verify_input_data->count = |
437 |
| - raw_txn_chunk[offset++]; ///< store the number of inputs in the |
438 |
| - ///< raw_txn |
439 |
| - |
440 |
| - verify_input_data->parsetype = INPUT; |
441 |
| - sha256_Init(&(verify_input_data->sha_256_ctx)); |
442 |
| - } else { |
443 |
| - offset += verify_input_data->prev_offset; |
444 |
| - } |
445 |
| - switch (verify_input_data->parsetype) { |
446 |
| - case INPUT: { |
447 |
| - while (verify_input_data->input_index < (verify_input_data->count) && |
448 |
| - INPUT == verify_input_data->parsetype) { |
449 |
| - input_case ip_case = verify_input_data->input_parse; |
450 |
| - switch (ip_case) { |
451 |
| - case PREVIOUS_TX_HASH_PLUS_OP_INDEX_CASE: { |
452 |
| - if (offset + 36 >= CHUNK_SIZE) { |
453 |
| - verify_input_data->prev_offset = (offset + 36) - CHUNK_SIZE; |
454 |
| - update_hash( |
455 |
| - verify_input_data, raw_txn_chunk, chunk_index, CHUNK_SIZE); |
456 |
| - verify_input_data->input_parse = SCRIPT_LENGTH_CASE; |
457 |
| - return 4; |
458 |
| - } else { |
459 |
| - offset += 36; |
460 |
| - } |
461 |
| - } |
462 |
| - |
463 |
| - case SCRIPT_LENGTH_CASE: { |
464 |
| - int64_t script_length = varint_decode(raw_txn_chunk, &offset); |
465 |
| - if (offset + script_length + 1 + 4 >= CHUNK_SIZE) { |
466 |
| - verify_input_data->prev_offset = |
467 |
| - (offset + script_length + 1 + 4) - CHUNK_SIZE; |
468 |
| - update_hash( |
469 |
| - verify_input_data, raw_txn_chunk, chunk_index, CHUNK_SIZE); |
470 |
| - verify_input_data->input_parse = |
471 |
| - PREVIOUS_TX_HASH_PLUS_OP_INDEX_CASE; |
472 |
| - verify_input_data->input_index++; |
473 |
| - return 4; |
474 |
| - } else { |
475 |
| - offset += (script_length + 1 + 4); |
476 |
| - } |
477 |
| - break; |
478 |
| - } |
479 |
| - |
480 |
| - default: |
481 |
| - break; |
482 |
| - } |
483 |
| - verify_input_data->input_parse = PREVIOUS_TX_HASH_PLUS_OP_INDEX_CASE; |
484 |
| - verify_input_data->input_index++; |
485 |
| - } |
486 |
| - verify_input_data->parsetype = OP_COUNT; |
487 |
| - } |
488 |
| - |
489 |
| - case OP_COUNT: { |
490 |
| - if (offset + 1 >= CHUNK_SIZE) { |
491 |
| - // reset prev offset |
492 |
| - verify_input_data->prev_offset = |
493 |
| - offset - CHUNK_SIZE; ///< Did not add +1 as returning back to |
494 |
| - ///< this stage to read op count |
495 |
| - update_hash(verify_input_data, raw_txn_chunk, chunk_index, CHUNK_SIZE); |
496 |
| - return 4; |
497 |
| - } else { |
498 |
| - verify_input_data->count = raw_txn_chunk[offset++]; |
499 |
| - } |
500 |
| - verify_input_data->parsetype = OUTPUT; |
501 |
| - verify_input_data->output_parse = VALUE_CASE; |
502 |
| - } |
503 |
| - |
504 |
| - case OUTPUT: { |
505 |
| - while (verify_input_data->output_index < verify_input_data->count) { |
506 |
| - output_case op_case = verify_input_data->output_parse; |
507 |
| - switch (op_case) { |
508 |
| - case VALUE_CASE: { |
509 |
| - if (verify_input_data->output_index == input->prev_output_index) { |
510 |
| - if (offset + 8 >= CHUNK_SIZE) { |
511 |
| - verify_input_data->prev_offset = (offset + 8) - CHUNK_SIZE; |
512 |
| - memcpy(verify_input_data->value, |
513 |
| - raw_txn_chunk + offset, |
514 |
| - CHUNK_SIZE - offset); |
515 |
| - update_hash( |
516 |
| - verify_input_data, raw_txn_chunk, chunk_index, CHUNK_SIZE); |
517 |
| - verify_input_data->output_parse = VALUE_SPLIT_CASE; |
518 |
| - verify_input_data->is_split = 1; |
519 |
| - return 4; |
520 |
| - } else { |
521 |
| - memcpy(verify_input_data->value, raw_txn_chunk + offset, 8); |
522 |
| - } |
523 |
| - } |
524 |
| - if (offset + 8 >= CHUNK_SIZE) { |
525 |
| - verify_input_data->prev_offset = (offset + 8) - CHUNK_SIZE; |
526 |
| - update_hash( |
527 |
| - verify_input_data, raw_txn_chunk, chunk_index, CHUNK_SIZE); |
528 |
| - verify_input_data->output_parse = SCRIPT_PUBKEY_CASE; |
529 |
| - return 4; |
530 |
| - } else { |
531 |
| - offset += 8; |
532 |
| - } |
533 |
| - } |
534 |
| - |
535 |
| - case VALUE_SPLIT_CASE: { |
536 |
| - if (verify_input_data->is_split) { |
537 |
| - memcpy(verify_input_data->value + (8 - offset), |
538 |
| - raw_txn_chunk, |
539 |
| - offset); |
540 |
| - verify_input_data->output_parse = SCRIPT_PUBKEY_CASE; |
541 |
| - verify_input_data->is_split = 0; |
542 |
| - } |
543 |
| - } |
544 |
| - |
545 |
| - case SCRIPT_PUBKEY_CASE: { |
546 |
| - if (offset + raw_txn_chunk[offset] + 1 >= CHUNK_SIZE) { |
547 |
| - verify_input_data->prev_offset = |
548 |
| - (offset + raw_txn_chunk[offset] + 1) - CHUNK_SIZE; |
549 |
| - update_hash( |
550 |
| - verify_input_data, raw_txn_chunk, chunk_index, CHUNK_SIZE); |
551 |
| - verify_input_data->output_parse = VALUE_CASE; |
552 |
| - verify_input_data->output_index++; |
553 |
| - return 4; |
554 |
| - } else { |
555 |
| - offset += (raw_txn_chunk[offset] + 1); |
556 |
| - } |
557 |
| - break; |
558 |
| - } |
559 |
| - default: |
560 |
| - break; |
561 |
| - } |
562 |
| - verify_input_data->output_parse = VALUE_CASE; |
563 |
| - verify_input_data->output_index++; |
564 |
| - } |
565 |
| - |
566 |
| - verify_input_data->parsetype = LOCK_TIME; |
567 |
| - update_hash(verify_input_data, raw_txn_chunk, chunk_index, offset); |
568 |
| - } |
569 |
| - |
570 |
| - case LOCK_TIME: { |
571 |
| - update_locktime(verify_input_data, raw_txn_chunk, chunk_index); |
572 |
| - if (false == verify_input_data->has_locktime) { |
573 |
| - return 4; |
574 |
| - } |
575 |
| - sha256_Update( |
576 |
| - &(verify_input_data->sha_256_ctx), verify_input_data->locktime, 4); |
577 |
| - } |
578 |
| - default: |
579 |
| - break; |
580 |
| - } |
581 |
| - |
582 |
| - verify_input_data->parsetype = END; |
583 |
| - |
584 |
| - // Finalize hashing |
585 |
| - uint8_t hash[SHA256_DIGEST_LENGTH] = {0}; |
586 |
| - sha256_Final(&(verify_input_data->sha_256_ctx), hash); |
587 |
| - |
588 |
| - if (U64_READ_LE_ARRAY(verify_input_data->value) == 0) { |
589 |
| - return 1; |
590 |
| - } |
591 |
| - sha256_Raw(hash, sizeof(hash), hash); |
592 |
| - // verify input txn hash |
593 |
| - if (memcmp(hash, input->prev_txn_hash, sizeof(input->prev_txn_hash)) != 0) { |
594 |
| - return 2; |
595 |
| - } |
596 |
| - if (U64_READ_LE_ARRAY(verify_input_data->value) != input->value) { |
597 |
| - return 3; |
598 |
| - } |
599 |
| - return 0; |
600 |
| -} |
601 |
| - |
602 | 334 | uint64_t get_transaction_fee_threshold(const btc_txn_context_t *txn_ctx) {
|
603 | 335 | return (g_btc_app->max_fee / 1000) * (get_transaction_weight(txn_ctx) / 4);
|
604 | 336 | }
|
|
0 commit comments