btcs

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

commit 5f236ed0bfcaaad0f1af33a0d99985b57395d1a5
parent 60d748d3e15ba89806c77207e69e039ae03facc3
Author: William Casarin <jb55@jb55.com>
Date:   Wed, 27 Dec 2017 21:25:42 -0800

script: implement raw, inline script data

One down side is that you don't see the decompiled ops like you get with
bitcoin-tx. Perhaps I should run VT_RAW through a decompilation phase after
that's implemented.

Closes #20

Diffstat:
Mlexer.l | 17++++++++++++++---
Mop.c | 7+++++++
Mparser.y | 5++++-
Mscript.c | 14+++++++++-----
Mscript.h | 5+++--
Mval.c | 6++++++
Mval.h | 1+
7 files changed, 44 insertions(+), 11 deletions(-)

diff --git a/lexer.l b/lexer.l @@ -31,12 +31,23 @@ return T_STR; } +0x[a-fA-F0-9]+ { + char * t = yytext + 2; + if (strlen(t) % 2 != 0) { + yylval.str = "Invalid raw string, it must have even length"; + return T_ERR; + } + yylval.str = t; + return T_RAW; +} + @[a-fA-F0-9]+ { - if (strlen(yytext + 1) % 2 != 0) { - yylval.str = "Invalid data string, byte string must have even length"; + char *t = yytext + 1; + if (strlen(t) % 2 != 0) { + yylval.str = "Invalid data string, it must have even length"; return T_ERR; } - yylval.str = yytext + 1; + yylval.str = t; return T_DATA; } diff --git a/op.c b/op.c @@ -381,6 +381,13 @@ val_print(struct val val) { print_bytes(data, len, 0); break; } + case VT_RAW: { + u32 len; + u8 *data = byte_pool_get(val.ind, &len); + printf("0x"); + print_bytes(data, len, 0); + break; + } default: assert(!"val_print data"); } diff --git a/parser.y b/parser.y @@ -23,6 +23,7 @@ void yyerror(const char* s); %token T_INT %token T_VAL %token T_DATA +%token T_RAW %token T_STR %token T_COMMENT %token T_ERR @@ -31,6 +32,7 @@ void yyerror(const char* s); %type<opcode> T_OP %type<integer> T_INT %type<str> T_DATA +%type<str> T_RAW %type<str> T_STR %type<val> T_VAL %type<str> T_EXAMPLE @@ -46,10 +48,11 @@ script: line: T_NEWLINE | T_COMMENT + | T_RAW { script_push_raw(&g_reader_stack, $1); } | T_INT { script_push_int(&g_reader_stack, $1); } | T_VAL { stack_push_val(&g_reader_stack, $1); } | T_OP { stack_push_op(&g_reader_stack, $1); } - | T_DATA { script_push_datastr(&g_reader_stack, $1); } + | T_DATA { script_push_datastr(&g_reader_stack, $1, 0); } | T_STR { script_push_str(&g_reader_stack, $1); } | T_ERR { parse_error($1); } | T_EXAMPLE { script_handle_input(&g_reader_stack, $1); } diff --git a/script.c b/script.c @@ -437,7 +437,6 @@ script_eval(const u8 *script, size_t script_size, struct stack *stack, struct val val = stack_top_val(stack, (-(n->val))-1); if (opcode == OP_ROLL) stack_erase(stack, -(n->val) - 1); - /* stack.erase(stack.end()-n-1); */ stack_push_val(stack, val); } break; @@ -733,7 +732,6 @@ void script_print_vals(struct stack *stack) { putchar('\n'); } - void script_push_int(struct stack *script, s64 intval) { /* u16 len; */ @@ -748,7 +746,7 @@ script_push_int(struct stack *script, s64 intval) { void -script_push_str(struct stack *script, char *str) { +script_push_str(struct stack *script, const char *str) { struct val val; u16 ind; u8 *bytes; @@ -762,7 +760,7 @@ script_push_str(struct stack *script, char *str) { } void -script_push_datastr(struct stack *script, const char *str) { +script_push_datastr(struct stack *script, const char *str, int raw) { int count = 0; u8 *bytes; const char *p = str; @@ -778,7 +776,7 @@ script_push_datastr(struct stack *script, const char *str) { p += 2; } - val.type = VT_DATA; + val.type = raw ? VT_RAW : VT_DATA; val.ind = ind; stack_push_val(script, val); @@ -786,6 +784,12 @@ script_push_datastr(struct stack *script, const char *str) { void +script_push_raw(struct stack *stack, const char *data) { + script_push_datastr(stack, data, 1); +} + + +void script_serialize(struct stack *stack, u8 *buf, int buflen, int* len) { struct val *valp; void **sp; diff --git a/script.h b/script.h @@ -17,8 +17,9 @@ void script_print_ops(char * buf, size_t size); void script_print_vals(struct stack *); void script_push_int(struct stack *, s64); -void script_push_str(struct stack *script, char *str); -void script_push_datastr(struct stack *, const char *str); +void script_push_str(struct stack *script, const char *str); +void script_push_raw(struct stack *, const char *str); +void script_push_datastr(struct stack *, const char *str, int israw); void script_serialize(struct stack *stack, u8 *buf, int buflen, int* len); diff --git a/val.c b/val.c @@ -56,6 +56,12 @@ val_serialize(struct val val, u32 *len, u8 *buf, int bufsize) { *len = 1; *buf = val.ind & 0xFF; return; + case VT_RAW: { + u8 *p; + p = byte_pool_get(val.ind, len); + memcpy(buf, p, *len); + return; + } case VT_DATA: { u8 *p; p = byte_pool_get(val.ind, len); diff --git a/val.h b/val.h @@ -9,6 +9,7 @@ enum valtype { VT_SCRIPTNUM=0, VT_SMALLINT, VT_OP, + VT_RAW, VT_DATA, VT_N };