├── .dir-locals.el ├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── alloc.c ├── alloc.h ├── btcs.1 ├── compiler.c ├── compiler.h ├── consts.h ├── default.nix ├── deps └── tap.c │ ├── package.json │ ├── tap.c │ └── tap.h ├── doc └── TODO.org ├── endian.h ├── examples └── htlc ├── lexer.l ├── main.c ├── misc.h ├── mph-opcodes ├── op.c ├── op.h ├── opcodes ├── oplookup.c ├── oplookup.h ├── parser.y ├── ripemd160.c ├── ripemd160.h ├── script.c ├── script.h ├── script_num.c ├── script_num.h ├── sha256.c ├── sha256.h ├── stack.c ├── stack.h ├── test.c ├── test ├── run └── tests.csv ├── util.c ├── util.h ├── val.c ├── val.h └── valstack.h /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ((c-mode . ((c-file-style . "linux") 2 | (indent-tabs-mode . t) 3 | (show-trailing-whitespace . t) 4 | (c-basic-offset . 8) 5 | (tab-width . 8) 6 | )) 7 | ) 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | /parser.tab.h 3 | /parser.tab.c 4 | /lex.yy.c 5 | /btcs 6 | /TAGS 7 | *.d 8 | /run_tests 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | script: make && make check 3 | compiler: 4 | - clang 5 | - gcc 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017, William Casarin 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-g -DHAVE_LITTLE_ENDIAN -O2 -Ideps -std=c99 -Wall -Wextra -Werror -Wno-unused-variable -Wno-unused-function 2 | 3 | DEPS=script.c \ 4 | oplookup.c \ 5 | op.c \ 6 | val.c \ 7 | alloc.c \ 8 | script_num.c \ 9 | sha256.c \ 10 | ripemd160.c \ 11 | compiler.c \ 12 | util.c \ 13 | stack.c 14 | 15 | CLIDEPS=parser.tab.c \ 16 | lex.yy.c \ 17 | main.c 18 | 19 | # DEPS=oplookup.h script.h misc.h Makefile op.h stack.h 20 | OBJS=$(DEPS:.c=.o) 21 | CLIOBJS=$(CLIDEPS:.c=.o) 22 | 23 | GEN=parser.tab.c \ 24 | parser.tab.h \ 25 | lex.yy.c \ 26 | oplookup.c \ 27 | oplookup.h \ 28 | $(OBJS) \ 29 | $(CLIOBJS) \ 30 | 31 | 32 | PREFIX ?= /usr/local 33 | BIN=btcs 34 | 35 | all: $(BIN) 36 | 37 | include $(OBJS:.o=.d) 38 | include $(CLIOBJS:.o=.d) 39 | 40 | op.c: oplookup.h oplookup.c 41 | 42 | %.d: %.c 43 | @rm -f $@; \ 44 | $(CC) -MM $(CFLAGS) $< > $@ 45 | 46 | oplookup.c oplookup.h: opcodes mph-opcodes 47 | @./mph-opcodes opcodes 48 | 49 | parser.tab.c parser.tab.h: parser.y 50 | bison -d parser.y 51 | 52 | lex.yy.c: lexer.l parser.tab.h 53 | flex lexer.l 54 | 55 | install: $(BIN) 56 | mkdir -p $(PREFIX)/bin 57 | mkdir -p $(PREFIX)/share/btcs 58 | cp $(BIN) $(PREFIX)/bin 59 | cp btcs.1 $(PREFIX)/share/btcs 60 | 61 | $(BIN): $(OBJS) $(CLIOBJS) 62 | $(CC) $(CFLAGS) -o $@ $(OBJS) $(CLIOBJS) 63 | 64 | 65 | check: $(BIN) fake 66 | @sh -c "cd test && ./run" 67 | 68 | clean: fake 69 | rm -f $(GEN) 70 | rm -f *.d 71 | 72 | TAGS: fake 73 | etags -o - *.c > $@ 74 | 75 | tags: fake 76 | ctags *.c 77 | 78 | .PHONY: fake 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # btcs 3 | 4 | [![Build Status](https://travis-ci.org/jb55/btcs.svg)](https://travis-ci.org/jb55/btcs) 5 | 6 | bitcoin script parser/evaluator/compiler/decompiler 7 | 8 | **WARNING**: This is not a consensus-critical implementation of 9 | bitcoin script. Make sure to actually test your script on testnet or 10 | with something like [btcdeb](https://github.com/kallewoof/btcdeb). 11 | 12 | ## Motivation 13 | 14 | I wanted a better way to hack on Bitcoin scripts 15 | 16 | ## Installing 17 | 18 | deps: `python3`, `bison`, `flex`, a C compiler 19 | 20 | $ make install 21 | 22 | with nix: 23 | 24 | $ nix-env -if . 25 | 26 | ## TODOs 27 | 28 | - [X] Tokenizer 29 | - [ ] Evaluator (partially complete) 30 | - [X] Compiler 31 | - [X] Decompiler 32 | - [X] Docs 33 | 34 | ## Usage 35 | 36 | Work in progress. Some OPs are working: 37 | 38 | ``` 39 | $ btcs 1 2 16 3dup 2swap 40 | 41 | script 1 2 16 OP_3DUP OP_2SWAP 42 | script_hex 5152606f72 43 | stack 1 2 2 16 16 1 44 | stack_hex 010202101001 45 | results success 46 | ``` 47 | -------------------------------------------------------------------------------- /alloc.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | #include 6 | #include "alloc.h" 7 | #include "stack.h" 8 | 9 | static struct arenas g_arenas; 10 | 11 | void 12 | alloc_arenas() { 13 | alloc_arena_sizes(0, MAX_STACK_SIZE, MAX_STACK_SIZE * MAX_STACK_SIZE); 14 | } 15 | 16 | void 17 | alloc_arena_sizes(struct arenas *arenas, const int nums, const int bytes) { 18 | if (!arenas) arenas = &g_arenas; 19 | arenas->nums = (struct num*)calloc(nums, sizeof(struct num)); 20 | assert(arenas->nums); 21 | arenas->bytes = (u8*)calloc(bytes, 1); 22 | stack_init_size(&arenas->bytes_map, bytes); 23 | arenas->bytes_top = arenas->bytes; 24 | arenas->num_count = 0; 25 | arenas->nbytes = bytes; 26 | } 27 | 28 | struct num * 29 | num_pool_get(const u16 ind) { 30 | return &g_arenas.nums[ind]; 31 | } 32 | 33 | 34 | struct num * 35 | num_pool_pop() { 36 | assert(g_arenas.num_count > 0); 37 | return &g_arenas.nums[g_arenas.num_count--]; 38 | } 39 | 40 | 41 | struct num * 42 | num_pool_new(u16 *ind) { 43 | *ind = g_arenas.num_count++; 44 | struct num *p; 45 | p = &g_arenas.nums[*ind]; 46 | assert(p); 47 | assert(p->val == 0 && p->ind == 0); 48 | p->ind = *ind; 49 | return p; 50 | } 51 | 52 | unsigned char *byte_pool_new(u32 len, u16 *ind) { 53 | assert((g_arenas.bytes_top - g_arenas.bytes + len) <= g_arenas.nbytes); 54 | u8 *start = g_arenas.bytes_top; 55 | u32 *c = (u32*)g_arenas.bytes_top; 56 | *c++ = len; 57 | u8 *p = (u8*)c; 58 | p += len; 59 | *ind = stack_size(&g_arenas.bytes_map); 60 | stack_push(&g_arenas.bytes_map, (void*)start); 61 | g_arenas.bytes_top = p; 62 | assert(*p == 0); 63 | assert(((g_arenas.bytes_top - g_arenas.bytes) + len) <= g_arenas.nbytes); 64 | return p - len; 65 | } 66 | 67 | 68 | // useful for quick alloc/deallocs 69 | u8 * 70 | byte_pool_pop() { 71 | u8 *p = (u8*)stack_pop(&g_arenas.bytes_map); 72 | u32 *c = (u32*)p; 73 | memset(p, 0, *c + sizeof(u32)); 74 | return p; 75 | } 76 | 77 | 78 | u8 * 79 | byte_pool_get(int ind, u32 *len) { 80 | assert(ind <= stack_size(&g_arenas.bytes_map) - 1); 81 | void **vp; 82 | u8 *p; 83 | u32 *up; 84 | vp = g_arenas.bytes_map.bottom + ind; 85 | p = (u8*)(*vp); 86 | //assert((g_arenas.bytes_top - g_arenas.bytes + *len) <= g_arenas.nbytes); 87 | assert(p); 88 | up = (u32*)p; 89 | *len = *up++; 90 | p = (u8*)up; 91 | assert((g_arenas.bytes_top - g_arenas.bytes + *len) <= g_arenas.nbytes); 92 | return p; 93 | } 94 | 95 | void 96 | free_arenas(struct arenas *arenas) { 97 | if (!arenas) arenas = &g_arenas; 98 | if (!arenas) return; 99 | stack_free(&arenas->bytes_map); 100 | free(arenas->bytes); 101 | free(arenas->nums); 102 | } 103 | 104 | -------------------------------------------------------------------------------- /alloc.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef BTCS_ALLOC_H 3 | #define BTCS_ALLOC_H 4 | 5 | #include "consts.h" 6 | #include "script_num.h" 7 | #include "misc.h" 8 | 9 | // MAX_OPS_PER_SCRIPT * 10 | #define MAX_PUSHDATA_REFS (MAX_OPS_PER_SCRIPT * MAX_STACK_SIZE) 11 | #define ALLOC_PUSHDATA_BYTES (MAX_STACK_SIZE * MAX_OPS_PER_SCRIPT) 12 | 13 | struct num * num_pool_new(u16 *ind); 14 | struct num * num_pool_pop(); 15 | struct num * num_pool_get(const u16 ind); 16 | 17 | u8 *byte_pool_new(u32 len, u16 *ind); 18 | u8 *byte_pool_get(int ind, u32 *len); 19 | u8 *byte_pool_pop(); 20 | 21 | struct arenas { 22 | struct num *nums; 23 | u8 *bytes; 24 | u8 *bytes_top; 25 | struct stack bytes_map; 26 | int nbytes; 27 | int num_count; 28 | }; 29 | 30 | void alloc_arena_sizes(struct arenas *, const int nums, const int bytes); 31 | void alloc_arenas(); 32 | void free_arenas(struct arenas *arenas); 33 | 34 | #endif /* BTCS_ALLOC_H */ 35 | -------------------------------------------------------------------------------- /btcs.1: -------------------------------------------------------------------------------- 1 | .de dT 2 | .ds Dt \\$2 3 | .. 4 | .dT Time-stamp: "2019-06-13" 5 | .TH BTCS 1 \*(Dt "btcs" "User Commands" 6 | .SH NAME 7 | btcs \- A Bitcoin script compiler, evaluator and decompiler 8 | .SH SYNOPSIS 9 | .B btcs 10 | [\fI\,OPTION\/\fR]... -d or [\fI\,EXPRS\/\fR]... 11 | 12 | .SH DESCRIPTION 13 | btcs accepts bitcoin script over stdin or as arguments 14 | 15 | .SH DECOMPILER OPTIONS 16 | 17 | .TP 18 | .BR \-d ", " \-\^\-decompile 19 | Decompile a hex string representing bitcoin script 20 | 21 | .TP 22 | .BR \-a ", " \-\^\-abbreviate-data 23 | Abbreviate data pushes when printing script data. 24 | .br 25 | For example, hashes would appear as 26 | .B data(20) 27 | and 28 | .B data(32) 29 | 30 | .SH COMPILER OPTIONS 31 | 32 | .TP 33 | .BR {-,+}l ", " \-\^\-{hide,show}-labels 34 | Hide or show labels such as "script" and "script_hex". 35 | .br 36 | This will default to 37 | .B hide 38 | when there is only one printed output 39 | 40 | .TP 41 | .BR \-s ", " \-\^\-script 42 | Print the interpreted script 43 | 44 | .TP 45 | .BR \-s ", " \-\^\-script-hex 46 | Print the hex form of the script 47 | 48 | .TP 49 | .BR \-t ", " \-\^\-stack 50 | Print the stack output 51 | 52 | .TP 53 | .BR \-th ", " \-\^\-stack-hex 54 | Print the stack output as hex 55 | 56 | .TP 57 | .BR \-r ", " \-\^\-result 58 | Print the evaluation result 59 | 60 | 61 | .SH EXPRS 62 | 63 | .SS @ 64 | .br 65 | Prepends a minimal PUSHDATA op with the length of the hex string, and then pushes the hex data 66 | .br 67 | eg: @ffabcd 68 | 69 | .SS OPCODE 70 | .br 71 | A bitcoin opcode in the form OP_ or 72 | 73 | .SS SCRIPTNUM 74 | .br 75 | Literal integers, which get converted to script nums (bitcoin script's number format) 76 | .br 77 | eg: 1 2 3 -1 2147483648 78 | 79 | .SS RAW BYTES 80 | .br 81 | Literal raw bytes, which may or may not be valid script. 82 | .br 83 | eg: pushdata1 0x02 0x0102 84 | .br 85 | You could use this for manual or non-minimal pushdata 86 | 87 | .SH EXAMPLES 88 | 89 | .SS 90 | Basic example 91 | .br 92 | $ btcs 1 2 add 93 | .br 94 | script 1 2 OP_ADD 95 | .br 96 | script_hex 515293 97 | .br 98 | stack 3 99 | .br 100 | stack_hex 03 101 | .br 102 | results success 103 | 104 | .SS 105 | Just compile 106 | .br 107 | $ btcs -sh hash160 @b472a266d0bd89c13706a4132ccfb16f7c3b9fcb equalverify 108 | .br 109 | a914b472a266d0bd89c13706a4132ccfb16f7c3b9fcb88 110 | 111 | 112 | .SH BUGS 113 | The evaluator isn't consensus-critical. Please test your scripts on testnet before use. 114 | 115 | .SH AUTHOR 116 | 117 | William Casarin 118 | .br 119 | Support my Bitcoin projects: bc1qthsruffh3qcn69hux2tcq87x95x8rmu4fdu9sm 120 | -------------------------------------------------------------------------------- /compiler.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "compiler.h" 4 | 5 | bool alignment_ok(const void *p, size_t n) 6 | { 7 | #if HAVE_UNALIGNED_ACCESS 8 | return true; 9 | #else 10 | return ((size_t)p % n == 0); 11 | #endif 12 | } 13 | -------------------------------------------------------------------------------- /compiler.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef COMPILER_H 3 | #define COMPILER_H 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | bool alignment_ok(const void *p, size_t n); 10 | 11 | #define UNUSED __attribute__((__unused__)) 12 | 13 | /** 14 | * BUILD_ASSERT - assert a build-time dependency. 15 | * @cond: the compile-time condition which must be true. 16 | * 17 | * Your compile will fail if the condition isn't true, or can't be evaluated 18 | * by the compiler. This can only be used within a function. 19 | * 20 | * Example: 21 | * #include 22 | * ... 23 | * static char *foo_to_char(struct foo *foo) 24 | * { 25 | * // This code needs string to be at start of foo. 26 | * BUILD_ASSERT(offsetof(struct foo, string) == 0); 27 | * return (char *)foo; 28 | * } 29 | */ 30 | #define BUILD_ASSERT(cond) \ 31 | do { (void) sizeof(char [1 - 2*!(cond)]); } while(0) 32 | 33 | /** 34 | * BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression. 35 | * @cond: the compile-time condition which must be true. 36 | * 37 | * Your compile will fail if the condition isn't true, or can't be evaluated 38 | * by the compiler. This can be used in an expression: its value is "0". 39 | * 40 | * Example: 41 | * #define foo_to_char(foo) \ 42 | * ((char *)(foo) \ 43 | * + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0)) 44 | */ 45 | #define BUILD_ASSERT_OR_ZERO(cond) \ 46 | (sizeof(char [1 - 2*!(cond)]) - 1) 47 | 48 | #define memclear(mem, size) memset(mem, 0, size) 49 | #define memclear_2(m1, s1, m2, s2) { memclear(m1, s1); memclear(m2, s2); } 50 | #define memclear_3(m1, s1, m2, s2, m3, s3) { memclear(m1, s1); memclear(m2, s2); memclear(m3, s3); } 51 | #define wally_clear memclear 52 | #define wally_clear_2 memclear_2 53 | #define wally_clear_3 memclear_3 54 | 55 | #endif /* COMPILER_H */ 56 | -------------------------------------------------------------------------------- /consts.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef BTCS_CONSTS_H 3 | #define BTCS_CONSTS_H 4 | 5 | // Maximum number of bytes pushable to the stack 6 | #define MAX_SCRIPT_ELEMENT_SIZE 520 7 | 8 | // Maximum number of non-push operations per script 9 | static const int MAX_OPS_PER_SCRIPT = 201; 10 | 11 | // Maximum number of public keys per multisig 12 | static const int MAX_PUBKEYS_PER_MULTISIG = 20; 13 | 14 | // Maximum script length in bytes 15 | static const int MAX_SCRIPT_SIZE = 10000; 16 | 17 | // Threshold for nLockTime: below this value it is interpreted as block number, 18 | // otherwise as UNIX timestamp. 19 | static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC 20 | 21 | 22 | #endif /* BTCS_CONSTS_H */ 23 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | { nixpkgs ? import {} 2 | , stdenv ? nixpkgs.stdenv 3 | , bison ? nixpkgs.bison 4 | , lib ? nixpkgs.lib 5 | , flex ? nixpkgs.flex 6 | , python3 ? nixpkgs.python3 7 | }: 8 | 9 | stdenv.mkDerivation rec { 10 | name = "btcs-${version}"; 11 | version = "0.1"; 12 | 13 | src = ./.; 14 | 15 | makeFlags = ["PREFIX=$(out)"]; 16 | 17 | nativeBuildInputs = [ bison flex python3 ]; 18 | 19 | patchPhase = '' 20 | patchShebangs mph-opcodes 21 | ''; 22 | 23 | meta = with lib; { 24 | description = "Bitcoin script evaluator"; 25 | homepage = "https://github.com/jb55/btcs"; 26 | maintainers = with maintainers; [ jb55 ]; 27 | license = licenses.mit; 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /deps/tap.c/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "tap.c", 3 | "version" : "0.0.1", 4 | "description" : "Write tap tests in C.", 5 | "src": [ "tap.c", "tap.h" ], 6 | "repository" : { 7 | "type" : "git", 8 | "url" : "git://github.com/thlorenz/tap.c.git" 9 | }, 10 | "homepage" : "https://github.com/thlorenz/tap.c", 11 | "dependencies" : { 12 | }, 13 | "keywords": ["tap", "test", "check", "tap.c" ] , 14 | "author" : { 15 | "name" : "Thorsten Lorenz", 16 | "email" : "thlorenz@gmx.de", 17 | "url" : "http://thlorenz.com" 18 | }, 19 | "license" : { 20 | "type": "GPLv2", 21 | "url": "https://github.com/thlorenz/tap.c/blob/master/COPYING" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /deps/tap.c/tap.c: -------------------------------------------------------------------------------- 1 | /* 2 | libtap - Write tests in C 3 | Copyright 2012 Jake Gelbman 4 | This file is licensed under the GPLv2 5 | */ 6 | 7 | #define _DEFAULT_SOURCE 1 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "tap.h" 14 | 15 | static int expected_tests = NO_PLAN; 16 | static int failed_tests; 17 | static int current_test; 18 | static char *todo_mesg; 19 | 20 | static char * 21 | vstrdupf (const char *fmt, va_list args) { 22 | char *str; 23 | int size; 24 | va_list args2; 25 | va_copy(args2, args); 26 | if (!fmt) 27 | fmt = ""; 28 | size = vsnprintf(NULL, 0, fmt, args2) + 2; 29 | str = malloc(size); 30 | if (!str) { 31 | perror("malloc error"); 32 | exit(1); 33 | } 34 | vsprintf(str, fmt, args); 35 | va_end(args2); 36 | return str; 37 | } 38 | 39 | void 40 | tap_plan (int tests, const char *fmt, ...) { 41 | expected_tests = tests; 42 | if (tests == SKIP_ALL) { 43 | char *why; 44 | va_list args; 45 | va_start(args, fmt); 46 | why = vstrdupf(fmt, args); 47 | va_end(args); 48 | printf("1..0 "); 49 | note("SKIP %s\n", why); 50 | exit(0); 51 | } 52 | if (tests != NO_PLAN) { 53 | printf("1..%d\n", tests); 54 | } 55 | } 56 | 57 | int 58 | vok_at_loc (const char *file, int line, int test, const char *fmt, 59 | va_list args) 60 | { 61 | char *name = vstrdupf(fmt, args); 62 | printf("%sok %d", test ? "" : "not ", ++current_test); 63 | if (*name) 64 | printf(" - %s", name); 65 | if (todo_mesg) { 66 | printf(" # TODO"); 67 | if (*todo_mesg) 68 | printf(" %s", todo_mesg); 69 | } 70 | printf("\n"); 71 | if (!test) { 72 | if (*name) 73 | diag(" Failed%s test '%s'\n at %s line %d.", 74 | todo_mesg ? " (TODO)" : "", name, file, line); 75 | else 76 | diag(" Failed%s test at %s line %d.", 77 | todo_mesg ? " (TODO)" : "", file, line); 78 | if (!todo_mesg) 79 | failed_tests++; 80 | } 81 | free(name); 82 | return test; 83 | } 84 | 85 | int 86 | ok_at_loc (const char *file, int line, int test, const char *fmt, ...) { 87 | va_list args; 88 | va_start(args, fmt); 89 | vok_at_loc(file, line, test, fmt, args); 90 | va_end(args); 91 | return test; 92 | } 93 | 94 | static int 95 | mystrcmp (const char *a, const char *b) { 96 | return a == b ? 0 : !a ? -1 : !b ? 1 : strcmp(a, b); 97 | } 98 | 99 | #define eq(a, b) (!mystrcmp(a, b)) 100 | #define ne(a, b) (mystrcmp(a, b)) 101 | 102 | int 103 | is_at_loc (const char *file, int line, const char *got, const char *expected, 104 | const char *fmt, ...) 105 | { 106 | int test = eq(got, expected); 107 | va_list args; 108 | va_start(args, fmt); 109 | vok_at_loc(file, line, test, fmt, args); 110 | va_end(args); 111 | if (!test) { 112 | diag(" got: '%s'", got); 113 | diag(" expected: '%s'", expected); 114 | } 115 | return test; 116 | } 117 | 118 | int 119 | isnt_at_loc (const char *file, int line, const char *got, const char *expected, 120 | const char *fmt, ...) 121 | { 122 | int test = ne(got, expected); 123 | va_list args; 124 | va_start(args, fmt); 125 | vok_at_loc(file, line, test, fmt, args); 126 | va_end(args); 127 | if (!test) { 128 | diag(" got: '%s'", got); 129 | diag(" expected: anything else"); 130 | } 131 | return test; 132 | } 133 | 134 | int 135 | cmp_ok_at_loc (const char *file, int line, int a, const char *op, int b, 136 | const char *fmt, ...) 137 | { 138 | int test = eq(op, "||") ? a || b 139 | : eq(op, "&&") ? a && b 140 | : eq(op, "|") ? a | b 141 | : eq(op, "^") ? a ^ b 142 | : eq(op, "&") ? a & b 143 | : eq(op, "==") ? a == b 144 | : eq(op, "!=") ? a != b 145 | : eq(op, "<") ? a < b 146 | : eq(op, ">") ? a > b 147 | : eq(op, "<=") ? a <= b 148 | : eq(op, ">=") ? a >= b 149 | : eq(op, "<<") ? a << b 150 | : eq(op, ">>") ? a >> b 151 | : eq(op, "+") ? a + b 152 | : eq(op, "-") ? a - b 153 | : eq(op, "*") ? a * b 154 | : eq(op, "/") ? a / b 155 | : eq(op, "%") ? a % b 156 | : diag("unrecognized operator '%s'", op); 157 | va_list args; 158 | va_start(args, fmt); 159 | vok_at_loc(file, line, test, fmt, args); 160 | va_end(args); 161 | if (!test) { 162 | diag(" %d", a); 163 | diag(" %s", op); 164 | diag(" %d", b); 165 | } 166 | return test; 167 | } 168 | 169 | static void 170 | vdiag_to_fh (FILE *fh, const char *fmt, va_list args) { 171 | char *mesg, *line; 172 | int i; 173 | if (!fmt) 174 | return; 175 | mesg = vstrdupf(fmt, args); 176 | line = mesg; 177 | for (i = 0; *line; i++) { 178 | char c = mesg[i]; 179 | if (!c || c == '\n') { 180 | mesg[i] = '\0'; 181 | fprintf(fh, "# %s\n", line); 182 | if (!c) 183 | break; 184 | mesg[i] = c; 185 | line = mesg + i + 1; 186 | } 187 | } 188 | free(mesg); 189 | return; 190 | } 191 | 192 | int 193 | diag (const char *fmt, ...) { 194 | va_list args; 195 | va_start(args, fmt); 196 | vdiag_to_fh(stderr, fmt, args); 197 | va_end(args); 198 | return 0; 199 | } 200 | 201 | int 202 | note (const char *fmt, ...) { 203 | va_list args; 204 | va_start(args, fmt); 205 | vdiag_to_fh(stdout, fmt, args); 206 | va_end(args); 207 | return 0; 208 | } 209 | 210 | int 211 | exit_status () { 212 | int retval = 0; 213 | if (expected_tests == NO_PLAN) { 214 | printf("1..%d\n", current_test); 215 | } 216 | else if (current_test != expected_tests) { 217 | diag("Looks like you planned %d test%s but ran %d.", 218 | expected_tests, expected_tests > 1 ? "s" : "", current_test); 219 | retval = 255; 220 | } 221 | if (failed_tests) { 222 | diag("Looks like you failed %d test%s of %d run.", 223 | failed_tests, failed_tests > 1 ? "s" : "", current_test); 224 | if (expected_tests == NO_PLAN) 225 | retval = failed_tests; 226 | else 227 | retval = expected_tests - current_test + failed_tests; 228 | } 229 | return retval; 230 | } 231 | 232 | int bail_out (const char *fmt, ...) { 233 | va_list args; 234 | va_start(args, fmt); 235 | printf("Bail out! "); 236 | vprintf(fmt, args); 237 | printf("\n"); 238 | va_end(args); 239 | exit(255); 240 | return 0; 241 | } 242 | 243 | void tap_skip (int n, const char *fmt, ...) { 244 | char *why; 245 | va_list args; 246 | va_start(args, fmt); 247 | why = vstrdupf(fmt, args); 248 | va_end(args); 249 | while (n --> 0) { 250 | printf("ok %d ", ++current_test); 251 | note("skip %s\n", why); 252 | } 253 | free(why); 254 | } 255 | 256 | void tap_todo (const char *fmt, ...) { 257 | va_list args; 258 | va_start(args, fmt); 259 | todo_mesg = vstrdupf(fmt, args); 260 | va_end(args); 261 | } 262 | 263 | void 264 | tap_end_todo () { 265 | free(todo_mesg); 266 | todo_mesg = NULL; 267 | } 268 | 269 | #ifndef _WIN32 270 | #include 271 | #include 272 | #include 273 | 274 | #if defined __APPLE__ || defined BSD 275 | #define MAP_ANONYMOUS MAP_ANON 276 | #endif 277 | 278 | /* Create a shared memory int to keep track of whether a piece of code executed 279 | dies. to be used in the dies_ok and lives_ok macros. */ 280 | int 281 | tap_test_died (int status) { 282 | static int *test_died = NULL; 283 | int prev; 284 | if (!test_died) { 285 | test_died = mmap(0, sizeof (int), PROT_READ | PROT_WRITE, 286 | MAP_SHARED | MAP_ANONYMOUS, -1, 0); 287 | *test_died = 0; 288 | } 289 | prev = *test_died; 290 | *test_died = status; 291 | return prev; 292 | } 293 | 294 | int 295 | like_at_loc (int for_match, const char *file, int line, const char *got, 296 | const char *expected, const char *fmt, ...) 297 | { 298 | int test; 299 | regex_t re; 300 | va_list args; 301 | int err = regcomp(&re, expected, REG_EXTENDED); 302 | if (err) { 303 | char errbuf[256]; 304 | regerror(err, &re, errbuf, sizeof errbuf); 305 | fprintf(stderr, "Unable to compile regex '%s': %s at %s line %d\n", 306 | expected, errbuf, file, line); 307 | exit(255); 308 | } 309 | err = regexec(&re, got, 0, NULL, 0); 310 | regfree(&re); 311 | test = for_match ? !err : err; 312 | va_start(args, fmt); 313 | vok_at_loc(file, line, test, fmt, args); 314 | va_end(args); 315 | if (!test) { 316 | if (for_match) { 317 | diag(" '%s'", got); 318 | diag(" doesn't match: '%s'", expected); 319 | } 320 | else { 321 | diag(" '%s'", got); 322 | diag(" matches: '%s'", expected); 323 | } 324 | } 325 | return test; 326 | } 327 | #endif 328 | 329 | -------------------------------------------------------------------------------- /deps/tap.c/tap.h: -------------------------------------------------------------------------------- 1 | /* 2 | libtap - Write tests in C 3 | Copyright 2012 Jake Gelbman 4 | This file is licensed under the GPLv2 5 | */ 6 | 7 | #ifndef __TAP_H__ 8 | #define __TAP_H__ 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #ifndef va_copy 15 | #ifdef __va_copy 16 | #define va_copy __va_copy 17 | #else 18 | #define va_copy(d, s) ((d) = (s)) 19 | #endif 20 | #endif 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | int vok_at_loc (const char *file, int line, int test, const char *fmt, 27 | va_list args); 28 | int ok_at_loc (const char *file, int line, int test, const char *fmt, 29 | ...); 30 | int is_at_loc (const char *file, int line, const char *got, 31 | const char *expected, const char *fmt, ...); 32 | int isnt_at_loc (const char *file, int line, const char *got, 33 | const char *expected, const char *fmt, ...); 34 | int cmp_ok_at_loc (const char *file, int line, int a, const char *op, 35 | int b, const char *fmt, ...); 36 | int bail_out (const char *fmt, ...); 37 | void tap_plan (int tests, const char *fmt, ...); 38 | int diag (const char *fmt, ...); 39 | int note (const char *fmt, ...); 40 | int exit_status (void); 41 | void tap_skip (int n, const char *fmt, ...); 42 | void tap_todo (const char *fmt, ...); 43 | void tap_end_todo (void); 44 | 45 | #define NO_PLAN -1 46 | #define SKIP_ALL -2 47 | #define ok(...) ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) 48 | #define is(...) is_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) 49 | #define isnt(...) isnt_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) 50 | #define cmp_ok(...) cmp_ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) 51 | #define plan(...) tap_plan(__VA_ARGS__, NULL) 52 | #define done_testing() return exit_status() 53 | #define BAIL_OUT(...) bail_out(0, "" __VA_ARGS__, NULL) 54 | #define pass(...) ok(1, "" __VA_ARGS__) 55 | #define fail(...) ok(0, "" __VA_ARGS__) 56 | 57 | #define skip(test, ...) do {if (test) {tap_skip(__VA_ARGS__, NULL); break;} 58 | #define end_skip } while (0) 59 | 60 | #define todo(...) tap_todo(0, "" __VA_ARGS__, NULL) 61 | #define end_todo tap_end_todo() 62 | 63 | #define dies_ok(...) dies_ok_common(1, __VA_ARGS__) 64 | #define lives_ok(...) dies_ok_common(0, __VA_ARGS__) 65 | 66 | #ifdef _WIN32 67 | #define like(...) tap_skip(1, "like is not implemented on Windows") 68 | #define unlike tap_skip(1, "unlike is not implemented on Windows") 69 | #define dies_ok_common(...) \ 70 | tap_skip(1, "Death detection is not supported on Windows") 71 | #else 72 | #define like(...) like_at_loc(1, __FILE__, __LINE__, __VA_ARGS__, NULL) 73 | #define unlike(...) like_at_loc(0, __FILE__, __LINE__, __VA_ARGS__, NULL) 74 | int like_at_loc (int for_match, const char *file, int line, 75 | const char *got, const char *expected, 76 | const char *fmt, ...); 77 | #include 78 | #include 79 | #include 80 | int tap_test_died (int status); 81 | #define dies_ok_common(for_death, code, ...) \ 82 | do { \ 83 | int cpid; \ 84 | int it_died; \ 85 | tap_test_died(1); \ 86 | cpid = fork(); \ 87 | switch (cpid) { \ 88 | case -1: \ 89 | perror("fork error"); \ 90 | exit(1); \ 91 | case 0: \ 92 | close(1); \ 93 | close(2); \ 94 | code \ 95 | tap_test_died(0); \ 96 | exit(0); \ 97 | } \ 98 | if (waitpid(cpid, NULL, 0) < 0) { \ 99 | perror("waitpid error"); \ 100 | exit(1); \ 101 | } \ 102 | it_died = tap_test_died(0); \ 103 | if (!it_died) \ 104 | {code} \ 105 | ok(for_death ? it_died : !it_died, "" __VA_ARGS__); \ 106 | } while (0) 107 | #endif 108 | 109 | #ifdef __cplusplus 110 | } 111 | #endif 112 | 113 | #endif 114 | 115 | -------------------------------------------------------------------------------- /doc/TODO.org: -------------------------------------------------------------------------------- 1 | 2 | * Suggestions 3 | 4 | `arubi` from #bitcoin-dev 5 | 6 | 10:44 jb55, awesome. for my serializer, I also defined a few "make 7 | your life easy" templates, like plain numbers are treated as scriptnum (need 8 | to be valid), the character @ means minimal push, so something like @ is converted to 0x21 0x (and longer pushes if needed), a 10 | 0x is just treated like literal serialized part of the script.. you're 11 | probably already on it, but just my pov :) 12 | 13 | 11:16 the behavior is pretty similar really, segwit serializes the 14 | codesep while legacy doesn't. segwit makes checksig ops a lot easier because 15 | of the better sighash scheme in bip143. there are so many interesting 16 | sighash types, and there are probably going to be more eventually, that 17 | implementing legacy just seems like a waste of time now 18 | 19 | * Remaining OPCODES 20 | -------------------------------------------------------------------------------- /endian.h: -------------------------------------------------------------------------------- 1 | /* CC0 (Public domain) */ 2 | #ifndef CCAN_ENDIAN_H 3 | #define CCAN_ENDIAN_H 4 | #include 5 | 6 | /** 7 | * BSWAP_16 - reverse bytes in a constant uint16_t value. 8 | * @val: constant value whose bytes to swap. 9 | * 10 | * Designed to be usable in constant-requiring initializers. 11 | * 12 | * Example: 13 | * struct mystruct { 14 | * char buf[BSWAP_16(0x1234)]; 15 | * }; 16 | */ 17 | #define BSWAP_16(val) \ 18 | ((((uint16_t)(val) & 0x00ff) << 8) \ 19 | | (((uint16_t)(val) & 0xff00) >> 8)) 20 | 21 | /** 22 | * BSWAP_32 - reverse bytes in a constant uint32_t value. 23 | * @val: constant value whose bytes to swap. 24 | * 25 | * Designed to be usable in constant-requiring initializers. 26 | * 27 | * Example: 28 | * struct mystruct { 29 | * char buf[BSWAP_32(0xff000000)]; 30 | * }; 31 | */ 32 | #define BSWAP_32(val) \ 33 | ((((uint32_t)(val) & 0x000000ff) << 24) \ 34 | | (((uint32_t)(val) & 0x0000ff00) << 8) \ 35 | | (((uint32_t)(val) & 0x00ff0000) >> 8) \ 36 | | (((uint32_t)(val) & 0xff000000) >> 24)) 37 | 38 | /** 39 | * BSWAP_64 - reverse bytes in a constant uint64_t value. 40 | * @val: constantvalue whose bytes to swap. 41 | * 42 | * Designed to be usable in constant-requiring initializers. 43 | * 44 | * Example: 45 | * struct mystruct { 46 | * char buf[BSWAP_64(0xff00000000000000ULL)]; 47 | * }; 48 | */ 49 | #define BSWAP_64(val) \ 50 | ((((uint64_t)(val) & 0x00000000000000ffULL) << 56) \ 51 | | (((uint64_t)(val) & 0x000000000000ff00ULL) << 40) \ 52 | | (((uint64_t)(val) & 0x0000000000ff0000ULL) << 24) \ 53 | | (((uint64_t)(val) & 0x00000000ff000000ULL) << 8) \ 54 | | (((uint64_t)(val) & 0x000000ff00000000ULL) >> 8) \ 55 | | (((uint64_t)(val) & 0x0000ff0000000000ULL) >> 24) \ 56 | | (((uint64_t)(val) & 0x00ff000000000000ULL) >> 40) \ 57 | | (((uint64_t)(val) & 0xff00000000000000ULL) >> 56)) 58 | 59 | #if HAVE_BYTESWAP_H 60 | #include 61 | #else 62 | /** 63 | * bswap_16 - reverse bytes in a uint16_t value. 64 | * @val: value whose bytes to swap. 65 | * 66 | * Example: 67 | * // Output contains "1024 is 4 as two bytes reversed" 68 | * printf("1024 is %u as two bytes reversed\n", bswap_16(1024)); 69 | */ 70 | static inline uint16_t bswap_16(uint16_t val) 71 | { 72 | return BSWAP_16(val); 73 | } 74 | 75 | /** 76 | * bswap_32 - reverse bytes in a uint32_t value. 77 | * @val: value whose bytes to swap. 78 | * 79 | * Example: 80 | * // Output contains "1024 is 262144 as four bytes reversed" 81 | * printf("1024 is %u as four bytes reversed\n", bswap_32(1024)); 82 | */ 83 | static inline uint32_t bswap_32(uint32_t val) 84 | { 85 | return BSWAP_32(val); 86 | } 87 | #endif /* !HAVE_BYTESWAP_H */ 88 | 89 | #if !HAVE_BSWAP_64 90 | /** 91 | * bswap_64 - reverse bytes in a uint64_t value. 92 | * @val: value whose bytes to swap. 93 | * 94 | * Example: 95 | * // Output contains "1024 is 1125899906842624 as eight bytes reversed" 96 | * printf("1024 is %llu as eight bytes reversed\n", 97 | * (unsigned long long)bswap_64(1024)); 98 | */ 99 | static inline uint64_t bswap_64(uint64_t val) 100 | { 101 | return BSWAP_64(val); 102 | } 103 | #endif 104 | 105 | /* Needed for Glibc like endiness check */ 106 | #define __LITTLE_ENDIAN 1234 107 | #define __BIG_ENDIAN 4321 108 | 109 | /* Sanity check the defines. We don't handle weird endianness. */ 110 | #if HAVE_LITTLE_ENDIAN && HAVE_BIG_ENDIAN 111 | #error "Can't compile for both big and little endian." 112 | #elif HAVE_LITTLE_ENDIAN 113 | #ifndef __BYTE_ORDER 114 | #define __BYTE_ORDER __LITTLE_ENDIAN 115 | #elif __BYTE_ORDER != __LITTLE_ENDIAN 116 | #error "__BYTE_ORDER already defined, but not equal to __LITTLE_ENDIAN" 117 | #endif 118 | #elif HAVE_BIG_ENDIAN 119 | #ifndef __BYTE_ORDER 120 | #define __BYTE_ORDER __BIG_ENDIAN 121 | #elif __BYTE_ORDER != __BIG_ENDIAN 122 | #error "__BYTE_ORDER already defined, but not equal to __BIG_ENDIAN" 123 | #endif 124 | #endif 125 | 126 | 127 | #ifdef __CHECKER__ 128 | /* sparse needs forcing to remove bitwise attribute from ccan/short_types */ 129 | #define ENDIAN_CAST __attribute__((force)) 130 | #define ENDIAN_TYPE __attribute__((bitwise)) 131 | #else 132 | #define ENDIAN_CAST 133 | #define ENDIAN_TYPE 134 | #endif 135 | 136 | typedef uint64_t ENDIAN_TYPE leint64_t; 137 | typedef uint64_t ENDIAN_TYPE beint64_t; 138 | typedef uint32_t ENDIAN_TYPE leint32_t; 139 | typedef uint32_t ENDIAN_TYPE beint32_t; 140 | typedef uint16_t ENDIAN_TYPE leint16_t; 141 | typedef uint16_t ENDIAN_TYPE beint16_t; 142 | 143 | #if HAVE_LITTLE_ENDIAN 144 | /** 145 | * CPU_TO_LE64 - convert a constant uint64_t value to little-endian 146 | * @native: constant to convert 147 | */ 148 | #define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)(native)) 149 | 150 | /** 151 | * CPU_TO_LE32 - convert a constant uint32_t value to little-endian 152 | * @native: constant to convert 153 | */ 154 | #define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)(native)) 155 | 156 | /** 157 | * CPU_TO_LE16 - convert a constant uint16_t value to little-endian 158 | * @native: constant to convert 159 | */ 160 | #define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)(native)) 161 | 162 | /** 163 | * LE64_TO_CPU - convert a little-endian uint64_t constant 164 | * @le_val: little-endian constant to convert 165 | */ 166 | #define LE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val)) 167 | 168 | /** 169 | * LE32_TO_CPU - convert a little-endian uint32_t constant 170 | * @le_val: little-endian constant to convert 171 | */ 172 | #define LE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val)) 173 | 174 | /** 175 | * LE16_TO_CPU - convert a little-endian uint16_t constant 176 | * @le_val: little-endian constant to convert 177 | */ 178 | #define LE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val)) 179 | 180 | #else /* ... HAVE_BIG_ENDIAN */ 181 | #define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)BSWAP_64(native)) 182 | #define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)BSWAP_32(native)) 183 | #define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)BSWAP_16(native)) 184 | #define LE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val) 185 | #define LE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val) 186 | #define LE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val) 187 | #endif /* HAVE_BIG_ENDIAN */ 188 | 189 | #if HAVE_BIG_ENDIAN 190 | /** 191 | * CPU_TO_BE64 - convert a constant uint64_t value to big-endian 192 | * @native: constant to convert 193 | */ 194 | #define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)(native)) 195 | 196 | /** 197 | * CPU_TO_BE32 - convert a constant uint32_t value to big-endian 198 | * @native: constant to convert 199 | */ 200 | #define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)(native)) 201 | 202 | /** 203 | * CPU_TO_BE16 - convert a constant uint16_t value to big-endian 204 | * @native: constant to convert 205 | */ 206 | #define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)(native)) 207 | 208 | /** 209 | * BE64_TO_CPU - convert a big-endian uint64_t constant 210 | * @le_val: big-endian constant to convert 211 | */ 212 | #define BE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val)) 213 | 214 | /** 215 | * BE32_TO_CPU - convert a big-endian uint32_t constant 216 | * @le_val: big-endian constant to convert 217 | */ 218 | #define BE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val)) 219 | 220 | /** 221 | * BE16_TO_CPU - convert a big-endian uint16_t constant 222 | * @le_val: big-endian constant to convert 223 | */ 224 | #define BE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val)) 225 | 226 | #else /* ... HAVE_LITTLE_ENDIAN */ 227 | #define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)BSWAP_64(native)) 228 | #define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)BSWAP_32(native)) 229 | #define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)BSWAP_16(native)) 230 | #define BE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val) 231 | #define BE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val) 232 | #define BE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val) 233 | #endif /* HAVE_LITTE_ENDIAN */ 234 | 235 | 236 | /** 237 | * cpu_to_le64 - convert a uint64_t value to little-endian 238 | * @native: value to convert 239 | */ 240 | static inline leint64_t cpu_to_le64(uint64_t native) 241 | { 242 | return CPU_TO_LE64(native); 243 | } 244 | 245 | /** 246 | * cpu_to_le32 - convert a uint32_t value to little-endian 247 | * @native: value to convert 248 | */ 249 | static inline leint32_t cpu_to_le32(uint32_t native) 250 | { 251 | return CPU_TO_LE32(native); 252 | } 253 | 254 | /** 255 | * cpu_to_le16 - convert a uint16_t value to little-endian 256 | * @native: value to convert 257 | */ 258 | static inline leint16_t cpu_to_le16(uint16_t native) 259 | { 260 | return CPU_TO_LE16(native); 261 | } 262 | 263 | /** 264 | * le64_to_cpu - convert a little-endian uint64_t value 265 | * @le_val: little-endian value to convert 266 | */ 267 | static inline uint64_t le64_to_cpu(leint64_t le_val) 268 | { 269 | return LE64_TO_CPU(le_val); 270 | } 271 | 272 | /** 273 | * le32_to_cpu - convert a little-endian uint32_t value 274 | * @le_val: little-endian value to convert 275 | */ 276 | static inline uint32_t le32_to_cpu(leint32_t le_val) 277 | { 278 | return LE32_TO_CPU(le_val); 279 | } 280 | 281 | /** 282 | * le16_to_cpu - convert a little-endian uint16_t value 283 | * @le_val: little-endian value to convert 284 | */ 285 | static inline uint16_t le16_to_cpu(leint16_t le_val) 286 | { 287 | return LE16_TO_CPU(le_val); 288 | } 289 | 290 | /** 291 | * cpu_to_be64 - convert a uint64_t value to big endian. 292 | * @native: value to convert 293 | */ 294 | static inline beint64_t cpu_to_be64(uint64_t native) 295 | { 296 | return CPU_TO_BE64(native); 297 | } 298 | 299 | /** 300 | * cpu_to_be32 - convert a uint32_t value to big endian. 301 | * @native: value to convert 302 | */ 303 | static inline beint32_t cpu_to_be32(uint32_t native) 304 | { 305 | return CPU_TO_BE32(native); 306 | } 307 | 308 | /** 309 | * cpu_to_be16 - convert a uint16_t value to big endian. 310 | * @native: value to convert 311 | */ 312 | static inline beint16_t cpu_to_be16(uint16_t native) 313 | { 314 | return CPU_TO_BE16(native); 315 | } 316 | 317 | /** 318 | * be64_to_cpu - convert a big-endian uint64_t value 319 | * @be_val: big-endian value to convert 320 | */ 321 | static inline uint64_t be64_to_cpu(beint64_t be_val) 322 | { 323 | return BE64_TO_CPU(be_val); 324 | } 325 | 326 | /** 327 | * be32_to_cpu - convert a big-endian uint32_t value 328 | * @be_val: big-endian value to convert 329 | */ 330 | static inline uint32_t be32_to_cpu(beint32_t be_val) 331 | { 332 | return BE32_TO_CPU(be_val); 333 | } 334 | 335 | /** 336 | * be16_to_cpu - convert a big-endian uint16_t value 337 | * @be_val: big-endian value to convert 338 | */ 339 | static inline uint16_t be16_to_cpu(beint16_t be_val) 340 | { 341 | return BE16_TO_CPU(be_val); 342 | } 343 | 344 | /* Whichever they include first, they get these definitions. */ 345 | #ifdef CCAN_SHORT_TYPES_H 346 | /** 347 | * be64/be32/be16 - 64/32/16 bit big-endian representation. 348 | */ 349 | typedef beint64_t be64; 350 | typedef beint32_t be32; 351 | typedef beint16_t be16; 352 | 353 | /** 354 | * le64/le32/le16 - 64/32/16 bit little-endian representation. 355 | */ 356 | typedef leint64_t le64; 357 | typedef leint32_t le32; 358 | typedef leint16_t le16; 359 | #endif 360 | #endif /* CCAN_ENDIAN_H */ 361 | -------------------------------------------------------------------------------- /examples/htlc: -------------------------------------------------------------------------------- 1 | OP_IF 2 | [HASHOP] OP_EQUALVERIFY OP_DUP OP_HASH160 3 | OP_ELSE 4 | [TIMEOUTOP] OP_DROP OP_DUP OP_HASH160 5 | OP_ENDIF 6 | OP_EQUALVERIFY 7 | OP_CHECKSIG 8 | -------------------------------------------------------------------------------- /lexer.l: -------------------------------------------------------------------------------- 1 | %option noyywrap 2 | 3 | %{ 4 | #include 5 | #include "script.h" 6 | #include "op.h" 7 | 8 | int fileno(FILE *stream); 9 | #define YY_DECL int yylex() 10 | 11 | #include "parser.tab.h" 12 | 13 | %} 14 | 15 | %% 16 | 17 | [ \t] ; // ignore all whitespace 18 | \n {return T_NEWLINE;} 19 | 20 | \<[^\>]+\> { yylval.str = yytext; return T_EXAMPLE; } 21 | 22 | \[[^\]]+\] { yylval.str = yytext; return T_EXAMPLE; } 23 | 24 | #[^\n]* { return T_COMMENT; } 25 | 26 | [oO][pP]_ {} 27 | 28 | \"[^\"]*\" { 29 | char *t = yytext + 1; 30 | t[strlen(t) - 1] = '\0'; 31 | yylval.str = t; 32 | return T_STR; 33 | } 34 | 35 | 0x[a-fA-F0-9]+ { 36 | char * t = yytext + 2; 37 | if (strlen(t) % 2 != 0) { 38 | yylval.str = "Invalid raw string, it must have even length"; 39 | return T_ERR; 40 | } 41 | yylval.str = t; 42 | return T_RAW; 43 | } 44 | 45 | @[a-fA-F0-9]+ { 46 | char *t = yytext + 1; 47 | if (strlen(t) % 2 != 0) { 48 | yylval.str = "Invalid data string, it must have even length"; 49 | return T_ERR; 50 | } 51 | yylval.str = t; 52 | return T_DATA; 53 | } 54 | 55 | -?[0-9]+ { 56 | s64 i = strtoll(yytext, NULL, 10); 57 | yylval.val = val_from_int(i); 58 | return T_VAL; 59 | } 60 | 61 | [a-zA-Z0-9]+ { 62 | yylval.opcode = op_tokenize(yytext); 63 | return T_OP; 64 | } 65 | 66 | %% 67 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "stack.h" 8 | #include "script.h" 9 | #include "alloc.h" 10 | #include "util.h" 11 | 12 | extern int yyparse(); 13 | extern FILE* yyin; 14 | 15 | char * g_reader_buf; 16 | char * g_reader_buf_top; 17 | struct stack g_reader_stack; 18 | u32 g_reader_buf_cap; 19 | int yy_scan_string(const char *); 20 | 21 | 22 | void yyerror(const char* s); 23 | 24 | #define streq(a,b) strcmp(a,b) == 0 25 | 26 | 27 | void parse_error(char* err) { 28 | fprintf(stderr, "[btcs] parse error: %s\n", err); 29 | exit(1); 30 | } 31 | 32 | #define COMPILE_SHOW_SCRIPT (1 << 0) 33 | #define COMPILE_SHOW_SCRIPT_HEX (1 << 1) 34 | #define COMPILE_SHOW_STACK (1 << 2) 35 | #define COMPILE_SHOW_STACK_HEX (1 << 3) 36 | #define COMPILE_SHOW_RESULTS (1 << 4) 37 | #define COMPILE_SHOW_LABELS (1 << 5) 38 | #define COMPILE_SHOW_ALL 0x3F 39 | 40 | static int compile(int compile_options, int argc, const char *argv[]) 41 | { 42 | yyin = stdin; 43 | 44 | struct result result; 45 | /* size_t size; */ 46 | size_t bufsize = MAX_STACK_SIZE * MAX_STACK_SIZE; 47 | int i; 48 | int compiled_len; 49 | u8 *buf = (u8*)malloc(bufsize); 50 | struct stack tmp_stack; 51 | alloc_arenas(); 52 | stack_init(&tmp_stack); 53 | stack_init(&g_reader_stack); 54 | 55 | if (argc > 1) { 56 | for (i = 1; i < argc; ++i) { 57 | yy_scan_string(argv[i]); 58 | yyparse(); 59 | } 60 | } 61 | else { 62 | do { 63 | yyparse(); 64 | } while(!feof(yyin)); 65 | } 66 | 67 | bool nol = (compile_options & COMPILE_SHOW_LABELS) == 0; 68 | 69 | /* size = g_reader_buf_top - g_reader_buf; */ 70 | if (compile_options & COMPILE_SHOW_SCRIPT) { 71 | if (compile_options & COMPILE_SHOW_LABELS) 72 | printf("script "); 73 | script_print_vals(&g_reader_stack); 74 | } 75 | 76 | script_serialize(&g_reader_stack, buf, bufsize, &compiled_len); 77 | script_eval(buf, compiled_len, &tmp_stack, &result); 78 | 79 | if (compile_options & COMPILE_SHOW_SCRIPT_HEX) { 80 | if (compile_options & COMPILE_SHOW_LABELS) 81 | printf("script_hex "); 82 | for(i = 0; i < compiled_len; ++i) 83 | printf("%02x", buf[i]); 84 | printf("\n"); 85 | } 86 | 87 | if (compile_options & COMPILE_SHOW_STACK) { 88 | if (compile_options & COMPILE_SHOW_LABELS) 89 | printf("stack "); 90 | script_print_vals(&tmp_stack); 91 | } 92 | 93 | stack_serialize(&tmp_stack, buf, bufsize, &compiled_len); 94 | 95 | if (compile_options & COMPILE_SHOW_STACK_HEX) { 96 | if (compile_options & COMPILE_SHOW_LABELS) 97 | printf("stack_hex "); 98 | for(i = 0; i < compiled_len; ++i) 99 | printf("%02x", buf[i]); 100 | printf("\n"); 101 | } 102 | 103 | if (compile_options & COMPILE_SHOW_RESULTS) { 104 | if (compile_options & COMPILE_SHOW_LABELS) 105 | printf("results "); 106 | if (result.error) 107 | printf("error:%d:%s:%s", result.op_count, result.error, 108 | op_name(result.last_op)); 109 | else 110 | printf("success"); 111 | printf("\n"); 112 | } 113 | 114 | stack_free(&g_reader_stack); 115 | stack_free(&tmp_stack); 116 | free_arenas(0); 117 | 118 | return !!result.error; 119 | } 120 | 121 | static void fail(int err, const char *msg) 122 | { 123 | fprintf(stderr, "error: %s\n", msg); 124 | exit(err); 125 | } 126 | 127 | 128 | static int decompile(const char *str, size_t *strlen, bool abbrev_data) 129 | { 130 | static u8 buf[10000]; 131 | 132 | hex_decode(str, strlen, buf, sizeof(buf)); 133 | 134 | if (*strlen % 2 != 0) 135 | return 0; 136 | 137 | size_t nbytes = *strlen / 2; 138 | 139 | script_print(buf, nbytes, abbrev_data); 140 | 141 | return 1; 142 | } 143 | 144 | 145 | static void usage() 146 | { 147 | fprintf(stderr, "usage: btcs [OPTIONS]