├── .travis.yml ├── .gitignore ├── .dir-locals.el ├── compiler.c ├── examples └── htlc ├── oplookup.h ├── util.h ├── default.nix ├── consts.h ├── deps └── tap.c │ ├── package.json │ ├── tap.h │ └── tap.c ├── test ├── run └── tests.csv ├── oplookup.c ├── alloc.h ├── doc └── TODO.org ├── script_num.h ├── README.md ├── script.h ├── val.h ├── lexer.l ├── LICENSE ├── misc.h ├── opcodes ├── parser.y ├── Makefile ├── valstack.h ├── compiler.h ├── stack.h ├── stack.c ├── btcs.1 ├── alloc.c ├── util.c ├── val.c ├── mph-opcodes ├── ripemd160.h ├── sha256.h ├── script_num.c ├── op.h ├── main.c ├── test.c ├── endian.h ├── sha256.c ├── op.c ├── ripemd160.c └── script.c /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | script: make && make check 3 | compiler: 4 | - clang 5 | - gcc 6 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /oplookup.h: -------------------------------------------------------------------------------- 1 | /* THIS IS GENERATED FROM mph-opcodes DO NOT EDIT */ 2 | 3 | #ifndef BCS_OPLOOKUP_H 4 | #define BCS_OPLOOKUP_H 5 | 6 | #include "misc.h" 7 | extern const int opcodes_g[120]; 8 | extern const int opcodes_v[120]; 9 | 10 | #endif /* BCS_OPLOOKUP_H */ 11 | -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef BTCS_UTIL_H 3 | #define BTCS_UTIL_H 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | typedef intptr_t ssize_t; 11 | 12 | 13 | int read_arg_or_stdin(const char *arg, unsigned char *buf, size_t buflen, size_t *written); 14 | bool hex_decode(const char *str, size_t *slen, void *buf, size_t bufsize); 15 | ssize_t getline(char **lineptr, size_t *n, FILE *stream); 16 | 17 | #endif /* UTIL_H */ 18 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /test/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | process () { 4 | tail -n+2 "$1" | sed -n '/^--- failing/q;p' 5 | } 6 | 7 | n=1 8 | c=$(($(process tests.csv | wc -l))) 9 | 10 | printf "1..%d\n" "$c" 11 | 12 | process tests.csv | \ 13 | (fail=0 14 | while IFS=, read -r description args input expected 15 | do 16 | output=$(../btcs $args <<<"$input" 2>&1) 17 | output2=${output//[$'\t\r\n']/ } 18 | if [ "$output2" == "$expected" ]; then 19 | printf "ok %d - %s\n" "$n" "$description" 20 | else 21 | printf "not ok %d - %s\n" "$n" "$description" 22 | printf "#\n# got '%s', \n# expected '%s'\n#\n" "$output2" "$expected" 23 | fail=1 24 | fi 25 | n=$((n + 1)) 26 | done 27 | exit $fail 28 | ) 29 | 30 | -------------------------------------------------------------------------------- /oplookup.c: -------------------------------------------------------------------------------- 1 | /* THIS IS GENERATED FROM mph-opcodes DO NOT EDIT */ 2 | 3 | #include "oplookup.h" 4 | const int opcodes_g[120] = { 1,-118,0,2,-116,0,0,2,0,0,0,-114,3,-111,8,0,0,0,0,8,-110,-107,1,0,0,-101,0,-98,0,-92,0,10,1,1,0,0,0,0,-89,0,5,-88,2,-87,4,-86,-79,-78,2,0,-74,-73,-72,-70,-69,0,1,1,-63,-61,-59,-56,-55,0,0,0,-53,0,-49,0,1,-48,0,-47,0,0,2,-46,1,0,5,3,-44,-41,0,2,-38,-33,-30,14,-29,0,2,0,-28,0,-27,0,0,-26,0,0,-23,0,0,0,-20,1,-18,0,-15,-12,8,1,0,-10,10,2,6,7 }; 5 | const int opcodes_v[120] = { 66,111,5,90,50,33,76,105,6,104,65,77,55,32,116,49,71,85,75,113,60,26,52,88,46,57,86,41,96,36,18,19,69,56,95,63,42,51,30,117,4,13,80,64,68,72,67,59,74,89,83,34,44,53,24,23,48,39,22,47,21,70,20,109,112,7,103,40,25,43,8,2,9,73,99,110,81,14,15,106,97,45,17,16,29,12,10,1,120,114,58,118,31,82,37,62,92,102,3,108,107,11,28,93,27,94,79,115,98,78,87,54,38,101,35,100,119,91,84,61 }; 6 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /script_num.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef BTCS_SCRIPTNUM_H 3 | #define BTCS_SCRIPTNUM_H 4 | 5 | #include "misc.h" 6 | #include "val.h" 7 | 8 | enum sn_result { 9 | SN_SUCCESS, 10 | SN_ERR_OVERFLOWED_INT 11 | }; 12 | 13 | struct num { 14 | s64 val; 15 | int ind; 16 | }; 17 | 18 | void 19 | sn_from_int(s64 n, struct num *); 20 | 21 | int 22 | sn_overflowed(struct num *num); 23 | 24 | enum sn_result 25 | sn_from_val(struct val val, struct num ** sn); 26 | 27 | struct val 28 | sn_to_val(struct num *sn); 29 | 30 | int 31 | sn_to_int(struct num *sn, int require_minimal); 32 | 33 | void 34 | sn_serialize(struct num *sn, u8 *buf, int bufsize, u16 *len); 35 | 36 | 37 | inline static void sn_add(struct num *a, struct num *b, struct num *c) { 38 | c->val = a->val + b->val; 39 | } 40 | 41 | inline static void sn_sub(struct num *a, struct num *b, struct num *c) { 42 | c->val = a->val - b->val; 43 | } 44 | 45 | inline static void sn_neg(struct num *a, struct num *b) { 46 | b->val = -(a->val); 47 | } 48 | 49 | 50 | #endif /* BTCS_SCRIPTNUM_H */ 51 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /script.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef BTCS_SCRIPT_H 3 | #define BTCS_SCRIPT_H 4 | 5 | #include "stack.h" 6 | #include "op.h" 7 | 8 | struct result { 9 | char * error; 10 | enum opcode last_op; 11 | int op_count; 12 | }; 13 | 14 | int script_eval(const u8 *script, size_t script_size, struct stack *stack, 15 | struct result *result); 16 | void script_print_ops(char * buf, size_t size); 17 | void script_print_vals(struct stack *); 18 | void script_push_int(struct stack *, s64); 19 | 20 | void script_push_str(struct stack *script, const char *str); 21 | void script_push_raw(struct stack *, const char *str); 22 | void script_push_datastr(struct stack *, const char *str, int israw); 23 | 24 | void script_serialize(struct stack *stack, u8 *buf, int buflen, int* len); 25 | void stack_serialize(struct stack *stack, u8 *buf, int buflen, int* len); 26 | 27 | void script_print(const u8 *script, size_t script_size, int abbrev_data); 28 | int script_getop(const u8 **p, const u8 *end, enum opcode *popcode, u8 *buf, int bufsize, u32 *outlen); 29 | 30 | extern int g_silence_script_err; 31 | extern int g_silence_script_warn; 32 | 33 | #endif /* BTCS_SCRIPT_H */ 34 | -------------------------------------------------------------------------------- /val.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef BTCS_VAL_H 3 | #define BTCS_VAL_H 4 | 5 | #include "misc.h" 6 | #include "stack.h" 7 | 8 | enum valtype { 9 | VT_SCRIPTNUM=0, 10 | VT_SMALLINT, 11 | VT_OP, 12 | VT_RAW, 13 | VT_DATA, 14 | VT_N 15 | }; 16 | // UPDATE VAL_TYPE_BITS if you need more valtypes 17 | 18 | 19 | #define VAL_TYPE_BITS 3 20 | /* static const int COMPACT_VAL_BITS = (32-VAL_TYPE_BITS-1); */ 21 | #define VAL_COMPACT_BITS 29 22 | 23 | struct val { 24 | u8 type : VAL_TYPE_BITS; 25 | int ind : VAL_COMPACT_BITS; 26 | }; 27 | 28 | #define smallintval(n) ((struct val){ .type = VT_SMALLINT, .ind = n }) 29 | #define falseval smallintval(0) 30 | #define trueval smallintval(1) 31 | 32 | // we want val to fit into the size of a 32-bit pointer 33 | STATIC_ASSERT(sizeof(struct val) <= 4, val_doesnt_fit_in_stack); 34 | 35 | struct val val_copy(struct val a); 36 | u32 val_size(struct val val); 37 | 38 | int 39 | val_eq(struct val a, struct val b); 40 | 41 | void val_serialize(struct val val, u32 *len, u8 *buf, int bufsize); 42 | void val_bytes(struct val val, u32 *len, u8 *buf, int bufsize); 43 | struct val val_cat(struct val a, struct val b); 44 | 45 | struct val val_from_int(s64); 46 | 47 | #endif /* BTCS_VAL_H */ 48 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /misc.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef BCS_MISC_H 3 | #define BCS_MISC_H 4 | 5 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 6 | 7 | /* #include */ 8 | #include 9 | #include 10 | #include 11 | 12 | #define DEBUG 0 13 | 14 | enum compiler_options { 15 | CO_WARNINGS_ARE_ERRORS = 1 << 1, 16 | CO_WARN_MINIMAL = 1 << 2 17 | }; 18 | 19 | 20 | /* #define debug(fmt, ...) \ */ 21 | /* do { if (DEBUG) fprintf(stderr, fmt, __VA_ARGS__); } while (0) */ 22 | 23 | typedef unsigned char u8; 24 | typedef unsigned short u16; 25 | typedef unsigned int u32; 26 | typedef int64_t s64; 27 | typedef uint64_t u64; 28 | 29 | #define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(!!(COND))*2-1] 30 | 31 | // TODO: host endianness 32 | #define le16toh(x) (x) 33 | #define le32toh(x) (x) 34 | 35 | inline static u16 36 | readle16(const u8* ptr) { 37 | u16 x; 38 | memcpy((char*)&x, ptr, 2); 39 | return le16toh(x); 40 | } 41 | 42 | inline static u32 43 | readle32(const u8* ptr) { 44 | u32 x; 45 | memcpy((char*)&x, ptr, 4); 46 | return le32toh(x); 47 | } 48 | 49 | inline static void 50 | print_bytes(u8 *bytes, size_t size, int with_space) { 51 | size_t i; 52 | for (i = 0; i < size; i++) { 53 | printf("%02x", bytes[i]); 54 | if (with_space) printf(" "); 55 | } 56 | } 57 | 58 | 59 | #endif /* BCS_MISC_H */ 60 | -------------------------------------------------------------------------------- /opcodes: -------------------------------------------------------------------------------- 1 | 0 2 | FALSE 3 | PUSHDATA1 4 | PUSHDATA2 5 | PUSHDATA4 6 | 1NEGATE 7 | RESERVED 8 | 1 9 | TRUE 10 | 2 11 | 3 12 | 4 13 | 5 14 | 6 15 | 7 16 | 8 17 | 9 18 | 10 19 | 11 20 | 12 21 | 13 22 | 14 23 | 15 24 | 16 25 | NOP 26 | VER 27 | IF 28 | NOTIF 29 | VERIF 30 | VERNOTIF 31 | ELSE 32 | ENDIF 33 | VERIFY 34 | RETURN 35 | TOALTSTACK 36 | FROMALTSTACK 37 | 2DROP 38 | 2DUP 39 | 3DUP 40 | 2OVER 41 | 2ROT 42 | 2SWAP 43 | IFDUP 44 | DEPTH 45 | DROP 46 | DUP 47 | NIP 48 | OVER 49 | PICK 50 | ROLL 51 | ROT 52 | SWAP 53 | TUCK 54 | CAT 55 | SUBSTR 56 | LEFT 57 | RIGHT 58 | SIZE 59 | INVERT 60 | AND 61 | OR 62 | XOR 63 | EQUAL 64 | EQUALVERIFY 65 | RESERVED1 66 | RESERVED2 67 | 1ADD 68 | 1SUB 69 | 2MUL 70 | 2DIV 71 | NEGATE 72 | ABS 73 | NOT 74 | 0NOTEQUAL 75 | ADD 76 | SUB 77 | MUL 78 | DIV 79 | MOD 80 | LSHIFT 81 | RSHIFT 82 | BOOLAND 83 | BOOLOR 84 | NUMEQUAL 85 | NUMEQUALVERIFY 86 | NUMNOTEQUAL 87 | LESSTHAN 88 | GREATERTHAN 89 | LESSTHANOREQUAL 90 | GREATERTHANOREQUAL 91 | MIN 92 | MAX 93 | WITHIN 94 | RIPEMD160 95 | SHA1 96 | SHA256 97 | HASH160 98 | HASH256 99 | CODESEPARATOR 100 | CHECKSIG 101 | CHECKSIGVERIFY 102 | CHECKMULTISIG 103 | CHECKMULTISIGVERIFY 104 | NOP1 105 | CHECKLOCKTIMEVERIFY 106 | NOP2 107 | CHECKSEQUENCEVERIFY 108 | NOP3 109 | NOP4 110 | NOP5 111 | NOP6 112 | NOP7 113 | NOP8 114 | NOP9 115 | NOP10 116 | SMALLINTEGER 117 | PUBKEYS 118 | PUBKEYHASH 119 | PUBKEY 120 | INVALIDOPCODE -------------------------------------------------------------------------------- /parser.y: -------------------------------------------------------------------------------- 1 | 2 | %{ 3 | #include 4 | #include "op.h" 5 | #include "script.h" 6 | #include "stack.h" 7 | #include "valstack.h" 8 | 9 | extern int yylex(); 10 | extern struct stack g_reader_stack; 11 | void yyerror(const char *s); 12 | 13 | void script_handle_input(struct stack *stack, const char *str); 14 | void parse_error(const char *err); 15 | 16 | %} 17 | 18 | %union { 19 | enum opcode opcode; 20 | s64 integer; 21 | struct val val; 22 | const char* str; 23 | } 24 | 25 | %token T_OP 26 | %token T_INT 27 | %token T_VAL 28 | %token T_DATA 29 | %token T_RAW 30 | %token T_STR 31 | %token T_COMMENT 32 | %token T_ERR 33 | %token T_NEWLINE T_QUIT T_EXAMPLE 34 | 35 | %type T_OP 36 | %type T_INT 37 | %type T_DATA 38 | %type T_RAW 39 | %type T_STR 40 | %type T_VAL 41 | %type T_EXAMPLE 42 | %type T_ERR 43 | 44 | %start script 45 | 46 | %% 47 | 48 | script: 49 | | script line 50 | ; 51 | 52 | line: T_NEWLINE 53 | | T_COMMENT 54 | | T_RAW { script_push_raw(&g_reader_stack, $1); } 55 | | T_INT { script_push_int(&g_reader_stack, $1); } 56 | | T_VAL { stack_push_val(&g_reader_stack, $1); } 57 | | T_OP { stack_push_op(&g_reader_stack, $1); } 58 | | T_DATA { script_push_datastr(&g_reader_stack, $1, 0); } 59 | | T_STR { script_push_str(&g_reader_stack, $1); } 60 | | T_ERR { parse_error($1); } 61 | | T_EXAMPLE { script_handle_input(&g_reader_stack, $1); } 62 | 63 | 64 | %% 65 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /valstack.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef BTCS_VALSTACK_H 3 | #define BTCS_VALSTACK_H 4 | 5 | #include "op.h" 6 | #include "val.h" 7 | #include "alloc.h" 8 | 9 | static inline struct val 10 | stack_top_val(struct stack *stack, int ind) { 11 | struct val val; 12 | stack_top_small(struct val, stack, &val, ind); 13 | return val; 14 | } 15 | 16 | static inline struct val 17 | stack_pop_val(struct stack *stack) { 18 | struct val val; 19 | val = stack_top_val(stack, -1); 20 | stack_pop(stack); 21 | return val; 22 | } 23 | 24 | static inline void 25 | stack_set_val(struct stack *stack, int ind, struct val val) { 26 | struct val *pval = (struct val *)(stack->top + ind); 27 | *pval = val; 28 | } 29 | 30 | static inline void 31 | stack_push_val(struct stack *stack, struct val val) { 32 | #if 0 33 | printf("pushing val "); 34 | val_print(val); 35 | printf("\n"); 36 | #endif 37 | stack_push_small(struct val, stack, &val); 38 | } 39 | 40 | static inline void 41 | stack_push_raw(struct stack *stack, u8 *data, int len) { 42 | struct val val = { .type = VT_RAW }; 43 | u8 *p; 44 | u16 ind; 45 | p = byte_pool_new(len, &ind); 46 | memcpy(p, data, len); 47 | val.ind = ind; 48 | stack_push_val(stack, val); 49 | } 50 | 51 | static inline void 52 | stack_push_op(struct stack *stack, enum opcode opcode) { 53 | struct val val = { .type = VT_OP, .ind = opcode }; 54 | stack_push_val(stack, val); 55 | } 56 | 57 | static inline int 58 | stack_any_val(struct stack *stack, struct val val) { 59 | void **p = stack->bottom; 60 | struct val *cval; 61 | 62 | while (p < stack->top) { 63 | cval = (struct val*)p; 64 | if (val.type == cval->type && val.ind == cval->ind) 65 | return 1; 66 | p++; 67 | } 68 | 69 | return 0; 70 | } 71 | 72 | #endif /* BTCS_VALSTACK_H */ 73 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /stack.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef BTCS_STACK_H 3 | #define BTCS_STACK_H 4 | 5 | #include 6 | #include 7 | #include 8 | #include "misc.h" 9 | 10 | // Maximum number of values on script interpreter stack 11 | static const int MAX_STACK_SIZE = 1000; 12 | 13 | // Maximum number of values on script interpreter stack 14 | #define DEFAULT_STACK_SIZE 32 15 | 16 | struct stack { 17 | void *_data[DEFAULT_STACK_SIZE]; 18 | void **bottom; 19 | void **top; 20 | int capacity; 21 | }; 22 | 23 | int stack_init(struct stack *); 24 | int stack_init_size(struct stack *, int size); 25 | void stack_free(struct stack *); 26 | void stack_clear(struct stack *); 27 | void* stack_pop(struct stack *); 28 | void stack_erase(struct stack *, int ind); 29 | void stack_push(struct stack *, void *val); 30 | 31 | static inline void * 32 | stack_top(struct stack *stack, int ind) { 33 | void **p = stack->top + ind; 34 | assert(p >= stack->bottom); 35 | assert(p); 36 | return *p; 37 | } 38 | 39 | static inline int 40 | stack_size(struct stack *stack) { 41 | return stack->top - stack->bottom; 42 | } 43 | 44 | static inline void 45 | stack_swap(struct stack *stack, int ind1, int ind2) { 46 | void *temp = *(stack->top + ind1); 47 | *(stack->top + ind1) = *(stack->top + ind2); 48 | *(stack->top + ind2) = temp; 49 | } 50 | 51 | #define stack_push_small(T, stack, val) { \ 52 | assert(sizeof(T) <= sizeof(void*)); \ 53 | void *tmp = 0; \ 54 | memcpy(&tmp, val, sizeof(T)); \ 55 | stack_push(stack, tmp); \ 56 | } 57 | 58 | #define stack_top_small(T, stack, v, ind) \ 59 | memcpy(v, stack->top + ind, sizeof(T)) 60 | 61 | static inline void 62 | _stack_push_smallt(struct stack *stack, void *p, size_t size) { 63 | #if 0 64 | u8 *b = (u8*)p; 65 | printf("pushing small", ""); 66 | for (size_t i = 0; i < size; ++i) { 67 | printf(" %02x", b[i]); 68 | } 69 | printf("\n"); 70 | #endif 71 | assert(size <= sizeof(void*)); 72 | void *tmp = 0; 73 | memcpy(&tmp, p, size); 74 | stack_push(stack, tmp); 75 | } 76 | 77 | #endif /* BTCS_STACK_H */ 78 | -------------------------------------------------------------------------------- /stack.c: -------------------------------------------------------------------------------- 1 | 2 | #include "stack.h" 3 | #include 4 | #include 5 | #include 6 | 7 | void 8 | stack_clear(struct stack *stack) { 9 | memset(stack->bottom, 0, stack->capacity); 10 | stack->top = stack->bottom; 11 | } 12 | 13 | int 14 | stack_init_size(struct stack *stack, int capacity) { 15 | if (capacity > DEFAULT_STACK_SIZE) { 16 | void *bottom = calloc(capacity, sizeof(void*)); 17 | if (!bottom) return 0; 18 | stack->bottom = bottom; 19 | stack->top = bottom; 20 | stack->capacity = capacity; 21 | } 22 | else { 23 | stack->bottom = stack->_data; 24 | stack->top = stack->bottom; 25 | stack->capacity = DEFAULT_STACK_SIZE; 26 | } 27 | stack_clear(stack); 28 | return 1; 29 | } 30 | 31 | int 32 | stack_init(struct stack *stack) { 33 | return stack_init_size(stack, DEFAULT_STACK_SIZE); 34 | } 35 | 36 | void 37 | stack_free(struct stack *stack) { 38 | if (stack->capacity > DEFAULT_STACK_SIZE) 39 | free(stack->bottom); 40 | stack->bottom = stack->_data; 41 | } 42 | 43 | 44 | int 45 | stack_expand(struct stack *stack) { 46 | size_t newcap = stack->capacity * 2; 47 | void **bottom = 0; 48 | int size = stack_size(stack); 49 | 50 | #if DEBUG 51 | printf("expanding s(%d) %d -> %d\n", size, stack->capacity, newcap); 52 | #endif 53 | 54 | // XXX: might want to relax this to <= eventually 55 | assert(size == stack->capacity); 56 | 57 | if (stack->capacity <= DEFAULT_STACK_SIZE) { 58 | bottom = malloc(newcap * sizeof(void*)); 59 | if (!bottom) return 0; 60 | memcpy(bottom, stack->bottom, size * sizeof(void*)); 61 | } 62 | else { 63 | bottom = realloc(stack->bottom, newcap * sizeof(void*)); 64 | if (!bottom) return 0; 65 | } 66 | stack->capacity = newcap; 67 | stack->bottom = bottom; 68 | stack->top = bottom+size; 69 | return 1; 70 | } 71 | 72 | void 73 | stack_push(struct stack *stack, void *val) { 74 | #if 0 75 | printf("pushing: %d %p\n", stack_size(stack), val); 76 | #endif 77 | 78 | if ((stack_size(stack) + 1) > stack->capacity) { 79 | stack_expand(stack); 80 | } 81 | 82 | *stack->top++ = val; 83 | } 84 | 85 | void 86 | stack_erase(struct stack *stack, int pos) { 87 | if (stack_size(stack) == 0) return; 88 | size_t len = stack->top - (stack->top + pos); 89 | memcpy(stack->top + pos, stack->top + pos + 1, sizeof(stack->top) * len); 90 | stack->top--; 91 | } 92 | 93 | void * 94 | stack_pop(struct stack *stack) { 95 | assert(stack); 96 | assert(stack_size(stack) != 0); 97 | void * v = stack_top(stack, -1); 98 | stack->top--; 99 | return v; 100 | } 101 | 102 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /test/tests.csv: -------------------------------------------------------------------------------- 1 | description,args,input,expected output 2 | test_simple,,OP_1 ,script 1 script_hex 51 stack 1 stack_hex 01 results success 3 | test_nip,,OP_1 OP_2 OP_NIP ,script 1 2 OP_NIP script_hex 515277 stack 2 stack_hex 02 results success 4 | test_2dup_not_enough_input,,OP_1 OP_2DUP ,script 1 OP_2DUP script_hex 516e stack 1 stack_hex 01 results error:2:INVALID_STACK_OPERATION:2DUP 5 | negative_integer,,-2 ,script -2 script_hex 0182 stack 0x82 stack_hex 82 results success 6 | add_negative_two,,-2 -2 OP_ADD ,script -2 -2 OP_ADD script_hex 0182018293 stack -4 stack_hex 84 results success 7 | big_int_serializes_ok,,2147483647 2147483647 OP_ADD ,script 2147483647 2147483647 OP_ADD script_hex 04ffffff7f04ffffff7f93 stack @feffffff00 stack_hex feffffff00 results success 8 | test_small_int,,127 ,script 127 script_hex 017f stack 0x7f stack_hex 7f results success 9 | test_OP_1ADD,,16 OP_1ADD ,script 16 OP_1ADD script_hex 608b stack 17 stack_hex 11 results success 10 | test_OP_1SUB,,16 OP_1SUB ,script 16 OP_1SUB script_hex 608c stack 15 stack_hex 0f results success 11 | test_OP_NEGATE,,2 OP_NEGATE ,script 2 OP_NEGATE script_hex 528f stack -2 stack_hex 82 results success 12 | test_OP_NEGATE_negative,,-2 OP_NEGATE ,script -2 OP_NEGATE script_hex 01828f stack 2 stack_hex 02 results success 13 | test_OP_ABS,,2 OP_ABS ,script 2 OP_ABS script_hex 5290 stack 2 stack_hex 02 results success 14 | test_OP_ABS_negative,,-2 OP_ABS ,script -2 OP_ABS script_hex 018290 stack 2 stack_hex 02 results success 15 | sub_negative_two,,-2 -12 OP_SUB ,script -2 -12 OP_SUB script_hex 0182018c94 stack 10 stack_hex 0a results success 16 | test_OP_DROP,,-1 OP_DROP ,script -1 OP_DROP script_hex 4f75 stack stack_hex results success 17 | test_OP_NOT_0,,0 OP_NOT ,script 0 OP_NOT script_hex 0091 stack 1 stack_hex 01 results success 18 | test_OP_NOT_1,,1 OP_NOT ,script 1 OP_NOT script_hex 5191 stack 0 stack_hex 00 results success 19 | test_OP_NOT_2,,2 OP_NOT ,script 2 OP_NOT script_hex 5291 stack 0 stack_hex 00 results success 20 | test_OP_0NOTEQUAL0,,0 OP_0NOTEQUAL ,script 0 OP_0NOTEQUAL script_hex 0092 stack 0 stack_hex 00 results success 21 | test_OP_0NOTEQUAL2,,2 OP_0NOTEQUAL ,script 2 OP_0NOTEQUAL script_hex 5292 stack 1 stack_hex 01 results success 22 | test_ADD_SUB,,111 1 OP_ADD 12 OP_SUB ,script 111 1 OP_ADD 12 OP_SUB script_hex 016f51935c94 stack 100 stack_hex 64 results success 23 | test_BOOLAND,,1 1 OP_BOOLAND ,script 1 1 OP_BOOLAND script_hex 51519a stack 1 stack_hex 01 results success 24 | test_BOOLAND,,0 0 OP_BOOLAND ,script 0 0 OP_BOOLAND script_hex 00009a stack 0 stack_hex 00 results success 25 | -------------------------------------------------------------------------------- /util.c: -------------------------------------------------------------------------------- 1 | 2 | #include "util.h" 3 | #include 4 | #include 5 | 6 | static bool char_to_hex(unsigned char *val, char c) 7 | { 8 | if (c >= '0' && c <= '9') { 9 | *val = c - '0'; 10 | return true; 11 | } 12 | if (c >= 'a' && c <= 'f') { 13 | *val = c - 'a' + 10; 14 | return true; 15 | } 16 | if (c >= 'A' && c <= 'F') { 17 | *val = c - 'A' + 10; 18 | return true; 19 | } 20 | return false; 21 | } 22 | 23 | bool hex_decode(const char *str, size_t *slen, void *buf, size_t bufsize) 24 | { 25 | unsigned char v1, v2; 26 | unsigned char *p = buf; 27 | int len = 0; 28 | 29 | while (*slen > 1) { 30 | if (!bufsize || !char_to_hex(&v1, str[0]) || !char_to_hex(&v2, str[1])) { 31 | *slen = len; 32 | return false; 33 | } 34 | *(p++) = (v1 << 4) | v2; 35 | str += 2; 36 | *slen -= 2; 37 | bufsize--; 38 | len += 2; 39 | } 40 | *slen = len; 41 | return *slen == 0 && bufsize == 0; 42 | } 43 | 44 | 45 | int read_fd(FILE *fd, unsigned char *buf, size_t buflen, size_t *written) 46 | { 47 | unsigned char *p = buf; 48 | int len = 0; 49 | *written = 0; 50 | 51 | do { 52 | len = fread(p, 1, 4096, fd); 53 | *written += len; 54 | p += len; 55 | if (p > buf + buflen) 56 | return 0; 57 | } while (len == 4096); 58 | 59 | return 1; 60 | } 61 | 62 | 63 | 64 | // if typedef doesn't exist (msvc, blah) 65 | ssize_t getline(char **lineptr, size_t *n, FILE *stream) { 66 | size_t pos; 67 | int c; 68 | 69 | if (lineptr == NULL || stream == NULL || n == NULL) { 70 | errno = EINVAL; 71 | return -1; 72 | } 73 | 74 | c = getc(stream); 75 | if (c == EOF) { 76 | return -1; 77 | } 78 | 79 | if (*lineptr == NULL) { 80 | *lineptr = malloc(128); 81 | if (*lineptr == NULL) { 82 | return -1; 83 | } 84 | *n = 128; 85 | } 86 | 87 | pos = 0; 88 | while(c != EOF) { 89 | if (pos + 1 >= *n) { 90 | size_t new_size = *n + (*n >> 2); 91 | if (new_size < 128) { 92 | new_size = 128; 93 | } 94 | char *new_ptr = realloc(*lineptr, new_size); 95 | if (new_ptr == NULL) { 96 | return -1; 97 | } 98 | *n = new_size; 99 | *lineptr = new_ptr; 100 | } 101 | 102 | ((unsigned char *)(*lineptr))[pos ++] = c; 103 | if (c == '\n') { 104 | break; 105 | } 106 | c = getc(stream); 107 | } 108 | 109 | (*lineptr)[pos] = '\0'; 110 | return pos; 111 | } 112 | 113 | int read_arg_or_stdin(const char *arg, unsigned char *buf, size_t buflen, 114 | size_t *written) 115 | { 116 | if (arg != NULL) { 117 | unsigned char *p = buf; 118 | bool done = false; 119 | for (size_t i = 0; i < buflen; i++) { 120 | *p = arg[i]; 121 | if (*p == 0 ) { 122 | done = true; 123 | break; 124 | } 125 | p++; 126 | } 127 | 128 | *written = p - buf; 129 | 130 | return done; 131 | } 132 | else { 133 | int ok = read_fd(stdin, buf, buflen, written); 134 | if (!ok) 135 | return ok; 136 | if (*written == 0) 137 | return 0; 138 | (*written)--; 139 | buf[*written] = 0; 140 | return ok; 141 | } 142 | } 143 | 144 | -------------------------------------------------------------------------------- /val.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "op.h" 4 | #include "val.h" 5 | #include "alloc.h" 6 | #include "script_num.h" 7 | 8 | static const char intbytes[] = { 9 | OP_1NEGATE, 10 | OP_0, 11 | OP_1, OP_2, OP_3, OP_4, OP_5, 12 | OP_6, OP_7, OP_8, OP_9, OP_10, 13 | OP_11, OP_12, OP_13, OP_14, OP_15, 14 | OP_16 15 | }; 16 | 17 | struct val 18 | val_from_int(s64 intval) { 19 | struct val val; 20 | struct num *sn; 21 | u16 ind; 22 | sn = num_pool_new(&ind); 23 | val.type = VT_SCRIPTNUM; 24 | val.ind = ind; 25 | sn->ind = ind; 26 | sn->val = intval; 27 | return val; 28 | } 29 | 30 | // TODO maybe replace this with serialize 31 | void val_bytes(struct val val, u32 *len, u8 *buf, int bufsize) { 32 | if (val.type == VT_DATA) 33 | val.type = VT_RAW; 34 | val_serialize(val, len, buf, bufsize); 35 | } 36 | 37 | void val_serialize(struct val val, u32 *len, u8 *buf, int bufsize) { 38 | struct num *sn; 39 | int n; 40 | u16 valsize; 41 | switch (val.type) { 42 | case VT_SCRIPTNUM: 43 | sn = num_pool_get(val.ind); 44 | assert(sn); 45 | 46 | /// TODO: if serialize_minimal 47 | sn_serialize(sn, buf, bufsize, &valsize); 48 | assert(valsize <= 0xFF); 49 | *len = valsize; 50 | return; 51 | case VT_OP: 52 | *len = 1; 53 | *buf = val.ind & 0xFF; 54 | return; 55 | case VT_DATA: 56 | case VT_RAW: { 57 | u8 *p; 58 | p = byte_pool_get(val.ind, len); 59 | memcpy(buf, p, *len); 60 | return; 61 | } 62 | case VT_SMALLINT: 63 | assert(0); 64 | *len = 1; 65 | n = val.ind; 66 | if (n >= -1 && n <= 16) { 67 | val.type = VT_SMALLINT; 68 | assert(bufsize >= 1); 69 | *buf = intbytes[n+1]; 70 | } 71 | else { 72 | assert(!"non-small VT_SMALLINT"); 73 | } 74 | return; 75 | } 76 | 77 | assert(!"val_serialize missing implementation"); 78 | } 79 | 80 | 81 | int val_eq(struct val a, struct val b) { 82 | u32 alen = 0, blen = 0; 83 | int eq = 0; 84 | 85 | static const int tmpsize = 4096; 86 | static u8 tmpa[4096]; 87 | static u8 tmpb[4096]; 88 | 89 | // TODO: do I need to serialize to compare? 90 | /* abytes = val_serialize(a, &alen, require_minimal); */ 91 | /* bbytes = val_serialize(b, &blen, require_minimal); */ 92 | val_serialize(a, &alen, tmpa, tmpsize); 93 | val_serialize(b, &blen, tmpb, tmpsize); 94 | // TODO: what if they're semantically equivalent? or does that matter 95 | // (eg. minimal vs not miniminal)? 96 | 97 | if (alen != blen) 98 | return 0; 99 | 100 | eq = memcmp(tmpa, tmpb, alen) == 0; 101 | 102 | return eq; 103 | } 104 | 105 | struct val val_cat(struct val a, struct val b) 106 | { 107 | struct val c = { .type = VT_RAW }; 108 | unsigned char *dst, *a_src, *b_src; 109 | u16 ind; 110 | u32 a_len, b_len; 111 | a_src = byte_pool_get(a.ind, &a_len); 112 | b_src = byte_pool_get(b.ind, &b_len); 113 | dst = byte_pool_new(a_len + b_len, &ind); 114 | memcpy(dst, a_src, a_len); 115 | memcpy(dst + a_len, b_src, b_len); 116 | c.ind = ind; 117 | return c; 118 | } 119 | 120 | struct val 121 | val_copy(struct val a) { 122 | u32 len; 123 | u16 newind; 124 | u8 *src, *dst; 125 | struct num *nsrc, *ndst; 126 | 127 | switch (a.type) { 128 | case VT_SMALLINT: 129 | return a; 130 | case VT_RAW: 131 | case VT_DATA: 132 | src = byte_pool_get(a.ind, &len); 133 | dst = byte_pool_new(len, &newind); 134 | memcpy(dst, src, len); 135 | a.ind = newind; 136 | return a; 137 | case VT_SCRIPTNUM: 138 | nsrc = num_pool_get(a.ind); 139 | ndst = num_pool_new(&newind); 140 | ndst->val = nsrc->val; 141 | return sn_to_val(ndst); 142 | default: 143 | assert(!"unhandle val_copy enum"); 144 | } 145 | } 146 | 147 | u32 148 | val_size(struct val val) { 149 | u32 len; 150 | 151 | switch (val.type) { 152 | case VT_DATA: { 153 | byte_pool_get(val.ind, &len); 154 | return len; 155 | } 156 | default: 157 | return 1; 158 | } 159 | } 160 | 161 | /* struct val */ 162 | /* val_int(s64 n) { */ 163 | /* struct val val; */ 164 | /* } */ 165 | -------------------------------------------------------------------------------- /mph-opcodes: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Easy Perfect Minimal Hashing 3 | # By Steve Hanov. Released to the public domain. 4 | # 5 | # Based on: 6 | # Edward A. Fox, Lenwood S. Heath, Qi Fan Chen and Amjad M. Daoud, 7 | # "Practical minimal perfect hash functions for large databases", CACM, 35(1):105-121 8 | # also a good reference: 9 | # Compress, Hash, and Displace algorithm by Djamal Belazzougui, 10 | # Fabiano C. Botelho, and Martin Dietzfelbinger 11 | import sys 12 | 13 | DICTIONARY = sys.argv[1] 14 | 15 | # Calculates a distinct hash function for a given string. Each value of the 16 | # integer d results in a different hash value. 17 | def hash( d, str ): 18 | if d == 0: d = 0x01000193 19 | 20 | # Use the FNV algorithm from http://isthe.com/chongo/tech/comp/fnv/ 21 | for c in str: 22 | d = ( (d * 0x01000193) ^ ord(c) ) & 0xffffffff; 23 | 24 | return d 25 | 26 | # Computes a minimal perfect hash table using the given python dictionary. It 27 | # returns a tuple (G, V). G and V are both arrays. G contains the intermediate 28 | # table of values needed to compute the index of the value in V. V contains the 29 | # values of the dictionary. 30 | def CreateMinimalPerfectHash( dict ): 31 | size = len(dict) 32 | 33 | # Step 1: Place all of the keys into buckets 34 | buckets = [ [] for i in range(size) ] 35 | G = [0] * size 36 | values = [None] * size 37 | 38 | for key in dict.keys(): 39 | buckets[hash(0, key) % size].append( key ) 40 | 41 | # Step 2: Sort the buckets and process the ones with the most items first. 42 | buckets.sort( key=len, reverse=True ) 43 | for b in range( size ): 44 | bucket = buckets[b] 45 | if len(bucket) <= 1: break 46 | 47 | d = 1 48 | item = 0 49 | slots = [] 50 | 51 | # Repeatedly try different values of d until we find a hash function 52 | # that places all items in the bucket into free slots 53 | while item < len(bucket): 54 | slot = hash( d, bucket[item] ) % size 55 | if values[slot] != None or slot in slots: 56 | d += 1 57 | item = 0 58 | slots = [] 59 | else: 60 | slots.append( slot ) 61 | item += 1 62 | 63 | G[hash(0, bucket[0]) % size] = d 64 | for i in range(len(bucket)): 65 | values[slots[i]] = dict[bucket[i]] 66 | 67 | # Only buckets with 1 item remain. Process them more quickly by directly 68 | # placing them into a free slot. Use a negative value of d to indicate 69 | # this. 70 | freelist = [] 71 | for i in range(size): 72 | if values[i] == None: freelist.append( i ) 73 | 74 | for b in range( b, size ): 75 | bucket = buckets[b] 76 | if len(bucket) == 0: break 77 | slot = freelist.pop() 78 | # We subtract one to ensure it's negative even if the zeroeth slot was 79 | # used. 80 | G[hash(0, bucket[0]) % size] = -slot-1 81 | values[slot] = dict[bucket[0]] 82 | 83 | return (G, values) 84 | 85 | # Look up a value in the hash table, defined by G and V. 86 | def PerfectHashLookup( G, V, key ): 87 | d = G[hash(0,key) % len(G)] 88 | if d < 0: return V[-d-1] 89 | return V[hash(d, key) % len(V)] 90 | 91 | dict = {} 92 | line = 1 93 | keys = map(lambda x: x.strip(), open(DICTIONARY, "rt").readlines()) 94 | for key in keys: 95 | dict[key] = line 96 | line += 1 97 | 98 | (G, V) = CreateMinimalPerfectHash( dict ) 99 | 100 | Gstrs = ",".join(map(str, G)) 101 | Vstrs = ",".join(map(str, V)) 102 | 103 | header = open('oplookup.h', 'w') 104 | 105 | 106 | 107 | header.write("/* THIS IS GENERATED FROM mph-opcodes DO NOT EDIT */\n\n") 108 | header.write("#ifndef BCS_OPLOOKUP_H\n") 109 | header.write("#define BCS_OPLOOKUP_H\n\n") 110 | 111 | header.write("#include \"misc.h\"\n") 112 | header.write("extern const int opcodes_g[{}];\n".format(len(G))) 113 | header.write("extern const int opcodes_v[{}];\n".format(len(V))) 114 | header.write("\n#endif /* BCS_OPLOOKUP_H */\n") 115 | header.close() 116 | 117 | cfile = open('oplookup.c', 'w') 118 | 119 | cfile.write("/* THIS IS GENERATED FROM mph-opcodes DO NOT EDIT */\n\n") 120 | cfile.write("#include \"oplookup.h\"\n".format(Gstrs)) 121 | cfile.write("const int opcodes_g[{}] = {{ {} }};\n".format(len(G), Gstrs)) 122 | cfile.write("const int opcodes_v[{}] = {{ {} }};\n".format(len(V), Vstrs)) 123 | cfile.close() 124 | -------------------------------------------------------------------------------- /ripemd160.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef CCAN_CRYPTO_RIPEMD160_H 3 | #define CCAN_CRYPTO_RIPEMD160_H 4 | /* BSD-MIT - see LICENSE file for details */ 5 | #include 6 | #include 7 | 8 | /* Uncomment this to use openssl's RIPEMD160 routines (and link with -lcrypto) */ 9 | /*#define CCAN_CRYPTO_RIPEMD160_USE_OPENSSL 1*/ 10 | 11 | #ifdef CCAN_CRYPTO_RIPEMD160_USE_OPENSSL 12 | #include 13 | #endif 14 | 15 | /** 16 | * struct ripemd160 - structure representing a completed RIPEMD160. 17 | * @u.u8: an unsigned char array. 18 | * @u.u32: a 32-bit integer array. 19 | * 20 | * Other fields may be added to the union in future. 21 | */ 22 | struct ripemd160 { 23 | union { 24 | /* Array of chars */ 25 | unsigned char u8[20]; 26 | /* Array of uint32_t */ 27 | uint32_t u32[5]; 28 | } u; 29 | }; 30 | 31 | /** 32 | * ripemd160 - return ripemd160 of an object. 33 | * @ripemd160: the ripemd160 to fill in 34 | * @p: pointer to memory, 35 | * @size: the number of bytes pointed to by @p 36 | * 37 | * The bytes pointed to by @p is RIPEMD160 hashed into @ripemd160. This is 38 | * equivalent to ripemd160_init(), ripemd160_update() then ripemd160_done(). 39 | */ 40 | void ripemd160(struct ripemd160 *ripemd, const void *p, size_t size); 41 | 42 | /** 43 | * struct ripemd160_ctx - structure to store running context for ripemd160 44 | */ 45 | struct ripemd160_ctx { 46 | #ifdef CCAN_CRYPTO_RIPEMD160_USE_OPENSSL 47 | RIPEMD160_CTX c; 48 | #else 49 | uint32_t s[5]; 50 | uint64_t bytes; 51 | union { 52 | uint32_t u32[16]; 53 | unsigned char u8[64]; 54 | } buf; 55 | #endif 56 | }; 57 | 58 | /** 59 | * ripemd160_init - initialize an RIPEMD160 context. 60 | * @ctx: the ripemd160_ctx to initialize 61 | * 62 | * This must be called before ripemd160_update or ripemd160_done, or 63 | * alternately you can assign RIPEMD160_INIT. 64 | * 65 | * If it was already initialized, this forgets anything which was 66 | * hashed before. 67 | * 68 | * Example: 69 | * static void hash_all(const char **arr, struct ripemd160 *hash) 70 | * { 71 | * size_t i; 72 | * struct ripemd160_ctx ctx; 73 | * 74 | * ripemd160_init(&ctx); 75 | * for (i = 0; arr[i]; i++) 76 | * ripemd160_update(&ctx, arr[i], strlen(arr[i])); 77 | * ripemd160_done(&ctx, hash); 78 | * } 79 | */ 80 | void ripemd160_init(struct ripemd160_ctx *ctx); 81 | 82 | /** 83 | * RIPEMD160_INIT - initializer for an RIPEMD160 context. 84 | * 85 | * This can be used to staticly initialize an RIPEMD160 context (instead 86 | * of ripemd160_init()). 87 | * 88 | * Example: 89 | * static void hash_all(const char **arr, struct ripemd160 *hash) 90 | * { 91 | * size_t i; 92 | * struct ripemd160_ctx ctx = RIPEMD160_INIT; 93 | * 94 | * for (i = 0; arr[i]; i++) 95 | * ripemd160_update(&ctx, arr[i], strlen(arr[i])); 96 | * ripemd160_done(&ctx, hash); 97 | * } 98 | */ 99 | #ifdef CCAN_CRYPTO_RIPEMD160_USE_OPENSSL 100 | #define RIPEMD160_INIT \ 101 | { { 0x67452301ul, 0xEFCDAB89ul, 0x98BADCFEul, 0x10325476ul, \ 102 | 0xC3D2E1F0ul, \ 103 | 0x0, 0x0, \ 104 | { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, \ 105 | 0 } } 106 | #else 107 | #define RIPEMD160_INIT \ 108 | { { 0x67452301ul, 0xEFCDAB89ul, 0x98BADCFEul, 0x10325476ul, \ 109 | 0xC3D2E1F0ul }, 0, {{ 0 }} } 110 | #endif 111 | 112 | /** 113 | * ripemd160_update - include some memory in the hash. 114 | * @ctx: the ripemd160_ctx to use 115 | * @p: pointer to memory, 116 | * @size: the number of bytes pointed to by @p 117 | * 118 | * You can call this multiple times to hash more data, before calling 119 | * ripemd160_done(). 120 | */ 121 | void ripemd160_update(struct ripemd160_ctx *ctx, const void *p, size_t size); 122 | 123 | /** 124 | * ripemd160_done - finish RIPEMD160 and return the hash 125 | * @ctx: the ripemd160_ctx to complete 126 | * @res: the hash to return. 127 | * 128 | * Note that @ctx is *destroyed* by this, and must be reinitialized. 129 | * To avoid that, pass a copy instead. 130 | */ 131 | void ripemd160_done(struct ripemd160_ctx *ripemd160, struct ripemd160 *res); 132 | 133 | /* Add various types to an RIPEMD160 hash */ 134 | void ripemd160_u8(struct ripemd160_ctx *ctx, uint8_t v); 135 | void ripemd160_u16(struct ripemd160_ctx *ctx, uint16_t v); 136 | void ripemd160_u32(struct ripemd160_ctx *ctx, uint32_t v); 137 | void ripemd160_u64(struct ripemd160_ctx *ctx, uint64_t v); 138 | 139 | /* Add as little-endian */ 140 | void ripemd160_le16(struct ripemd160_ctx *ctx, uint16_t v); 141 | void ripemd160_le32(struct ripemd160_ctx *ctx, uint32_t v); 142 | void ripemd160_le64(struct ripemd160_ctx *ctx, uint64_t v); 143 | 144 | /* Add as big-endian */ 145 | void ripemd160_be16(struct ripemd160_ctx *ctx, uint16_t v); 146 | void ripemd160_be32(struct ripemd160_ctx *ctx, uint32_t v); 147 | void ripemd160_be64(struct ripemd160_ctx *ctx, uint64_t v); 148 | #endif /* CCAN_CRYPTO_RIPEMD160_H */ 149 | -------------------------------------------------------------------------------- /sha256.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef CCAN_CRYPTO_SHA256_H 3 | #define CCAN_CRYPTO_SHA256_H 4 | 5 | 6 | /** Output length for `wally_sha256` */ 7 | #define SHA256_LEN 32 8 | 9 | 10 | /* BSD-MIT - see LICENSE file for details */ 11 | /* #include "config.h" */ 12 | #include 13 | #include 14 | 15 | /* Uncomment this to use openssl's SHA256 routines (and link with -lcrypto) */ 16 | /*#define CCAN_CRYPTO_SHA256_USE_OPENSSL 1*/ 17 | 18 | #ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL 19 | #include 20 | #endif 21 | 22 | /** 23 | * struct sha256 - structure representing a completed SHA256. 24 | * @u.u8: an unsigned char array. 25 | * @u.u32: a 32-bit integer array. 26 | * 27 | * Other fields may be added to the union in future. 28 | */ 29 | struct sha256 { 30 | union { 31 | uint32_t u32[8]; 32 | unsigned char u8[32]; 33 | } u; 34 | }; 35 | 36 | /** 37 | * sha256 - return sha256 of an object. 38 | * @sha256: the sha256 to fill in 39 | * @p: pointer to memory, 40 | * @size: the number of bytes pointed to by @p 41 | * 42 | * The bytes pointed to by @p is SHA256 hashed into @sha256. This is 43 | * equivalent to sha256_init(), sha256_update() then sha256_done(). 44 | */ 45 | void sha256(struct sha256 *sha, const void *p, size_t size); 46 | 47 | /** 48 | * struct sha256_ctx - structure to store running context for sha256 49 | */ 50 | struct sha256_ctx { 51 | #ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL 52 | SHA256_CTX c; 53 | #else 54 | uint32_t s[8]; 55 | union { 56 | uint32_t u32[16]; 57 | unsigned char u8[64]; 58 | } buf; 59 | size_t bytes; 60 | #endif 61 | }; 62 | 63 | /** 64 | * sha256_init - initialize an SHA256 context. 65 | * @ctx: the sha256_ctx to initialize 66 | * 67 | * This must be called before sha256_update or sha256_done, or 68 | * alternately you can assign SHA256_INIT. 69 | * 70 | * If it was already initialized, this forgets anything which was 71 | * hashed before. 72 | * 73 | * Example: 74 | * static void hash_all(const char **arr, struct sha256 *hash) 75 | * { 76 | * size_t i; 77 | * struct sha256_ctx ctx; 78 | * 79 | * sha256_init(&ctx); 80 | * for (i = 0; arr[i]; i++) 81 | * sha256_update(&ctx, arr[i], strlen(arr[i])); 82 | * sha256_done(&ctx, hash); 83 | * } 84 | */ 85 | void sha256_init(struct sha256_ctx *ctx); 86 | 87 | /** 88 | * SHA256_INIT - initializer for an SHA256 context. 89 | * 90 | * This can be used to statically initialize an SHA256 context (instead 91 | * of sha256_init()). 92 | * 93 | * Example: 94 | * static void hash_all(const char **arr, struct sha256 *hash) 95 | * { 96 | * size_t i; 97 | * struct sha256_ctx ctx = SHA256_INIT; 98 | * 99 | * for (i = 0; arr[i]; i++) 100 | * sha256_update(&ctx, arr[i], strlen(arr[i])); 101 | * sha256_done(&ctx, hash); 102 | * } 103 | */ 104 | #ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL 105 | #define SHA256_INIT \ 106 | { { { 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, \ 107 | 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul }, \ 108 | 0x0, 0x0, \ 109 | { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, \ 110 | 0x0, 0x20 } } 111 | #else 112 | #define SHA256_INIT \ 113 | { { 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, \ 114 | 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul }, \ 115 | { { 0 } }, 0 } 116 | #endif 117 | 118 | /** 119 | * sha256_update - include some memory in the hash. 120 | * @ctx: the sha256_ctx to use 121 | * @p: pointer to memory, 122 | * @size: the number of bytes pointed to by @p 123 | * 124 | * You can call this multiple times to hash more data, before calling 125 | * sha256_done(). 126 | */ 127 | void sha256_update(struct sha256_ctx *ctx, const void *p, size_t size); 128 | 129 | /** 130 | * sha256_done - finish SHA256 and return the hash 131 | * @ctx: the sha256_ctx to complete 132 | * @res: the hash to return. 133 | * 134 | * Note that @ctx is *destroyed* by this, and must be reinitialized. 135 | * To avoid that, pass a copy instead. 136 | */ 137 | void sha256_done(struct sha256_ctx *sha256, struct sha256 *res); 138 | 139 | /* Add various types to an SHA256 hash */ 140 | void sha256_u8(struct sha256_ctx *ctx, uint8_t v); 141 | void sha256_u16(struct sha256_ctx *ctx, uint16_t v); 142 | void sha256_u32(struct sha256_ctx *ctx, uint32_t v); 143 | void sha256_u64(struct sha256_ctx *ctx, uint64_t v); 144 | 145 | /* Add as little-endian */ 146 | void sha256_le16(struct sha256_ctx *ctx, uint16_t v); 147 | void sha256_le32(struct sha256_ctx *ctx, uint32_t v); 148 | void sha256_le64(struct sha256_ctx *ctx, uint64_t v); 149 | 150 | /* Add as big-endian */ 151 | void sha256_be16(struct sha256_ctx *ctx, uint16_t v); 152 | void sha256_be32(struct sha256_ctx *ctx, uint32_t v); 153 | void sha256_be64(struct sha256_ctx *ctx, uint64_t v); 154 | 155 | int sha256d(const unsigned char *bytes, size_t bytes_len, 156 | unsigned char *bytes_out, size_t len); 157 | 158 | #endif /* CCAN_CRYPTO_SHA256_H */ 159 | -------------------------------------------------------------------------------- /script_num.c: -------------------------------------------------------------------------------- 1 | 2 | #include "script_num.h" 3 | #include "alloc.h" 4 | #include "val.h" 5 | #include 6 | #include 7 | 8 | /** 9 | * Numeric opcodes (OP_1ADD, etc) are restricted to operating on 4-byte 10 | * integers. The semantics are subtle, though: operands must be in the range 11 | * [-2^31 +1...2^31 -1], but results may overflow (and are valid as long as they 12 | * are not used in a subsequent numeric operation). struct num enforces those 13 | * semantics by storing results as an int64 and allowing out-of-range values to 14 | * be returned, but throwing an exception if arithmetic is done or the result is 15 | * interpreted as an integer. 16 | */ 17 | 18 | 19 | void 20 | sn_from_int(s64 n, struct num *sn) { 21 | sn->ind = -1; 22 | sn->val = n; 23 | } 24 | 25 | 26 | /* enum sn_result */ 27 | /* sn_to_int(struct num *sn, int *res) { */ 28 | /* if (sn_overflowed(sn)) { */ 29 | /* return SN_ERR_OVERFLOWED_INT; */ 30 | /* } */ 31 | /* } */ 32 | 33 | 34 | void sn_serialize(struct num *sn, u8 *buf, int bufsize, u16 *len) { 35 | u8 *p = buf; 36 | 37 | if(sn->val == 0) { 38 | *len = 0; 39 | return; 40 | } 41 | 42 | const int neg = sn->val < 0; 43 | u64 absvalue = neg ? -(sn->val) : sn->val; 44 | 45 | while(absvalue) { 46 | *(p++) = absvalue & 0xff; 47 | assert((p - buf) <= bufsize); 48 | absvalue >>= 8; 49 | } 50 | 51 | // - If the most significant byte is >= 0x80 and the value is positive, push a 52 | // new zero-byte to make the significant byte < 0x80 again. 53 | 54 | // - If the most significant byte is >= 0x80 and the value is negative, push a 55 | // new 0x80 byte that will be popped off when converting to an integral. 56 | 57 | // - If the most significant byte is < 0x80 and the value is negative, add 58 | // 0x80 to it, since it will be subtracted and interpreted as a negative when 59 | // converting to an integral. 60 | 61 | if (*(p - 1) & 0x80) 62 | *(p++) = neg ? 0x80 : 0; 63 | else if (neg) 64 | *(p - 1) |= 0x80; 65 | 66 | *len = p - buf; 67 | } 68 | 69 | static inline int 70 | int_overflowed(s64 val) { 71 | return val < INT_MIN || val > INT_MAX; 72 | } 73 | 74 | 75 | int 76 | sn_overflowed(struct num *num) { 77 | return int_overflowed(num->val); 78 | } 79 | 80 | 81 | s64 82 | int_from_data(u8 *data, u16 size) { 83 | s64 result = 0; 84 | 85 | if (size == 0) 86 | return 0; 87 | 88 | for (size_t i = 0; i != size; ++i) 89 | result |= (s64)((data[i]) << 8*i); 90 | 91 | // If the input vector's most significant byte is 0x80, remove it from 92 | // the result's msb and return a negative. 93 | if (data[size-1] & 0x80) { 94 | return -((s64)(result & ~(0x80ULL << (8 * (size - 1))))); 95 | } 96 | 97 | return result; 98 | } 99 | 100 | 101 | enum sn_result 102 | sn_from_data(u8 *data, u16 size, struct num **num) { 103 | u16 ind; 104 | s64 i; 105 | if (size > 4) 106 | return SN_ERR_OVERFLOWED_INT; 107 | i = int_from_data(data, size); 108 | /* printf("%" PRId64" okkkk\n", i); */ 109 | *num = num_pool_new(&ind); 110 | (*num)->val = i; 111 | (*num)->ind = ind; 112 | return SN_SUCCESS; 113 | } 114 | 115 | 116 | // Return a script num only if it's still a 4-byte integer 117 | enum sn_result sn_from_val(struct val val, struct num ** sn) { 118 | 119 | switch (val.type) { 120 | case VT_SMALLINT: 121 | case VT_SCRIPTNUM: 122 | *sn = num_pool_get(val.ind); 123 | assert((*sn)->ind == val.ind); 124 | assert(*sn); 125 | 126 | // we're trying to return a scriptnum that is larger than 4 bytes. This is not 127 | // a valid scriptnum at this point. return an error. 128 | if (sn_overflowed(*sn)) { 129 | *sn = 0; 130 | return SN_ERR_OVERFLOWED_INT; 131 | } 132 | 133 | if (val.type == VT_SMALLINT) 134 | (*sn)->val = val.ind; 135 | 136 | return SN_SUCCESS; 137 | case VT_RAW: 138 | case VT_DATA: { 139 | u8 *data; 140 | u32 size; 141 | enum sn_result res; 142 | assert(val.ind != -1); 143 | data = byte_pool_get(val.ind, &size); 144 | return sn_from_data(data, size, sn); 145 | } 146 | } 147 | 148 | printf("type: %d\n", val.type); 149 | assert(!"sn_from_val: unhandled"); 150 | 151 | return SN_SUCCESS; 152 | } 153 | 154 | struct val 155 | sn_to_val(struct num *sn) { 156 | struct val val; 157 | struct num *snref; 158 | u16 ind; 159 | 160 | if (sn_overflowed(sn)) { 161 | u16 ind, len; 162 | static u8 tmp[8]; 163 | sn_serialize(sn, tmp, 8, &len); 164 | u8 *data = byte_pool_new(len, &ind); 165 | memcpy(data, tmp, len); 166 | val.type = VT_DATA; 167 | val.ind = ind; 168 | } 169 | else 170 | { 171 | val.type = VT_SCRIPTNUM; 172 | if (sn->ind > -1) 173 | val.ind = sn->ind; 174 | else { 175 | snref = num_pool_new(&ind); 176 | snref->val = sn->val; 177 | val.ind = ind; 178 | } 179 | 180 | } 181 | return val; 182 | } 183 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /op.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef BCS_OP_H 3 | #define BCS_OP_H 4 | 5 | #include "misc.h" 6 | #include "stack.h" 7 | #include "val.h" 8 | #include 9 | #include 10 | 11 | enum opcode 12 | { 13 | // push value 14 | OP_0 = 0x00, 15 | OP_FALSE = OP_0, 16 | OP_PUSHDATA1 = 0x4c, 17 | OP_PUSHDATA2 = 0x4d, 18 | OP_PUSHDATA4 = 0x4e, 19 | OP_1NEGATE = 0x4f, 20 | OP_RESERVED = 0x50, 21 | OP_1 = 0x51, 22 | OP_TRUE=OP_1, 23 | OP_2 = 0x52, 24 | OP_3 = 0x53, 25 | OP_4 = 0x54, 26 | OP_5 = 0x55, 27 | OP_6 = 0x56, 28 | OP_7 = 0x57, 29 | OP_8 = 0x58, 30 | OP_9 = 0x59, 31 | OP_10 = 0x5a, 32 | OP_11 = 0x5b, 33 | OP_12 = 0x5c, 34 | OP_13 = 0x5d, 35 | OP_14 = 0x5e, 36 | OP_15 = 0x5f, 37 | OP_16 = 0x60, 38 | 39 | // control 40 | OP_NOP = 0x61, 41 | OP_VER = 0x62, 42 | OP_IF = 0x63, 43 | OP_NOTIF = 0x64, 44 | OP_VERIF = 0x65, 45 | OP_VERNOTIF = 0x66, 46 | OP_ELSE = 0x67, 47 | OP_ENDIF = 0x68, 48 | OP_VERIFY = 0x69, 49 | OP_RETURN = 0x6a, 50 | 51 | // stack ops 52 | OP_TOALTSTACK = 0x6b, 53 | OP_FROMALTSTACK = 0x6c, 54 | OP_2DROP = 0x6d, 55 | OP_2DUP = 0x6e, 56 | OP_3DUP = 0x6f, 57 | OP_2OVER = 0x70, 58 | OP_2ROT = 0x71, 59 | OP_2SWAP = 0x72, 60 | OP_IFDUP = 0x73, 61 | OP_DEPTH = 0x74, 62 | OP_DROP = 0x75, 63 | OP_DUP = 0x76, 64 | OP_NIP = 0x77, 65 | OP_OVER = 0x78, 66 | OP_PICK = 0x79, 67 | OP_ROLL = 0x7a, 68 | OP_ROT = 0x7b, 69 | OP_SWAP = 0x7c, 70 | OP_TUCK = 0x7d, 71 | 72 | // splice ops 73 | OP_CAT = 0x7e, 74 | OP_SUBSTR = 0x7f, 75 | OP_LEFT = 0x80, 76 | OP_RIGHT = 0x81, 77 | OP_SIZE = 0x82, 78 | 79 | // bit logic 80 | OP_INVERT = 0x83, 81 | OP_AND = 0x84, 82 | OP_OR = 0x85, 83 | OP_XOR = 0x86, 84 | OP_EQUAL = 0x87, 85 | OP_EQUALVERIFY = 0x88, 86 | OP_RESERVED1 = 0x89, 87 | OP_RESERVED2 = 0x8a, 88 | 89 | // numeric 90 | OP_1ADD = 0x8b, 91 | OP_1SUB = 0x8c, 92 | OP_2MUL = 0x8d, 93 | OP_2DIV = 0x8e, 94 | OP_NEGATE = 0x8f, 95 | OP_ABS = 0x90, 96 | OP_NOT = 0x91, 97 | OP_0NOTEQUAL = 0x92, 98 | 99 | OP_ADD = 0x93, 100 | OP_SUB = 0x94, 101 | OP_MUL = 0x95, 102 | OP_DIV = 0x96, 103 | OP_MOD = 0x97, 104 | OP_LSHIFT = 0x98, 105 | OP_RSHIFT = 0x99, 106 | 107 | OP_BOOLAND = 0x9a, 108 | OP_BOOLOR = 0x9b, 109 | OP_NUMEQUAL = 0x9c, 110 | OP_NUMEQUALVERIFY = 0x9d, 111 | OP_NUMNOTEQUAL = 0x9e, 112 | OP_LESSTHAN = 0x9f, 113 | OP_GREATERTHAN = 0xa0, 114 | OP_LESSTHANOREQUAL = 0xa1, 115 | OP_GREATERTHANOREQUAL = 0xa2, 116 | OP_MIN = 0xa3, 117 | OP_MAX = 0xa4, 118 | 119 | OP_WITHIN = 0xa5, 120 | 121 | // crypto 122 | OP_RIPEMD160 = 0xa6, 123 | OP_SHA1 = 0xa7, 124 | OP_SHA256 = 0xa8, 125 | OP_HASH160 = 0xa9, 126 | OP_HASH256 = 0xaa, 127 | OP_CODESEPARATOR = 0xab, 128 | OP_CHECKSIG = 0xac, 129 | OP_CHECKSIGVERIFY = 0xad, 130 | OP_CHECKMULTISIG = 0xae, 131 | OP_CHECKMULTISIGVERIFY = 0xaf, 132 | 133 | // expansion 134 | OP_NOP1 = 0xb0, 135 | OP_CHECKLOCKTIMEVERIFY = 0xb1, 136 | OP_NOP2 = OP_CHECKLOCKTIMEVERIFY, 137 | OP_CHECKSEQUENCEVERIFY = 0xb2, 138 | OP_NOP3 = OP_CHECKSEQUENCEVERIFY, 139 | OP_NOP4 = 0xb3, 140 | OP_NOP5 = 0xb4, 141 | OP_NOP6 = 0xb5, 142 | OP_NOP7 = 0xb6, 143 | OP_NOP8 = 0xb7, 144 | OP_NOP9 = 0xb8, 145 | OP_NOP10 = 0xb9, 146 | 147 | 148 | // template matching params 149 | OP_SMALLINTEGER = 0xfa, 150 | OP_PUBKEYS = 0xfb, 151 | OP_PUBKEYHASH = 0xfd, 152 | OP_PUBKEY = 0xfe, 153 | 154 | OP_INVALIDOPCODE = 0xff, 155 | }; 156 | 157 | 158 | enum opcode_token 159 | { 160 | // push value 161 | _OP_0=1, 162 | _OP_FALSE, 163 | _OP_PUSHDATA1, 164 | _OP_PUSHDATA2, 165 | _OP_PUSHDATA4, 166 | _OP_1NEGATE, 167 | _OP_RESERVED, 168 | _OP_1, 169 | _OP_TRUE, 170 | _OP_2, 171 | _OP_3, 172 | _OP_4, 173 | _OP_5, 174 | _OP_6, 175 | _OP_7, 176 | _OP_8, 177 | _OP_9, 178 | _OP_10, 179 | _OP_11, 180 | _OP_12, 181 | _OP_13, 182 | _OP_14, 183 | _OP_15, 184 | _OP_16, 185 | 186 | // control 187 | _OP_NOP, 188 | _OP_VER, 189 | _OP_IF, 190 | _OP_NOTIF, 191 | _OP_VERIF, 192 | _OP_VERNOTIF, 193 | _OP_ELSE, 194 | _OP_ENDIF, 195 | _OP_VERIFY, 196 | _OP_RETURN, 197 | 198 | // stack ops 199 | _OP_TOALTSTACK, 200 | _OP_FROMALTSTACK, 201 | _OP_2DROP, 202 | _OP_2DUP, 203 | _OP_3DUP, 204 | _OP_2OVER, 205 | _OP_2ROT, 206 | _OP_2SWAP, 207 | _OP_IFDUP, 208 | _OP_DEPTH, 209 | _OP_DROP, 210 | _OP_DUP, 211 | _OP_NIP, 212 | _OP_OVER, 213 | _OP_PICK, 214 | _OP_ROLL, 215 | _OP_ROT, 216 | _OP_SWAP, 217 | _OP_TUCK, 218 | 219 | // splice ops 220 | _OP_CAT, 221 | _OP_SUBSTR, 222 | _OP_LEFT, 223 | _OP_RIGHT, 224 | _OP_SIZE, 225 | 226 | // bit logic 227 | _OP_INVERT, 228 | _OP_AND, 229 | _OP_OR, 230 | _OP_XOR, 231 | _OP_EQUAL, 232 | _OP_EQUALVERIFY, 233 | _OP_RESERVED1, 234 | _OP_RESERVED2, 235 | 236 | // numeric 237 | _OP_1ADD, 238 | _OP_1SUB, 239 | _OP_2MUL, 240 | _OP_2DIV, 241 | _OP_NEGATE, 242 | _OP_ABS, 243 | _OP_NOT, 244 | _OP_0NOTEQUAL, 245 | 246 | _OP_ADD, 247 | _OP_SUB, 248 | _OP_MUL, 249 | _OP_DIV, 250 | _OP_MOD, 251 | _OP_LSHIFT, 252 | _OP_RSHIFT, 253 | 254 | _OP_BOOLAND, 255 | _OP_BOOLOR, 256 | _OP_NUMEQUAL, 257 | _OP_NUMEQUALVERIFY, 258 | _OP_NUMNOTEQUAL, 259 | _OP_LESSTHAN, 260 | _OP_GREATERTHAN, 261 | _OP_LESSTHANOREQUAL, 262 | _OP_GREATERTHANOREQUAL, 263 | _OP_MIN, 264 | _OP_MAX, 265 | 266 | _OP_WITHIN, 267 | 268 | // crypto 269 | _OP_RIPEMD160, 270 | _OP_SHA1, 271 | _OP_SHA256, 272 | _OP_HASH160, 273 | _OP_HASH256, 274 | _OP_CODESEPARATOR, 275 | _OP_CHECKSIG, 276 | _OP_CHECKSIGVERIFY, 277 | _OP_CHECKMULTISIG, 278 | _OP_CHECKMULTISIGVERIFY, 279 | 280 | // expansion 281 | _OP_NOP1, 282 | _OP_CHECKLOCKTIMEVERIFY, 283 | _OP_NOP2, 284 | _OP_CHECKSEQUENCEVERIFY, 285 | _OP_NOP3, 286 | _OP_NOP4, 287 | _OP_NOP5, 288 | _OP_NOP6, 289 | _OP_NOP7, 290 | _OP_NOP8, 291 | _OP_NOP9, 292 | _OP_NOP10, 293 | 294 | 295 | // template matching params 296 | _OP_SMALLINTEGER, 297 | _OP_PUBKEYS, 298 | _OP_PUBKEYHASH, 299 | _OP_PUBKEY, 300 | 301 | _OP_INVALIDOPCODE, 302 | }; 303 | 304 | // Maximum value that an opcode can be 305 | static const unsigned int MAX_OPCODE = OP_NOP10; 306 | 307 | void op_add(enum opcode); 308 | const char * op_name(enum opcode); 309 | enum opcode op_tokenize(char *); 310 | void val_print(struct val); 311 | const char * val_name(struct val); 312 | 313 | 314 | 315 | #endif /* BCS_OP_H */ 316 | -------------------------------------------------------------------------------- /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]