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 : }