LCOV - code coverage report
Current view: top level - signer/src - btctx.c (source / functions) Hit Total Coverage
Test: powHSM firmware Lines: 135 140 96.4 %
Date: 2024-04-05 20:46:34 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 "btctx.h"
      29             : #include "memutil.h"
      30             : 
      31             : #include "svarint.h"
      32             : 
      33             : // Context pointer
      34             : static btctx_ctx_t *ctx;
      35             : 
      36             : /*
      37             :  * Initialize the parser.
      38             :  *
      39             :  * @arg[in] ctx the context to be used for this session
      40             :  *          (should have its callback set)
      41             :  */
      42         317 : void btctx_init(btctx_ctx_t *_ctx, btctx_cb_t _cb) {
      43         317 :     ctx = _ctx;
      44         317 :     memset(ctx, 0, sizeof(btctx_ctx_t));
      45         317 :     ctx->state = BTCTX_ST_VERSION;
      46         317 :     ctx->callback = _cb;
      47         317 : }
      48             : 
      49             : /*
      50             :  * Tell whether parsing is finished, and
      51             :  * whether it triggered an error (and which one)
      52             :  * This should be checked after every call to btctx_consume
      53             :  */
      54      448742 : int8_t btctx_result() {
      55      448742 :     if (ctx->state < 0 || ctx->state == BTCTX_ST_DONE)
      56         632 :         return ctx->state;
      57      448110 :     return BTCTX_ERR_NONE;
      58             : }
      59             : 
      60             : /*
      61             :  * Consume a chunk of bytes.
      62             :  *
      63             :  * @arg[in] buf: buffer holding bytes to be consumed
      64             :  * @arg[in] len: number of bytes to consume in buffer
      65             :  *
      66             :  * @return the number of bytes actually read and processed
      67             :  */
      68      448426 : uint8_t btctx_consume(uint8_t *buf, const uint8_t len) {
      69             :     uint8_t processed;
      70             : 
      71     4304062 :     for (uint8_t i = 0; i < len; i++) {
      72     3855952 :         switch (ctx->state) {
      73        1264 :         case BTCTX_ST_VERSION:
      74             :             // Read little endian TX version
      75        1264 :             ctx->raw[ctx->offset] = buf[i];
      76        1264 :             ctx->parsed.version += (uint32_t)buf[i] << (8 * ctx->offset++);
      77        1264 :             if (ctx->offset == BTCTX_VERSION_SIZE) {
      78         316 :                 ctx->raw_size = BTCTX_VERSION_SIZE;
      79         316 :                 ctx->callback(BTCTX_EV_VERSION);
      80         316 :                 ctx->state = BTCTX_ST_VIN_COUNT;
      81         316 :                 svarint_init(&ctx->parsed.varint);
      82             :             }
      83        1264 :             break;
      84       26711 :         case BTCTX_ST_VIN_COUNT:
      85             :         case BTCTX_ST_VOUT_COUNT:
      86             :         case BTCTX_ST_VIN_SLENGTH:
      87             :         case BTCTX_ST_VOUT_SLENGTH:
      88       26711 :             if (svarint_notstarted())
      89       26666 :                 ctx->raw_size = 0;
      90       26711 :             processed = svarint_consume(buf + i, len - i);
      91       53422 :             SAFE_MEMMOVE(ctx->raw,
      92             :                          sizeof(ctx->raw),
      93             :                          ctx->raw_size,
      94             :                          buf,
      95             :                          len,
      96             :                          i,
      97             :                          processed,
      98             :                          {
      99             :                              ctx->state = BTCTX_ERR_INVALID;
     100             :                              return processed;
     101             :                          });
     102       26711 :             ctx->raw_size += processed;
     103       26711 :             i += processed - 1;
     104             : 
     105       26711 :             switch (svarint_result()) {
     106          45 :             case SVARINT_ERR_NONE:
     107          45 :                 break;
     108       26647 :             case SVARINT_ST_DONE:
     109       26647 :                 switch (ctx->state) {
     110         315 :                 case BTCTX_ST_VIN_COUNT:
     111         315 :                     ctx->callback(BTCTX_EV_VIN_COUNT);
     112         315 :                     ctx->inout_total = ctx->parsed.varint.value;
     113         315 :                     ctx->inout_current = 0;
     114         315 :                     ctx->state = BTCTX_ST_VIN_TXH;
     115         315 :                     ctx->offset = 0;
     116         315 :                     break;
     117         304 :                 case BTCTX_ST_VOUT_COUNT:
     118         304 :                     ctx->callback(BTCTX_EV_VOUT_COUNT);
     119         304 :                     ctx->inout_total = ctx->parsed.varint.value;
     120         304 :                     ctx->inout_current = 0;
     121         304 :                     ctx->state = BTCTX_ST_VOUT_VALUE;
     122         304 :                     ctx->offset = 0;
     123         304 :                     break;
     124       25225 :                 case BTCTX_ST_VIN_SLENGTH:
     125       25225 :                     ctx->callback(BTCTX_EV_VIN_SLENGTH);
     126       25225 :                     ctx->state = BTCTX_ST_VIN_SCRIPT;
     127       25225 :                     ctx->script_remaining = ctx->parsed.varint.value;
     128       25225 :                     break;
     129         803 :                 case BTCTX_ST_VOUT_SLENGTH:
     130         803 :                     ctx->callback(BTCTX_EV_VOUT_SLENGTH);
     131         803 :                     ctx->state = BTCTX_ST_VOUT_SCRIPT;
     132         803 :                     ctx->script_remaining = ctx->parsed.varint.value;
     133         803 :                     break;
     134             :                 }
     135       26647 :                 break;
     136          19 :             case SVARINT_ERR_UNSUPPORTED:
     137          19 :                 ctx->state = BTCTX_ERR_UNSUPPORTED;
     138          19 :                 return i + 1;
     139           0 :             case SVARINT_ERR_INVALID:
     140             :             default:
     141           0 :                 ctx->state = BTCTX_ERR_INVALID;
     142           0 :                 return i + 1;
     143             :             }
     144             : 
     145       26692 :             break;
     146      807360 :         case BTCTX_ST_VIN_TXH:
     147      807360 :             if (ctx->offset == 0) {
     148       25230 :                 ctx->raw_size = 0;
     149       25230 :                 ctx->callback(BTCTX_EV_VIN_TXH_START);
     150             :             }
     151      807360 :             ctx->parsed.value = ctx->raw[0] = buf[i];
     152      807360 :             ctx->raw_size = 1;
     153      807360 :             ctx->callback(BTCTX_EV_VIN_TXH_DATA);
     154      807360 :             if (++ctx->offset == BTCTX_HASH_SIZE) {
     155       25230 :                 ctx->raw_size = 0;
     156       25230 :                 ctx->callback(BTCTX_EV_VIN_TXH_END);
     157       25230 :                 ctx->state = BTCTX_ST_VIN_TXIX;
     158       25230 :                 ctx->offset = 0;
     159             :             }
     160      807360 :             break;
     161      100920 :         case BTCTX_ST_VIN_TXIX:
     162      100920 :             if (ctx->offset == 0)
     163       25230 :                 ctx->parsed.ptxo_index = 0;
     164      100920 :             ctx->raw[ctx->offset] = buf[i];
     165      100920 :             ctx->parsed.ptxo_index += (uint32_t)buf[i] << (8 * ctx->offset++);
     166      100920 :             if (ctx->offset == BTCTX_INPUT_INDEX_SIZE) {
     167       25230 :                 ctx->raw_size = BTCTX_INPUT_INDEX_SIZE;
     168       25230 :                 ctx->callback(BTCTX_EV_VIN_TXIX);
     169       25230 :                 ctx->state = BTCTX_ST_VIN_SLENGTH;
     170       25230 :                 svarint_init(&ctx->parsed.varint);
     171             :             }
     172      100920 :             break;
     173     2811129 :         case BTCTX_ST_VIN_SCRIPT:
     174             :         case BTCTX_ST_VOUT_SCRIPT:
     175     2811129 :             ctx->parsed.value = ctx->raw[0] = buf[i];
     176     2811129 :             ctx->raw_size = 1;
     177     2811129 :             ctx->script_remaining--;
     178     2811129 :             ctx->callback(ctx->state == BTCTX_ST_VIN_SCRIPT
     179             :                               ? BTCTX_EV_VIN_SCRIPT_DATA
     180             :                               : BTCTX_EV_VOUT_SCRIPT_DATA);
     181     2811129 :             if (ctx->script_remaining == 0) {
     182       26028 :                 if (ctx->state == BTCTX_ST_VIN_SCRIPT) {
     183       25225 :                     ctx->state = BTCTX_ST_VIN_SEQNO;
     184             :                 } else {
     185         803 :                     ctx->state = ++ctx->inout_current == ctx->inout_total
     186             :                                      ? BTCTX_ST_LOCK_TIME
     187             :                                      : BTCTX_ST_VOUT_VALUE;
     188             :                 }
     189       26028 :                 ctx->offset = 0;
     190             :             }
     191     2811129 :             break;
     192      100900 :         case BTCTX_ST_VIN_SEQNO:
     193      100900 :             if (ctx->offset == 0)
     194       25225 :                 ctx->parsed.seqno = 0;
     195      100900 :             ctx->raw[ctx->offset] = buf[i];
     196      100900 :             ctx->parsed.seqno += (uint32_t)buf[i] << (8 * ctx->offset++);
     197      100900 :             if (ctx->offset == BTCTX_INPUT_SEQNO_SIZE) {
     198       25225 :                 ctx->raw_size = BTCTX_INPUT_SEQNO_SIZE;
     199       25225 :                 ctx->callback(BTCTX_EV_VIN_SEQNO);
     200       25225 :                 if (++ctx->inout_current == ctx->inout_total) {
     201         310 :                     ctx->state = BTCTX_ST_VOUT_COUNT;
     202         310 :                     svarint_init(&ctx->parsed.varint);
     203             :                 } else {
     204       24915 :                     ctx->state = BTCTX_ST_VIN_TXH;
     205       24915 :                     ctx->offset = 0;
     206             :                 }
     207             :             }
     208      100900 :             break;
     209        6480 :         case BTCTX_ST_VOUT_VALUE:
     210        6480 :             if (ctx->offset == 0)
     211         810 :                 ctx->parsed.vout_value = 0L;
     212        6480 :             ctx->raw[ctx->offset] = buf[i];
     213        6480 :             ctx->parsed.vout_value += (uint64_t)buf[i] << 8 * ctx->offset++;
     214        6480 :             if (ctx->offset == BTCTX_OUTPUT_VALUE_SIZE) {
     215         810 :                 ctx->raw_size = BTCTX_OUTPUT_VALUE_SIZE;
     216         810 :                 ctx->callback(BTCTX_EV_VOUT_VALUE);
     217         810 :                 ctx->state = BTCTX_ST_VOUT_SLENGTH;
     218         810 :                 svarint_init(&ctx->parsed.varint);
     219             :             }
     220        6480 :             break;
     221        1188 :         case BTCTX_ST_LOCK_TIME:
     222        1188 :             if (ctx->offset == 0)
     223         297 :                 ctx->parsed.locktime = 0;
     224        1188 :             ctx->raw[ctx->offset] = buf[i];
     225        1188 :             ctx->parsed.locktime += (uint32_t)buf[i] << (8 * ctx->offset++);
     226        1188 :             if (ctx->offset == BTCTX_LOCKTIME_SIZE) {
     227         297 :                 ctx->raw_size = BTCTX_LOCKTIME_SIZE;
     228         297 :                 ctx->callback(BTCTX_EV_LOCKTIME);
     229         297 :                 ctx->state = BTCTX_ST_DONE;
     230         297 :                 return i + 1;
     231             :             }
     232         891 :             break;
     233           0 :         default:
     234           0 :             return 0;
     235             :         }
     236             :     }
     237             : 
     238      448110 :     return len;
     239             : }

Generated by: LCOV version 1.14