LCOV - code coverage report
Current view: top level - powhsm/src - btcscript.c (source / functions) Hit Total Coverage
Test: powHSM firmware Lines: 57 59 96.6 %
Date: 2025-07-10 13:49:13 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /**
       2             :  * The MIT License (MIT)
       3             :  *
       4             :  * Copyright (c) 2021 RSK Labs Ltd
       5             :  *
       6             :  * Permission is hereby granted, free of charge, to any person obtaining a copy
       7             :  * of this software and associated documentation files (the "Software"), to
       8             :  * deal in the Software without restriction, including without limitation the
       9             :  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
      10             :  * sell copies of the Software, and to permit persons to whom the Software is
      11             :  * furnished to do so, subject to the following conditions:
      12             :  *
      13             :  * The above copyright notice and this permission notice shall be included in
      14             :  * all copies or substantial portions of the Software.
      15             :  *
      16             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      17             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      18             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      19             :  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      20             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      21             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
      22             :  * IN THE SOFTWARE.
      23             :  */
      24             : 
      25             : #include <stdint.h>
      26             : #include <string.h>
      27             : 
      28             : #include "btcscript.h"
      29             : 
      30             : #include "svarint.h"
      31             : 
      32             : // Context pointer
      33             : static btcscript_ctx_t *ctx;
      34             : 
      35             : /*
      36             :  * Initialize the parser.
      37             :  *
      38             :  * @arg[in] ctx         the context to be used for this session
      39             :  * @arg[in] cb          the callback to be used for this session
      40             :  * @arg[in] script_size the total script size in bytes
      41             :  */
      42         159 : void btcscript_init(btcscript_ctx_t *_ctx,
      43             :                     btcscript_cb_t _cb,
      44             :                     uint32_t script_size) {
      45         159 :     ctx = _ctx;
      46         159 :     memset(ctx, 0, sizeof(btcscript_ctx_t));
      47         159 :     ctx->state = BTCSCRIPT_ST_OPCODE;
      48         159 :     ctx->callback = _cb;
      49         159 :     ctx->bytes_remaining = script_size;
      50         159 : }
      51             : 
      52             : /*
      53             :  * Tell whether parsing is finished, and
      54             :  * whether it triggered an error (and which one)
      55             :  * This should be checked after every call to btcscript_consume
      56             :  */
      57       11289 : int8_t btcscript_result() {
      58       11289 :     if (ctx->state < 0 || ctx->state == BTCSCRIPT_ST_DONE)
      59         293 :         return ctx->state;
      60       10996 :     return BTCSCRIPT_ERR_NONE;
      61             : }
      62             : 
      63             : /*
      64             :  * Consume a chunk of bytes.
      65             :  *
      66             :  * @arg[in] buf: buffer holding bytes to be consumed
      67             :  * @arg[in] len: number of bytes to consume in buffer
      68             :  *
      69             :  * @return the number of bytes actually read and processed
      70             :  */
      71       11151 : uint8_t btcscript_consume(uint8_t *buf, const uint8_t len) {
      72       38913 :     for (uint8_t i = 0; i < len; i++) {
      73       27918 :         ctx->bytes_remaining--;
      74       27918 :         switch (ctx->state) {
      75         539 :         case BTCSCRIPT_ST_OPCODE:
      76         539 :             ctx->opcode = buf[i];
      77             :             // Push only - taken from
      78             :             // https://github.com/bitcoin/bitcoin/blob/v0.20.2/src/script/script.cpp#L242
      79         539 :             if (ctx->opcode > BTCSCRIPT_OP_16) {
      80          14 :                 ctx->state = BTCSCRIPT_ERR_INVALID;
      81          14 :                 return i + 1;
      82             :             }
      83             : 
      84             :             // Taken from
      85             :             // https://github.com/bitcoin/bitcoin/blob/v0.20.2/src/script/script.cpp#L278
      86         525 :             if (ctx->opcode > BTCSCRIPT_OP_0 &&
      87         195 :                 ctx->opcode < BTCSCRIPT_OP_PUSHDATA1) {
      88          53 :                 ctx->operand_size = ctx->opcode;
      89          53 :                 ctx->callback(BTCSCRIPT_EV_OPCODE);
      90          53 :                 ctx->state = BTCSCRIPT_ST_OPERAND;
      91         472 :             } else if (ctx->opcode == BTCSCRIPT_OP_0 ||
      92         142 :                        ctx->opcode >= BTCSCRIPT_OP_1NEGATE) {
      93         350 :                 ctx->operand_size = 0;
      94         350 :                 ctx->callback(BTCSCRIPT_EV_OPCODE);
      95             :             } else { // OP_PUSHDATA{1,2,4}
      96         122 :                 ctx->operand_size = 0;
      97         122 :                 ctx->size_offset = 0;
      98         122 :                 ctx->state = BTCSCRIPT_ST_OPERAND_SIZE;
      99             :             }
     100         525 :             break;
     101         233 :         case BTCSCRIPT_ST_OPERAND_SIZE:
     102         233 :             ctx->operand_size += buf[i] << (8 * ctx->size_offset++);
     103         233 :             if ((ctx->opcode == BTCSCRIPT_OP_PUSHDATA1 &&
     104          59 :                  ctx->size_offset == 1) ||
     105         174 :                 (ctx->opcode == BTCSCRIPT_OP_PUSHDATA2 &&
     106          78 :                  ctx->size_offset == 2) ||
     107         135 :                 (ctx->opcode == BTCSCRIPT_OP_PUSHDATA4 &&
     108          96 :                  ctx->size_offset == 4)) {
     109         122 :                 ctx->callback(BTCSCRIPT_EV_OPCODE);
     110         122 :                 ctx->state = BTCSCRIPT_ST_OPERAND;
     111             :             }
     112         233 :             break;
     113       27146 :         case BTCSCRIPT_ST_OPERAND:
     114       27146 :             ctx->operand_byte = buf[i];
     115       27146 :             ctx->callback(BTCSCRIPT_EV_OPERAND);
     116       27146 :             if (!--ctx->operand_size) {
     117         171 :                 ctx->callback(BTCSCRIPT_EV_OPERAND_END);
     118         171 :                 ctx->state = BTCSCRIPT_ST_OPCODE;
     119             :             }
     120       27146 :             break;
     121           0 :         default:
     122           0 :             return 0;
     123             :         }
     124             : 
     125       27904 :         if (!ctx->bytes_remaining) {
     126         142 :             if (ctx->state == BTCSCRIPT_ST_OPCODE) {
     127         140 :                 ctx->state = BTCSCRIPT_ST_DONE;
     128             :             } else {
     129           2 :                 ctx->state = BTCSCRIPT_ERR_INVALID;
     130             :             }
     131         142 :             return i + 1;
     132             :         }
     133             :     }
     134             : 
     135       10995 :     return len;
     136             : }

Generated by: LCOV version 1.16