btcs

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

commit 8cb4e6f3311178f0099f637ac1e2eb69a92987d1
parent 70fb50ba8ea67b45281813d6a3effb22fd2a4464
Author: William Casarin <jb55@jb55.com>
Date:   Mon,  3 Jun 2019 10:27:38 -0700

some initial hashing stuff

Diffstat:
MMakefile | 5++++-
Malloc.c | 2+-
Mconsts.h | 2+-
Mmain.c | 2+-
Mscript.c | 62+++++++++++++++++++++++++++++++++++++++++++-------------------
Mscript.h | 4++--
Mval.c | 25+++++++++++++++----------
Mval.h | 4++--
8 files changed, 69 insertions(+), 37 deletions(-)

diff --git a/Makefile b/Makefile @@ -7,6 +7,9 @@ DEPS=script.c \ val.c \ alloc.c \ script_num.c \ + sha256.c \ + ripemd160.c \ + compiler.c \ stack.c CLIDEPS=parser.tab.c \ @@ -65,7 +68,7 @@ $(BIN): $(OBJS) $(CLIOBJS) run_tests: $(OBJS) $(TESTOBJS) $(CC) $(CFLAGS) -o $@ $(OBJS) $(TESTOBJS) -test: run_tests $(BIN) +check: run_tests $(BIN) @./run_tests clean: diff --git a/alloc.c b/alloc.c @@ -84,7 +84,7 @@ byte_pool_get(int ind, u32 *len) { u32 *up; vp = g_arenas.bytes_map.bottom + ind; p = (u8*)(*vp); - assert((g_arenas.bytes_top - g_arenas.bytes + *len) <= g_arenas.nbytes); + //assert((g_arenas.bytes_top - g_arenas.bytes + *len) <= g_arenas.nbytes); assert(p); up = (u32*)p; *len = *up++; diff --git a/consts.h b/consts.h @@ -3,7 +3,7 @@ #define BTCS_CONSTS_H // Maximum number of bytes pushable to the stack -static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; +#define MAX_SCRIPT_ELEMENT_SIZE 520 // Maximum number of non-push operations per script static const int MAX_OPS_PER_SCRIPT = 201; diff --git a/main.c b/main.c @@ -51,7 +51,7 @@ int main(int argc, const char *argv[]) { /* size = g_reader_buf_top - g_reader_buf; */ printf("script "); script_print_vals(&g_reader_stack); - script_serialize(&g_reader_stack, buf, bufsize, &compiled_len); + script_serialize_minimal(&g_reader_stack, buf, bufsize, &compiled_len); script_eval(buf, compiled_len, &tmp_stack, &result); printf("script_hex "); diff --git a/script.c b/script.c @@ -5,6 +5,8 @@ #include "stack.h" #include "alloc.h" #include "valstack.h" +#include "sha256.h" +#include "ripemd160.h" #include <stdio.h> /* #define SCRIPTERR(serr) script_add_error(c, opcode, serr) */ @@ -117,6 +119,7 @@ script_eval(const u8 *script, size_t script_size, struct stack *stack, const u8 *p = script; const u8 *top = script + script_size; static char tmpbuf[32]; + static u8 tmpbytes[MAX_SCRIPT_ELEMENT_SIZE]; enum opcode opcode; struct val val_true = val_from_int(1); struct val val_false = val_from_int(0); @@ -653,32 +656,42 @@ script_eval(const u8 *script, size_t script_size, struct stack *stack, case OP_HASH160: case OP_HASH256: { - SCRIPTERR("unhandled hash opcode"); // (in -- hash) - /* if (stack_size(stack) < 1) */ - /* SCRIPTERR("script_err_invalid_stack_operation"); */ + if (stack_size(stack) < 1) + SCRIPTERR("script_err_invalid_stack_operation"); + + u16 hashind; + u32 valsize; + u32 hashlen = + (opcode == OP_RIPEMD160 || opcode == OP_SHA1 || + opcode == OP_HASH160) ? 20 : 32; - /* u16 hashind; */ - /* u32 hashlen = */ - /* (opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160) */ - /* ? 20 : 32; */ + struct val v = stack_top_val(stack, -1); - /* struct val val = stack_top_val(stack, -1); */ - /* struct val hash = byte_pool_new(hashlen, &hashind); */ + val_bytes(v, &valsize, tmpbytes, sizeof(tmpbytes)); + u8 *hash = byte_pool_new(hashlen, &hashind); - /* if (opcode == OP_RIPEMD160) */ - /* ripemd160() */ + if (opcode == OP_RIPEMD160) { + ripemd160((struct ripemd160*)hash, tmpbytes, valsize); + } + else if (opcode == OP_SHA256) { + sha256((struct sha256*)hash, tmpbytes, valsize); + } + else + SCRIPTERR("unhandled hash opcode"); /* cripemd160().write(vch.data(), vch.size()).finalize(vchhash.data()); */ /* else if (opcode == op_sha1) */ /* csha1().write(vch.data(), vch.size()).finalize(vchhash.data()); */ /* else if (opcode == op_sha256) */ /* csha256().write(vch.data(), vch.size()).finalize(vchhash.data()); */ - /* else if (opcode == op_hash160) */ - /* chash160().write(vch.data(), vch.size()).finalize(vchhash.data()); */ /* else if (opcode == op_hash256) */ /* chash256().write(vch.data(), vch.size()).finalize(vchhash.data()); */ - /* popstack(stack); */ - /* stack.push_back(vchhash); */ + + v.ind = hashind; + v.type = VT_RAW; + + stack_pop(stack); + stack_push_val(stack, v); } break; @@ -788,9 +801,9 @@ 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) { +void script_serialize_(struct stack *stack, u8 *buf, int buflen, + int* len, int serialize_minimal) +{ struct val *valp; void **sp; u8 *p = buf; @@ -802,7 +815,8 @@ script_serialize(struct stack *stack, u8 *buf, int buflen, int* len) { /* printf("%02x %02x %02x %02x | ", huh[0], huh[1], huh[2], huh[3]); */ /* printf("%d %d\n", val.type, val.ind); */ valp = (struct val*)sp; - val_serialize(*valp, &valsize, p, buflen-(p-buf)); + val_serialize(*valp, &valsize, p, buflen-(p-buf), + serialize_minimal); p += valsize; *len += valsize; assert(p-buf <= buflen); @@ -813,3 +827,13 @@ script_serialize(struct stack *stack, u8 *buf, int buflen, int* len) { void script_handle_input(struct stack *stack, const char *str) { } + +void script_serialize(struct stack *stack, u8 *buf, int buflen, int* len) +{ + script_serialize_(stack, buf, buflen, len, 0); +} + +void script_serialize_minimal(struct stack *stack, u8 *buf, int buflen, int* len) +{ + script_serialize_(stack, buf, buflen, len, 1); +} diff --git a/script.h b/script.h @@ -21,8 +21,8 @@ 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); +void script_serialize(struct stack *stack, u8 *buf, int buflen, int* len); +void script_serialize_minimal(struct stack *stack, u8 *buf, int buflen, int* len); extern int g_silence_script_err; extern int g_silence_script_warn; diff --git a/val.c b/val.c @@ -27,8 +27,15 @@ val_from_int(s64 intval) { return val; } -void -val_serialize(struct val val, u32 *len, u8 *buf, int bufsize) { +// TODO maybe replace this with serialize +void val_bytes(struct val val, u32 *len, u8 *buf, int bufsize) { + if (val.type == VT_DATA) + val.type = VT_RAW; + static const int serialize_minimal = 0; + val_serialize(val, len, buf, bufsize, serialize_minimal); +} + +void val_serialize(struct val val, u32 *len, u8 *buf, int bufsize, int serialize_minimal) { struct num *sn; int n; u16 valsize; @@ -37,8 +44,7 @@ val_serialize(struct val val, u32 *len, u8 *buf, int bufsize) { sn = num_pool_get(val.ind); assert(sn); - /// TODO: if serialize_minimal - if (1) { + if (serialize_minimal) { if (sn->val == -1) { *len = 1; *buf = OP_1NEGATE; return; } if (sn->val == 0 ) { *len = 1; *buf = 0; return; } if (sn->val >= 1 && sn->val <= 16 ) { @@ -47,10 +53,9 @@ val_serialize(struct val val, u32 *len, u8 *buf, int bufsize) { return; } } - sn_serialize(sn, buf+1, bufsize - 1, &valsize); + sn_serialize(sn, buf, bufsize, &valsize); assert(valsize <= 0xFF); - *buf = (u8)valsize; - *len = valsize + 1; + *len = valsize; return; case VT_OP: *len = 1; @@ -125,8 +130,8 @@ val_eq(struct val a, struct val b, int require_minimal) { // TODO: do I need to serialize to compare? /* abytes = val_serialize(a, &alen, require_minimal); */ /* bbytes = val_serialize(b, &blen, require_minimal); */ - val_serialize(a, &alen, tmpa, tmpsize); - val_serialize(b, &blen, tmpb, tmpsize); + val_serialize(a, &alen, tmpa, tmpsize, 0); + val_serialize(b, &blen, tmpb, tmpsize, 0); // TODO: what if they're semantically equivalent? or does that matter // (eg. minimal vs not miniminal)? @@ -170,7 +175,7 @@ val_size(struct val val) { switch (val.type) { case VT_DATA: { - u8 *data = byte_pool_get(val.ind, &len); + byte_pool_get(val.ind, &len); return len; } default: diff --git a/val.h b/val.h @@ -38,8 +38,8 @@ u32 val_size(struct val val); int val_eq(struct val a, struct val b, int require_minimal); -void -val_serialize(struct val val, u32 *len, u8 *buf, int bufsize); +void val_serialize(struct val val, u32 *len, u8 *buf, int bufsize, int serialize_minimal); +void val_bytes(struct val val, u32 *len, u8 *buf, int bufsize); struct val val_from_int(s64);