-
Notifications
You must be signed in to change notification settings - Fork 382
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge commit '13f988a70653463000090b3377c532ad7d09f516' as 'src/simpl…
…icity'
- Loading branch information
Showing
89 changed files
with
35,603 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
OBJS := bitstream.o dag.o deserialize.o eval.o frame.o jets.o jets-secp256k1.o rsort.o sha256.o type.o typeInference.o primitive/elements/env.o primitive/elements/exec.o primitive/elements/ops.o primitive/elements/jets.o primitive/elements/primitive.o | ||
TEST_OBJS := test.o hashBlock.o schnorr0.o schnorr6.o primitive/elements/checkSigHashAllTx1.o | ||
|
||
# From https://fastcompression.blogspot.com/2019/01/compiler-warnings.html | ||
CWARN := -Werror -Wall -Wextra -Wcast-qual -Wcast-align -Wstrict-aliasing -Wpointer-arith -Winit-self -Wshadow -Wswitch-enum -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wfloat-equal -Wundef -Wconversion | ||
|
||
ifneq ($(doCheck), 1) | ||
CPPFLAGS := $(CPPFLAGS) -DNDEBUG | ||
endif | ||
|
||
ifneq ($(strip $(SINGLE_THREADED)),) | ||
# SINGLE_THREADED is non-empty | ||
CPPFLAGS := $(CPPFLAGS) -DSINGLE_THREADED | ||
endif | ||
|
||
CFLAGS := -I include | ||
|
||
ifeq ($(strip $(SINGLE_THREADED)),) | ||
# SINGLE_THREADED is empty | ||
LDFLAGS := -pthread | ||
endif | ||
|
||
# libsecp256k1 is full of conversion warnings, so we compile jets-secp256k1.c separately. | ||
jets-secp256k1.o: jets-secp256k1.c | ||
$(CC) -c $(CFLAGS) $(CWARN) -Wno-conversion $(CPPFLAGS) -o $@ $< | ||
|
||
primitive/elements/jets.o: primitive/elements/jets.c | ||
$(CC) -c $(CFLAGS) $(CWARN) -Wno-switch-enum -Wswitch $(CPPFLAGS) -o $@ $< | ||
|
||
%.o: %.c | ||
$(CC) -c $(CFLAGS) $(CWARN) $(CPPFLAGS) -o $@ $< | ||
|
||
libElementsSimplicity.a: $(OBJS) | ||
ar rcs $@ $^ | ||
|
||
test: $(TEST_OBJS) libElementsSimplicity.a | ||
$(CC) $^ -o $@ $(LDFLAGS) | ||
|
||
install: libElementsSimplicity.a | ||
mkdir -p $(out)/lib | ||
cp $^ $(out)/lib/ | ||
cp -R include $(out)/include | ||
|
||
check: test | ||
./test | ||
|
||
clean: | ||
-rm -f test libElementsSimplicity.a $(TEST_OBJS) $(OBJS) | ||
|
||
.PHONY: install check clean |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
_Static_assert( | ||
0x20 == ' ' && 0x40 == '@' && 0x60 == '`' && | ||
0x21 == '!' && 0x41 == 'A' && 0x61 == 'a' && | ||
0x22 == '"' && 0x42 == 'B' && 0x62 == 'b' && | ||
0x23 == '#' && 0x43 == 'C' && 0x63 == 'c' && | ||
0x24 == '$' && 0x44 == 'D' && 0x64 == 'd' && | ||
0x25 == '%' && 0x45 == 'E' && 0x65 == 'e' && | ||
0x26 == '&' && 0x46 == 'F' && 0x66 == 'f' && | ||
0x27 == '\'' && 0x47 == 'G' && 0x67 == 'g' && | ||
0x28 == '(' && 0x48 == 'H' && 0x68 == 'h' && | ||
0x29 == ')' && 0x49 == 'I' && 0x69 == 'i' && | ||
0x2a == '*' && 0x4a == 'J' && 0x6a == 'j' && | ||
0x2b == '+' && 0x4b == 'K' && 0x6b == 'k' && | ||
0x2c == ',' && 0x4c == 'L' && 0x6c == 'l' && | ||
0x2d == '-' && 0x4d == 'M' && 0x6d == 'm' && | ||
0x2e == '.' && 0x4e == 'N' && 0x6e == 'n' && | ||
0x2f == '/' && 0x4f == 'O' && 0x6f == 'o' && | ||
0x30 == '0' && 0x50 == 'P' && 0x70 == 'p' && | ||
0x31 == '1' && 0x51 == 'Q' && 0x71 == 'q' && | ||
0x32 == '2' && 0x52 == 'R' && 0x72 == 'r' && | ||
0x33 == '3' && 0x53 == 'S' && 0x73 == 's' && | ||
0x34 == '4' && 0x54 == 'T' && 0x74 == 't' && | ||
0x35 == '5' && 0x55 == 'U' && 0x75 == 'u' && | ||
0x36 == '6' && 0x56 == 'V' && 0x76 == 'v' && | ||
0x37 == '7' && 0x57 == 'W' && 0x77 == 'w' && | ||
0x38 == '8' && 0x58 == 'X' && 0x78 == 'x' && | ||
0x39 == '9' && 0x59 == 'Y' && 0x79 == 'y' && | ||
0x3a == ':' && 0x5a == 'Z' && 0x7a == 'z' && | ||
0x3b == ';' && 0x5b == '[' && 0x7b == '{' && | ||
0x3c == '<' && 0x5c == '\\' && 0x7c == '|' && | ||
0x3d == '=' && 0x5d == ']' && 0x7d == '}' && | ||
0x3e == '>' && 0x5e == '^' && 0x7e == '~' && | ||
0x3f == '?' && 0x5f == '_' | ||
, "ASCII character set required"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
#include "bitstream.h" | ||
|
||
#include <assert.h> | ||
#include <limits.h> | ||
#include <stdlib.h> | ||
|
||
/* Closes a bitstream by consuming all remaining bits. | ||
* Returns false if CHAR_BIT or more bits remain in the stream or if any remaining bits are non-zero. | ||
* | ||
* Precondition: NULL != stream | ||
*/ | ||
bool closeBitstream(bitstream* stream) { | ||
if (1 < stream->len) return false; /* If there is more than one byte remaining. */ | ||
if (1 == stream->len && /* If there is one byte remaining */ | ||
(0 == stream->offset || /* and either no bits have been consumed */ | ||
0 != (*stream->arr & (UCHAR_MAX >> stream->offset)) /* or any of the unconsumed bits are non-zero */ | ||
)) return false; | ||
/* Otherwise there are either 0 bits remaining or there are between 1 and CHAR_BITS-1 bits remaining and they are all zero. */ | ||
*stream = (bitstream){0}; | ||
return true; | ||
} | ||
|
||
/* Fetches up to 31 bits from 'stream' as the 'n' least significant bits of return value. | ||
* The 'n' bits are set from the MSB to the LSB. | ||
* Returns 'SIMPLICITY_ERR_BITSTREAM_EOF' if not enough bits are available. | ||
* | ||
* Precondition: 0 <= n < 32 | ||
* NULL != stream | ||
*/ | ||
int32_t readNBits(int n, bitstream* stream) { | ||
assert(0 <= n && n < 32); | ||
|
||
uint32_t result = 0; | ||
while (CHAR_BIT <= stream->offset + n) { | ||
if (!stream->len) return SIMPLICITY_ERR_BITSTREAM_EOF; | ||
n -= CHAR_BIT - stream->offset; | ||
result |= (uint32_t)(*stream->arr & (UCHAR_MAX >> stream->offset)) << n; | ||
stream->arr++; stream->len--; stream->offset = 0; | ||
} | ||
/* stream->offset + n < CHAR_BIT */ | ||
if (n) { | ||
if (!stream->len) return SIMPLICITY_ERR_BITSTREAM_EOF; | ||
stream->offset += (unsigned char)n; | ||
result |= (*stream->arr >> (CHAR_BIT - stream->offset)) & ((UCHAR_MAX >> (CHAR_BIT - n))); | ||
} | ||
return (int32_t)result; | ||
} | ||
/* Decode an encoded bitstring up to length 1. | ||
* If successful returns the length of the bitstring and 'result' contains the decoded bits. | ||
* The decoded bitstring is stored in the LSBs of 'result', with the LSB being the last bit decoded. | ||
* Any remaining bits in 'result' are reset to 0. | ||
* If the decoded bitstring would be too long 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned ('result' may be modified). | ||
* If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned ('result' may be modified). | ||
* If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned ('result' may be modified). | ||
* | ||
* Precondition: NULL != result | ||
* NULL != stream | ||
*/ | ||
static int32_t decodeUpto1Bit(int32_t* result, bitstream* stream) { | ||
*result = read1Bit(stream); | ||
if (*result <= 0) return *result; | ||
|
||
*result = read1Bit(stream); | ||
if (*result < 0) return *result; | ||
if (0 != *result) return SIMPLICITY_ERR_DATA_OUT_OF_RANGE; | ||
|
||
*result = read1Bit(stream); | ||
if (*result < 0) return *result; | ||
return 1; | ||
} | ||
|
||
/* Decode an encoded number between 1 and 3 inclusive. | ||
* When successful returns the decoded result. | ||
* If the decoded value would be too large, 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned. | ||
* If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned. | ||
* If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned. | ||
* | ||
* Precondition: NULL != stream | ||
*/ | ||
static int32_t decodeUpto3(bitstream* stream) { | ||
int32_t result; | ||
int32_t len = decodeUpto1Bit(&result, stream); | ||
if (len < 0) return len; | ||
result |= 1 << len; | ||
return result; | ||
} | ||
|
||
/* Decode an encoded bitstring up to length 3. | ||
* If successful returns the length of the bitstring and 'result' contains the decoded bits. | ||
* The decoded bitstring is stored in the LSBs of 'result', with the LSB being the last bit decoded. | ||
* Any remaining bits in 'result' are reset to 0. | ||
* If the decoded bitstring would be too long 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned ('result' may be modified). | ||
* If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned ('result' may be modified). | ||
* If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned ('result' may be modified). | ||
* | ||
* Precondition: NULL != result | ||
* NULL != stream | ||
*/ | ||
static int32_t decodeUpto3Bits(int32_t* result, bitstream* stream) { | ||
int32_t bit = read1Bit(stream); | ||
if (bit < 0) return bit; | ||
|
||
*result = 0; | ||
if (0 == bit) { | ||
return 0; | ||
} else { | ||
int32_t n = decodeUpto3(stream); | ||
if (0 <= n) { | ||
*result = readNBits(n, stream); | ||
if (*result < 0) return *result; | ||
} | ||
return n; | ||
} | ||
} | ||
|
||
/* Decode an encoded number between 1 and 15 inclusive. | ||
* When successful returns the decoded result. | ||
* If the decoded value would be too large, 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned. | ||
* If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned. | ||
* If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned. | ||
* | ||
* Precondition: NULL != stream | ||
*/ | ||
static int32_t decodeUpto15(bitstream* stream) { | ||
int32_t result; | ||
int32_t len = decodeUpto3Bits(&result, stream); | ||
if (len < 0) return len; | ||
result |= 1 << len; | ||
return result; | ||
} | ||
|
||
/* Decode an encoded bitstring up to length 15. | ||
* If successful returns the length of the bitstring and 'result' contains the decoded bits. | ||
* The decoded bitstring is stored in the LSBs of 'result', with the LSB being the last bit decoded. | ||
* Any remaining bits in 'result' are reset to 0. | ||
* If the decoded bitstring would be too long 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned ('result' may be modified). | ||
* If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned ('result' may be modified). | ||
* If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned ('result' may be modified). | ||
* | ||
* Precondition: NULL != result | ||
* NULL != stream | ||
*/ | ||
static int32_t decodeUpto15Bits(int32_t* result, bitstream* stream) { | ||
int32_t bit = read1Bit(stream); | ||
if (bit < 0) return bit; | ||
|
||
*result = 0; | ||
if (0 == bit) { | ||
return 0; | ||
} else { | ||
int32_t n = decodeUpto15(stream); | ||
if (0 <= n) { | ||
*result = readNBits(n, stream); | ||
if (*result < 0) return *result; | ||
} | ||
return n; | ||
} | ||
} | ||
|
||
/* Decode an encoded number between 1 and 65535 inclusive. | ||
* When successful returns the decoded result. | ||
* If the decoded value would be too large, 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned. | ||
* If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned. | ||
* If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned. | ||
* | ||
* Precondition: NULL != stream | ||
*/ | ||
static int32_t decodeUpto65535(bitstream* stream) { | ||
int32_t result; | ||
int32_t len = decodeUpto15Bits(&result, stream); | ||
if (len < 0) return len; | ||
result |= 1 << len; | ||
return result; | ||
} | ||
|
||
/* Decode an encoded number between 1 and 2^31 - 1 inclusive. | ||
* When successful returns the decoded result. | ||
* If the decoded value would be too large, 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned. | ||
* If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned. | ||
* If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned. | ||
* | ||
* Precondition: NULL != stream | ||
*/ | ||
int32_t decodeUptoMaxInt(bitstream* stream) { | ||
int32_t bit = read1Bit(stream); | ||
if (bit < 0) return bit; | ||
if (0 == bit) { | ||
return 1; | ||
} else { | ||
int32_t n = decodeUpto65535(stream); | ||
if (n < 0) return n; | ||
if (30 < n) return SIMPLICITY_ERR_DATA_OUT_OF_RANGE; | ||
{ | ||
int32_t result = readNBits(n, stream); | ||
if (result < 0) return result; | ||
return ((1 << n) | result); | ||
} | ||
} | ||
} | ||
|
||
/* Fills a 'bitstring' containing 'n' bits from 'stream'. | ||
* Returns 'SIMPLICITY_ERR_BITSTREAM_EOF' if not enough bits are available. | ||
* If successful, '*result' is set to a bitstring with 'n' bits read from 'stream' and 0 is returned. | ||
* | ||
* If an error is returned '*result' might be modified. | ||
* | ||
* Precondition: NULL != result | ||
* n <= 2^31 | ||
* NULL != stream | ||
*/ | ||
int32_t readBitstring(bitstring* result, size_t n, bitstream* stream) { | ||
static_assert(0x8000u + 2*(CHAR_BIT - 1) <= SIZE_MAX, "size_t needs to be at least 32-bits"); | ||
assert(n <= 0x8000u); | ||
size_t total_offset = n + stream->offset; | ||
/* |= stream->len * CHAR_BIT < total_offset iff stream->len < (total_offset + (CHAR_BIT - 1)) / CHAR_BIT */ | ||
if (stream->len < (total_offset + (CHAR_BIT - 1)) / CHAR_BIT) return SIMPLICITY_ERR_BITSTREAM_EOF; | ||
/* total_offset <= stream->len * CHAR_BIT */ | ||
*result = (bitstring) | ||
{ .arr = stream->arr | ||
, .offset = stream->offset | ||
, .len = n | ||
}; | ||
{ | ||
size_t delta = total_offset / CHAR_BIT; | ||
stream->arr += delta; stream->len -= delta; | ||
stream->offset = total_offset % CHAR_BIT; | ||
/* Note that if 0 == stream->len then 0 == stream->offset. */ | ||
} | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* This module provides functions for initializing and reading from a stream of bits from a 'FILE'. */ | ||
#ifndef SIMPLICITY_BITSTREAM_H | ||
#define SIMPLICITY_BITSTREAM_H | ||
|
||
#include <stdio.h> | ||
#include <stdint.h> | ||
#include <stdbool.h> | ||
#include "bitstring.h" | ||
#include "errorCodes.h" | ||
|
||
/* :TODO: consider adding an 'invalid' state that can be set when parsing has failed and should not be resumed. */ | ||
/* Datatype representing a bit stream. | ||
* Bits are streamed from MSB to LSB. | ||
* | ||
* Invariant: unsigned char arr[len] | ||
* 0 <= offset < CHAR_BIT | ||
* 0 == len implies 0 == offset | ||
*/ | ||
typedef struct bitstream { | ||
const unsigned char *arr; /* Underlying byte array */ | ||
size_t len; /* Length of arr (in bytes) */ | ||
unsigned char offset; /* Number of bits parsed from the beginning of arr */ | ||
} bitstream; | ||
|
||
/* Initialize a bit stream, 'stream', from a given byte array. | ||
* Precondition: unsigned char arr[len]; | ||
*/ | ||
static inline bitstream initializeBitstream(const unsigned char* arr, size_t len) { | ||
return (bitstream){ .arr = arr, .len = len }; | ||
} | ||
|
||
/* Closes a bitstream by consuming all remaining bits. | ||
* Returns false if CHAR_BIT or more bits remain in the stream or if any remaining bits are non-zero. | ||
* | ||
* Precondition: NULL != stream | ||
*/ | ||
bool closeBitstream(bitstream* stream); | ||
|
||
/* Fetches up to 31 bits from 'stream' as the 'n' least significant bits of return value. | ||
* The 'n' bits are set from the MSB to the LSB. | ||
* Returns 'SIMPLICITY_ERR_BITSTREAM_EOF' if not enough bits are available. | ||
* | ||
* Precondition: 0 <= n < 32 | ||
* NULL != stream | ||
*/ | ||
int32_t readNBits(int n, bitstream* stream); | ||
|
||
/* Returns one bit from 'stream', 0 or 1. | ||
* Returns 'SIMPLICITY_ERR_BITSTREAM_EOF' if no bits are available. | ||
* | ||
* Precondition: NULL != stream | ||
*/ | ||
static inline int32_t read1Bit(bitstream* stream) { | ||
return readNBits(1, stream); | ||
} | ||
|
||
/* Decode an encoded number between 1 and 2^31 - 1 inclusive. | ||
* When successful returns the decoded result. | ||
* If the decoded value would be too large, 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned. | ||
* If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned. | ||
* If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned. | ||
* | ||
* Precondition: NULL != stream | ||
*/ | ||
int32_t decodeUptoMaxInt(bitstream* stream); | ||
|
||
/* Fills a 'bitstring' containing 'n' bits from 'stream'. | ||
* Returns 'SIMPLICITY_ERR_BITSTREAM_EOF' if not enough bits are available. | ||
* If successful, '*result' is set to a bitstring with 'n' bits read from 'stream' and 0 is returned. | ||
* | ||
* If an error is returned '*result' might be modified. | ||
* | ||
* Precondition: NULL != result | ||
* n <= 2^31 | ||
* NULL != stream | ||
*/ | ||
int32_t readBitstring(bitstring* result, size_t n, bitstream* stream); | ||
#endif |
Oops, something went wrong.