btcs

bitcoin script parser/evaluator/compiler/decompiler
git clone git://jb55.com/btcs
Log | Files | Refs | README | LICENSE

commit f69017607010372aaecdf65e4aca6ed5b25bf846
parent 9005e5c975d57701622880ac9ff93fecf92f2e6b
Author: William Casarin <jb55@jb55.com>
Date:   Wed, 19 Jun 2019 00:36:33 -0700

decode: parse more bad inputs

it will try to parse until it can't any longer, and then it
will continue to print the remaining line.

This is useful for things like:

bitcoin-iterate -q --cache=cache --output=$'%os,%th' \
  --start 500000 --blockdir=/zbig/bitcoin2/blocks \
    | btcs -a -d \
    | awk -F, '!x[$1]++'

HASH160 data(20) EQUAL,2157b554dcfda405233906e461ee593875ae4b1b97615872db6a25130ecc1dd6
RETURN data(36),2157b554dcfda405233906e461ee593875ae4b1b97615872db6a25130ecc1dd6
DUP HASH160 data(20) EQUALVERIFY CHECKSIG,1024cb12a576b69defa67dbc2f1899700ab58e5ad3d5e058edefb907f59865bc
RETURN data(20),8662e51ae3e9a8a050dc958a95ea27015107388ba212e483755121427e7ba2b7
0 data(20),761619410d9f2a7fa69336583a0351dd86caf9ed2cee8765132a93caa44f77de
0 data(32),577819ae38ccd0d2b931aeec4f83801ad3c42b3158d4ceb4874f2ef482f1d805
RETURN data(17),af41a3eb6505c08003195be6affd3961e45278b45d58d0a427532eeb67501353

Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Mmain.c | 20+++++++++++++-------
Mscript.c | 9++++++---
Mutil.c | 21++++++++++++---------
Mutil.h | 2+-
4 files changed, 32 insertions(+), 20 deletions(-)

diff --git a/main.c b/main.c @@ -125,15 +125,16 @@ static void fail(int err, const char *msg) } -static int decompile(const char *str, int strlen, bool abbrev_data) +static int decompile(const char *str, size_t *strlen, bool abbrev_data) { static u8 buf[10000]; - if (strlen % 2 != 0) + hex_decode(str, strlen, buf, sizeof(buf)); + + if (*strlen % 2 != 0) return 0; - hex_decode(str, strlen, buf, sizeof(buf)); - size_t nbytes = strlen / 2; + size_t nbytes = *strlen / 2; script_print(buf, nbytes, abbrev_data); @@ -203,14 +204,18 @@ int main(int argc, const char *argv[]) if (is_decompile) { // we have stdin char *line = NULL; - ssize_t len = 0; + ssize_t len = 0, prevlen; size_t n; int ok; bool failed = false; if (input == NULL) { while ((len = getline(&line, &n, stdin)) != -1) { - ok = decompile(line, len-1, abbrev_data); + len--; + prevlen = len; + ok = decompile(line, (size_t*)&len, abbrev_data); + + printf("%.*s\n", (int)(prevlen - len), line+len); if (!ok) { failed = true; @@ -224,7 +229,8 @@ int main(int argc, const char *argv[]) if (!ok) fail(4, "failed to read input arg (too big?)"); - ok = decompile((const char *)buf, written, abbrev_data); + ok = decompile((const char *)buf, &written, abbrev_data); + printf("\n"); if (!ok) { fprintf(stderr, "failed to decompile\n"); diff --git a/script.c b/script.c @@ -755,24 +755,27 @@ void script_print(const u8 *script, size_t script_size, int abbrev_data) { static u8 tmpbuf[4096]; const u8 *p = script; const u8 *top = script + script_size; + bool first = true; while (p < top) { enum opcode opcode; script_getop(&p, top, &opcode, tmpbuf, sizeof(tmpbuf), &len); + if (!first) + putchar(' '); + first = false; + if (is_push_data(opcode)) { if (abbrev_data) printf("data(%d)", len); else hex_print(tmpbuf, len); - printf(" "); } else - printf("%s ", op_name(opcode)); + printf("%s", op_name(opcode)); len = 0; } - printf("\n"); } void script_print_vals(struct stack *stack) { diff --git a/util.c b/util.c @@ -1,6 +1,7 @@ #include "util.h" #include <errno.h> +#include <assert.h> static bool char_to_hex(unsigned char *val, char c) { @@ -19,22 +20,25 @@ static bool char_to_hex(unsigned char *val, char c) return false; } -bool hex_decode(const char *str, size_t slen, void *buf, size_t bufsize) +bool hex_decode(const char *str, size_t *slen, void *buf, size_t bufsize) { unsigned char v1, v2; unsigned char *p = buf; + int len = 0; - while (slen > 1) { - if (!char_to_hex(&v1, str[0]) || !char_to_hex(&v2, str[1])) - return false; - if (!bufsize) + while (*slen > 1) { + if (!bufsize || !char_to_hex(&v1, str[0]) || !char_to_hex(&v2, str[1])) { + *slen = len; return false; + } *(p++) = (v1 << 4) | v2; str += 2; - slen -= 2; + *slen -= 2; bufsize--; + len += 2; } - return slen == 0 && bufsize == 0; + *slen = len; + return *slen == 0 && bufsize == 0; } @@ -109,13 +113,12 @@ ssize_t getline(char **lineptr, size_t *n, FILE *stream) { int read_arg_or_stdin(const char *arg, unsigned char *buf, size_t buflen, size_t *written) { - unsigned char dummy; if (arg != NULL) { unsigned char *p = buf; bool done = false; for (size_t i = 0; i < buflen; i++) { *p = arg[i]; - if (*p == 0 || !char_to_hex(&dummy, *p)) { + if (*p == 0 ) { done = true; break; } diff --git a/util.h b/util.h @@ -11,7 +11,7 @@ typedef intptr_t ssize_t; int read_arg_or_stdin(const char *arg, unsigned char *buf, size_t buflen, size_t *written); -bool hex_decode(const char *str, size_t slen, void *buf, size_t bufsize); +bool hex_decode(const char *str, size_t *slen, void *buf, size_t bufsize); ssize_t getline(char **lineptr, size_t *n, FILE *stream); #endif /* UTIL_H */