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 375 : void btctx_init(btctx_ctx_t *_ctx, btctx_cb_t _cb) { 43 375 : ctx = _ctx; 44 375 : memset(ctx, 0, sizeof(btctx_ctx_t)); 45 375 : ctx->state = BTCTX_ST_VERSION; 46 375 : ctx->callback = _cb; 47 375 : } 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 453026 : int8_t btctx_result() { 55 453026 : if (ctx->state < 0 || ctx->state == BTCTX_ST_DONE) 56 736 : return ctx->state; 57 452290 : 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 450572 : uint8_t btctx_consume(uint8_t *buf, const uint8_t len) { 69 : uint8_t processed; 70 : 71 4476230 : for (uint8_t i = 0; i < len; i++) { 72 4026030 : switch (ctx->state) { 73 1496 : case BTCTX_ST_VERSION: 74 : // Read little endian TX version 75 1496 : ctx->raw[ctx->offset] = buf[i]; 76 1496 : ctx->parsed.version += (uint32_t)buf[i] << (8 * ctx->offset++); 77 1496 : if (ctx->offset == BTCTX_VERSION_SIZE) { 78 374 : ctx->raw_size = BTCTX_VERSION_SIZE; 79 374 : ctx->callback(BTCTX_EV_VERSION); 80 372 : ctx->state = BTCTX_ST_VIN_COUNT; 81 372 : svarint_init(&ctx->parsed.varint); 82 : } 83 1494 : break; 84 27999 : case BTCTX_ST_VIN_COUNT: 85 : case BTCTX_ST_VOUT_COUNT: 86 : case BTCTX_ST_VIN_SLENGTH: 87 : case BTCTX_ST_VOUT_SLENGTH: 88 27999 : if (svarint_notstarted()) 89 27954 : ctx->raw_size = 0; 90 27999 : processed = svarint_consume(buf + i, len - i); 91 55998 : 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 27999 : ctx->raw_size += processed; 103 27999 : i += processed - 1; 104 : 105 27999 : switch (svarint_result()) { 106 45 : case SVARINT_ERR_NONE: 107 45 : break; 108 27935 : case SVARINT_ST_DONE: 109 27935 : switch (ctx->state) { 110 371 : case BTCTX_ST_VIN_COUNT: 111 371 : ctx->callback(BTCTX_EV_VIN_COUNT); 112 371 : ctx->inout_total = ctx->parsed.varint.value; 113 371 : ctx->inout_current = 0; 114 371 : ctx->state = BTCTX_ST_VIN_TXH; 115 371 : ctx->offset = 0; 116 371 : break; 117 356 : case BTCTX_ST_VOUT_COUNT: 118 356 : ctx->callback(BTCTX_EV_VOUT_COUNT); 119 356 : ctx->inout_total = ctx->parsed.varint.value; 120 356 : ctx->inout_current = 0; 121 356 : ctx->state = BTCTX_ST_VOUT_VALUE; 122 356 : ctx->offset = 0; 123 356 : break; 124 26299 : case BTCTX_ST_VIN_SLENGTH: 125 26299 : ctx->callback(BTCTX_EV_VIN_SLENGTH); 126 26299 : ctx->state = BTCTX_ST_VIN_SCRIPT; 127 26299 : ctx->script_remaining = ctx->parsed.varint.value; 128 26299 : break; 129 909 : case BTCTX_ST_VOUT_SLENGTH: 130 909 : ctx->callback(BTCTX_EV_VOUT_SLENGTH); 131 909 : ctx->state = BTCTX_ST_VOUT_SCRIPT; 132 909 : ctx->script_remaining = ctx->parsed.varint.value; 133 909 : break; 134 : } 135 27935 : 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 27980 : break; 146 841728 : case BTCTX_ST_VIN_TXH: 147 841728 : if (ctx->offset == 0) { 148 26304 : ctx->raw_size = 0; 149 26304 : ctx->callback(BTCTX_EV_VIN_TXH_START); 150 : } 151 841728 : ctx->parsed.value = ctx->raw[0] = buf[i]; 152 841728 : ctx->raw_size = 1; 153 841728 : ctx->callback(BTCTX_EV_VIN_TXH_DATA); 154 841728 : if (++ctx->offset == BTCTX_HASH_SIZE) { 155 26304 : ctx->raw_size = 0; 156 26304 : ctx->callback(BTCTX_EV_VIN_TXH_END); 157 26304 : ctx->state = BTCTX_ST_VIN_TXIX; 158 26304 : ctx->offset = 0; 159 : } 160 841728 : break; 161 105216 : case BTCTX_ST_VIN_TXIX: 162 105216 : if (ctx->offset == 0) 163 26304 : ctx->parsed.ptxo_index = 0; 164 105216 : ctx->raw[ctx->offset] = buf[i]; 165 105216 : ctx->parsed.ptxo_index += (uint32_t)buf[i] << (8 * ctx->offset++); 166 105216 : if (ctx->offset == BTCTX_INPUT_INDEX_SIZE) { 167 26304 : ctx->raw_size = BTCTX_INPUT_INDEX_SIZE; 168 26304 : ctx->callback(BTCTX_EV_VIN_TXIX); 169 26304 : ctx->state = BTCTX_ST_VIN_SLENGTH; 170 26304 : svarint_init(&ctx->parsed.varint); 171 : } 172 105216 : break; 173 2935687 : case BTCTX_ST_VIN_SCRIPT: 174 : case BTCTX_ST_VOUT_SCRIPT: 175 2935687 : ctx->parsed.value = ctx->raw[0] = buf[i]; 176 2935687 : ctx->raw_size = 1; 177 2935687 : ctx->script_remaining--; 178 2935687 : ctx->callback(ctx->state == BTCTX_ST_VIN_SCRIPT 179 : ? BTCTX_EV_VIN_SCRIPT_DATA 180 : : BTCTX_EV_VOUT_SCRIPT_DATA); 181 2935685 : if (ctx->script_remaining == 0) { 182 27204 : if (ctx->state == BTCTX_ST_VIN_SCRIPT) { 183 26295 : ctx->state = BTCTX_ST_VIN_SEQNO; 184 : } else { 185 909 : ctx->state = ++ctx->inout_current == ctx->inout_total 186 : ? BTCTX_ST_LOCK_TIME 187 : : BTCTX_ST_VOUT_VALUE; 188 : } 189 27204 : ctx->offset = 0; 190 : } 191 2935685 : break; 192 105180 : case BTCTX_ST_VIN_SEQNO: 193 105180 : if (ctx->offset == 0) 194 26295 : ctx->parsed.seqno = 0; 195 105180 : ctx->raw[ctx->offset] = buf[i]; 196 105180 : ctx->parsed.seqno += (uint32_t)buf[i] << (8 * ctx->offset++); 197 105180 : if (ctx->offset == BTCTX_INPUT_SEQNO_SIZE) { 198 26295 : ctx->raw_size = BTCTX_INPUT_SEQNO_SIZE; 199 26295 : ctx->callback(BTCTX_EV_VIN_SEQNO); 200 26295 : if (++ctx->inout_current == ctx->inout_total) { 201 362 : ctx->state = BTCTX_ST_VOUT_COUNT; 202 362 : svarint_init(&ctx->parsed.varint); 203 : } else { 204 25933 : ctx->state = BTCTX_ST_VIN_TXH; 205 25933 : ctx->offset = 0; 206 : } 207 : } 208 105180 : break; 209 7328 : case BTCTX_ST_VOUT_VALUE: 210 7328 : if (ctx->offset == 0) 211 916 : ctx->parsed.vout_value = 0L; 212 7328 : ctx->raw[ctx->offset] = buf[i]; 213 7328 : ctx->parsed.vout_value += (uint64_t)buf[i] << 8 * ctx->offset++; 214 7328 : if (ctx->offset == BTCTX_OUTPUT_VALUE_SIZE) { 215 916 : ctx->raw_size = BTCTX_OUTPUT_VALUE_SIZE; 216 916 : ctx->callback(BTCTX_EV_VOUT_VALUE); 217 916 : ctx->state = BTCTX_ST_VOUT_SLENGTH; 218 916 : svarint_init(&ctx->parsed.varint); 219 : } 220 7328 : break; 221 1396 : case BTCTX_ST_LOCK_TIME: 222 1396 : if (ctx->offset == 0) 223 349 : ctx->parsed.locktime = 0; 224 1396 : ctx->raw[ctx->offset] = buf[i]; 225 1396 : ctx->parsed.locktime += (uint32_t)buf[i] << (8 * ctx->offset++); 226 1396 : if (ctx->offset == BTCTX_LOCKTIME_SIZE) { 227 349 : ctx->raw_size = BTCTX_LOCKTIME_SIZE; 228 349 : ctx->callback(BTCTX_EV_LOCKTIME); 229 349 : ctx->state = BTCTX_ST_DONE; 230 349 : return i + 1; 231 : } 232 1047 : break; 233 0 : default: 234 0 : return 0; 235 : } 236 : } 237 : 238 450200 : return len; 239 : }